diff --git a/src/app/ItemPage.js b/src/app/ItemPage.js
index 5d4edfb..78c78db 100644
--- a/src/app/ItemPage.js
+++ b/src/app/ItemPage.js
@@ -40,7 +40,7 @@ import {
itemAppearanceFragment,
petAppearanceFragment,
} from "./components/useOutfitAppearance";
-import OutfitPreview from "./components/OutfitPreview";
+import { useOutfitPreview } from "./components/OutfitPreview";
import SpeciesColorPicker, {
useAllValidPetPoses,
getValidPoses,
@@ -646,39 +646,28 @@ function ItemPageOutfitPreview({ itemId }) {
valids,
} = useAllValidPetPoses();
- // To check whether the item is compatible with this pet, query for the
- // appearance, but only against the cache. That way, we don't send a
- // redundant network request just for this (the OutfitPreview component will
- // handle it!), but we'll get an update once it arrives in the cache.
- const { data: cachedData } = useQuery(
- gql`
- query ItemPageOutfitPreview_CacheOnly(
- $itemId: ID!
- $speciesId: ID!
- $colorId: ID!
- ) {
- item(id: $itemId) {
- appearanceOn(speciesId: $speciesId, colorId: $colorId) {
- layers {
- id
- }
- }
- }
- }
- `,
- {
- variables: {
- itemId,
- speciesId: petState.speciesId,
- colorId: petState.colorId,
- },
- fetchPolicy: "cache-only",
- }
- );
-
const [hasAnimations, setHasAnimations] = React.useState(false);
const [isPaused, setIsPaused] = useLocalStorage("DTIOutfitIsPaused", true);
+ // This is like , but we can use the appearance data, too!
+ const { appearance, preview } = useOutfitPreview({
+ speciesId: petState.speciesId,
+ colorId: petState.colorId,
+ pose: petState.pose,
+ appearanceId: petState.appearanceId,
+ wornItemIds: [itemId],
+ isLoading: loadingGQL || loadingValids,
+ spinnerVariant: "corner",
+ loadingDelayMs: 200,
+ engine: "canvas",
+ onChangeHasAnimations: setHasAnimations,
+ });
+
+ // If there's an appearance loaded for this item, but it's empty, then the
+ // item is incompatible. (There should only be one item appearance: this one!)
+ const itemAppearance = appearance?.itemAppearances?.[0];
+ const isIncompatible = itemAppearance && itemAppearance.layers.length === 0;
+
const borderColor = useColorModeValue("green.700", "green.400");
const errorColor = useColorModeValue("red.600", "red.400");
@@ -687,12 +676,6 @@ function ItemPageOutfitPreview({ itemId }) {
return {error.message};
}
- // If the layers are null-y, then we're still loading. Otherwise, if the
- // layers are an empty array, then we're incomaptible. Or, if they're a
- // non-empty array, then we're compatible!
- const layers = cachedData?.item?.appearanceOn?.layers;
- const isIncompatible = Array.isArray(layers) && layers.length === 0;
-
return (
-
+ {preview}
`, but a bit more power!
+ *
+ * It takes the same props and returns a `preview` field, which is just like
+ * `` - but it also returns `appearance` data too, in case you
+ * want to show some additional UI that uses the appearance data we loaded!
+ */
+export function useOutfitPreview({
speciesId,
colorId,
pose,
@@ -41,13 +53,14 @@ function OutfitPreview({
spinnerVariant,
onChangeHasAnimations = null,
}) {
- const { loading, error, visibleLayers } = useOutfitAppearance({
+ const appearance = useOutfitAppearance({
speciesId,
colorId,
pose,
appearanceId,
wornItemIds,
});
+ const { loading, error, visibleLayers } = appearance;
const {
loading: loading2,
@@ -76,7 +89,7 @@ function OutfitPreview({
);
}
- return (
+ const preview = (
);
+
+ return { appearance, preview };
}
/**
diff --git a/src/app/components/useOutfitAppearance.js b/src/app/components/useOutfitAppearance.js
index 1ffa48b..3420b10 100644
--- a/src/app/components/useOutfitAppearance.js
+++ b/src/app/components/useOutfitAppearance.js
@@ -69,7 +69,7 @@ export default function useOutfitAppearance(outfitState) {
) {
items(ids: $wornItemIds) {
id
- appearanceOn(speciesId: $speciesId, colorId: $colorId) {
+ appearance: appearanceOn(speciesId: $speciesId, colorId: $colorId) {
...ItemAppearanceForOutfitPreview
}
}
@@ -86,20 +86,25 @@ export default function useOutfitAppearance(outfitState) {
}
);
+ const petAppearance = data1?.petAppearance;
+ const items = data2?.items;
const itemAppearances = React.useMemo(
- () => (data2?.items || []).map((i) => i.appearanceOn),
- [data2]
+ () => (items || []).map((i) => i.appearance),
+ [items]
);
const visibleLayers = React.useMemo(
- () => getVisibleLayers(data1?.petAppearance, itemAppearances),
- [data1, itemAppearances]
+ () => getVisibleLayers(petAppearance, itemAppearances),
+ [petAppearance, itemAppearances]
);
- const bodyId = data1?.petAppearance?.bodyId;
+ const bodyId = petAppearance?.bodyId;
return {
loading: loading1 || loading2,
error: error1 || error2,
+ petAppearance,
+ items,
+ itemAppearances,
visibleLayers,
bodyId,
};