import { useMemo, useState } from 'react'; import { useSession } from '../context/SessionContext.jsx'; import { useTelemetryFrame } from '../context/TelemetryContext.jsx'; import { useControlSystem } from '../controls/index.js'; import { formatKeyLabel } from '../controls/keymapUtils.js'; import TopDownMap from './TopDownMap.jsx'; import RoverRoster from './RoverRoster.jsx'; import DriveDockAction, { useDriveDockState } from './DriveDockAction.jsx'; import NightVisionControl from './NightVisionControl.jsx'; import HornControl from './HornControl.jsx'; import CameraTiltControl from './CameraTiltControl.jsx'; export function RoverRosterPanel({ title = 'Rovers' }) { const { session, requestControl } = useSession(); const [pending, setPending] = useState({}); const canRequest = useMemo(() => session?.role && session.role !== 'spectator', [session?.role]); async function handleRequest(targetRoverId) { if (!targetRoverId) return; setPending((prev) => ({ ...prev, [targetRoverId]: true })); try { await requestControl(targetRoverId); } catch (err) { alert(err.message); } finally { setPending((prev) => ({ ...prev, [targetRoverId]: false })); } } return ( canRequest ? ( ) : null } /> ); } export default function ControlSummary() { const { state: { roverId, keymap, camera, horn }, pipeline, actions: { setServoAngle, setNightVision, startHorn, stopHorn }, } = useControlSystem(); const frame = useTelemetryFrame(roverId); const sensors = frame?.sensors || {}; const driveDockState = useDriveDockState(roverId); const hideInlineControls = driveDockState.docked && !driveDockState.driving; const config = camera?.config; const cameraEnabled = Boolean(roverId && camera?.enabled && config); const nightVisionAvailable = Boolean(roverId && pipeline?.nightVision); const nightVisionState = pipeline?.nightVisionState; const hornAvailable = Boolean(roverId && pipeline?.horn); const hornBlocked = horn?.overheated; const min = typeof config?.minAngle === 'number' ? config.minAngle : -30; const max = typeof config?.maxAngle === 'number' ? config.maxAngle : 30; const value = typeof camera?.angle === 'number' ? camera.angle : typeof config?.homeAngle === 'number' ? config.homeAngle : (min + max) / 2; const nightVisionLabel = formatKeyLabel(keymap?.nightVisionToggle?.[0]); const hornLabel = formatKeyLabel(keymap?.hornHonk?.[0]); const upLabel = formatKeyLabel(keymap?.cameraUp?.[0]); const downLabel = formatKeyLabel(keymap?.cameraDown?.[0]); return (
{!hideInlineControls ? (
{nightVisionAvailable && ( )} {hornAvailable && ( )} {cameraEnabled && ( )}
) : null}
); }