fix(rec): a fresh take starts its clock at zero, not at the last take's total

Two effects, wrong order: the ticking effect ran before the reset effect on a
new take, so its closure captured the PREVIOUS take's elapsed as its starting
point — the counter showed 0 for one second and then jumped back to thirty
minutes. Effects run in declaration order; the reset now comes first.
This commit is contained in:
2026-08-29 16:31:38 +02:00
parent 7f328d4eb5
commit 582fa561b2
2 changed files with 11 additions and 5 deletions
+7 -3
View File
@@ -1051,6 +1051,13 @@ export default function App() {
if (!active) setError(t('rec.manualFailed'));
}).catch((e: any) => setError(String(e?.message ?? e)));
};
// recTick means "a fresh take" — that is the only case where the clock returns
// to zero, as opposed to resuming after a stop. Declared BEFORE the ticking
// effect below and deliberately so: effects run in declaration order, and the
// other way round the ticker captured the PREVIOUS take's elapsed as its
// starting point — the counter showed 0 for one second, then jumped straight
// back to the old thirty minutes.
useEffect(() => { setRecSeconds(0); recSecondsRef.current = 0; setRecStopped(false); }, [recTick]);
useEffect(() => {
if (!recording) { setRecSeconds(0); return; }
// A stopped take freezes the clock where it is: it must show the length of
@@ -1061,9 +1068,6 @@ export default function App() {
const id = window.setInterval(() => setRecSeconds(from + Math.floor((Date.now() - start) / 1000)), 1000);
return () => window.clearInterval(id);
}, [recording, recTick, recStopped]);
// recTick means "a fresh take" — that is the only case where the clock returns
// to zero, as opposed to resuming after a stop.
useEffect(() => { setRecSeconds(0); recSecondsRef.current = 0; setRecStopped(false); }, [recTick]);
// The callsign the in-progress recording belongs to (uppercased; '' = none).
// Lets us restart from zero when the operator edits the call to a different
// station mid-recording, instead of continuing the old take.