impress/app/javascript/wardrobe-2020/loaders/alt-styles.js
Emi Matchu 46dc4cf009 Skip loading alt styles until speciesId is present
Before this change, when loading an outfit by ID, we'd send a request
to `/species/null/alt-styles.json`, which would come back as a 404,
oops lol
2024-02-08 10:46:37 -08:00

82 lines
2.2 KiB
JavaScript

import { useQuery } from "@tanstack/react-query";
export function useAltStylesForSpecies(speciesId, options = {enabled = true}) {
return useQuery({
...options,
queryKey: ["altStylesForSpecies", String(speciesId)],
queryFn: () => loadAltStylesForSpecies(speciesId),
enabled: options.enabled && speciesId != null,
});
}
// NOTE: This is actually just a wrapper for `useAltStylesForSpecies`, to share
// the same cache key!
export function useAltStyle(id, speciesId, options = {}) {
const query = useAltStylesForSpecies(speciesId, options);
return {
...query,
data: query.data?.find((s) => s.id === id) ?? null,
};
}
async function loadAltStylesForSpecies(speciesId) {
const res = await fetch(
`/species/${encodeURIComponent(speciesId)}/alt-styles.json`,
);
if (!res.ok) {
throw new Error(
`loading alt styles failed: ${res.status} ${res.statusText}`,
);
}
return res.json().then(normalizeAltStyles);
}
function normalizeAltStyles(altStylesData) {
return altStylesData.map(normalizeAltStyle);
}
function normalizeAltStyle(altStyleData) {
return {
id: String(altStyleData.id),
speciesId: String(altStyleData.species_id),
colorId: String(altStyleData.color_id),
bodyId: String(altStyleData.body_id),
seriesName: altStyleData.series_name,
adjectiveName: altStyleData.adjective_name,
thumbnailUrl: altStyleData.thumbnail_url,
// This matches the PetAppearanceForOutfitPreview GQL fragment!
appearance: {
bodyId: String(altStyleData.body_id),
pose: "UNKNOWN",
isGlitched: false,
species: { id: String(altStyleData.species_id) },
color: { id: String(altStyleData.species_id) },
layers: altStyleData.swf_assets.map(normalizeSwfAssetToLayer),
restrictedZones: [],
},
};
}
function normalizeSwfAssetToLayer(swfAssetData) {
return {
id: String(swfAssetData.id),
zone: {
id: String(swfAssetData.zone.id),
depth: swfAssetData.zone.depth,
label: swfAssetData.zone.label,
},
bodyId: swfAssetData.body_id,
knownGlitches: [], // TODO
// HACK: We're just simplifying this adapter, but it would be better to
// actually check what file formats the manifest says!
svgUrl: swfAssetData.html5_svg_url,
canvasMovieLibraryUrl: null,
imageUrl: swfAssetData.html5_image_url,
swfUrl: swfAssetData.url,
};
}