import { useCallback, useEffect, useMemo, useState } from 'react'; import TelemetryPanel from './components/TelemetryPanel.jsx'; import ReplaySourcesPanel from './components/ReplaySourcesPanel.jsx'; import AlertFeed from './components/AlertFeed.jsx'; import MobileControls, { MobileLandscapeAuxColumn, MobileLandscapeControlColumn, } from './components/MobileControls.jsx'; import { ControlSystemProvider, KeyboardInputManager, GamepadInputManager } from './controls/index.js'; import { SettingsProvider } from './settings/index.js'; import RoomCameraPanel from './components/RoomCameraPanel.jsx'; import LogPanel from './components/LogPanel.jsx'; import DriverVideoPanel from './components/DriverVideoPanel.jsx'; import RightPaneTabs from './components/RightPaneTabs.jsx'; import ModeGateOverlay from './components/ModeGateOverlay.jsx'; import HomeAssistantControls from './components/HomeAssistantControls.jsx'; import TurnAlertListener from './components/TurnAlertListener.jsx'; import RawUserPilePanel from './components/RawUserPilePanel.jsx'; import ChatPanel from './components/ChatPanel.jsx'; import FullscreenPrompt from './components/FullscreenPrompt.jsx'; import { useFullscreenPrompt } from './hooks/useFullscreenPrompt.js'; import { useSettingsNamespace } from './settings/index.js'; import HelpOverlay from './components/HelpOverlay.jsx'; import HelpPanel from './components/HelpPanel.jsx'; import SettingsPanel from './components/SettingsPanel.jsx'; import Tabs, { Tab, TabList, TabPanel, TabPanels } from './components/Tabs.jsx'; import useDefaultNickname from './hooks/useDefaultNickname.js'; import CommunityGoalBanner from './components/CommunityGoalBanner.jsx'; import RoverQueuesPanel from './components/RoverQueuesPanel.jsx'; import BannedOverlay from './components/BannedOverlay.jsx'; 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 DesktopLayout({ layout, onOpenHelpOverlay }) { return (
{/* */}
); } function MobileFeatureTabs({ layout, onOpenHelpOverlay, roomPanelId, showTelemetry = true, }) { return (
Chat Room Controls Help Settings
{/* {showTelemetry ? : null} */}
); } function MobilePortraitLayout({ onOpenHelpOverlay }) { return (
{/* */}
); } function MobileLandscapeLayout({ onOpenHelpOverlay }) { return (
{/* */}
); } function App() { const layout = useLayoutMode(); const isDesktop = layout === 'desktop'; const fullscreen = useFullscreenPrompt(layout); return (
); } function AppWithProviders({ layout, isDesktop, fullscreen }) { useDefaultNickname(); const { visible: fullscreenVisible, mode: fullscreenMode, enterFullscreen, dismiss, } = fullscreen; const { value: helpSettings, status: helpStatus, save: saveHelpSettings, } = useSettingsNamespace('help', { showOnLoad: true }); const [helpVisible, setHelpVisible] = useState(false); useEffect(() => { if (helpStatus === 'ready') { setHelpVisible(helpSettings?.showOnLoad !== false); } }, [helpStatus, helpSettings?.showOnLoad]); const openHelp = useCallback(() => setHelpVisible(true), []); const closeHelp = useCallback(() => setHelpVisible(false), []); const setShowOnLoad = useCallback( (enabled) => { const next = Boolean(enabled); saveHelpSettings((current) => ({ ...(current ?? {}), showOnLoad: next })); if (!next) { setHelpVisible(false); } }, [saveHelpSettings], ); const renderedLayout = useMemo( () => isDesktop ? : layout === 'mobile-landscape' ? : , [isDesktop, layout, openHelp], ); return (
{!isDesktop ? : null} {renderedLayout}
); } export default App;