diff --git a/ui/v2.5/src/components/Tagger/scenes/SceneTagger.tsx b/ui/v2.5/src/components/Tagger/scenes/SceneTagger.tsx index 8db55d412..96dd2cc1d 100755 --- a/ui/v2.5/src/components/Tagger/scenes/SceneTagger.tsx +++ b/ui/v2.5/src/components/Tagger/scenes/SceneTagger.tsx @@ -1,4 +1,4 @@ -import React, { useContext, useState } from "react"; +import React, { useContext, useMemo, useState } from "react"; import * as GQL from "src/core/generated-graphql"; import { SceneQueue } from "src/models/sceneQueue"; import { Button, Form } from "react-bootstrap"; @@ -15,6 +15,7 @@ import { SceneSearchResults } from "./StashSearchResult"; import { ConfigurationContext } from "src/hooks/Config"; import { faCog } from "@fortawesome/free-solid-svg-icons"; import { distance } from "src/utils/hamming"; +import { useLightbox } from "src/hooks/Lightbox/hooks"; interface ITaggerProps { scenes: GQL.SlimSceneDataFragment[]; @@ -221,6 +222,19 @@ export const Tagger: React.FC = ({ scenes, queue }) => { return minDurationDiffSceneA - minDurationDiffSceneB; } + const [spriteImage, setSpriteImage] = useState(null); + const lightboxImage = useMemo( + () => [{ paths: { thumbnail: spriteImage, image: spriteImage } }], + [spriteImage] + ); + const showLightbox = useLightbox({ + images: lightboxImage, + }); + function showLightboxImage(imagePath: string) { + setSpriteImage(imagePath); + showLightbox(); + } + function renderScenes() { const filteredScenes = !hideUnmatched ? scenes @@ -267,6 +281,7 @@ export const Tagger: React.FC = ({ scenes, queue }) => { } : undefined } + showLightboxImage={showLightboxImage} > {searchResult && searchResult.results?.length ? ( diff --git a/ui/v2.5/src/components/Tagger/scenes/TaggerScene.tsx b/ui/v2.5/src/components/Tagger/scenes/TaggerScene.tsx index 05b11b9f6..7988a5b82 100644 --- a/ui/v2.5/src/components/Tagger/scenes/TaggerScene.tsx +++ b/ui/v2.5/src/components/Tagger/scenes/TaggerScene.tsx @@ -12,7 +12,11 @@ import { TruncatedText } from "src/components/Shared/TruncatedText"; import { parsePath, prepareQueryString } from "src/components/Tagger/utils"; import { ScenePreview } from "src/components/Scenes/SceneCard"; import { TaggerStateContext } from "../context"; -import { faChevronDown, faChevronUp } from "@fortawesome/free-solid-svg-icons"; +import { + faChevronDown, + faChevronUp, + faImage, +} from "@fortawesome/free-solid-svg-icons"; import { objectPath, objectTitle } from "src/core/files"; interface ITaggerSceneDetails { @@ -84,6 +88,7 @@ interface ITaggerScene { doSceneQuery?: (queryString: string) => void; scrapeSceneFragment?: (scene: GQL.SlimSceneDataFragment) => void; loading?: boolean; + showLightboxImage: (imagePath: string) => void; } export const TaggerScene: React.FC> = ({ @@ -94,6 +99,7 @@ export const TaggerScene: React.FC> = ({ scrapeSceneFragment, errorMessage, children, + showLightboxImage, }) => { const { config } = useContext(TaggerStateContext); const [queryString, setQueryString] = useState(""); @@ -186,6 +192,27 @@ export const TaggerScene: React.FC> = ({ } } + function onSpriteClick(ev: React.MouseEvent) { + ev.preventDefault(); + showLightboxImage(scene.paths.sprite ?? ""); + } + + function maybeRenderSpriteIcon() { + // If a scene doesn't have any files, or doesn't have a sprite generated, the + // path will be http://localhost:9999/scene/_sprite.jpg + if (scene.files.length > 0) { + return ( + + ); + } + } + return (
@@ -198,6 +225,7 @@ export const TaggerScene: React.FC> = ({ isPortrait={isPortrait} soundActive={false} /> + {maybeRenderSpriteIcon()}
diff --git a/ui/v2.5/src/components/Tagger/styles.scss b/ui/v2.5/src/components/Tagger/styles.scss index d19494cf8..3a7594ca4 100644 --- a/ui/v2.5/src/components/Tagger/styles.scss +++ b/ui/v2.5/src/components/Tagger/styles.scss @@ -6,6 +6,10 @@ padding-bottom: 0; } + .scene-card { + position: relative; + } + .scene-card-preview { border-radius: 3px; margin-bottom: 0; @@ -18,6 +22,14 @@ } } + .sprite-button { + bottom: 5px; + filter: drop-shadow(1px 1px 1px #222); + padding: 0; + position: absolute; + right: 5px; + } + .sub-content { min-height: 1.5rem; } diff --git a/ui/v2.5/src/docs/en/Changelog/v0200.md b/ui/v2.5/src/docs/en/Changelog/v0200.md index 1ed11770c..6b7d22d1e 100644 --- a/ui/v2.5/src/docs/en/Changelog/v0200.md +++ b/ui/v2.5/src/docs/en/Changelog/v0200.md @@ -1,6 +1,7 @@ ##### 💥 Note: The cache directory is now required if using HLS/DASH streaming. Please set the cache directory in the System Settings page. ### ✨ New Features +* Added button to tagger scene cards to view scene sprite. ([#3536](https://github.com/stashapp/stash/pull/3536)) * Added hardware acceleration support (for a limited number of encoders) for transcoding. ([#3419](https://github.com/stashapp/stash/pull/3419)) * Added support for DASH streaming. ([#3275](https://github.com/stashapp/stash/pull/3275)) * Added configuration option for the maximum number of items in selector drop-downs. ([#3277](https://github.com/stashapp/stash/pull/3277))