import { useEffect, useMemo, useState } from 'react'; import { useSession } from './context/SessionContext.jsx'; import { useTelemetryFrame } from './context/TelemetryContext.jsx'; import TelemetryPanel from './components/TelemetryPanel.jsx'; import VideoTile from './components/VideoTile.jsx'; import DrivePanel from './components/DrivePanel.jsx'; import AlertFeed from './components/AlertFeed.jsx'; import AdminPanel from './components/AdminPanel.jsx'; import MobileControls, { MobileJoystick, AuxMotorControls } from './components/MobileControls.jsx'; import { DriveControlProvider } from './context/DriveControlContext.jsx'; import { useVideoRequests } from './hooks/useVideoRequests.js'; function RoomCameraPanel() { return (

Room camera

Feed placeholder. Wire upcoming room cam here.

); } function useLayoutMode() { const [mode, setMode] = useState(() => { if (typeof window === 'undefined') return 'desktop'; return window.innerWidth >= 1024 ? 'desktop' : window.innerWidth > window.innerHeight ? 'mobile-landscape' : 'mobile-portrait'; }); useEffect(() => { function updateMode() { if (typeof window === 'undefined') return; const { innerWidth, innerHeight } = window; if (innerWidth >= 1024) { setMode('desktop'); } else if (innerWidth > innerHeight) { setMode('mobile-landscape'); } else { setMode('mobile-portrait'); } } updateMode(); window.addEventListener('resize', updateMode); return () => window.removeEventListener('resize', updateMode); }, []); return mode; } function LogPanel() { const { logs } = useSession(); return (
Server logs {logs.length}
{logs.length === 0 ? (

No logs yet.

) : ( logs .slice() .reverse() .map((entry) => (
{entry.timestamp}{' '} [{entry.level}]{' '} {entry.label && [{entry.label}]}{' '} {entry.message}
)) )}
); } function DriverVideoPanel() { const { session } = useSession(); const roverId = session?.assignment?.roverId; const sources = useVideoRequests(roverId ? [roverId] : []); const info = roverId ? sources[roverId] : null; const frame = useTelemetryFrame(roverId); const batteryConfig = useMemo(() => { if (!roverId || !session?.roster) return null; const record = session.roster.find((item) => String(item.id) === String(roverId)); return record?.battery ?? null; }, [session?.roster, roverId]); return (
{roverId ? (
) : (

Assign a rover to view the video feed.

)}
); } function AuthPanel() { const { login, setRole } = useSession(); const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); const [loading, setLoading] = useState(false); async function handleLogin(event) { event.preventDefault(); setLoading(true); try { await login(username, password); setUsername(''); setPassword(''); } catch (err) { alert(err.message); } finally { setLoading(false); } } return (

Admin login

setUsername(e.target.value)} /> setPassword(e.target.value)} />
); } function DesktopLayout() { return (
); } function MobilePortraitLayout() { return (
); } function MobileLandscapeLayout() { return (
); } function App() { const layout = useLayoutMode(); const renderedLayout = layout === 'desktop' ? : layout === 'mobile-landscape' ? : ; return (
{renderedLayout}
); } export default App;