forked from OpenNeo/impress
Run Prettier on all wardrobe-2020 JS
Looks like the version of Prettier I just installed is v3, whereas our last run in the impress-2020 repo was with v2. I don't think we had any special config in that project, I think these are just changes to Prettier's defaults, and I'm comfortable accepting them! (Mostly seems like a lot of trailing commas.)
This commit is contained in:
parent
70d21e2815
commit
e300b2d342
39 changed files with 260 additions and 250 deletions
|
@ -9,5 +9,5 @@ ReactDOM.render(
|
||||||
<AppProvider>
|
<AppProvider>
|
||||||
<ItemPageOutfitPreview itemId={itemId} />
|
<ItemPageOutfitPreview itemId={itemId} />
|
||||||
</AppProvider>,
|
</AppProvider>,
|
||||||
rootNode
|
rootNode,
|
||||||
);
|
);
|
||||||
|
|
|
@ -8,5 +8,5 @@ ReactDOM.render(
|
||||||
<AppProvider>
|
<AppProvider>
|
||||||
<WardrobePage />
|
<WardrobePage />
|
||||||
</AppProvider>,
|
</AppProvider>,
|
||||||
rootNode
|
rootNode,
|
||||||
);
|
);
|
||||||
|
|
|
@ -55,7 +55,7 @@ function DTIApolloProvider({ children, additionalCacheState = {} }) {
|
||||||
getAuth0: () => auth0Ref.current,
|
getAuth0: () => auth0Ref.current,
|
||||||
initialCacheState,
|
initialCacheState,
|
||||||
}),
|
}),
|
||||||
[initialCacheState]
|
[initialCacheState],
|
||||||
);
|
);
|
||||||
|
|
||||||
// When we get a new `additionalCacheState` object, merge it into the cache:
|
// When we get a new `additionalCacheState` object, merge it into the cache:
|
||||||
|
@ -88,7 +88,7 @@ function DTIApolloProvider({ children, additionalCacheState = {} }) {
|
||||||
console.debug(
|
console.debug(
|
||||||
"Merging Apollo cache:",
|
"Merging Apollo cache:",
|
||||||
additionalCacheState,
|
additionalCacheState,
|
||||||
mergedCacheState
|
mergedCacheState,
|
||||||
);
|
);
|
||||||
client.cache.restore(mergedCacheState);
|
client.cache.restore(mergedCacheState);
|
||||||
}, [client, additionalCacheState]);
|
}, [client, additionalCacheState]);
|
||||||
|
|
|
@ -91,7 +91,7 @@ export function ItemPageContent({ itemId, isEmbedded = false }) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
{ variables: { itemId }, returnPartialData: true }
|
{ variables: { itemId }, returnPartialData: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
|
@ -296,7 +296,7 @@ const ItemPageOwnWantListsDropdownButton = React.forwardRef(
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
function ItemPageOwnWantListsDropdownContent({ closetLists, item }) {
|
function ItemPageOwnWantListsDropdownContent({ closetLists, item }) {
|
||||||
|
@ -330,7 +330,7 @@ function ItemPageOwnWantsListsDropdownRow({ closetList, item }) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
{ context: { sendAuth: true } }
|
{ context: { sendAuth: true } },
|
||||||
);
|
);
|
||||||
|
|
||||||
const [sendRemoveFromListMutation] = useMutation(
|
const [sendRemoveFromListMutation] = useMutation(
|
||||||
|
@ -346,7 +346,7 @@ function ItemPageOwnWantsListsDropdownRow({ closetList, item }) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
{ context: { sendAuth: true } }
|
{ context: { sendAuth: true } },
|
||||||
);
|
);
|
||||||
|
|
||||||
const onChange = React.useCallback(
|
const onChange = React.useCallback(
|
||||||
|
@ -391,7 +391,13 @@ function ItemPageOwnWantsListsDropdownRow({ closetList, item }) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[closetList, item, sendAddToListMutation, sendRemoveFromListMutation, toast]
|
[
|
||||||
|
closetList,
|
||||||
|
item,
|
||||||
|
sendAddToListMutation,
|
||||||
|
sendRemoveFromListMutation,
|
||||||
|
toast,
|
||||||
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -439,7 +445,7 @@ function ItemPageOwnButton({ itemId, isChecked }) {
|
||||||
context: { sendAuth: true },
|
context: { sendAuth: true },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const [sendRemoveMutation] = useMutation(
|
const [sendRemoveMutation] = useMutation(
|
||||||
|
@ -470,7 +476,7 @@ function ItemPageOwnButton({ itemId, isChecked }) {
|
||||||
context: { sendAuth: true },
|
context: { sendAuth: true },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -565,7 +571,7 @@ function ItemPageWantButton({ itemId, isChecked }) {
|
||||||
context: { sendAuth: true },
|
context: { sendAuth: true },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const [sendRemoveMutation] = useMutation(
|
const [sendRemoveMutation] = useMutation(
|
||||||
|
@ -596,7 +602,7 @@ function ItemPageWantButton({ itemId, isChecked }) {
|
||||||
context: { sendAuth: true },
|
context: { sendAuth: true },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -670,7 +676,7 @@ function ItemPageTradeLinks({ itemId, isEmbedded }) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
{ variables: { itemId } }
|
{ variables: { itemId } },
|
||||||
);
|
);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
|
@ -762,7 +768,7 @@ function IconCheckbox({ icon, isChecked, ...props }) {
|
||||||
export function ItemPageOutfitPreview({ itemId }) {
|
export function ItemPageOutfitPreview({ itemId }) {
|
||||||
const idealPose = React.useMemo(
|
const idealPose = React.useMemo(
|
||||||
() => (Math.random() > 0.5 ? "HAPPY_FEM" : "HAPPY_MASC"),
|
() => (Math.random() > 0.5 ? "HAPPY_FEM" : "HAPPY_MASC"),
|
||||||
[]
|
[],
|
||||||
);
|
);
|
||||||
const [petState, setPetState] = React.useState({
|
const [petState, setPetState] = React.useState({
|
||||||
// We'll fill these in once the canonical appearance data arrives.
|
// We'll fill these in once the canonical appearance data arrives.
|
||||||
|
@ -780,11 +786,11 @@ export function ItemPageOutfitPreview({ itemId }) {
|
||||||
});
|
});
|
||||||
const [preferredSpeciesId, setPreferredSpeciesId] = useLocalStorage(
|
const [preferredSpeciesId, setPreferredSpeciesId] = useLocalStorage(
|
||||||
"DTIItemPreviewPreferredSpeciesId",
|
"DTIItemPreviewPreferredSpeciesId",
|
||||||
null
|
null,
|
||||||
);
|
);
|
||||||
const [preferredColorId, setPreferredColorId] = useLocalStorage(
|
const [preferredColorId, setPreferredColorId] = useLocalStorage(
|
||||||
"DTIItemPreviewPreferredColorId",
|
"DTIItemPreviewPreferredColorId",
|
||||||
null
|
null,
|
||||||
);
|
);
|
||||||
|
|
||||||
const setPetStateFromUserAction = React.useCallback(
|
const setPetStateFromUserAction = React.useCallback(
|
||||||
|
@ -819,7 +825,7 @@ export function ItemPageOutfitPreview({ itemId }) {
|
||||||
|
|
||||||
return newPetState;
|
return newPetState;
|
||||||
}),
|
}),
|
||||||
[setPreferredColorId, setPreferredSpeciesId]
|
[setPreferredColorId, setPreferredSpeciesId],
|
||||||
);
|
);
|
||||||
|
|
||||||
// We don't need to reload this query when preferred species/color change, so
|
// We don't need to reload this query when preferred species/color change, so
|
||||||
|
@ -917,7 +923,7 @@ export function ItemPageOutfitPreview({ itemId }) {
|
||||||
appearanceId: canonicalPetAppearance?.id,
|
appearanceId: canonicalPetAppearance?.id,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const compatibleBodies =
|
const compatibleBodies =
|
||||||
|
@ -933,7 +939,7 @@ export function ItemPageOutfitPreview({ itemId }) {
|
||||||
compatibleBodies.length === 1 &&
|
compatibleBodies.length === 1 &&
|
||||||
!compatibleBodies[0].representsAllBodies &&
|
!compatibleBodies[0].representsAllBodies &&
|
||||||
(data?.item?.name || "").includes(
|
(data?.item?.name || "").includes(
|
||||||
data?.item?.canonicalAppearance?.body?.canonicalAppearance?.species?.name
|
data?.item?.canonicalAppearance?.body?.canonicalAppearance?.species?.name,
|
||||||
);
|
);
|
||||||
const couldProbablyModelMoreData = !isProbablySpeciesSpecific;
|
const couldProbablyModelMoreData = !isProbablySpeciesSpecific;
|
||||||
|
|
||||||
|
@ -979,7 +985,7 @@ export function ItemPageOutfitPreview({ itemId }) {
|
||||||
appearanceId: null,
|
appearanceId: null,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[valids, idealPose, setPetStateFromUserAction]
|
[valids, idealPose, setPetStateFromUserAction],
|
||||||
);
|
);
|
||||||
|
|
||||||
const borderColor = useColorModeValue("green.700", "green.400");
|
const borderColor = useColorModeValue("green.700", "green.400");
|
||||||
|
@ -1195,8 +1201,8 @@ function ExpandOnGroupHover({ children, ...props }) {
|
||||||
// I don't think this is possible, but I'd like to know if it happens!
|
// I don't think this is possible, but I'd like to know if it happens!
|
||||||
logAndCapture(
|
logAndCapture(
|
||||||
new Error(
|
new Error(
|
||||||
`Measurer node not ready during effect. Transition won't be smooth.`
|
`Measurer node not ready during effect. Transition won't be smooth.`,
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1277,8 +1283,8 @@ export function ItemZonesInfo({
|
||||||
|
|
||||||
const sortedZonesAndTheirBodies = [...zoneLabelsAndTheirBodies].sort((a, b) =>
|
const sortedZonesAndTheirBodies = [...zoneLabelsAndTheirBodies].sort((a, b) =>
|
||||||
buildSortKeyForZoneLabelsAndTheirBodies(a).localeCompare(
|
buildSortKeyForZoneLabelsAndTheirBodies(a).localeCompare(
|
||||||
buildSortKeyForZoneLabelsAndTheirBodies(b)
|
buildSortKeyForZoneLabelsAndTheirBodies(b),
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
const restrictedZoneLabels = [
|
const restrictedZoneLabels = [
|
||||||
|
@ -1290,8 +1296,8 @@ export function ItemZonesInfo({
|
||||||
// preview available in the list has the zones listed here.
|
// preview available in the list has the zones listed here.
|
||||||
const bodyGroups = new Set(
|
const bodyGroups = new Set(
|
||||||
zoneLabelsAndTheirBodies.map(({ bodies }) =>
|
zoneLabelsAndTheirBodies.map(({ bodies }) =>
|
||||||
bodies.map((b) => b.id).join(",")
|
bodies.map((b) => b.id).join(","),
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
const showBodyInfo = bodyGroups.size > 1;
|
const showBodyInfo = bodyGroups.size > 1;
|
||||||
|
|
||||||
|
|
|
@ -56,11 +56,11 @@ function SpeciesFacesPicker({
|
||||||
variables: { selectedColorId },
|
variables: { selectedColorId },
|
||||||
skip: selectedColorId == null || selectedColorIsBasic,
|
skip: selectedColorId == null || selectedColorIsBasic,
|
||||||
onError: (e) => console.error(e),
|
onError: (e) => console.error(e),
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const allBodiesAreCompatible = compatibleBodies.some(
|
const allBodiesAreCompatible = compatibleBodies.some(
|
||||||
(body) => body.representsAllBodies
|
(body) => body.representsAllBodies,
|
||||||
);
|
);
|
||||||
const compatibleBodyIds = compatibleBodies.map((body) => body.id);
|
const compatibleBodyIds = compatibleBodies.map((body) => body.id);
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ function SpeciesFacesPicker({
|
||||||
|
|
||||||
const allSpeciesFaces = DEFAULT_SPECIES_FACES.map((defaultSpeciesFace) => {
|
const allSpeciesFaces = DEFAULT_SPECIES_FACES.map((defaultSpeciesFace) => {
|
||||||
const providedSpeciesFace = speciesFacesFromData.find(
|
const providedSpeciesFace = speciesFacesFromData.find(
|
||||||
(f) => f.species.id === defaultSpeciesFace.speciesId
|
(f) => f.species.id === defaultSpeciesFace.speciesId,
|
||||||
);
|
);
|
||||||
if (providedSpeciesFace) {
|
if (providedSpeciesFace) {
|
||||||
return {
|
return {
|
||||||
|
@ -250,7 +250,8 @@ const SpeciesFaceOption = React.memo(
|
||||||
input:checked + & {
|
input:checked + & {
|
||||||
background: ${selectedBackgroundColorValue};
|
background: ${selectedBackgroundColorValue};
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
box-shadow: ${xlShadow},
|
box-shadow:
|
||||||
|
${xlShadow},
|
||||||
${selectedBorderColorValue} 0 0 2px 2px;
|
${selectedBorderColorValue} 0 0 2px 2px;
|
||||||
transform: scale(1.2);
|
transform: scale(1.2);
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
@ -258,7 +259,9 @@ const SpeciesFaceOption = React.memo(
|
||||||
|
|
||||||
input:focus + & {
|
input:focus + & {
|
||||||
background: ${focusBackgroundColorValue};
|
background: ${focusBackgroundColorValue};
|
||||||
box-shadow: ${xlShadow}, ${focusBorderColorValue} 0 0 0 3px;
|
box-shadow:
|
||||||
|
${xlShadow},
|
||||||
|
${focusBorderColorValue} 0 0 0 3px;
|
||||||
}
|
}
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
|
@ -324,7 +327,7 @@ const SpeciesFaceOption = React.memo(
|
||||||
)}
|
)}
|
||||||
</ClassNames>
|
</ClassNames>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -364,7 +364,7 @@ const LinkBadge = React.forwardRef(
|
||||||
}
|
}
|
||||||
</Badge>
|
</Badge>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const fullDateFormatter = new Intl.DateTimeFormat("en-US", {
|
const fullDateFormatter = new Intl.DateTimeFormat("en-US", {
|
||||||
|
|
|
@ -26,7 +26,7 @@ import useSupport from "./support/useSupport";
|
||||||
|
|
||||||
const LoadableItemPageDrawer = loadable(() => import("../ItemPageDrawer"));
|
const LoadableItemPageDrawer = loadable(() => import("../ItemPageDrawer"));
|
||||||
const LoadableItemSupportDrawer = loadable(() =>
|
const LoadableItemSupportDrawer = loadable(() =>
|
||||||
import("./support/ItemSupportDrawer")
|
import("./support/ItemSupportDrawer"),
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -151,17 +151,17 @@ function ItemContainer({ children, isDisabled = false }) {
|
||||||
|
|
||||||
const focusBackgroundColor = useColorModeValue(
|
const focusBackgroundColor = useColorModeValue(
|
||||||
theme.colors.gray["100"],
|
theme.colors.gray["100"],
|
||||||
theme.colors.gray["700"]
|
theme.colors.gray["700"],
|
||||||
);
|
);
|
||||||
|
|
||||||
const activeBorderColor = useColorModeValue(
|
const activeBorderColor = useColorModeValue(
|
||||||
theme.colors.green["400"],
|
theme.colors.green["400"],
|
||||||
theme.colors.green["500"]
|
theme.colors.green["500"],
|
||||||
);
|
);
|
||||||
|
|
||||||
const focusCheckedBorderColor = useColorModeValue(
|
const focusCheckedBorderColor = useColorModeValue(
|
||||||
theme.colors.green["800"],
|
theme.colors.green["800"],
|
||||||
theme.colors.green["300"]
|
theme.colors.green["300"],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -205,10 +205,10 @@ function ItemBadges({ item }) {
|
||||||
const { isSupportUser } = useSupport();
|
const { isSupportUser } = useSupport();
|
||||||
const occupiedZones = item.appearanceOn.layers.map((l) => l.zone);
|
const occupiedZones = item.appearanceOn.layers.map((l) => l.zone);
|
||||||
const restrictedZones = item.appearanceOn.restrictedZones.filter(
|
const restrictedZones = item.appearanceOn.restrictedZones.filter(
|
||||||
(z) => z.isCommonlyUsedByItems
|
(z) => z.isCommonlyUsedByItems,
|
||||||
);
|
);
|
||||||
const isMaybeAnimated = item.appearanceOn.layers.some(
|
const isMaybeAnimated = item.appearanceOn.layers.some(
|
||||||
(l) => l.canvasMovieLibraryUrl
|
(l) => l.canvasMovieLibraryUrl,
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -237,11 +237,11 @@ function ItemActionButton({ icon, label, to, onClick }) {
|
||||||
|
|
||||||
const focusBackgroundColor = useColorModeValue(
|
const focusBackgroundColor = useColorModeValue(
|
||||||
theme.colors.gray["300"],
|
theme.colors.gray["300"],
|
||||||
theme.colors.gray["800"]
|
theme.colors.gray["800"],
|
||||||
);
|
);
|
||||||
const focusColor = useColorModeValue(
|
const focusColor = useColorModeValue(
|
||||||
theme.colors.gray["700"],
|
theme.colors.gray["700"],
|
||||||
theme.colors.gray["200"]
|
theme.colors.gray["200"],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -35,7 +35,7 @@ function ItemsAndSearchPanels({
|
||||||
const hasRoomForSearchFooter = useBreakpointValue({ base: false, md: true });
|
const hasRoomForSearchFooter = useBreakpointValue({ base: false, md: true });
|
||||||
const [canUseSearchFooter] = useLocalStorage(
|
const [canUseSearchFooter] = useLocalStorage(
|
||||||
"DTIFeatureFlagCanUseSearchFooter",
|
"DTIFeatureFlagCanUseSearchFooter",
|
||||||
false
|
false,
|
||||||
);
|
);
|
||||||
const isShowingSearchFooter = canUseSearchFooter && hasRoomForSearchFooter;
|
const isShowingSearchFooter = canUseSearchFooter && hasRoomForSearchFooter;
|
||||||
|
|
||||||
|
|
|
@ -164,7 +164,7 @@ function ItemZoneGroup({
|
||||||
(itemId) => {
|
(itemId) => {
|
||||||
dispatchToOutfit({ type: "removeItem", itemId });
|
dispatchToOutfit({ type: "removeItem", itemId });
|
||||||
},
|
},
|
||||||
[dispatchToOutfit]
|
[dispatchToOutfit],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -472,7 +472,7 @@ function DeleteOutfitMenuItem({ outfitState }) {
|
||||||
cache.evict(`Outfit:${id}`);
|
cache.evict(`Outfit:${id}`);
|
||||||
cache.gc();
|
cache.gc();
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -62,11 +62,11 @@ function OutfitControls({
|
||||||
const [focusIsLocked, setFocusIsLocked] = React.useState(false);
|
const [focusIsLocked, setFocusIsLocked] = React.useState(false);
|
||||||
const onLockFocus = React.useCallback(
|
const onLockFocus = React.useCallback(
|
||||||
() => setFocusIsLocked(true),
|
() => setFocusIsLocked(true),
|
||||||
[setFocusIsLocked]
|
[setFocusIsLocked],
|
||||||
);
|
);
|
||||||
const onUnlockFocus = React.useCallback(
|
const onUnlockFocus = React.useCallback(
|
||||||
() => setFocusIsLocked(false),
|
() => setFocusIsLocked(false),
|
||||||
[setFocusIsLocked]
|
[setFocusIsLocked],
|
||||||
);
|
);
|
||||||
|
|
||||||
// HACK: As of 1.0.0-rc.0, Chakra's `toast` function rebuilds unnecessarily,
|
// HACK: As of 1.0.0-rc.0, Chakra's `toast` function rebuilds unnecessarily,
|
||||||
|
@ -97,7 +97,7 @@ function OutfitControls({
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[dispatchToOutfit, toast]
|
[dispatchToOutfit, toast],
|
||||||
);
|
);
|
||||||
|
|
||||||
const maybeUnlockFocus = (e) => {
|
const maybeUnlockFocus = (e) => {
|
||||||
|
@ -145,11 +145,11 @@ function OutfitControls({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
focusIsLocked && "focus-is-locked"
|
focusIsLocked && "focus-is-locked",
|
||||||
)}
|
)}
|
||||||
onClickCapture={(e) => {
|
onClickCapture={(e) => {
|
||||||
const opacity = parseFloat(
|
const opacity = parseFloat(
|
||||||
getComputedStyle(e.currentTarget).opacity
|
getComputedStyle(e.currentTarget).opacity,
|
||||||
);
|
);
|
||||||
if (opacity < 0.5) {
|
if (opacity < 0.5) {
|
||||||
// If the controls aren't visible right now, then clicks on them are
|
// If the controls aren't visible right now, then clicks on them are
|
||||||
|
@ -321,7 +321,7 @@ function OutfitHTML5Badge({ appearance }) {
|
||||||
appearance.petAppearance?.layers.every(layerUsesHTML5);
|
appearance.petAppearance?.layers.every(layerUsesHTML5);
|
||||||
|
|
||||||
const itemsNotUsingHTML5 = appearance.items.filter((item) =>
|
const itemsNotUsingHTML5 = appearance.items.filter((item) =>
|
||||||
item.appearance.layers.some((l) => !layerUsesHTML5(l))
|
item.appearance.layers.some((l) => !layerUsesHTML5(l)),
|
||||||
);
|
);
|
||||||
itemsNotUsingHTML5.sort((a, b) => a.name.localeCompare(b.name));
|
itemsNotUsingHTML5.sort((a, b) => a.name.localeCompare(b.name));
|
||||||
|
|
||||||
|
@ -448,7 +448,7 @@ function PlayPauseButton() {
|
||||||
// We show an intro animation if this mounts while paused. Whereas if we're
|
// We show an intro animation if this mounts while paused. Whereas if we're
|
||||||
// not paused, we initialize as if we had already finished.
|
// not paused, we initialize as if we had already finished.
|
||||||
const [blinkInState, setBlinkInState] = React.useState(
|
const [blinkInState, setBlinkInState] = React.useState(
|
||||||
isPaused ? { type: "ready" } : { type: "done" }
|
isPaused ? { type: "ready" } : { type: "done" },
|
||||||
);
|
);
|
||||||
const buttonRef = React.useRef(null);
|
const buttonRef = React.useRef(null);
|
||||||
|
|
||||||
|
@ -532,7 +532,7 @@ const PlayPauseButtonContent = React.forwardRef(
|
||||||
{isPaused ? <>Paused</> : <>Playing</>}
|
{isPaused ? <>Paused</> : <>Playing</>}
|
||||||
</TranslucentButton>
|
</TranslucentButton>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
function SettingsButton({ onLockFocus, onUnlockFocus }) {
|
function SettingsButton({ onLockFocus, onUnlockFocus }) {
|
||||||
|
@ -700,7 +700,7 @@ function useDownloadableImage(visibleLayers) {
|
||||||
loadImage(getBestImageUrlForLayer(layer, { hiResMode }), {
|
loadImage(getBestImageUrlForLayer(layer, { hiResMode }), {
|
||||||
crossOrigin: "anonymous",
|
crossOrigin: "anonymous",
|
||||||
preferArchive,
|
preferArchive,
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
let images;
|
let images;
|
||||||
|
@ -729,7 +729,7 @@ function useDownloadableImage(visibleLayers) {
|
||||||
console.debug(
|
console.debug(
|
||||||
"Generated image for download",
|
"Generated image for download",
|
||||||
layerIds,
|
layerIds,
|
||||||
canvas.toDataURL("image/png")
|
canvas.toDataURL("image/png"),
|
||||||
);
|
);
|
||||||
setDownloadImageUrl(canvas.toDataURL("image/png"));
|
setDownloadImageUrl(canvas.toDataURL("image/png"));
|
||||||
setPreparedForLayerIds(layerIds);
|
setPreparedForLayerIds(layerIds);
|
||||||
|
|
|
@ -36,7 +36,7 @@ function OutfitKnownGlitchesBadge({ appearance }) {
|
||||||
We're hiding the item art, which is outdated behavior, and we should
|
We're hiding the item art, which is outdated behavior, and we should
|
||||||
instead be treating it as entirely incompatible. Fixing this is in
|
instead be treating it as entirely incompatible. Fixing this is in
|
||||||
our todo list, sorry for the confusing UI!
|
our todo list, sorry for the confusing UI!
|
||||||
</Box>
|
</Box>,
|
||||||
);
|
);
|
||||||
} else if (compatibleItemLayers.length < allItemLayers.length) {
|
} else if (compatibleItemLayers.length < allItemLayers.length) {
|
||||||
glitchMessages.push(
|
glitchMessages.push(
|
||||||
|
@ -45,7 +45,7 @@ function OutfitKnownGlitchesBadge({ appearance }) {
|
||||||
we believe this is how it looks: some zones are visible, and some
|
we believe this is how it looks: some zones are visible, and some
|
||||||
zones are hidden. If this isn't quite right, please email me at
|
zones are hidden. If this isn't quite right, please email me at
|
||||||
matchu@openneo.net and let me know!
|
matchu@openneo.net and let me know!
|
||||||
</Box>
|
</Box>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,12 +54,12 @@ function OutfitKnownGlitchesBadge({ appearance }) {
|
||||||
// Look for items with the OFFICIAL_SWF_IS_INCORRECT glitch.
|
// Look for items with the OFFICIAL_SWF_IS_INCORRECT glitch.
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
const itemHasBrokenOnNeopetsDotCom = item.appearance.layers.some((l) =>
|
const itemHasBrokenOnNeopetsDotCom = item.appearance.layers.some((l) =>
|
||||||
(l.knownGlitches || []).includes("OFFICIAL_SWF_IS_INCORRECT")
|
(l.knownGlitches || []).includes("OFFICIAL_SWF_IS_INCORRECT"),
|
||||||
);
|
);
|
||||||
const itemHasBrokenUnconvertedLayers = item.appearance.layers.some(
|
const itemHasBrokenUnconvertedLayers = item.appearance.layers.some(
|
||||||
(l) =>
|
(l) =>
|
||||||
(l.knownGlitches || []).includes("OFFICIAL_SWF_IS_INCORRECT") &&
|
(l.knownGlitches || []).includes("OFFICIAL_SWF_IS_INCORRECT") &&
|
||||||
!layerUsesHTML5(l)
|
!layerUsesHTML5(l),
|
||||||
);
|
);
|
||||||
if (itemHasBrokenOnNeopetsDotCom) {
|
if (itemHasBrokenOnNeopetsDotCom) {
|
||||||
glitchMessages.push(
|
glitchMessages.push(
|
||||||
|
@ -79,7 +79,7 @@ function OutfitKnownGlitchesBadge({ appearance }) {
|
||||||
know if it looks right, or still looks wrong! Thank you!
|
know if it looks right, or still looks wrong! Thank you!
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ function OutfitKnownGlitchesBadge({ appearance }) {
|
||||||
// Look for items with the OFFICIAL_MOVIE_IS_INCORRECT glitch.
|
// Look for items with the OFFICIAL_MOVIE_IS_INCORRECT glitch.
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
const itemHasGlitch = item.appearance.layers.some((l) =>
|
const itemHasGlitch = item.appearance.layers.some((l) =>
|
||||||
(l.knownGlitches || []).includes("OFFICIAL_MOVIE_IS_INCORRECT")
|
(l.knownGlitches || []).includes("OFFICIAL_MOVIE_IS_INCORRECT"),
|
||||||
);
|
);
|
||||||
if (itemHasGlitch) {
|
if (itemHasGlitch) {
|
||||||
glitchMessages.push(
|
glitchMessages.push(
|
||||||
|
@ -96,7 +96,7 @@ function OutfitKnownGlitchesBadge({ appearance }) {
|
||||||
looks this way on-site, too. But our version might be out of date! If
|
looks this way on-site, too. But our version might be out of date! If
|
||||||
you've seen it look better on-site, please email me at
|
you've seen it look better on-site, please email me at
|
||||||
matchu@openneo.net so we can fix it!
|
matchu@openneo.net so we can fix it!
|
||||||
</Box>
|
</Box>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ function OutfitKnownGlitchesBadge({ appearance }) {
|
||||||
if (hiResMode) {
|
if (hiResMode) {
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
const itemHasOfficialSvgIsIncorrect = item.appearance.layers.some((l) =>
|
const itemHasOfficialSvgIsIncorrect = item.appearance.layers.some((l) =>
|
||||||
(l.knownGlitches || []).includes("OFFICIAL_SVG_IS_INCORRECT")
|
(l.knownGlitches || []).includes("OFFICIAL_SVG_IS_INCORRECT"),
|
||||||
);
|
);
|
||||||
if (itemHasOfficialSvgIsIncorrect) {
|
if (itemHasOfficialSvgIsIncorrect) {
|
||||||
glitchMessages.push(
|
glitchMessages.push(
|
||||||
|
@ -114,7 +114,7 @@ function OutfitKnownGlitchesBadge({ appearance }) {
|
||||||
There's a glitch in the art for <i>{item.name}</i> that prevents us
|
There's a glitch in the art for <i>{item.name}</i> that prevents us
|
||||||
from showing the SVG image for Hi-Res Mode. Instead, we're showing a
|
from showing the SVG image for Hi-Res Mode. Instead, we're showing a
|
||||||
PNG, which might look a bit blurry on larger screens.
|
PNG, which might look a bit blurry on larger screens.
|
||||||
</Box>
|
</Box>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,9 @@ function OutfitKnownGlitchesBadge({ appearance }) {
|
||||||
// Look for items with the DISPLAYS_INCORRECTLY_BUT_CAUSE_UNKNOWN glitch.
|
// Look for items with the DISPLAYS_INCORRECTLY_BUT_CAUSE_UNKNOWN glitch.
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
const itemHasGlitch = item.appearance.layers.some((l) =>
|
const itemHasGlitch = item.appearance.layers.some((l) =>
|
||||||
(l.knownGlitches || []).includes("DISPLAYS_INCORRECTLY_BUT_CAUSE_UNKNOWN")
|
(l.knownGlitches || []).includes(
|
||||||
|
"DISPLAYS_INCORRECTLY_BUT_CAUSE_UNKNOWN",
|
||||||
|
),
|
||||||
);
|
);
|
||||||
if (itemHasGlitch) {
|
if (itemHasGlitch) {
|
||||||
glitchMessages.push(
|
glitchMessages.push(
|
||||||
|
@ -132,7 +134,7 @@ function OutfitKnownGlitchesBadge({ appearance }) {
|
||||||
display incorrectly—but we're not sure if it's on our end, or TNT's.
|
display incorrectly—but we're not sure if it's on our end, or TNT's.
|
||||||
If you own this item, please email me at matchu@openneo.net to let us
|
If you own this item, please email me at matchu@openneo.net to let us
|
||||||
know how it looks in the on-site customizer!
|
know how it looks in the on-site customizer!
|
||||||
</Box>
|
</Box>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,7 +142,7 @@ function OutfitKnownGlitchesBadge({ appearance }) {
|
||||||
// Look for items with the OFFICIAL_BODY_ID_IS_INCORRECT glitch.
|
// Look for items with the OFFICIAL_BODY_ID_IS_INCORRECT glitch.
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
const itemHasOfficialBodyIdIsIncorrect = item.appearance.layers.some((l) =>
|
const itemHasOfficialBodyIdIsIncorrect = item.appearance.layers.some((l) =>
|
||||||
(l.knownGlitches || []).includes("OFFICIAL_BODY_ID_IS_INCORRECT")
|
(l.knownGlitches || []).includes("OFFICIAL_BODY_ID_IS_INCORRECT"),
|
||||||
);
|
);
|
||||||
if (itemHasOfficialBodyIdIsIncorrect) {
|
if (itemHasOfficialBodyIdIsIncorrect) {
|
||||||
glitchMessages.push(
|
glitchMessages.push(
|
||||||
|
@ -148,7 +150,7 @@ function OutfitKnownGlitchesBadge({ appearance }) {
|
||||||
Last we checked, <i>{item.name}</i> actually is compatible with this
|
Last we checked, <i>{item.name}</i> actually is compatible with this
|
||||||
pet, even though it seems like it shouldn't be. But TNT might change
|
pet, even though it seems like it shouldn't be. But TNT might change
|
||||||
this at any time, so be careful!
|
this at any time, so be careful!
|
||||||
</Box>
|
</Box>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -164,7 +166,7 @@ function OutfitKnownGlitchesBadge({ appearance }) {
|
||||||
<i>{item.name}</i> isn't converted to HTML5 yet, and our Classic DTI
|
<i>{item.name}</i> isn't converted to HTML5 yet, and our Classic DTI
|
||||||
code often shows old Dyeworks items in the wrong color. Once it's
|
code often shows old Dyeworks items in the wrong color. Once it's
|
||||||
converted, we'll display it correctly!
|
converted, we'll display it correctly!
|
||||||
</Box>
|
</Box>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,7 +180,7 @@ function OutfitKnownGlitchesBadge({ appearance }) {
|
||||||
this pose looks incorrect, you can try another by clicking the emoji
|
this pose looks incorrect, you can try another by clicking the emoji
|
||||||
face next to the species/color picker. But be aware that Neopets.com
|
face next to the species/color picker. But be aware that Neopets.com
|
||||||
might look different!
|
might look different!
|
||||||
</Box>
|
</Box>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,7 +196,7 @@ function OutfitKnownGlitchesBadge({ appearance }) {
|
||||||
horn with the feminine design, and the yellow horn with the masculine
|
horn with the feminine design, and the yellow horn with the masculine
|
||||||
design—but the pet's gender does not actually affect which horn you'll
|
design—but the pet's gender does not actually affect which horn you'll
|
||||||
get, and it will often change over time!
|
get, and it will often change over time!
|
||||||
</Box>
|
</Box>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,7 +213,7 @@ function OutfitKnownGlitchesBadge({ appearance }) {
|
||||||
correct data, we'll use that instead. For now, you could also try
|
correct data, we'll use that instead. For now, you could also try
|
||||||
switching to another pose, by clicking the emoji face next to the
|
switching to another pose, by clicking the emoji face next to the
|
||||||
species/color picker!
|
species/color picker!
|
||||||
</Box>
|
</Box>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,7 +222,7 @@ function OutfitKnownGlitchesBadge({ appearance }) {
|
||||||
// Look for pet layers with the OFFICIAL_SWF_IS_INCORRECT glitch.
|
// Look for pet layers with the OFFICIAL_SWF_IS_INCORRECT glitch.
|
||||||
for (const layer of petLayers) {
|
for (const layer of petLayers) {
|
||||||
const layerHasGlitch = (layer.knownGlitches || []).includes(
|
const layerHasGlitch = (layer.knownGlitches || []).includes(
|
||||||
"OFFICIAL_SWF_IS_INCORRECT"
|
"OFFICIAL_SWF_IS_INCORRECT",
|
||||||
);
|
);
|
||||||
if (layerHasGlitch) {
|
if (layerHasGlitch) {
|
||||||
glitchMessages.push(
|
glitchMessages.push(
|
||||||
|
@ -230,7 +232,7 @@ function OutfitKnownGlitchesBadge({ appearance }) {
|
||||||
affected its appearance on Neopets.com, too. But our version might be
|
affected its appearance on Neopets.com, too. But our version might be
|
||||||
out of date! If you've seen it look better on-site, please email me at
|
out of date! If you've seen it look better on-site, please email me at
|
||||||
matchu@openneo.net so we can fix it!
|
matchu@openneo.net so we can fix it!
|
||||||
</Box>
|
</Box>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -248,7 +250,7 @@ function OutfitKnownGlitchesBadge({ appearance }) {
|
||||||
zone that prevents us from showing the SVG image for Hi-Res Mode.
|
zone that prevents us from showing the SVG image for Hi-Res Mode.
|
||||||
Instead, we're showing a PNG, which might look a bit blurry on
|
Instead, we're showing a PNG, which might look a bit blurry on
|
||||||
larger screens.
|
larger screens.
|
||||||
</Box>
|
</Box>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -257,7 +259,7 @@ function OutfitKnownGlitchesBadge({ appearance }) {
|
||||||
// Look for pet layers with the DISPLAYS_INCORRECTLY_BUT_CAUSE_UNKNOWN glitch.
|
// Look for pet layers with the DISPLAYS_INCORRECTLY_BUT_CAUSE_UNKNOWN glitch.
|
||||||
for (const layer of petLayers) {
|
for (const layer of petLayers) {
|
||||||
const layerHasGlitch = (layer.knownGlitches || []).includes(
|
const layerHasGlitch = (layer.knownGlitches || []).includes(
|
||||||
"DISPLAYS_INCORRECTLY_BUT_CAUSE_UNKNOWN"
|
"DISPLAYS_INCORRECTLY_BUT_CAUSE_UNKNOWN",
|
||||||
);
|
);
|
||||||
if (layerHasGlitch) {
|
if (layerHasGlitch) {
|
||||||
glitchMessages.push(
|
glitchMessages.push(
|
||||||
|
@ -269,7 +271,7 @@ function OutfitKnownGlitchesBadge({ appearance }) {
|
||||||
on our end, or TNT's. If you have this pet, please email me at
|
on our end, or TNT's. If you have this pet, please email me at
|
||||||
matchu@openneo.net to let us know how it looks in the on-site
|
matchu@openneo.net to let us know how it looks in the on-site
|
||||||
customizer!
|
customizer!
|
||||||
</Box>
|
</Box>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ import twemojiFem from "../images/twemoji/fem.svg";
|
||||||
const PosePickerSupport = loadable(() => import("./support/PosePickerSupport"));
|
const PosePickerSupport = loadable(() => import("./support/PosePickerSupport"));
|
||||||
|
|
||||||
const PosePickerSupportSwitch = loadable(() =>
|
const PosePickerSupportSwitch = loadable(() =>
|
||||||
import("./support/PosePickerSupport").then((m) => m.PosePickerSupportSwitch)
|
import("./support/PosePickerSupport").then((m) => m.PosePickerSupportSwitch),
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -68,7 +68,7 @@ function PosePicker({
|
||||||
const { loading, error, poseInfos } = usePoses(speciesId, colorId, pose);
|
const { loading, error, poseInfos } = usePoses(speciesId, colorId, pose);
|
||||||
const [isInSupportMode, setIsInSupportMode] = useLocalStorage(
|
const [isInSupportMode, setIsInSupportMode] = useLocalStorage(
|
||||||
"DTIPosePickerIsInSupportMode",
|
"DTIPosePickerIsInSupportMode",
|
||||||
false
|
false,
|
||||||
);
|
);
|
||||||
const { isSupportUser } = useSupport();
|
const { isSupportUser } = useSupport();
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
|
@ -87,10 +87,10 @@ function PosePicker({
|
||||||
// can happen with direct URL navigation, or pet loading when modeling isn't
|
// can happen with direct URL navigation, or pet loading when modeling isn't
|
||||||
// updated! Let's do some recovery.
|
// updated! Let's do some recovery.
|
||||||
const selectedPoseIsAvailable = Object.values(poseInfos).some(
|
const selectedPoseIsAvailable = Object.values(poseInfos).some(
|
||||||
(pi) => pi.isSelected && pi.isAvailable
|
(pi) => pi.isSelected && pi.isAvailable,
|
||||||
);
|
);
|
||||||
const firstAvailablePose = Object.values(poseInfos).find(
|
const firstAvailablePose = Object.values(poseInfos).find(
|
||||||
(pi) => pi.isAvailable
|
(pi) => pi.isAvailable,
|
||||||
)?.pose;
|
)?.pose;
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (loading) {
|
if (loading) {
|
||||||
|
@ -114,7 +114,7 @@ function PosePicker({
|
||||||
|
|
||||||
console.warn(
|
console.warn(
|
||||||
`Pose ${pose} not found for speciesId=${speciesId}, ` +
|
`Pose ${pose} not found for speciesId=${speciesId}, ` +
|
||||||
`colorId=${colorId}. Redirecting to pose ${firstAvailablePose}.`
|
`colorId=${colorId}. Redirecting to pose ${firstAvailablePose}.`,
|
||||||
);
|
);
|
||||||
dispatchToOutfit({ type: "setPose", pose: firstAvailablePose });
|
dispatchToOutfit({ type: "setPose", pose: firstAvailablePose });
|
||||||
}
|
}
|
||||||
|
@ -143,7 +143,7 @@ function PosePicker({
|
||||||
// (Unless we're Support, in which case we want the ability to pop it open to
|
// (Unless we're Support, in which case we want the ability to pop it open to
|
||||||
// inspect and label the Unknown poses!)
|
// inspect and label the Unknown poses!)
|
||||||
const numAvailablePoses = Object.values(poseInfos).filter(
|
const numAvailablePoses = Object.values(poseInfos).filter(
|
||||||
(p) => p.isAvailable
|
(p) => p.isAvailable,
|
||||||
).length;
|
).length;
|
||||||
if (numAvailablePoses <= 1 && !isSupportUser) {
|
if (numAvailablePoses <= 1 && !isSupportUser) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -192,7 +192,7 @@ function PosePicker({
|
||||||
border-width: 2px !important;
|
border-width: 2px !important;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
isOpen && "is-open"
|
isOpen && "is-open",
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
|
@ -393,7 +393,7 @@ function PoseOption({
|
||||||
|
|
||||||
const borderColor = useColorModeValue(
|
const borderColor = useColorModeValue(
|
||||||
theme.colors.green["600"],
|
theme.colors.green["600"],
|
||||||
theme.colors.green["300"]
|
theme.colors.green["300"],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -480,7 +480,7 @@ function PoseOption({
|
||||||
border-width: 3px;
|
border-width: 3px;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
!poseInfo.isAvailable && "not-available"
|
!poseInfo.isAvailable && "not-available",
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
{poseInfo.isAvailable ? (
|
{poseInfo.isAvailable ? (
|
||||||
|
@ -580,7 +580,7 @@ function usePoses(speciesId, colorId, selectedPose) {
|
||||||
|
|
||||||
${petAppearanceForPosePickerFragment}
|
${petAppearanceForPosePickerFragment}
|
||||||
`,
|
`,
|
||||||
{ variables: { speciesId, colorId }, onError: (e) => console.error(e) }
|
{ variables: { speciesId, colorId }, onError: (e) => console.error(e) },
|
||||||
);
|
);
|
||||||
|
|
||||||
const poseInfos = {
|
const poseInfos = {
|
||||||
|
|
|
@ -13,13 +13,13 @@ import { useSearchResults } from "./useSearchResults";
|
||||||
function SearchFooter({ searchQuery, onChangeSearchQuery, outfitState }) {
|
function SearchFooter({ searchQuery, onChangeSearchQuery, outfitState }) {
|
||||||
const [canUseSearchFooter, setCanUseSearchFooter] = useLocalStorage(
|
const [canUseSearchFooter, setCanUseSearchFooter] = useLocalStorage(
|
||||||
"DTIFeatureFlagCanUseSearchFooter",
|
"DTIFeatureFlagCanUseSearchFooter",
|
||||||
false
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
const { items, numTotalPages } = useSearchResults(
|
const { items, numTotalPages } = useSearchResults(
|
||||||
searchQuery,
|
searchQuery,
|
||||||
outfitState,
|
outfitState,
|
||||||
1
|
1,
|
||||||
);
|
);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
|
|
|
@ -85,7 +85,7 @@ function SearchResults({
|
||||||
const { loading, error, items, numTotalPages } = useSearchResults(
|
const { loading, error, items, numTotalPages } = useSearchResults(
|
||||||
query,
|
query,
|
||||||
outfitState,
|
outfitState,
|
||||||
currentPageNumber
|
currentPageNumber,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Preload the previous and next page of search results, with this quick
|
// Preload the previous and next page of search results, with this quick
|
||||||
|
@ -121,7 +121,7 @@ function SearchResults({
|
||||||
onMoveFocusUpToQuery(e);
|
onMoveFocusUpToQuery(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[onMoveFocusUpToQuery]
|
[onMoveFocusUpToQuery],
|
||||||
);
|
);
|
||||||
const goToNextItem = React.useCallback((e) => {
|
const goToNextItem = React.useCallback((e) => {
|
||||||
const nextLabel = e.target.closest("label").nextSibling;
|
const nextLabel = e.target.closest("label").nextSibling;
|
||||||
|
@ -223,7 +223,7 @@ function SearchResultItem({
|
||||||
itemId: item.id,
|
itemId: item.id,
|
||||||
itemIdsToReconsider,
|
itemIdsToReconsider,
|
||||||
}),
|
}),
|
||||||
[item.id, itemIdsToReconsider, dispatchToOutfit]
|
[item.id, itemIdsToReconsider, dispatchToOutfit],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -111,7 +111,7 @@ function SearchToolbar({
|
||||||
{text}
|
{text}
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
[suggestionBgColor, highlightedBgColor]
|
[suggestionBgColor, highlightedBgColor],
|
||||||
);
|
);
|
||||||
|
|
||||||
const renderSuggestionsContainer = React.useCallback(
|
const renderSuggestionsContainer = React.useCallback(
|
||||||
|
@ -133,7 +133,7 @@ function SearchToolbar({
|
||||||
li {
|
li {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
}
|
}
|
||||||
`
|
`,
|
||||||
)}
|
)}
|
||||||
{...SUGGESTIONS_PLACEMENT_PROPS[suggestionsPlacement]}
|
{...SUGGESTIONS_PLACEMENT_PROPS[suggestionsPlacement]}
|
||||||
>
|
>
|
||||||
|
@ -153,7 +153,7 @@ function SearchToolbar({
|
||||||
</ClassNames>
|
</ClassNames>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
[advancedSearchIsOpen, suggestionsPlacement]
|
[advancedSearchIsOpen, suggestionsPlacement],
|
||||||
);
|
);
|
||||||
|
|
||||||
// When we change the query filters, clear out the suggestions.
|
// When we change the query filters, clear out the suggestions.
|
||||||
|
@ -205,7 +205,7 @@ function SearchToolbar({
|
||||||
// always happened? Idk? Let's just, gate around it, I guess?
|
// always happened? Idk? Let's just, gate around it, I guess?
|
||||||
if (typeof value === "string") {
|
if (typeof value === "string") {
|
||||||
setSuggestions(
|
setSuggestions(
|
||||||
getSuggestions(value, query, zoneLabels, isLoggedIn)
|
getSuggestions(value, query, zoneLabels, isLoggedIn),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
@ -342,7 +342,7 @@ function getSuggestions(
|
||||||
query,
|
query,
|
||||||
zoneLabels,
|
zoneLabels,
|
||||||
isLoggedIn,
|
isLoggedIn,
|
||||||
{ showAll = false } = {}
|
{ showAll = false } = {},
|
||||||
) {
|
) {
|
||||||
if (!value && !showAll) {
|
if (!value && !showAll) {
|
||||||
return [];
|
return [];
|
||||||
|
@ -467,8 +467,8 @@ function removeLastWord(text) {
|
||||||
logAndCapture(
|
logAndCapture(
|
||||||
new Error(
|
new Error(
|
||||||
`Assertion failure: pattern should match any input text, ` +
|
`Assertion failure: pattern should match any input text, ` +
|
||||||
`but failed to match ${JSON.stringify(text)}`
|
`but failed to match ${JSON.stringify(text)}`,
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ function OutfitThumbnailIfCached({ outfitId }) {
|
||||||
skip: outfitId == null,
|
skip: outfitId == null,
|
||||||
fetchPolicy: "cache-only",
|
fetchPolicy: "cache-only",
|
||||||
onError: (e) => console.error(e),
|
onError: (e) => console.error(e),
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!data?.outfit) {
|
if (!data?.outfit) {
|
||||||
|
|
|
@ -117,7 +117,7 @@ function WardrobePage() {
|
||||||
*/
|
*/
|
||||||
function SavedOutfitMetaTags({ outfitState }) {
|
function SavedOutfitMetaTags({ outfitState }) {
|
||||||
const updatedAtTimestamp = Math.floor(
|
const updatedAtTimestamp = Math.floor(
|
||||||
new Date(outfitState.updatedAt).getTime() / 1000
|
new Date(outfitState.updatedAt).getTime() / 1000,
|
||||||
);
|
);
|
||||||
const imageUrl =
|
const imageUrl =
|
||||||
`https://impress-outfit-images.openneo.net/outfits` +
|
`https://impress-outfit-images.openneo.net/outfits` +
|
||||||
|
|
|
@ -67,7 +67,7 @@ function AllItemLayersSupportModal({ item, isOpen, onClose }) {
|
||||||
|
|
||||||
function BulkAddBodySpecificAssetsForm({ bulkAddProposal, onSubmit }) {
|
function BulkAddBodySpecificAssetsForm({ bulkAddProposal, onSubmit }) {
|
||||||
const [minAssetId, setMinAssetId] = React.useState(
|
const [minAssetId, setMinAssetId] = React.useState(
|
||||||
bulkAddProposal?.minAssetId
|
bulkAddProposal?.minAssetId,
|
||||||
);
|
);
|
||||||
const [assetIdStepValue, setAssetIdStepValue] = React.useState(1);
|
const [assetIdStepValue, setAssetIdStepValue] = React.useState(1);
|
||||||
const [numSpecies, setNumSpecies] = React.useState(55);
|
const [numSpecies, setNumSpecies] = React.useState(55);
|
||||||
|
@ -136,7 +136,7 @@ function BulkAddBodySpecificAssetsForm({ bulkAddProposal, onSubmit }) {
|
||||||
setMinAssetId(
|
setMinAssetId(
|
||||||
e.target.value
|
e.target.value
|
||||||
? Number(e.target.value) - assetIdStepValue * (numSpecies - 1)
|
? Number(e.target.value) - assetIdStepValue * (numSpecies - 1)
|
||||||
: null
|
: null,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
@ -230,7 +230,7 @@ function AllItemLayersSupportModalContent({
|
||||||
|
|
||||||
${allAppearancesFragment}
|
${allAppearancesFragment}
|
||||||
`,
|
`,
|
||||||
{ variables: { itemId: item.id } }
|
{ variables: { itemId: item.id } },
|
||||||
);
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
@ -293,14 +293,14 @@ function AllItemLayersSupportModalContent({
|
||||||
? Array.from({ length: 54 }, (_, i) =>
|
? Array.from({ length: 54 }, (_, i) =>
|
||||||
String(
|
String(
|
||||||
Number(bulkAddProposal.minAssetId) +
|
Number(bulkAddProposal.minAssetId) +
|
||||||
i * bulkAddProposal.assetIdStepValue
|
i * bulkAddProposal.assetIdStepValue,
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
: [],
|
: [],
|
||||||
colorId: bulkAddProposal?.colorId,
|
colorId: bulkAddProposal?.colorId,
|
||||||
},
|
},
|
||||||
skip: bulkAddProposal == null,
|
skip: bulkAddProposal == null,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const [
|
const [
|
||||||
|
@ -341,7 +341,7 @@ function AllItemLayersSupportModalContent({
|
||||||
itemAppearances = mergeBulkAddProposalIntoItemAppearances(
|
itemAppearances = mergeBulkAddProposalIntoItemAppearances(
|
||||||
itemAppearances,
|
itemAppearances,
|
||||||
bulkAddProposal,
|
bulkAddProposal,
|
||||||
bulkAddProposalData
|
bulkAddProposalData,
|
||||||
);
|
);
|
||||||
itemAppearances = [...itemAppearances].sort((a, b) => {
|
itemAppearances = [...itemAppearances].sort((a, b) => {
|
||||||
const aKey = getSortKeyForBody(a.body);
|
const aKey = getSortKeyForBody(a.body);
|
||||||
|
@ -383,7 +383,7 @@ function AllItemLayersSupportModalContent({
|
||||||
// that we use for body assignment in most of this tool.
|
// that we use for body assignment in most of this tool.
|
||||||
const entries = itemAppearances
|
const entries = itemAppearances
|
||||||
.map((a) =>
|
.map((a) =>
|
||||||
a.layers.map((l) => ({ layerId: l.id, bodyId: a.body.id }))
|
a.layers.map((l) => ({ layerId: l.id, bodyId: a.body.id })),
|
||||||
)
|
)
|
||||||
.flat();
|
.flat();
|
||||||
|
|
||||||
|
@ -415,7 +415,7 @@ function ItemAppearanceCard({ item, itemAppearance }) {
|
||||||
const petAppearance = itemAppearance.body.canonicalAppearance;
|
const petAppearance = itemAppearance.body.canonicalAppearance;
|
||||||
const biologyLayers = petAppearance.layers;
|
const biologyLayers = petAppearance.layers;
|
||||||
const itemLayers = [...itemAppearance.layers].sort(
|
const itemLayers = [...itemAppearance.layers].sort(
|
||||||
(a, b) => a.zone.depth - b.zone.depth
|
(a, b) => a.zone.depth - b.zone.depth,
|
||||||
);
|
);
|
||||||
|
|
||||||
const { brightBackground } = useCommonStyles();
|
const { brightBackground } = useCommonStyles();
|
||||||
|
@ -494,7 +494,7 @@ function capitalize(str) {
|
||||||
function mergeBulkAddProposalIntoItemAppearances(
|
function mergeBulkAddProposalIntoItemAppearances(
|
||||||
itemAppearances,
|
itemAppearances,
|
||||||
bulkAddProposal,
|
bulkAddProposal,
|
||||||
bulkAddProposalData
|
bulkAddProposalData,
|
||||||
) {
|
) {
|
||||||
if (!bulkAddProposalData) {
|
if (!bulkAddProposalData) {
|
||||||
return itemAppearances;
|
return itemAppearances;
|
||||||
|
@ -514,7 +514,7 @@ function mergeBulkAddProposalIntoItemAppearances(
|
||||||
|
|
||||||
// Set up the incoming data in convenient formats.
|
// Set up the incoming data in convenient formats.
|
||||||
const sortedSpeciesColorPairs = [...speciesColorPairsToInclude].sort((a, b) =>
|
const sortedSpeciesColorPairs = [...speciesColorPairsToInclude].sort((a, b) =>
|
||||||
a.species.name.localeCompare(b.species.name)
|
a.species.name.localeCompare(b.species.name),
|
||||||
);
|
);
|
||||||
const layersToAddByRemoteId = {};
|
const layersToAddByRemoteId = {};
|
||||||
for (const layer of layersToAdd) {
|
for (const layer of layersToAdd) {
|
||||||
|
@ -527,7 +527,7 @@ function mergeBulkAddProposalIntoItemAppearances(
|
||||||
// Find the existing item appearance to add to, or create a new one if it
|
// Find the existing item appearance to add to, or create a new one if it
|
||||||
// doesn't exist yet.
|
// doesn't exist yet.
|
||||||
let itemAppearance = mergedItemAppearances.find(
|
let itemAppearance = mergedItemAppearances.find(
|
||||||
(a) => a.body.id === body.id && !a.body.representsAllBodies
|
(a) => a.body.id === body.id && !a.body.representsAllBodies,
|
||||||
);
|
);
|
||||||
if (!itemAppearance) {
|
if (!itemAppearance) {
|
||||||
itemAppearance = {
|
itemAppearance = {
|
||||||
|
@ -543,7 +543,7 @@ function mergeBulkAddProposalIntoItemAppearances(
|
||||||
|
|
||||||
const layerToAddRemoteId = String(
|
const layerToAddRemoteId = String(
|
||||||
Number(bulkAddProposal.minAssetId) +
|
Number(bulkAddProposal.minAssetId) +
|
||||||
index * bulkAddProposal.assetIdStepValue
|
index * bulkAddProposal.assetIdStepValue,
|
||||||
);
|
);
|
||||||
const layerToAdd = layersToAddByRemoteId[layerToAddRemoteId];
|
const layerToAdd = layersToAddByRemoteId[layerToAddRemoteId];
|
||||||
if (!layerToAdd) {
|
if (!layerToAdd) {
|
||||||
|
@ -554,7 +554,7 @@ function mergeBulkAddProposalIntoItemAppearances(
|
||||||
// override its body ID), then add it to this new one.
|
// override its body ID), then add it to this new one.
|
||||||
for (const otherItemAppearance of mergedItemAppearances) {
|
for (const otherItemAppearance of mergedItemAppearances) {
|
||||||
const indexToDelete = otherItemAppearance.layers.findIndex(
|
const indexToDelete = otherItemAppearance.layers.findIndex(
|
||||||
(l) => l.remoteId === layerToAddRemoteId
|
(l) => l.remoteId === layerToAddRemoteId,
|
||||||
);
|
);
|
||||||
if (indexToDelete >= 0) {
|
if (indexToDelete >= 0) {
|
||||||
otherItemAppearance.layers.splice(indexToDelete, 1);
|
otherItemAppearance.layers.splice(indexToDelete, 1);
|
||||||
|
|
|
@ -50,7 +50,7 @@ function AppearanceLayerSupportModal({
|
||||||
}) {
|
}) {
|
||||||
const [selectedBodyId, setSelectedBodyId] = React.useState(layer.bodyId);
|
const [selectedBodyId, setSelectedBodyId] = React.useState(layer.bodyId);
|
||||||
const [selectedKnownGlitches, setSelectedKnownGlitches] = React.useState(
|
const [selectedKnownGlitches, setSelectedKnownGlitches] = React.useState(
|
||||||
layer.knownGlitches
|
layer.knownGlitches,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [previewBiology, setPreviewBiology] = React.useState({
|
const [previewBiology, setPreviewBiology] = React.useState({
|
||||||
|
@ -140,7 +140,7 @@ function AppearanceLayerSupportModal({
|
||||||
title: `Saved layer ${layer.id}: ${parentName}`,
|
title: `Saved layer ${layer.id}: ${parentName}`,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO: Would be nicer to just learn the correct URL from the server, but we
|
// TODO: Would be nicer to just learn the correct URL from the server, but we
|
||||||
|
@ -148,7 +148,7 @@ function AppearanceLayerSupportModal({
|
||||||
// the GraphQL request for non-Support users. We could also just try
|
// the GraphQL request for non-Support users. We could also just try
|
||||||
// loading them, but, ehhh…
|
// loading them, but, ehhh…
|
||||||
const [newManifestUrl, oldManifestUrl] = convertSwfUrlToPossibleManifestUrls(
|
const [newManifestUrl, oldManifestUrl] = convertSwfUrlToPossibleManifestUrls(
|
||||||
layer.swfUrl
|
layer.swfUrl,
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -553,7 +553,7 @@ function AppearanceLayerSupportModalRemoveButton({
|
||||||
title: `Removed layer ${layer.id} from ${item.name}`,
|
title: `Removed layer ${layer.id} from ${item.name}`,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -54,7 +54,7 @@ function AppearanceLayerSupportUploadModal({ item, layer, isOpen, onClose }) {
|
||||||
mergeIntoImageWithAlpha(
|
mergeIntoImageWithAlpha(
|
||||||
imageOnBlackUrl,
|
imageOnBlackUrl,
|
||||||
imageOnWhiteUrl,
|
imageOnWhiteUrl,
|
||||||
conflictMode
|
conflictMode,
|
||||||
).then(([url, blob, numWarnings]) => {
|
).then(([url, blob, numWarnings]) => {
|
||||||
setImageWithAlphaUrl(url);
|
setImageWithAlphaUrl(url);
|
||||||
setImageWithAlphaBlob(blob);
|
setImageWithAlphaBlob(blob);
|
||||||
|
@ -86,7 +86,7 @@ function AppearanceLayerSupportUploadModal({ item, layer, isOpen, onClose }) {
|
||||||
};
|
};
|
||||||
reader.readAsDataURL(file);
|
reader.readAsDataURL(file);
|
||||||
},
|
},
|
||||||
[step]
|
[step],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onSubmitFinalImage = React.useCallback(async () => {
|
const onSubmitFinalImage = React.useCallback(async () => {
|
||||||
|
@ -104,7 +104,7 @@ function AppearanceLayerSupportUploadModal({ item, layer, isOpen, onClose }) {
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
setIsUploading(false);
|
setIsUploading(false);
|
||||||
setUploadError(
|
setUploadError(
|
||||||
new Error(`Network error: ${res.status} ${res.statusText}`)
|
new Error(`Network error: ${res.status} ${res.statusText}`),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -432,7 +432,7 @@ function AppearanceLayerSupportFlashPlayer({ swfUrl, backgroundColor }) {
|
||||||
async function mergeIntoImageWithAlpha(
|
async function mergeIntoImageWithAlpha(
|
||||||
imageOnBlackUrl,
|
imageOnBlackUrl,
|
||||||
imageOnWhiteUrl,
|
imageOnWhiteUrl,
|
||||||
conflictMode
|
conflictMode,
|
||||||
) {
|
) {
|
||||||
const [imageOnBlack, imageOnWhite] = await Promise.all([
|
const [imageOnBlack, imageOnWhite] = await Promise.all([
|
||||||
readImageDataFromUrl(imageOnBlackUrl),
|
readImageDataFromUrl(imageOnBlackUrl),
|
||||||
|
@ -442,7 +442,7 @@ async function mergeIntoImageWithAlpha(
|
||||||
const [imageWithAlphaData, numWarnings] = mergeDataIntoImageWithAlpha(
|
const [imageWithAlphaData, numWarnings] = mergeDataIntoImageWithAlpha(
|
||||||
imageOnBlack,
|
imageOnBlack,
|
||||||
imageOnWhite,
|
imageOnWhite,
|
||||||
conflictMode
|
conflictMode,
|
||||||
);
|
);
|
||||||
const [imageWithAlphaUrl, imageWithAlphaBlob] =
|
const [imageWithAlphaUrl, imageWithAlphaBlob] =
|
||||||
await writeImageDataToUrlAndBlob(imageWithAlphaData);
|
await writeImageDataToUrlAndBlob(imageWithAlphaData);
|
||||||
|
@ -474,14 +474,14 @@ function mergeDataIntoImageWithAlpha(imageOnBlack, imageOnWhite, conflictMode) {
|
||||||
` vs ` +
|
` vs ` +
|
||||||
`#${rOnBlack.toString(16)}${bOnBlack.toString(16)}` +
|
`#${rOnBlack.toString(16)}${bOnBlack.toString(16)}` +
|
||||||
`${gOnWhite.toString(16)}. ` +
|
`${gOnWhite.toString(16)}. ` +
|
||||||
`Using conflict mode ${conflictMode} to fall back.`
|
`Using conflict mode ${conflictMode} to fall back.`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const [r, g, b, a] = resolveConflict(
|
const [r, g, b, a] = resolveConflict(
|
||||||
[rOnBlack, gOnBlack, bOnBlack],
|
[rOnBlack, gOnBlack, bOnBlack],
|
||||||
[rOnWhite, gOnWhite, bOnWhite],
|
[rOnWhite, gOnWhite, bOnWhite],
|
||||||
conflictMode
|
conflictMode,
|
||||||
);
|
);
|
||||||
imageWithAlpha.data[pixelIndex] = r;
|
imageWithAlpha.data[pixelIndex] = r;
|
||||||
imageWithAlpha.data[pixelIndex + 1] = g;
|
imageWithAlpha.data[pixelIndex + 1] = g;
|
||||||
|
@ -513,14 +513,14 @@ function mergeDataIntoImageWithAlpha(imageOnBlack, imageOnWhite, conflictMode) {
|
||||||
` vs ` +
|
` vs ` +
|
||||||
`#${rOnBlack.toString(16)}${bOnBlack.toString(16)}` +
|
`#${rOnBlack.toString(16)}${bOnBlack.toString(16)}` +
|
||||||
`${gOnWhite.toString(16)}. ` +
|
`${gOnWhite.toString(16)}. ` +
|
||||||
`Using conflict mode ${conflictMode} to fall back.`
|
`Using conflict mode ${conflictMode} to fall back.`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const [r, g, b, a] = resolveConflict(
|
const [r, g, b, a] = resolveConflict(
|
||||||
[rOnBlack, gOnBlack, bOnBlack],
|
[rOnBlack, gOnBlack, bOnBlack],
|
||||||
[rOnWhite, gOnWhite, bOnWhite],
|
[rOnWhite, gOnWhite, bOnWhite],
|
||||||
conflictMode
|
conflictMode,
|
||||||
);
|
);
|
||||||
imageWithAlpha.data[pixelIndex] = r;
|
imageWithAlpha.data[pixelIndex] = r;
|
||||||
imageWithAlpha.data[pixelIndex + 1] = g;
|
imageWithAlpha.data[pixelIndex + 1] = g;
|
||||||
|
@ -585,7 +585,7 @@ async function writeImageDataToUrlAndBlob(imageData) {
|
||||||
|
|
||||||
const dataUrl = canvas.toDataURL("image/png");
|
const dataUrl = canvas.toDataURL("image/png");
|
||||||
const blob = await new Promise((resolve) =>
|
const blob = await new Promise((resolve) =>
|
||||||
canvas.toBlob(resolve, "image/png")
|
canvas.toBlob(resolve, "image/png"),
|
||||||
);
|
);
|
||||||
return [dataUrl, blob];
|
return [dataUrl, blob];
|
||||||
}
|
}
|
||||||
|
@ -593,7 +593,7 @@ async function writeImageDataToUrlAndBlob(imageData) {
|
||||||
function resolveConflict(
|
function resolveConflict(
|
||||||
[rOnBlack, gOnBlack, bOnBlack],
|
[rOnBlack, gOnBlack, bOnBlack],
|
||||||
[rOnWhite, gOnWhite, bOnWhite],
|
[rOnWhite, gOnWhite, bOnWhite],
|
||||||
conflictMode
|
conflictMode,
|
||||||
) {
|
) {
|
||||||
if (conflictMode === "onBlack") {
|
if (conflictMode === "onBlack") {
|
||||||
return [rOnBlack, gOnBlack, bOnBlack, 255];
|
return [rOnBlack, gOnBlack, bOnBlack, 255];
|
||||||
|
|
|
@ -114,7 +114,7 @@ function ItemSupportRestrictedZones({ item }) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
{ variables: { itemId: item.id, speciesId, colorId } }
|
{ variables: { itemId: item.id, speciesId, colorId } },
|
||||||
);
|
);
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
|
@ -160,7 +160,7 @@ function ItemSupportFields({ item }) {
|
||||||
// persuades Apollo that this is a different query, so it re-checks
|
// persuades Apollo that this is a different query, so it re-checks
|
||||||
// its cache and finds the empty `manualSpecialColor`. Weird!
|
// its cache and finds the empty `manualSpecialColor`. Weird!
|
||||||
displayName: `ItemSupportFields-${new Date()}`,
|
displayName: `ItemSupportFields-${new Date()}`,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const errorColor = useColorModeValue("red.500", "red.300");
|
const errorColor = useColorModeValue("red.500", "red.300");
|
||||||
|
@ -196,8 +196,7 @@ function ItemSupportSpecialColorFields({
|
||||||
loading: colorsLoading,
|
loading: colorsLoading,
|
||||||
error: colorsError,
|
error: colorsError,
|
||||||
data: colorsData,
|
data: colorsData,
|
||||||
} = useQuery(
|
} = useQuery(gql`
|
||||||
gql`
|
|
||||||
query ItemSupportDrawerAllColors {
|
query ItemSupportDrawerAllColors {
|
||||||
allColors {
|
allColors {
|
||||||
id
|
id
|
||||||
|
@ -205,8 +204,7 @@ function ItemSupportSpecialColorFields({
|
||||||
isStandard
|
isStandard
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`);
|
||||||
);
|
|
||||||
|
|
||||||
const [
|
const [
|
||||||
mutate,
|
mutate,
|
||||||
|
@ -253,7 +251,7 @@ function ItemSupportSpecialColorFields({
|
||||||
// Ignore errors from the promise, because we'll handle them on render!
|
// Ignore errors from the promise, because we'll handle them on render!
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[item.id, mutate, supportSecret]
|
[item.id, mutate, supportSecret],
|
||||||
);
|
);
|
||||||
|
|
||||||
const nonStandardColors =
|
const nonStandardColors =
|
||||||
|
@ -362,7 +360,7 @@ function ItemSupportPetCompatibilityRuleFields({
|
||||||
// Ignore errors from the promise, because we'll handle them on render!
|
// Ignore errors from the promise, because we'll handle them on render!
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[item.id, mutate, supportSecret]
|
[item.id, mutate, supportSecret],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -82,7 +82,7 @@ function PosePickerSupport({
|
||||||
${canonicalPetAppearancesFragment}
|
${canonicalPetAppearancesFragment}
|
||||||
${petAppearanceForPosePickerFragment}
|
${petAppearanceForPosePickerFragment}
|
||||||
`,
|
`,
|
||||||
{ variables: { speciesId, colorId } }
|
{ variables: { speciesId, colorId } },
|
||||||
);
|
);
|
||||||
|
|
||||||
// Resize the Popover when we toggle loading state, because it probably will
|
// Resize the Popover when we toggle loading state, because it probably will
|
||||||
|
@ -111,7 +111,7 @@ function PosePickerSupport({
|
||||||
UNKNOWN: data?.unknown?.id,
|
UNKNOWN: data?.unknown?.id,
|
||||||
};
|
};
|
||||||
const canonicalAppearanceIds = Object.values(
|
const canonicalAppearanceIds = Object.values(
|
||||||
canonicalAppearanceIdsByPose
|
canonicalAppearanceIdsByPose,
|
||||||
).filter((id) => id);
|
).filter((id) => id);
|
||||||
|
|
||||||
const providedAppearanceId = appearanceId;
|
const providedAppearanceId = appearanceId;
|
||||||
|
@ -149,7 +149,7 @@ function PosePickerSupport({
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentPetAppearance = data.petAppearances.find(
|
const currentPetAppearance = data.petAppearances.find(
|
||||||
(pa) => pa.id === appearanceId
|
(pa) => pa.id === appearanceId,
|
||||||
);
|
);
|
||||||
if (!currentPetAppearance) {
|
if (!currentPetAppearance) {
|
||||||
return (
|
return (
|
||||||
|
@ -353,7 +353,7 @@ function PosePickerSupportPoseFields({ petAppearance, speciesId, colorId }) {
|
||||||
variables: { speciesId, colorId },
|
variables: { speciesId, colorId },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const [mutateIsGlitched, isGlitchedMutation] = useMutation(
|
const [mutateIsGlitched, isGlitchedMutation] = useMutation(
|
||||||
|
@ -388,7 +388,7 @@ function PosePickerSupportPoseFields({ petAppearance, speciesId, colorId }) {
|
||||||
variables: { speciesId, colorId },
|
variables: { speciesId, colorId },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -21,7 +21,7 @@ function useSupport() {
|
||||||
typeof localStorage !== "undefined"
|
typeof localStorage !== "undefined"
|
||||||
? localStorage.getItem("supportSecret")
|
? localStorage.getItem("supportSecret")
|
||||||
: null,
|
: null,
|
||||||
[]
|
[],
|
||||||
);
|
);
|
||||||
|
|
||||||
const isSupportUser = supportSecret != null;
|
const isSupportUser = supportSecret != null;
|
||||||
|
|
|
@ -27,14 +27,14 @@ function useOutfitSaving(outfitState, dispatchToOutfit) {
|
||||||
outfitState.savedOutfitState &&
|
outfitState.savedOutfitState &&
|
||||||
outfitStatesAreEqual(
|
outfitStatesAreEqual(
|
||||||
outfitState.outfitStateWithoutExtras,
|
outfitState.outfitStateWithoutExtras,
|
||||||
outfitState.savedOutfitState
|
outfitState.savedOutfitState,
|
||||||
);
|
);
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
console.debug(
|
console.debug(
|
||||||
"[useOutfitSaving] Latest version is saved? %s\nCurrent: %o\nSaved: %o",
|
"[useOutfitSaving] Latest version is saved? %s\nCurrent: %o\nSaved: %o",
|
||||||
latestVersionIsSaved,
|
latestVersionIsSaved,
|
||||||
outfitState.outfitStateWithoutExtras,
|
outfitState.outfitStateWithoutExtras,
|
||||||
outfitState.savedOutfitState
|
outfitState.savedOutfitState,
|
||||||
);
|
);
|
||||||
}, [
|
}, [
|
||||||
latestVersionIsSaved,
|
latestVersionIsSaved,
|
||||||
|
@ -107,7 +107,7 @@ function useOutfitSaving(outfitState, dispatchToOutfit) {
|
||||||
fields: {
|
fields: {
|
||||||
outfits: (existingOutfitRefs = [], { readField }) => {
|
outfits: (existingOutfitRefs = [], { readField }) => {
|
||||||
const isAlreadyInList = existingOutfitRefs.some(
|
const isAlreadyInList = existingOutfitRefs.some(
|
||||||
(ref) => readField("id", ref) === outfit.id
|
(ref) => readField("id", ref) === outfit.id,
|
||||||
);
|
);
|
||||||
if (isAlreadyInList) {
|
if (isAlreadyInList) {
|
||||||
return existingOutfitRefs;
|
return existingOutfitRefs;
|
||||||
|
@ -139,7 +139,7 @@ function useOutfitSaving(outfitState, dispatchToOutfit) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const saveOutfitFromProvidedState = React.useCallback(
|
const saveOutfitFromProvidedState = React.useCallback(
|
||||||
|
@ -176,12 +176,12 @@ function useOutfitSaving(outfitState, dispatchToOutfit) {
|
||||||
// It's important that this callback _doesn't_ change when the outfit
|
// It's important that this callback _doesn't_ change when the outfit
|
||||||
// changes, so that the auto-save effect is only responding to the
|
// changes, so that the auto-save effect is only responding to the
|
||||||
// debounced state!
|
// debounced state!
|
||||||
[sendSaveOutfitMutation, pathname, navigate, toast]
|
[sendSaveOutfitMutation, pathname, navigate, toast],
|
||||||
);
|
);
|
||||||
|
|
||||||
const saveOutfit = React.useCallback(
|
const saveOutfit = React.useCallback(
|
||||||
() => saveOutfitFromProvidedState(outfitState.outfitStateWithoutExtras),
|
() => saveOutfitFromProvidedState(outfitState.outfitStateWithoutExtras),
|
||||||
[saveOutfitFromProvidedState, outfitState.outfitStateWithoutExtras]
|
[saveOutfitFromProvidedState, outfitState.outfitStateWithoutExtras],
|
||||||
);
|
);
|
||||||
|
|
||||||
// Auto-saving! First, debounce the outfit state. Use `outfitStateWithoutExtras`,
|
// Auto-saving! First, debounce the outfit state. Use `outfitStateWithoutExtras`,
|
||||||
|
@ -196,7 +196,7 @@ function useOutfitSaving(outfitState, dispatchToOutfit) {
|
||||||
// When the outfit ID changes, update the debounced state immediately!
|
// When the outfit ID changes, update the debounced state immediately!
|
||||||
forceReset: (debouncedOutfitState, newOutfitState) =>
|
forceReset: (debouncedOutfitState, newOutfitState) =>
|
||||||
debouncedOutfitState.id !== newOutfitState.id,
|
debouncedOutfitState.id !== newOutfitState.id,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
// HACK: This prevents us from auto-saving the outfit state that's still
|
// HACK: This prevents us from auto-saving the outfit state that's still
|
||||||
// loading. I worry that this might not catch other loading scenarios
|
// loading. I worry that this might not catch other loading scenarios
|
||||||
|
@ -216,7 +216,7 @@ function useOutfitSaving(outfitState, dispatchToOutfit) {
|
||||||
console.info(
|
console.info(
|
||||||
"[useOutfitSaving] Auto-saving outfit\nSaved: %o\nCurrent (debounced): %o",
|
"[useOutfitSaving] Auto-saving outfit\nSaved: %o\nCurrent (debounced): %o",
|
||||||
outfitState.savedOutfitState,
|
outfitState.savedOutfitState,
|
||||||
debouncedOutfitState
|
debouncedOutfitState,
|
||||||
);
|
);
|
||||||
saveOutfitFromProvidedState(debouncedOutfitState);
|
saveOutfitFromProvidedState(debouncedOutfitState);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ function useOutfitState() {
|
||||||
const urlOutfitState = useParseOutfitUrl();
|
const urlOutfitState = useParseOutfitUrl();
|
||||||
const [localOutfitState, dispatchToOutfit] = React.useReducer(
|
const [localOutfitState, dispatchToOutfit] = React.useReducer(
|
||||||
outfitStateReducer(apolloClient),
|
outfitStateReducer(apolloClient),
|
||||||
urlOutfitState
|
urlOutfitState,
|
||||||
);
|
);
|
||||||
|
|
||||||
// If there's an outfit ID (i.e. we're on /outfits/:id), load basic data
|
// If there's an outfit ID (i.e. we're on /outfits/:id), load basic data
|
||||||
|
@ -68,7 +68,7 @@ function useOutfitState() {
|
||||||
savedOutfitData: outfitData.outfit,
|
savedOutfitData: outfitData.outfit,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const creator = outfitData?.outfit?.creator;
|
const creator = outfitData?.outfit?.creator;
|
||||||
|
@ -78,7 +78,7 @@ function useOutfitState() {
|
||||||
// stable object!
|
// stable object!
|
||||||
const savedOutfitState = React.useMemo(
|
const savedOutfitState = React.useMemo(
|
||||||
() => getOutfitStateFromOutfitData(outfitData?.outfit),
|
() => getOutfitStateFromOutfitData(outfitData?.outfit),
|
||||||
[outfitData?.outfit]
|
[outfitData?.outfit],
|
||||||
);
|
);
|
||||||
|
|
||||||
// Choose which customization state to use. We want it to match the outfit in
|
// Choose which customization state to use. We want it to match the outfit in
|
||||||
|
@ -182,7 +182,7 @@ function useOutfitState() {
|
||||||
// have the species/color ID loaded yet because we're waiting on the
|
// have the species/color ID loaded yet because we're waiting on the
|
||||||
// saved outfit to load.
|
// saved outfit to load.
|
||||||
skip: allItemIds.length === 0 || speciesId == null || colorId == null,
|
skip: allItemIds.length === 0 || speciesId == null || colorId == null,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const resultItems = itemsData?.items || [];
|
const resultItems = itemsData?.items || [];
|
||||||
|
@ -226,7 +226,7 @@ function useOutfitState() {
|
||||||
const zonesAndItems = getZonesAndItems(
|
const zonesAndItems = getZonesAndItems(
|
||||||
itemsById,
|
itemsById,
|
||||||
wornItemIds,
|
wornItemIds,
|
||||||
closetedItemIds
|
closetedItemIds,
|
||||||
);
|
);
|
||||||
const incompatibleItems = items
|
const incompatibleItems = items
|
||||||
.filter((i) => i.appearanceOn.layers.length === 0)
|
.filter((i) => i.appearanceOn.layers.length === 0)
|
||||||
|
@ -334,7 +334,7 @@ const outfitStateReducer = (apolloClient) => (baseState, action) => {
|
||||||
// Don't include the unworn item in items to reconsider!
|
// Don't include the unworn item in items to reconsider!
|
||||||
itemIdsToReconsider.filter((x) => x !== itemId),
|
itemIdsToReconsider.filter((x) => x !== itemId),
|
||||||
state,
|
state,
|
||||||
apolloClient
|
apolloClient,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
case "removeItem":
|
case "removeItem":
|
||||||
|
@ -350,7 +350,7 @@ const outfitStateReducer = (apolloClient) => (baseState, action) => {
|
||||||
// Don't include the removed item in items to reconsider!
|
// Don't include the removed item in items to reconsider!
|
||||||
itemIdsToReconsider.filter((x) => x !== itemId),
|
itemIdsToReconsider.filter((x) => x !== itemId),
|
||||||
state,
|
state,
|
||||||
apolloClient
|
apolloClient,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
case "setPose":
|
case "setPose":
|
||||||
|
@ -386,7 +386,7 @@ function useParseOutfitUrl() {
|
||||||
// stable object!
|
// stable object!
|
||||||
const memoizedOutfitState = React.useMemo(
|
const memoizedOutfitState = React.useMemo(
|
||||||
() => readOutfitStateFromSearchParams(searchParams),
|
() => readOutfitStateFromSearchParams(searchParams),
|
||||||
[searchParams]
|
[searchParams],
|
||||||
);
|
);
|
||||||
|
|
||||||
return memoizedOutfitState;
|
return memoizedOutfitState;
|
||||||
|
@ -433,7 +433,7 @@ function getOutfitStateFromOutfitData(outfit) {
|
||||||
// Whereas the items are more convenient to just leave as empty lists!
|
// Whereas the items are more convenient to just leave as empty lists!
|
||||||
wornItemIds: new Set((outfit.wornItems || []).map((item) => item.id)),
|
wornItemIds: new Set((outfit.wornItems || []).map((item) => item.id)),
|
||||||
closetedItemIds: new Set(
|
closetedItemIds: new Set(
|
||||||
(outfit.closetedItems || []).map((item) => item.id)
|
(outfit.closetedItems || []).map((item) => item.id),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -475,7 +475,7 @@ function findItemConflicts(itemIdToAdd, state, apolloClient) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const wornItems = Array.from(wornItemIds).map((id) =>
|
const wornItems = Array.from(wornItemIds).map((id) =>
|
||||||
items.find((i) => i.id === id)
|
items.find((i) => i.id === id),
|
||||||
);
|
);
|
||||||
|
|
||||||
const itemToAddZoneSets = getItemZones(itemToAdd);
|
const itemToAddZoneSets = getItemZones(itemToAdd);
|
||||||
|
@ -491,11 +491,11 @@ function findItemConflicts(itemIdToAdd, state, apolloClient) {
|
||||||
const itemsConflict =
|
const itemsConflict =
|
||||||
setsIntersect(
|
setsIntersect(
|
||||||
itemToAddZoneSets.occupies,
|
itemToAddZoneSets.occupies,
|
||||||
wornItemZoneSets.occupiesOrRestricts
|
wornItemZoneSets.occupiesOrRestricts,
|
||||||
) ||
|
) ||
|
||||||
setsIntersect(
|
setsIntersect(
|
||||||
wornItemZoneSets.occupies,
|
wornItemZoneSets.occupies,
|
||||||
itemToAddZoneSets.occupiesOrRestricts
|
itemToAddZoneSets.occupiesOrRestricts,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (itemsConflict) {
|
if (itemsConflict) {
|
||||||
|
@ -536,7 +536,7 @@ function reconsiderItems(itemIdsToReconsider, state, apolloClient) {
|
||||||
const conflictingIds = findItemConflicts(
|
const conflictingIds = findItemConflicts(
|
||||||
itemIdToReconsider,
|
itemIdToReconsider,
|
||||||
state,
|
state,
|
||||||
apolloClient
|
apolloClient,
|
||||||
);
|
);
|
||||||
if (conflictingIds.length === 0) {
|
if (conflictingIds.length === 0) {
|
||||||
state.wornItemIds.add(itemIdToReconsider);
|
state.wornItemIds.add(itemIdToReconsider);
|
||||||
|
@ -576,19 +576,19 @@ function getZonesAndItems(itemsById, wornItemIds, closetedItemIds) {
|
||||||
([zoneLabel, items]) => ({
|
([zoneLabel, items]) => ({
|
||||||
zoneLabel: zoneLabel,
|
zoneLabel: zoneLabel,
|
||||||
items: [...items].sort((a, b) => a.name.localeCompare(b.name)),
|
items: [...items].sort((a, b) => a.name.localeCompare(b.name)),
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
zonesAndItems.sort((a, b) => a.zoneLabel.localeCompare(b.zoneLabel));
|
zonesAndItems.sort((a, b) => a.zoneLabel.localeCompare(b.zoneLabel));
|
||||||
|
|
||||||
// As one last step, try to remove zone groups that aren't helpful.
|
// As one last step, try to remove zone groups that aren't helpful.
|
||||||
const groupsWithConflicts = zonesAndItems.filter(
|
const groupsWithConflicts = zonesAndItems.filter(
|
||||||
({ items }) => items.length > 1
|
({ items }) => items.length > 1,
|
||||||
);
|
);
|
||||||
const itemIdsWithConflicts = new Set(
|
const itemIdsWithConflicts = new Set(
|
||||||
groupsWithConflicts
|
groupsWithConflicts
|
||||||
.map(({ items }) => items)
|
.map(({ items }) => items)
|
||||||
.flat()
|
.flat()
|
||||||
.map((item) => item.id)
|
.map((item) => item.id),
|
||||||
);
|
);
|
||||||
const itemIdsWeHaveSeen = new Set();
|
const itemIdsWeHaveSeen = new Set();
|
||||||
zonesAndItems = zonesAndItems.filter(({ items }) => {
|
zonesAndItems = zonesAndItems.filter(({ items }) => {
|
||||||
|
|
|
@ -12,7 +12,7 @@ export function useSearchResults(
|
||||||
query,
|
query,
|
||||||
outfitState,
|
outfitState,
|
||||||
currentPageNumber,
|
currentPageNumber,
|
||||||
{ skip = false } = {}
|
{ skip = false } = {},
|
||||||
) {
|
) {
|
||||||
const { speciesId, colorId } = outfitState;
|
const { speciesId, colorId } = outfitState;
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ export function useSearchResults(
|
||||||
},
|
},
|
||||||
// Return `numTotalItems` from the GQL cache while waiting for next page!
|
// Return `numTotalItems` from the GQL cache while waiting for next page!
|
||||||
returnPartialData: true,
|
returnPartialData: true,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const loading = debouncedQuery !== query || loadingGQL;
|
const loading = debouncedQuery !== query || loadingGQL;
|
||||||
|
|
|
@ -22,7 +22,7 @@ const typePolicies = {
|
||||||
},
|
},
|
||||||
items: (_, { args, toReference }) => {
|
items: (_, { args, toReference }) => {
|
||||||
return args.ids.map((id) =>
|
return args.ids.map((id) =>
|
||||||
toReference({ __typename: "Item", id }, true)
|
toReference({ __typename: "Item", id }, true),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
item: (_, { args, toReference }) => {
|
item: (_, { args, toReference }) => {
|
||||||
|
@ -63,15 +63,15 @@ const typePolicies = {
|
||||||
"[appearanceOn] seeking cached appearance",
|
"[appearanceOn] seeking cached appearance",
|
||||||
speciesId,
|
speciesId,
|
||||||
colorId,
|
colorId,
|
||||||
readField("id")
|
readField("id"),
|
||||||
);
|
);
|
||||||
const speciesStandardBodyId = readField(
|
const speciesStandardBodyId = readField(
|
||||||
"standardBodyId",
|
"standardBodyId",
|
||||||
toReference({ __typename: "Species", id: speciesId })
|
toReference({ __typename: "Species", id: speciesId }),
|
||||||
);
|
);
|
||||||
const colorIsStandard = readField(
|
const colorIsStandard = readField(
|
||||||
"isStandard",
|
"isStandard",
|
||||||
toReference({ __typename: "Color", id: colorId })
|
toReference({ __typename: "Color", id: colorId }),
|
||||||
);
|
);
|
||||||
if (speciesStandardBodyId == null || colorIsStandard == null) {
|
if (speciesStandardBodyId == null || colorIsStandard == null) {
|
||||||
// We haven't loaded all the species/colors into cache yet. We might
|
// We haven't loaded all the species/colors into cache yet. We might
|
||||||
|
@ -86,7 +86,7 @@ const typePolicies = {
|
||||||
const itemId = readField("id");
|
const itemId = readField("id");
|
||||||
console.debug(
|
console.debug(
|
||||||
"[appearanceOn] standard color, will read:",
|
"[appearanceOn] standard color, will read:",
|
||||||
`item-${itemId}-body-${speciesStandardBodyId}`
|
`item-${itemId}-body-${speciesStandardBodyId}`,
|
||||||
);
|
);
|
||||||
return toReference({
|
return toReference({
|
||||||
__typename: "ItemAppearance",
|
__typename: "ItemAppearance",
|
||||||
|
@ -121,7 +121,7 @@ const typePolicies = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const theyOwnThisItem = itemsTheyOwn.some(
|
const theyOwnThisItem = itemsTheyOwn.some(
|
||||||
(itemRef) => readField("id", itemRef) === thisItemId
|
(itemRef) => readField("id", itemRef) === thisItemId,
|
||||||
);
|
);
|
||||||
return theyOwnThisItem;
|
return theyOwnThisItem;
|
||||||
},
|
},
|
||||||
|
@ -144,7 +144,7 @@ const typePolicies = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const theyWantThisItem = itemsTheyWant.some(
|
const theyWantThisItem = itemsTheyWant.some(
|
||||||
(itemRef) => readField("id", itemRef) === thisItemId
|
(itemRef) => readField("id", itemRef) === thisItemId,
|
||||||
);
|
);
|
||||||
return theyWantThisItem;
|
return theyWantThisItem;
|
||||||
},
|
},
|
||||||
|
@ -218,7 +218,7 @@ const buildLink = (getAuth0) =>
|
||||||
.concat(
|
.concat(
|
||||||
createPersistedQueryLink({
|
createPersistedQueryLink({
|
||||||
useGETForHashedQueries: true,
|
useGETForHashedQueries: true,
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
.concat(httpLink);
|
.concat(httpLink);
|
||||||
|
|
||||||
|
|
|
@ -140,7 +140,7 @@ export function layerUsesHTML5(layer) {
|
||||||
layer.canvasMovieLibraryUrl ||
|
layer.canvasMovieLibraryUrl ||
|
||||||
// If this glitch is applied, then `svgUrl` will be null, but there's still
|
// If this glitch is applied, then `svgUrl` will be null, but there's still
|
||||||
// an HTML5 manifest that the official player can render.
|
// an HTML5 manifest that the official player can render.
|
||||||
(layer.knownGlitches || []).includes("OFFICIAL_SVG_IS_INCORRECT")
|
(layer.knownGlitches || []).includes("OFFICIAL_SVG_IS_INCORRECT"),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -109,12 +109,12 @@ export function ItemThumbnail({
|
||||||
|
|
||||||
const borderColor = useColorModeValue(
|
const borderColor = useColorModeValue(
|
||||||
theme.colors.green["700"],
|
theme.colors.green["700"],
|
||||||
"transparent"
|
"transparent",
|
||||||
);
|
);
|
||||||
|
|
||||||
const focusBorderColor = useColorModeValue(
|
const focusBorderColor = useColorModeValue(
|
||||||
theme.colors.green["600"],
|
theme.colors.green["600"],
|
||||||
"transparent"
|
"transparent",
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -233,7 +233,7 @@ export function ItemBadgeList({ children, ...props }) {
|
||||||
<Wrap spacing="2" opacity="0.7" {...props}>
|
<Wrap spacing="2" opacity="0.7" {...props}>
|
||||||
{React.Children.map(
|
{React.Children.map(
|
||||||
children,
|
children,
|
||||||
(badge) => badge && <WrapItem>{badge}</WrapItem>
|
(badge) => badge && <WrapItem>{badge}</WrapItem>,
|
||||||
)}
|
)}
|
||||||
</Wrap>
|
</Wrap>
|
||||||
);
|
);
|
||||||
|
@ -316,7 +316,7 @@ export const ItemKindBadge = React.forwardRef(
|
||||||
} else {
|
} else {
|
||||||
return <NpBadge ref={ref} isEditButton={isEditButton} {...props} />;
|
return <NpBadge ref={ref} isEditButton={isEditButton} {...props} />;
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
export function YouOwnThisBadge({ variant = "long" }) {
|
export function YouOwnThisBadge({ variant = "long" }) {
|
||||||
|
|
|
@ -209,7 +209,7 @@ function OutfitMovieLayer({
|
||||||
const roundedFps = Math.round(fps * 100) / 100;
|
const roundedFps = Math.round(fps * 100) / 100;
|
||||||
|
|
||||||
console.debug(
|
console.debug(
|
||||||
`[OutfitMovieLayer] FPS: ${roundedFps} (Target: ${targetFps}) (${libraryUrl})`
|
`[OutfitMovieLayer] FPS: ${roundedFps} (Target: ${targetFps}) (${libraryUrl})`,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (onLowFps && fps < 2) {
|
if (onLowFps && fps < 2) {
|
||||||
|
@ -328,7 +328,7 @@ export function loadMovieLibrary(librarySrc, { preferArchive = false } = {}) {
|
||||||
|
|
||||||
// Then, load the script tag. (Make sure we set it up to be cancelable!)
|
// Then, load the script tag. (Make sure we set it up to be cancelable!)
|
||||||
const scriptPromise = loadScriptTag(
|
const scriptPromise = loadScriptTag(
|
||||||
safeImageUrl(librarySrc, { preferArchive })
|
safeImageUrl(librarySrc, { preferArchive }),
|
||||||
);
|
);
|
||||||
cancelableResourcePromises.push(scriptPromise);
|
cancelableResourcePromises.push(scriptPromise);
|
||||||
await scriptPromise;
|
await scriptPromise;
|
||||||
|
@ -350,16 +350,16 @@ export function loadMovieLibrary(librarySrc, { preferArchive = false } = {}) {
|
||||||
// the race anymore? But fingers crossed!
|
// the race anymore? But fingers crossed!
|
||||||
if (Object.keys(window.AdobeAn?.compositions || {}).length === 0) {
|
if (Object.keys(window.AdobeAn?.compositions || {}).length === 0) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Movie library ${librarySrc} did not add a composition to window.AdobeAn.compositions.`
|
`Movie library ${librarySrc} did not add a composition to window.AdobeAn.compositions.`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const [compositionId, composition] = Object.entries(
|
const [compositionId, composition] = Object.entries(
|
||||||
window.AdobeAn.compositions
|
window.AdobeAn.compositions,
|
||||||
)[0];
|
)[0];
|
||||||
if (Object.keys(window.AdobeAn.compositions).length > 1) {
|
if (Object.keys(window.AdobeAn.compositions).length > 1) {
|
||||||
console.warn(
|
console.warn(
|
||||||
`Grabbing composition ${compositionId}, but there are >1 here: `,
|
`Grabbing composition ${compositionId}, but there are >1 here: `,
|
||||||
Object.keys(window.AdobeAn.compositions).length
|
Object.keys(window.AdobeAn.compositions).length,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
delete window.AdobeAn.compositions[compositionId];
|
delete window.AdobeAn.compositions[compositionId];
|
||||||
|
@ -380,7 +380,7 @@ export function loadMovieLibrary(librarySrc, { preferArchive = false } = {}) {
|
||||||
crossOrigin: "anonymous",
|
crossOrigin: "anonymous",
|
||||||
preferArchive,
|
preferArchive,
|
||||||
}),
|
}),
|
||||||
])
|
]),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Wait for the images, and make sure they're cancelable while we do.
|
// Wait for the images, and make sure they're cancelable while we do.
|
||||||
|
@ -440,8 +440,8 @@ export function buildMovieClip(library, libraryUrl) {
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Movie libraryUrl ${JSON.stringify(
|
`Movie libraryUrl ${JSON.stringify(
|
||||||
libraryUrl
|
libraryUrl,
|
||||||
)} did not match expected format: ${e.message}`
|
)} did not match expected format: ${e.message}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -449,7 +449,7 @@ export function buildMovieClip(library, libraryUrl) {
|
||||||
if (!LibraryMovieClipConstructor) {
|
if (!LibraryMovieClipConstructor) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Expected JS movie library ${libraryUrl} to contain a constructor ` +
|
`Expected JS movie library ${libraryUrl} to contain a constructor ` +
|
||||||
`named ${constructorName}, but it did not: ${Object.keys(library)}`
|
`named ${constructorName}, but it did not: ${Object.keys(library)}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const movieClip = new LibraryMovieClipConstructor();
|
const movieClip = new LibraryMovieClipConstructor();
|
||||||
|
|
|
@ -111,7 +111,7 @@ export function useOutfitPreview({
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[setIsPaused, toast]
|
[setIsPaused, toast],
|
||||||
);
|
);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
|
@ -184,7 +184,7 @@ export function OutfitLayers({
|
||||||
setLoadingDelayHasPassed(false);
|
setLoadingDelayHasPassed(false);
|
||||||
const t = setTimeout(
|
const t = setTimeout(
|
||||||
() => setLoadingDelayHasPassed(true),
|
() => setLoadingDelayHasPassed(true),
|
||||||
loadingDelayMs
|
loadingDelayMs,
|
||||||
);
|
);
|
||||||
return () => clearTimeout(t);
|
return () => clearTimeout(t);
|
||||||
}
|
}
|
||||||
|
@ -203,8 +203,8 @@ export function OutfitLayers({
|
||||||
Math.min(
|
Math.min(
|
||||||
containerRef.current.offsetWidth,
|
containerRef.current.offsetWidth,
|
||||||
containerRef.current.offsetHeight,
|
containerRef.current.offsetHeight,
|
||||||
600
|
600,
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,7 +283,7 @@ export function OutfitLayers({
|
||||||
as="img"
|
as="img"
|
||||||
src={safeImageUrl(
|
src={safeImageUrl(
|
||||||
getBestImageUrlForLayer(layer, { hiResMode }),
|
getBestImageUrlForLayer(layer, { hiResMode }),
|
||||||
{ preferArchive }
|
{ preferArchive },
|
||||||
)}
|
)}
|
||||||
alt=""
|
alt=""
|
||||||
objectFit="contain"
|
objectFit="contain"
|
||||||
|
@ -397,7 +397,7 @@ export function usePreloadLayers(layers) {
|
||||||
for (const layer of layers) {
|
for (const layer of layers) {
|
||||||
const imageAssetPromise = loadImage(
|
const imageAssetPromise = loadImage(
|
||||||
getBestImageUrlForLayer(layer, { hiResMode }),
|
getBestImageUrlForLayer(layer, { hiResMode }),
|
||||||
{ preferArchive }
|
{ preferArchive },
|
||||||
);
|
);
|
||||||
imageAssetPromises.push(imageAssetPromise);
|
imageAssetPromises.push(imageAssetPromise);
|
||||||
|
|
||||||
|
@ -407,7 +407,7 @@ export function usePreloadLayers(layers) {
|
||||||
// placeholder, which should usually be noticeably faster!
|
// placeholder, which should usually be noticeably faster!
|
||||||
const movieLibraryPromise = loadMovieLibrary(
|
const movieLibraryPromise = loadMovieLibrary(
|
||||||
layer.canvasMovieLibraryUrl,
|
layer.canvasMovieLibraryUrl,
|
||||||
{ preferArchive }
|
{ preferArchive },
|
||||||
);
|
);
|
||||||
const movieAssetPromise = movieLibraryPromise.then((library) => ({
|
const movieAssetPromise = movieLibraryPromise.then((library) => ({
|
||||||
library,
|
library,
|
||||||
|
@ -420,7 +420,7 @@ export function usePreloadLayers(layers) {
|
||||||
// The minimal asset for the movie case is *either* the image *or*
|
// The minimal asset for the movie case is *either* the image *or*
|
||||||
// the movie, because we can start rendering when either is ready.
|
// the movie, because we can start rendering when either is ready.
|
||||||
minimalAssetPromises.push(
|
minimalAssetPromises.push(
|
||||||
Promise.any([imageAssetPromise, movieAssetPromise])
|
Promise.any([imageAssetPromise, movieAssetPromise]),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
minimalAssetPromises.push(imageAssetPromise);
|
minimalAssetPromises.push(imageAssetPromise);
|
||||||
|
@ -458,13 +458,13 @@ export function usePreloadLayers(layers) {
|
||||||
}
|
}
|
||||||
|
|
||||||
setLayersHaveAnimations(
|
setLayersHaveAnimations(
|
||||||
(alreadyHasAnimations) => alreadyHasAnimations || assetHasAnimations
|
(alreadyHasAnimations) => alreadyHasAnimations || assetHasAnimations,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
movieAssetPromises.forEach((p) =>
|
movieAssetPromises.forEach((p) =>
|
||||||
p.then(checkHasAnimations).catch((e) => {
|
p.then(checkHasAnimations).catch((e) => {
|
||||||
console.error(`Error preloading movie library ${p.libraryUrl}:`, e);
|
console.error(`Error preloading movie library ${p.libraryUrl}:`, e);
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
|
|
@ -89,14 +89,14 @@ export function useRouterPagination(totalCount, numPerPage) {
|
||||||
return newParams;
|
return newParams;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[query, numPerPage]
|
[query, numPerPage],
|
||||||
);
|
);
|
||||||
|
|
||||||
const goToPageNumber = React.useCallback(
|
const goToPageNumber = React.useCallback(
|
||||||
(newPageNumber) => {
|
(newPageNumber) => {
|
||||||
pushHistory(buildPageUrl(newPageNumber));
|
pushHistory(buildPageUrl(newPageNumber));
|
||||||
},
|
},
|
||||||
[buildPageUrl, pushHistory]
|
[buildPageUrl, pushHistory],
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -125,7 +125,7 @@ function PageNumberSelect({
|
||||||
|
|
||||||
const handleChange = React.useCallback(
|
const handleChange = React.useCallback(
|
||||||
(e) => onChange(Number(e.target.value)),
|
(e) => onChange(Number(e.target.value)),
|
||||||
[onChange]
|
[onChange],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -110,8 +110,8 @@ function SpeciesColorPicker({
|
||||||
new Error(
|
new Error(
|
||||||
`Assertion error in SpeciesColorPicker: Entered an invalid state, ` +
|
`Assertion error in SpeciesColorPicker: Entered an invalid state, ` +
|
||||||
`with prop stateMustAlwaysBeValid: speciesId=${speciesId}, ` +
|
`with prop stateMustAlwaysBeValid: speciesId=${speciesId}, ` +
|
||||||
`colorId=${newColorId}.`
|
`colorId=${newColorId}.`,
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -146,8 +146,8 @@ function SpeciesColorPicker({
|
||||||
new Error(
|
new Error(
|
||||||
`Assertion error in SpeciesColorPicker: species not found. ` +
|
`Assertion error in SpeciesColorPicker: species not found. ` +
|
||||||
`speciesId=${speciesId}, newSpeciesId=${newSpeciesId}, ` +
|
`speciesId=${speciesId}, newSpeciesId=${newSpeciesId}, ` +
|
||||||
`colorId=${colorId}.`
|
`colorId=${colorId}.`,
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -187,7 +187,8 @@ function SpeciesColorPicker({
|
||||||
let visibleColors = allColors;
|
let visibleColors = allColors;
|
||||||
if (stateMustAlwaysBeValid && valids && speciesId) {
|
if (stateMustAlwaysBeValid && valids && speciesId) {
|
||||||
visibleColors = visibleColors.filter(
|
visibleColors = visibleColors.filter(
|
||||||
(c) => getValidPoses(valids, speciesId, c.id).size > 0 || c.id === colorId
|
(c) =>
|
||||||
|
getValidPoses(valids, speciesId, c.id).size > 0 || c.id === colorId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,7 +351,7 @@ export function useAllValidPetPoses() {
|
||||||
responseType: "arrayBuffer",
|
responseType: "arrayBuffer",
|
||||||
// If we already have globally-cached valids, skip the request.
|
// If we already have globally-cached valids, skip the request.
|
||||||
skip: cachedResponseForAllValidPetPoses != null,
|
skip: cachedResponseForAllValidPetPoses != null,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// Use the globally-cached response if we have one, or await the network
|
// Use the globally-cached response if we have one, or await the network
|
||||||
|
@ -360,7 +361,7 @@ export function useAllValidPetPoses() {
|
||||||
|
|
||||||
const valids = React.useMemo(
|
const valids = React.useMemo(
|
||||||
() => validsBuffer && new DataView(validsBuffer),
|
() => validsBuffer && new DataView(validsBuffer),
|
||||||
[validsBuffer]
|
[validsBuffer],
|
||||||
);
|
);
|
||||||
|
|
||||||
// Once a network response comes in, save it as the globally-cached response.
|
// Once a network response comes in, save it as the globally-cached response.
|
||||||
|
@ -388,8 +389,8 @@ function getPairByte(valids, speciesId, colorId) {
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logAndCapture(
|
logAndCapture(
|
||||||
new Error(
|
new Error(
|
||||||
`Error loading valid poses for species=${speciesId}, color=${colorId}: ${e.message}`
|
`Error loading valid poses for species=${speciesId}, color=${colorId}: ${e.message}`,
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -185,7 +185,7 @@ function ItemThumbnail({ item, tradeMatchingMode }) {
|
||||||
|
|
||||||
const thumbnailShadowColor = useColorModeValue(
|
const thumbnailShadowColor = useColorModeValue(
|
||||||
`${kindColorScheme}.200`,
|
`${kindColorScheme}.200`,
|
||||||
`${kindColorScheme}.600`
|
`${kindColorScheme}.600`,
|
||||||
);
|
);
|
||||||
const thumbnailShadowColorValue = useToken("colors", thumbnailShadowColor);
|
const thumbnailShadowColorValue = useToken("colors", thumbnailShadowColor);
|
||||||
const mdRadiusValue = useToken("radii", "md");
|
const mdRadiusValue = useToken("radii", "md");
|
||||||
|
@ -318,11 +318,11 @@ function ItemThumbnail({ item, tradeMatchingMode }) {
|
||||||
function ItemOwnsWantsBadge({ colorScheme, children, label }) {
|
function ItemOwnsWantsBadge({ colorScheme, children, label }) {
|
||||||
const badgeBackground = useColorModeValue(
|
const badgeBackground = useColorModeValue(
|
||||||
`${colorScheme}.100`,
|
`${colorScheme}.100`,
|
||||||
`${colorScheme}.500`
|
`${colorScheme}.500`,
|
||||||
);
|
);
|
||||||
const badgeColor = useColorModeValue(
|
const badgeColor = useColorModeValue(
|
||||||
`${colorScheme}.500`,
|
`${colorScheme}.500`,
|
||||||
`${colorScheme}.100`
|
`${colorScheme}.100`,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [badgeBackgroundValue, badgeColorValue] = useToken("colors", [
|
const [badgeBackgroundValue, badgeColorValue] = useToken("colors", [
|
||||||
|
@ -369,11 +369,11 @@ function ItemOwnsWantsBadge({ colorScheme, children, label }) {
|
||||||
function ItemThumbnailKindBadge({ colorScheme, children }) {
|
function ItemThumbnailKindBadge({ colorScheme, children }) {
|
||||||
const badgeBackground = useColorModeValue(
|
const badgeBackground = useColorModeValue(
|
||||||
`${colorScheme}.100`,
|
`${colorScheme}.100`,
|
||||||
`${colorScheme}.500`
|
`${colorScheme}.500`,
|
||||||
);
|
);
|
||||||
const badgeColor = useColorModeValue(
|
const badgeColor = useColorModeValue(
|
||||||
`${colorScheme}.500`,
|
`${colorScheme}.500`,
|
||||||
`${colorScheme}.100`
|
`${colorScheme}.100`,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [badgeBackgroundValue, badgeColorValue] = useToken("colors", [
|
const [badgeBackgroundValue, badgeColorValue] = useToken("colors", [
|
||||||
|
|
|
@ -20,10 +20,10 @@ function getVisibleLayers(petAppearance, itemAppearances) {
|
||||||
validItemAppearances
|
validItemAppearances
|
||||||
.map((a) => a.restrictedZones)
|
.map((a) => a.restrictedZones)
|
||||||
.flat()
|
.flat()
|
||||||
.map((z) => z.id)
|
.map((z) => z.id),
|
||||||
);
|
);
|
||||||
const petRestrictedZoneIds = new Set(
|
const petRestrictedZoneIds = new Set(
|
||||||
petAppearance.restrictedZones.map((z) => z.id)
|
petAppearance.restrictedZones.map((z) => z.id),
|
||||||
);
|
);
|
||||||
|
|
||||||
const visibleLayers = allLayers.filter((layer) => {
|
const visibleLayers = allLayers.filter((layer) => {
|
||||||
|
|
|
@ -96,7 +96,7 @@ function useCurrentUserViaDb({ isEnabled }) {
|
||||||
// something is wrong and they need to reach out.
|
// something is wrong and they need to reach out.
|
||||||
console.error("[useCurrentUser] Couldn't get current user:", error);
|
console.error("[useCurrentUser] Couldn't get current user:", error);
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!isEnabled) {
|
if (!isEnabled) {
|
||||||
|
@ -159,7 +159,7 @@ export function useLogout() {
|
||||||
}
|
}
|
||||||
cache.gc();
|
cache.gc();
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const logoutWithDb = () => {
|
const logoutWithDb = () => {
|
||||||
|
@ -191,13 +191,13 @@ export function useAuthModeFeatureFlag() {
|
||||||
// setting this override value to auth0 on everyone's devices 😅)
|
// setting this override value to auth0 on everyone's devices 😅)
|
||||||
let [savedValue, setSavedValue] = useLocalStorage(
|
let [savedValue, setSavedValue] = useLocalStorage(
|
||||||
"DTIAuthModeFeatureFlag",
|
"DTIAuthModeFeatureFlag",
|
||||||
null
|
null,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!["auth0", "db", null].includes(savedValue)) {
|
if (!["auth0", "db", null].includes(savedValue)) {
|
||||||
console.warn(
|
console.warn(
|
||||||
`Unexpected DTIAuthModeFeatureFlag value: %o. Ignoring.`,
|
`Unexpected DTIAuthModeFeatureFlag value: %o. Ignoring.`,
|
||||||
savedValue
|
savedValue,
|
||||||
);
|
);
|
||||||
savedValue = null;
|
savedValue = null;
|
||||||
}
|
}
|
||||||
|
@ -226,7 +226,7 @@ export function getAuthModeFeatureFlag() {
|
||||||
if (!["auth0", "db", null].includes(savedValue)) {
|
if (!["auth0", "db", null].includes(savedValue)) {
|
||||||
console.warn(
|
console.warn(
|
||||||
`Unexpected DTIAuthModeFeatureFlag value: %o. Ignoring.`,
|
`Unexpected DTIAuthModeFeatureFlag value: %o. Ignoring.`,
|
||||||
savedValue
|
savedValue,
|
||||||
);
|
);
|
||||||
savedValue = null;
|
savedValue = null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@ export default function useOutfitAppearance(outfitState) {
|
||||||
speciesId == null ||
|
speciesId == null ||
|
||||||
colorId == null ||
|
colorId == null ||
|
||||||
(pose == null && appearanceId == null),
|
(pose == null && appearanceId == null),
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
@ -99,18 +99,18 @@ export default function useOutfitAppearance(outfitState) {
|
||||||
wornItemIds,
|
wornItemIds,
|
||||||
},
|
},
|
||||||
skip: speciesId == null || colorId == null || wornItemIds.length === 0,
|
skip: speciesId == null || colorId == null || wornItemIds.length === 0,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const petAppearance = data1?.petAppearance;
|
const petAppearance = data1?.petAppearance;
|
||||||
const items = data2?.items;
|
const items = data2?.items;
|
||||||
const itemAppearances = React.useMemo(
|
const itemAppearances = React.useMemo(
|
||||||
() => (items || []).map((i) => i.appearance),
|
() => (items || []).map((i) => i.appearance),
|
||||||
[items]
|
[items],
|
||||||
);
|
);
|
||||||
const visibleLayers = React.useMemo(
|
const visibleLayers = React.useMemo(
|
||||||
() => getVisibleLayers(petAppearance, itemAppearances),
|
() => getVisibleLayers(petAppearance, itemAppearances),
|
||||||
[petAppearance, itemAppearances]
|
[petAppearance, itemAppearances],
|
||||||
);
|
);
|
||||||
|
|
||||||
const bodyId = petAppearance?.bodyId;
|
const bodyId = petAppearance?.bodyId;
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { useLocalStorage } from "../util";
|
||||||
function usePreferArchive() {
|
function usePreferArchive() {
|
||||||
const [preferArchiveSavedValue, setPreferArchive] = useLocalStorage(
|
const [preferArchiveSavedValue, setPreferArchive] = useLocalStorage(
|
||||||
"DTIPreferArchive",
|
"DTIPreferArchive",
|
||||||
null
|
null,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Oct 13 2022: I might default this back to on again if the lag gets
|
// Oct 13 2022: I might default this back to on again if the lag gets
|
||||||
|
|
|
@ -117,7 +117,7 @@ export function useCommonStyles() {
|
||||||
*/
|
*/
|
||||||
export function safeImageUrl(
|
export function safeImageUrl(
|
||||||
urlString,
|
urlString,
|
||||||
{ crossOrigin = null, preferArchive = false } = {}
|
{ crossOrigin = null, preferArchive = false } = {},
|
||||||
) {
|
) {
|
||||||
if (urlString == null) {
|
if (urlString == null) {
|
||||||
return urlString;
|
return urlString;
|
||||||
|
@ -133,13 +133,13 @@ export function safeImageUrl(
|
||||||
// So, we provide "http://images.neopets.com" as the base URL when
|
// So, we provide "http://images.neopets.com" as the base URL when
|
||||||
// parsing. Most URLs are absolute and will ignore it, but relative URLs
|
// parsing. Most URLs are absolute and will ignore it, but relative URLs
|
||||||
// will resolve relative to that base.
|
// will resolve relative to that base.
|
||||||
"http://images.neopets.com"
|
"http://images.neopets.com",
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logAndCapture(
|
logAndCapture(
|
||||||
new Error(
|
new Error(
|
||||||
`safeImageUrl could not parse URL: ${urlString}. Returning a placeholder.`
|
`safeImageUrl could not parse URL: ${urlString}. Returning a placeholder.`,
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
return "https://impress-2020.openneo.net/__error__URL-was-not-parseable__";
|
return "https://impress-2020.openneo.net/__error__URL-was-not-parseable__";
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,7 @@ export function safeImageUrl(
|
||||||
if (preferArchive) {
|
if (preferArchive) {
|
||||||
const archiveUrl = new URL(
|
const archiveUrl = new URL(
|
||||||
`/api/readFromArchive`,
|
`/api/readFromArchive`,
|
||||||
window.location.origin
|
window.location.origin,
|
||||||
);
|
);
|
||||||
archiveUrl.search = new URLSearchParams({ url: url.toString() });
|
archiveUrl.search = new URLSearchParams({ url: url.toString() });
|
||||||
url = archiveUrl;
|
url = archiveUrl;
|
||||||
|
@ -175,8 +175,8 @@ export function safeImageUrl(
|
||||||
logAndCapture(
|
logAndCapture(
|
||||||
new Error(
|
new Error(
|
||||||
`safeImageUrl was provided an unsafe URL, but we don't know how to ` +
|
`safeImageUrl was provided an unsafe URL, but we don't know how to ` +
|
||||||
`upgrade it to HTTPS: ${urlString}. Returning a placeholder.`
|
`upgrade it to HTTPS: ${urlString}. Returning a placeholder.`,
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
return "https://impress-2020.openneo.net/__error__URL-was-not-HTTPS__";
|
return "https://impress-2020.openneo.net/__error__URL-was-not-HTTPS__";
|
||||||
}
|
}
|
||||||
|
@ -197,11 +197,11 @@ export function safeImageUrl(
|
||||||
export function useDebounce(
|
export function useDebounce(
|
||||||
value,
|
value,
|
||||||
delay,
|
delay,
|
||||||
{ waitForFirstPause = false, initialValue = null, forceReset = null } = {}
|
{ waitForFirstPause = false, initialValue = null, forceReset = null } = {},
|
||||||
) {
|
) {
|
||||||
// State and setters for debounced value
|
// State and setters for debounced value
|
||||||
const [debouncedValue, setDebouncedValue] = React.useState(
|
const [debouncedValue, setDebouncedValue] = React.useState(
|
||||||
waitForFirstPause ? initialValue : value
|
waitForFirstPause ? initialValue : value,
|
||||||
);
|
);
|
||||||
|
|
||||||
React.useEffect(
|
React.useEffect(
|
||||||
|
@ -218,7 +218,7 @@ export function useDebounce(
|
||||||
clearTimeout(handler);
|
clearTimeout(handler);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
[value, delay] // Only re-call effect if value or delay changes
|
[value, delay], // Only re-call effect if value or delay changes
|
||||||
);
|
);
|
||||||
|
|
||||||
// The `forceReset` option helps us decide whether to set the value
|
// The `forceReset` option helps us decide whether to set the value
|
||||||
|
@ -322,7 +322,7 @@ export function useLocalStorage(key, initialValue) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[key]
|
[key],
|
||||||
);
|
);
|
||||||
|
|
||||||
const reloadValue = React.useCallback(() => {
|
const reloadValue = React.useCallback(() => {
|
||||||
|
@ -349,7 +349,7 @@ export function useLocalStorage(key, initialValue) {
|
||||||
|
|
||||||
export function loadImage(
|
export function loadImage(
|
||||||
rawSrc,
|
rawSrc,
|
||||||
{ crossOrigin = null, preferArchive = false } = {}
|
{ crossOrigin = null, preferArchive = false } = {},
|
||||||
) {
|
) {
|
||||||
const src = safeImageUrl(rawSrc, { crossOrigin, preferArchive });
|
const src = safeImageUrl(rawSrc, { crossOrigin, preferArchive });
|
||||||
const image = new Image();
|
const image = new Image();
|
||||||
|
@ -403,7 +403,7 @@ export function loadable(load, options) {
|
||||||
// Return a component that renders nothing, while we reload!
|
// Return a component that renders nothing, while we reload!
|
||||||
return () => null;
|
return () => null;
|
||||||
}),
|
}),
|
||||||
options
|
options,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue