mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-17 01:50:47 -04:00
rarare
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -11,7 +11,7 @@
|
|||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||||
<meta name="apple-mobile-web-app-title" content="Roomba Rover" />
|
<meta name="apple-mobile-web-app-title" content="Roomba Rover" />
|
||||||
<title>Roomba Rover</title>
|
<title>Roomba Rover</title>
|
||||||
<script type="module" crossorigin src="/assets/index-CI46Zplu.js"></script>
|
<script type="module" crossorigin src="/assets/index-Cwxivvoc.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-DCGeKtS8.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-DCGeKtS8.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useSessionSelector } from '../../context/SessionContext.jsx';
|
import { useSessionSelector } from '../../context/SessionContext.jsx';
|
||||||
import RoverMediaPlayer from '../RoverMediaPlayer/index.jsx';
|
import RoverMediaPlayer from '../RoverMediaPlayer/index.jsx';
|
||||||
import { useControlSystem } from '../../controls/index.js';
|
import { useControlSystem } from '../../controls/index.js';
|
||||||
|
import { useDriverVideoModePolicy } from '../../hooks/useDriverVideoModePolicy.js';
|
||||||
import TurnsOverlay from '../HudOverlays/TurnsOverlay/index.jsx';
|
import TurnsOverlay from '../HudOverlays/TurnsOverlay/index.jsx';
|
||||||
import HudOverlay from '../HudOverlays/HudOverlay/index.jsx';
|
import HudOverlay from '../HudOverlays/HudOverlay/index.jsx';
|
||||||
import RoverDescriptionOverlay from '../HudOverlays/RoverDescriptionOverlay/index.jsx';
|
import RoverDescriptionOverlay from '../HudOverlays/RoverDescriptionOverlay/index.jsx';
|
||||||
@@ -11,6 +12,7 @@ import HudChatInput from '../HudOverlays/HudChatInput/index.jsx';
|
|||||||
|
|
||||||
export default function DriverVideo({ layoutFormat = 'desktop' }) {
|
export default function DriverVideo({ layoutFormat = 'desktop' }) {
|
||||||
const roverId = useSessionSelector((state) => state.session?.assignment?.roverId ?? null);
|
const roverId = useSessionSelector((state) => state.session?.assignment?.roverId ?? null);
|
||||||
|
const videoMode = useDriverVideoModePolicy(roverId);
|
||||||
const {
|
const {
|
||||||
state: { lastControlIntentAt },
|
state: { lastControlIntentAt },
|
||||||
} = useControlSystem();
|
} = useControlSystem();
|
||||||
@@ -35,7 +37,7 @@ export default function DriverVideo({ layoutFormat = 'desktop' }) {
|
|||||||
<section className="panel">
|
<section className="panel">
|
||||||
<div className="flex flex-col gap-0.5">
|
<div className="flex flex-col gap-0.5">
|
||||||
<div className="relative w-full overflow-hidden bg-black aspect-[4/3]">
|
<div className="relative w-full overflow-hidden bg-black aspect-[4/3]">
|
||||||
<RoverMediaPlayer />
|
<RoverMediaPlayer roverId={roverId} videoMode={videoMode} />
|
||||||
<TurnsOverlay mobileHud={mobileHud} />
|
<TurnsOverlay mobileHud={mobileHud} />
|
||||||
<RoverDescriptionOverlay
|
<RoverDescriptionOverlay
|
||||||
variant="default"
|
variant="default"
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
|
import { useSessionSelector } from '../context/SessionContext.jsx';
|
||||||
|
|
||||||
|
export function useDriverVideoModePolicy(roverId) {
|
||||||
|
const mode = useSessionSelector((state) => state.session?.mode || null);
|
||||||
|
const roster = useSessionSelector((state) => state.session?.roster ?? []);
|
||||||
|
const users = useSessionSelector((state) => state.session?.users ?? []);
|
||||||
|
const turnQueues = useSessionSelector((state) => state.session?.turnQueues ?? {});
|
||||||
|
const socketId = useSessionSelector((state) => state.session?.socketId || null);
|
||||||
|
const activeDrivers = useSessionSelector((state) => state.session?.activeDrivers ?? {});
|
||||||
|
const [now, setNow] = useState(() => Date.now());
|
||||||
|
|
||||||
|
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?.queue, turnInfo?.current]);
|
||||||
|
const isNextDriver = Boolean(socketId && nextDriverId === socketId);
|
||||||
|
const deadline = turnInfo?.deadline || null;
|
||||||
|
const msUntilTurn = deadline ? deadline - now : null;
|
||||||
|
const isTurnsMode = mode === 'turns';
|
||||||
|
const totalRovers = roster.length;
|
||||||
|
const totalDrivers = useMemo(() => {
|
||||||
|
const unique = new Set();
|
||||||
|
users.forEach((entry) => {
|
||||||
|
const role = String(entry?.role || '');
|
||||||
|
if (role === 'spectator') return;
|
||||||
|
const turnRoverId = String(entry?.roverId || '').trim();
|
||||||
|
const turnSocketId = String(entry?.socketId || '').trim();
|
||||||
|
if (!turnRoverId || !turnSocketId) return;
|
||||||
|
unique.add(turnSocketId);
|
||||||
|
});
|
||||||
|
return unique.size;
|
||||||
|
}, [users]);
|
||||||
|
const shouldUsePreviewByLoad = isTurnsMode && totalDrivers > totalRovers;
|
||||||
|
const isPreSwitchWindow =
|
||||||
|
isTurnsMode && isNextDriver && msUntilTurn != null && msUntilTurn <= 5000 && msUntilTurn > 0;
|
||||||
|
const showNotTurnNotice = isTurnsMode && !isActiveDriver;
|
||||||
|
const forceSnapshotByTurnPolicy = showNotTurnNotice && !isPreSwitchWindow && shouldUsePreviewByLoad;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (mode !== 'turns') return undefined;
|
||||||
|
const timer = setInterval(() => setNow(Date.now()), 250);
|
||||||
|
return () => clearInterval(timer);
|
||||||
|
}, [mode]);
|
||||||
|
|
||||||
|
return forceSnapshotByTurnPolicy ? 'snapshot' : null;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user