diff --git a/services/web-ui/public/screens-ingest.jsx b/services/web-ui/public/screens-ingest.jsx index 0ca3054..b43039e 100644 --- a/services/web-ui/public/screens-ingest.jsx +++ b/services/web-ui/public/screens-ingest.jsx @@ -219,6 +219,7 @@ function Recorders({ navigate, onNew }) { }, []); React.useEffect(() => { + refresh(); const id = setInterval(refresh, 10000); return () => clearInterval(id); }, []); @@ -261,10 +262,42 @@ function RecorderRow({ recorder: initialRecorder, onRefresh }) { const [recorder, setRecorder] = React.useState(initialRecorder); const [pending, setPending] = React.useState(false); const [err, setErr] = React.useState(null); + const [liveStatus, setLiveStatus] = React.useState(null); const isRec = recorder.status === 'recording'; React.useEffect(() => { setRecorder(initialRecorder); }, [initialRecorder.id, initialRecorder.status]); + // Poll the status endpoint every 3s while recording for live feedback. + React.useEffect(() => { + if (!isRec) { setLiveStatus(null); return; } + const poll = () => { + window.ZAMPP_API.fetch('/recorders/' + recorder.id + '/status') + .then(s => setLiveStatus(s)) + .catch(() => {}); + }; + poll(); + const id = setInterval(poll, 3000); + return () => clearInterval(id); + }, [isRec, recorder.id]); + + const displayElapsed = React.useMemo(() => { + if (liveStatus && liveStatus.duration != null) { + const d = Math.max(0, liveStatus.duration); + return String(Math.floor(d / 3600)).padStart(2, '0') + ':' + + String(Math.floor((d % 3600) / 60)).padStart(2, '0') + ':' + + String(d % 60).padStart(2, '0'); + } + return recorder.elapsed; + }, [liveStatus, recorder.elapsed]); + + const displaySignal = liveStatus + ? (liveStatus.signal || '—') + : (isRec ? 'connecting…' : '—'); + + const signalColor = displaySignal === 'receiving' ? 'var(--success)' + : displaySignal === 'stopped' ? 'var(--danger)' + : 'var(--text-3)'; + const toggle = () => { if (pending) return; const action = isRec ? 'stop' : 'start'; @@ -297,16 +330,25 @@ function RecorderRow({ recorder: initialRecorder, onRefresh }) { {recorder.res} {err &&