mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 09:31:20 -04:00
spectator tweakings
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { SettingsProvider } from '../settings/index.js';
|
||||
import { useSession } from '../context/SessionContext.jsx';
|
||||
import { useSpectatorMode } from '../hooks/useSpectatorMode.js';
|
||||
@@ -14,6 +15,33 @@ import CommunityGoalBanner from '../components/CommunityGoalBanner.jsx';
|
||||
import RoverQueuesPanel from '../components/RoverQueuesPanel.jsx';
|
||||
import RawUserPilePanel from '../components/RawUserPilePanel.jsx';
|
||||
|
||||
function usePortraitLayout() {
|
||||
const [isPortrait, setIsPortrait] = useState(() => {
|
||||
if (typeof window === 'undefined') return false;
|
||||
return window.matchMedia('(max-aspect-ratio: 4/3)').matches;
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window === 'undefined') return undefined;
|
||||
const media = window.matchMedia('(max-aspect-ratio: 4/3)');
|
||||
const handleChange = (event) => setIsPortrait(event.matches);
|
||||
if (media.addEventListener) {
|
||||
media.addEventListener('change', handleChange);
|
||||
} else {
|
||||
media.addListener(handleChange);
|
||||
}
|
||||
return () => {
|
||||
if (media.removeEventListener) {
|
||||
media.removeEventListener('change', handleChange);
|
||||
} else {
|
||||
media.removeListener(handleChange);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
return isPortrait;
|
||||
}
|
||||
|
||||
function formatDriverLabel({ roverId, session }) {
|
||||
const activeDriverId = session?.activeDrivers?.[roverId] || null;
|
||||
const user = (session?.users || []).find((entry) => entry.socketId === activeDriverId);
|
||||
@@ -98,6 +126,7 @@ function SpectatorContent() {
|
||||
const inLockdown = session?.mode === 'lockdown';
|
||||
useDefaultNickname();
|
||||
useSpectatorMode();
|
||||
const isPortraitLayout = usePortraitLayout();
|
||||
const frames = useTelemetryFrames();
|
||||
const roster = session?.roster ?? [];
|
||||
const snapshotFeeds = useRoverSnapshots(
|
||||
@@ -122,10 +151,46 @@ function SpectatorContent() {
|
||||
);
|
||||
}
|
||||
|
||||
const mainClass = isPortraitLayout
|
||||
? 'flex min-h-screen flex-col bg-black text-slate-100 md:h-screen md:overflow-hidden'
|
||||
: 'grid min-h-screen grid-cols-1 gap-0.5 bg-black text-slate-100 md:h-full md:min-h-0 md:grid-cols-[minmax(0,1fr)_18rem] lg:grid-cols-[minmax(0,1fr)_20rem]';
|
||||
const contentClass = isPortraitLayout
|
||||
? 'order-2 flex min-h-0 min-w-0 flex-1 flex-col gap-0.5 overflow-y-auto'
|
||||
: 'order-1 flex min-h-0 min-w-0 flex-col gap-0.5 md:overflow-y-auto';
|
||||
const sidebarClass = isPortraitLayout
|
||||
? 'order-1 flex min-h-0 w-full items-stretch gap-0.5 overflow-x-auto border-b border-slate-800/60 bg-slate-950/90 p-0.5'
|
||||
: 'order-2 flex min-h-0 min-w-0 flex-col gap-0.5 border-l border-slate-800/60 bg-slate-950/90 md:h-full md:overflow-y-auto';
|
||||
const topBarItemClass = isPortraitLayout ? 'min-w-[16rem] max-w-[22rem] flex-1' : '';
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-black text-slate-100 md:h-screen md:overflow-hidden">
|
||||
<main className="grid min-h-screen grid-cols-1 gap-0.5 p-0 md:h-full md:min-h-0 md:grid-cols-[minmax(0,1fr)_18rem] lg:grid-cols-[minmax(0,1fr)_20rem]">
|
||||
<section className="flex min-h-0 min-w-0 flex-col gap-0.5 md:overflow-y-auto">
|
||||
<main className={mainClass}>
|
||||
<section className={sidebarClass}>
|
||||
<div className={topBarItemClass}>
|
||||
<CommunityGoalBanner layout="desktop" dismissable={false} className="text-sm" />
|
||||
</div>
|
||||
<div className={`${topBarItemClass} ${isPortraitLayout ? 'h-32 overflow-y-auto' : ''}`}>
|
||||
<div className="panel h-full">
|
||||
<RoverQueuesPanel title="Rovers" />
|
||||
</div>
|
||||
</div>
|
||||
<div className={`${topBarItemClass} ${isPortraitLayout ? 'h-32' : 'flex-1 min-h-0'}`}>
|
||||
<RawUserPilePanel
|
||||
hideNicknameForm
|
||||
hideHeader
|
||||
compact
|
||||
fillHeight
|
||||
className="h-full"
|
||||
/>
|
||||
</div>
|
||||
<div className={`${topBarItemClass} ${isPortraitLayout ? 'h-32' : 'flex-[1.1] min-h-0'}`}>
|
||||
<ChatPanel hideInput hideSpectatorNotice fillHeight />
|
||||
</div>
|
||||
<div className={`${topBarItemClass} ${isPortraitLayout ? 'h-32' : ''}`}>
|
||||
<LogsRow className={`${isPortraitLayout ? 'h-full' : 'h-40'} overflow-hidden`} />
|
||||
</div>
|
||||
</section>
|
||||
<section className={contentClass}>
|
||||
<RoverRow
|
||||
roster={roster}
|
||||
frames={frames}
|
||||
@@ -135,21 +200,6 @@ function SpectatorContent() {
|
||||
/>
|
||||
<SecondaryRow />
|
||||
</section>
|
||||
<section className="flex min-h-0 min-w-0 flex-col gap-0.5 md:h-full">
|
||||
<CommunityGoalBanner layout="desktop" />
|
||||
<div className="panel">
|
||||
<RoverQueuesPanel title="Rovers" />
|
||||
</div>
|
||||
<div className="min-h-0 min-w-0 flex-1 overflow-hidden">
|
||||
<RawUserPilePanel hideNicknameForm hideHeader fillHeight className="h-full" />
|
||||
</div>
|
||||
<div className="min-h-0 min-w-0 flex-[1.1] overflow-hidden">
|
||||
<ChatPanel hideInput hideSpectatorNotice fillHeight />
|
||||
</div>
|
||||
<div className="min-h-0 min-w-0">
|
||||
<LogsRow className="h-40 overflow-hidden" />
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<AlertFeed />
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user