fix: address remaining timeline review feedback

This commit is contained in:
webadderall
2026-04-17 00:23:52 +10:00
parent 1dc758e535
commit f91e29abba
4 changed files with 91 additions and 60 deletions
@@ -130,7 +130,6 @@ export default function Item({
}}
onClick={(event) => {
event.stopPropagation();
onSelect?.();
}}
>
<div
@@ -404,11 +404,11 @@ describe("findDominantRegion", () => {
it("holds the next region's focus between connected-transition end and next start", () => {
const regions: ZoomRegion[] = [
{ id: "a", startMs: 1000, endMs: 3000, depth: 2, focus: { cx: 0.2, cy: 0.2 } },
{ id: "b", startMs: 4200, endMs: 7000, depth: 3, focus: { cx: 0.7, cy: 0.7 } },
{ id: "b", startMs: 4300, endMs: 7000, depth: 3, focus: { cx: 0.7, cy: 0.7 } },
];
// After transition end (3000+200+1000=4200) but before b starts (4200)
const result = findDominantRegion(regions, 4100, { connectZooms: true });
// After transition end (3000+200+1000=4200) but before b starts (4300)
const result = findDominantRegion(regions, 4250, { connectZooms: true });
expect(result.strength).toBe(1);
expect(result.region).not.toBeNull();
expect(result.region!.id).toBe("b");
@@ -157,7 +157,7 @@ function getActiveRegion(
function getConnectedRegionHold(timeMs: number, connectedPairs: ConnectedRegionPair[]) {
for (const pair of connectedPairs) {
if (timeMs > pair.transitionEnd && timeMs < pair.nextRegion.startMs) {
if (timeMs >= pair.transitionEnd && timeMs < pair.nextRegion.startMs) {
const nextScale = ZOOM_DEPTH_SCALES[pair.nextRegion.depth];
return {
region: {
+87 -55
View File
@@ -398,38 +398,101 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
[clearRecordingFinalizationToast],
);
const stopMicFallbackRecorder = useCallback((): Promise<Blob | null> => {
return new Promise((resolve) => {
const recorder = micFallbackRecorder.current;
if (!recorder || recorder.state === "inactive") {
micFallbackRecorder.current = null;
resolve(null);
return;
}
recorder.ondataavailable = (event) => {
if (event.data.size > 0) {
micFallbackChunks.current.push(event.data);
}
};
recorder.onstop = () => {
const blob =
micFallbackChunks.current.length > 0
? new Blob(micFallbackChunks.current, { type: recorder.mimeType })
: null;
micFallbackChunks.current = [];
recorder.stream.getTracks().forEach((track) => track.stop());
micFallbackRecorder.current = null;
resolve(blob);
};
recorder.stop();
});
}, []);
const storeMicrophoneSidecar = useCallback(
async (micFallbackBlobPromise: Promise<Blob | null> | null | undefined, finalPath: string) => {
const micFallbackBlob = await micFallbackBlobPromise;
if (!micFallbackBlob) {
return;
}
try {
const arrayBuffer = await micFallbackBlob.arrayBuffer();
await window.electronAPI.storeMicrophoneSidecar(arrayBuffer, finalPath);
} catch (error) {
console.warn("Failed to store microphone sidecar:", error);
}
},
[],
);
const stopWebcamRecorder = useCallback(async () => {
const recorder = webcamRecorder.current;
const pending = webcamStopPromise.current;
if (!recorder) {
return null;
const result = pending ? await pending : resolvedWebcamPath.current;
webcamStopPromise.current = null;
pendingWebcamPathPromise.current = null;
resolvedWebcamPath.current = result ?? null;
return result ?? null;
}
if (recorder.state !== "inactive") {
recorder.stop();
} else if (pending && webcamStopResolver.current) {
webcamStopResolver.current(resolvedWebcamPath.current);
webcamStopResolver.current = null;
}
const result = pending ? await pending : null;
resolvedWebcamPath.current = result;
const result = pending ? await pending : resolvedWebcamPath.current;
webcamStopPromise.current = null;
pendingWebcamPathPromise.current = null;
return result;
resolvedWebcamPath.current = result ?? null;
return result ?? null;
}, []);
const recoverNativeRecordingSession = useCallback(async () => {
if (typeof window.electronAPI?.recoverNativeScreenRecording !== "function") {
return null;
}
const recoverNativeRecordingSession = useCallback(
async (micFallbackBlobPromise?: Promise<Blob | null> | null) => {
if (typeof window.electronAPI?.recoverNativeScreenRecording !== "function") {
return null;
}
const result = await window.electronAPI.recoverNativeScreenRecording();
if (!result.success || !result.path) {
return null;
}
const result = await window.electronAPI.recoverNativeScreenRecording();
if (!result.success || !result.path) {
return null;
}
const webcamPath = await stopWebcamRecorder();
await finalizeRecordingSession(result.path, webcamPath);
return result.path;
}, [finalizeRecordingSession, stopWebcamRecorder]);
const resolvedMicFallbackBlobPromise =
micFallbackBlobPromise ?? stopMicFallbackRecorder();
const webcamPath = await stopWebcamRecorder();
await storeMicrophoneSidecar(resolvedMicFallbackBlobPromise, result.path);
await finalizeRecordingSession(result.path, webcamPath);
return result.path;
},
[
finalizeRecordingSession,
stopMicFallbackRecorder,
stopWebcamRecorder,
storeMicrophoneSidecar,
],
);
/**
* Acquire the webcam stream and prepare the MediaRecorder, but do NOT start
@@ -573,7 +636,9 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
);
void logNativeCaptureDiagnostics("stop-native-screen-recording");
try {
const recoveredPath = await recoverNativeRecordingSession();
const recoveredPath = await recoverNativeRecordingSession(
micFallbackBlobPromise,
);
if (recoveredPath) {
return;
}
@@ -602,16 +667,7 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
finalPath = muxResult?.path ?? result.path;
}
// Save the browser-captured microphone sidecar if one was recorded.
const micFallbackBlob = await micFallbackBlobPromise;
if (micFallbackBlob && finalPath) {
try {
const arrayBuffer = await micFallbackBlob.arrayBuffer();
await window.electronAPI.storeMicrophoneSidecar(arrayBuffer, finalPath);
} catch (e) {
console.warn("Failed to store microphone sidecar:", e);
}
}
await storeMicrophoneSidecar(micFallbackBlobPromise, finalPath);
await finalizeRecordingSession(finalPath, webcamPath);
})();
@@ -751,40 +807,16 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
void window.electronAPI.stopNativeScreenRecording();
}
if (mediaRecorder.current?.state === "recording") {
mediaRecorder.current.stop();
const recorder = mediaRecorder.current;
const recorderState = recorder?.state;
if (recorder && (recorderState === "recording" || recorderState === "paused")) {
recorder.stop();
}
cleanupCapturedMedia();
};
}, [cleanupCapturedMedia, recoverNativeRecordingSession]);
const stopMicFallbackRecorder = useCallback((): Promise<Blob | null> => {
return new Promise((resolve) => {
const recorder = micFallbackRecorder.current;
if (!recorder || recorder.state === "inactive") {
micFallbackRecorder.current = null;
resolve(null);
return;
}
recorder.ondataavailable = (event) => {
if (event.data.size > 0) {
micFallbackChunks.current.push(event.data);
}
};
recorder.onstop = () => {
const blob =
micFallbackChunks.current.length > 0
? new Blob(micFallbackChunks.current, { type: recorder.mimeType })
: null;
micFallbackChunks.current = [];
micFallbackRecorder.current = null;
resolve(blob);
};
recorder.stop();
});
}, []);
const startRecording = async () => {
if (startInFlight.current) {
return;