import React from "react"; import { Box, Center, DarkMode } from "@chakra-ui/react"; import gql from "graphql-tag"; import { useQuery } from "@apollo/client"; import * as Sentry from "@sentry/react"; import OutfitThumbnail 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, altStyleId: outfitState.altStyleId, 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 /> <Center position="absolute" top="0" bottom="0" left="0" right="0"> <DarkMode>{preview}</DarkMode> </Center> <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!) { outfit(id: $outfitId) { id updatedAt } } `, { variables: { outfitId, }, skip: outfitId == null, fetchPolicy: "cache-only", onError: (e) => console.error(e), }, ); if (!data?.outfit) { return null; } return ( <OutfitThumbnail outfitId={data.outfit.id} updatedAt={data.outfit.updatedAt} alt="" objectFit="contain" width="100%" height="100%" filter="blur(2px)" /> ); } export default WardrobePreviewAndControls;