rover descriptions

This commit is contained in:
legop3
2026-05-13 02:06:47 -04:00
parent fb996469d8
commit 1b296d5010
19 changed files with 211 additions and 134 deletions
@@ -183,6 +183,7 @@ export default function DriverVideoPanel({ layoutFormat = 'desktop' }) {
snapshotFeed={snapshotFeed}
audioSessionInfo={audioInfo}
label={roverLabel}
roverDescription={batteryRecord?.description}
roverColor={batteryRecord?.color || null}
telemetryFrame={frame}
batteryConfig={batteryConfig}
@@ -0,0 +1,56 @@
import { useEffect, useState } from 'react';
const LARGE_VISIBLE_MS = 3500;
const LARGE_FADE_MS = 700;
export default function RoverDescriptionOverlay({
description,
variant = 'default',
mobileHud = false,
displayKey = '',
}) {
const [largeVisible, setLargeVisible] = useState(false);
const [largeFading, setLargeFading] = useState(false);
useEffect(() => {
if (variant !== 'default' || !description) {
setLargeVisible(false);
setLargeFading(false);
return undefined;
}
setLargeVisible(true);
setLargeFading(false);
const fadeTimer = setTimeout(() => setLargeFading(true), LARGE_VISIBLE_MS);
const hideTimer = setTimeout(() => setLargeVisible(false), LARGE_VISIBLE_MS + LARGE_FADE_MS);
return () => {
clearTimeout(fadeTimer);
clearTimeout(hideTimer);
};
}, [description, displayKey, variant]);
if (!description) return null;
if (variant === 'spectator') {
return (
<div className="pointer-events-none absolute inset-x-0 top-1 z-50 flex justify-center">
<div className="surface max-w-[92%] border border-slate-600/80 px-1 py-0.5 text-center text-[0.62rem] leading-tight text-slate-100 shadow-lg">
{description}
</div>
</div>
);
}
if (variant !== 'default' || !largeVisible) return null;
return (
<div className="pointer-events-none absolute inset-x-0 top-2 z-50 flex justify-center">
<div
className={`surface max-w-[94%] border border-slate-500/85 px-2 py-1 text-center font-semibold text-slate-100 shadow-2xl transition-opacity duration-700 ${
largeFading ? 'opacity-0' : 'opacity-100'
} ${mobileHud ? 'text-[1rem] leading-tight' : 'text-[1.5rem] leading-tight'}`}
>
{description}
</div>
</div>
);
}
+11
View File
@@ -12,6 +12,7 @@ import BatteryBar from '../BatteryBar/index.jsx';
import { buildBatteryVisual } from '../../lib/battery.js';
import TurnCueOverlay from './TurnCueOverlay.jsx';
import HudOverlay from './HudOverlay.jsx';
import RoverDescriptionOverlay from './RoverDescriptionOverlay.jsx';
import OvercurrentOverlay from './OvercurrentOverlay.jsx';
import LowBatteryOverlay from './LowBatteryOverlay.jsx';
import LightBumpBars from './LightBumpBars.jsx';
@@ -31,6 +32,7 @@ export default function VideoTile({
snapshotFeed = null,
qualityNotice = null,
label,
roverDescription = null,
roverColor = null,
forceMute = false,
telemetryFrame,
@@ -594,6 +596,7 @@ export default function VideoTile({
: audioStatus;
const showVerticalBattery = hudVariant === 'spectator';
const noHud = hudVariant === 'none';
const descriptionDisplayKey = `${label || ''}::${roverDescription || ''}`;
return (
<div className={`flex flex-col gap-0.5 ${fitParent ? 'h-full' : ''}`}>
@@ -631,6 +634,14 @@ export default function VideoTile({
idleSkipSeconds={idleSkipSeconds}
/>
) : null}
{!noHud ? (
<RoverDescriptionOverlay
description={roverDescription}
variant={hudVariant}
mobileHud={mobileHud}
displayKey={descriptionDisplayKey}
/>
) : null}
{!noHud ? (
<HudOverlay
sensors={sensors}
@@ -15,6 +15,7 @@ export default function RoverSpectatorCard({ rover, frame, sessionInfo, videoMod
snapshotFeed={snapshotFeed}
audioSessionInfo={audioInfo}
label={rover.name}
roverDescription={rover.description}
roverColor={rover.color || null}
telemetryFrame={frame}
batteryConfig={rover.battery}