add items to outfit thumbnails

Now that wasn't so hard! :3
This commit is contained in:
Emi Matchu 2021-01-04 08:26:05 +00:00
parent 9a2308fd41
commit b01feba038
3 changed files with 73 additions and 6 deletions

View file

@ -7,6 +7,7 @@ import { ErrorMessage, Heading1 } from "./util";
import { import {
getVisibleLayers, getVisibleLayers,
petAppearanceFragmentForGetVisibleLayers, petAppearanceFragmentForGetVisibleLayers,
itemAppearanceFragmentForGetVisibleLayers,
} from "./components/useOutfitAppearance"; } from "./components/useOutfitAppearance";
import HangerSpinner from "./components/HangerSpinner"; import HangerSpinner from "./components/HangerSpinner";
import useRequireLogin from "./components/useRequireLogin"; import useRequireLogin from "./components/useRequireLogin";
@ -43,10 +44,20 @@ function UserOutfitsPageContent() {
} }
...PetAppearanceForGetVisibleLayers ...PetAppearanceForGetVisibleLayers
} }
itemAppearances {
id
layers {
id
svgUrl
imageUrl(size: $size)
}
...ItemAppearanceForGetVisibleLayers
}
} }
} }
} }
${petAppearanceFragmentForGetVisibleLayers} ${petAppearanceFragmentForGetVisibleLayers}
${itemAppearanceFragmentForGetVisibleLayers}
`, `,
{ variables: { size: "SIZE_" + getBestImageSize() }, skip: userLoading } { variables: { size: "SIZE_" + getBestImageSize() }, skip: userLoading }
); );
@ -77,7 +88,10 @@ function UserOutfitsPageContent() {
} }
function OutfitCard({ outfit }) { function OutfitCard({ outfit }) {
const thumbnailUrl = buildOutfitThumbnailUrl(outfit.petAppearance, []); const thumbnailUrl = buildOutfitThumbnailUrl(
outfit.petAppearance,
outfit.itemAppearances
);
return ( return (
<Flex <Flex
@ -105,6 +119,14 @@ function buildOutfitThumbnailUrl(petAppearance, itemAppearances) {
return `/api/outfitImage?size=${size}&layerUrls=${layerUrls.join(",")}`; return `/api/outfitImage?size=${size}&layerUrls=${layerUrls.join(",")}`;
} }
/**
* getBestImageSize 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.
*/
function getBestImageSize() { function getBestImageSize() {
if (window.devicePixelRatio > 1) { if (window.devicePixelRatio > 1) {
return 300; return 300;

View file

@ -137,6 +137,22 @@ export function getVisibleLayers(petAppearance, itemAppearances) {
return visibleLayers; return visibleLayers;
} }
export const itemAppearanceFragmentForGetVisibleLayers = gql`
fragment ItemAppearanceForGetVisibleLayers on ItemAppearance {
id
layers {
id
zone {
id
depth @client
}
}
restrictedZones {
id
}
}
`;
export const itemAppearanceFragment = gql` export const itemAppearanceFragment = gql`
fragment ItemAppearanceForOutfitPreview on ItemAppearance { fragment ItemAppearanceForOutfitPreview on ItemAppearance {
id id
@ -149,15 +165,13 @@ export const itemAppearanceFragment = gql`
swfUrl # HACK: This is for Support tools, but other views don't need it swfUrl # HACK: This is for Support tools, but other views don't need it
bodyId bodyId
zone { zone {
id
depth @client
label @client # HACK: This is for Support tools, but other views don't need it label @client # HACK: This is for Support tools, but other views don't need it
} }
} }
restrictedZones { ...ItemAppearanceForGetVisibleLayers
id
}
} }
${itemAppearanceFragmentForGetVisibleLayers}
`; `;
export const petAppearanceFragmentForGetVisibleLayers = gql` export const petAppearanceFragmentForGetVisibleLayers = gql`

View file

@ -7,6 +7,10 @@ const typeDefs = gql`
petAppearance: PetAppearance! petAppearance: PetAppearance!
wornItems: [Item!]! wornItems: [Item!]!
closetedItems: [Item!]! closetedItems: [Item!]!
# This is a convenience field: you could query this from the combination of
# petAppearance and wornItems, but this gets you it in one shot!
itemAppearances: [ItemAppearance!]!
} }
extend type Query { extend type Query {
@ -24,6 +28,33 @@ const resolvers = {
const outfit = await outfitLoader.load(id); const outfit = await outfitLoader.load(id);
return { id: outfit.petStateId }; return { id: outfit.petStateId };
}, },
itemAppearances: async (
{ id },
_,
{
outfitLoader,
petStateLoader,
petTypeLoader,
itemOutfitRelationshipsLoader,
}
) => {
const [petType, relationships] = await Promise.all([
outfitLoader
.load(id)
.then((outfit) => petStateLoader.load(outfit.petStateId))
.then((petState) => petTypeLoader.load(petState.petTypeId)),
itemOutfitRelationshipsLoader.load(id),
]);
const wornItemIds = relationships
.filter((oir) => oir.isWorn)
.map((oir) => oir.itemId);
return wornItemIds.map((itemId) => ({
item: { id: itemId },
bodyId: petType.bodyId,
}));
},
wornItems: async ({ id }, _, { itemOutfitRelationshipsLoader }) => { wornItems: async ({ id }, _, { itemOutfitRelationshipsLoader }) => {
const relationships = await itemOutfitRelationshipsLoader.load(id); const relationships = await itemOutfitRelationshipsLoader.load(id);
return relationships return relationships