forked from OpenNeo/impress
Emi Matchu
46dc4cf009
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
82 lines
2.2 KiB
JavaScript
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,
|
|
};
|
|
}
|