mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 09:31:20 -04:00
better /display ptz operator popup
This commit is contained in:
File diff suppressed because one or more lines are too long
+1
-1
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
@@ -78,8 +78,8 @@
|
|||||||
<script defer src="https://analytics.otter.land/script.js" data-website-id="82dd56a5-db44-4279-bd1e-a4d9fee39af7" data-domains="rover.otter.land"></script>
|
<script defer src="https://analytics.otter.land/script.js" data-website-id="82dd56a5-db44-4279-bd1e-a4d9fee39af7" data-domains="rover.otter.land"></script>
|
||||||
<script defer src="https://analytics.otter.land/recorder.js" data-website-id="82dd56a5-db44-4279-bd1e-a4d9fee39af7" data-domains="rover.otter.land" data-sample-rate="0.15" data-mask-level="moderate" data-max-duration="300000"></script>
|
<script defer src="https://analytics.otter.land/recorder.js" data-website-id="82dd56a5-db44-4279-bd1e-a4d9fee39af7" data-domains="rover.otter.land" data-sample-rate="0.15" data-mask-level="moderate" data-max-duration="300000"></script>
|
||||||
<title>Roomba Rover</title>
|
<title>Roomba Rover</title>
|
||||||
<script type="module" crossorigin src="/assets/index-Dqo9kxw3.js"></script>
|
<script type="module" crossorigin src="/assets/index-C8ryXPtn.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-ZpgWUPKf.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-PKUQHBrm.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
@@ -36,8 +36,14 @@ export default function ServerDisplayContent() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="display-page flex h-screen w-screen flex-col overflow-hidden bg-black text-slate-100">
|
<div className="display-page flex h-screen w-screen flex-col overflow-hidden bg-black text-slate-100">
|
||||||
<div className="h-[8vh] min-h-[4rem] shrink-0">
|
<div className="flex h-[8vh] min-h-[4rem] shrink-0 overflow-hidden">
|
||||||
<OnlinePeopleStrip users={session?.users || []} />
|
<OnlinePeopleStrip users={session?.users || []} />
|
||||||
|
{/* The PTZ operator belongs in the same information band as the people
|
||||||
|
strip because it is another "who is active right now" signal. Making
|
||||||
|
it a flex sibling lets the badge reserve real layout space when it
|
||||||
|
appears, which pushes the scrolling strip left instead of covering
|
||||||
|
the rover or chat areas. */}
|
||||||
|
<DisplayPtzOperatorBadge />
|
||||||
</div>
|
</div>
|
||||||
<div className="min-h-0 flex-[0.72]">
|
<div className="min-h-0 flex-[0.72]">
|
||||||
<DisplayRoverGrid roster={session?.roster || []} session={session} />
|
<DisplayRoverGrid roster={session?.roster || []} session={session} />
|
||||||
@@ -45,11 +51,6 @@ export default function ServerDisplayContent() {
|
|||||||
<div className="min-h-0 flex-[1.28]">
|
<div className="min-h-0 flex-[1.28]">
|
||||||
<DisplayChatFeed />
|
<DisplayChatFeed />
|
||||||
</div>
|
</div>
|
||||||
{/* Keep the PTZ operator visible on the room board without changing the
|
|
||||||
existing rover/chat layout. The badge is self-hiding when nobody owns
|
|
||||||
the camera, so the display remains exactly as sparse as before between
|
|
||||||
PTZ turns. */}
|
|
||||||
<DisplayPtzOperatorBadge />
|
|
||||||
<DisplayNoticeOverlay />
|
<DisplayNoticeOverlay />
|
||||||
<RewardRunOverlay />
|
<RewardRunOverlay />
|
||||||
{/* Display is spectator-like: every Discord-hosted replay should take over
|
{/* Display is spectator-like: every Discord-hosted replay should take over
|
||||||
|
|||||||
@@ -8,32 +8,31 @@ import { useSessionSelector } from '../../../context/SessionContext.jsx';
|
|||||||
export default function DisplayPtzOperatorBadge() {
|
export default function DisplayPtzOperatorBadge() {
|
||||||
const ptz = useSessionSelector((state) => state.session?.ptzCamera || null);
|
const ptz = useSessionSelector((state) => state.session?.ptzCamera || null);
|
||||||
const operatorLabel = String(ptz?.operatorLabel || '').trim();
|
const operatorLabel = String(ptz?.operatorLabel || '').trim();
|
||||||
|
const visible = Boolean(ptz?.enabled && operatorLabel);
|
||||||
if (!ptz?.enabled || !operatorLabel) {
|
|
||||||
/*
|
|
||||||
The display should stay clean when nobody has the camera. Returning null
|
|
||||||
instead of showing "none" makes the badge behave like a popup: it appears
|
|
||||||
only for an active PTZ operator and disappears as soon as the turn ends.
|
|
||||||
*/
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<aside
|
<aside
|
||||||
className="pointer-events-none fixed bottom-[2vh] right-[2vw] z-[90] max-w-[42vw] border-4 border-sky-200 bg-sky-700 px-[1.4vw] py-[1vh] text-center"
|
className={`pointer-events-none h-full shrink-0 overflow-hidden border-b border-l border-sky-200 bg-sky-700 transition-[width,opacity] duration-300 ease-out ${
|
||||||
aria-label={`PTZ operator ${operatorLabel}`}
|
visible ? 'w-[min(34vw,34rem)] opacity-100' : 'w-0 opacity-0'
|
||||||
|
}`}
|
||||||
|
aria-hidden={!visible}
|
||||||
|
aria-label={visible ? `PTZ operator ${operatorLabel}` : undefined}
|
||||||
>
|
>
|
||||||
{/*
|
{/*
|
||||||
The label is deliberately short because /display is a room board, not a
|
This is a flex-row segment instead of a fixed overlay so the online
|
||||||
control panel. The large name is the useful information from across the
|
people marquee loses width when PTZ is active. That makes the badge feel
|
||||||
room, while the smaller prefix prevents the blue box from being mistaken
|
like it enters from the right edge of the top bar while avoiding the
|
||||||
for a rover driver or chat message.
|
previous problem where it covered content in the bottom-right corner.
|
||||||
*/}
|
*/}
|
||||||
<div className="text-7xl font-black tracking-normal text-sky-100">
|
<div className="flex h-full min-w-0 items-center justify-center gap-[1vw] px-[1.2vw] text-[clamp(2.1rem,5.1vh,5.6rem)] font-black leading-none tracking-normal text-white">
|
||||||
PTZ camera
|
{/*
|
||||||
</div>
|
The user explicitly requested uppercase "PTZ" here because the room
|
||||||
<div className="truncate text-9xl font-black leading-none text-white">
|
display needs a terse, instantly recognizable camera marker. The name
|
||||||
{operatorLabel}
|
remains the larger variable part, and truncation prevents a long
|
||||||
|
nickname from resizing the bar or overlapping the scrolling strip.
|
||||||
|
*/}
|
||||||
|
<span className="shrink-0 text-sky-100">PTZ</span>
|
||||||
|
<span className="min-w-0 truncate">{operatorLabel}</span>
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -68,7 +68,10 @@ export default function OnlinePeopleStrip({ users = [] }) {
|
|||||||
));
|
));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={viewportRef} className="relative h-full min-w-0 overflow-hidden border-b border-slate-800/80 bg-black">
|
<div
|
||||||
|
ref={viewportRef}
|
||||||
|
className="relative h-full min-w-0 flex-1 overflow-hidden border-b border-slate-800/80 bg-black"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
ref={trackRef}
|
ref={trackRef}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
|
|||||||
Reference in New Issue
Block a user