mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-17 01:50:47 -04:00
glorp!
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
import { useRef } from 'react';
|
||||
import { FaBullhorn, FaCrosshairs, FaLightbulb } from 'react-icons/fa';
|
||||
import { useControlActions, useControlSelector } from '../../../../controls/index.js';
|
||||
import { formatKeyLabel } from '../../../../controls/keymapUtils.js';
|
||||
import ControlHint from '../../../ControlHint/index.jsx';
|
||||
import { useSessionSelector } from '../../../../context/SessionContext.jsx';
|
||||
import useCanControlRover from '../../../../hooks/useCanControlRover.js';
|
||||
import KeyPill from '../../../vip/VipAudioUploadCard/KeyPill.jsx';
|
||||
@@ -45,7 +45,6 @@ export default function BottomLeftPod({ roverId }) {
|
||||
const headlightOn = useControlSelector((control) => Boolean(control.pipeline?.headlightState?.headlightOn));
|
||||
const laserOn = useControlSelector((control) => Boolean(control.pipeline?.laserState?.laserOn));
|
||||
const hornActive = useControlSelector((control) => Boolean(control.state.horn?.active));
|
||||
const keymap = useControlSelector((control) => control.state.keymap);
|
||||
const { setHeadlight, setLaser, startHorn, stopHorn } = useControlActions();
|
||||
const canControl = useCanControlRover(roverId);
|
||||
const hornPointerRef = useRef(null);
|
||||
@@ -80,13 +79,13 @@ export default function BottomLeftPod({ roverId }) {
|
||||
{/* Physical rover actions become visibly and behaviorally unavailable
|
||||
while another queued driver owns the turn. Pod/settings controls
|
||||
remain interactive because they do not mutate rover hardware. */}
|
||||
{hornDevice ? <RoundControl label="Horn" icon={FaBullhorn} keyLabel={formatKeyLabel(keymap?.hornHonk?.[0])} active={hornActive} tone="horn" disabled={!canControl} large onPointerDown={startHornPointer} onPointerUp={stopHornPointer} className="absolute bottom-1 left-1" /> : null}
|
||||
{headlight ? <RoundControl label="Headlight" icon={FaLightbulb} keyLabel={formatKeyLabel(keymap?.headlightToggle?.[0])} active={headlightOn} disabled={!canControl} onClick={() => setHeadlight(!headlightOn)} className="absolute left-[1.979rem] top-[0.662rem]" /> : null}
|
||||
{hornDevice ? <RoundControl label="Horn" icon={FaBullhorn} keyLabel={<ControlHint actionId="hornHonk" />} active={hornActive} tone="horn" disabled={!canControl} large onPointerDown={startHornPointer} onPointerUp={stopHornPointer} className="absolute bottom-1 left-1" /> : null}
|
||||
{headlight ? <RoundControl label="Headlight" icon={FaLightbulb} keyLabel={<ControlHint actionId="headlightToggle" />} active={headlightOn} disabled={!canControl} onClick={() => setHeadlight(!headlightOn)} className="absolute left-[1.979rem] top-[0.662rem]" /> : null}
|
||||
{/* The room-light lock deliberately blocks laser activation because
|
||||
the laser is only intended for use while the room is dark. This
|
||||
mirrors the old desktop control's visible disabled state; turn
|
||||
ownership remains the other independent control restriction. */}
|
||||
{laser ? <RoundControl label="Laser" icon={FaCrosshairs} keyLabel={formatKeyLabel(keymap?.laserToggle?.[0])} active={laserOn} disabled={!canControl || roomLightsLockedOn} onClick={() => setLaser(!laserOn)} className="absolute left-[5.338rem] top-[4.021rem]" /> : null}
|
||||
{laser ? <RoundControl label="Laser" icon={FaCrosshairs} keyLabel={<ControlHint actionId="laserToggle" />} active={laserOn} disabled={!canControl || roomLightsLockedOn} onClick={() => setLaser(!laserOn)} className="absolute left-[5.338rem] top-[4.021rem]" /> : null}
|
||||
<CornerPodToggle corner="bottom-left" expanded label="Hide rover controls" onClick={() => setOpen(false)} />
|
||||
</div>
|
||||
) : (
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { useCallback } from 'react';
|
||||
import { FaVideo } from 'react-icons/fa';
|
||||
import { useControlActions, useControlSelector } from '../../../../controls/index.js';
|
||||
import { formatKeyLabel } from '../../../../controls/keymapUtils.js';
|
||||
import ControlHint from '../../../ControlHint/index.jsx';
|
||||
import useCanControlRover from '../../../../hooks/useCanControlRover.js';
|
||||
import { useDriverLayout } from '../../../../layouts/driver/DriverLayoutContext.jsx';
|
||||
import KeyPill from '../../../vip/VipAudioUploadCard/KeyPill.jsx';
|
||||
@@ -32,7 +32,6 @@ export default function BottomRightPod({ roverId }) {
|
||||
const [open, setOpen] = usePodVisibility('camera', true);
|
||||
const camera = useControlSelector((control) => control.state.camera);
|
||||
const dockAssistActive = useControlSelector((control) => Boolean(control.state.manualDockAssist?.active));
|
||||
const keymap = useControlSelector((control) => control.state.keymap);
|
||||
const { setServoAngle } = useControlActions();
|
||||
const canControl = useCanControlRover(roverId);
|
||||
const config = camera?.config;
|
||||
@@ -86,8 +85,8 @@ export default function BottomRightPod({ roverId }) {
|
||||
</button>
|
||||
{/* These positions continue around the same circle just beyond the two slider endpoints.
|
||||
Together they occupy the open third facing the corner without enlarging the pod. */}
|
||||
<div className="absolute left-[61%] top-[90%] -translate-x-1/2 -translate-y-1/2"><KeyPill label={formatKeyLabel(keymap?.cameraDown?.[0])} /></div>
|
||||
<div className="absolute left-[90%] top-[61%] -translate-x-1/2 -translate-y-1/2"><KeyPill label={formatKeyLabel(keymap?.cameraUp?.[0])} /></div>
|
||||
<div className="absolute left-[61%] top-[90%] -translate-x-1/2 -translate-y-1/2"><KeyPill label={<ControlHint actionId="cameraDown" />} /></div>
|
||||
<div className="absolute left-[90%] top-[61%] -translate-x-1/2 -translate-y-1/2"><KeyPill label={<ControlHint actionId="cameraUp" />} /></div>
|
||||
<CornerPodToggle corner="bottom-right" expanded label="Hide camera tilt" onClick={() => setOpen(false)} />
|
||||
</div>
|
||||
) : showCameraControls && enabled ? (
|
||||
|
||||
@@ -4,14 +4,12 @@ import { useCallback, useState } from 'react';
|
||||
import { FaComment } from 'react-icons/fa';
|
||||
import { useChatActions } from '../../../../context/ChatContext.jsx';
|
||||
import { useSessionSelector } from '../../../../context/SessionContext.jsx';
|
||||
import { useControlSelector } from '../../../../controls/index.js';
|
||||
import { formatKeyLabel } from '../../../../controls/keymapUtils.js';
|
||||
import ControlHint from '../../../ControlHint/index.jsx';
|
||||
import HudChatInput from '../../HudChatInput/index.jsx';
|
||||
import KeyPill from '../../../vip/VipAudioUploadCard/KeyPill.jsx';
|
||||
|
||||
export default function ChatExpansion({ podOpen }) {
|
||||
const role = useSessionSelector((state) => state.session?.role || null);
|
||||
const chatKeyLabel = useControlSelector((control) => formatKeyLabel(control.state.keymap?.chatFocus?.[0]));
|
||||
const { blurChat, focusChat } = useChatActions();
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
@@ -50,7 +48,7 @@ export default function ChatExpansion({ podOpen }) {
|
||||
<FaComment aria-hidden="true" />
|
||||
{/* The pill reflects the live keymap so remapping chat focus updates this
|
||||
compact HUD hint without duplicating or hardcoding the default key. */}
|
||||
{chatKeyLabel ? <KeyPill label={chatKeyLabel} /> : null}
|
||||
<KeyPill label={<ControlHint actionId="chatFocus" />} />
|
||||
</button>
|
||||
|
||||
<HudChatInput variant="newdrive" open={open} onOpenChange={setChatOpen} />
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
// the archived desktop layout retains its previous DriveDockAction behavior.
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { FaChargingStation } from 'react-icons/fa';
|
||||
import { useControlActions, useControlSelector } from '../../../../controls/index.js';
|
||||
import { formatKeyLabel } from '../../../../controls/keymapUtils.js';
|
||||
import { useControlActions } from '../../../../controls/index.js';
|
||||
import ControlHint from '../../../ControlHint/index.jsx';
|
||||
import { useTelemetrySelector } from '../../../../context/TelemetryContext.jsx';
|
||||
import { dockTelemetryEqual, selectDockTelemetry } from '../../../../context/telemetryViews.js';
|
||||
import { useManualDockAssist } from '../../../../features/manualDockAssist/useManualDockAssist.js';
|
||||
@@ -252,7 +252,6 @@ function UndockTransitionGhost({ onFinish }) {
|
||||
export default function DockingHud({ roverId }) {
|
||||
const layout = useDriverLayout();
|
||||
const actions = useControlActions();
|
||||
const keymap = useControlSelector((control) => control.state.keymap);
|
||||
const dockTelemetry = useTelemetrySelector(roverId, selectDockTelemetry, dockTelemetryEqual);
|
||||
// This replaces ManualDockAssistOverlay as the current HUD's one lifecycle owner. It preserves the
|
||||
// success sounds, camera positioning, speed cap, and automatic exit after charging begins.
|
||||
@@ -282,12 +281,8 @@ export default function DockingHud({ roverId }) {
|
||||
/* Mobile already presents its own touch-oriented driving controls. The docked
|
||||
action therefore keeps its plain-language instruction without advertising a
|
||||
keyboard shortcut that is irrelevant on that layout. */
|
||||
const driveKeyLabel = layout === 'desktop'
|
||||
? formatKeyLabel(keymap?.driveMacro?.[0])
|
||||
: '';
|
||||
const dockKeyLabel = layout === 'desktop'
|
||||
? formatKeyLabel(keymap?.dockMacro?.[0])
|
||||
: '';
|
||||
const driveKeyLabel = layout === 'desktop' ? <ControlHint actionId="driveMacro" /> : '';
|
||||
const dockKeyLabel = layout === 'desktop' ? <ControlHint actionId="dockMacro" /> : '';
|
||||
const batteryPodOpen = podSettings?.battery !== false;
|
||||
// The camera arc is the shared circular-pod reference size. Keep the dock expansion flush
|
||||
// against the battery shell after enlarging that gauge to the same 8.5-rem footprint.
|
||||
|
||||
Reference in New Issue
Block a user