better popuping vs not

This commit is contained in:
legop3
2026-06-07 17:02:54 -04:00
parent 3cff250ba0
commit b2bd3a5e41
12 changed files with 217 additions and 155 deletions
@@ -15,10 +15,11 @@ function formatBytes(value) {
return `${(size / 1024 / 1024).toFixed(1)} MB`;
}
export default function ReplayReadyPopup({ replay, onClose }) {
export default function ReplayReadyPopup({ replay, onClose, variant = 'modal' }) {
const videoUrl = normalizeUrl(replay?.url);
if (!videoUrl) return null;
const isPanel = variant === 'panel';
const title = String(replay?.title || 'Replay').trim() || 'Replay';
const messageUrl = normalizeUrl(replay?.messageUrl);
const meta = formatBytes(replay?.size) || null;
@@ -38,12 +39,35 @@ export default function ReplayReadyPopup({ replay, onClose }) {
</div>
);
return (
<div
className="fixed inset-0 z-[110] flex items-center justify-center bg-black/80 p-1"
onClick={onClose}
role="presentation"
const card = (
<CardFrame
title={title}
meta={meta}
actions={actions}
fillHeight={isPanel}
clipOverflow={false}
bodyClassName={`${isPanel ? 'flex min-h-0 flex-1 flex-col' : ''} space-y-0.5 p-0.5 text-sm text-slate-200`}
>
<div className={`${isPanel ? 'min-h-0 flex-1' : ''} overflow-hidden rounded bg-black`}>
<video
key={videoUrl}
src={videoUrl}
controls
autoPlay
preload="auto"
playsInline
className={`${isPanel ? 'h-full min-h-[10rem]' : 'aspect-video max-h-[72vh]'} w-full bg-black`}
/>
</div>
</CardFrame>
);
if (isPanel) {
return <div className="flex h-full min-h-[14rem] flex-col">{card}</div>;
}
return (
<div className="fixed inset-0 z-[110] flex items-center justify-center bg-black/80 p-1" onClick={onClose} role="presentation">
<div
className="pointer-events-auto w-full max-w-4xl"
onClick={(event) => {
@@ -52,19 +76,7 @@ export default function ReplayReadyPopup({ replay, onClose }) {
}}
role="presentation"
>
<CardFrame title={title} meta={meta} actions={actions} clipOverflow={false} bodyClassName="space-y-0.5 p-0.5 text-sm text-slate-200">
<div className="overflow-hidden rounded bg-black">
<video
key={videoUrl}
src={videoUrl}
controls
autoPlay
preload="auto"
playsInline
className="aspect-video max-h-[72vh] w-full bg-black"
/>
</div>
</CardFrame>
{card}
</div>
</div>
);
@@ -6,6 +6,7 @@ import { useSessionActions, useSessionSelector } from '../../context/SessionCont
import { useSettingsNamespace } from '../../settings/index.js';
import CardFrame from '../CardFrame/index.jsx';
import RoverLabel from '../RoverLabel/index.jsx';
import ReplayReadyPopup from './ReplayReadyPopup.jsx';
function normalizeSources(list = []) {
return list
@@ -26,8 +27,10 @@ export default function ReplaySourcesPanel({ panelId = 'replay-sources', fillHei
const replaySources = useSessionSelector((state) => state.session?.replaySources ?? []);
const mode = useSessionSelector((state) => state.session?.mode || null);
const assignmentRoverId = useSessionSelector((state) => state.session?.assignment?.roverId ?? null);
const selfSocketId = useSessionSelector((state) => state.session?.socketId || null);
const roster = useSessionSelector((state) => state.session?.roster ?? []);
const replayState = useSessionSelector((state) => state.session?.replay || null);
const latestReplay = useSessionSelector((state) => state.latestReplay);
const { triggerReplay } = useSessionActions();
const sources = normalizeSources(replaySources || []);
const { value: settings, save: saveSettings } = useSettingsNamespace('replaySources', {});
@@ -40,9 +43,24 @@ export default function ReplaySourcesPanel({ panelId = 'replay-sources', fillHei
const [includeSidebar, setIncludeSidebar] = useState(true);
const [remainingMs, setRemainingMs] = useState(0);
const [activeJobId, setActiveJobId] = useState(null);
const [dismissedPanelReplayId, setDismissedPanelReplayId] = useState(null);
const activeReplayJob = useSessionSelector((state) => (
activeJobId ? state.replayJobs?.[activeJobId] || null : null
));
const latestReplayJobId = latestReplay?.jobId || null;
const latestReplayRequesterSocketId = latestReplay?.requestedBy?.socketId || null;
const latestReplayRequestedBySelf = Boolean(
latestReplayJobId &&
selfSocketId &&
latestReplayRequesterSocketId &&
String(latestReplayRequesterSocketId) === String(selfSocketId),
);
const showPanelReplay = Boolean(
latestReplay?.url &&
latestReplayJobId &&
!latestReplayRequestedBySelf &&
dismissedPanelReplayId !== latestReplayJobId,
);
const defaults = useMemo(() => {
const roverId = assignmentRoverId;
@@ -173,6 +191,16 @@ export default function ReplaySourcesPanel({ panelId = 'replay-sources', fillHei
const listWrapClass = fillHeight ? 'flex-1 min-h-0 overflow-y-auto' : '';
if (showPanelReplay) {
return (
<ReplayReadyPopup
replay={latestReplay}
variant="panel"
onClose={() => setDismissedPanelReplayId(latestReplayJobId)}
/>
);
}
return (
<CardFrame title="Replay Sources" fillHeight={fillHeight} bodyClassName="space-y-0.5 text-sm">
<div className={`grid gap-0.5 md:grid-cols-2 ${listWrapClass}`}>