mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 01:21:20 -04:00
fixing up mobile layouts
This commit is contained in:
+15
-9
@@ -72,8 +72,10 @@ function DesktopLayout({ layout }) {
|
||||
function MobilePortraitLayout() {
|
||||
return (
|
||||
<div className="flex flex-col gap-0.5">
|
||||
<DriverVideoPanel />
|
||||
<DriverVideoPanel layoutFormat='mobile'/>
|
||||
<MobileControls />
|
||||
<ChatPanel />
|
||||
<UserListPanel />
|
||||
<DrivePanel />
|
||||
<TelemetryPanel />
|
||||
<AuthPanel />
|
||||
@@ -90,23 +92,27 @@ function MobileLandscapeLayout() {
|
||||
<div className="flex flex-col gap-0.5">
|
||||
<section className="grid min-h-screen grid-cols-[minmax(0,0.7fr)_minmax(0,2.1fr)_minmax(0,0.7fr)] gap-0.5">
|
||||
<MobileLandscapeAuxColumn />
|
||||
<DriverVideoPanel />
|
||||
<div>
|
||||
<DriverVideoPanel layoutFormat='mobile'/>
|
||||
<TelemetryPanel />
|
||||
</div>
|
||||
<MobileLandscapeControlColumn />
|
||||
</section>
|
||||
<div className="flex flex-col gap-0.5 pb-0.5">
|
||||
<RoomCameraPanel />
|
||||
<HomeAssistantControls />
|
||||
<DrivePanel />
|
||||
<section className="grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)] gap-0.5">
|
||||
<div className="flex flex-col gap-0.5">
|
||||
<AuthPanel />
|
||||
<AdminPanel />
|
||||
{/* <AuthPanel /> */}
|
||||
{/* <AdminPanel /> */}
|
||||
<UserListPanel />
|
||||
</div>
|
||||
<div className="flex flex-col gap-0.5">
|
||||
<LogPanel />
|
||||
<TelemetryPanel />
|
||||
{/* <LogPanel /> */}
|
||||
<ChatPanel />
|
||||
</div>
|
||||
</section>
|
||||
<RoomCameraPanel />
|
||||
<HomeAssistantControls />
|
||||
{/* <DrivePanel /> */}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useTelemetryFrame } from '../context/TelemetryContext.jsx';
|
||||
import { useVideoRequests } from '../hooks/useVideoRequests.js';
|
||||
import VideoTile from './VideoTile.jsx';
|
||||
|
||||
export default function DriverVideoPanel() {
|
||||
export default function DriverVideoPanel({layoutFormat = 'desktop'}) {
|
||||
const { session } = useSession();
|
||||
const roverId = session?.assignment?.roverId;
|
||||
const sources = useVideoRequests(roverId ? [roverId] : []);
|
||||
@@ -20,7 +20,7 @@ export default function DriverVideoPanel() {
|
||||
return (
|
||||
<section className="panel">
|
||||
{roverId ? (
|
||||
<VideoTile sessionInfo={info} label={roverLabel} telemetryFrame={frame} batteryConfig={batteryConfig} />
|
||||
<VideoTile sessionInfo={info} label={roverLabel} telemetryFrame={frame} batteryConfig={batteryConfig} layoutFormat={layoutFormat}/>
|
||||
) : (
|
||||
<div className="panel-muted content-center text-center text-sm text-slate-400 aspect-video">
|
||||
<p>You are not assigned to a rover.</p>
|
||||
|
||||
@@ -7,13 +7,13 @@ const SOURCE = 'mobile-joystick';
|
||||
const JOYSTICK_RADIUS = 80;
|
||||
const JOYSTICK_SMOOTHING = 0.15;
|
||||
const AUX_BUTTONS = [
|
||||
{ id: 'main-forward', label: 'Main +', values: { main: 127 }, hold: true, color: 'bg-emerald-600' },
|
||||
{ id: 'main-reverse', label: 'Main -', values: { main: -127 }, hold: true, color: 'bg-emerald-800' },
|
||||
{ id: 'side-forward', label: 'Side +', values: { side: 127 }, hold: true, color: 'bg-cyan-600' },
|
||||
{ id: 'side-reverse', label: 'Side -', values: { side: -70 }, hold: true, color: 'bg-cyan-800' },
|
||||
{ id: 'main-forward', label: 'Main Brush +', values: { main: 127 }, hold: true, color: 'bg-emerald-600' },
|
||||
{ id: 'main-reverse', label: 'Main Brush -', values: { main: -127 }, hold: true, color: 'bg-emerald-800' },
|
||||
{ id: 'all-forward', label: 'All Motors +', values: { main: 127, side: 127, vacuum: 127 }, hold: true, color: 'bg-fuchsia-600' },
|
||||
{ id: 'side-forward', label: 'Side Brush +', values: { side: 127 }, hold: true, color: 'bg-cyan-600' },
|
||||
{ id: 'side-reverse', label: 'Side Brush -', values: { side: -70 }, hold: true, color: 'bg-cyan-800' },
|
||||
{ id: 'vacuum-fast', label: 'Vacuum Max', values: { vacuum: 127 }, hold: true, color: 'bg-amber-500 text-amber-950' },
|
||||
{ id: 'vacuum-slow', label: 'Vacuum Low', values: { vacuum: 50 }, hold: true, color: 'bg-amber-700' },
|
||||
{ id: 'all-forward', label: 'All +', values: { main: 127, side: 127, vacuum: 127 }, hold: true, color: 'bg-fuchsia-600' },
|
||||
{ id: 'stop-all', label: 'Stop', values: { main: 0, side: 0, vacuum: 0 }, hold: false, color: 'bg-slate-900' },
|
||||
];
|
||||
|
||||
@@ -196,17 +196,8 @@ function MobileJoystickPanel({ layout }) {
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-0.5 text-slate-100">
|
||||
|
||||
<DriveModeToggle size="compact" />
|
||||
<FloatingJoystick
|
||||
disabled={disabled}
|
||||
layout={layout}
|
||||
radius={joystickRadius}
|
||||
onMove={handleMove}
|
||||
onStop={handleStop}
|
||||
/>
|
||||
<button type="button" onClick={stopAllMotion} disabled={disabled} className="button-danger w-full disabled:opacity-40">
|
||||
Panic Stop
|
||||
</button>
|
||||
{cameraEnabled && (
|
||||
<div className="bg-zinc-950 p-0.5 text-xs">
|
||||
<div className="flex items-center justify-between text-[0.75rem] text-slate-400">
|
||||
@@ -224,6 +215,17 @@ function MobileJoystickPanel({ layout }) {
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<FloatingJoystick
|
||||
disabled={disabled}
|
||||
layout={layout}
|
||||
radius={joystickRadius}
|
||||
onMove={handleMove}
|
||||
onStop={handleStop}
|
||||
/>
|
||||
<button type="button" onClick={stopAllMotion} disabled={disabled} className="button-danger w-full disabled:opacity-40">
|
||||
Panic Stop
|
||||
</button>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -280,7 +282,7 @@ function AuxMotorPanel({ orientation }) {
|
||||
onPointerLeave={() => handleRelease(button)}
|
||||
onPointerCancel={() => handleRelease(button)}
|
||||
onContextMenu={(event) => event.preventDefault()}
|
||||
className={`px-0.5 py-0.5 text-left text-sm font-semibold text-white transition ${button.color} hover:brightness-110 disabled:opacity-30`}
|
||||
className={`px-0.5 py-0.5 text-left text-sm font-semibold text-white transition ${button.color} hover:brightness-110 disabled:opacity-30 h-10`}
|
||||
>
|
||||
{button.label}
|
||||
</button>
|
||||
|
||||
@@ -4,7 +4,7 @@ import { WhepPlayer } from '../lib/whepPlayer.js';
|
||||
const RESTART_DELAY_MS = 2000;
|
||||
const UNMUTE_RETRY_MS = 3000;
|
||||
|
||||
export default function VideoTile({ sessionInfo, label, forceMute = false, telemetryFrame, batteryConfig }) {
|
||||
export default function VideoTile({ sessionInfo, label, forceMute = false, telemetryFrame, batteryConfig, layoutFormat = 'desktop' }) {
|
||||
const videoRef = useRef(null);
|
||||
const restartTimer = useRef(null);
|
||||
const unmuteTimer = useRef(null);
|
||||
@@ -14,6 +14,7 @@ export default function VideoTile({ sessionInfo, label, forceMute = false, telem
|
||||
const [muted, setMuted] = useState(true);
|
||||
const sensors = telemetryFrame?.sensors;
|
||||
const batteryCharge = sensors?.batteryChargeMah ?? null;
|
||||
const desktopLayout = layoutFormat === 'desktop';
|
||||
// console.log('[BatteryBarDebug]', {
|
||||
// frameSensors: sensors,
|
||||
// batteryCharge,
|
||||
@@ -157,7 +158,7 @@ export default function VideoTile({ sessionInfo, label, forceMute = false, telem
|
||||
controls={false}
|
||||
className="h-full w-full object-contain"
|
||||
/>
|
||||
<HudOverlay frame={telemetryFrame} label={label} status={renderedStatus} />
|
||||
<HudOverlay frame={telemetryFrame} label={label} status={renderedStatus} desktopLayout={desktopLayout}/>
|
||||
<OvercurrentOverlay motors={overcurrentMotors} />
|
||||
<LowBatteryOverlay charge={batteryCharge} config={batteryConfig} />
|
||||
</div>
|
||||
@@ -200,7 +201,7 @@ function BatteryBar({ charge, config }) {
|
||||
);
|
||||
}
|
||||
|
||||
function HudOverlay({ frame, label, status }) {
|
||||
function HudOverlay({ frame, label, status, desktopLayout = true }) {
|
||||
const sensors = frame?.sensors;
|
||||
const bumps = sensors?.bumpsAndWheelDrops || {};
|
||||
const [now, setNow] = useState(() => Date.now());
|
||||
@@ -224,11 +225,11 @@ function HudOverlay({ frame, label, status }) {
|
||||
|
||||
|
||||
{/* bump and wheel drops bar */}
|
||||
<div className="absolute top-0.5 left-1/2 flex -translate-x-1/2 gap-1 bg-black/70 px-0.5 py-0.5 text-[0.6rem] font-medium text-slate-200">
|
||||
<div className={`px-1 py-0.5 ${bumps.bumpLeft ? 'bg-red-600 text-white animate-pulse' : 'text-slate-500'}`}>Left bump</div>
|
||||
<div className={`px-1 py-0.5 ${bumps.wheelDropLeft ? 'bg-red-600 text-white animate-pulse' : 'text-slate-500'}`}>Left wheel drop</div>
|
||||
<div className={`px-1 py-0.5 ${bumps.wheelDropRight ? 'bg-red-600 text-white animate-pulse' : 'text-slate-500'}`}>Right wheel drop</div>
|
||||
<div className={`px-1 py-0.5 ${bumps.bumpRight ? 'bg-red-600 text-white animate-pulse' : 'text-slate-500'}`}>Right bump</div>
|
||||
<div className="absolute top-0.5 left-1/2 flex -translate-x-1/2 gap-1 bg-black/70 text-[0.6rem] font-medium text-slate-200">
|
||||
<div className={`${desktopLayout ? 'px-1 py-0.5':'px-0.5 py-0 text-nowrap'} ${bumps.bumpLeft ? 'bg-red-600 text-white animate-pulse' : 'text-slate-500'}`}>Left bump</div>
|
||||
<div className={`${desktopLayout ? 'px-1 py-0.5':'px-0.5 py-0 text-nowrap'} ${bumps.wheelDropLeft ? 'bg-red-600 text-white animate-pulse' : 'text-slate-500'}`}>Left wheel drop</div>
|
||||
<div className={`${desktopLayout ? 'px-1 py-0.5':'px-0.5 py-0 text-nowrap'} ${bumps.wheelDropRight ? 'bg-red-600 text-white animate-pulse' : 'text-slate-500'}`}>Right wheel drop</div>
|
||||
<div className={`${desktopLayout ? 'px-1 py-0.5':'px-0.5 py-0 text-nowrap'} ${bumps.bumpRight ? 'bg-red-600 text-white animate-pulse' : 'text-slate-500'}`}>Right bump</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user