import RoomCameraPanel from './RoomCameraPanel.jsx'; import HomeAssistantControls from './HomeAssistantControls.jsx'; import SettingsPanel from './SettingsPanel.jsx'; import HelpPanel from './HelpPanel.jsx'; import ChatPanel from './ChatPanel.jsx'; import { LinkButtonsPanel, NicknameEntryPanel } from './UserListPanel.jsx'; import ReplaySourcesPanel from './ReplaySourcesPanel.jsx'; import Tabs, { Tab, TabList, TabPanel, TabPanels } from './Tabs.jsx'; import TopDownMap from './TopDownMap.jsx'; import DriveDockAction, { useDriveDockState } from './DriveDockAction.jsx'; import { useTelemetryFrame } from '../context/TelemetryContext.jsx'; import { useControlSystem } from '../controls/index.js'; import RoverQueuesPanel from './RoverQueuesPanel.jsx'; import RawUserPilePanel from './RawUserPilePanel.jsx'; import { formatKeyLabel } from '../controls/keymapUtils.js'; import NightVisionControl from './NightVisionControl.jsx'; import HornControl from './HornControl.jsx'; import CameraTiltControl from './CameraTiltControl.jsx'; import VipPanel from './VipPanel.jsx'; import { useSessionSelector } from '../context/SessionContext.jsx'; import { useSettingsNamespace } from '../settings/index.js'; import ButtonBoxPanel from './ButtonBoxPanel.jsx'; function TopDownMapPanel() { const { state: { roverId }, } = useControlSystem(); const frame = useTelemetryFrame(roverId); const sensors = frame?.sensors || {}; return (
); } function DriveDockPanel() { const { state: { roverId, keymap, camera, horn }, pipeline, actions: { setServoAngle, setNightVision, startHorn, stopHorn }, } = useControlSystem(); 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}
); } export default function RightPaneTabs({ layout, onOpenHelpOverlay }) { const session = useSessionSelector((state) => state.session); const { state: controlState } = useControlSystem(); const { value: vipAudio } = useSettingsNamespace('vipAudio', { openMicEnabled: false, pttMode: 'live' }); const vipDotClass = session?.isVerified ? 'bg-emerald-400' : 'bg-red-600'; const ownRoverId = String(session?.assignment?.roverId || '').trim(); const ownAudioForward = ownRoverId ? session?.audioForward?.[ownRoverId] : null; const pttActive = Boolean(controlState?.mic?.pttActive); const openMicEnabled = Boolean(vipAudio?.openMicEnabled); const pttMode = vipAudio?.pttMode === 'clip' ? 'clip' : 'live'; const vipMicActive = Boolean( ownRoverId && session?.isVerified && (pttMode === 'clip' ? pttActive : (openMicEnabled || pttActive)), ); const vipClipPlaying = Boolean( ownRoverId && session?.isVerified && pttMode === 'clip' && ownAudioForward?.source === 'upload' && ownAudioForward?.state === 'playing', ); return (
Controls VIP Help Settings
); }