mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 01:21:20 -04:00
loading screen, better HUD, etc.
This commit is contained in:
+2
-2
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
|
After Width: | Height: | Size: 337 KiB |
@@ -12,8 +12,8 @@
|
|||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||||
<!-- site-metadata:inject -->
|
<!-- site-metadata:inject -->
|
||||||
<!-- analytics:inject -->
|
<!-- analytics:inject -->
|
||||||
<script type="module" crossorigin src="/assets/index-C0lpCbci.js"></script>
|
<script type="module" crossorigin src="/assets/index-BZ2ymoHR.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-BITzjVQo.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-BFNKIMjg.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 337 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.8 MiB |
@@ -18,18 +18,34 @@ import ExpansionPanel from '../CornerPods/ExpansionPanel.jsx';
|
|||||||
import usePodVisibility from '../CornerPods/usePodVisibility.js';
|
import usePodVisibility from '../CornerPods/usePodVisibility.js';
|
||||||
|
|
||||||
function DockedAction({ driveKeyLabel, pending, controlsDisabled, error, onUndock }) {
|
function DockedAction({ driveKeyLabel, pending, controlsDisabled, error, onUndock }) {
|
||||||
|
const [hidden, setHidden] = useState(false);
|
||||||
const waitingForTurn = controlsDisabled && !pending;
|
const waitingForTurn = controlsDisabled && !pending;
|
||||||
|
|
||||||
|
/* The dismissal belongs to this mounted docked episode. DockingHud unmounts
|
||||||
|
this component when the rover leaves the base, and its roverId key remounts
|
||||||
|
it for a different assignment, so no persistence or reset effect is needed. */
|
||||||
|
if (hidden && !pending) return null;
|
||||||
|
|
||||||
|
const mainToneClass = waitingForTurn
|
||||||
|
? 'cursor-not-allowed bg-slate-950/95 ring-slate-400/70'
|
||||||
|
: 'bg-emerald-950/90 ring-emerald-300/80 hover:bg-emerald-900/95 focus-visible:ring-emerald-200 disabled:cursor-wait disabled:opacity-75';
|
||||||
|
const hideToneClass = waitingForTurn
|
||||||
|
? 'bg-slate-950/95 ring-slate-400/70 hover:bg-slate-900'
|
||||||
|
: 'bg-emerald-950/90 ring-emerald-300/80 hover:bg-emerald-900/95 focus-visible:ring-emerald-200';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
|
{/* The docked shield is owned by the dismissible action so hiding the
|
||||||
|
prompt also reveals the video and ordinary HUD instead of leaving an
|
||||||
|
unexplained dark, input-blocking layer behind. */}
|
||||||
|
<div className="pointer-events-auto absolute inset-0 z-[25] bg-black/75" aria-hidden="true" />
|
||||||
<div className="pointer-events-none absolute inset-0 z-30 flex items-center justify-center p-6">
|
<div className="pointer-events-none absolute inset-0 z-30 flex items-center justify-center p-6">
|
||||||
|
<div className="relative w-[min(32rem,80%)]">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
disabled={pending || controlsDisabled}
|
disabled={pending || controlsDisabled}
|
||||||
onClick={onUndock}
|
onClick={onUndock}
|
||||||
className={`pointer-events-auto flex w-[min(32rem,80%)] flex-col items-center gap-2 px-8 py-7 text-center text-white shadow-2xl ring-2 transition focus-visible:outline-none focus-visible:ring-4 ${
|
className={`pointer-events-auto flex w-full flex-col items-center gap-2 px-8 py-7 text-center text-white shadow-2xl ring-2 transition focus-visible:outline-none focus-visible:ring-4 ${mainToneClass}`}
|
||||||
waitingForTurn
|
|
||||||
? 'cursor-not-allowed bg-slate-950/95 ring-slate-400/70'
|
|
||||||
: 'bg-emerald-950/90 ring-emerald-300/80 hover:bg-emerald-900/95 focus-visible:ring-emerald-200 disabled:cursor-wait disabled:opacity-75'
|
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
<strong className="text-3xl leading-tight">{pending ? 'Undocking…' : 'Your rover is docked'}</strong>
|
<strong className="text-3xl leading-tight">{pending ? 'Undocking…' : 'Your rover is docked'}</strong>
|
||||||
{pending ? (
|
{pending ? (
|
||||||
@@ -53,7 +69,18 @@ function DockedAction({ driveKeyLabel, pending, controlsDisabled, error, onUndoc
|
|||||||
)}
|
)}
|
||||||
{error ? <span className="text-sm font-semibold text-red-200">{error}</span> : null}
|
{error ? <span className="text-sm font-semibold text-red-200">{error}</span> : null}
|
||||||
</button>
|
</button>
|
||||||
|
{!pending ? (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setHidden(true)}
|
||||||
|
className={`pointer-events-auto absolute left-1/2 top-full -translate-x-1/2 rounded-b-lg px-6 py-1.5 text-sm font-bold text-white shadow-xl ring-2 transition focus-visible:outline-none focus-visible:ring-4 ${hideToneClass}`}
|
||||||
|
>
|
||||||
|
Hide
|
||||||
|
</button>
|
||||||
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,15 +345,12 @@ export default function DockingHud({ roverId }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* This single layer both dims and blocks the ordinary rover HUD. A passive
|
{/* Automatic docking keeps its own lighter blocking shield. The ordinary
|
||||||
undocked rover is still moving autonomously, so it gets a lighter but equally
|
docked shield lives inside DockedAction because the new Hide control
|
||||||
blocking shield. Explicit pending state keeps the correct shield mounted until
|
must dismiss the prompt and its dimming as one coherent surface. */}
|
||||||
the complete drive sequence finishes even as telemetry changes underneath it. */}
|
|
||||||
<div
|
<div
|
||||||
className={`absolute inset-0 z-[25] transition-all duration-300 ${
|
className={`absolute inset-0 z-[25] transition-all duration-300 ${
|
||||||
docked || pendingAction === 'undocking'
|
autoDocking || pendingAction === 'resuming'
|
||||||
? 'pointer-events-auto bg-black/75 opacity-100'
|
|
||||||
: autoDocking || pendingAction === 'resuming'
|
|
||||||
? 'pointer-events-auto bg-black/55 opacity-100'
|
? 'pointer-events-auto bg-black/55 opacity-100'
|
||||||
: 'pointer-events-none opacity-0'
|
: 'pointer-events-none opacity-0'
|
||||||
}`}
|
}`}
|
||||||
@@ -335,6 +359,7 @@ export default function DockingHud({ roverId }) {
|
|||||||
|
|
||||||
{docked || pendingAction === 'undocking' ? (
|
{docked || pendingAction === 'undocking' ? (
|
||||||
<DockedAction
|
<DockedAction
|
||||||
|
key={roverId}
|
||||||
driveKeyLabel={driveKeyLabel}
|
driveKeyLabel={driveKeyLabel}
|
||||||
pending={pendingAction === 'undocking'}
|
pending={pendingAction === 'undocking'}
|
||||||
controlsDisabled={!canControl}
|
controlsDisabled={!canControl}
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
// Initial Session Overlay
|
||||||
|
// Purpose: Hides incomplete driver-page placeholders until the first authoritative session snapshot arrives.
|
||||||
|
// Scope: Provides startup presentation only; it deliberately does not delay or alter page initialization underneath.
|
||||||
|
import { useSessionSelector } from '../../context/SessionContext.jsx';
|
||||||
|
import spinnerImage from '../../assets/spinner.png';
|
||||||
|
import './styles.css';
|
||||||
|
|
||||||
|
export default function InitialSessionOverlay() {
|
||||||
|
const connected = useSessionSelector((state) => Boolean(state.connected));
|
||||||
|
const sessionReady = useSessionSelector((state) => state.session !== null);
|
||||||
|
|
||||||
|
if (sessionReady) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="fixed inset-0 z-[1000] flex items-center justify-center bg-black text-slate-200"
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={connected ? 'Loading session' : 'Connecting'}
|
||||||
|
>
|
||||||
|
<div className="flex flex-col items-center gap-3">
|
||||||
|
{/* The source image is intentionally constrained to a small fixed box;
|
||||||
|
its intrinsic pixel dimensions must never determine overlay layout.
|
||||||
|
Reduced-motion users still see the identifying image without either
|
||||||
|
the rotation or continuously changing color. */}
|
||||||
|
<div className="initial-session-spinner-rotation h-20 w-20" aria-hidden="true">
|
||||||
|
<img
|
||||||
|
src={spinnerImage}
|
||||||
|
alt=""
|
||||||
|
draggable="false"
|
||||||
|
className="initial-session-spinner-image h-full w-full select-none object-contain"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="text-sm font-medium text-slate-300">
|
||||||
|
{connected ? 'Loading session…' : 'Connecting…'}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
These animations belong only to InitialSessionOverlay. Keeping them beside
|
||||||
|
the component avoids adding feature-specific behavior to the global styles.
|
||||||
|
Rotation and hue use separate elements so their independent infinite cycles
|
||||||
|
cannot overwrite one another's transform or filter properties.
|
||||||
|
*/
|
||||||
|
@keyframes initial-session-spinner-rotate {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes initial-session-spinner-hue {
|
||||||
|
from {
|
||||||
|
filter: hue-rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
filter: hue-rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: no-preference) {
|
||||||
|
.initial-session-spinner-rotation {
|
||||||
|
animation: initial-session-spinner-rotate 1.8s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.initial-session-spinner-image {
|
||||||
|
animation: initial-session-spinner-hue 2.8s linear infinite;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,9 +19,9 @@ function ControlRow({ label, keyLabel }) {
|
|||||||
function DesktopQuickstart({ keymap }) {
|
function DesktopQuickstart({ keymap }) {
|
||||||
return (
|
return (
|
||||||
<div className="space-y-0.5">
|
<div className="space-y-0.5">
|
||||||
<p className="text-sm text-slate-200">1. Press "Start Driving" put your rover into driving mode.</p>
|
<p className="text-sm text-slate-200">1. Click "Your rover is docked" to undock.</p>
|
||||||
<div className="space-y-0.5">
|
<div className="space-y-0.5">
|
||||||
<p className="text-sm text-slate-200">2. Use the drive controls to move your rover:</p>
|
<p className="text-sm text-slate-200">2. Drive with these keybindings:</p>
|
||||||
<div className="space-y-0.5">
|
<div className="space-y-0.5">
|
||||||
<ControlRow label="Forward" keyLabel={formatKeyLabel(keymap?.driveForward?.[0])} />
|
<ControlRow label="Forward" keyLabel={formatKeyLabel(keymap?.driveForward?.[0])} />
|
||||||
<ControlRow label="Backward" keyLabel={formatKeyLabel(keymap?.driveBackward?.[0])} />
|
<ControlRow label="Backward" keyLabel={formatKeyLabel(keymap?.driveBackward?.[0])} />
|
||||||
@@ -31,7 +31,8 @@ function DesktopQuickstart({ keymap }) {
|
|||||||
<ControlRow label="Move slower" keyLabel={formatKeyLabel(keymap?.slowModifier?.[0])} />
|
<ControlRow label="Move slower" keyLabel={formatKeyLabel(keymap?.slowModifier?.[0])} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-slate-200">3. When done, enter "Docking Assist" and line up the front sensor with the dock sensor.</p>
|
<p className="text-sm text-slate-200">3. Use the video HUD for rover controls and information.</p>
|
||||||
|
<p className="text-sm text-slate-200">4. Click "Dock rover" when finished.</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -39,10 +40,11 @@ function DesktopQuickstart({ keymap }) {
|
|||||||
function MobileQuickstart() {
|
function MobileQuickstart() {
|
||||||
return (
|
return (
|
||||||
<div className="space-y-0.5 text-sm text-slate-200">
|
<div className="space-y-0.5 text-sm text-slate-200">
|
||||||
<p>1. Press "Start Driving" put your rover into driving mode.</p>
|
<p>1. Tap "Your rover is docked" to undock.</p>
|
||||||
<p>2. Touch and hold in Joystick area to move.</p>
|
<p>2. Hold and drag on the drive pad.</p>
|
||||||
<p>3. Use the other column for motor, horn, and camera controls.</p>
|
<p>3. Choose Precision, Normal, or Turbo above the drive pad.</p>
|
||||||
<p>4. When done, enter "Docking Assist" and line up the front sensor with the dock sensor.</p>
|
<p>4. Use the other column for rover controls.</p>
|
||||||
|
<p>5. Tap "Dock and charge" when finished.</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -71,7 +73,6 @@ export default function QuickstartOverlay({
|
|||||||
layout,
|
layout,
|
||||||
showOnLoad,
|
showOnLoad,
|
||||||
onToggleShowOnLoad,
|
onToggleShowOnLoad,
|
||||||
onOpenHelp,
|
|
||||||
onClose,
|
onClose,
|
||||||
}) {
|
}) {
|
||||||
const rawKeymap = useControlSelector((control) => control.state.keymap);
|
const rawKeymap = useControlSelector((control) => control.state.keymap);
|
||||||
|
|||||||
@@ -87,10 +87,6 @@ function DriverPageContent({ layout, oldDesktop }) {
|
|||||||
},
|
},
|
||||||
[saveQuickstartSettings],
|
[saveQuickstartSettings],
|
||||||
);
|
);
|
||||||
const openHelpFromQuickstart = useCallback(() => {
|
|
||||||
setQuickstartVisible(false);
|
|
||||||
setHelpVisible(true);
|
|
||||||
}, []);
|
|
||||||
return (
|
return (
|
||||||
<ControlSystemProvider>
|
<ControlSystemProvider>
|
||||||
{/*
|
{/*
|
||||||
@@ -127,7 +123,6 @@ function DriverPageContent({ layout, oldDesktop }) {
|
|||||||
layout={layout}
|
layout={layout}
|
||||||
showOnLoad={quickstartSettings?.showOnLoad !== false}
|
showOnLoad={quickstartSettings?.showOnLoad !== false}
|
||||||
onToggleShowOnLoad={setQuickstartShowOnLoad}
|
onToggleShowOnLoad={setQuickstartShowOnLoad}
|
||||||
onOpenHelp={openHelpFromQuickstart}
|
|
||||||
onClose={closeQuickstart}
|
onClose={closeQuickstart}
|
||||||
/>
|
/>
|
||||||
</ControlSystemProvider>
|
</ControlSystemProvider>
|
||||||
|
|||||||
+60
-27
@@ -11,26 +11,44 @@ export const HELP_CONTENT = {
|
|||||||
type: 'list',
|
type: 'list',
|
||||||
title: 'Chat and nicknames',
|
title: 'Chat and nicknames',
|
||||||
items: [
|
items: [
|
||||||
'Set a nickname in the user list panel, on the bottom left of the page below the rover video.',
|
'Chat and nickname controls are in the Chat/Rovers tab.',
|
||||||
{ segments: ['Toggle chat focus with ', { action: 'chatFocus' }, '. Press ', { action: 'chatFocus'}, ' again to send.'] },
|
{ segments: ['Open the HUD chat composer with ', { action: 'chatFocus' }, '. Press ', { action: 'chatFocus'}, ' again to send.'] },
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'list',
|
type: 'list',
|
||||||
title: 'Driving the rover',
|
title: 'Driving the rover',
|
||||||
items: [
|
items: [
|
||||||
{ segments: ['Press the "Start Driving" button onscreen, or press ' , { action: 'driveMacro' }, ' on your keyboard to put the rover into driving mode.'] },
|
{ segments: ['Click "Your rover is docked", or press ', { action: 'driveMacro' }, ', to undock.'] },
|
||||||
'Refer to the controls for the controls for the rover.'
|
'Drive with the movement keybindings.',
|
||||||
|
'Rover controls dim while another person has the turn.',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'list',
|
||||||
|
title: 'Video HUD',
|
||||||
|
items: [
|
||||||
|
'Top left shows the rover name and turns.',
|
||||||
|
'Top right shows battery and rover status.',
|
||||||
|
'Bottom left contains horn, headlight, and laser controls.',
|
||||||
|
'Bottom right contains camera tilt and chat.',
|
||||||
|
'Use the arrows to open and close pods and their expansions.',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'list',
|
||||||
|
title: 'Page layout',
|
||||||
|
items: [
|
||||||
|
'Room, Activities, and VIP are in the left sidebar.',
|
||||||
|
'Chat/Rovers, Help, and Settings are in the right sidebar.',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'list',
|
type: 'list',
|
||||||
title: 'Docking the rover',
|
title: 'Docking the rover',
|
||||||
items: [
|
items: [
|
||||||
'If the rover shows "Docking in Progress", it is already auto-seeking the dock.',
|
{ segments: ['Click "Dock rover", or press ', { action: 'dockMacro' }, '.'] },
|
||||||
'To dock manually, enter Docking Assist from the drive panel.',
|
'Click "Rover is docking itself" to resume driving.',
|
||||||
{ segments: ['Press "Enter Docking Assist", or press ', { action: 'dockMacro' }, '.'] },
|
|
||||||
'In assist mode, camera tilts down and driving speed is limited for precise alignment.',
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -56,8 +74,8 @@ export const HELP_CONTENT = {
|
|||||||
id: 'macros',
|
id: 'macros',
|
||||||
title: 'Rover modes & chat',
|
title: 'Rover modes & chat',
|
||||||
items: [
|
items: [
|
||||||
{ action: 'driveMacro', label: 'Drive macro' },
|
{ action: 'driveMacro', label: 'Undock / resume driving' },
|
||||||
{ action: 'dockMacro', label: 'Docking assist toggle' },
|
{ action: 'dockMacro', label: 'Dock rover' },
|
||||||
{ action: 'chatFocus', label: 'Chat focus' },
|
{ action: 'chatFocus', label: 'Chat focus' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -119,27 +137,35 @@ export const HELP_CONTENT = {
|
|||||||
type: 'list',
|
type: 'list',
|
||||||
title: 'Chat and nicknames',
|
title: 'Chat and nicknames',
|
||||||
items: [
|
items: [
|
||||||
'Set a nickname in the user list panel below.',
|
'Chat and nickname controls are in the Chat tab.',
|
||||||
'Tap in the chat box to send messages in the chat.'
|
'Tap the chat box to send a message.',
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'list',
|
type: 'list',
|
||||||
title: 'Driving the rover',
|
title: 'Driving the rover',
|
||||||
items: [
|
items: [
|
||||||
{ segments: ['Press the "Start Driving" button onscreen to put the rover into driving mode.'] },
|
'Tap "Your rover is docked" to undock.',
|
||||||
'Look below the rover video. Use the joystick column to move the rover, and hold the aux buttons in the other control column.'
|
'Hold and drag on the drive pad.',
|
||||||
|
'Choose Precision, Normal, or Turbo above the drive pad.',
|
||||||
|
'Use the other column for rover controls.',
|
||||||
|
'Rover controls dim while another person has the turn.',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'list',
|
type: 'list',
|
||||||
title: 'Docking the rover',
|
title: 'Docking the rover',
|
||||||
items: [
|
items: [
|
||||||
'If you see "Docking in Progress", the rover is currently auto-seeking the dock.',
|
'Tap "Dock and charge" when finished.',
|
||||||
{ segments: ['For manual docking, press "Enter Docking Assist".'] },
|
|
||||||
'Assist mode tilts camera down and limits speed for precise alignment.',
|
|
||||||
],
|
],
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
type: 'list',
|
||||||
|
title: 'More controls',
|
||||||
|
items: [
|
||||||
|
'Chat, Activities, VIP, Room Controls, Help, and Settings are below the rover controls.',
|
||||||
|
],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
'mobile-landscape': {
|
'mobile-landscape': {
|
||||||
@@ -148,28 +174,35 @@ export const HELP_CONTENT = {
|
|||||||
type: 'list',
|
type: 'list',
|
||||||
title: 'Chat and nicknames',
|
title: 'Chat and nicknames',
|
||||||
items: [
|
items: [
|
||||||
'Scroll down to see more of the page.',
|
'Chat and nickname controls are in the Chat tab.',
|
||||||
'Set a nickname in the user list panel below.',
|
'Tap the chat box to send a message.',
|
||||||
'Tap in the chat box to send messages in the chat.'
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'list',
|
type: 'list',
|
||||||
title: 'Driving the rover',
|
title: 'Driving the rover',
|
||||||
items: [
|
items: [
|
||||||
{ segments: ['Press the "Start Driving" button, or the "Drive" button to put the rover into driving mode.'] },
|
'Tap "Your rover is docked" to undock.',
|
||||||
'Use the joystick column beside the video feed to move the rover, and hold the aux buttons in the other control column.'
|
'Hold and drag on the drive pad.',
|
||||||
|
'Choose Precision, Normal, or Turbo above the drive pad.',
|
||||||
|
'Use the other column for rover controls.',
|
||||||
|
'Rover controls dim while another person has the turn.',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'list',
|
type: 'list',
|
||||||
title: 'Docking the rover',
|
title: 'Docking the rover',
|
||||||
items: [
|
items: [
|
||||||
'If you see "Docking in Progress", the rover is currently auto-seeking the dock.',
|
'Tap "Dock and charge" when finished.',
|
||||||
{ segments: ['For manual docking, press "Enter Docking Assist" (or "Dock" button).'] },
|
|
||||||
'Assist mode tilts camera down and limits speed for precise alignment.',
|
|
||||||
],
|
],
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
type: 'list',
|
||||||
|
title: 'More controls',
|
||||||
|
items: [
|
||||||
|
'Chat, Activities, VIP, Room Controls, Help, and Settings are below the rover controls.',
|
||||||
|
],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
// aside: [
|
// aside: [
|
||||||
// {
|
// {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import { SettingsProvider } from './settings/index.js'
|
|||||||
import DeterrenceChaos from './components/DeterrenceChaos/index.jsx'
|
import DeterrenceChaos from './components/DeterrenceChaos/index.jsx'
|
||||||
import AnalyticsReporter from './analytics/AnalyticsReporter.jsx'
|
import AnalyticsReporter from './analytics/AnalyticsReporter.jsx'
|
||||||
import PtzAppRoot from './ptz/PtzAppRoot.jsx'
|
import PtzAppRoot from './ptz/PtzAppRoot.jsx'
|
||||||
|
import InitialSessionOverlay from './components/InitialSessionOverlay/index.jsx'
|
||||||
|
|
||||||
// The reporting route includes the charting and CSV libraries. Loading that
|
// The reporting route includes the charting and CSV libraries. Loading that
|
||||||
// bundle only when `/reports` is visited keeps ordinary rover-control sessions
|
// bundle only when `/reports` is visited keeps ordinary rover-control sessions
|
||||||
@@ -31,6 +32,11 @@ createRoot(document.getElementById('root')).render(
|
|||||||
<StrictMode>
|
<StrictMode>
|
||||||
<SocketProvider>
|
<SocketProvider>
|
||||||
<SessionProvider>
|
<SessionProvider>
|
||||||
|
{/* Every route depends on the first authoritative session snapshot.
|
||||||
|
Mounting this opaque layer at the shared provider boundary prevents
|
||||||
|
incomplete route-specific placeholders from flashing while still
|
||||||
|
allowing every application tree to initialize underneath it. */}
|
||||||
|
<InitialSessionOverlay />
|
||||||
<TelemetryProvider>
|
<TelemetryProvider>
|
||||||
<SettingsProvider>
|
<SettingsProvider>
|
||||||
<ChatProvider>
|
<ChatProvider>
|
||||||
|
|||||||
Reference in New Issue
Block a user