impress-2020/src/app/WardrobePage/WardrobePreviewAndControls.js
Matchu 65af7ef64c Add general error message for wardrobe crashes
Boom, pulled some stuff out into util! Now we also have error boundaries in both panels of the wardrobe page.

You can test this one by visiting `/outfits/new?send-test-error-for-sentry`, just like on the home page! Util component for fake errors owo
2021-05-05 00:22:28 -07:00

103 lines
3 KiB
JavaScript

import React from "react";
import { Box, DarkMode } from "@chakra-ui/react";
import gql from "graphql-tag";
import { useQuery } from "@apollo/client";
import * as Sentry from "@sentry/react";
import OutfitThumbnail, {
outfitThumbnailFragment,
getOutfitThumbnailRenderSize,
} from "../components/OutfitThumbnail";
import { useOutfitPreview } from "../components/OutfitPreview";
import { loadable, MajorErrorMessage, TestErrorSender } from "../util";
const OutfitControls = loadable(() => import("./OutfitControls"));
function WardrobePreviewAndControls({
isLoading,
outfitState,
dispatchToOutfit,
}) {
// Whether the current outfit preview has animations. Determines whether we
// show the play/pause button.
const [hasAnimations, setHasAnimations] = React.useState(false);
const { appearance, preview } = useOutfitPreview({
isLoading: isLoading,
speciesId: outfitState.speciesId,
colorId: outfitState.colorId,
pose: outfitState.pose,
appearanceId: outfitState.appearanceId,
wornItemIds: outfitState.wornItemIds,
onChangeHasAnimations: setHasAnimations,
placeholder: <OutfitThumbnailIfCached outfitId={outfitState.id} />,
"data-test-id": "wardrobe-outfit-preview",
});
return (
<Sentry.ErrorBoundary fallback={MajorErrorMessage}>
<TestErrorSender />
<Box position="absolute" top="0" bottom="0" left="0" right="0">
<DarkMode>{preview}</DarkMode>
</Box>
<Box position="absolute" top="0" bottom="0" left="0" right="0">
<OutfitControls
outfitState={outfitState}
dispatchToOutfit={dispatchToOutfit}
showAnimationControls={hasAnimations}
appearance={appearance}
/>
</Box>
</Sentry.ErrorBoundary>
);
}
/**
* OutfitThumbnailIfCached will render an OutfitThumbnail as a placeholder for
* the outfit preview... but only if we already have the data to generate the
* thumbnail stored in our local Apollo GraphQL cache.
*
* This means that, when you come from the Your Outfits page, we can show the
* outfit thumbnail instantly while everything else loads. But on direct
* navigation, this does nothing, and we just wait for the preview to load in
* like usual!
*/
function OutfitThumbnailIfCached({ outfitId }) {
const { data } = useQuery(
gql`
query OutfitThumbnailIfCached($outfitId: ID!, $size: LayerImageSize!) {
outfit(id: $outfitId) {
id
...OutfitThumbnailFragment
}
}
${outfitThumbnailFragment}
`,
{
variables: {
outfitId,
// NOTE: This parameter is used inside `OutfitThumbnailFragment`!
size: "SIZE_" + getOutfitThumbnailRenderSize(),
},
fetchPolicy: "cache-only",
}
);
if (!data?.outfit) {
return null;
}
return (
<OutfitThumbnail
petAppearance={data.outfit.petAppearance}
itemAppearances={data.outfit.itemAppearances}
alt=""
objectFit="contain"
width="100%"
height="100%"
filter="blur(2px)"
/>
);
}
export default WardrobePreviewAndControls;