diff --git a/src/app/ItemPage.js b/src/app/ItemPage.js index 5ede8a0..a80d4e4 100644 --- a/src/app/ItemPage.js +++ b/src/app/ItemPage.js @@ -38,6 +38,7 @@ import { Link, useParams } from "react-router-dom"; import ItemPageLayout, { SubtleSkeleton } from "./ItemPageLayout"; import { Delay, logAndCapture, usePageTitle } from "./util"; +import HTML5Badge from "./components/HTML5Badge"; import { itemAppearanceFragment, petAppearanceFragment, @@ -895,127 +896,6 @@ function ExpandOnGroupHover({ children, ...props }) { ); } -function HTML5Badge({ usesHTML5, isLoading }) { - const greenBackground = useColorModeValue("green.100", "green.900"); - const greenBorderColor = useColorModeValue("green.600", "green.500"); - const greenTextColor = useColorModeValue("green.700", "white"); - - const yellowBackground = useColorModeValue("yellow.100", "yellow.900"); - const yellowBorderColor = useColorModeValue("yellow.600", "yellow.500"); - const yellowTextColor = useColorModeValue("yellow.700", "white"); - - // `delayedUsesHTML5` stores the last known value of `usesHTML5`, when - // `isLoading` was `false`. This enables us to keep showing the badge, even - // when loading a new appearance - because it's unlikely the badge will - // change between different appearances for the same item, and the flicker is - // annoying! - const [delayedUsesHTML5, setDelayedUsesHTML5] = React.useState(null); - React.useEffect(() => { - if (!isLoading) { - setDelayedUsesHTML5(usesHTML5); - } - }, [usesHTML5, isLoading]); - - if (delayedUsesHTML5 === true) { - return ( - - - - {/* From Twemoji Keycap 5 */} - - - - ); - } else if (delayedUsesHTML5 === false) { - return ( - - This item isn't converted to HTML5 yet, so it might not appear in - Neopets.com customization yet. Once it's ready, it could look a bit - different than our temporary preview here. It might even be - animated! - - } - > - - - {/* From Twemoji Keycap 5 */} - - - {/* From Twemoji Not Allowed */} - - - - ); - } else { - // If no `usesHTML5` value has been provided yet, we're empty for now! - return null; - } -} - -function HTML5BadgeLayout({ children, tooltipLabel, ...props }) { - const [isHovered, setIsHovered] = React.useState(false); - const [isFocused, setIsFocused] = React.useState(false); - - return ( - - setIsHovered(true)} - onMouseLeave={() => setIsHovered(false)} - onFocus={() => setIsFocused(true)} - onBlur={() => setIsFocused(false)} - {...props} - > - {children} - - - ); -} - function PlayPauseButton({ isPaused, onClick }) { return ( setFocusIsLocked(true), [ @@ -84,6 +86,11 @@ function OutfitControls({ } }; + const itemLayers = appearance.itemAppearances.map((a) => a.layers).flat(); + const usesHTML5 = itemLayers.every( + (l) => l.svgUrl || l.canvasMovieLibraryUrl + ); + return ( {({ css, cx }) => ( @@ -173,7 +180,32 @@ function OutfitControls({ * We try to center the species/color picker, but the left spacer will * shrink more than the pose picker container if we run out of space! */} - + + + This outfit is converted to HTML5, and ready to use on + Neopets.com! + + ) : ( + <> + This outfit isn't converted to HTML5 yet, so it might + not appear in Neopets.com customization yet. Once it's + ready, it could look a bit different than our temporary + preview here. It might even be animated! + + ) + } + /> + { diff --git a/src/app/WardrobePage/WardrobePreviewAndControls.js b/src/app/WardrobePage/WardrobePreviewAndControls.js index c0f27da..a5804bc 100644 --- a/src/app/WardrobePage/WardrobePreviewAndControls.js +++ b/src/app/WardrobePage/WardrobePreviewAndControls.js @@ -7,7 +7,7 @@ import OutfitThumbnail, { outfitThumbnailFragment, getOutfitThumbnailRenderSize, } from "../components/OutfitThumbnail"; -import OutfitPreview from "../components/OutfitPreview"; +import OutfitPreview, { useOutfitPreview } from "../components/OutfitPreview"; import { loadable } from "../util"; const OutfitControls = loadable(() => import("./OutfitControls")); @@ -21,27 +21,28 @@ function WardrobePreviewAndControls({ // show the play/pause button. const [hasAnimations, setHasAnimations] = React.useState(false); + const { appearance, preview } = useOutfitPreview({ + isLoading: isLoading, + speciesId: outfitState.speciesId, + colorId: outfitState.colorId, + pose: outfitState.pose, + appearanceId: outfitState.appearanceId, + wornItemIds: outfitState.wornItemIds, + onChangeHasAnimations: setHasAnimations, + backdrop: , + }); + return ( <> - - } - /> - + {preview} diff --git a/src/app/components/HTML5Badge.js b/src/app/components/HTML5Badge.js new file mode 100644 index 0000000..2124a13 --- /dev/null +++ b/src/app/components/HTML5Badge.js @@ -0,0 +1,131 @@ +import React from "react"; +import { Tooltip, useColorModeValue, Flex, Icon } from "@chakra-ui/react"; +import { CheckCircleIcon, WarningTwoIcon } from "@chakra-ui/icons"; + +function HTML5Badge({ usesHTML5, isLoading, tooltipLabel }) { + const greenBackground = useColorModeValue("green.100", "green.900"); + const greenBorderColor = useColorModeValue("green.600", "green.500"); + const greenTextColor = useColorModeValue("green.700", "white"); + + const yellowBackground = useColorModeValue("yellow.100", "yellow.900"); + const yellowBorderColor = useColorModeValue("yellow.600", "yellow.500"); + const yellowTextColor = useColorModeValue("yellow.700", "white"); + + // `delayedUsesHTML5` stores the last known value of `usesHTML5`, when + // `isLoading` was `false`. This enables us to keep showing the badge, even + // when loading a new appearance - because it's unlikely the badge will + // change between different appearances for the same item, and the flicker is + // annoying! + const [delayedUsesHTML5, setDelayedUsesHTML5] = React.useState(null); + React.useEffect(() => { + if (!isLoading) { + setDelayedUsesHTML5(usesHTML5); + } + }, [usesHTML5, isLoading]); + + if (delayedUsesHTML5 === true) { + return ( + + + + {/* From Twemoji Keycap 5 */} + + + + ); + } else if (delayedUsesHTML5 === false) { + return ( + + This item isn't converted to HTML5 yet, so it might not appear in + Neopets.com customization yet. Once it's ready, it could look a + bit different than our temporary preview here. It might even be + animated! + + ) + } + > + + + {/* From Twemoji Keycap 5 */} + + + {/* From Twemoji Not Allowed */} + + + + ); + } else { + // If no `usesHTML5` value has been provided yet, we're empty for now! + return null; + } +} + +function HTML5BadgeLayout({ children, tooltipLabel, ...props }) { + const [isHovered, setIsHovered] = React.useState(false); + const [isFocused, setIsFocused] = React.useState(false); + + return ( + + setIsHovered(true)} + onMouseLeave={() => setIsHovered(false)} + onFocus={() => setIsFocused(true)} + onBlur={() => setIsFocused(false)} + {...props} + > + {children} + + + ); +} + +export default HTML5Badge;