Align recorder and cursor pause boundaries

This commit is contained in:
webadderall
2026-05-01 17:18:12 +10:00
parent 667efdc02e
commit 9df44c7bbf
5 changed files with 86 additions and 22 deletions
+2 -2
View File
@@ -151,12 +151,12 @@ interface Window {
message?: string;
error?: string;
}>;
pauseCursorCapture: () => Promise<{
pauseCursorCapture: (boundaryMs?: number) => Promise<{
success: boolean;
message?: string;
error?: string;
}>;
resumeCursorCapture: () => Promise<{
resumeCursorCapture: (boundaryMs?: number) => Promise<{
success: boolean;
message?: string;
error?: string;
+2 -2
View File
@@ -168,9 +168,9 @@ export function pushCursorSample(
}
}
export function sampleCursorPoint() {
export function sampleCursorPoint(sampledAtMs = Date.now()) {
const point = getNormalizedCursorPoint();
pushCursorSample(point.cx, point.cy, getCursorCaptureElapsedMs(), "move");
pushCursorSample(point.cx, point.cy, getCursorCaptureElapsedMs(sampledAtMs), "move");
}
export async function persistPendingCursorTelemetry(videoPath: string) {
+14 -6
View File
@@ -1312,15 +1312,23 @@ export function registerRecordingHandlers(
}
});
ipcMain.handle("pause-cursor-capture", () => {
sampleCursorPoint();
pauseCursorCapture(Date.now());
ipcMain.handle("pause-cursor-capture", (_event, boundaryMs?: number) => {
const timestamp =
typeof boundaryMs === "number" && Number.isFinite(boundaryMs)
? boundaryMs
: Date.now();
sampleCursorPoint(timestamp);
pauseCursorCapture(timestamp);
return { success: true };
});
ipcMain.handle("resume-cursor-capture", () => {
resumeCursorCapture(Date.now());
sampleCursorPoint();
ipcMain.handle("resume-cursor-capture", (_event, boundaryMs?: number) => {
const timestamp =
typeof boundaryMs === "number" && Number.isFinite(boundaryMs)
? boundaryMs
: Date.now();
resumeCursorCapture(timestamp);
sampleCursorPoint(timestamp);
return { success: true };
});
+4 -4
View File
@@ -293,11 +293,11 @@ contextBridge.exposeInMainWorld("electronAPI", {
resumeNativeScreenRecording: () => {
return ipcRenderer.invoke("resume-native-screen-recording");
},
pauseCursorCapture: () => {
return ipcRenderer.invoke("pause-cursor-capture");
pauseCursorCapture: (boundaryMs?: number) => {
return ipcRenderer.invoke("pause-cursor-capture", boundaryMs);
},
resumeCursorCapture: () => {
return ipcRenderer.invoke("resume-cursor-capture");
resumeCursorCapture: (boundaryMs?: number) => {
return ipcRenderer.invoke("resume-cursor-capture", boundaryMs);
},
startFfmpegRecording: (source: ProcessedDesktopSource) => {
return ipcRenderer.invoke("start-ffmpeg-recording", source);
+64 -8
View File
@@ -1440,12 +1440,32 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
if (webcamRecorder.current?.state === "recording") {
webcamRecorder.current.pause();
}
const boundaryMs = Date.now();
try {
await window.electronAPI.pauseCursorCapture();
await window.electronAPI.pauseCursorCapture(boundaryMs);
} catch (error) {
console.warn("Failed to pause cursor capture:", error);
try {
const rollbackResult =
await window.electronAPI.resumeNativeScreenRecording();
if (!rollbackResult.success) {
console.warn(
"Failed to roll back native pause after cursor pause failure:",
rollbackResult.error ?? rollbackResult.message,
);
}
} catch (rollbackError) {
console.warn(
"Failed to roll back native pause after cursor pause failure:",
rollbackError,
);
}
if (webcamRecorder.current?.state === "paused") {
webcamRecorder.current.resume();
}
return;
}
markRecordingPaused(Date.now());
markRecordingPaused(boundaryMs);
setPaused(true);
})();
return;
@@ -1455,13 +1475,21 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
if (webcamRecorder.current?.state === "recording") {
webcamRecorder.current.pause();
}
const boundaryMs = Date.now();
void (async () => {
try {
await window.electronAPI.pauseCursorCapture();
await window.electronAPI.pauseCursorCapture(boundaryMs);
} catch (error) {
console.warn("Failed to pause cursor capture:", error);
if (mediaRecorder.current?.state === "paused") {
mediaRecorder.current.resume();
}
if (webcamRecorder.current?.state === "paused") {
webcamRecorder.current.resume();
}
return;
}
markRecordingPaused(Date.now());
markRecordingPaused(boundaryMs);
setPaused(true);
})();
}
@@ -1483,12 +1511,32 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
if (webcamRecorder.current?.state === "paused") {
webcamRecorder.current.resume();
}
const boundaryMs = Date.now();
try {
await window.electronAPI.resumeCursorCapture();
await window.electronAPI.resumeCursorCapture(boundaryMs);
} catch (error) {
console.warn("Failed to resume cursor capture:", error);
try {
const rollbackResult =
await window.electronAPI.pauseNativeScreenRecording();
if (!rollbackResult.success) {
console.warn(
"Failed to roll back native resume after cursor resume failure:",
rollbackResult.error ?? rollbackResult.message,
);
}
} catch (rollbackError) {
console.warn(
"Failed to roll back native resume after cursor resume failure:",
rollbackError,
);
}
if (webcamRecorder.current?.state === "recording") {
webcamRecorder.current.pause();
}
return;
}
markRecordingResumed(Date.now());
markRecordingResumed(boundaryMs);
setPaused(false);
})();
return;
@@ -1498,13 +1546,21 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
if (webcamRecorder.current?.state === "paused") {
webcamRecorder.current.resume();
}
const boundaryMs = Date.now();
void (async () => {
try {
await window.electronAPI.resumeCursorCapture();
await window.electronAPI.resumeCursorCapture(boundaryMs);
} catch (error) {
console.warn("Failed to resume cursor capture:", error);
if (mediaRecorder.current?.state === "recording") {
mediaRecorder.current.pause();
}
if (webcamRecorder.current?.state === "recording") {
webcamRecorder.current.pause();
}
return;
}
markRecordingResumed(Date.now());
markRecordingResumed(boundaryMs);
setPaused(false);
})();
}