Recover from missing pose data
Previously, if you typed a pet name on the homepage, but its pose wasn't labeled in our database, you'd get a black empty screen. Now, we redirect to the UNKNOWN pose, or whatever exists for us to use!
This commit is contained in:
parent
71ec5ddc58
commit
be7401d62a
1 changed files with 62 additions and 1 deletions
|
@ -14,6 +14,7 @@ import {
|
||||||
VisuallyHidden,
|
VisuallyHidden,
|
||||||
useColorModeValue,
|
useColorModeValue,
|
||||||
useTheme,
|
useTheme,
|
||||||
|
useToast,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import { loadable } from "../util";
|
import { loadable } from "../util";
|
||||||
|
|
||||||
|
@ -71,6 +72,7 @@ function PosePicker({
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
const { isSupportUser } = useSupport();
|
const { isSupportUser } = useSupport();
|
||||||
|
const toast = useToast();
|
||||||
|
|
||||||
// Resize the Popover when we toggle support mode, because it probably will
|
// Resize the Popover when we toggle support mode, because it probably will
|
||||||
// affect the content size.
|
// affect the content size.
|
||||||
|
@ -82,6 +84,52 @@ function PosePicker({
|
||||||
window.dispatchEvent(new Event("resize"));
|
window.dispatchEvent(new Event("resize"));
|
||||||
}, [isInSupportMode]);
|
}, [isInSupportMode]);
|
||||||
|
|
||||||
|
// Generally, the app tries to never put us in an invalid pose state. But it
|
||||||
|
// can happen with direct URL navigation, or pet loading when modeling isn't
|
||||||
|
// updated! Let's do some recovery.
|
||||||
|
const selectedPoseIsAvailable = Object.values(poseInfos).some(
|
||||||
|
(pi) => pi.isSelected && pi.isAvailable
|
||||||
|
);
|
||||||
|
const firstAvailablePose = Object.values(poseInfos).find(
|
||||||
|
(pi) => pi.isAvailable
|
||||||
|
)?.pose;
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (loading) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!selectedPoseIsAvailable) {
|
||||||
|
if (!firstAvailablePose) {
|
||||||
|
// TODO: I suppose this error would fit better in SpeciesColorPicker!
|
||||||
|
toast({
|
||||||
|
status: "error",
|
||||||
|
title: "Oops, we don't have data for this pet color!",
|
||||||
|
description:
|
||||||
|
"If it's new, this might be a modeling issue—try modeling it on " +
|
||||||
|
"Classic DTI first. Sorry!",
|
||||||
|
duration: null,
|
||||||
|
isClosable: true,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.warn(
|
||||||
|
`Pose ${pose} not found for speciesId=${speciesId}, ` +
|
||||||
|
`colorId=${colorId}. Redirecting to pose ${firstAvailablePose}.`
|
||||||
|
);
|
||||||
|
dispatchToOutfit({ type: "setPose", pose: firstAvailablePose });
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
loading,
|
||||||
|
selectedPoseIsAvailable,
|
||||||
|
firstAvailablePose,
|
||||||
|
speciesId,
|
||||||
|
colorId,
|
||||||
|
pose,
|
||||||
|
toast,
|
||||||
|
dispatchToOutfit,
|
||||||
|
]);
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -519,6 +567,13 @@ function usePoses(speciesId, colorId, selectedPose) {
|
||||||
) {
|
) {
|
||||||
...PetAppearanceForPosePicker
|
...PetAppearanceForPosePicker
|
||||||
}
|
}
|
||||||
|
unknown: petAppearance(
|
||||||
|
speciesId: $speciesId
|
||||||
|
colorId: $colorId
|
||||||
|
pose: UNKNOWN
|
||||||
|
) {
|
||||||
|
...PetAppearanceForPosePicker
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fragment PetAppearanceForPosePicker on PetAppearance {
|
fragment PetAppearanceForPosePicker on PetAppearance {
|
||||||
|
@ -529,7 +584,7 @@ function usePoses(speciesId, colorId, selectedPose) {
|
||||||
}
|
}
|
||||||
${petAppearanceFragment}
|
${petAppearanceFragment}
|
||||||
`,
|
`,
|
||||||
{ variables: { speciesId, colorId } }
|
{ variables: { speciesId, colorId }, onError: (e) => console.error(e) }
|
||||||
);
|
);
|
||||||
|
|
||||||
const poseInfos = {
|
const poseInfos = {
|
||||||
|
@ -575,6 +630,12 @@ function usePoses(speciesId, colorId, selectedPose) {
|
||||||
isAvailable: Boolean(data?.unconverted),
|
isAvailable: Boolean(data?.unconverted),
|
||||||
isSelected: selectedPose === "UNCONVERTED",
|
isSelected: selectedPose === "UNCONVERTED",
|
||||||
},
|
},
|
||||||
|
unknown: {
|
||||||
|
...data?.unknown,
|
||||||
|
pose: "UNKNOWN",
|
||||||
|
isAvailable: Boolean(data?.unknown),
|
||||||
|
isSelected: selectedPose === "UNKNOWN",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return { loading, error, poseInfos };
|
return { loading, error, poseInfos };
|
||||||
|
|
Loading…
Reference in a new issue