fix:prevent stale countdown IPC updates from repainting overlay
This commit is contained in:
Vendored
+3
-3
@@ -135,9 +135,9 @@ interface Window {
|
||||
saveShortcuts: (shortcuts: unknown) => Promise<{ success: boolean; error?: string }>;
|
||||
hudOverlayHide: () => void;
|
||||
hudOverlayClose: () => void;
|
||||
showCountdownOverlay: (value: number) => Promise<void>;
|
||||
setCountdownOverlayValue: (value: number) => Promise<void>;
|
||||
hideCountdownOverlay: () => Promise<void>;
|
||||
showCountdownOverlay: (value: number, runId: number) => Promise<void>;
|
||||
setCountdownOverlayValue: (value: number, runId: number) => Promise<void>;
|
||||
hideCountdownOverlay: (runId: number) => Promise<void>;
|
||||
onCountdownOverlayValue: (callback: (value: number | null) => void) => () => void;
|
||||
setMicrophoneExpanded: (expanded: boolean) => void;
|
||||
setHasUnsavedChanges: (hasChanges: boolean) => void;
|
||||
|
||||
@@ -362,6 +362,7 @@ export function registerIpcHandlers(
|
||||
const countdownOverlayState = {
|
||||
visible: false,
|
||||
value: null as number | null,
|
||||
activeRunId: null as number | null,
|
||||
};
|
||||
|
||||
const flushCountdownOverlayState = (win: BrowserWindow) => {
|
||||
@@ -379,7 +380,8 @@ export function registerIpcHandlers(
|
||||
}
|
||||
};
|
||||
|
||||
ipcMain.handle("countdown-overlay-show", (_, value: number) => {
|
||||
ipcMain.handle("countdown-overlay-show", (_, value: number, runId: number) => {
|
||||
countdownOverlayState.activeRunId = runId;
|
||||
countdownOverlayState.visible = true;
|
||||
countdownOverlayState.value = value;
|
||||
|
||||
@@ -399,7 +401,11 @@ export function registerIpcHandlers(
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("countdown-overlay-set-value", (_, value: number) => {
|
||||
ipcMain.handle("countdown-overlay-set-value", (_, value: number, runId: number) => {
|
||||
if (countdownOverlayState.activeRunId !== runId || !countdownOverlayState.visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
countdownOverlayState.value = value;
|
||||
|
||||
const win = getCountdownOverlayWindow();
|
||||
@@ -414,7 +420,11 @@ export function registerIpcHandlers(
|
||||
win.webContents.send("countdown-overlay-value", value);
|
||||
});
|
||||
|
||||
ipcMain.handle("countdown-overlay-hide", () => {
|
||||
ipcMain.handle("countdown-overlay-hide", (_, runId: number) => {
|
||||
if (countdownOverlayState.activeRunId !== runId) {
|
||||
return;
|
||||
}
|
||||
|
||||
countdownOverlayState.visible = false;
|
||||
countdownOverlayState.value = null;
|
||||
|
||||
|
||||
+6
-6
@@ -130,14 +130,14 @@ contextBridge.exposeInMainWorld("electronAPI", {
|
||||
setHasUnsavedChanges: (hasChanges: boolean) => {
|
||||
ipcRenderer.send("set-has-unsaved-changes", hasChanges);
|
||||
},
|
||||
showCountdownOverlay: (value: number) => {
|
||||
return ipcRenderer.invoke("countdown-overlay-show", value);
|
||||
showCountdownOverlay: (value: number, runId: number) => {
|
||||
return ipcRenderer.invoke("countdown-overlay-show", value, runId);
|
||||
},
|
||||
setCountdownOverlayValue: (value: number) => {
|
||||
return ipcRenderer.invoke("countdown-overlay-set-value", value);
|
||||
setCountdownOverlayValue: (value: number, runId: number) => {
|
||||
return ipcRenderer.invoke("countdown-overlay-set-value", value, runId);
|
||||
},
|
||||
hideCountdownOverlay: () => {
|
||||
return ipcRenderer.invoke("countdown-overlay-hide");
|
||||
hideCountdownOverlay: (runId: number) => {
|
||||
return ipcRenderer.invoke("countdown-overlay-hide", runId);
|
||||
},
|
||||
onCountdownOverlayValue: (callback: (value: number | null) => void) => {
|
||||
const listener = (_event: unknown, value: number | null) => callback(value);
|
||||
|
||||
@@ -14,7 +14,10 @@ export function CountdownOverlay() {
|
||||
return (
|
||||
<div className="w-screen h-screen bg-transparent flex items-center justify-center pointer-events-none select-none">
|
||||
{value === null ? null : (
|
||||
<div className="text-white/90 text-[120px] font-bold leading-none tabular-nums">
|
||||
<div
|
||||
className="text-white/90 text-[120px] font-bold leading-none tabular-nums"
|
||||
style={{ textShadow: "0 4px 24px rgba(0, 0, 0, 0.65)" }}
|
||||
>
|
||||
{value}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -336,9 +336,10 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
|
||||
}
|
||||
|
||||
return () => {
|
||||
const activeRunId = countdownRunId.current;
|
||||
if (cleanup) cleanup();
|
||||
countdownRunId.current += 1;
|
||||
void window.electronAPI.hideCountdownOverlay();
|
||||
void window.electronAPI.hideCountdownOverlay(activeRunId);
|
||||
allowAutoFinalize.current = false;
|
||||
restarting.current = false;
|
||||
discardRecordingId.current = null;
|
||||
@@ -370,14 +371,15 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
|
||||
}, [teardownMedia]);
|
||||
|
||||
const cancelCountdown = () => {
|
||||
const activeRunId = countdownRunId.current;
|
||||
countdownRunId.current += 1;
|
||||
setCountdownActive(false);
|
||||
void window.electronAPI.hideCountdownOverlay();
|
||||
void window.electronAPI.hideCountdownOverlay(activeRunId);
|
||||
};
|
||||
|
||||
const safeShowCountdownOverlay = async (value: number) => {
|
||||
const safeShowCountdownOverlay = async (value: number, runId: number) => {
|
||||
try {
|
||||
await window.electronAPI.showCountdownOverlay(value);
|
||||
await window.electronAPI.showCountdownOverlay(value, runId);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.warn("Failed to show countdown overlay:", error);
|
||||
@@ -385,17 +387,17 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
|
||||
}
|
||||
};
|
||||
|
||||
const safeSetCountdownOverlayValue = async (value: number) => {
|
||||
const safeSetCountdownOverlayValue = async (value: number, runId: number) => {
|
||||
try {
|
||||
await window.electronAPI.setCountdownOverlayValue(value);
|
||||
await window.electronAPI.setCountdownOverlayValue(value, runId);
|
||||
} catch (error) {
|
||||
console.warn("Failed to update countdown overlay value:", error);
|
||||
}
|
||||
};
|
||||
|
||||
const safeHideCountdownOverlay = async () => {
|
||||
const safeHideCountdownOverlay = async (runId: number) => {
|
||||
try {
|
||||
await window.electronAPI.hideCountdownOverlay();
|
||||
await window.electronAPI.hideCountdownOverlay(runId);
|
||||
} catch (error) {
|
||||
console.warn("Failed to hide countdown overlay:", error);
|
||||
}
|
||||
@@ -427,7 +429,11 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
|
||||
|
||||
try {
|
||||
const values = [3, 2, 1];
|
||||
const overlayShown = await safeShowCountdownOverlay(values[0]);
|
||||
const overlayShown = await safeShowCountdownOverlay(values[0], runId);
|
||||
|
||||
if (countdownRunId.current !== runId) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const value of values) {
|
||||
if (countdownRunId.current !== runId) {
|
||||
@@ -435,7 +441,11 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
|
||||
}
|
||||
|
||||
if (overlayShown && value !== values[0]) {
|
||||
await safeSetCountdownOverlayValue(value);
|
||||
await safeSetCountdownOverlayValue(value, runId);
|
||||
|
||||
if (countdownRunId.current !== runId) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
await new Promise((resolve) => window.setTimeout(resolve, 1000));
|
||||
@@ -449,7 +459,7 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
|
||||
} finally {
|
||||
if (countdownRunId.current === runId) {
|
||||
setCountdownActive(false);
|
||||
await safeHideCountdownOverlay();
|
||||
await safeHideCountdownOverlay(runId);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user