From 880466b48ea2dfb1817645ea10bee4664ee96b37 Mon Sep 17 00:00:00 2001 From: WithoutPants <53250216+WithoutPants@users.noreply.github.com> Date: Sat, 16 Mar 2024 20:14:39 +1100 Subject: [PATCH 01/13] Style scene details --- .../Scenes/SceneDetails/SceneDetailPanel.tsx | 163 +++++++----------- ui/v2.5/src/components/Scenes/styles.scss | 22 +++ ui/v2.5/src/components/Shared/DetailItem.tsx | 14 +- .../StudioDetails/StudioDetailsPanel.tsx | 2 +- ui/v2.5/src/index.scss | 32 ++-- 5 files changed, 110 insertions(+), 123 deletions(-) diff --git a/ui/v2.5/src/components/Scenes/SceneDetails/SceneDetailPanel.tsx b/ui/v2.5/src/components/Scenes/SceneDetails/SceneDetailPanel.tsx index 729be465a72..3526b77408f 100644 --- a/ui/v2.5/src/components/Scenes/SceneDetails/SceneDetailPanel.tsx +++ b/ui/v2.5/src/components/Scenes/SceneDetails/SceneDetailPanel.tsx @@ -1,6 +1,6 @@ import React, { useMemo } from "react"; import { Link } from "react-router-dom"; -import { FormattedDate, FormattedMessage, useIntl } from "react-intl"; +import { useIntl } from "react-intl"; import * as GQL from "src/core/generated-graphql"; import TextUtils from "src/utils/text"; import { TagLink } from "src/components/Shared/TagLink"; @@ -10,6 +10,7 @@ import { sortPerformers } from "src/core/performers"; import { RatingSystem } from "src/components/Shared/Rating/RatingSystem"; import { objectTitle } from "src/core/files"; import { DirectorLink } from "src/components/Shared/Link"; +import { DetailItem } from "src/components/Shared/DetailItem"; interface ISceneDetailProps { scene: GQL.SceneDataFragment; @@ -23,64 +24,30 @@ export const SceneDetailPanel: React.FC = (props) => { [props.scene] ); - function renderDetails() { - if (!props.scene.details || props.scene.details === "") return; - return ( - <> -
- :{" "} -
-

{props.scene.details}

- - ); - } + // filename should use entire row if there is no studio + const sceneDetailsWidth = props.scene.studio ? "col-9" : "col-12"; - function renderTags() { - if (props.scene.tags.length === 0) return; - const tags = props.scene.tags.map((tag) => ( - - )); - return ( - <> -
- -
- {tags} - - ); - } + const tags = useMemo( + () => props.scene.tags.map((tag) => ), + [props.scene.tags] + ); - function renderPerformers() { - if (props.scene.performers.length === 0) return; - const performers = sortPerformers(props.scene.performers); - const cards = performers.map((performer) => ( + const performers = useMemo(() => { + const sorted = sortPerformers(props.scene.performers); + return sorted.map((performer) => ( )); + }, [props.scene.performers, props.scene.date]); - return ( - <> -
- -
-
- {cards} -
- - ); - } - - // filename should use entire row if there is no studio - const sceneDetailsWidth = props.scene.studio ? "col-9" : "col-12"; + const details = useMemo(() => { + return props.scene.details?.length ? ( +

{props.scene.details}

+ ) : undefined; + }, [props.scene.details]); return ( <> @@ -91,48 +58,53 @@ export const SceneDetailPanel: React.FC = (props) => { - {props.scene.date ? ( -
- -
- ) : undefined} - {props.scene.rating100 ? ( -
- :{" "} - -
- ) : ( - "" - )} - {file?.width && file?.height && ( -
- :{" "} - {TextUtils.resolution(file.width, file.height)} -
- )} -
- :{" "} - {TextUtils.formatDateTime(intl, props.scene.created_at)}{" "} -
-
- :{" "} - {TextUtils.formatDateTime(intl, props.scene.updated_at)}{" "} -
- {props.scene.code && ( -
- : {props.scene.code}{" "} -
- )} - {props.scene.director && ( -
- :{" "} - -
- )} + +
+ + + } + fullWidth + /> + + ) : undefined + } + fullWidth + /> + + + + + + +
{props.scene.studio && (
@@ -146,13 +118,6 @@ export const SceneDetailPanel: React.FC = (props) => {
)} -
-
- {renderDetails()} - {renderTags()} - {renderPerformers()} -
-
); }; diff --git a/ui/v2.5/src/components/Scenes/styles.scss b/ui/v2.5/src/components/Scenes/styles.scss index 2f66a54e92a..38b8754afb1 100644 --- a/ui/v2.5/src/components/Scenes/styles.scss +++ b/ui/v2.5/src/components/Scenes/styles.scss @@ -784,3 +784,25 @@ input[type="range"].blue-slider { } } } + +.scene-details { + .detail-item { + font-size: 1.25em; + + &.created-at, + &.updated-at { + font-size: 1em; + } + + &.rating, + &.tags, + &.performers, + &.details { + flex-basis: 100%; + } + + &:not(.full-width) .detail-item-title { + margin-bottom: 0.25em; + } + } +} diff --git a/ui/v2.5/src/components/Shared/DetailItem.tsx b/ui/v2.5/src/components/Shared/DetailItem.tsx index 304655a4c69..15dca58298d 100644 --- a/ui/v2.5/src/components/Shared/DetailItem.tsx +++ b/ui/v2.5/src/components/Shared/DetailItem.tsx @@ -1,5 +1,6 @@ import React from "react"; import { FormattedMessage } from "react-intl"; +import cx from "classnames"; interface IDetailItem { id?: string | null; @@ -20,17 +21,16 @@ export const DetailItem: React.FC = ({ const message = ; + // according to linter rule CSS classes shouldn't use underscores + const cssId = id?.replace("_", "-"); + return ( - // according to linter rule CSS classes shouldn't use underscores -
- +
+ {message} {fullWidth ? ":" : ""} - + {value}
diff --git a/ui/v2.5/src/components/Studios/StudioDetails/StudioDetailsPanel.tsx b/ui/v2.5/src/components/Studios/StudioDetails/StudioDetailsPanel.tsx index a6c5126cb6b..38983dbbcd7 100644 --- a/ui/v2.5/src/components/Studios/StudioDetails/StudioDetailsPanel.tsx +++ b/ui/v2.5/src/components/Studios/StudioDetails/StudioDetailsPanel.tsx @@ -47,7 +47,7 @@ export const StudioDetailsPanel: React.FC = ({ return (
- + Date: Sat, 16 Mar 2024 20:56:57 +1100 Subject: [PATCH 02/13] Add scene detail header --- .../components/Scenes/SceneDetails/Scene.tsx | 57 ++++++++++++++++++- .../Scenes/SceneDetails/SceneDetailPanel.tsx | 21 ------- ui/v2.5/src/components/Scenes/styles.scss | 23 ++++++++ 3 files changed, 77 insertions(+), 24 deletions(-) diff --git a/ui/v2.5/src/components/Scenes/SceneDetails/Scene.tsx b/ui/v2.5/src/components/Scenes/SceneDetails/Scene.tsx index f4cbbe0e38b..f82be57e3d5 100644 --- a/ui/v2.5/src/components/Scenes/SceneDetails/Scene.tsx +++ b/ui/v2.5/src/components/Scenes/SceneDetails/Scene.tsx @@ -7,7 +7,7 @@ import React, { useRef, useLayoutEffect, } from "react"; -import { FormattedMessage, useIntl } from "react-intl"; +import { FormattedDate, FormattedMessage, useIntl } from "react-intl"; import { Link, RouteComponentProps } from "react-router-dom"; import { Helmet } from "react-helmet"; import * as GQL from "src/core/generated-graphql"; @@ -74,6 +74,8 @@ const SceneVideoFilterPanel = lazyComponent( () => import("./SceneVideoFilterPanel") ); import { objectPath, objectTitle } from "src/core/files"; +import { RatingSystem } from "src/components/Shared/Rating/RatingSystem"; +import TextUtils from "src/utils/text"; interface IProps { scene: GQL.SceneDataFragment; @@ -420,7 +422,7 @@ const ScenePage: React.FC = ({ - + {/* @@ -440,7 +442,7 @@ const ScenePage: React.FC = ({ /> {renderOperations()} - + */}
@@ -509,6 +511,11 @@ const ScenePage: React.FC = ({ const title = objectTitle(scene); + const file = useMemo( + () => (scene.files.length > 0 ? scene.files[0] : undefined), + [scene] + ); + return ( <> @@ -534,6 +541,50 @@ const ScenePage: React.FC = ({ )}

{title}

+ +
+ + {!!scene.date && ( + + )} + + {file?.width && file.height ? ( + + {TextUtils.resolution(file.width, file.height)} + + ) : undefined} +
+ +
+ + + + + + + + + + + + + + {renderOperations()} + +
{renderTabs()} diff --git a/ui/v2.5/src/components/Scenes/SceneDetails/SceneDetailPanel.tsx b/ui/v2.5/src/components/Scenes/SceneDetails/SceneDetailPanel.tsx index 3526b77408f..f97bb88a966 100644 --- a/ui/v2.5/src/components/Scenes/SceneDetails/SceneDetailPanel.tsx +++ b/ui/v2.5/src/components/Scenes/SceneDetails/SceneDetailPanel.tsx @@ -7,7 +7,6 @@ import { TagLink } from "src/components/Shared/TagLink"; import { TruncatedText } from "src/components/Shared/TruncatedText"; import { PerformerCard } from "src/components/Performers/PerformerCard"; import { sortPerformers } from "src/core/performers"; -import { RatingSystem } from "src/components/Shared/Rating/RatingSystem"; import { objectTitle } from "src/core/files"; import { DirectorLink } from "src/components/Shared/Link"; import { DetailItem } from "src/components/Shared/DetailItem"; @@ -19,11 +18,6 @@ interface ISceneDetailProps { export const SceneDetailPanel: React.FC = (props) => { const intl = useIntl(); - const file = useMemo( - () => (props.scene.files.length > 0 ? props.scene.files[0] : undefined), - [props.scene] - ); - // filename should use entire row if there is no studio const sceneDetailsWidth = props.scene.studio ? "col-9" : "col-12"; @@ -60,13 +54,7 @@ export const SceneDetailPanel: React.FC = (props) => {
- - } - fullWidth - /> = (props) => { } fullWidth /> - Date: Sun, 17 Mar 2024 07:28:19 +1100 Subject: [PATCH 03/13] Add movies to details panel --- .../components/Performers/PerformerCard.tsx | 10 ++-- .../components/Scenes/SceneDetails/Scene.tsx | 37 --------------- .../Scenes/SceneDetails/SceneDetailPanel.tsx | 47 +++++++++++++++++-- .../Scenes/SceneDetails/SceneMoviePanel.tsx | 27 ----------- ui/v2.5/src/components/Scenes/styles.scss | 35 ++++++++++++++ ui/v2.5/src/components/Shared/DetailItem.tsx | 12 ++++- 6 files changed, 94 insertions(+), 74 deletions(-) delete mode 100644 ui/v2.5/src/components/Scenes/SceneDetails/SceneMoviePanel.tsx diff --git a/ui/v2.5/src/components/Performers/PerformerCard.tsx b/ui/v2.5/src/components/Performers/PerformerCard.tsx index 4792e452cd3..33c8a0e16bf 100644 --- a/ui/v2.5/src/components/Performers/PerformerCard.tsx +++ b/ui/v2.5/src/components/Performers/PerformerCard.tsx @@ -35,7 +35,7 @@ export interface IPerformerCardExtraCriteria { interface IPerformerCardProps { performer: GQL.PerformerDataFragment; containerWidth?: number; - ageFromDate?: string; + ageFromDate?: string | null; selecting?: boolean; selected?: boolean; onSelectedChanged?: (selected: boolean, shiftKey: boolean) => void; @@ -52,10 +52,10 @@ export const PerformerCard: React.FC = ({ extraCriteria, }) => { const intl = useIntl(); - const age = TextUtils.age( - performer.birthdate, - ageFromDate ?? performer.death_date - ); + const age = + ageFromDate === null + ? 0 + : TextUtils.age(performer.birthdate, ageFromDate ?? performer.death_date); const ageL10nId = ageFromDate ? "media_info.performer_card.age_context" : "media_info.performer_card.age"; diff --git a/ui/v2.5/src/components/Scenes/SceneDetails/Scene.tsx b/ui/v2.5/src/components/Scenes/SceneDetails/Scene.tsx index f82be57e3d5..ecf3aad4ed4 100644 --- a/ui/v2.5/src/components/Scenes/SceneDetails/Scene.tsx +++ b/ui/v2.5/src/components/Scenes/SceneDetails/Scene.tsx @@ -62,7 +62,6 @@ const SceneMarkersPanel = lazyComponent(() => import("./SceneMarkersPanel")); const SceneFileInfoPanel = lazyComponent(() => import("./SceneFileInfoPanel")); const SceneDetailPanel = lazyComponent(() => import("./SceneDetailPanel")); const SceneHistoryPanel = lazyComponent(() => import("./SceneHistoryPanel")); -const SceneMoviePanel = lazyComponent(() => import("./SceneMoviePanel")); const SceneGalleriesPanel = lazyComponent( () => import("./SceneGalleriesPanel") ); @@ -379,18 +378,6 @@ const ScenePage: React.FC = ({ - {scene.movies.length > 0 ? ( - - - - - - ) : ( - "" - )} {scene.galleries.length >= 1 ? ( @@ -422,27 +409,6 @@ const ScenePage: React.FC = ({ - {/* - - - - - - - - - - {renderOperations()} - */}
@@ -473,9 +439,6 @@ const ScenePage: React.FC = ({ isVisible={activeTabKey === "scene-markers-panel"} /> - - - {scene.galleries.length >= 1 && ( diff --git a/ui/v2.5/src/components/Scenes/SceneDetails/SceneDetailPanel.tsx b/ui/v2.5/src/components/Scenes/SceneDetails/SceneDetailPanel.tsx index f97bb88a966..e9e5680ad60 100644 --- a/ui/v2.5/src/components/Scenes/SceneDetails/SceneDetailPanel.tsx +++ b/ui/v2.5/src/components/Scenes/SceneDetails/SceneDetailPanel.tsx @@ -1,6 +1,6 @@ import React, { useMemo } from "react"; import { Link } from "react-router-dom"; -import { useIntl } from "react-intl"; +import { FormattedMessage, useIntl } from "react-intl"; import * as GQL from "src/core/generated-graphql"; import TextUtils from "src/utils/text"; import { TagLink } from "src/components/Shared/TagLink"; @@ -10,6 +10,8 @@ import { sortPerformers } from "src/core/performers"; import { objectTitle } from "src/core/files"; import { DirectorLink } from "src/components/Shared/Link"; import { DetailItem } from "src/components/Shared/DetailItem"; +import { Button } from "react-bootstrap"; +import { MovieCard } from "src/components/Movies/MovieCard"; interface ISceneDetailProps { scene: GQL.SceneDataFragment; @@ -26,13 +28,25 @@ export const SceneDetailPanel: React.FC = (props) => { [props.scene.tags] ); + const movies = useMemo( + () => + props.scene.movies.map((sceneMovie) => ( + + )), + [props.scene.movies] + ); + const performers = useMemo(() => { const sorted = sortPerformers(props.scene.performers); return sorted.map((performer) => ( )); }, [props.scene.performers, props.scene.date]); @@ -67,10 +81,37 @@ export const SceneDetailPanel: React.FC = (props) => { } fullWidth /> - + + + + + + } + value={tags.length ? tags : undefined} + /> + + + + } value={performers.length ? performers : undefined} /> = ( - props: ISceneMoviePanelProps -) => { - const cards = props.scene.movies.map((sceneMovie) => ( - - )); - - return ( - <> -
{cards}
- - ); -}; - -export default SceneMoviePanel; diff --git a/ui/v2.5/src/components/Scenes/styles.scss b/ui/v2.5/src/components/Scenes/styles.scss index 14fd6089c45..a63cd47c286 100644 --- a/ui/v2.5/src/components/Scenes/styles.scss +++ b/ui/v2.5/src/components/Scenes/styles.scss @@ -828,4 +828,39 @@ input[type="range"].blue-slider { margin-bottom: 0.25em; } } + + .performer-card { + max-width: 50%; + padding-bottom: 0; + + .rating-banner, + .favorite-button, + .performer-card__country-flag, + .card-popovers { + display: none; + } + + .card-section-title { + font-size: 1rem; + } + } + + .movie-card { + padding-bottom: 0; + width: 10rem; + + .card-section-title, + .movie-scene-number { + font-size: 1rem; + } + + .movie-scene-number { + color: $text-muted; + } + + .movie-card__details, + .card-popovers { + display: none; + } + } } diff --git a/ui/v2.5/src/components/Shared/DetailItem.tsx b/ui/v2.5/src/components/Shared/DetailItem.tsx index 15dca58298d..ea2adad6661 100644 --- a/ui/v2.5/src/components/Shared/DetailItem.tsx +++ b/ui/v2.5/src/components/Shared/DetailItem.tsx @@ -4,6 +4,7 @@ import cx from "classnames"; interface IDetailItem { id?: string | null; + heading?: React.ReactNode; value?: React.ReactNode; title?: string; fullWidth?: boolean; @@ -11,6 +12,7 @@ interface IDetailItem { export const DetailItem: React.FC = ({ id, + heading, value, title, fullWidth, @@ -27,8 +29,14 @@ export const DetailItem: React.FC = ({ return (
- {message} - {fullWidth ? ":" : ""} + {heading ? ( + heading + ) : ( + <> + {message} + {fullWidth ? ":" : ""} + + )} {value} From 29e0b07e55240fcfef060d9880ceaa85573e7646 Mon Sep 17 00:00:00 2001 From: WithoutPants <53250216+WithoutPants@users.noreply.github.com> Date: Sun, 17 Mar 2024 09:26:30 +1100 Subject: [PATCH 04/13] Move file info to pane --- ui/v2.5/graphql/data/file.graphql | 6 + .../components/Scenes/SceneDetails/Scene.tsx | 114 +++++++++++------- .../Scenes/SceneDetails/SceneDetailPanel.tsx | 75 ++++++++---- ui/v2.5/src/components/Scenes/styles.scss | 13 ++ ui/v2.5/src/components/Shared/DetailItem.tsx | 4 +- 5 files changed, 140 insertions(+), 72 deletions(-) diff --git a/ui/v2.5/graphql/data/file.graphql b/ui/v2.5/graphql/data/file.graphql index 52a4c50f89b..fe7f8fa0ecd 100644 --- a/ui/v2.5/graphql/data/file.graphql +++ b/ui/v2.5/graphql/data/file.graphql @@ -6,6 +6,7 @@ fragment FolderData on Folder { fragment VideoFileData on VideoFile { id path + basename size mod_time duration @@ -24,6 +25,7 @@ fragment VideoFileData on VideoFile { fragment ImageFileData on ImageFile { id path + basename size mod_time width @@ -37,6 +39,7 @@ fragment ImageFileData on ImageFile { fragment GalleryFileData on GalleryFile { id path + basename size mod_time fingerprints { @@ -49,6 +52,7 @@ fragment VisualFileData on VisualFile { ... on BaseFile { id path + basename size mod_time fingerprints { @@ -59,6 +63,7 @@ fragment VisualFileData on VisualFile { ... on ImageFile { id path + basename size mod_time width @@ -71,6 +76,7 @@ fragment VisualFileData on VisualFile { ... on VideoFile { id path + basename size mod_time duration diff --git a/ui/v2.5/src/components/Scenes/SceneDetails/Scene.tsx b/ui/v2.5/src/components/Scenes/SceneDetails/Scene.tsx index ecf3aad4ed4..0aecc7ac3ac 100644 --- a/ui/v2.5/src/components/Scenes/SceneDetails/Scene.tsx +++ b/ui/v2.5/src/components/Scenes/SceneDetails/Scene.tsx @@ -6,6 +6,7 @@ import React, { useContext, useRef, useLayoutEffect, + PropsWithChildren, } from "react"; import { FormattedDate, FormattedMessage, useIntl } from "react-intl"; import { Link, RouteComponentProps } from "react-router-dom"; @@ -27,7 +28,6 @@ import { SceneEditPanel } from "./SceneEditPanel"; import { ErrorMessage } from "src/components/Shared/ErrorMessage"; import { LoadingIndicator } from "src/components/Shared/LoadingIndicator"; import { Icon } from "src/components/Shared/Icon"; -import { Counter } from "src/components/Shared/Counter"; import { useToast } from "src/hooks/Toast"; import SceneQueue, { QueuedScene } from "src/models/sceneQueue"; import { ListFilterModel } from "src/models/list-filter/filter"; @@ -40,6 +40,7 @@ import { faEllipsisV, faChevronRight, faChevronLeft, + faTimes, } from "@fortawesome/free-solid-svg-icons"; import { lazyComponent } from "src/utils/lazyComponent"; @@ -133,6 +134,7 @@ const ScenePage: React.FC = ({ const [organizedLoading, setOrganizedLoading] = useState(false); const [activeTabKey, setActiveTabKey] = useState("scene-details-panel"); + const [activePane, setActivePane] = useState(); const [isDeleteAlertOpen, setIsDeleteAlertOpen] = useState(false); const [isGenerateDialogOpen, setIsGenerateDialogOpen] = useState(false); @@ -352,69 +354,89 @@ const ScenePage: React.FC = ({ ); + function TabLink( + props: PropsWithChildren<{ + className?: string; + eventKey: string; + pane?: boolean; + messageId?: string; + }> + ) { + if ( + (activePane !== undefined && activePane !== props.eventKey) || + (props.pane && activePane === undefined) + ) { + return null; + } + + return ( + + + {props.messageId ? ( + + ) : undefined} + {props.children} + + + ); + } + const renderTabs = () => ( k && setActiveTabKey(k)} >
- + setActivePane("scene-file-info-panel")} + /> void; } -export const SceneDetailPanel: React.FC = (props) => { +export const SceneDetailPanel: React.FC = ({ + scene, + onClickFileDetails, +}) => { const intl = useIntl(); // filename should use entire row if there is no studio - const sceneDetailsWidth = props.scene.studio ? "col-9" : "col-12"; + const sceneDetailsWidth = scene.studio ? "col-9" : "col-12"; const tags = useMemo( - () => props.scene.tags.map((tag) => ), - [props.scene.tags] + () => scene.tags.map((tag) => ), + [scene.tags] ); const movies = useMemo( () => - props.scene.movies.map((sceneMovie) => ( + scene.movies.map((sceneMovie) => ( )), - [props.scene.movies] + [scene.movies] ); const performers = useMemo(() => { - const sorted = sortPerformers(props.scene.performers); + const sorted = sortPerformers(scene.performers); return sorted.map((performer) => ( )); - }, [props.scene.performers, props.scene.date]); + }, [scene.performers, scene.date]); const details = useMemo(() => { - return props.scene.details?.length ? ( -

{props.scene.details}

+ return scene.details?.length ? ( +

{scene.details}

) : undefined; - }, [props.scene.details]); + }, [scene.details]); + + const files = useMemo(() => { + return ( +
    + {scene.files.map((file) => ( +
  • + +
  • + ))} +
+ ); + }, [scene.files, onClickFileDetails]); return ( <> @@ -63,20 +86,17 @@ export const SceneDetailPanel: React.FC = (props) => {

- +

- + + scene.director ? ( + ) : undefined } fullWidth @@ -114,24 +134,29 @@ export const SceneDetailPanel: React.FC = (props) => { } value={performers.length ? performers : undefined} /> +
- {props.scene.studio && ( + {scene.studio && (
- + {`${props.scene.studio.name} diff --git a/ui/v2.5/src/components/Scenes/styles.scss b/ui/v2.5/src/components/Scenes/styles.scss index a63cd47c286..c594299f720 100644 --- a/ui/v2.5/src/components/Scenes/styles.scss +++ b/ui/v2.5/src/components/Scenes/styles.scss @@ -812,11 +812,24 @@ input[type="range"].blue-slider { .detail-item { font-size: 1.25em; + &.files, &.created-at, &.updated-at { font-size: 1em; } + &.files ul { + font-size: 0.9em; + list-style-type: none; + padding-inline-start: 0; + + .file-info-button { + padding-left: 0; + padding-right: 0; + text-align: left; + } + } + &.rating, &.tags, &.performers, diff --git a/ui/v2.5/src/components/Shared/DetailItem.tsx b/ui/v2.5/src/components/Shared/DetailItem.tsx index ea2adad6661..83a728d7d1a 100644 --- a/ui/v2.5/src/components/Shared/DetailItem.tsx +++ b/ui/v2.5/src/components/Shared/DetailItem.tsx @@ -4,6 +4,7 @@ import cx from "classnames"; interface IDetailItem { id?: string | null; + messageId?: string; heading?: React.ReactNode; value?: React.ReactNode; title?: string; @@ -12,6 +13,7 @@ interface IDetailItem { export const DetailItem: React.FC = ({ id, + messageId, heading, value, title, @@ -21,7 +23,7 @@ export const DetailItem: React.FC = ({ return <>; } - const message = ; + const message = ; // according to linter rule CSS classes shouldn't use underscores const cssId = id?.replace("_", "-"); From 5916c0ce78a51339b43f1a8035ca561b25283349 Mon Sep 17 00:00:00 2001 From: WithoutPants <53250216+WithoutPants@users.noreply.github.com> Date: Sun, 17 Mar 2024 10:10:54 +1100 Subject: [PATCH 05/13] Make common count button and add view count --- .../components/Scenes/SceneDetails/Scene.tsx | 56 +++++++++---------- ui/v2.5/src/components/Shared/CountButton.tsx | 54 ++++++++++++++++++ ui/v2.5/src/components/Shared/styles.scss | 40 +++++++++++++ ui/v2.5/src/hooks/Lightbox/Lightbox.tsx | 29 +--------- 4 files changed, 124 insertions(+), 55 deletions(-) create mode 100644 ui/v2.5/src/components/Shared/CountButton.tsx diff --git a/ui/v2.5/src/components/Scenes/SceneDetails/Scene.tsx b/ui/v2.5/src/components/Scenes/SceneDetails/Scene.tsx index 0aecc7ac3ac..8473aa1690e 100644 --- a/ui/v2.5/src/components/Scenes/SceneDetails/Scene.tsx +++ b/ui/v2.5/src/components/Scenes/SceneDetails/Scene.tsx @@ -16,12 +16,11 @@ import { mutateMetadataScan, useFindScene, useSceneIncrementO, - useSceneDecrementO, - useSceneResetO, useSceneGenerateScreenshot, useSceneUpdate, queryFindScenes, queryFindScenesByID, + useSceneIncrementPlayCount, } from "src/core/StashService"; import { SceneEditPanel } from "./SceneEditPanel"; @@ -32,7 +31,6 @@ import { useToast } from "src/hooks/Toast"; import SceneQueue, { QueuedScene } from "src/models/sceneQueue"; import { ListFilterModel } from "src/models/list-filter/filter"; import Mousetrap from "mousetrap"; -import { OCounterButton } from "./OCounterButton"; import { OrganizedButton } from "./OrganizedButton"; import { ConfigurationContext } from "src/hooks/Config"; import { getPlayerPosition } from "src/components/ScenePlayer/util"; @@ -76,6 +74,10 @@ const SceneVideoFilterPanel = lazyComponent( import { objectPath, objectTitle } from "src/core/files"; import { RatingSystem } from "src/components/Shared/Rating/RatingSystem"; import TextUtils from "src/utils/text"; +import { + OCounterButton, + ViewCountButton, +} from "src/components/Shared/CountButton"; interface IProps { scene: GQL.SceneDataFragment; @@ -128,8 +130,16 @@ const ScenePage: React.FC = ({ const boxes = configuration?.general?.stashBoxes ?? []; const [incrementO] = useSceneIncrementO(scene.id); - const [decrementO] = useSceneDecrementO(scene.id); - const [resetO] = useSceneResetO(scene.id); + + const [incrementPlay] = useSceneIncrementPlayCount(); + + function incrementPlayCount() { + incrementPlay({ + variables: { + id: scene.id, + }, + }); + } const [organizedLoading, setOrganizedLoading] = useState(false); @@ -139,7 +149,7 @@ const ScenePage: React.FC = ({ const [isDeleteAlertOpen, setIsDeleteAlertOpen] = useState(false); const [isGenerateDialogOpen, setIsGenerateDialogOpen] = useState(false); - const onIncrementClick = async () => { + const onIncrementOClick = async () => { try { await incrementO(); } catch (e) { @@ -147,14 +157,6 @@ const ScenePage: React.FC = ({ } }; - const onDecrementClick = async () => { - try { - await decrementO(); - } catch (e) { - Toast.error(e); - } - }; - // set up hotkeys useEffect(() => { Mousetrap.bind("a", () => setActiveTabKey("scene-details-panel")); @@ -164,7 +166,7 @@ const ScenePage: React.FC = ({ Mousetrap.bind("i", () => setActiveTabKey("scene-file-info-panel")); Mousetrap.bind("h", () => setActiveTabKey("scene-history-panel")); Mousetrap.bind("o", () => { - onIncrementClick(); + onIncrementOClick(); }); Mousetrap.bind("p n", () => onQueueNext()); Mousetrap.bind("p p", () => onQueuePrevious()); @@ -221,14 +223,6 @@ const ScenePage: React.FC = ({ } }; - const onResetClick = async () => { - try { - await resetO(); - } catch (e) { - Toast.error(e); - } - }; - function onClickMarker(marker: GQL.SceneMarkerDataFragment) { setTimestamp(marker.seconds); } @@ -412,7 +406,7 @@ const ScenePage: React.FC = ({ messageId="file_info" pane /> - + = ({ + + incrementPlayCount()} + onValueClicked={() => setActivePane("scene-history-panel")} + /> + onIncrementOClick()} + onValueClicked={() => setActivePane("scene-history-panel")} /> diff --git a/ui/v2.5/src/components/Shared/CountButton.tsx b/ui/v2.5/src/components/Shared/CountButton.tsx new file mode 100644 index 00000000000..aac2d6012c7 --- /dev/null +++ b/ui/v2.5/src/components/Shared/CountButton.tsx @@ -0,0 +1,54 @@ +import { faEye } from "@fortawesome/free-solid-svg-icons"; +import React from "react"; +import { Button, ButtonGroup } from "react-bootstrap"; +import { Icon } from "src/components/Shared/Icon"; +import { SweatDrops } from "./SweatDrops"; +import cx from "classnames"; + +interface ICountButtonProps { + value: number; + icon: React.ReactNode; + onIncrement?: () => void; + onValueClicked?: () => void; + title?: string; +} + +export const CountButton: React.FC = ({ + value, + icon, + onIncrement, + onValueClicked, + title, +}) => { + return ( + + + + + ); +}; + +type CountButtonPropsNoIcon = Omit; + +export const ViewCountButton: React.FC = (props) => ( + } /> +); + +export const OCounterButton: React.FC = (props) => ( + } /> +); diff --git a/ui/v2.5/src/components/Shared/styles.scss b/ui/v2.5/src/components/Shared/styles.scss index 2ac707f066d..3736ad52432 100644 --- a/ui/v2.5/src/components/Shared/styles.scss +++ b/ui/v2.5/src/components/Shared/styles.scss @@ -552,3 +552,43 @@ button.btn.favorite-button { box-shadow: none; } } + +.count-button { + border-radius: 5px; + + &:hover { + background: rgba(138, 155, 168, 0.15); + color: #f5f8fa; + } + + .count-icon { + padding-left: 0.5rem; + padding-right: 0.25rem; + } + + .count-value { + padding-left: 0.25rem; + padding-right: 0.5rem; + } + + button.count-icon, + &.increment-only button.count-value { + &:hover { + background: none; + color: #f5f8fa; + } + } + + button.btn-secondary.count-icon, + button.btn-secondary.count-value { + &:focus { + border: none; + box-shadow: none; + color: #f5f8fa; + + &:not(:hover) { + background: none; + } + } + } +} diff --git a/ui/v2.5/src/hooks/Lightbox/Lightbox.tsx b/ui/v2.5/src/hooks/Lightbox/Lightbox.tsx index dcdbc4b33e9..abcb9bddd4d 100644 --- a/ui/v2.5/src/hooks/Lightbox/Lightbox.tsx +++ b/ui/v2.5/src/hooks/Lightbox/Lightbox.tsx @@ -21,13 +21,7 @@ import { FormattedMessage, useIntl } from "react-intl"; import { LightboxImage } from "./LightboxImage"; import { ConfigurationContext } from "../Config"; import { Link } from "react-router-dom"; -import { OCounterButton } from "src/components/Scenes/SceneDetails/OCounterButton"; -import { - mutateImageIncrementO, - mutateImageDecrementO, - mutateImageResetO, - useImageUpdate, -} from "src/core/StashService"; +import { mutateImageIncrementO, useImageUpdate } from "src/core/StashService"; import * as GQL from "src/core/generated-graphql"; import { useInterfaceLocalForage } from "../LocalForage"; import { imageLightboxDisplayModeIntlMap } from "src/core/enums"; @@ -48,6 +42,7 @@ import { import { RatingSystem } from "src/components/Shared/Rating/RatingSystem"; import { useDebounce } from "../debounce"; import { isVideo } from "src/utils/visualFile"; +import { OCounterButton } from "src/components/Shared/CountButton"; const CLASSNAME = "Lightbox"; const CLASSNAME_HEADER = `${CLASSNAME}-header`; @@ -712,24 +707,6 @@ export const LightboxComponent: React.FC = ({ } } - async function onDecrementClick() { - if (currentImage?.id === undefined) return; - try { - await mutateImageDecrementO(currentImage.id); - } catch (e) { - Toast.error(e); - } - } - - async function onResetClick() { - if (currentImage?.id === undefined) return; - try { - await mutateImageResetO(currentImage?.id); - } catch (e) { - Toast.error(e); - } - } - const pageHeader = page && pages ? intl.formatMessage( @@ -916,9 +893,7 @@ export const LightboxComponent: React.FC = ({ <>
From b5c3ed4300260de87cc54458b859907ec2ed7afa Mon Sep 17 00:00:00 2001 From: WithoutPants <53250216+WithoutPants@users.noreply.github.com> Date: Tue, 19 Mar 2024 12:15:13 +1100 Subject: [PATCH 06/13] Move performer age --- .../components/Performers/PerformerCard.tsx | 23 ++++++++----- ui/v2.5/src/components/Scenes/styles.scss | 34 ++++++++++++++++--- 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/ui/v2.5/src/components/Performers/PerformerCard.tsx b/ui/v2.5/src/components/Performers/PerformerCard.tsx index 33c8a0e16bf..32ed0c4106e 100644 --- a/ui/v2.5/src/components/Performers/PerformerCard.tsx +++ b/ui/v2.5/src/components/Performers/PerformerCard.tsx @@ -253,13 +253,20 @@ export const PerformerCard: React.FC = ({ } title={ -
- {performer.name} - {performer.disambiguation && ( - - {` (${performer.disambiguation})`} - - )} +
+ + {performer.name} + {performer.disambiguation && ( + + {` (${performer.disambiguation})`} + + )} + {ageFromDate && ( + + {age} + + )} +
} image={ @@ -284,7 +291,7 @@ export const PerformerCard: React.FC = ({ } details={ <> - {age !== 0 ? ( + {!ageFromDate && age !== 0 ? (
{ageString}
) : ( "" diff --git a/ui/v2.5/src/components/Scenes/styles.scss b/ui/v2.5/src/components/Scenes/styles.scss index c594299f720..da9dd63dff6 100644 --- a/ui/v2.5/src/components/Scenes/styles.scss +++ b/ui/v2.5/src/components/Scenes/styles.scss @@ -811,11 +811,13 @@ input[type="range"].blue-slider { .scene-details { .detail-item { font-size: 1.25em; + padding-right: 1rem; &.files, &.created-at, - &.updated-at { - font-size: 1em; + &.updated-at, + &.details .detail-item-value { + font-size: 1rem; } &.files ul { @@ -842,19 +844,41 @@ input[type="range"].blue-slider { } } + .detail-item-value.performers { + display: flex; + flex-wrap: wrap; + justify-content: flex-start; + } + .performer-card { - max-width: 50%; + max-width: 12rem; padding-bottom: 0; .rating-banner, .favorite-button, - .performer-card__country-flag, - .card-popovers { + .performer-card__country-flag { + // .card-popovers { display: none; } + .card-popovers { + margin-bottom: 0.25rem; + } + .card-section-title { font-size: 1rem; + justify-content: center; + } + + .performer-age { + color: $text-muted; + font-size: 0.9em; + margin-bottom: 0; + margin-left: 0.5rem; + } + + hr { + margin-bottom: 0; } } From a0ed6d2609fa131ff4e4fde4d99c1a74437a3e05 Mon Sep 17 00:00:00 2001 From: WithoutPants <53250216+WithoutPants@users.noreply.github.com> Date: Tue, 19 Mar 2024 12:29:42 +1100 Subject: [PATCH 07/13] Comment out add buttons --- .../components/Scenes/SceneDetails/SceneDetailPanel.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/v2.5/src/components/Scenes/SceneDetails/SceneDetailPanel.tsx b/ui/v2.5/src/components/Scenes/SceneDetails/SceneDetailPanel.tsx index 6c2f5429308..5e6d3411114 100644 --- a/ui/v2.5/src/components/Scenes/SceneDetails/SceneDetailPanel.tsx +++ b/ui/v2.5/src/components/Scenes/SceneDetails/SceneDetailPanel.tsx @@ -111,9 +111,9 @@ export const SceneDetailPanel: React.FC = ({ heading={ <> - + */} } value={tags.length ? tags : undefined} @@ -123,13 +123,13 @@ export const SceneDetailPanel: React.FC = ({ heading={ <> - + */} } value={performers.length ? performers : undefined} From 2bf9acd0864644e611edd34d62e80421164e1b1d Mon Sep 17 00:00:00 2001 From: WithoutPants <53250216+WithoutPants@users.noreply.github.com> Date: Tue, 19 Mar 2024 12:30:10 +1100 Subject: [PATCH 08/13] Capitalise detail item titles --- ui/v2.5/src/components/Shared/styles.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ui/v2.5/src/components/Shared/styles.scss b/ui/v2.5/src/components/Shared/styles.scss index 3736ad52432..066a92da34a 100644 --- a/ui/v2.5/src/components/Shared/styles.scss +++ b/ui/v2.5/src/components/Shared/styles.scss @@ -592,3 +592,7 @@ button.btn.favorite-button { } } } + +.detail-item-title { + text-transform: capitalize; +} From 013aea754c51e86fcc575af640eb48027d1a2fd6 Mon Sep 17 00:00:00 2001 From: WithoutPants <53250216+WithoutPants@users.noreply.github.com> Date: Tue, 19 Mar 2024 12:30:39 +1100 Subject: [PATCH 09/13] Add titles to play count and o count buttons --- ui/v2.5/src/components/Shared/CountButton.tsx | 32 +++++++++++++++---- ui/v2.5/src/locales/en-GB.json | 1 + 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/ui/v2.5/src/components/Shared/CountButton.tsx b/ui/v2.5/src/components/Shared/CountButton.tsx index aac2d6012c7..1519c104bde 100644 --- a/ui/v2.5/src/components/Shared/CountButton.tsx +++ b/ui/v2.5/src/components/Shared/CountButton.tsx @@ -4,6 +4,7 @@ import { Button, ButtonGroup } from "react-bootstrap"; import { Icon } from "src/components/Shared/Icon"; import { SweatDrops } from "./SweatDrops"; import cx from "classnames"; +import { useIntl } from "react-intl"; interface ICountButtonProps { value: number; @@ -11,6 +12,7 @@ interface ICountButtonProps { onIncrement?: () => void; onValueClicked?: () => void; title?: string; + countTitle?: string; } export const CountButton: React.FC = ({ @@ -19,6 +21,7 @@ export const CountButton: React.FC = ({ onIncrement, onValueClicked, title, + countTitle, }) => { return ( = ({ className="minimal count-value" variant="secondary" onClick={() => (onValueClicked ?? onIncrement)?.()} + title={!!onValueClicked ? countTitle : undefined} > {value} @@ -45,10 +49,26 @@ export const CountButton: React.FC = ({ type CountButtonPropsNoIcon = Omit; -export const ViewCountButton: React.FC = (props) => ( - } /> -); +export const ViewCountButton: React.FC = (props) => { + const intl = useIntl(); + return ( + } + title={intl.formatMessage({ id: "media_info.play_count" })} + countTitle={intl.formatMessage({ id: "actions.view_history" })} + /> + ); +}; -export const OCounterButton: React.FC = (props) => ( - } /> -); +export const OCounterButton: React.FC = (props) => { + const intl = useIntl(); + return ( + } + title={intl.formatMessage({ id: "o_count" })} + countTitle={intl.formatMessage({ id: "actions.view_history" })} + /> + ); +}; diff --git a/ui/v2.5/src/locales/en-GB.json b/ui/v2.5/src/locales/en-GB.json index eabbfe1ef7e..a1e06009436 100644 --- a/ui/v2.5/src/locales/en-GB.json +++ b/ui/v2.5/src/locales/en-GB.json @@ -134,6 +134,7 @@ "temp_enable": "Enable temporarily…", "unset": "Unset", "use_default": "Use default", + "view_history": "View history", "view_random": "View Random" }, "actions_name": "Actions", From 1b09be06d67b04ce503fb61f0677a00234c2c64c Mon Sep 17 00:00:00 2001 From: WithoutPants <53250216+WithoutPants@users.noreply.github.com> Date: Tue, 19 Mar 2024 12:48:30 +1100 Subject: [PATCH 10/13] Move rating from edit panel --- .../components/Scenes/SceneDetails/Scene.tsx | 37 +++++++++++++++---- .../Scenes/SceneDetails/SceneEditPanel.tsx | 15 -------- ui/v2.5/src/components/Scenes/styles.scss | 4 ++ ui/v2.5/src/components/Tagger/styles.scss | 12 +++--- 4 files changed, 41 insertions(+), 27 deletions(-) diff --git a/ui/v2.5/src/components/Scenes/SceneDetails/Scene.tsx b/ui/v2.5/src/components/Scenes/SceneDetails/Scene.tsx index 8473aa1690e..eea75ba3264 100644 --- a/ui/v2.5/src/components/Scenes/SceneDetails/Scene.tsx +++ b/ui/v2.5/src/components/Scenes/SceneDetails/Scene.tsx @@ -78,6 +78,7 @@ import { OCounterButton, ViewCountButton, } from "src/components/Shared/CountButton"; +import { useRatingKeybinds } from "src/hooks/keybinds"; interface IProps { scene: GQL.SceneDataFragment; @@ -157,14 +158,36 @@ const ScenePage: React.FC = ({ } }; + function setRating(v: number | null) { + updateScene({ + variables: { + input: { + id: scene.id, + rating100: v, + }, + }, + }); + } + + useRatingKeybinds( + true, + configuration?.ui.ratingSystemOptions?.type, + setRating + ); + + function onSetActiveTabKey(key: string) { + setActiveTabKey(key); + setActivePane(undefined); + } + // set up hotkeys useEffect(() => { - Mousetrap.bind("a", () => setActiveTabKey("scene-details-panel")); - Mousetrap.bind("q", () => setActiveTabKey("scene-queue-panel")); - Mousetrap.bind("e", () => setActiveTabKey("scene-edit-panel")); - Mousetrap.bind("k", () => setActiveTabKey("scene-markers-panel")); - Mousetrap.bind("i", () => setActiveTabKey("scene-file-info-panel")); - Mousetrap.bind("h", () => setActiveTabKey("scene-history-panel")); + Mousetrap.bind("a", () => onSetActiveTabKey("scene-details-panel")); + Mousetrap.bind("q", () => onSetActiveTabKey("scene-queue-panel")); + Mousetrap.bind("e", () => onSetActiveTabKey("scene-edit-panel")); + Mousetrap.bind("k", () => onSetActiveTabKey("scene-markers-panel")); + Mousetrap.bind("i", () => setActivePane("scene-file-info-panel")); + Mousetrap.bind("h", () => setActivePane("scene-history-panel")); Mousetrap.bind("o", () => { onIncrementOClick(); }); @@ -540,7 +563,7 @@ const ScenePage: React.FC = ({
- + diff --git a/ui/v2.5/src/components/Scenes/SceneDetails/SceneEditPanel.tsx b/ui/v2.5/src/components/Scenes/SceneDetails/SceneEditPanel.tsx index b4c3048c380..bee912c599f 100644 --- a/ui/v2.5/src/components/Scenes/SceneDetails/SceneEditPanel.tsx +++ b/ui/v2.5/src/components/Scenes/SceneDetails/SceneEditPanel.tsx @@ -33,7 +33,6 @@ import { IMovieEntry, SceneMovieTable } from "./SceneMovieTable"; import { faSearch, faSyncAlt } from "@fortawesome/free-solid-svg-icons"; import { objectTitle } from "src/core/files"; import { galleryTitle } from "src/core/galleries"; -import { useRatingKeybinds } from "src/hooks/keybinds"; import { lazyComponent } from "src/utils/lazyComponent"; import isEqual from "lodash-es/isEqual"; import { @@ -128,7 +127,6 @@ export const SceneEditPanel: React.FC = ({ urls: yupUniqueStringList(intl), date: yupDateString(intl), director: yup.string().ensure(), - rating100: yup.number().integer().nullable().defined(), gallery_ids: yup.array(yup.string().required()).defined(), studio_id: yup.string().required().nullable(), performer_ids: yup.array(yup.string().required()).defined(), @@ -153,7 +151,6 @@ export const SceneEditPanel: React.FC = ({ urls: scene.urls ?? [], date: scene.date ?? "", director: scene.director ?? "", - rating100: scene.rating100 ?? null, gallery_ids: (scene.galleries ?? []).map((g) => g.id), studio_id: scene.studio?.id ?? null, performer_ids: (scene.performers ?? []).map((p) => p.id), @@ -201,10 +198,6 @@ export const SceneEditPanel: React.FC = ({ .filter((m) => m.movie !== undefined) as IMovieEntry[]; }, [formik.values.movies, movies]); - function setRating(v: number) { - formik.setFieldValue("rating100", v); - } - function onSetGalleries(items: Gallery[]) { setGalleries(items); formik.setFieldValue( @@ -234,12 +227,6 @@ export const SceneEditPanel: React.FC = ({ formik.setFieldValue("studio_id", item ? item.id : null); } - useRatingKeybinds( - isVisible, - stashConfig?.ui.ratingSystemOptions?.type, - setRating - ); - useEffect(() => { if (isVisible) { Mousetrap.bind("s s", () => { @@ -726,7 +713,6 @@ export const SceneEditPanel: React.FC = ({ renderField, renderInputField, renderDateField, - renderRatingField, renderURLListField, renderStashIDsField, } = formikUtils(intl, formik, splitProps); @@ -865,7 +851,6 @@ export const SceneEditPanel: React.FC = ({ {renderDateField("date")} {renderInputField("director")} - {renderRatingField("rating100", "rating")} {renderGalleriesField()} {renderStudioField()} diff --git a/ui/v2.5/src/components/Scenes/styles.scss b/ui/v2.5/src/components/Scenes/styles.scss index da9dd63dff6..ffe356a6f42 100644 --- a/ui/v2.5/src/components/Scenes/styles.scss +++ b/ui/v2.5/src/components/Scenes/styles.scss @@ -809,6 +809,10 @@ input[type="range"].blue-slider { } .scene-details { + .detail-group { + padding-top: 0; + } + .detail-item { font-size: 1.25em; padding-right: 1rem; diff --git a/ui/v2.5/src/components/Tagger/styles.scss b/ui/v2.5/src/components/Tagger/styles.scss index 38ae10652fd..9d7187da6a2 100644 --- a/ui/v2.5/src/components/Tagger/styles.scss +++ b/ui/v2.5/src/components/Tagger/styles.scss @@ -402,12 +402,14 @@ li.active .optional-field.excluded .scene-link { // margin-left: 1rem; // } -.scene-details, -.original-scene-details { - margin-top: 0.5rem; +.tagger-container { + .scene-details, + .original-scene-details { + margin-top: 0.5rem; - > .row { - width: 100%; + > .row { + width: 100%; + } } } From 4e8f5d2669ae1bf1a501343d58cfbc74d76139ce Mon Sep 17 00:00:00 2001 From: WithoutPants <53250216+WithoutPants@users.noreply.github.com> Date: Tue, 19 Mar 2024 13:17:36 +1100 Subject: [PATCH 11/13] Styling --- .../components/Scenes/SceneDetails/Scene.tsx | 47 ++++++++++--------- .../Scenes/SceneDetails/SceneDetailPanel.tsx | 24 +--------- ui/v2.5/src/components/Scenes/styles.scss | 19 ++++++++ 3 files changed, 46 insertions(+), 44 deletions(-) diff --git a/ui/v2.5/src/components/Scenes/SceneDetails/Scene.tsx b/ui/v2.5/src/components/Scenes/SceneDetails/Scene.tsx index eea75ba3264..ee53e8c13e1 100644 --- a/ui/v2.5/src/components/Scenes/SceneDetails/Scene.tsx +++ b/ui/v2.5/src/components/Scenes/SceneDetails/Scene.tsx @@ -41,6 +41,15 @@ import { faTimes, } from "@fortawesome/free-solid-svg-icons"; import { lazyComponent } from "src/utils/lazyComponent"; +import { objectPath, objectTitle } from "src/core/files"; +import { RatingSystem } from "src/components/Shared/Rating/RatingSystem"; +import TextUtils from "src/utils/text"; +import { + OCounterButton, + ViewCountButton, +} from "src/components/Shared/CountButton"; +import { useRatingKeybinds } from "src/hooks/keybinds"; +import cx from "classnames"; const SubmitStashBoxDraft = lazyComponent( () => import("src/components/Dialogs/SubmitDraft") @@ -71,14 +80,6 @@ const GenerateDialog = lazyComponent( const SceneVideoFilterPanel = lazyComponent( () => import("./SceneVideoFilterPanel") ); -import { objectPath, objectTitle } from "src/core/files"; -import { RatingSystem } from "src/components/Shared/Rating/RatingSystem"; -import TextUtils from "src/utils/text"; -import { - OCounterButton, - ViewCountButton, -} from "src/components/Shared/CountButton"; -import { useRatingKeybinds } from "src/hooks/keybinds"; interface IProps { scene: GQL.SceneDataFragment; @@ -530,19 +531,23 @@ const ScenePage: React.FC = ({ collapsed ? "collapsed" : "" }`} > -
- {scene.studio && ( -

- - {`${scene.studio.name} - -

- )} -

{title}

+
+
+ {scene.studio && ( +

+ + {`${scene.studio.name} + +

+ )} +

+ {title} +

+
diff --git a/ui/v2.5/src/components/Scenes/SceneDetails/SceneDetailPanel.tsx b/ui/v2.5/src/components/Scenes/SceneDetails/SceneDetailPanel.tsx index 5e6d3411114..0f99cc85847 100644 --- a/ui/v2.5/src/components/Scenes/SceneDetails/SceneDetailPanel.tsx +++ b/ui/v2.5/src/components/Scenes/SceneDetails/SceneDetailPanel.tsx @@ -1,5 +1,4 @@ import React, { useMemo } from "react"; -import { Link } from "react-router-dom"; import { FormattedMessage, useIntl } from "react-intl"; import * as GQL from "src/core/generated-graphql"; import TextUtils from "src/utils/text"; @@ -7,7 +6,6 @@ import { TagLink } from "src/components/Shared/TagLink"; import { TruncatedText } from "src/components/Shared/TruncatedText"; import { PerformerCard } from "src/components/Performers/PerformerCard"; import { sortPerformers } from "src/core/performers"; -import { objectTitle } from "src/core/files"; import { DirectorLink } from "src/components/Shared/Link"; import { DetailItem } from "src/components/Shared/DetailItem"; import { Button } from "react-bootstrap"; @@ -24,9 +22,6 @@ export const SceneDetailPanel: React.FC = ({ }) => { const intl = useIntl(); - // filename should use entire row if there is no studio - const sceneDetailsWidth = scene.studio ? "col-9" : "col-12"; - const tags = useMemo( () => scene.tags.map((tag) => ), [scene.tags] @@ -83,13 +78,7 @@ export const SceneDetailPanel: React.FC = ({ return ( <>
-
-
-

- -

-
- +
= ({ />
- {scene.studio && ( -
- - {`${scene.studio.name} - -
- )}
); diff --git a/ui/v2.5/src/components/Scenes/styles.scss b/ui/v2.5/src/components/Scenes/styles.scss index ffe356a6f42..0b6c0c9335c 100644 --- a/ui/v2.5/src/components/Scenes/styles.scss +++ b/ui/v2.5/src/components/Scenes/styles.scss @@ -63,10 +63,29 @@ max-width: 100%; } +@include media-breakpoint-only(lg) { + .scene-header-container { + display: flex; + justify-content: space-between; + + .scene-header { + order: 1; + } + + .scene-studio-image { + order: 2; + } + } +} + .scene-header { flex-basis: auto; font-size: 1.5rem; margin-top: 30px; + + @include media-breakpoint-down(xl) { + font-size: 1.75rem; + } } .scene-subheader { From 9c3221686009ebee2c924d97ac02044533fe9a7e Mon Sep 17 00:00:00 2001 From: WithoutPants <53250216+WithoutPants@users.noreply.github.com> Date: Tue, 19 Mar 2024 13:52:17 +1100 Subject: [PATCH 12/13] Rearrange and restyle fields --- .../Scenes/SceneDetails/SceneDetailPanel.tsx | 28 +++++++++---------- ui/v2.5/src/components/Scenes/styles.scss | 2 ++ 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/ui/v2.5/src/components/Scenes/SceneDetails/SceneDetailPanel.tsx b/ui/v2.5/src/components/Scenes/SceneDetails/SceneDetailPanel.tsx index 0f99cc85847..63e11b89ec7 100644 --- a/ui/v2.5/src/components/Scenes/SceneDetails/SceneDetailPanel.tsx +++ b/ui/v2.5/src/components/Scenes/SceneDetails/SceneDetailPanel.tsx @@ -80,21 +80,7 @@ export const SceneDetailPanel: React.FC = ({
- - - ) : undefined - } - fullWidth - /> - = ({ } value={performers.length ? performers : undefined} /> + + + + ) : undefined + } + fullWidth + /> Date: Tue, 19 Mar 2024 14:35:24 +1100 Subject: [PATCH 13/13] Styling for lg viewports --- ui/v2.5/src/components/Scenes/styles.scss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ui/v2.5/src/components/Scenes/styles.scss b/ui/v2.5/src/components/Scenes/styles.scss index 4234d4c876f..2d9e87f6466 100644 --- a/ui/v2.5/src/components/Scenes/styles.scss +++ b/ui/v2.5/src/components/Scenes/styles.scss @@ -65,14 +65,17 @@ @include media-breakpoint-only(lg) { .scene-header-container { + align-items: center; display: flex; justify-content: space-between; .scene-header { + flex: 0 0 75%; order: 1; } .scene-studio-image { + flex: 0 0 25%; order: 2; } }