diff --git a/ui/v2.5/src/components/Scenes/SceneCard.tsx b/ui/v2.5/src/components/Scenes/SceneCard.tsx index 49bee3148..d09697cac 100644 --- a/ui/v2.5/src/components/Scenes/SceneCard.tsx +++ b/ui/v2.5/src/components/Scenes/SceneCard.tsx @@ -12,6 +12,7 @@ import { TruncatedText, } from "src/components/Shared"; import { TextUtils } from "src/utils"; +import { SceneQueue } from "src/models/sceneQueue"; import { PerformerPopoverButton } from "../Shared/PerformerPopoverButton"; interface IScenePreviewProps { @@ -65,12 +66,13 @@ export const ScenePreview: React.FC = ({ interface ISceneCardProps { scene: GQL.SlimSceneDataFragment; + index?: number; + queue?: SceneQueue; compact?: boolean; selecting?: boolean; selected?: boolean | undefined; zoomIndex?: number; onSelectedChanged?: (selected: boolean, shiftKey: boolean) => void; - onSceneClicked?: () => void; } export const SceneCard: React.FC = ( @@ -300,9 +302,6 @@ export const SceneCard: React.FC = ( if (props.selecting && props.onSelectedChanged) { props.onSelectedChanged(!props.selected, shiftKey); event.preventDefault(); - } else if (props.onSceneClicked) { - props.onSceneClicked(); - event.preventDefault(); } } @@ -340,6 +339,10 @@ export const SceneCard: React.FC = ( let shiftKey = false; + const sceneLink = props.queue + ? props.queue.makeLink(props.scene.id, { sceneIndex: props.index }) + : `/scenes/${props.scene.id}`; + return ( = (
; zoomIndex: number; onSelectChange: (id: string, selected: boolean, shiftKey: boolean) => void; - onSceneClick?: (id: string, index: number) => void; } export const SceneCardsGrid: React.FC = ({ scenes, + queue, selectedIds, zoomIndex, onSelectChange, - onSceneClick, }) => { - function sceneClicked(sceneID: string, index: number) { - if (onSceneClick) { - onSceneClick(sceneID, index); - } - } - return (
{scenes.map((scene, index) => ( 0} selected={selectedIds.has(scene.id)} onSelectedChanged={(selected: boolean, shiftKey: boolean) => onSelectChange(scene.id, selected, shiftKey) } - onSceneClicked={() => sceneClicked(scene.id, index)} /> ))}
diff --git a/ui/v2.5/src/components/Scenes/SceneList.tsx b/ui/v2.5/src/components/Scenes/SceneList.tsx index 22b8a18e0..1fcd9b345 100644 --- a/ui/v2.5/src/components/Scenes/SceneList.tsx +++ b/ui/v2.5/src/components/Scenes/SceneList.tsx @@ -123,8 +123,8 @@ export const SceneList: React.FC = ({ if (queryResults.data.findScenes.scenes.length > index) { const { id } = queryResults!.data!.findScenes!.scenes[index]; // navigate to the image player page - const queue = SceneQueue.fromListFilterModel(filterCopy, index); - queue.playScene(history, id, { autoPlay: true }); + const queue = SceneQueue.fromListFilterModel(filterCopy); + queue.playScene(history, id, { sceneIndex: index, autoPlay: true }); } } } @@ -143,15 +143,6 @@ export const SceneList: React.FC = ({ setIsExportDialogOpen(true); } - async function sceneClicked( - sceneId: string, - sceneIndex: number, - filter: ListFilterModel - ) { - const queue = SceneQueue.fromListFilterModel(filter, sceneIndex); - queue.playScene(history, sceneId); - } - function maybeRenderSceneGenerateDialog(selectedIds: Set) { if (isGenerateDialogOpen) { return ( @@ -207,27 +198,34 @@ export const SceneList: React.FC = ({ if (!result.data || !result.data.findScenes) { return; } + + const queue = SceneQueue.fromListFilterModel(filter); + if (filter.displayMode === DisplayMode.Grid) { return ( listData.onSelectChange(id, selected, shiftKey) } - onSceneClick={(id, index) => sceneClicked(id, index, filter)} /> ); } if (filter.displayMode === DisplayMode.List) { - return ; + return ( + + ); } if (filter.displayMode === DisplayMode.Wall) { - return ; + return ( + + ); } if (filter.displayMode === DisplayMode.Tagger) { - return ; + return ; } } diff --git a/ui/v2.5/src/components/Scenes/SceneListTable.tsx b/ui/v2.5/src/components/Scenes/SceneListTable.tsx index 518e7f2a5..97496b440 100644 --- a/ui/v2.5/src/components/Scenes/SceneListTable.tsx +++ b/ui/v2.5/src/components/Scenes/SceneListTable.tsx @@ -9,6 +9,7 @@ import { Icon, TruncatedText } from "src/components/Shared"; interface ISceneListTableProps { scenes: GQL.SlimSceneDataFragment[]; + queue?: SceneQueue; } export const SceneListTable: React.FC = ( @@ -37,52 +38,58 @@ export const SceneListTable: React.FC = ( ) ); - const renderSceneRow = (scene: GQL.SlimSceneDataFragment) => ( - - - - {scene.title - - - - -
- { + const sceneLink = props.queue + ? props.queue.makeLink(scene.id, { sceneIndex: index }) + : `/scenes/${scene.id}`; + + return ( + + + + {scene.title -
- - - {scene.rating ? scene.rating : ""} - - {scene.file.duration && - TextUtils.secondsToTimestamp(scene.file.duration)} - - {renderTags(scene.tags)} - {renderPerformers(scene.performers)} - - {scene.studio && ( - -
{scene.studio.name}
- )} - - {renderMovies(scene)} - - {scene.gallery && ( - - )} - - - ); + )} + + {renderMovies(scene)} + + {scene.gallery && ( + + )} + + + ); + }; return (
diff --git a/ui/v2.5/src/components/Tagger/Tagger.tsx b/ui/v2.5/src/components/Tagger/Tagger.tsx index d18827b1e..ed9aa0a17 100755 --- a/ui/v2.5/src/components/Tagger/Tagger.tsx +++ b/ui/v2.5/src/components/Tagger/Tagger.tsx @@ -14,6 +14,7 @@ import { } from "src/core/StashService"; import { Manual } from "src/components/Help/Manual"; +import { SceneQueue } from "src/models/sceneQueue"; import StashSearchResult from "./StashSearchResult"; import Config from "./Config"; import { @@ -141,6 +142,7 @@ function prepareQueryString( interface ITaggerListProps { scenes: GQL.SlimSceneDataFragment[]; + queue?: SceneQueue; selectedEndpoint: { endpoint: string; index: number }; config: ITaggerConfig; queueFingerprintSubmission: (sceneId: string, endpoint: string) => void; @@ -149,6 +151,7 @@ interface ITaggerListProps { const TaggerList: React.FC = ({ scenes, + queue, selectedEndpoint, config, queueFingerprintSubmission, @@ -304,8 +307,15 @@ const TaggerList: React.FC = ({ setHideUnmatched(!hideUnmatched); }; + function generateSceneLink(scene: GQL.SlimSceneDataFragment, index: number) { + return queue + ? queue.makeLink(scene.id, { sceneIndex: index }) + : `/scenes/${scene.id}`; + } + const renderScenes = () => - scenes.map((scene) => { + scenes.map((scene, index) => { + const sceneLink = generateSceneLink(scene, index); const { paths, file, ext } = parsePath(scene.path); const originalDir = scene.path.slice( 0, @@ -376,7 +386,7 @@ const TaggerList: React.FC = ({
Scene successfully tagged:
- + {taggedScenes[scene.id].title}
@@ -476,7 +486,7 @@ const TaggerList: React.FC = ({
- + = ({ />
- + = ({ interface ITaggerProps { scenes: GQL.SlimSceneDataFragment[]; + queue?: SceneQueue; } -export const Tagger: React.FC = ({ scenes }) => { +export const Tagger: React.FC = ({ scenes, queue }) => { const stashConfig = useConfiguration(); const [{ data: config }, setConfig] = useLocalForage( LOCAL_FORAGE_KEY, @@ -620,6 +628,7 @@ export const Tagger: React.FC = ({ scenes }) => { = (props: IWallItemProps) => { let linkSrc: string = "#"; if (!props.clickHandler) { if (props.scene) { - linkSrc = `/scenes/${props.scene.id}`; + linkSrc = props.sceneQueue + ? props.sceneQueue.makeLink(props.scene.id, { sceneIndex: props.index }) + : `/scenes/${props.scene.id}`; } else if (props.sceneMarker) { linkSrc = NavUtils.makeSceneMarkerUrl(props.sceneMarker); } else if (props.image) { diff --git a/ui/v2.5/src/components/Wall/WallPanel.tsx b/ui/v2.5/src/components/Wall/WallPanel.tsx index b3f2a3f2d..a50ce1414 100644 --- a/ui/v2.5/src/components/Wall/WallPanel.tsx +++ b/ui/v2.5/src/components/Wall/WallPanel.tsx @@ -1,9 +1,11 @@ import React from "react"; import * as GQL from "src/core/generated-graphql"; +import { SceneQueue } from "src/models/sceneQueue"; import { WallItem } from "./WallItem"; interface IWallPanelProps { scenes?: GQL.SlimSceneDataFragment[]; + sceneQueue?: SceneQueue; sceneMarkers?: GQL.SceneMarkerDataFragment[]; images?: GQL.SlimImageDataFragment[]; clickHandler?: ( @@ -43,7 +45,9 @@ export const WallPanel: React.FC = ( const scenes = (props.scenes ?? []).map((scene, index, sceneArray) => ( diff --git a/ui/v2.5/src/locale/en-GB.json b/ui/v2.5/src/locale/en-GB.json index 0e09f413c..5295121cf 100644 --- a/ui/v2.5/src/locale/en-GB.json +++ b/ui/v2.5/src/locale/en-GB.json @@ -1,6 +1,7 @@ { "developmentVersion": "Development Version", "images": "Images", + "images-size": "Images size", "galleries": "Galleries", "library-size": "Library size", "markers": "Markers", @@ -9,6 +10,7 @@ "organized": "Organised", "performers": "Performers", "scenes": "Scenes", + "scenes-size": "Scenes size", "studios": "Studios", "tags": "Tags", "up-dir": "Up a directory", diff --git a/ui/v2.5/src/locale/en-US.json b/ui/v2.5/src/locale/en-US.json index d6ac76584..113c8a42a 100644 --- a/ui/v2.5/src/locale/en-US.json +++ b/ui/v2.5/src/locale/en-US.json @@ -1,6 +1,7 @@ { "developmentVersion": "Development Version", "images": "Images", + "images-size": "Images size", "galleries": "Galleries", "library-size": "Library size", "markers": "Markers", @@ -9,6 +10,7 @@ "organized": "Organized", "performers": "Performers", "scenes": "Scenes", + "scenes-size": "Scenes size", "studios": "Studios", "tags": "Tags", "up-dir": "Up a directory", diff --git a/ui/v2.5/src/models/sceneQueue.ts b/ui/v2.5/src/models/sceneQueue.ts index feb0f9569..3631470f4 100644 --- a/ui/v2.5/src/models/sceneQueue.ts +++ b/ui/v2.5/src/models/sceneQueue.ts @@ -13,6 +13,7 @@ interface IQueryParameters { } export interface IPlaySceneOptions { + sceneIndex?: number; newPage?: number; autoPlay?: boolean; } @@ -20,11 +21,10 @@ export interface IPlaySceneOptions { export class SceneQueue { public query?: ListFilterModel; public sceneIDs?: number[]; + private originalQueryPage?: number; + private originalQueryPageSize?: number; - public static fromListFilterModel( - filter: ListFilterModel, - currentSceneIndex?: number - ) { + public static fromListFilterModel(filter: ListFilterModel) { const ret = new SceneQueue(); const filterCopy = Object.assign( @@ -33,13 +33,8 @@ export class SceneQueue { ); filterCopy.itemsPerPage = 40; - // adjust page to be correct for the index - const filterIndex = - currentSceneIndex !== undefined - ? currentSceneIndex + (filter.currentPage - 1) * filter.itemsPerPage - : 0; - const newPage = Math.floor(filterIndex / filterCopy.itemsPerPage) + 1; - filterCopy.currentPage = newPage; + ret.originalQueryPage = filter.currentPage; + ret.originalQueryPageSize = filter.itemsPerPage; ret.query = filterCopy; return ret; @@ -51,7 +46,7 @@ export class SceneQueue { return ret; } - private makeQueryParameters(page?: number) { + private makeQueryParameters(sceneIndex?: number, page?: number) { if (this.query) { const queryParams = this.query.getQueryParameters(); const translatedParams = { @@ -64,6 +59,17 @@ export class SceneQueue { if (page !== undefined) { translatedParams.qfp = page; + } else if ( + sceneIndex !== undefined && + this.originalQueryPage !== undefined && + this.originalQueryPageSize !== undefined + ) { + // adjust page to be correct for the index + const filterIndex = + sceneIndex + + (this.originalQueryPage - 1) * this.originalQueryPageSize; + const newPage = Math.floor(filterIndex / this.query.itemsPerPage) + 1; + translatedParams.qfp = newPage; } return queryString.stringify(translatedParams, { encode: false }); @@ -109,8 +115,15 @@ export class SceneQueue { sceneID: string, options?: IPlaySceneOptions ) { - const paramStr = this.makeQueryParameters(options?.newPage); + history.push(this.makeLink(sceneID, options)); + } + + public makeLink(sceneID: string, options?: IPlaySceneOptions) { + const paramStr = this.makeQueryParameters( + options?.sceneIndex, + options?.newPage + ); const autoplayParam = options?.autoPlay ? "&autoplay=true" : ""; - history.push(`/scenes/${sceneID}?${paramStr}${autoplayParam}`); + return `/scenes/${sceneID}?${paramStr}${autoplayParam}`; } }