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:
+4
-4
@@ -14,14 +14,14 @@
|
||||
<!-- 2. pi-side sensor throttle (1/5th) -->
|
||||
<!-- 3. convert rover roster to a reusable component, unbake it from telemetry and admin panels -->
|
||||
<!-- 4. room cameras -->
|
||||
4. fix gamepad input - add manual inversions?
|
||||
4. fix gamepad input - more complex axis assignment? division, combined axes?
|
||||
<!-- 5. home assistant controls -->
|
||||
<!-- 6. nicknames -->
|
||||
<!-- 7. discord bot -->
|
||||
8. turns mode display
|
||||
<!-- 8. turns mode display -->
|
||||
<!-- 9. online user list -->
|
||||
<!-- 10. chat -->
|
||||
9. discord invite button
|
||||
<!-- 9. discord invite button -->
|
||||
10. redo both mobile layouts
|
||||
11. redo spectator view (last)
|
||||
21. finally.. set the favicon
|
||||
21. finally.. set the favicon and title
|
||||
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
@@ -5,8 +5,8 @@
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>webui</title>
|
||||
<script type="module" crossorigin src="/assets/index-D4k56rvM.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-DUduiIaK.css">
|
||||
<script type="module" crossorigin src="/assets/index-CoT66lYm.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-DQGzoV_h.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
+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