mirror of
https://github.com/stashapp/stash.git
synced 2025-12-18 21:04:37 +03:00
Fix issues navigating scene queue (#4325)
* Fix issues navigating between queue scenes * Fix queue next/previous button display * Autplay when clicking scene in queue * Sticky queue controls
This commit is contained in:
@@ -32,7 +32,7 @@ export interface IPlaylistViewer {
|
|||||||
export const QueueViewer: React.FC<IPlaylistViewer> = ({
|
export const QueueViewer: React.FC<IPlaylistViewer> = ({
|
||||||
scenes,
|
scenes,
|
||||||
currentID,
|
currentID,
|
||||||
start,
|
start = 0,
|
||||||
continue: continuePlaylist = false,
|
continue: continuePlaylist = false,
|
||||||
hasMoreScenes,
|
hasMoreScenes,
|
||||||
setContinue,
|
setContinue,
|
||||||
@@ -47,7 +47,7 @@ export const QueueViewer: React.FC<IPlaylistViewer> = ({
|
|||||||
const [lessLoading, setLessLoading] = useState(false);
|
const [lessLoading, setLessLoading] = useState(false);
|
||||||
const [moreLoading, setMoreLoading] = useState(false);
|
const [moreLoading, setMoreLoading] = useState(false);
|
||||||
|
|
||||||
const currentIndex = scenes?.findIndex((s) => s.id === currentID);
|
const currentIndex = scenes?.findIndex((s) => s.id === currentID) ?? 0;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setLessLoading(false);
|
setLessLoading(false);
|
||||||
@@ -119,7 +119,7 @@ export const QueueViewer: React.FC<IPlaylistViewer> = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{(currentIndex ?? 0) > 0 ? (
|
{currentIndex > 0 || start > 1 ? (
|
||||||
<Button
|
<Button
|
||||||
className="minimal"
|
className="minimal"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
@@ -130,7 +130,7 @@ export const QueueViewer: React.FC<IPlaylistViewer> = ({
|
|||||||
) : (
|
) : (
|
||||||
""
|
""
|
||||||
)}
|
)}
|
||||||
{(currentIndex ?? 0) < (scenes ?? []).length - 1 ? (
|
{currentIndex < (scenes ?? []).length - 1 || hasMoreScenes ? (
|
||||||
<Button
|
<Button
|
||||||
className="minimal"
|
className="minimal"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
@@ -151,7 +151,7 @@ export const QueueViewer: React.FC<IPlaylistViewer> = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="queue-content">
|
<div id="queue-content">
|
||||||
{(start ?? 0) > 1 ? (
|
{start > 1 ? (
|
||||||
<div className="d-flex justify-content-center">
|
<div className="d-flex justify-content-center">
|
||||||
<Button onClick={() => lessClicked()} disabled={lessLoading}>
|
<Button onClick={() => lessClicked()} disabled={lessLoading}>
|
||||||
{!lessLoading ? (
|
{!lessLoading ? (
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ interface IProps {
|
|||||||
onDelete: () => void;
|
onDelete: () => void;
|
||||||
continuePlaylist: boolean;
|
continuePlaylist: boolean;
|
||||||
loadScene: (sceneID: string) => void;
|
loadScene: (sceneID: string) => void;
|
||||||
queueHasMoreScenes: () => boolean;
|
queueHasMoreScenes: boolean;
|
||||||
onQueueMoreScenes: () => void;
|
onQueueMoreScenes: () => void;
|
||||||
onQueueLessScenes: () => void;
|
onQueueLessScenes: () => void;
|
||||||
queueStart: number;
|
queueStart: number;
|
||||||
@@ -450,7 +450,7 @@ const ScenePage: React.FC<IProps> = ({
|
|||||||
onPrevious={onQueuePrevious}
|
onPrevious={onQueuePrevious}
|
||||||
onRandom={onQueueRandom}
|
onRandom={onQueueRandom}
|
||||||
start={queueStart}
|
start={queueStart}
|
||||||
hasMoreScenes={queueHasMoreScenes()}
|
hasMoreScenes={queueHasMoreScenes}
|
||||||
onLessScenes={onQueueLessScenes}
|
onLessScenes={onQueueLessScenes}
|
||||||
onMoreScenes={onQueueMoreScenes}
|
onMoreScenes={onQueueMoreScenes}
|
||||||
/>
|
/>
|
||||||
@@ -594,9 +594,10 @@ const SceneLoader: React.FC<RouteComponentProps<ISceneParams>> = ({
|
|||||||
const [queueStart, setQueueStart] = useState(1);
|
const [queueStart, setQueueStart] = useState(1);
|
||||||
|
|
||||||
const autoplay = queryParams.get("autoplay") === "true";
|
const autoplay = queryParams.get("autoplay") === "true";
|
||||||
const currentQueueIndex = queueScenes
|
const currentQueueIndex = useMemo(
|
||||||
? queueScenes.findIndex((s) => s.id === id)
|
() => (queueScenes ? queueScenes.findIndex((s) => s.id === id) : -1),
|
||||||
: -1;
|
[queueScenes, id]
|
||||||
|
);
|
||||||
|
|
||||||
function getSetTimestamp(fn: (value: number) => void) {
|
function getSetTimestamp(fn: (value: number) => void) {
|
||||||
_setTimestamp.current = fn;
|
_setTimestamp.current = fn;
|
||||||
@@ -656,14 +657,16 @@ const SceneLoader: React.FC<RouteComponentProps<ISceneParams>> = ({
|
|||||||
const newScenes = (scenes as QueuedScene[]).concat(queueScenes);
|
const newScenes = (scenes as QueuedScene[]).concat(queueScenes);
|
||||||
setQueueScenes(newScenes);
|
setQueueScenes(newScenes);
|
||||||
setQueueStart(newStart);
|
setQueueStart(newStart);
|
||||||
|
|
||||||
|
return scenes;
|
||||||
}
|
}
|
||||||
|
|
||||||
function queueHasMoreScenes() {
|
const queueHasMoreScenes = useMemo(() => {
|
||||||
return queueStart + queueScenes.length - 1 < queueTotal;
|
return queueStart + queueScenes.length - 1 < queueTotal;
|
||||||
}
|
}, [queueStart, queueScenes, queueTotal]);
|
||||||
|
|
||||||
async function onQueueMoreScenes() {
|
async function onQueueMoreScenes() {
|
||||||
if (!sceneQueue.query || !queueHasMoreScenes()) {
|
if (!sceneQueue.query || !queueHasMoreScenes) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -677,6 +680,7 @@ const SceneLoader: React.FC<RouteComponentProps<ISceneParams>> = ({
|
|||||||
const newScenes = queueScenes.concat(scenes as QueuedScene[]);
|
const newScenes = queueScenes.concat(scenes as QueuedScene[]);
|
||||||
setQueueScenes(newScenes);
|
setQueueScenes(newScenes);
|
||||||
// don't change queue start
|
// don't change queue start
|
||||||
|
return scenes;
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadScene(sceneID: string, autoPlay?: boolean, newPage?: number) {
|
function loadScene(sceneID: string, autoPlay?: boolean, newPage?: number) {
|
||||||
@@ -701,19 +705,42 @@ const SceneLoader: React.FC<RouteComponentProps<ISceneParams>> = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onQueueNext() {
|
async function onQueueNext() {
|
||||||
if (!queueScenes) return;
|
if (!queueScenes) return;
|
||||||
|
|
||||||
if (currentQueueIndex >= 0 && currentQueueIndex < queueScenes.length - 1) {
|
if (currentQueueIndex >= 0 && currentQueueIndex < queueScenes.length - 1) {
|
||||||
loadScene(queueScenes[currentQueueIndex + 1].id);
|
loadScene(queueScenes[currentQueueIndex + 1].id, true);
|
||||||
|
} else {
|
||||||
|
// if we're at the end of the queue, load more scenes
|
||||||
|
if (
|
||||||
|
currentQueueIndex >= 0 &&
|
||||||
|
currentQueueIndex === queueScenes.length - 1 &&
|
||||||
|
queueHasMoreScenes
|
||||||
|
) {
|
||||||
|
const loadedScenes = await onQueueMoreScenes();
|
||||||
|
if (loadedScenes && loadedScenes.length > 0) {
|
||||||
|
// set the page to the next page
|
||||||
|
const newPage = (sceneQueue.query?.currentPage ?? 0) + 1;
|
||||||
|
loadScene(loadedScenes[0].id, true, newPage);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onQueuePrevious() {
|
async function onQueuePrevious() {
|
||||||
if (!queueScenes) return;
|
if (!queueScenes) return;
|
||||||
|
|
||||||
if (currentQueueIndex > 0) {
|
if (currentQueueIndex > 0) {
|
||||||
loadScene(queueScenes[currentQueueIndex - 1].id);
|
loadScene(queueScenes[currentQueueIndex - 1].id, true);
|
||||||
|
} else {
|
||||||
|
// if we're at the beginning of the queue, load the previous page
|
||||||
|
if (currentQueueIndex === 0 && queueStart > 1) {
|
||||||
|
const loadedScenes = await onQueueLessScenes();
|
||||||
|
if (loadedScenes && loadedScenes.length > 0) {
|
||||||
|
const newPage = (sceneQueue.query?.currentPage ?? 0) - 1;
|
||||||
|
loadScene(loadedScenes[loadedScenes.length - 1].id, true, newPage);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -746,29 +773,24 @@ const SceneLoader: React.FC<RouteComponentProps<ISceneParams>> = ({
|
|||||||
|
|
||||||
// load the next scene if we're continuing
|
// load the next scene if we're continuing
|
||||||
if (continuePlaylist) {
|
if (continuePlaylist) {
|
||||||
if (
|
onQueueNext();
|
||||||
currentQueueIndex >= 0 &&
|
|
||||||
currentQueueIndex < queueScenes.length - 1
|
|
||||||
) {
|
|
||||||
loadScene(queueScenes[currentQueueIndex + 1].id, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onNext() {
|
function getScenePage(sceneID: string) {
|
||||||
if (!queueScenes) return;
|
if (!sceneQueue.query) return;
|
||||||
|
|
||||||
if (currentQueueIndex >= 0 && currentQueueIndex < queueScenes.length - 1) {
|
// find the page that the scene is on
|
||||||
loadScene(queueScenes[currentQueueIndex + 1].id, true);
|
const index = queueScenes.findIndex((s) => s.id === sceneID);
|
||||||
}
|
|
||||||
|
if (index === -1) return;
|
||||||
|
|
||||||
|
const perPage = sceneQueue.query.itemsPerPage;
|
||||||
|
return Math.floor((index + queueStart - 1) / perPage) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
function onPrevious() {
|
function onSceneClicked(sceneID: string) {
|
||||||
if (!queueScenes) return;
|
loadScene(sceneID, true, getScenePage(sceneID));
|
||||||
|
|
||||||
if (currentQueueIndex > 0) {
|
|
||||||
loadScene(queueScenes[currentQueueIndex - 1].id, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!scene) {
|
if (!scene) {
|
||||||
@@ -789,7 +811,7 @@ const SceneLoader: React.FC<RouteComponentProps<ISceneParams>> = ({
|
|||||||
onQueuePrevious={onQueuePrevious}
|
onQueuePrevious={onQueuePrevious}
|
||||||
onQueueRandom={onQueueRandom}
|
onQueueRandom={onQueueRandom}
|
||||||
continuePlaylist={continuePlaylist}
|
continuePlaylist={continuePlaylist}
|
||||||
loadScene={loadScene}
|
loadScene={onSceneClicked}
|
||||||
queueHasMoreScenes={queueHasMoreScenes}
|
queueHasMoreScenes={queueHasMoreScenes}
|
||||||
onQueueLessScenes={onQueueLessScenes}
|
onQueueLessScenes={onQueueLessScenes}
|
||||||
onQueueMoreScenes={onQueueMoreScenes}
|
onQueueMoreScenes={onQueueMoreScenes}
|
||||||
@@ -807,8 +829,8 @@ const SceneLoader: React.FC<RouteComponentProps<ISceneParams>> = ({
|
|||||||
initialTimestamp={initialTimestamp}
|
initialTimestamp={initialTimestamp}
|
||||||
sendSetTimestamp={getSetTimestamp}
|
sendSetTimestamp={getSetTimestamp}
|
||||||
onComplete={onComplete}
|
onComplete={onComplete}
|
||||||
onNext={onNext}
|
onNext={onQueueNext}
|
||||||
onPrevious={onPrevious}
|
onPrevious={onQueuePrevious}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -543,9 +543,13 @@ input[type="range"].blue-slider {
|
|||||||
#queue-viewer {
|
#queue-viewer {
|
||||||
.queue-controls {
|
.queue-controls {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
background-color: $body-bg;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 0 1 auto;
|
flex: 0 1 auto;
|
||||||
|
height: 30px;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.thumbnail-container {
|
.thumbnail-container {
|
||||||
|
|||||||
Reference in New Issue
Block a user