Add item search results to Apollo cache, use in finding item conflicts
This makes clicking on search results in the new mode actually work! It correctly adds it to the outfit, and removes other items. The thing that's behaving strangely is that, when you add the item, we visually remove all items until we can finish a fresh network request for what they should all look like. This probably means that the cache lookup for `useOutfitAppearance` is not as satisfied with what we cache here as `findItemConflicts` is? Something to investigate!
This commit is contained in:
parent
752bee3c39
commit
66c1e14dd0
3 changed files with 88 additions and 5 deletions
|
@ -495,7 +495,8 @@ function getOutfitStateFromOutfitData(outfit) {
|
||||||
function findItemConflicts(itemIdToAdd, state, apolloClient) {
|
function findItemConflicts(itemIdToAdd, state, apolloClient) {
|
||||||
const { wornItemIds, speciesId, colorId, altStyleId } = state;
|
const { wornItemIds, speciesId, colorId, altStyleId } = state;
|
||||||
|
|
||||||
const { items } = apolloClient.readQuery({
|
const itemIds = [itemIdToAdd, ...wornItemIds];
|
||||||
|
const data = apolloClient.readQuery({
|
||||||
query: gql`
|
query: gql`
|
||||||
query OutfitStateItemConflicts(
|
query OutfitStateItemConflicts(
|
||||||
$itemIds: [ID!]!
|
$itemIds: [ID!]!
|
||||||
|
@ -524,12 +525,21 @@ function findItemConflicts(itemIdToAdd, state, apolloClient) {
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
variables: {
|
variables: {
|
||||||
itemIds: [itemIdToAdd, ...wornItemIds],
|
itemIds,
|
||||||
speciesId,
|
speciesId,
|
||||||
colorId,
|
colorId,
|
||||||
altStyleId,
|
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);
|
const itemToAdd = items.find((i) => i.id === itemIdToAdd);
|
||||||
if (!itemToAdd.appearanceOn) {
|
if (!itemToAdd.appearanceOn) {
|
||||||
return [];
|
return [];
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
|
import gql from "graphql-tag";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
|
||||||
|
import apolloClient from "../apolloClient";
|
||||||
import { normalizeSwfAssetToLayer, normalizeZone } from "./shared-types";
|
import { normalizeSwfAssetToLayer, normalizeZone } from "./shared-types";
|
||||||
|
|
||||||
export function useItemAppearances(id, options = {}) {
|
export function useItemAppearances(id, options = {}) {
|
||||||
|
@ -87,12 +89,77 @@ async function loadItemSearch(searchOptions) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res
|
const data = await res.json();
|
||||||
.json()
|
const result = normalizeItemSearchData(data, searchOptions);
|
||||||
.then((data) => normalizeItemSearchData(data, searchOptions));
|
|
||||||
|
for (const item of result.items) {
|
||||||
|
writeItemToApolloCache(item, searchOptions.withAppearancesFor);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
window.loadItemSearch = loadItemSearch;
|
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
|
||||||
|
swfUrl
|
||||||
|
zone {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
restrictedZones {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
variables: {
|
||||||
|
itemId: item.id,
|
||||||
|
speciesId,
|
||||||
|
colorId,
|
||||||
|
altStyleId,
|
||||||
|
},
|
||||||
|
data: { item },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function normalizeItemAppearancesData(data) {
|
function normalizeItemAppearancesData(data) {
|
||||||
return {
|
return {
|
||||||
name: data.name,
|
name: data.name,
|
||||||
|
@ -106,9 +173,11 @@ function normalizeItemAppearancesData(data) {
|
||||||
|
|
||||||
function normalizeItemSearchData(data, searchOptions) {
|
function normalizeItemSearchData(data, searchOptions) {
|
||||||
return {
|
return {
|
||||||
|
__typename: "ItemSearchResultV2",
|
||||||
id: buildItemSearchParams(searchOptions),
|
id: buildItemSearchParams(searchOptions),
|
||||||
numTotalPages: data.total_pages,
|
numTotalPages: data.total_pages,
|
||||||
items: data.items.map((item) => ({
|
items: data.items.map((item) => ({
|
||||||
|
__typename: "Item",
|
||||||
id: String(item.id),
|
id: String(item.id),
|
||||||
name: item.name,
|
name: item.name,
|
||||||
thumbnailUrl: item.thumbnail_url,
|
thumbnailUrl: item.thumbnail_url,
|
||||||
|
@ -130,6 +199,7 @@ function normalizeItemSearchAppearance(data, item) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
__typename: "ItemAppearance",
|
||||||
id: `item-${item.id}-body-${data.body.id}`,
|
id: `item-${item.id}-body-${data.body.id}`,
|
||||||
layers: data.swf_assets.map(normalizeSwfAssetToLayer),
|
layers: data.swf_assets.map(normalizeSwfAssetToLayer),
|
||||||
restrictedZones: data.swf_assets
|
restrictedZones: data.swf_assets
|
||||||
|
@ -145,6 +215,7 @@ function normalizeBody(body) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
__typename: "Body",
|
||||||
id: String(body.id),
|
id: String(body.id),
|
||||||
species: {
|
species: {
|
||||||
id: String(body.species.id),
|
id: String(body.species.id),
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
export function normalizeSwfAssetToLayer(data) {
|
export function normalizeSwfAssetToLayer(data) {
|
||||||
return {
|
return {
|
||||||
|
__typename: "AppearanceLayer",
|
||||||
id: String(data.id),
|
id: String(data.id),
|
||||||
remoteId: String(data.remote_id),
|
remoteId: String(data.remote_id),
|
||||||
zone: normalizeZone(data.zone),
|
zone: normalizeZone(data.zone),
|
||||||
|
@ -15,6 +16,7 @@ export function normalizeSwfAssetToLayer(data) {
|
||||||
|
|
||||||
export function normalizeZone(data) {
|
export function normalizeZone(data) {
|
||||||
return {
|
return {
|
||||||
|
__typename: "Zone",
|
||||||
id: String(data.id),
|
id: String(data.id),
|
||||||
depth: data.depth,
|
depth: data.depth,
|
||||||
label: data.label,
|
label: data.label,
|
||||||
|
|
Loading…
Reference in a new issue