mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-15 17:12:59 -04:00
spectator updates
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-title" content="Multi Roomba Rover" />
|
||||
<title>Multi Roomba Rover</title>
|
||||
<script type="module" crossorigin src="/assets/index-Cx2yYVpk.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-sMfSpjY4.css">
|
||||
<script type="module" crossorigin src="/assets/index-Bu0ya-aM.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-B8zLJlAS.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
@@ -39,11 +39,12 @@ function buildWhepUrlForSource(source) {
|
||||
|
||||
function passesMode(socket) {
|
||||
const mode = getMode();
|
||||
if (mode === MODES.LOCKDOWN && !isLockdownAdmin(socket)) {
|
||||
return false;
|
||||
if (mode === MODES.LOCKDOWN) {
|
||||
return isLockdownAdmin(socket);
|
||||
}
|
||||
if (mode === MODES.ADMIN && !isAdmin(socket)) {
|
||||
return false;
|
||||
if (mode === MODES.ADMIN) {
|
||||
const role = getRole(socket);
|
||||
return role === 'spectator' || isAdmin(socket);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { useMemo } from 'react';
|
||||
import { SettingsProvider } from '../settings/index.js';
|
||||
import { useSession } from '../context/SessionContext.jsx';
|
||||
import { useSpectatorMode } from '../hooks/useSpectatorMode.js';
|
||||
@@ -10,22 +9,6 @@ import UserListPanel from '../components/UserListPanel.jsx';
|
||||
import ChatPanel from '../components/ChatPanel.jsx';
|
||||
import LogPanel from '../components/LogPanel.jsx';
|
||||
|
||||
function SpectatorStatus({ connected, ready, rosterCount, mode, blocked }) {
|
||||
return (
|
||||
<div className="flex flex-wrap items-center gap-0.5 text-sm">
|
||||
<span className={`px-0.5 py-0.5 font-semibold ${connected ? 'bg-emerald-500/20 text-emerald-200' : 'bg-red-500/20 text-red-200'}`}>
|
||||
{connected ? 'Connected' : 'Disconnected'}
|
||||
</span>
|
||||
<span className={`px-0.5 py-0.5 ${ready ? 'bg-blue-600/40 text-blue-100' : 'bg-slate-700 text-slate-200'}`}>
|
||||
Spectator mode {ready ? 'active' : 'pending…'}
|
||||
</span>
|
||||
<span className="bg-slate-800 px-0.5 py-0.5 text-slate-200">Rovers: {rosterCount}</span>
|
||||
<span className="bg-slate-800 px-0.5 py-0.5 text-slate-200">Mode: {mode || 'unknown'}</span>
|
||||
{blocked && <span className="bg-red-700/60 px-0.5 py-0.5 text-red-100">Spectate blocked</span>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function TelemetrySummary({ frame }) {
|
||||
const sensors = frame?.sensors || {};
|
||||
const updated = frame?.receivedAt ? new Date(frame.receivedAt).toLocaleTimeString() : null;
|
||||
@@ -87,7 +70,7 @@ function RoverRow({ roster, frames, videoSources, session }) {
|
||||
return <p className="col-span-full text-slate-400">No rovers registered.</p>;
|
||||
}
|
||||
return (
|
||||
<section className="grid grid-cols-1 gap-0.5 md:grid-cols-2 xl:grid-cols-3">
|
||||
<section className="grid grid-cols-1 gap-0.5 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
|
||||
{roster.map((rover) => (
|
||||
<RoverSpectatorCard
|
||||
key={rover.id}
|
||||
@@ -120,30 +103,16 @@ function LogsRow() {
|
||||
}
|
||||
|
||||
export default function SpectatorApp() {
|
||||
const { connected, session } = useSession();
|
||||
const spectatorReady = useSpectatorMode();
|
||||
const { session } = useSession();
|
||||
useSpectatorMode();
|
||||
const frames = useTelemetryFrames();
|
||||
const roster = session?.roster ?? [];
|
||||
const videoSources = useVideoRequests(roster.map((rover) => rover.id));
|
||||
const blocked = session?.mode === 'lockdown';
|
||||
|
||||
const status = useMemo(
|
||||
() => ({ connected, ready: spectatorReady, rosterCount: roster.length, mode: session?.mode, blocked }),
|
||||
[blocked, connected, roster.length, session?.mode, spectatorReady],
|
||||
);
|
||||
|
||||
return (
|
||||
<SettingsProvider>
|
||||
<div className="min-h-screen bg-black text-slate-100">
|
||||
<main className="mx-auto flex max-w-7xl flex-col gap-0.5 px-0.5 py-0.5">
|
||||
<header className="space-y-0.5">
|
||||
<h1 className="text-4xl font-semibold text-white">Spectator Console</h1>
|
||||
<p className="text-slate-400">Live rover telemetry & logs. This view is read-only.</p>
|
||||
<SpectatorStatus {...status} />
|
||||
{blocked && (
|
||||
<p className="text-sm text-amber-300">Lockdown active. Spectator view will resume automatically when access returns.</p>
|
||||
)}
|
||||
</header>
|
||||
<main className="flex flex-col gap-0.5 p-0.5">
|
||||
<RoverRow roster={roster} frames={frames} videoSources={videoSources} session={session} />
|
||||
<SecondaryRow />
|
||||
<LogsRow />
|
||||
|
||||
Reference in New Issue
Block a user