mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-15 17:12:59 -04:00
updated mobile page
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -11,7 +11,7 @@
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||
<meta name="apple-mobile-web-app-title" content="Multi Roomba Rover" />
|
||||
<title>Multi Roomba Rover</title>
|
||||
<script type="module" crossorigin src="/assets/index-IngetVG6.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-DcfJLiso.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-DCrU2sZz.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
+6
-4
@@ -1,6 +1,6 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import TelemetryPanel from './components/TelemetryPanel.jsx';
|
||||
import ControlSummary from './components/ControlSummary.jsx';
|
||||
import ControlSummary, { RoverRosterPanel } from './components/ControlSummary.jsx';
|
||||
import AlertFeed from './components/AlertFeed.jsx';
|
||||
import MobileControls, {
|
||||
MobileLandscapeAuxColumn,
|
||||
@@ -125,8 +125,9 @@ function MobileFeatureTabs({
|
||||
function MobilePortraitLayout({ onOpenHelpOverlay }) {
|
||||
return (
|
||||
<div className="flex flex-col gap-0.5">
|
||||
<DriverVideoPanel layoutFormat='mobile'/>
|
||||
<DriverVideoPanel layoutFormat="mobile-portrait" />
|
||||
<MobileControls />
|
||||
<RoverRosterPanel />
|
||||
{/* <ControlSummary /> */}
|
||||
<MobileFeatureTabs
|
||||
layout="mobile-portrait"
|
||||
@@ -143,8 +144,9 @@ function MobileLandscapeLayout({ onOpenHelpOverlay }) {
|
||||
<section className="grid min-h-screen grid-cols-[minmax(0,0.7fr)_minmax(0,2.1fr)_minmax(0,0.7fr)] gap-0.5">
|
||||
<MobileLandscapeAuxColumn />
|
||||
<div>
|
||||
<DriverVideoPanel layoutFormat='mobile'/>
|
||||
<TelemetryPanel />
|
||||
<DriverVideoPanel layoutFormat="mobile-landscape" />
|
||||
<RoverRosterPanel />
|
||||
{/* <TelemetryPanel /> */}
|
||||
</div>
|
||||
<MobileLandscapeControlColumn />
|
||||
</section>
|
||||
|
||||
@@ -7,21 +7,12 @@ import TopDownMap from './TopDownMap.jsx';
|
||||
import RoverRoster from './RoverRoster.jsx';
|
||||
import DriveDockAction, { useDriveDockState } from './DriveDockAction.jsx';
|
||||
|
||||
export default function ControlSummary() {
|
||||
export function RoverRosterPanel({ title = 'Rovers' }) {
|
||||
const { session, requestControl } = useSession();
|
||||
const {
|
||||
state: { roverId, keymap },
|
||||
} = useControlSystem();
|
||||
const frame = useTelemetryFrame(roverId);
|
||||
const sensors = frame?.sensors || {};
|
||||
const driveDockState = useDriveDockState(roverId);
|
||||
const roster = session?.roster ?? [];
|
||||
const [pending, setPending] = useState({});
|
||||
|
||||
const canRequest = useMemo(() => session?.role && session.role !== 'spectator', [session?.role]);
|
||||
|
||||
const hideInlineControls = driveDockState.docked && !driveDockState.driving;
|
||||
|
||||
async function handleRequest(targetRoverId) {
|
||||
if (!targetRoverId) return;
|
||||
setPending((prev) => ({ ...prev, [targetRoverId]: true }));
|
||||
@@ -34,6 +25,35 @@ export default function ControlSummary() {
|
||||
}
|
||||
}
|
||||
|
||||
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({ showRoster = true }) {
|
||||
const {
|
||||
state: { roverId, keymap },
|
||||
} = useControlSystem();
|
||||
const frame = useTelemetryFrame(roverId);
|
||||
const sensors = frame?.sensors || {};
|
||||
const driveDockState = useDriveDockState(roverId);
|
||||
const hideInlineControls = driveDockState.docked && !driveDockState.driving;
|
||||
|
||||
return (
|
||||
<section className="panel-section">
|
||||
<div className="grid items-stretch gap-1 md:grid-cols-[minmax(0,2fr)_minmax(0,1fr)] md:min-h-[22rem]">
|
||||
@@ -49,22 +69,7 @@ export default function ControlSummary() {
|
||||
{!hideInlineControls ? <InlineCameraTilt keymap={keymap} /> : null}
|
||||
</div>
|
||||
</div>
|
||||
<RoverRoster
|
||||
title="Rovers"
|
||||
roster={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
|
||||
}
|
||||
/>
|
||||
{showRoster ? <RoverRosterPanel /> : null}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -368,6 +368,7 @@ export default function VideoTile({
|
||||
status={renderedStatus}
|
||||
audioStatus={renderedAudioStatus}
|
||||
desktopLayout={desktopLayout}
|
||||
layoutFormat={layoutFormat}
|
||||
variant={hudVariant}
|
||||
driverLabel={driverLabel}
|
||||
battery={batteryVisual}
|
||||
@@ -484,6 +485,7 @@ function HudOverlay({
|
||||
status,
|
||||
audioStatus,
|
||||
desktopLayout = true,
|
||||
layoutFormat = 'desktop',
|
||||
variant = 'default',
|
||||
driverLabel = null,
|
||||
battery,
|
||||
@@ -502,12 +504,13 @@ function HudOverlay({
|
||||
|
||||
const pulse = frame?.receivedAt ? now - frame.receivedAt < 200 : false;
|
||||
const isMobile = mobileHud;
|
||||
const portraitMobile = layoutFormat === 'mobile-portrait';
|
||||
const statusTextClass = isMobile ? 'text-[0.55rem]' : 'text-[0.65rem]';
|
||||
const statusPadClass = isMobile ? 'px-0.5 py-0.25' : 'px-1 py-0.5';
|
||||
const labelPadClass = isMobile ? 'px-0.5 py-0.25' : 'px-0.5 py-0.5';
|
||||
const labelTextClass = isMobile ? 'text-[0.7rem]' : 'text-[0.8rem]';
|
||||
const mapSize = isMobile ? '240px' : '240px';
|
||||
const mapScale = isMobile ? 0.45 : 0.7;
|
||||
const mapSize = '240px';
|
||||
const mapScale = portraitMobile ? 0.36 : isMobile ? 0.45 : 0.7;
|
||||
const mapOpacity = isMobile ? 0.85 : 0.7;
|
||||
const mapStyle = {
|
||||
width: mapSize,
|
||||
|
||||
Reference in New Issue
Block a user