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:
WithoutPants
2023-11-30 10:45:45 +11:00
committed by GitHub
parent 54461aa140
commit 5ebd3b3568
3 changed files with 63 additions and 37 deletions

View File

@@ -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 ? (

View File

@@ -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>

View File

@@ -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 {