impress-2020/src/app/components/OutfitThumbnail.js
Matchu 2a8be58973 Show thumbnail in wardrobe page while outfit loads
To help the load time for outfits feel shorter, we now reuse the outfit thumbnail from the Your Outfits page as a placeholder!

This doesn't add any overhead when the thumbnail data _isn't_ in your session cache, e.g. if you navigate to the outfit directly. But if we have the thumbnail on hand already, we just show it, easy peasy!
2021-01-08 01:23:24 -08:00

82 lines
2 KiB
JavaScript

import React from "react";
import { Box } from "@chakra-ui/react";
import gql from "graphql-tag";
import {
getVisibleLayers,
petAppearanceFragmentForGetVisibleLayers,
itemAppearanceFragmentForGetVisibleLayers,
} from "./useOutfitAppearance";
function OutfitThumbnail({ petAppearance, itemAppearances, ...props }) {
return (
<Box
as="img"
src={buildOutfitThumbnailUrl(petAppearance, itemAppearances)}
{...props}
/>
);
}
function buildOutfitThumbnailUrl(petAppearance, itemAppearances) {
const size = getOutfitThumbnailRenderSize();
const visibleLayers = getVisibleLayers(petAppearance, itemAppearances);
const layerUrls = visibleLayers.map(
(layer) => layer.svgUrl || layer.imageUrl
);
return `/api/outfitImage?size=${size}&layerUrls=${layerUrls.join(",")}`;
}
/**
* getOutfitThumbnailRenderSize returns the right image size to render at
* 150x150, for the current device.
*
* On high-DPI devices, we'll download a 300x300 image to render at 150x150
* scale. On standard-DPI devices, we'll download a 150x150 image, to save
* bandwidth.
*/
export function getOutfitThumbnailRenderSize() {
if (window.devicePixelRatio > 1) {
return 300;
} else {
return 150;
}
}
// NOTE: The query must include a `$size: LayerImageSize` parameter, probably
// with the return value of `getOutfitThumbnailRenderSize`!
export const outfitThumbnailFragment = gql`
fragment OutfitThumbnailFragment on Outfit {
petAppearance {
id
layers {
id
svgUrl
imageUrl(size: $size)
}
species {
id
name
}
color {
id
name
}
...PetAppearanceForGetVisibleLayers
}
itemAppearances {
id
layers {
id
svgUrl
imageUrl(size: $size)
}
...ItemAppearanceForGetVisibleLayers
}
}
${petAppearanceFragmentForGetVisibleLayers}
${itemAppearanceFragmentForGetVisibleLayers}
`;
export default OutfitThumbnail;