Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scene queue looping and scene looping #5012

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions ui/v2.5/src/components/ScenePlayer/ScenePlayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ interface IScenePlayerProps {
autoplay?: boolean;
permitLoop?: boolean;
initialTimestamp: number;
forceLoop?: boolean;
sendSetTimestamp: (setTimestamp: (value: number) => void) => void;
onComplete: () => void;
onNext: () => void;
Expand All @@ -215,6 +216,7 @@ export const ScenePlayer: React.FC<IScenePlayerProps> = ({
autoplay,
permitLoop = true,
initialTimestamp: _initialTimestamp,
forceLoop,
sendSetTimestamp,
onComplete,
onNext,
Expand Down Expand Up @@ -264,11 +266,12 @@ export const ScenePlayer: React.FC<IScenePlayerProps> = ({
const maxLoopDuration = interfaceConfig?.maximumLoopDuration ?? 0;
const looping = useMemo(
() =>
!!file?.duration &&
permitLoop &&
maxLoopDuration !== 0 &&
file.duration < maxLoopDuration,
[file, permitLoop, maxLoopDuration]
forceLoop ||
(!!file?.duration &&
permitLoop &&
maxLoopDuration !== 0 &&
file.duration < maxLoopDuration),
[file, permitLoop, maxLoopDuration, forceLoop]
);

const getPlayer = useCallback(() => {
Expand Down
75 changes: 50 additions & 25 deletions ui/v2.5/src/components/Scenes/SceneDetails/QueueViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
faChevronDown,
faChevronUp,
faRandom,
faRepeat,
faStepBackward,
faStepForward,
} from "@fortawesome/free-solid-svg-icons";
Expand All @@ -20,6 +21,10 @@ export interface IPlaylistViewer {
start?: number;
continue?: boolean;
hasMoreScenes: boolean;
loopQueue: boolean;
loopScene: boolean;
setLoopQueue: (v: boolean) => void;
setLoopScene: (v: boolean) => void;
setContinue: (v: boolean) => void;
onSceneClicked: (id: string) => void;
onNext: () => void;
Expand All @@ -35,6 +40,10 @@ export const QueueViewer: React.FC<IPlaylistViewer> = ({
start = 0,
continue: continuePlaylist = false,
hasMoreScenes,
loopQueue,
loopScene,
setLoopQueue,
setLoopScene,
setContinue,
onNext,
onPrevious,
Expand All @@ -47,8 +56,6 @@ export const QueueViewer: React.FC<IPlaylistViewer> = ({
const [lessLoading, setLessLoading] = useState(false);
const [moreLoading, setMoreLoading] = useState(false);

const currentIndex = scenes.findIndex((s) => s.id === currentID);

useEffect(() => {
setLessLoading(false);
setMoreLoading(false);
Expand Down Expand Up @@ -76,6 +83,19 @@ export const QueueViewer: React.FC<IPlaylistViewer> = ({
onMoreScenes();
}

function handleLoopClick() {
if (loopQueue) {
setLoopQueue(false);
setLoopScene(true);
} else if (loopScene) {
setLoopQueue(false);
setLoopScene(false);
} else {
setLoopQueue(true);
setLoopScene(false);
}
}

function renderPlaylistEntry(scene: QueuedScene) {
return (
<li
Expand Down Expand Up @@ -111,7 +131,6 @@ export const QueueViewer: React.FC<IPlaylistViewer> = ({
</li>
);
}

return (
<div id="queue-viewer">
<div className="queue-controls">
Expand All @@ -124,33 +143,39 @@ export const QueueViewer: React.FC<IPlaylistViewer> = ({
setContinue(!continuePlaylist);
}}
/>
<Button
className="minimal"
variant="secondary"
disabled={!continuePlaylist}
active={loopScene || loopQueue}
onClick={() => handleLoopClick()}
>
<Icon icon={faRepeat} />
{loopScene && 1}
</Button>
</div>
<div>
{currentIndex > 0 || start > 1 ? (
<Button
className="minimal"
variant="secondary"
onClick={() => onPrevious()}
>
<Icon icon={faStepBackward} />
</Button>
) : (
""
)}
{currentIndex < scenes.length - 1 || hasMoreScenes ? (
<Button
className="minimal"
variant="secondary"
onClick={() => onNext()}
>
<Icon icon={faStepForward} />
</Button>
) : (
""
)}
<Button
className="minimal"
variant="secondary"
disabled={scenes.length <= 1}
onClick={() => onPrevious()}
>
<Icon icon={faStepBackward} />
</Button>

<Button
className="minimal"
variant="secondary"
disabled={scenes.length <= 1}
onClick={() => onNext()}
>
<Icon icon={faStepForward} />
</Button>
<Button
className="minimal"
variant="secondary"
disabled={scenes.length <= 1}
onClick={() => onRandom()}
>
<Icon icon={faRandom} />
Expand Down
105 changes: 97 additions & 8 deletions ui/v2.5/src/components/Scenes/SceneDetails/Scene.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ interface IProps {
collapsed: boolean;
setCollapsed: (state: boolean) => void;
setContinuePlaylist: (value: boolean) => void;
loopQueue: boolean;
setLoopQueue: (value: boolean) => void;
loopScene: boolean;
setLoopScene: (value: boolean) => void;
}

interface ISceneParams {
Expand All @@ -170,6 +174,10 @@ const ScenePage: React.FC<IProps> = ({
collapsed,
setCollapsed,
setContinuePlaylist,
loopQueue,
setLoopQueue,
loopScene,
setLoopScene,
}) => {
const Toast = useToast();
const intl = useIntl();
Expand Down Expand Up @@ -505,6 +513,10 @@ const ScenePage: React.FC<IProps> = ({
hasMoreScenes={queueHasMoreScenes}
onLessScenes={onQueueLessScenes}
onMoreScenes={onQueueMoreScenes}
loopQueue={loopQueue}
setLoopQueue={setLoopQueue}
loopScene={loopScene}
setLoopScene={setLoopScene}
/>
</Tab.Pane>
<Tab.Pane eventKey="scene-markers-panel">
Expand Down Expand Up @@ -719,6 +731,14 @@ const SceneLoader: React.FC<RouteComponentProps<ISceneParams>> = ({
[queueScenes, id]
);

const [loopQueue, setLoopQueue] = useState(false);

const [loopScene, setLoopScene] = useState(false);

const forceLoop =
(continuePlaylist && loopScene) ||
(continuePlaylist && loopQueue && queueTotal === 1);

function getSetTimestamp(fn: (value: number) => void) {
_setTimestamp.current = fn;
}
Expand Down Expand Up @@ -803,6 +823,36 @@ const SceneLoader: React.FC<RouteComponentProps<ISceneParams>> = ({
return scenes;
}

async function onQueueFirstScenes() {
if (!sceneQueue.query || queueStart <= 1) {
return;
}

const filterCopy = sceneQueue.query.clone();
const newStart = 1;
filterCopy.currentPage = newStart;
const query = await queryFindScenes(filterCopy);
const { scenes } = query.data.findScenes;
setQueueScenes(scenes);

return scenes;
}

async function onQueueLastScenes() {
if (!sceneQueue.query || !queueHasMoreScenes) {
return;
}

const filterCopy = sceneQueue.query.clone();
const newStart = queueTotal;
filterCopy.currentPage = Math.ceil(newStart / filterCopy.itemsPerPage);
const query = await queryFindScenes(filterCopy);
const { scenes } = query.data.findScenes;
setQueueScenes(scenes);

return scenes;
}

function loadScene(sceneID: string, autoPlay?: boolean, newPage?: number) {
const sceneLink = sceneQueue.makeLink(sceneID, {
newPage,
Expand All @@ -812,19 +862,34 @@ const SceneLoader: React.FC<RouteComponentProps<ISceneParams>> = ({
history.replace(sceneLink);
}

async function queueNext(autoPlay: boolean) {
async function queueNext(autoPlay: boolean, loop?: boolean) {
if (currentQueueIndex === -1) return;

if (currentQueueIndex < queueScenes.length - 1) {
loadScene(queueScenes[currentQueueIndex + 1].id, autoPlay);
} else {
// if we're at the end of the queue, load more scenes
if (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, autoPlay, newPage);
if (currentQueueIndex === queueScenes.length - 1) {
if (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, autoPlay, newPage);
}
} else if (loop !== false) {
// no more scenes in queue
if (queueStart > 1) {
// load the first page and jump to the first scene
const loadedScenes = await onQueueFirstScenes();
if (loadedScenes && loadedScenes.length > 0) {
const newPage = 1;
loadScene(loadedScenes[0].id, autoPlay, newPage);
}
} else {
// jump to first scene in queue
loadScene(queueScenes[0].id, autoPlay);
}
}
}
}
Expand All @@ -847,6 +912,25 @@ const SceneLoader: React.FC<RouteComponentProps<ISceneParams>> = ({
newPage
);
}
} else {
// we're at the first scene of the first page.
if (queueHasMoreScenes) {
// we're at the beginning of the queue and queue has more pages. Jump to the last scene in the last page.
const loadedScenes = await onQueueLastScenes();
if (loadedScenes && loadedScenes.length > 0) {
const newPage = Math.ceil(
queueTotal / (sceneQueue.query?.itemsPerPage ?? 0)
);
loadScene(
loadedScenes[loadedScenes.length - 1].id,
autoPlay,
newPage
);
}
} else {
// we're at the beginning of the queue and there are no more pages so jump the last scene in the queue.
loadScene(queueScenes[queueScenes.length - 1].id, autoPlay);
}
}
}
}
Expand Down Expand Up @@ -876,7 +960,7 @@ const SceneLoader: React.FC<RouteComponentProps<ISceneParams>> = ({
function onComplete() {
// load the next scene if we're continuing
if (continuePlaylist) {
queueNext(true);
queueNext(true, loopQueue);
}
}

Expand Down Expand Up @@ -933,6 +1017,10 @@ const SceneLoader: React.FC<RouteComponentProps<ISceneParams>> = ({
collapsed={collapsed}
setCollapsed={setCollapsed}
setContinuePlaylist={setContinuePlaylist}
loopQueue={loopQueue}
setLoopQueue={setLoopQueue}
loopScene={loopScene}
setLoopScene={setLoopScene}
/>
<div className={`scene-player-container ${collapsed ? "expanded" : ""}`}>
<ScenePlayer
Expand All @@ -946,6 +1034,7 @@ const SceneLoader: React.FC<RouteComponentProps<ISceneParams>> = ({
onComplete={onComplete}
onNext={() => queueNext(true)}
onPrevious={() => queuePrevious(true)}
forceLoop={forceLoop}
/>
</div>
</div>
Expand Down
4 changes: 4 additions & 0 deletions ui/v2.5/src/components/Scenes/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,10 @@ input[type="range"].blue-slider {
position: sticky;
top: 0;
z-index: 100;

.form-check {
display: inline-block;
}
}

.queue-scene-details {
Expand Down
Loading