mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-17 10:00:46 -04:00
new spectator layout
This commit is contained in:
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
@@ -11,8 +11,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" />
|
||||||
<meta name="apple-mobile-web-app-title" content="Multi Roomba Rover" />
|
<meta name="apple-mobile-web-app-title" content="Multi Roomba Rover" />
|
||||||
<title>Multi Roomba Rover</title>
|
<title>Multi Roomba Rover</title>
|
||||||
<script type="module" crossorigin src="/assets/index-DTymo3jY.js"></script>
|
<script type="module" crossorigin src="/assets/index-87I948St.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-D-GAautK.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-DOhplnYF.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { useEffect, useRef, useState } from 'react';
|
|
||||||
import { SettingsProvider } from '../settings/index.js';
|
import { SettingsProvider } from '../settings/index.js';
|
||||||
import { useSession } from '../context/SessionContext.jsx';
|
import { useSession } from '../context/SessionContext.jsx';
|
||||||
import { useSpectatorMode } from '../hooks/useSpectatorMode.js';
|
import { useSpectatorMode } from '../hooks/useSpectatorMode.js';
|
||||||
@@ -21,20 +20,17 @@ function TelemetrySummary({ frame }) {
|
|||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="surface space-y-0.25 text-sm text-slate-200">
|
<div className="surface-muted flex flex-wrap items-center gap-0.5 rounded px-0.5 py-0.25 text-[0.75rem] text-slate-200">
|
||||||
<div className="flex items-center justify-between text-xs text-slate-500">
|
<span className="text-[0.7rem] uppercase tracking-wide text-slate-500">
|
||||||
<span>Telemetry</span>
|
{updated ? `Updated ${updated}` : 'Telemetry'}
|
||||||
<span>{updated ? `Updated ${updated}` : 'Waiting...'}</span>
|
</span>
|
||||||
</div>
|
|
||||||
<div className="grid grid-cols-2 gap-0.25">
|
|
||||||
{entries.map(([label, value]) => (
|
{entries.map(([label, value]) => (
|
||||||
<div key={label} className="surface-muted flex items-center justify-between px-0.5 py-0.25 text-xs">
|
<span key={label} className="flex items-center gap-0.25 rounded bg-slate-900/50 px-0.5 py-0.25">
|
||||||
<span className="text-slate-400">{label}</span>
|
<span className="text-slate-400">{label}</span>
|
||||||
<span className="font-semibold text-white">{value}</span>
|
<span className="font-semibold text-white">{value}</span>
|
||||||
</div>
|
</span>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,17 +51,24 @@ function CurrentDriverBadge({ roverId, session }) {
|
|||||||
|
|
||||||
function RoverSpectatorCard({ rover, frame, videoInfo, session }) {
|
function RoverSpectatorCard({ rover, frame, videoInfo, session }) {
|
||||||
return (
|
return (
|
||||||
<article className="space-y-1 bg-zinc-900 p-0.5">
|
<article className="grid min-h-[16rem] grid-rows-[auto_minmax(0,1fr)_auto] gap-0.5 rounded bg-zinc-900 p-0.5 sm:min-h-[18rem]">
|
||||||
<header className="flex flex-col gap-0.25">
|
<header className="flex items-center justify-between gap-0.5">
|
||||||
<h3 className="text-2xl font-semibold text-white leading-tight">{rover.name}</h3>
|
<div className="flex flex-col leading-tight">
|
||||||
|
<h3 className="text-xl font-semibold text-white">{rover.name}</h3>
|
||||||
<CurrentDriverBadge roverId={rover.id} session={session} />
|
<CurrentDriverBadge roverId={rover.id} session={session} />
|
||||||
|
</div>
|
||||||
|
<span className="rounded bg-slate-800 px-1 text-[0.7rem] text-slate-300">
|
||||||
|
Rover {rover.id}
|
||||||
|
</span>
|
||||||
</header>
|
</header>
|
||||||
|
<div className="min-h-0 overflow-hidden rounded bg-black/20">
|
||||||
<VideoTile
|
<VideoTile
|
||||||
sessionInfo={videoInfo}
|
sessionInfo={videoInfo}
|
||||||
label={rover.name}
|
label={rover.name}
|
||||||
telemetryFrame={frame}
|
telemetryFrame={frame}
|
||||||
batteryConfig={rover.battery}
|
batteryConfig={rover.battery}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
<TelemetrySummary frame={frame} />
|
<TelemetrySummary frame={frame} />
|
||||||
</article>
|
</article>
|
||||||
);
|
);
|
||||||
@@ -76,7 +79,7 @@ function RoverRow({ roster, frames, videoSources, session }) {
|
|||||||
return <p className="col-span-full text-slate-400">No rovers registered.</p>;
|
return <p className="col-span-full text-slate-400">No rovers registered.</p>;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<section className="grid grid-cols-1 gap-0.5 sm:grid-cols-2 lg:grid-cols-3">
|
<section className="grid grid-cols-1 gap-0.5 md:grid-cols-2 xl:grid-cols-3">
|
||||||
{roster.map((rover) => (
|
{roster.map((rover) => (
|
||||||
<RoverSpectatorCard
|
<RoverSpectatorCard
|
||||||
key={rover.id}
|
key={rover.id}
|
||||||
@@ -91,39 +94,11 @@ function RoverRow({ roster, frames, videoSources, session }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function SecondaryRow() {
|
function SecondaryRow() {
|
||||||
const roomRef = useRef(null);
|
|
||||||
const [roomHeight, setRoomHeight] = useState(0);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const target = roomRef.current;
|
|
||||||
if (!target || typeof ResizeObserver === 'undefined') return undefined;
|
|
||||||
const observer = new ResizeObserver((entries) => {
|
|
||||||
const entry = entries[0];
|
|
||||||
if (!entry) return;
|
|
||||||
const nextHeight = entry.contentRect?.height || 0;
|
|
||||||
setRoomHeight(nextHeight);
|
|
||||||
});
|
|
||||||
observer.observe(target);
|
|
||||||
return () => observer.disconnect();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="grid grid-cols-1 items-stretch gap-0.5 lg:grid-cols-[2fr_1fr_1fr]">
|
<section className="min-h-0">
|
||||||
<div ref={roomRef} className="flex h-full min-h-0 flex-col">
|
<div className="surface min-h-[14rem] overflow-hidden">
|
||||||
<RoomCameraPanel defaultOrientation="horizontal" hideLayoutToggle hideHeader />
|
<RoomCameraPanel defaultOrientation="horizontal" hideLayoutToggle hideHeader />
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
className="flex min-h-0 flex-col"
|
|
||||||
style={roomHeight ? { height: roomHeight } : undefined}
|
|
||||||
>
|
|
||||||
<UserListPanel hideNicknameForm hideHeader fillHeight />
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="flex min-h-0 flex-col"
|
|
||||||
style={roomHeight ? { height: roomHeight } : undefined}
|
|
||||||
>
|
|
||||||
<ChatPanel hideInput hideSpectatorNotice fillHeight />
|
|
||||||
</div>
|
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -146,10 +121,22 @@ export default function SpectatorApp() {
|
|||||||
return (
|
return (
|
||||||
<SettingsProvider>
|
<SettingsProvider>
|
||||||
<div className="min-h-screen bg-black text-slate-100">
|
<div className="min-h-screen bg-black text-slate-100">
|
||||||
<main className="flex flex-col gap-0.5 p-0.5">
|
<main className="grid min-h-screen grid-cols-1 gap-0.5 p-0.5 md:grid-cols-[3fr_1.15fr] lg:grid-cols-[5fr_2fr]">
|
||||||
|
<section className="flex min-h-0 flex-col gap-0.5">
|
||||||
<RoverRow roster={roster} frames={frames} videoSources={videoSources} session={session} />
|
<RoverRow roster={roster} frames={frames} videoSources={videoSources} session={session} />
|
||||||
<SecondaryRow />
|
<SecondaryRow />
|
||||||
|
</section>
|
||||||
|
<section className="grid min-h-0 grid-rows-[1fr_1.2fr_auto] gap-0.5">
|
||||||
|
<div className="min-h-0">
|
||||||
|
<UserListPanel hideNicknameForm hideHeader fillHeight />
|
||||||
|
</div>
|
||||||
|
<div className="min-h-0">
|
||||||
|
<ChatPanel hideInput hideSpectatorNotice fillHeight />
|
||||||
|
</div>
|
||||||
|
<div className="min-h-0">
|
||||||
<LogsRow />
|
<LogsRow />
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
</SettingsProvider>
|
</SettingsProvider>
|
||||||
|
|||||||
Reference in New Issue
Block a user