mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-17 18:10:47 -04:00
48 lines
2.4 KiB
JavaScript
48 lines
2.4 KiB
JavaScript
import { useMemo } from 'react';
|
|
import { useSessionSelector } from '../context/SessionContext.jsx';
|
|
import { useSharedClock } from './useSharedClock.js';
|
|
|
|
export function useDriverVideoModePolicy(roverId) {
|
|
const mode = useSessionSelector((state) => state.session?.mode || null);
|
|
const turnQueues = useSessionSelector((state) => state.session?.turnQueues ?? {});
|
|
const socketId = useSessionSelector((state) => state.session?.socketId || null);
|
|
const activeDrivers = useSessionSelector((state) => state.session?.activeDrivers ?? {});
|
|
const nonTurnSnapshotsActive = useSessionSelector(
|
|
(state) => Boolean(state.session?.bandwidthSavings?.nonTurnVideo?.snapshotsActive),
|
|
);
|
|
const isTurnsMode = mode === 'turns';
|
|
/*
|
|
This policy only switches preview/full video around a multi-second turn
|
|
boundary. A shared one-second clock is responsive enough for that UI policy
|
|
and avoids running a separate 250ms timer beside the TurnsOverlay countdown.
|
|
*/
|
|
const now = useSharedClock(1000, isTurnsMode);
|
|
|
|
const turnInfo = roverId ? turnQueues?.[roverId] || null : null;
|
|
const activeDriverId = roverId ? activeDrivers?.[roverId] || null : null;
|
|
const isActiveDriver = Boolean(socketId && activeDriverId === socketId);
|
|
const nextDriverId = useMemo(() => {
|
|
const queue = turnInfo?.queue || [];
|
|
if (!queue.length || !turnInfo?.current || queue.length <= 1) return null;
|
|
const idx = queue.findIndex((id) => id === turnInfo.current);
|
|
if (idx === -1) return queue[0] || null;
|
|
return queue[(idx + 1) % queue.length] || null;
|
|
}, [turnInfo]);
|
|
const isNextDriver = Boolean(socketId && nextDriverId === socketId);
|
|
const deadline = turnInfo?.deadline || null;
|
|
const msUntilTurn = deadline ? deadline - now : null;
|
|
/*
|
|
The server evaluates the global controllable-user threshold because that
|
|
same decision is enforced in socket video tokens and MediaMTX auth. This
|
|
hook only mirrors the active result so the browser does not request live
|
|
video when snapshots are already the authoritative non-turn outcome.
|
|
*/
|
|
const shouldUsePreviewByLoad = nonTurnSnapshotsActive && isTurnsMode;
|
|
const isPreSwitchWindow =
|
|
isTurnsMode && isNextDriver && msUntilTurn != null && msUntilTurn <= 5000 && msUntilTurn > 0;
|
|
const showNotTurnNotice = isTurnsMode && !isActiveDriver;
|
|
const forceSnapshotByTurnPolicy = showNotTurnNotice && !isPreSwitchWindow && shouldUsePreviewByLoad;
|
|
|
|
return forceSnapshotByTurnPolicy ? 'snapshot' : null;
|
|
}
|