Compare commits
3 commits
345a45ee0c
...
f3e10dea7f
Author | SHA1 | Date | |
---|---|---|---|
f3e10dea7f | |||
66c1e14dd0 | |||
752bee3c39 |
4 changed files with 90 additions and 15 deletions
|
@ -4,6 +4,7 @@ import { Box, Text, useColorModeValue, VisuallyHidden } from "@chakra-ui/react";
|
|||
import Item, { ItemListContainer, ItemListSkeleton } from "./Item";
|
||||
import PaginationToolbar from "../components/PaginationToolbar";
|
||||
import { useSearchResults } from "./useSearchResults";
|
||||
import { MajorErrorMessage } from "../util";
|
||||
|
||||
export const SEARCH_PER_PAGE = 30;
|
||||
|
||||
|
@ -134,17 +135,8 @@ function SearchResults({
|
|||
|
||||
const searchPanelBackground = useColorModeValue("white", "gray.900");
|
||||
|
||||
// If the results aren't ready, we have some special case UI!
|
||||
if (error) {
|
||||
return (
|
||||
<Text>
|
||||
We hit an error trying to load your search results{" "}
|
||||
<span role="img" aria-label="(sweat emoji)">
|
||||
😓
|
||||
</span>{" "}
|
||||
Try again?
|
||||
</Text>
|
||||
);
|
||||
return <MajorErrorMessage error={error} variant="network" />;
|
||||
}
|
||||
|
||||
// Finally, render the item list, with checkboxes and Item components!
|
||||
|
|
|
@ -495,7 +495,8 @@ function getOutfitStateFromOutfitData(outfit) {
|
|||
function findItemConflicts(itemIdToAdd, state, apolloClient) {
|
||||
const { wornItemIds, speciesId, colorId, altStyleId } = state;
|
||||
|
||||
const { items } = apolloClient.readQuery({
|
||||
const itemIds = [itemIdToAdd, ...wornItemIds];
|
||||
const data = apolloClient.readQuery({
|
||||
query: gql`
|
||||
query OutfitStateItemConflicts(
|
||||
$itemIds: [ID!]!
|
||||
|
@ -524,12 +525,21 @@ function findItemConflicts(itemIdToAdd, state, apolloClient) {
|
|||
}
|
||||
`,
|
||||
variables: {
|
||||
itemIds: [itemIdToAdd, ...wornItemIds],
|
||||
itemIds,
|
||||
speciesId,
|
||||
colorId,
|
||||
altStyleId,
|
||||
},
|
||||
});
|
||||
if (data == null) {
|
||||
throw new Error(
|
||||
`[findItemConflicts] Cache lookup failed for: ` +
|
||||
`items=${itemIds.join(",")}, speciesId=${speciesId}, ` +
|
||||
`colorId=${colorId}, altStyleId=${altStyleId}`,
|
||||
);
|
||||
}
|
||||
|
||||
const { items } = data;
|
||||
const itemToAdd = items.find((i) => i.id === itemIdToAdd);
|
||||
if (!itemToAdd.appearanceOn) {
|
||||
return [];
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import gql from "graphql-tag";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
|
||||
import apolloClient from "../apolloClient";
|
||||
import { normalizeSwfAssetToLayer, normalizeZone } from "./shared-types";
|
||||
|
||||
export function useItemAppearances(id, options = {}) {
|
||||
|
@ -87,12 +89,77 @@ async function loadItemSearch(searchOptions) {
|
|||
);
|
||||
}
|
||||
|
||||
return res
|
||||
.json()
|
||||
.then((data) => normalizeItemSearchData(data, searchOptions));
|
||||
const data = await res.json();
|
||||
const result = normalizeItemSearchData(data, searchOptions);
|
||||
|
||||
for (const item of result.items) {
|
||||
writeItemToApolloCache(item, searchOptions.withAppearancesFor);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
window.loadItemSearch = loadItemSearch;
|
||||
|
||||
/**
|
||||
* writeItemToApolloCache is one last important bridge between our loaders and
|
||||
* GQL! In `useOutfitState`, we consult the GraphQL cache to look up basic item
|
||||
* info like zones, to decide when wearing an item would trigger a conflict
|
||||
* with another.
|
||||
*/
|
||||
function writeItemToApolloCache(item, { speciesId, colorId, altStyleId }) {
|
||||
apolloClient.writeQuery({
|
||||
query: gql`
|
||||
query WriteItemFromLoader(
|
||||
$itemId: ID!
|
||||
$speciesId: ID!
|
||||
$colorId: ID!
|
||||
$altStyleId: ID
|
||||
) {
|
||||
item(id: $itemId) {
|
||||
id
|
||||
name
|
||||
thumbnailUrl
|
||||
isNc
|
||||
isPb
|
||||
currentUserOwnsThis
|
||||
currentUserWantsThis
|
||||
appearanceOn(
|
||||
speciesId: $speciesId
|
||||
colorId: $colorId
|
||||
altStyleId: $altStyleId
|
||||
) {
|
||||
id
|
||||
layers {
|
||||
id
|
||||
remoteId
|
||||
bodyId
|
||||
knownGlitches
|
||||
svgUrl
|
||||
canvasMovieLibraryUrl
|
||||
imageUrl: imageUrlV2(idealSize: SIZE_600)
|
||||
swfUrl
|
||||
zone {
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
restrictedZones {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
itemId: item.id,
|
||||
speciesId,
|
||||
colorId,
|
||||
altStyleId,
|
||||
},
|
||||
data: { item },
|
||||
});
|
||||
}
|
||||
|
||||
function normalizeItemAppearancesData(data) {
|
||||
return {
|
||||
name: data.name,
|
||||
|
@ -106,9 +173,11 @@ function normalizeItemAppearancesData(data) {
|
|||
|
||||
function normalizeItemSearchData(data, searchOptions) {
|
||||
return {
|
||||
__typename: "ItemSearchResultV2",
|
||||
id: buildItemSearchParams(searchOptions),
|
||||
numTotalPages: data.total_pages,
|
||||
items: data.items.map((item) => ({
|
||||
__typename: "Item",
|
||||
id: String(item.id),
|
||||
name: item.name,
|
||||
thumbnailUrl: item.thumbnail_url,
|
||||
|
@ -130,6 +199,7 @@ function normalizeItemSearchAppearance(data, item) {
|
|||
}
|
||||
|
||||
return {
|
||||
__typename: "ItemAppearance",
|
||||
id: `item-${item.id}-body-${data.body.id}`,
|
||||
layers: data.swf_assets.map(normalizeSwfAssetToLayer),
|
||||
restrictedZones: data.swf_assets
|
||||
|
@ -145,6 +215,7 @@ function normalizeBody(body) {
|
|||
}
|
||||
|
||||
return {
|
||||
__typename: "Body",
|
||||
id: String(body.id),
|
||||
species: {
|
||||
id: String(body.species.id),
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
export function normalizeSwfAssetToLayer(data) {
|
||||
return {
|
||||
__typename: "AppearanceLayer",
|
||||
id: String(data.id),
|
||||
remoteId: String(data.remote_id),
|
||||
zone: normalizeZone(data.zone),
|
||||
|
@ -15,6 +16,7 @@ export function normalizeSwfAssetToLayer(data) {
|
|||
|
||||
export function normalizeZone(data) {
|
||||
return {
|
||||
__typename: "Zone",
|
||||
id: String(data.id),
|
||||
depth: data.depth,
|
||||
label: data.label,
|
||||
|
|
Loading…
Reference in a new issue