diff --git a/src/OutfitPreview.js b/src/OutfitPreview.js index 361032c..a707252 100644 --- a/src/OutfitPreview.js +++ b/src/OutfitPreview.js @@ -10,8 +10,10 @@ import { Image, PseudoBox, Spinner, + Stack, Text, Tooltip, + useClipboard, } from "@chakra-ui/core"; import { Delay } from "./util"; @@ -68,6 +70,8 @@ function OutfitPreview({ outfitState, dispatchToOutfit }) { visibleLayers ); + const { onCopy, hasCopied } = useClipboard(getShareUrl(outfitState)); + if (error) { return ( @@ -133,9 +137,9 @@ function OutfitPreview({ outfitState, dispatchToOutfit }) { bottom={{ base: 2, lg: 6 }} // Grid layout for the content! display="grid" - gridTemplateAreas={`"space picker download"`} + gridTemplateAreas={`"space picker buttons"`} gridTemplateColumns="minmax(0, 1fr) auto 1fr" - alignItems="center" + alignItems="flex-end" > setHasFocus(false)} /> - - - { - prepareDownload(); - setHasFocus(true); - }} - onBlur={() => setHasFocus(false)} - cursor={!downloadImageUrl && "wait"} - variant="unstyled" - backgroundColor="gray.600" - color="gray.50" - boxShadow="md" - d="flex" - alignItems="center" - justifyContent="center" - opacity={hasFocus ? 1 : 0} - transition="all 0.2s" - _groupHover={{ - opacity: 1, - }} - _focus={{ - opacity: 1, - backgroundColor: "gray.500", - }} - _hover={{ - backgroundColor: "gray.500", - }} - outline="initial" - /> - - + + + + setHasFocus(true)} + onBlur={() => setHasFocus(false)} + variant="unstyled" + backgroundColor="gray.600" + color="gray.50" + boxShadow="md" + d="flex" + alignItems="center" + justifyContent="center" + opacity={hasFocus ? 1 : 0} + transition="all 0.2s" + _groupHover={{ + opacity: 1, + }} + _focus={{ + opacity: 1, + backgroundColor: "gray.500", + }} + _hover={{ + backgroundColor: "gray.500", + }} + outline="initial" + /> + + + + + { + prepareDownload(); + setHasFocus(true); + }} + onBlur={() => setHasFocus(false)} + cursor={!downloadImageUrl && "wait"} + variant="unstyled" + backgroundColor="gray.600" + color="gray.50" + boxShadow="md" + d="flex" + alignItems="center" + justifyContent="center" + opacity={hasFocus ? 1 : 0} + transition="all 0.2s" + _groupHover={{ + opacity: 1, + }} + _focus={{ + opacity: 1, + backgroundColor: "gray.500", + }} + _hover={{ + backgroundColor: "gray.500", + }} + outline="initial" + /> + + + { - if (!fetchMoreResult) return prev; + if (!fetchMoreResult || fetchMoreResult.query !== prev.query) { + return prev; + } // Note: This is a bit awkward because, if the results count ends on // a multiple of 30, the user will see a flash of loading before diff --git a/src/useOutfitState.js b/src/useOutfitState.js index 9658443..ef1a081 100644 --- a/src/useOutfitState.js +++ b/src/useOutfitState.js @@ -29,6 +29,21 @@ function useOutfitState() { } ); + React.useEffect(() => { + const urlParams = new URLSearchParams(window.location.search); + if (urlParams.has("species")) { + dispatchToOutfit({ + type: "reset", + name: urlParams.get("name"), + speciesId: urlParams.get("species"), + colorId: urlParams.get("color"), + wornItemIds: urlParams.getAll("objects[]"), + closetedItemIds: urlParams.getAll("closet[]"), + }); + } + window.history.replaceState(null, "", window.location.href.split("?")[0]); + }); + const { name, speciesId, colorId } = state; // It's more convenient to manage these as a Set in state, but most callers @@ -82,6 +97,7 @@ function useOutfitState() { zonesAndItems, name, wornItemIds, + closetedItemIds, allItemIds, speciesId, colorId, @@ -150,10 +166,14 @@ const outfitStateReducer = (apolloClient) => (baseState, action) => { const { name, speciesId, colorId, wornItemIds, closetedItemIds } = action; return { name, - speciesId: String(speciesId || baseState.speciesId), - colorId: String(colorId || baseState.colorId), - wornItemIds: new Set(wornItemIds.map(String)), - closetedItemIds: new Set(closetedItemIds.map(String)), + speciesId: speciesId ? String(speciesId) : baseState.speciesId, + colorId: colorId ? String(colorId) : baseState.colorId, + wornItemIds: wornItemIds + ? new Set(wornItemIds.map(String)) + : baseState.wornItemIds, + closetedItemIds: closetedItemIds + ? new Set(closetedItemIds.map(String)) + : baseState.closetedItemIds, }; default: throw new Error(`unexpected action ${JSON.stringify(action)}`);