From ddfdd5fc115ce62e0a44d26e9c886bdc9e668cf3 Mon Sep 17 00:00:00 2001 From: Matchu Date: Sun, 15 Oct 2023 14:20:55 -0700 Subject: [PATCH] Add outfit layers info modal to download PNGs etc This is an important workflow for people doing art stuff, I'm told! They used to use the Classic DTI broken image UI for this, but now that that's uhh Fully Gone, let's add this more explicitly! --- .../WardrobePage/LayersInfoModal.js | 92 +++++++++++++++++++ .../WardrobePage/OutfitControls.js | 18 +++- .../components/useOutfitAppearance.js | 1 + 3 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 app/javascript/wardrobe-2020/WardrobePage/LayersInfoModal.js diff --git a/app/javascript/wardrobe-2020/WardrobePage/LayersInfoModal.js b/app/javascript/wardrobe-2020/WardrobePage/LayersInfoModal.js new file mode 100644 index 00000000..297ddbd8 --- /dev/null +++ b/app/javascript/wardrobe-2020/WardrobePage/LayersInfoModal.js @@ -0,0 +1,92 @@ +import React from "react"; +import { + Box, + Button, + Modal, + ModalBody, + ModalCloseButton, + ModalContent, + ModalHeader, + ModalOverlay, + Table, + Tbody, + Td, + Th, + Thead, + Tr, +} from "@chakra-ui/react"; + +function LayersInfoModal({ isOpen, onClose, visibleLayers }) { + return ( + + + + Outfit layers + + + + + + + + ); +} + +function LayerTable({ layers }) { + return ( + + + + + + + + + + + {layers.map((layer) => ( + + ))} + +
PreviewDTI IDZoneLinks
+ ); +} + +function LayerTableRow({ layer, ...props }) { + return ( + + + + + {layer.id} + {layer.zone.label} + + + {layer.imageUrl && ( + + )} + {layer.swfUrl && ( + + )} + {layer.svgUrl && ( + + )} + + + + ); +} + +export default LayersInfoModal; diff --git a/app/javascript/wardrobe-2020/WardrobePage/OutfitControls.js b/app/javascript/wardrobe-2020/WardrobePage/OutfitControls.js index 836b20c0..a8dfc954 100644 --- a/app/javascript/wardrobe-2020/WardrobePage/OutfitControls.js +++ b/app/javascript/wardrobe-2020/WardrobePage/OutfitControls.js @@ -41,12 +41,14 @@ import { getBestImageUrlForLayer } from "../components/OutfitPreview"; import HTML5Badge, { layerUsesHTML5 } from "../components/HTML5Badge"; import PosePicker from "./PosePicker"; import SpeciesColorPicker from "../components/SpeciesColorPicker"; -import { loadImage, useLocalStorage } from "../util"; +import { loadImage, loadable, useLocalStorage } from "../util"; import useCurrentUser from "../components/useCurrentUser"; import useOutfitAppearance from "../components/useOutfitAppearance"; import OutfitKnownGlitchesBadge from "./OutfitKnownGlitchesBadge"; import usePreferArchive from "../components/usePreferArchive"; +const LoadableLayersInfoModal = loadable(() => import("./LayersInfoModal")); + /** * OutfitControls is the set of controls layered over the outfit preview, to * control things like species/color and sharing links! @@ -260,6 +262,9 @@ function OutfitControlsContextMenu({ outfitState, children }) { const [isOpen, setIsOpen] = React.useState(false); const [position, setPosition] = React.useState({ x: 0, y: 0 }); + const [layersInfoModalIsOpen, setLayersInfoModalIsOpen] = + React.useState(false); + const { visibleLayers } = useOutfitAppearance(outfitState); const [downloadImageUrl, prepareDownload] = useDownloadableImage(visibleLayers); @@ -293,9 +298,20 @@ function OutfitControlsContextMenu({ outfitState, children }) { > Download + } + onClick={() => setLayersInfoModalIsOpen(true)} + > + Layers (SWF, PNG) + + setLayersInfoModalIsOpen(false)} + visibleLayers={visibleLayers} + /> ); } diff --git a/app/javascript/wardrobe-2020/components/useOutfitAppearance.js b/app/javascript/wardrobe-2020/components/useOutfitAppearance.js index 8d94da34..73e60db5 100644 --- a/app/javascript/wardrobe-2020/components/useOutfitAppearance.js +++ b/app/javascript/wardrobe-2020/components/useOutfitAppearance.js @@ -139,6 +139,7 @@ export const appearanceLayerFragment = gql` depth label } + swfUrl # For the layer info modal } `;