mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 09:31:20 -04:00
goop converter
This commit is contained in:
+23
-23
@@ -1,7 +1,7 @@
|
||||
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 TelemetryPanel from './components/TelemetryPanel/index.jsx';
|
||||
import ReplaySourcesPanel from './components/ReplaySourcesPanel/index.jsx';
|
||||
import AlertFeed from './components/AlertFeed/index.jsx';
|
||||
import MobileControls, {
|
||||
MobileActionsColumn,
|
||||
MobileDriveColumn,
|
||||
@@ -12,31 +12,31 @@ import {
|
||||
GamepadInputManager,
|
||||
useControlSystem,
|
||||
} from './controls/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 FloatingFullscreenButton from './components/FloatingFullscreenButton.jsx';
|
||||
import RoomCameraPanel from './components/RoomCameraPanel/index.jsx';
|
||||
import LogPanel from './components/LogPanel/index.jsx';
|
||||
import DriverVideoPanel from './components/DriverVideoPanel/index.jsx';
|
||||
import RightPaneTabs from './components/RightPaneTabs/index.jsx';
|
||||
import ModeGateOverlay from './components/ModeGateOverlay/index.jsx';
|
||||
import HomeAssistantControls from './components/HomeAssistantControls/index.jsx';
|
||||
import TurnAlertListener from './components/TurnAlertListener/index.jsx';
|
||||
import RawUserPilePanel from './components/RawUserPilePanel/index.jsx';
|
||||
import ChatPanel from './components/ChatPanel/index.jsx';
|
||||
import FullscreenPrompt from './components/FullscreenPrompt/index.jsx';
|
||||
import FloatingFullscreenButton from './components/FloatingFullscreenButton/index.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 HelpOverlay from './components/HelpOverlay/index.jsx';
|
||||
import HelpPanel from './components/HelpPanel/index.jsx';
|
||||
import SettingsPanel from './components/SettingsPanel/index.jsx';
|
||||
import Tabs, { Tab, TabList, TabPanel, TabPanels } from './components/Tabs/index.jsx';
|
||||
import useDefaultNickname from './hooks/useDefaultNickname.js';
|
||||
import useUserIdentitySync from './hooks/useUserIdentitySync.js';
|
||||
import CommunityGoalBanner from './components/CommunityGoalBanner.jsx';
|
||||
import RoverQueuesPanel from './components/RoverQueuesPanel.jsx';
|
||||
import VipPanel from './components/VipPanel.jsx';
|
||||
import CommunityGoalBanner from './components/CommunityGoalBanner/index.jsx';
|
||||
import RoverQueuesPanel from './components/RoverQueuesPanel/index.jsx';
|
||||
import VipPanel from './components/VipPanel/index.jsx';
|
||||
import { useSessionSelector } from './context/SessionContext.jsx';
|
||||
import ButtonBoxPanel from './components/ButtonBoxPanel.jsx';
|
||||
import RewardRunOverlay from './components/RewardRunOverlay.jsx';
|
||||
import ButtonBoxPanel from './components/ButtonBoxPanel/index.jsx';
|
||||
import RewardRunOverlay from './components/RewardRunOverlay/index.jsx';
|
||||
|
||||
function useLayoutMode() {
|
||||
const [mode, setMode] = useState(() => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Admin control panel main composition and action handlers.
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { useSession } from '../../context/SessionContext.jsx';
|
||||
import RoverRoster from '../RoverRoster.jsx';
|
||||
import RoverRoster from '../RoverRoster/index.jsx';
|
||||
import LlmCommentaryPanel from './LlmCommentaryPanel.jsx';
|
||||
import ReplaySnapshotHealth from './ReplaySnapshotHealth.jsx';
|
||||
import AdminIpLogPanel from './AdminIpLogPanel.jsx';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Admin LLM commentary monitor panel.
|
||||
import { useState } from 'react';
|
||||
import ChatMessageRow from '../ChatMessageRow.jsx';
|
||||
import ChatMessageRow from '../ChatMessageRow/index.jsx';
|
||||
import { buildLlmLargeIndicatorFromState, buildLlmConversationRowsFromMessages } from './llmHelpers.js';
|
||||
|
||||
export default function LlmCommentaryPanel({ state, onClearHistory, clearingHistory }) {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { useSessionActions, useSessionSelector } from '../context/SessionContext.jsx';
|
||||
import { useSocket } from '../context/SocketContext.jsx';
|
||||
import ChatMessageRow from './ChatMessageRow.jsx';
|
||||
import ChatTypingRow from './ChatTypingRow.jsx';
|
||||
import ButtonBoxTile from './ButtonBoxTile.jsx';
|
||||
import { useSessionActions, useSessionSelector } from '../../context/SessionContext.jsx';
|
||||
import { useSocket } from '../../context/SocketContext.jsx';
|
||||
import ChatMessageRow from '../ChatMessageRow/index.jsx';
|
||||
import ChatTypingRow from '../ChatTypingRow/index.jsx';
|
||||
import ButtonBoxTile from '../ButtonBoxTile/index.jsx';
|
||||
|
||||
const LIFETIME_MS = 3000;
|
||||
const BUTTONBOX_LIFETIME_MS = 3500;
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState } from 'react';
|
||||
import { useSessionActions } from '../context/SessionContext.jsx';
|
||||
import { useSessionActions } from '../../context/SessionContext.jsx';
|
||||
|
||||
export default function AuthPanel() {
|
||||
const { login, setRole } = useSessionActions();
|
||||
@@ -1,4 +1,4 @@
|
||||
import { WARN_DISPLAY_PERCENT } from '../lib/battery.js';
|
||||
import { WARN_DISPLAY_PERCENT } from '../../lib/battery.js';
|
||||
|
||||
const WARN_FLASH_MS = 1600;
|
||||
const URGENT_FLASH_MS = 800;
|
||||
+5
-5
@@ -1,9 +1,9 @@
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useSession } from '../context/SessionContext.jsx';
|
||||
import { useSocket } from '../context/SocketContext.jsx';
|
||||
import { useSettingsNamespace } from '../settings/index.js';
|
||||
import { AUDIO_SETTINGS_DEFAULTS } from '../settings/namespaces.js';
|
||||
import ButtonBoxTile from './ButtonBoxTile.jsx';
|
||||
import { useSession } from '../../context/SessionContext.jsx';
|
||||
import { useSocket } from '../../context/SocketContext.jsx';
|
||||
import { useSettingsNamespace } from '../../settings/index.js';
|
||||
import { AUDIO_SETTINGS_DEFAULTS } from '../../settings/namespaces.js';
|
||||
import ButtonBoxTile from '../ButtonBoxTile/index.jsx';
|
||||
|
||||
const FLASH_MS = 420;
|
||||
const REWARD_FLASH_MS = 1200;
|
||||
@@ -1,92 +0,0 @@
|
||||
import { useControlSystem } from '../controls/index.js';
|
||||
import { formatKeyLabel } from '../controls/keymapUtils.js';
|
||||
import NightVisionControl from './NightVisionControl.jsx';
|
||||
import HornControl from './HornControl.jsx';
|
||||
import CameraTiltControl from './CameraTiltControl.jsx';
|
||||
|
||||
const SLIDER_THROTTLE_MS = 150;
|
||||
|
||||
export default function CameraServoPanel() {
|
||||
const {
|
||||
state: { roverId, camera, keymap, horn },
|
||||
pipeline,
|
||||
actions: { setServoAngle, setNightVision, startHorn, stopHorn },
|
||||
} = useControlSystem();
|
||||
const config = camera?.config;
|
||||
const enabled = Boolean(roverId && camera?.enabled && config);
|
||||
const nightVisionAvailable = Boolean(roverId && pipeline?.nightVision);
|
||||
const nightVisionState = pipeline?.nightVisionState;
|
||||
const hornAvailable = Boolean(roverId && pipeline?.horn);
|
||||
const nightVisionKey = formatKeyLabel(keymap?.nightVisionToggle?.[0]);
|
||||
const hornKey = formatKeyLabel(keymap?.hornHonk?.[0]);
|
||||
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;
|
||||
|
||||
if (!enabled && !nightVisionAvailable && !hornAvailable) return null;
|
||||
|
||||
const handleNightVisionToggle = (nextOn) => {
|
||||
if (!nightVisionAvailable) return;
|
||||
setNightVision(nextOn);
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="panel-section space-y-0.5 text-base">
|
||||
{nightVisionAvailable && (
|
||||
<NightVisionControl
|
||||
nightVisionOn={nightVisionState?.nightVisionOn}
|
||||
disabled={!roverId}
|
||||
onToggle={handleNightVisionToggle}
|
||||
keyLabel={nightVisionKey}
|
||||
/>
|
||||
)}
|
||||
{hornAvailable && (
|
||||
<HornControl
|
||||
disabled={!roverId || hornBlocked}
|
||||
onStart={startHorn}
|
||||
onStop={stopHorn}
|
||||
keyLabel={hornKey}
|
||||
active={horn?.active}
|
||||
heat={horn?.heat}
|
||||
/>
|
||||
)}
|
||||
{enabled && (
|
||||
<CameraTiltControl
|
||||
value={value}
|
||||
min={min}
|
||||
max={max}
|
||||
step={0.5}
|
||||
onChange={setServoAngle}
|
||||
throttleMs={SLIDER_THROTTLE_MS}
|
||||
className="space-y-0.5"
|
||||
labelRowClass="text-sm text-slate-300"
|
||||
valueClass="font-mono text-sm text-slate-100"
|
||||
sliderClass="w-full"
|
||||
accentClass="accent-emerald-400"
|
||||
endpointClass="text-xs text-slate-400"
|
||||
endpointLabelClass=""
|
||||
/>
|
||||
)}
|
||||
{/* <div className="flex gap-0.5 text-sm">
|
||||
<button type="button" className="flex-1 button-dark" onClick={() => handleNudge(-1)}>
|
||||
Tilt Down
|
||||
</button>
|
||||
<button type="button" className="flex-1 button-dark" onClick={() => goServoHome()}>
|
||||
Center
|
||||
</button>
|
||||
<button type="button" className="flex-1 button-dark" onClick={() => handleNudge(1)}>
|
||||
Tilt Up
|
||||
</button>
|
||||
</div> */}
|
||||
{/* <p className="text-xs text-slate-400">
|
||||
Step: {formatDegrees(step)} · Pin GPIO {config?.pin}
|
||||
</p> */}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { FaDiscord } from 'react-icons/fa';
|
||||
import { roverBadgeStyle } from '../lib/roverColor.js';
|
||||
import { roverBadgeStyle } from '../../lib/roverColor.js';
|
||||
|
||||
function roleColors(role) {
|
||||
switch (role) {
|
||||
@@ -1,9 +1,9 @@
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useChat } from '../context/ChatContext.jsx';
|
||||
import { useSessionSelector } from '../context/SessionContext.jsx';
|
||||
import { useSettingsNamespace } from '../settings/index.js';
|
||||
import ChatMessageRow from './ChatMessageRow.jsx';
|
||||
import ChatTypingRow from './ChatTypingRow.jsx';
|
||||
import { useChat } from '../../context/ChatContext.jsx';
|
||||
import { useSessionSelector } from '../../context/SessionContext.jsx';
|
||||
import { useSettingsNamespace } from '../../settings/index.js';
|
||||
import ChatMessageRow from '../ChatMessageRow/index.jsx';
|
||||
import ChatTypingRow from '../ChatTypingRow/index.jsx';
|
||||
|
||||
const FLITE_VOICES = ['kal', 'rms', 'slt', 'ksp', 'bdl'];
|
||||
const ESPEAK_PITCHES = Array.from({ length: 10 }, (_, idx) => idx * 10);
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { ChatIdentity, chatRowClass } from './ChatMessageRow.jsx';
|
||||
import { ChatIdentity, chatRowClass } from '../ChatMessageRow/index.jsx';
|
||||
|
||||
export default function ChatTypingRow({ message }) {
|
||||
return (
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useSession } from '../context/SessionContext.jsx';
|
||||
import { useSession } from '../../context/SessionContext.jsx';
|
||||
|
||||
const MOBILE_DISMISS_MS = 10000;
|
||||
const MAX_FONT_PX = 28;
|
||||
@@ -1,134 +0,0 @@
|
||||
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/index.jsx';
|
||||
import RoverRoster from './RoverRoster.jsx';
|
||||
import DriveDockAction, { useDriveDockState } from './DriveDockAction/index.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 (
|
||||
<RoverRoster
|
||||
title={title}
|
||||
roster={session?.roster ?? []}
|
||||
renderActions={(rover) =>
|
||||
canRequest ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleRequest(rover.id)}
|
||||
disabled={pending[rover.id]}
|
||||
className="button-dark disabled:opacity-40"
|
||||
>
|
||||
{pending[rover.id] ? '...' : 'request'}
|
||||
</button>
|
||||
) : 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 (
|
||||
<section className="panel-section">
|
||||
<div className="grid items-stretch gap-0.5 md:grid-cols-[minmax(0,1.1fr)_minmax(0,1fr)] md:min-h-[18rem]">
|
||||
<div className="flex h-full w-full items-stretch justify-center">
|
||||
<div className="aspect-square h-full w-full">
|
||||
<TopDownMap sensors={sensors} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid h-full min-h-0 grid-rows-[minmax(0,1fr)_auto] gap-0.5">
|
||||
<DriveDockAction layout="desktop" expand driveDockState={driveDockState} />
|
||||
{!hideInlineControls ? (
|
||||
<div className="surface space-y-0.5 p-0 text-sm text-slate-200">
|
||||
{nightVisionAvailable && (
|
||||
<NightVisionControl
|
||||
nightVisionOn={nightVisionState?.nightVisionOn}
|
||||
disabled={!roverId}
|
||||
onToggle={setNightVision}
|
||||
keyLabel={nightVisionLabel}
|
||||
/>
|
||||
)}
|
||||
{hornAvailable && (
|
||||
<HornControl
|
||||
disabled={!roverId || hornBlocked}
|
||||
onStart={startHorn}
|
||||
onStop={stopHorn}
|
||||
keyLabel={hornLabel}
|
||||
active={horn?.active}
|
||||
heat={horn?.heat}
|
||||
/>
|
||||
)}
|
||||
{cameraEnabled && (
|
||||
<CameraTiltControl
|
||||
value={value}
|
||||
min={min}
|
||||
max={max}
|
||||
onChange={setServoAngle}
|
||||
keyDownLabel={downLabel}
|
||||
keyUpLabel={upLabel}
|
||||
className="space-y-0.5 px-1 py-1"
|
||||
labelRowClass="text-xs text-slate-300"
|
||||
labelClass=""
|
||||
valueClass="font-mono text-slate-100"
|
||||
sliderClass="w-full"
|
||||
accentClass="accent-emerald-400"
|
||||
endpointClass="text-[0.7rem] text-slate-400"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useSessionSelector } from '../context/SessionContext.jsx';
|
||||
import { useSessionSelector } from '../../context/SessionContext.jsx';
|
||||
|
||||
function getRandomElement(elements) {
|
||||
if (!elements || !elements.length) return null;
|
||||
+6
-6
@@ -1,10 +1,10 @@
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useSessionSelector } from '../context/SessionContext.jsx';
|
||||
import { useTelemetryFrame } from '../context/TelemetryContext.jsx';
|
||||
import { useVideoRequests } from '../hooks/useVideoRequests.js';
|
||||
import { useRoverSnapshots } from '../hooks/useRoverSnapshots.js';
|
||||
import { useControlSystem } from '../controls/index.js';
|
||||
import VideoTile from './VideoTile.jsx';
|
||||
import { useSessionSelector } from '../../context/SessionContext.jsx';
|
||||
import { useTelemetryFrame } from '../../context/TelemetryContext.jsx';
|
||||
import { useVideoRequests } from '../../hooks/useVideoRequests.js';
|
||||
import { useRoverSnapshots } from '../../hooks/useRoverSnapshots.js';
|
||||
import { useControlSystem } from '../../controls/index.js';
|
||||
import VideoTile from '../VideoTile/index.jsx';
|
||||
|
||||
export default function DriverVideoPanel({layoutFormat = 'desktop'}) {
|
||||
const session = useSessionSelector((state) => state.session);
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
import { useMemo } from 'react';
|
||||
import { formatKeyLabel } from '../controls/keymapUtils.js';
|
||||
import { getHelpContent } from '../help/content.js';
|
||||
import { formatKeyLabel } from '../../controls/keymapUtils.js';
|
||||
import { getHelpContent } from '../../help/content.js';
|
||||
|
||||
function KeyPill({ actionId, keymap }) {
|
||||
const value = keymap?.[actionId]?.[0] ?? '';
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useControlSystem } from '../controls/index.js';
|
||||
import HelpContentView from './HelpContentView.jsx';
|
||||
import { useControlSystem } from '../../controls/index.js';
|
||||
import HelpContentView from '../HelpContentView/index.jsx';
|
||||
|
||||
export default function HelpOverlay({ visible, layout, onClose, showOnLoad, onToggleShowOnLoad }) {
|
||||
if (!visible) return null;
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useControlSystem } from '../controls/index.js';
|
||||
import HelpContentView from './HelpContentView.jsx';
|
||||
import { useControlSystem } from '../../controls/index.js';
|
||||
import HelpContentView from '../HelpContentView/index.jsx';
|
||||
|
||||
export default function HelpPanel({ layout, onOpenOverlay }) {
|
||||
const { state } = useControlSystem();
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useSessionActions, useSessionSelector } from '../context/SessionContext.jsx';
|
||||
import { useControlSystem } from '../controls/index.js';
|
||||
import { formatKeyLabel } from '../controls/keymapUtils.js';
|
||||
import { useSessionActions, useSessionSelector } from '../../context/SessionContext.jsx';
|
||||
import { useControlSystem } from '../../controls/index.js';
|
||||
import { formatKeyLabel } from '../../controls/keymapUtils.js';
|
||||
|
||||
function StatusBadge({ label, tone = 'muted' }) {
|
||||
const styles =
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useSettingsNamespace } from '../settings/index.js';
|
||||
import { HORN_SETTINGS_DEFAULTS } from '../settings/namespaces.js';
|
||||
import { useSettingsNamespace } from '../../settings/index.js';
|
||||
import { HORN_SETTINGS_DEFAULTS } from '../../settings/namespaces.js';
|
||||
|
||||
function clampFreq(value) {
|
||||
const num = Number(value);
|
||||
+6
-6
@@ -1,10 +1,10 @@
|
||||
import { useMemo, useState, useEffect, useCallback } from 'react';
|
||||
import { useControlSystem } from '../controls/index.js';
|
||||
import { DEFAULT_KEYMAP } from '../controls/constants.js';
|
||||
import { canonicalizeKeyInput, formatKeyLabel } from '../controls/keymapUtils.js';
|
||||
import { setKeyboardCaptureLocked } from '../controls/inputs/keyboardCaptureLock.js';
|
||||
import { useSettingsNamespace } from '../settings/index.js';
|
||||
import { INPUT_SETTINGS_DEFAULTS } from '../settings/namespaces.js';
|
||||
import { useControlSystem } from '../../controls/index.js';
|
||||
import { DEFAULT_KEYMAP } from '../../controls/constants.js';
|
||||
import { canonicalizeKeyInput, formatKeyLabel } from '../../controls/keymapUtils.js';
|
||||
import { setKeyboardCaptureLocked } from '../../controls/inputs/keyboardCaptureLock.js';
|
||||
import { useSettingsNamespace } from '../../settings/index.js';
|
||||
import { INPUT_SETTINGS_DEFAULTS } from '../../settings/namespaces.js';
|
||||
|
||||
const KEY_ACTIONS = [
|
||||
{ id: 'driveForward', label: 'Drive Forward', group: 'Driving' },
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useSessionSelector } from '../context/SessionContext.jsx';
|
||||
import { useSessionSelector } from '../../context/SessionContext.jsx';
|
||||
|
||||
export default function LogPanel() {
|
||||
const logs = useSessionSelector((state) => state.logs);
|
||||
@@ -3,9 +3,9 @@ import { useCallback, useEffect, useRef } from 'react';
|
||||
import { useControlSystem } from '../../controls/index.js';
|
||||
import { clampUnit } from '../../controls/controlMath.js';
|
||||
import DriveDockAction, { useDriveDockState } from '../DriveDockAction/index.jsx';
|
||||
import NightVisionControl from '../NightVisionControl.jsx';
|
||||
import HornControl from '../HornControl.jsx';
|
||||
import CameraTiltControl from '../CameraTiltControl.jsx';
|
||||
import NightVisionControl from '../NightVisionControl/index.jsx';
|
||||
import HornControl from '../HornControl/index.jsx';
|
||||
import CameraTiltControl from '../CameraTiltControl/index.jsx';
|
||||
import FloatingJoystick from './FloatingJoystick.jsx';
|
||||
import MobileAuxButton from './MobileAuxButton.jsx';
|
||||
import {
|
||||
|
||||
+5
-5
@@ -1,9 +1,9 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import AuthPanel from './AuthPanel.jsx';
|
||||
import { useSessionSelector } from '../context/SessionContext.jsx';
|
||||
import SocialButton from './SocialButton.jsx';
|
||||
import ChatPanel from './ChatPanel.jsx';
|
||||
import NicknameForm from './NicknameForm.jsx';
|
||||
import AuthPanel from '../AuthPanel/index.jsx';
|
||||
import { useSessionSelector } from '../../context/SessionContext.jsx';
|
||||
import SocialButton from '../SocialButton/index.jsx';
|
||||
import ChatPanel from '../ChatPanel/index.jsx';
|
||||
import NicknameForm from '../NicknameForm/index.jsx';
|
||||
|
||||
const PRIVILEGED_ROLES = new Set(['admin', 'lockdown', 'lockdown-admin']);
|
||||
const LOCKDOWN_ROLES = new Set(['lockdown', 'lockdown-admin']);
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useSession } from '../context/SessionContext.jsx';
|
||||
import { useSettingsNamespace } from '../settings/index.js';
|
||||
import { useSession } from '../../context/SessionContext.jsx';
|
||||
import { useSettingsNamespace } from '../../settings/index.js';
|
||||
|
||||
export default function NicknameForm({ compact = false }) {
|
||||
const { session, setNickname } = useSession();
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useControlSystem } from '../controls/index.js';
|
||||
import { OVERCURRENT_GROUPS } from '../controls/overcurrentLimiter.js';
|
||||
import { useControlSystem } from '../../controls/index.js';
|
||||
import { OVERCURRENT_GROUPS } from '../../controls/overcurrentLimiter.js';
|
||||
|
||||
const GROUP_LABELS = {
|
||||
drive: 'Drive wheels',
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useSession } from '../context/SessionContext.jsx';
|
||||
import NicknameForm from './NicknameForm.jsx';
|
||||
import SocialButtonsGrid from './SocialButtonsGrid.jsx';
|
||||
import { useSession } from '../../context/SessionContext.jsx';
|
||||
import NicknameForm from '../NicknameForm/index.jsx';
|
||||
import SocialButtonsGrid from '../SocialButtonsGrid/index.jsx';
|
||||
|
||||
function roleColors(role) {
|
||||
switch (role) {
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { useSession } from '../context/SessionContext.jsx';
|
||||
import { useSettingsNamespace } from '../settings/index.js';
|
||||
import { roverNameChromeStyle } from '../lib/roverColor.js';
|
||||
import { useSession } from '../../context/SessionContext.jsx';
|
||||
import { useSettingsNamespace } from '../../settings/index.js';
|
||||
import { roverNameChromeStyle } from '../../lib/roverColor.js';
|
||||
|
||||
function normalizeSources(list = []) {
|
||||
return list
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useSocket } from '../context/SocketContext.jsx';
|
||||
import { useSettingsNamespace } from '../settings/index.js';
|
||||
import { AUDIO_SETTINGS_DEFAULTS } from '../settings/namespaces.js';
|
||||
import { useSocket } from '../../context/SocketContext.jsx';
|
||||
import { useSettingsNamespace } from '../../settings/index.js';
|
||||
import { AUDIO_SETTINGS_DEFAULTS } from '../../settings/namespaces.js';
|
||||
|
||||
const SHOW_MS = 3200;
|
||||
|
||||
+22
-22
@@ -1,25 +1,25 @@
|
||||
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/index.jsx';
|
||||
import DriveDockAction, { useDriveDockState } from './DriveDockAction/index.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';
|
||||
import RoomCameraPanel from '../RoomCameraPanel/index.jsx';
|
||||
import HomeAssistantControls from '../HomeAssistantControls/index.jsx';
|
||||
import SettingsPanel from '../SettingsPanel/index.jsx';
|
||||
import HelpPanel from '../HelpPanel/index.jsx';
|
||||
import ChatPanel from '../ChatPanel/index.jsx';
|
||||
import { LinkButtonsPanel, NicknameEntryPanel } from '../UserListPanel/index.jsx';
|
||||
import ReplaySourcesPanel from '../ReplaySourcesPanel/index.jsx';
|
||||
import Tabs, { Tab, TabList, TabPanel, TabPanels } from '../Tabs/index.jsx';
|
||||
import TopDownMap from '../TopDownMap/index.jsx';
|
||||
import DriveDockAction, { useDriveDockState } from '../DriveDockAction/index.jsx';
|
||||
import { useTelemetryFrame } from '../../context/TelemetryContext.jsx';
|
||||
import { useControlSystem } from '../../controls/index.js';
|
||||
import RoverQueuesPanel from '../RoverQueuesPanel/index.jsx';
|
||||
import RawUserPilePanel from '../RawUserPilePanel/index.jsx';
|
||||
import { formatKeyLabel } from '../../controls/keymapUtils.js';
|
||||
import NightVisionControl from '../NightVisionControl/index.jsx';
|
||||
import HornControl from '../HornControl/index.jsx';
|
||||
import CameraTiltControl from '../CameraTiltControl/index.jsx';
|
||||
import VipPanel from '../VipPanel/index.jsx';
|
||||
import { useSessionSelector } from '../../context/SessionContext.jsx';
|
||||
import { useSettingsNamespace } from '../../settings/index.js';
|
||||
import ButtonBoxPanel from '../ButtonBoxPanel/index.jsx';
|
||||
|
||||
function TopDownMapPanel() {
|
||||
const {
|
||||
+4
-4
@@ -1,8 +1,8 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useSession } from '../context/SessionContext.jsx';
|
||||
import { useSettingsNamespace } from '../settings/index.js';
|
||||
import { useRoomCameraSnapshots } from '../hooks/useRoomCameraSnapshots.js';
|
||||
import RoomCameraFeed from './RoomCameraFeed.jsx';
|
||||
import { useSession } from '../../context/SessionContext.jsx';
|
||||
import { useSettingsNamespace } from '../../settings/index.js';
|
||||
import { useRoomCameraSnapshots } from '../../hooks/useRoomCameraSnapshots.js';
|
||||
import RoomCameraFeed from '../RoomCameraFeed/index.jsx';
|
||||
|
||||
function EmptyState() {
|
||||
return (
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { useSessionActions, useSessionSelector } from '../context/SessionContext.jsx';
|
||||
import { roverNameChromeStyle } from '../lib/roverColor.js';
|
||||
import { useSessionActions, useSessionSelector } from '../../context/SessionContext.jsx';
|
||||
import { roverNameChromeStyle } from '../../lib/roverColor.js';
|
||||
|
||||
function classNames(...values) {
|
||||
return values.filter(Boolean).join(' ');
|
||||
@@ -1,4 +1,4 @@
|
||||
import { roverNameChromeStyle } from '../lib/roverColor.js';
|
||||
import { roverNameChromeStyle } from '../../lib/roverColor.js';
|
||||
|
||||
function classNames(...values) {
|
||||
return values.filter(Boolean).join(' ');
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useSession } from '../context/SessionContext.jsx';
|
||||
import { useSession } from '../../context/SessionContext.jsx';
|
||||
|
||||
export default function SessionSnapshot() {
|
||||
const { session } = useSession();
|
||||
+13
-13
@@ -1,17 +1,17 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useControlSystem } from '../controls/index.js';
|
||||
import AuthPanel from './AuthPanel.jsx';
|
||||
import AdminPanel from './AdminPanel/index.jsx';
|
||||
import KeymapSettings from './KeymapSettings.jsx';
|
||||
import GamepadMappingSettings from './GamepadMappingSettings/index.jsx';
|
||||
import OvercurrentLimiterPanel from './OvercurrentLimiterPanel.jsx';
|
||||
import Tabs, { Tab, TabList, TabPanel, TabPanels } from './Tabs.jsx';
|
||||
import SessionSnapshot from './SessionSnapshot.jsx';
|
||||
import SocketLogPanel from './SocketLogPanel.jsx';
|
||||
import { useHudMapSetting } from '../hooks/useHudMapSetting.js';
|
||||
import { useSettingsNamespace } from '../settings/index.js';
|
||||
import { useSocket } from '../context/SocketContext.jsx';
|
||||
import { AUDIO_SETTINGS_DEFAULTS } from '../settings/namespaces.js';
|
||||
import { useControlSystem } from '../../controls/index.js';
|
||||
import AuthPanel from '../AuthPanel/index.jsx';
|
||||
import AdminPanel from '../AdminPanel/index.jsx';
|
||||
import KeymapSettings from '../KeymapSettings/index.jsx';
|
||||
import GamepadMappingSettings from '../GamepadMappingSettings/index.jsx';
|
||||
import OvercurrentLimiterPanel from '../OvercurrentLimiterPanel/index.jsx';
|
||||
import Tabs, { Tab, TabList, TabPanel, TabPanels } from '../Tabs/index.jsx';
|
||||
import SessionSnapshot from '../SessionSnapshot/index.jsx';
|
||||
import SocketLogPanel from '../SocketLogPanel/index.jsx';
|
||||
import { useHudMapSetting } from '../../hooks/useHudMapSetting.js';
|
||||
import { useSettingsNamespace } from '../../settings/index.js';
|
||||
import { useSocket } from '../../context/SocketContext.jsx';
|
||||
import { AUDIO_SETTINGS_DEFAULTS } from '../../settings/namespaces.js';
|
||||
|
||||
const manualTabs = [
|
||||
{ key: 'start', label: 'Start OI' },
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { useSession } from '../context/SessionContext.jsx';
|
||||
import SocialButton from './SocialButton.jsx';
|
||||
import { useSession } from '../../context/SessionContext.jsx';
|
||||
import SocialButton from '../SocialButton/index.jsx';
|
||||
|
||||
function normalizeSocials(session) {
|
||||
const configured = Array.isArray(session?.socials) ? session.socials : null;
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { useSocket } from '../context/SocketContext.jsx';
|
||||
import { useSocket } from '../../context/SocketContext.jsx';
|
||||
|
||||
const MAX_ENTRIES = 300;
|
||||
const MAX_PAYLOAD_LENGTH = 240;
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useSessionSelector } from '../context/SessionContext.jsx';
|
||||
import { useTelemetryFrame } from '../context/TelemetryContext.jsx';
|
||||
import { useDockIr } from '../hooks/useDockIr.js';
|
||||
import { useSessionSelector } from '../../context/SessionContext.jsx';
|
||||
import { useTelemetryFrame } from '../../context/TelemetryContext.jsx';
|
||||
import { useDockIr } from '../../hooks/useDockIr.js';
|
||||
|
||||
function formatMetric(value, fallback = '--') {
|
||||
if (value == null || value === '') return fallback;
|
||||
+4
-4
@@ -1,8 +1,8 @@
|
||||
import { useEffect, useMemo, useRef } from 'react';
|
||||
import turnSound from '../assets/turn_alert.mp3';
|
||||
import { useSessionActions, useSessionSelector } from '../context/SessionContext.jsx';
|
||||
import { useSettingsNamespace } from '../settings/index.js';
|
||||
import { AUDIO_SETTINGS_DEFAULTS } from '../settings/namespaces.js';
|
||||
import turnSound from '../../assets/turn_alert.mp3';
|
||||
import { useSessionActions, useSessionSelector } from '../../context/SessionContext.jsx';
|
||||
import { useSettingsNamespace } from '../../settings/index.js';
|
||||
import { AUDIO_SETTINGS_DEFAULTS } from '../../settings/namespaces.js';
|
||||
|
||||
function useAudio(src, volume = 1) {
|
||||
const audioRef = useRef(null);
|
||||
+4
-4
@@ -1,8 +1,8 @@
|
||||
import { useEffect, useMemo, useState, useCallback } from 'react';
|
||||
import { useSession } from '../context/SessionContext.jsx';
|
||||
import NicknameForm from './NicknameForm.jsx';
|
||||
import SocialButtonsGrid from './SocialButtonsGrid.jsx';
|
||||
import { roverBadgeStyle, roverNameChromeStyle } from '../lib/roverColor.js';
|
||||
import { useSession } from '../../context/SessionContext.jsx';
|
||||
import NicknameForm from '../NicknameForm/index.jsx';
|
||||
import SocialButtonsGrid from '../SocialButtonsGrid/index.jsx';
|
||||
import { roverBadgeStyle, roverNameChromeStyle } from '../../lib/roverColor.js';
|
||||
|
||||
export function NicknameEntryPanel({ compact = false }) {
|
||||
return (
|
||||
@@ -1,25 +1,25 @@
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { WhepPlayer } from '../lib/whepPlayer.js';
|
||||
import { useHudMapSetting } from '../hooks/useHudMapSetting.js';
|
||||
import { useSessionSelector } from '../context/SessionContext.jsx';
|
||||
import { useSettingsNamespace } from '../settings/index.js';
|
||||
import { AUDIO_SETTINGS_DEFAULTS } from '../settings/namespaces.js';
|
||||
import SocialButton from './SocialButton.jsx';
|
||||
import BatteryBar from './BatteryBar.jsx';
|
||||
import { buildBatteryVisual } from '../lib/battery.js';
|
||||
import TurnCueOverlay from './VideoTile/TurnCueOverlay.jsx';
|
||||
import HudOverlay from './VideoTile/HudOverlay.jsx';
|
||||
import OvercurrentOverlay from './VideoTile/OvercurrentOverlay.jsx';
|
||||
import LowBatteryOverlay from './VideoTile/LowBatteryOverlay.jsx';
|
||||
import LightBumpBars from './VideoTile/LightBumpBars.jsx';
|
||||
import HudChatInput from './VideoTile/HudChatInput.jsx';
|
||||
import { WhepPlayer } from '../../lib/whepPlayer.js';
|
||||
import { useHudMapSetting } from '../../hooks/useHudMapSetting.js';
|
||||
import { useSessionSelector } from '../../context/SessionContext.jsx';
|
||||
import { useSettingsNamespace } from '../../settings/index.js';
|
||||
import { AUDIO_SETTINGS_DEFAULTS } from '../../settings/namespaces.js';
|
||||
import SocialButton from '../SocialButton/index.jsx';
|
||||
import BatteryBar from '../BatteryBar/index.jsx';
|
||||
import { buildBatteryVisual } from '../../lib/battery.js';
|
||||
import TurnCueOverlay from './TurnCueOverlay.jsx';
|
||||
import HudOverlay from './HudOverlay.jsx';
|
||||
import OvercurrentOverlay from './OvercurrentOverlay.jsx';
|
||||
import LowBatteryOverlay from './LowBatteryOverlay.jsx';
|
||||
import LightBumpBars from './LightBumpBars.jsx';
|
||||
import HudChatInput from './HudChatInput.jsx';
|
||||
import {
|
||||
RESTART_DELAY_MS,
|
||||
UNMUTE_RETRY_MS,
|
||||
AUDIO_RETRY_MS,
|
||||
BRUSH_CURRENT_THRESHOLD_MA,
|
||||
DUCK_RELEASE_FADE_MS,
|
||||
} from './VideoTile/constants.js';
|
||||
} from './constants.js';
|
||||
|
||||
export default function VideoTile({
|
||||
sessionInfo,
|
||||
@@ -1,12 +1,12 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useSession } from '../context/SessionContext.jsx';
|
||||
import { useSettingsNamespace } from '../settings/index.js';
|
||||
import { COOKIE_KEY_REGEX, flowWrapClass } from './vip/constants.js';
|
||||
import VipAudioUploadCard from './vip/VipAudioUploadCard/index.jsx';
|
||||
import VipVerificationCard from './vip/VipVerificationCard.jsx';
|
||||
import VipIdentityCard from './vip/VipIdentityCard.jsx';
|
||||
import VipPrivateRoverAccessCard from './vip/VipPrivateRoverAccessCard.jsx';
|
||||
import VipNeatoCard from './vip/VipNeatoCard.jsx';
|
||||
import { useSession } from '../../context/SessionContext.jsx';
|
||||
import { useSettingsNamespace } from '../../settings/index.js';
|
||||
import { COOKIE_KEY_REGEX, flowWrapClass } from '../vip/constants.js';
|
||||
import VipAudioUploadCard from '../vip/VipAudioUploadCard/index.jsx';
|
||||
import VipVerificationCard from '../vip/VipVerificationCard.jsx';
|
||||
import VipIdentityCard from '../vip/VipIdentityCard.jsx';
|
||||
import VipPrivateRoverAccessCard from '../vip/VipPrivateRoverAccessCard.jsx';
|
||||
import VipNeatoCard from '../vip/VipNeatoCard.jsx';
|
||||
|
||||
export default function VipPanel() {
|
||||
const {
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState } from 'react';
|
||||
import NicknameForm from '../NicknameForm.jsx';
|
||||
import NicknameForm from '../NicknameForm/index.jsx';
|
||||
import { flowWrapClass, innerFlowClass, fieldClass } from './constants.js';
|
||||
|
||||
export default function VipVerificationCard({
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ import { ChatProvider } from './context/ChatContext.jsx'
|
||||
import SpectatorApp from './spectate/SpectatorApp.jsx'
|
||||
import MiniSummaryApp from './mini/MiniSummaryApp.jsx'
|
||||
import { SettingsProvider } from './settings/index.js'
|
||||
import DeterrenceChaos from './components/DeterrenceChaos.jsx'
|
||||
import DeterrenceChaos from './components/DeterrenceChaos/index.jsx'
|
||||
|
||||
createRoot(document.getElementById('root')).render(
|
||||
<StrictMode>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Top-level mini summary app shell with hard-refresh timer and alerts.
|
||||
import { useEffect } from 'react';
|
||||
import AlertFeed from '../../components/AlertFeed.jsx';
|
||||
import AlertFeed from '../../components/AlertFeed/index.jsx';
|
||||
import MiniSummaryContent from './MiniSummaryContent.jsx';
|
||||
import { HARD_REFRESH_MS } from './constants.js';
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import { useVideoRequests } from '../../hooks/useVideoRequests.js';
|
||||
import { useRoverSnapshots } from '../../hooks/useRoverSnapshots.js';
|
||||
import { useSpectatorMode } from '../../hooks/useSpectatorMode.js';
|
||||
import useDefaultNickname from '../../hooks/useDefaultNickname.js';
|
||||
import VideoTile from '../../components/VideoTile.jsx';
|
||||
import VideoTile from '../../components/VideoTile/index.jsx';
|
||||
import FitViewportFrame from './components/FitViewportFrame.jsx';
|
||||
import InfoColumn from './components/InfoColumn.jsx';
|
||||
import { ROTATE_MS } from './constants.js';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Rover information and optional preview column for mini summary UI.
|
||||
import VideoTile from '../../../components/VideoTile.jsx';
|
||||
import BatteryBar from '../../../components/BatteryBar.jsx';
|
||||
import VideoTile from '../../../components/VideoTile/index.jsx';
|
||||
import BatteryBar from '../../../components/BatteryBar/index.jsx';
|
||||
import { roverNameChromeStyle } from '../../../lib/roverColor.js';
|
||||
import { getBatteryVisual } from '../utils.js';
|
||||
import AutoFitText from './AutoFitText.jsx';
|
||||
|
||||
@@ -5,13 +5,13 @@ import { useVideoRequests } from '../../hooks/useVideoRequests.js';
|
||||
import { useRoverSnapshots } from '../../hooks/useRoverSnapshots.js';
|
||||
import { useSpectatorMode } from '../../hooks/useSpectatorMode.js';
|
||||
import useDefaultNickname from '../../hooks/useDefaultNickname.js';
|
||||
import ChatPanel from '../../components/ChatPanel.jsx';
|
||||
import AlertFeed from '../../components/AlertFeed.jsx';
|
||||
import CommunityGoalBanner from '../../components/CommunityGoalBanner.jsx';
|
||||
import RoverQueuesPanel from '../../components/RoverQueuesPanel.jsx';
|
||||
import RawUserPilePanel from '../../components/RawUserPilePanel.jsx';
|
||||
import ButtonBoxPanel from '../../components/ButtonBoxPanel.jsx';
|
||||
import RewardRunOverlay from '../../components/RewardRunOverlay.jsx';
|
||||
import ChatPanel from '../../components/ChatPanel/index.jsx';
|
||||
import AlertFeed from '../../components/AlertFeed/index.jsx';
|
||||
import CommunityGoalBanner from '../../components/CommunityGoalBanner/index.jsx';
|
||||
import RoverQueuesPanel from '../../components/RoverQueuesPanel/index.jsx';
|
||||
import RawUserPilePanel from '../../components/RawUserPilePanel/index.jsx';
|
||||
import ButtonBoxPanel from '../../components/ButtonBoxPanel/index.jsx';
|
||||
import RewardRunOverlay from '../../components/RewardRunOverlay/index.jsx';
|
||||
import usePortraitLayout from './hooks/usePortraitLayout.js';
|
||||
import RoverRow from './components/RoverRow.jsx';
|
||||
import SecondaryRow from './components/SecondaryRow.jsx';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Log panel wrapper row for spectator layout.
|
||||
import LogPanel from '../../../components/LogPanel.jsx';
|
||||
import LogPanel from '../../../components/LogPanel/index.jsx';
|
||||
|
||||
export default function LogsRow({ className = '' }) {
|
||||
return (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Single rover spectator card containing live/snapshot tile and HUD.
|
||||
import VideoTile from '../../../components/VideoTile.jsx';
|
||||
import VideoTile from '../../../components/VideoTile/index.jsx';
|
||||
import { formatDriverLabel } from '../utils.js';
|
||||
|
||||
export default function RoverSpectatorCard({ rover, frame, sessionInfo, videoMode, snapshotFeed, audioInfo, session }) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Secondary panel row showing room cameras.
|
||||
import RoomCameraPanel from '../../../components/RoomCameraPanel.jsx';
|
||||
import RoomCameraPanel from '../../../components/RoomCameraPanel/index.jsx';
|
||||
|
||||
export default function SecondaryRow() {
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user