Compare commits

..

No commits in common. "81a58f865672d41d29f8be9485266319d2fc9cff" and "0a9193aed75b230566da1264d4466de4fd2c2ac3" have entirely different histories.

6 changed files with 48 additions and 45 deletions

View file

@ -1,31 +0,0 @@
class OutfitLayer extends HTMLElement {
#internals;
constructor() {
super();
this.#internals = this.attachInternals();
}
connectedCallback() {
setTimeout(() => this.#initializeImage(), 0);
}
#initializeImage() {
this.image = this.querySelector("img");
if (!this.image) {
throw new Error(`<outfit-layer> must contain an <img> tag`);
}
this.image.addEventListener("load", () => this.#setStatus("loaded"));
this.image.addEventListener("error", () => this.#setStatus("error"));
this.#setStatus(this.image.complete ? "loaded" : "loading");
}
#setStatus(newStatus) {
this.#internals.states.clear();
this.#internals.states.add(newStatus);
}
}
customElements.define("outfit-layer", OutfitLayer);

View file

@ -49,7 +49,7 @@ body.items-show
margin: 0 auto .75em
outfit-layer
.outfit-layer
display: block
position: absolute
inset: 0
@ -58,7 +58,7 @@ body.items-show
width: 100%
height: 100%
&:has(outfit-layer:state(loading))
&:has(.outfit-layer[data-status="loading"])
background: gray
.species-color-picker

View file

@ -244,5 +244,15 @@ module ItemsHelper
def item_header_user_lists_form_state
cookies.fetch("DTIItemPageUserListsFormState", "closed")
end
def outfit_viewer_layers(swf_assets)
swf_assets.map { |a| outfit_viewer_layer(a) }.join("\n").html_safe
end
def outfit_viewer_layer(swf_asset)
content_tag :div, class: "outfit-layer" do
image_tag swf_asset.image_url, alt: ""
end
end
end

View file

@ -0,0 +1,32 @@
// When we load in a new preview, set the status on the images. We use this in
// our CSS to show a loading state when needed.
function setImageStatuses() {
for (const layer of document.querySelectorAll(".outfit-layer")) {
const isLoaded = layer.querySelector("img").complete;
layer.setAttribute("data-status", isLoaded ? "loaded" : "loading");
}
}
document.addEventListener("turbo:frame-render", () => setImageStatuses());
document.addEventListener("turbo:load", () => setImageStatuses());
// When a preview image loads or fails, update its status. (Note that `load`
// does not fire for images that were loaded from cache, which is why we need
// both this and `setImageStatuses` when rendering new images!)
document.addEventListener(
"load",
({ target }) => {
if (target.matches(".outfit-layer img")) {
target.closest(".outfit-layer").setAttribute("data-status", "loaded");
}
},
{ capture: true },
);
document.addEventListener(
"error",
({ target }) => {
if (target.matches(".outfit-layer img")) {
target.closest(".outfit-layer").setAttribute("data-status", "error");
}
},
{ capture: true },
);

View file

@ -1,9 +0,0 @@
.outfit-viewer
- outfit.visible_layers.each do |swf_asset|
%outfit-layer{
data: {
"asset-id": swf_asset.id,
"zone": swf_asset.zone.label,
},
}
= image_tag swf_asset.image_url, alt: ""

View file

@ -14,7 +14,8 @@
sorry!
= turbo_frame_tag "item-preview" do
= render partial: "outfit_viewer", locals: {outfit: @preview_outfit}
.outfit-viewer
= outfit_viewer_layers @preview_outfit.visible_layers
= form_for item_path(@item), method: :get, class: "species-color-picker",
data: {"is-valid": @preview_error.nil?} do |f|
@ -39,6 +40,6 @@
%li= link_to(contributor.name, user_contributions_path(contributor)) + format_contribution_count(count)
%footer= t '.contributors.footer'
- content_for :javascripts do
= javascript_include_tag 'outfit-viewer', async: true
- content_for :javascripts_body do
= javascript_include_tag 'item-page', defer: true