mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-17 01:50:47 -04:00
tryina make mini not reload stuff..
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
@@ -78,7 +78,7 @@
|
|||||||
<script defer src="https://analytics.otter.land/script.js" data-website-id="82dd56a5-db44-4279-bd1e-a4d9fee39af7" data-domains="rover.otter.land"></script>
|
<script defer src="https://analytics.otter.land/script.js" data-website-id="82dd56a5-db44-4279-bd1e-a4d9fee39af7" data-domains="rover.otter.land"></script>
|
||||||
<script defer src="https://analytics.otter.land/recorder.js" data-website-id="82dd56a5-db44-4279-bd1e-a4d9fee39af7" data-domains="rover.otter.land" data-sample-rate="0.15" data-mask-level="moderate" data-max-duration="300000"></script>
|
<script defer src="https://analytics.otter.land/recorder.js" data-website-id="82dd56a5-db44-4279-bd1e-a4d9fee39af7" data-domains="rover.otter.land" data-sample-rate="0.15" data-mask-level="moderate" data-max-duration="300000"></script>
|
||||||
<title>Roomba Rover</title>
|
<title>Roomba Rover</title>
|
||||||
<script type="module" crossorigin src="/assets/index-BOymxzTs.js"></script>
|
<script type="module" crossorigin src="/assets/index-H6WndPjR.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-tRV3nWgE.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-tRV3nWgE.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -170,18 +170,21 @@ export default function MiniSummaryContent() {
|
|||||||
() => roster.filter((rover) => activeDrivers[rover.id]),
|
() => roster.filter((rover) => activeDrivers[rover.id]),
|
||||||
[roster, activeDrivers],
|
[roster, activeDrivers],
|
||||||
);
|
);
|
||||||
const snapshotRoster = driverRoster.length ? driverRoster : roster;
|
const mediaRovers = useMemo(
|
||||||
|
() => roster.filter((rover) => rover?.id),
|
||||||
|
[roster],
|
||||||
|
);
|
||||||
|
|
||||||
const snapshotFeeds = useRoverSnapshots(
|
const snapshotFeeds = useRoverSnapshots(
|
||||||
snapshotRoster.map((rover) => rover.id),
|
mediaRovers.map((rover) => rover.id),
|
||||||
{ enabled: !inLockdown && !canSpectateVideo, version: session?.mode },
|
{ enabled: !inLockdown && !canSpectateVideo, version: session?.mode },
|
||||||
);
|
);
|
||||||
const videoEntries = useMemo(
|
const videoEntries = useMemo(
|
||||||
() =>
|
() =>
|
||||||
canSpectateVideo
|
canSpectateVideo
|
||||||
? snapshotRoster.map((rover) => ({ type: 'rover', id: rover.id, key: rover.id }))
|
? mediaRovers.map((rover) => ({ type: 'rover', id: rover.id, key: rover.id }))
|
||||||
: [],
|
: [],
|
||||||
[canSpectateVideo, snapshotRoster],
|
[canSpectateVideo, mediaRovers],
|
||||||
);
|
);
|
||||||
const videoSources = useVideoRequests(videoEntries, {
|
const videoSources = useVideoRequests(videoEntries, {
|
||||||
enabled: !inLockdown && canSpectateVideo,
|
enabled: !inLockdown && canSpectateVideo,
|
||||||
@@ -198,30 +201,18 @@ export default function MiniSummaryContent() {
|
|||||||
);
|
);
|
||||||
const audioSources = useVideoRequests(audioEntries, { enabled: !inLockdown, version: session?.mode });
|
const audioSources = useVideoRequests(audioEntries, { enabled: !inLockdown, version: session?.mode });
|
||||||
|
|
||||||
const roverPool = useMemo(() => {
|
|
||||||
if (!driverRoster.length) return [];
|
|
||||||
if (!canSpectateVideo) {
|
|
||||||
const withSnapshot = driverRoster.filter((rover) => snapshotFeeds[rover.id]?.objectUrl);
|
|
||||||
return withSnapshot.length ? withSnapshot : driverRoster;
|
|
||||||
}
|
|
||||||
const withVideo = driverRoster.filter((rover) => {
|
|
||||||
const sessionInfo = videoSources[rover.id];
|
|
||||||
return sessionInfo?.url && !sessionInfo?.error;
|
|
||||||
});
|
|
||||||
return withVideo.length ? withVideo : driverRoster;
|
|
||||||
}, [driverRoster, snapshotFeeds, videoSources, canSpectateVideo]);
|
|
||||||
|
|
||||||
const rotationPool = useMemo(() => {
|
const rotationPool = useMemo(() => {
|
||||||
/*
|
/*
|
||||||
PTZ is deliberately added only to the active-driver rotation. The branch
|
Rotation membership is intentionally based on human-controlled sources,
|
||||||
below that shows every rover side-by-side when nobody is driving remains
|
not on WHEP response timing. The mounted media players below are a
|
||||||
rover-only, because that view is a roster/status fallback rather than a
|
separate full-roster list, so a video token refresh, snapshot arrival, or
|
||||||
source carousel.
|
active-driver update changes which already-warm layer is visible instead
|
||||||
|
of tearing down the player components themselves.
|
||||||
*/
|
*/
|
||||||
const entries = roverPool.map((rover) => ({ type: 'rover', rover }));
|
const entries = driverRoster.map((rover) => ({ type: 'rover', rover }));
|
||||||
if (hasActivePtzOperator) entries.push({ type: 'ptz' });
|
if (hasActivePtzOperator) entries.push({ type: 'ptz' });
|
||||||
return entries;
|
return entries;
|
||||||
}, [hasActivePtzOperator, roverPool]);
|
}, [driverRoster, hasActivePtzOperator]);
|
||||||
|
|
||||||
const rotationKey = useMemo(
|
const rotationKey = useMemo(
|
||||||
() =>
|
() =>
|
||||||
@@ -251,6 +242,8 @@ export default function MiniSummaryContent() {
|
|||||||
const activeAudio = activeRover ? audioSources[`${activeRover.id}-audio`] || null : null;
|
const activeAudio = activeRover ? audioSources[`${activeRover.id}-audio`] || null : null;
|
||||||
const activeFrame = activeRover ? frames[activeRover.id] || null : null;
|
const activeFrame = activeRover ? frames[activeRover.id] || null : null;
|
||||||
const driverLabel = activeRover ? formatDriverLabel({ roverId: activeRover.id, session }) : null;
|
const driverLabel = activeRover ? formatDriverLabel({ roverId: activeRover.id, session }) : null;
|
||||||
|
const showSideBySideFallback = !driverRoster.length && !hasActivePtzOperator;
|
||||||
|
const hasMountedMediaSources = Boolean(mediaRovers.length || ptz?.enabled);
|
||||||
|
|
||||||
if (inLockdown) {
|
if (inLockdown) {
|
||||||
return (
|
return (
|
||||||
@@ -263,10 +256,10 @@ export default function MiniSummaryContent() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!driverRoster.length && !hasActivePtzOperator) {
|
return (
|
||||||
return (
|
<div className="relative flex h-screen w-screen overflow-hidden bg-black text-slate-100">
|
||||||
<div className="relative flex h-screen w-screen overflow-hidden bg-black text-slate-100">
|
{showSideBySideFallback ? (
|
||||||
<section className="flex h-full w-full gap-x-3 bg-slate-900 px-0">
|
<section className="absolute inset-0 z-30 flex h-full w-full gap-x-3 bg-slate-900 px-0">
|
||||||
{roster.length ? (
|
{roster.length ? (
|
||||||
roster.map((rover) => (
|
roster.map((rover) => (
|
||||||
<InfoColumn
|
<InfoColumn
|
||||||
@@ -287,14 +280,16 @@ export default function MiniSummaryContent() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</section>
|
</section>
|
||||||
</div>
|
) : null}
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="relative flex h-screen w-screen overflow-hidden bg-black text-slate-100">
|
|
||||||
<section
|
<section
|
||||||
className="relative flex h-full shrink-0 items-center justify-start overflow-hidden bg-black"
|
className={`relative flex h-full shrink-0 items-center justify-start overflow-hidden bg-black ${
|
||||||
|
/*
|
||||||
|
The no-driver view is still visually the old side-by-side roster,
|
||||||
|
but keeping this carousel layer mounted behind it prevents every
|
||||||
|
rover WHEP player from cold-starting when the first driver appears.
|
||||||
|
*/
|
||||||
|
showSideBySideFallback ? 'opacity-0 pointer-events-none' : ''
|
||||||
|
}`}
|
||||||
style={{
|
style={{
|
||||||
/*
|
/*
|
||||||
Rover cameras are framed by the existing 4:3 viewport helper below,
|
Rover cameras are framed by the existing 4:3 viewport helper below,
|
||||||
@@ -310,7 +305,7 @@ export default function MiniSummaryContent() {
|
|||||||
<div className="flex h-full w-full items-center justify-center text-sm text-slate-500">
|
<div className="flex h-full w-full items-center justify-center text-sm text-slate-500">
|
||||||
Switching to spectator…
|
Switching to spectator…
|
||||||
</div>
|
</div>
|
||||||
) : activeEntry ? (
|
) : hasMountedMediaSources ? (
|
||||||
<div className="relative h-full w-full overflow-hidden bg-black">
|
<div className="relative h-full w-full overflow-hidden bg-black">
|
||||||
{/*
|
{/*
|
||||||
Keep every mini media source mounted while the carousel rotates.
|
Keep every mini media source mounted while the carousel rotates.
|
||||||
@@ -318,9 +313,7 @@ export default function MiniSummaryContent() {
|
|||||||
blank gap, so inactive sources are hidden with opacity instead of
|
blank gap, so inactive sources are hidden with opacity instead of
|
||||||
being removed from React's tree and forced to reconnect later.
|
being removed from React's tree and forced to reconnect later.
|
||||||
*/}
|
*/}
|
||||||
{rotationPool.map((entry) => {
|
{mediaRovers.map((rover) => {
|
||||||
if (entry.type !== 'rover') return null;
|
|
||||||
const rover = entry.rover;
|
|
||||||
const isActive = activeRover?.id === rover.id;
|
const isActive = activeRover?.id === rover.id;
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -330,7 +323,7 @@ export default function MiniSummaryContent() {
|
|||||||
<FitViewportFrame>
|
<FitViewportFrame>
|
||||||
{canSpectateVideo ? (
|
{canSpectateVideo ? (
|
||||||
<RoverMediaPlayer
|
<RoverMediaPlayer
|
||||||
sessionInfo={videoSources[rover.id] || null}
|
roverId={rover.id}
|
||||||
videoMode="whep"
|
videoMode="whep"
|
||||||
snapshotFeed={null}
|
snapshotFeed={null}
|
||||||
audioSessionInfo={isActive ? activeAudio : null}
|
audioSessionInfo={isActive ? activeAudio : null}
|
||||||
@@ -353,7 +346,7 @@ export default function MiniSummaryContent() {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
{hasActivePtzOperator ? (
|
{ptz?.enabled ? (
|
||||||
<div className={`absolute inset-0 ${activePtz ? 'opacity-100' : 'opacity-0 pointer-events-none'}`}>
|
<div className={`absolute inset-0 ${activePtz ? 'opacity-100' : 'opacity-0 pointer-events-none'}`}>
|
||||||
{/*
|
{/*
|
||||||
PTZ bypasses FitViewportFrame because that helper intentionally
|
PTZ bypasses FitViewportFrame because that helper intentionally
|
||||||
@@ -363,7 +356,7 @@ export default function MiniSummaryContent() {
|
|||||||
when PTZ becomes active.
|
when PTZ becomes active.
|
||||||
*/}
|
*/}
|
||||||
<PtzLiveVideo
|
<PtzLiveVideo
|
||||||
enabled
|
enabled={!inLockdown}
|
||||||
startMuted
|
startMuted
|
||||||
className="relative h-full w-full bg-black"
|
className="relative h-full w-full bg-black"
|
||||||
videoClassName="h-full w-full object-cover"
|
videoClassName="h-full w-full object-cover"
|
||||||
@@ -377,7 +370,11 @@ export default function MiniSummaryContent() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</section>
|
</section>
|
||||||
<aside className="flex h-full min-w-0 flex-1 flex-col border-l border-slate-800/60 bg-black">
|
<aside
|
||||||
|
className={`flex h-full min-w-0 flex-1 flex-col border-l border-slate-800/60 bg-black ${
|
||||||
|
showSideBySideFallback ? 'opacity-0 pointer-events-none' : ''
|
||||||
|
}`}
|
||||||
|
>
|
||||||
{activePtz ? (
|
{activePtz ? (
|
||||||
<MiniPtzUserColumn label={ptzOperatorLabel} />
|
<MiniPtzUserColumn label={ptzOperatorLabel} />
|
||||||
) : activeRover ? (
|
) : activeRover ? (
|
||||||
|
|||||||
Reference in New Issue
Block a user