From bdb01ac82562e8a9798d136e9739bb001061d8d3 Mon Sep 17 00:00:00 2001 From: WithoutPants <53250216+WithoutPants@users.noreply.github.com> Date: Mon, 12 Feb 2024 14:03:13 +1100 Subject: [PATCH] Common studio overlay component (#4540) * Move GridCard to own directory * Make common studio overlay component --- .../src/components/Galleries/GalleryCard.tsx | 30 +--------- .../src/components/Galleries/GalleryList.tsx | 2 +- ui/v2.5/src/components/Images/ImageCard.tsx | 7 ++- ui/v2.5/src/components/Images/ImageList.tsx | 2 +- ui/v2.5/src/components/Movies/MovieCard.tsx | 2 +- .../src/components/Movies/MovieCardGrid.tsx | 2 +- .../components/Performers/PerformerCard.tsx | 2 +- .../Performers/PerformerCardGrid.tsx | 2 +- ui/v2.5/src/components/Scenes/SceneCard.tsx | 42 +------------ .../src/components/Scenes/SceneCardsGrid.tsx | 2 +- ui/v2.5/src/components/Scenes/styles.scss | 46 +-------------- .../Shared/{ => GridCard}/GridCard.tsx | 2 +- .../Shared/GridCard/StudioOverlay.tsx | 51 ++++++++++++++++ .../components/Shared/GridCard/styles.scss | 59 +++++++++++++++++++ ui/v2.5/src/components/Studios/StudioCard.tsx | 5 +- .../src/components/Studios/StudioCardGrid.tsx | 2 +- ui/v2.5/src/components/Tags/TagCard.tsx | 2 +- ui/v2.5/src/components/Tags/TagCardGrid.tsx | 2 +- ui/v2.5/src/index.scss | 1 + 19 files changed, 140 insertions(+), 123 deletions(-) rename ui/v2.5/src/components/Shared/{ => GridCard}/GridCard.tsx (99%) create mode 100644 ui/v2.5/src/components/Shared/GridCard/StudioOverlay.tsx create mode 100644 ui/v2.5/src/components/Shared/GridCard/styles.scss diff --git a/ui/v2.5/src/components/Galleries/GalleryCard.tsx b/ui/v2.5/src/components/Galleries/GalleryCard.tsx index 4df51efab5f..0c7491dc6f5 100644 --- a/ui/v2.5/src/components/Galleries/GalleryCard.tsx +++ b/ui/v2.5/src/components/Galleries/GalleryCard.tsx @@ -1,8 +1,7 @@ import { Button, ButtonGroup, OverlayTrigger, Tooltip } from "react-bootstrap"; import React, { useEffect, useState } from "react"; -import { Link } from "react-router-dom"; import * as GQL from "src/core/generated-graphql"; -import { GridCard, calculateCardWidth } from "../Shared/GridCard"; +import { GridCard, calculateCardWidth } from "../Shared/GridCard/GridCard"; import { HoverPopover } from "../Shared/HoverPopover"; import { Icon } from "../Shared/Icon"; import { SceneLink, TagLink } from "../Shared/TagLink"; @@ -10,11 +9,11 @@ import { TruncatedText } from "../Shared/TruncatedText"; import { PerformerPopoverButton } from "../Shared/PerformerPopoverButton"; import { PopoverCountButton } from "../Shared/PopoverCountButton"; import NavUtils from "src/utils/navigation"; -import { ConfigurationContext } from "src/hooks/Config"; import { RatingBanner } from "../Shared/RatingBanner"; import { faBox, faPlayCircle, faTag } from "@fortawesome/free-solid-svg-icons"; import { galleryTitle } from "src/core/galleries"; import ScreenUtils from "src/utils/screen"; +import { StudioOverlay } from "../Shared/GridCard/StudioOverlay"; interface IProps { gallery: GQL.SlimGalleryDataFragment; @@ -26,8 +25,6 @@ interface IProps { } export const GalleryCard: React.FC = (props) => { - const { configuration } = React.useContext(ConfigurationContext); - const showStudioAsText = configuration?.interface.showStudioAsText ?? false; const [cardWidth, setCardWidth] = useState(); useEffect(() => { @@ -121,27 +118,6 @@ export const GalleryCard: React.FC = (props) => { ); } - function maybeRenderSceneStudioOverlay() { - if (!props.gallery.studio) return; - - return ( -
- - {showStudioAsText ? ( - props.gallery.studio.name - ) : ( - {props.gallery.studio.name} - )} - -
- ); - } - function maybeRenderOrganized() { if (props.gallery.organized) { return ( @@ -202,7 +178,7 @@ export const GalleryCard: React.FC = (props) => { } - overlays={maybeRenderSceneStudioOverlay()} + overlays={} details={
{props.gallery.date} diff --git a/ui/v2.5/src/components/Galleries/GalleryList.tsx b/ui/v2.5/src/components/Galleries/GalleryList.tsx index 1e44a0a5b6e..6bc84208240 100644 --- a/ui/v2.5/src/components/Galleries/GalleryList.tsx +++ b/ui/v2.5/src/components/Galleries/GalleryList.tsx @@ -18,7 +18,7 @@ import { EditGalleriesDialog } from "./EditGalleriesDialog"; import { DeleteGalleriesDialog } from "./DeleteGalleriesDialog"; import { ExportDialog } from "../Shared/ExportDialog"; import { GalleryListTable } from "./GalleryListTable"; -import { useContainerDimensions } from "../Shared/GridCard"; +import { useContainerDimensions } from "../Shared/GridCard/GridCard"; const GalleryItemList = makeItemList({ filterMode: GQL.FilterMode.Galleries, diff --git a/ui/v2.5/src/components/Images/ImageCard.tsx b/ui/v2.5/src/components/Images/ImageCard.tsx index 98ae5b2fb86..12e8b9e0012 100644 --- a/ui/v2.5/src/components/Images/ImageCard.tsx +++ b/ui/v2.5/src/components/Images/ImageCard.tsx @@ -7,7 +7,10 @@ import { GalleryLink, TagLink } from "src/components/Shared/TagLink"; import { HoverPopover } from "src/components/Shared/HoverPopover"; import { SweatDrops } from "src/components/Shared/SweatDrops"; import { PerformerPopoverButton } from "src/components/Shared/PerformerPopoverButton"; -import { GridCard, calculateCardWidth } from "src/components/Shared/GridCard"; +import { + GridCard, + calculateCardWidth, +} from "src/components/Shared/GridCard/GridCard"; import { RatingBanner } from "src/components/Shared/RatingBanner"; import { faBox, @@ -18,6 +21,7 @@ import { import { objectTitle } from "src/core/files"; import { TruncatedText } from "../Shared/TruncatedText"; import ScreenUtils from "src/utils/screen"; +import { StudioOverlay } from "../Shared/GridCard/StudioOverlay"; interface IImageCardProps { image: GQL.SlimImageDataFragment; @@ -221,6 +225,7 @@ export const ImageCard: React.FC = ( />
} + overlays={} popovers={maybeRenderPopoverButtonGroup()} selected={props.selected} selecting={props.selecting} diff --git a/ui/v2.5/src/components/Images/ImageList.tsx b/ui/v2.5/src/components/Images/ImageList.tsx index aaec0c8500a..df244fc3e92 100644 --- a/ui/v2.5/src/components/Images/ImageList.tsx +++ b/ui/v2.5/src/components/Images/ImageList.tsx @@ -32,7 +32,7 @@ import { ExportDialog } from "../Shared/ExportDialog"; import { objectTitle } from "src/core/files"; import TextUtils from "src/utils/text"; import { ConfigurationContext } from "src/hooks/Config"; -import { useContainerDimensions } from "../Shared/GridCard"; +import { useContainerDimensions } from "../Shared/GridCard/GridCard"; interface IImageWallProps { images: GQL.SlimImageDataFragment[]; diff --git a/ui/v2.5/src/components/Movies/MovieCard.tsx b/ui/v2.5/src/components/Movies/MovieCard.tsx index 35a87333d1e..d517359265e 100644 --- a/ui/v2.5/src/components/Movies/MovieCard.tsx +++ b/ui/v2.5/src/components/Movies/MovieCard.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useState } from "react"; import { Button, ButtonGroup } from "react-bootstrap"; import * as GQL from "src/core/generated-graphql"; -import { GridCard, calculateCardWidth } from "../Shared/GridCard"; +import { GridCard, calculateCardWidth } from "../Shared/GridCard/GridCard"; import { HoverPopover } from "../Shared/HoverPopover"; import { Icon } from "../Shared/Icon"; import { SceneLink } from "../Shared/TagLink"; diff --git a/ui/v2.5/src/components/Movies/MovieCardGrid.tsx b/ui/v2.5/src/components/Movies/MovieCardGrid.tsx index 0748fb473b8..251d0c88153 100644 --- a/ui/v2.5/src/components/Movies/MovieCardGrid.tsx +++ b/ui/v2.5/src/components/Movies/MovieCardGrid.tsx @@ -1,7 +1,7 @@ import React, { useRef } from "react"; import * as GQL from "src/core/generated-graphql"; import { MovieCard } from "./MovieCard"; -import { useContainerDimensions } from "../Shared/GridCard"; +import { useContainerDimensions } from "../Shared/GridCard/GridCard"; interface IMovieCardGrid { movies: GQL.MovieDataFragment[]; diff --git a/ui/v2.5/src/components/Performers/PerformerCard.tsx b/ui/v2.5/src/components/Performers/PerformerCard.tsx index e4a83f42498..50da0bcb530 100644 --- a/ui/v2.5/src/components/Performers/PerformerCard.tsx +++ b/ui/v2.5/src/components/Performers/PerformerCard.tsx @@ -4,7 +4,7 @@ import { useIntl } from "react-intl"; import * as GQL from "src/core/generated-graphql"; import NavUtils from "src/utils/navigation"; import TextUtils from "src/utils/text"; -import { GridCard, calculateCardWidth } from "../Shared/GridCard"; +import { GridCard, calculateCardWidth } from "../Shared/GridCard/GridCard"; import { CountryFlag } from "../Shared/CountryFlag"; import { SweatDrops } from "../Shared/SweatDrops"; import { HoverPopover } from "../Shared/HoverPopover"; diff --git a/ui/v2.5/src/components/Performers/PerformerCardGrid.tsx b/ui/v2.5/src/components/Performers/PerformerCardGrid.tsx index 972005724c7..6fb59198f89 100644 --- a/ui/v2.5/src/components/Performers/PerformerCardGrid.tsx +++ b/ui/v2.5/src/components/Performers/PerformerCardGrid.tsx @@ -1,7 +1,7 @@ import React, { useRef } from "react"; import * as GQL from "src/core/generated-graphql"; import { IPerformerCardExtraCriteria, PerformerCard } from "./PerformerCard"; -import { useContainerDimensions } from "../Shared/GridCard"; +import { useContainerDimensions } from "../Shared/GridCard/GridCard"; interface IPerformerCardGrid { performers: GQL.PerformerDataFragment[]; diff --git a/ui/v2.5/src/components/Scenes/SceneCard.tsx b/ui/v2.5/src/components/Scenes/SceneCard.tsx index c385c9ea095..37c814bbedd 100644 --- a/ui/v2.5/src/components/Scenes/SceneCard.tsx +++ b/ui/v2.5/src/components/Scenes/SceneCard.tsx @@ -18,7 +18,7 @@ import TextUtils from "src/utils/text"; import { SceneQueue } from "src/models/sceneQueue"; import { ConfigurationContext } from "src/hooks/Config"; import { PerformerPopoverButton } from "../Shared/PerformerPopoverButton"; -import { GridCard, calculateCardWidth } from "../Shared/GridCard"; +import { GridCard, calculateCardWidth } from "../Shared/GridCard/GridCard"; import { RatingBanner } from "../Shared/RatingBanner"; import { FormattedNumber } from "react-intl"; import { @@ -33,6 +33,7 @@ import { objectPath, objectTitle } from "src/core/files"; import { PreviewScrubber } from "./PreviewScrubber"; import { PatchComponent } from "src/pluginApi"; import ScreenUtils from "src/utils/screen"; +import { StudioOverlay } from "../Shared/GridCard/StudioOverlay"; interface IScenePreviewProps { isPortrait: boolean; @@ -328,44 +329,7 @@ const SceneCardDetails = PatchComponent( const SceneCardOverlays = PatchComponent( "SceneCard.Overlays", (props: ISceneCardProps) => { - const { configuration } = React.useContext(ConfigurationContext); - - function renderStudioThumbnail() { - const studioImage = props.scene.studio?.image_path; - const studioName = props.scene.studio?.name; - - if (configuration?.interface.showStudioAsText || !studioImage) { - return studioName; - } - - const studioImageURL = new URL(studioImage); - if (studioImageURL.searchParams.get("default") === "true") { - return studioName; - } - - return ( - {studioName} - ); - } - - function maybeRenderSceneStudioOverlay() { - if (!props.scene.studio) return; - - return ( -
- - {renderStudioThumbnail()} - -
- ); - } - - return <>{maybeRenderSceneStudioOverlay()}; + return ; } ); diff --git a/ui/v2.5/src/components/Scenes/SceneCardsGrid.tsx b/ui/v2.5/src/components/Scenes/SceneCardsGrid.tsx index 2d21eda2bf1..26d3ce72824 100644 --- a/ui/v2.5/src/components/Scenes/SceneCardsGrid.tsx +++ b/ui/v2.5/src/components/Scenes/SceneCardsGrid.tsx @@ -2,7 +2,7 @@ import React, { useRef } from "react"; import * as GQL from "src/core/generated-graphql"; import { SceneQueue } from "src/models/sceneQueue"; import { SceneCard } from "./SceneCard"; -import { useContainerDimensions } from "../Shared/GridCard"; +import { useContainerDimensions } from "../Shared/GridCard/GridCard"; interface ISceneCardsGrid { scenes: GQL.SlimSceneDataFragment[]; diff --git a/ui/v2.5/src/components/Scenes/styles.scss b/ui/v2.5/src/components/Scenes/styles.scss index c09e14dfe41..6b08dffd022 100644 --- a/ui/v2.5/src/components/Scenes/styles.scss +++ b/ui/v2.5/src/components/Scenes/styles.scss @@ -132,33 +132,6 @@ textarea.scene-description { left: 0.7rem; } -.scene-studio-overlay { - display: block; - font-weight: 900; - height: 10%; - max-width: 40%; - opacity: 0.75; - position: absolute; - right: 0.7rem; - top: 0.7rem; - z-index: 8; - - .image-thumbnail { - height: 50px; - object-fit: contain; - width: 100%; - } - - a { - color: $text-color; - display: inline-block; - letter-spacing: -0.03rem; - text-align: right; - text-decoration: none; - text-shadow: 0 0 3px #000; - } -} - .extra-scene-info { display: none; } @@ -177,14 +150,7 @@ textarea.scene-description { .scene-card, .gallery-card { - a { - color: $text-color; - text-decoration: none; - } - - .scene-specs-overlay, - .rating-banner, - .scene-studio-overlay { + .scene-specs-overlay { transition: opacity 0.5s; } @@ -223,19 +189,11 @@ textarea.scene-description { &:hover, &:active { - .scene-specs-overlay, - .rating-banner, - .scene-studio-overlay { + .scene-specs-overlay { opacity: 0; transition: opacity 0.5s; } - .scene-studio-overlay:hover, - .scene-studio-overlay:active { - opacity: 0.75; - transition: opacity 0.5s; - } - .scene-card-check { opacity: 0.75; transition: opacity 0.5s; diff --git a/ui/v2.5/src/components/Shared/GridCard.tsx b/ui/v2.5/src/components/Shared/GridCard/GridCard.tsx similarity index 99% rename from ui/v2.5/src/components/Shared/GridCard.tsx rename to ui/v2.5/src/components/Shared/GridCard/GridCard.tsx index a8b221521af..7d0976c4fa8 100644 --- a/ui/v2.5/src/components/Shared/GridCard.tsx +++ b/ui/v2.5/src/components/Shared/GridCard/GridCard.tsx @@ -2,7 +2,7 @@ import React, { useEffect, useState } from "react"; import { Card, Form } from "react-bootstrap"; import { Link } from "react-router-dom"; import cx from "classnames"; -import { TruncatedText } from "./TruncatedText"; +import { TruncatedText } from "../TruncatedText"; import ScreenUtils from "src/utils/screen"; interface ICardProps { diff --git a/ui/v2.5/src/components/Shared/GridCard/StudioOverlay.tsx b/ui/v2.5/src/components/Shared/GridCard/StudioOverlay.tsx new file mode 100644 index 00000000000..875b122d89d --- /dev/null +++ b/ui/v2.5/src/components/Shared/GridCard/StudioOverlay.tsx @@ -0,0 +1,51 @@ +import React, { useMemo } from "react"; +import { Link } from "react-router-dom"; +import { ConfigurationContext } from "src/hooks/Config"; + +interface IStudio { + id: string; + name: string; + image_path?: string | null; +} + +export const StudioOverlay: React.FC<{ + studio: IStudio | null | undefined; +}> = ({ studio }) => { + const { configuration } = React.useContext(ConfigurationContext); + + const configValue = configuration?.interface.showStudioAsText; + + const showStudioAsText = useMemo(() => { + if (configValue || !studio?.image_path) { + return true; + } + + // If the studio has a default image, show the studio name as text + const studioImageURL = new URL(studio.image_path); + if (studioImageURL.searchParams.get("default") === "true") { + return true; + } + + return false; + }, [configValue, studio?.image_path]); + + if (!studio) return <>; + + return ( + // this class name is incorrect +
+ + {showStudioAsText ? ( + studio.name + ) : ( + {studio.name} + )} + +
+ ); +}; diff --git a/ui/v2.5/src/components/Shared/GridCard/styles.scss b/ui/v2.5/src/components/Shared/GridCard/styles.scss new file mode 100644 index 00000000000..fcf699fe234 --- /dev/null +++ b/ui/v2.5/src/components/Shared/GridCard/styles.scss @@ -0,0 +1,59 @@ +.grid-card { + a { + color: $text-color; + text-decoration: none; + } + + .rating-banner { + transition: opacity 0.5s; + } + + &:hover, + &:active { + .rating-banner, + .studio-overlay { + opacity: 0; + transition: opacity 0.5s; + } + + .studio-overlay:hover, + .studio-overlay:active { + opacity: 0.75; + transition: opacity 0.5s; + } + } +} + +.studio-overlay { + display: block; + font-weight: 900; + height: 10%; + max-width: 40%; + opacity: 0.75; + position: absolute; + right: 0.7rem; + top: 0.7rem; + transition: opacity 0.5s; + z-index: 8; + + .image-thumbnail { + height: 50px; + object-fit: contain; + width: 100%; + } + + a { + color: $text-color; + display: inline-block; + letter-spacing: -0.03rem; + text-align: right; + text-decoration: none; + text-shadow: 0 0 3px #000; + } + + &:hover, + &:active { + opacity: 0.75; + transition: opacity 0.5s; + } +} diff --git a/ui/v2.5/src/components/Studios/StudioCard.tsx b/ui/v2.5/src/components/Studios/StudioCard.tsx index 64dc52a137c..e0915597bf6 100644 --- a/ui/v2.5/src/components/Studios/StudioCard.tsx +++ b/ui/v2.5/src/components/Studios/StudioCard.tsx @@ -2,7 +2,10 @@ import React, { useEffect, useState } from "react"; import { Link } from "react-router-dom"; import * as GQL from "src/core/generated-graphql"; import NavUtils from "src/utils/navigation"; -import { GridCard, calculateCardWidth } from "src/components/Shared/GridCard"; +import { + GridCard, + calculateCardWidth, +} from "src/components/Shared/GridCard/GridCard"; import { ButtonGroup } from "react-bootstrap"; import { FormattedMessage } from "react-intl"; import { PopoverCountButton } from "../Shared/PopoverCountButton"; diff --git a/ui/v2.5/src/components/Studios/StudioCardGrid.tsx b/ui/v2.5/src/components/Studios/StudioCardGrid.tsx index e6ab718e967..cce7006001c 100644 --- a/ui/v2.5/src/components/Studios/StudioCardGrid.tsx +++ b/ui/v2.5/src/components/Studios/StudioCardGrid.tsx @@ -1,6 +1,6 @@ import React, { useRef } from "react"; import * as GQL from "src/core/generated-graphql"; -import { useContainerDimensions } from "../Shared/GridCard"; +import { useContainerDimensions } from "../Shared/GridCard/GridCard"; import { StudioCard } from "./StudioCard"; interface IStudioCardGrid { diff --git a/ui/v2.5/src/components/Tags/TagCard.tsx b/ui/v2.5/src/components/Tags/TagCard.tsx index 9e651a4eadc..dfd994ce895 100644 --- a/ui/v2.5/src/components/Tags/TagCard.tsx +++ b/ui/v2.5/src/components/Tags/TagCard.tsx @@ -5,7 +5,7 @@ import * as GQL from "src/core/generated-graphql"; import NavUtils from "src/utils/navigation"; import { FormattedMessage } from "react-intl"; import { TruncatedText } from "../Shared/TruncatedText"; -import { GridCard, calculateCardWidth } from "../Shared/GridCard"; +import { GridCard, calculateCardWidth } from "../Shared/GridCard/GridCard"; import { PopoverCountButton } from "../Shared/PopoverCountButton"; import ScreenUtils from "src/utils/screen"; diff --git a/ui/v2.5/src/components/Tags/TagCardGrid.tsx b/ui/v2.5/src/components/Tags/TagCardGrid.tsx index ccbe98e3e83..7e320113ef3 100644 --- a/ui/v2.5/src/components/Tags/TagCardGrid.tsx +++ b/ui/v2.5/src/components/Tags/TagCardGrid.tsx @@ -1,6 +1,6 @@ import React, { useRef } from "react"; import * as GQL from "src/core/generated-graphql"; -import { useContainerDimensions } from "../Shared/GridCard"; +import { useContainerDimensions } from "../Shared/GridCard/GridCard"; import { TagCard } from "./TagCard"; interface ITagCardGrid { diff --git a/ui/v2.5/src/index.scss b/ui/v2.5/src/index.scss index a86e7f7a5fc..0aff6234dec 100755 --- a/ui/v2.5/src/index.scss +++ b/ui/v2.5/src/index.scss @@ -17,6 +17,7 @@ @import "src/components/Setup/styles.scss"; @import "src/components/Studios/styles.scss"; @import "src/components/Shared/styles.scss"; +@import "src/components/Shared/GridCard/styles.scss"; @import "src/components/Shared/Rating/styles.scss"; @import "src/components/Shared/PackageManager/styles.scss"; @import "src/components/Tags/styles.scss";