Skip to content

Commit fdc8833

Browse files
committed
fix: addresses review - differentiate webcam error types and handle stream acquisition
1 parent 20b0899 commit fdc8833

5 files changed

Lines changed: 34 additions & 4 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ dist-ssr
2525
*.sw?
2626
release/**
2727
*.kiro/
28+
.claude/
2829
# npx electron-builder --mac --win
2930

3031
# Playwright

src/hooks/useScreenRecorder.ts

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
103103
const allowAutoFinalize = useRef(false);
104104
const discardRecordingId = useRef<number | null>(null);
105105
const restarting = useRef(false);
106+
const webcamReady = useRef(false);
106107

107108
const selectMimeType = () => {
108109
const preferred = [
@@ -182,6 +183,7 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
182183

183184
let cancelled = false;
184185
let acquiredStream: MediaStream | null = null;
186+
webcamReady.current = false;
185187

186188
const acquire = async () => {
187189
try {
@@ -217,11 +219,18 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
217219
};
218220
});
219221
webcamStream.current = stream;
222+
webcamReady.current = true;
220223
} catch (cameraError) {
221224
if (!cancelled) {
222225
console.warn("Failed to get webcam access:", cameraError);
223226
setWebcamEnabledState(false);
224-
toast.error(t("recording.cameraBlocked"));
227+
const isDeviceError =
228+
cameraError instanceof DOMException &&
229+
["NotFoundError", "OverconstrainedError", "NotReadableError"].includes(
230+
cameraError.name,
231+
);
232+
toast.error(t(isDeviceError ? "recording.cameraNotFound" : "recording.cameraBlocked"));
233+
webcamReady.current = true;
225234
}
226235
}
227236
};
@@ -230,6 +239,7 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
230239

231240
return () => {
232241
cancelled = true;
242+
webcamReady.current = false;
233243
if (acquiredStream) {
234244
acquiredStream.getTracks().forEach((track) => track.stop());
235245
webcamStream.current = null;
@@ -464,9 +474,25 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
464474
}
465475
}
466476

467-
if (webcamEnabled && !webcamStream.current) {
468-
setWebcamEnabledState(false);
469-
toast.error(t("recording.cameraDenied"));
477+
if (webcamEnabled) {
478+
if (!webcamReady.current) {
479+
await new Promise<void>((resolve) => {
480+
const interval = setInterval(() => {
481+
if (webcamReady.current) {
482+
clearInterval(interval);
483+
resolve();
484+
}
485+
}, 50);
486+
setTimeout(() => {
487+
clearInterval(interval);
488+
resolve();
489+
}, 5000);
490+
});
491+
}
492+
if (!webcamStream.current) {
493+
setWebcamEnabledState(false);
494+
toast.error(t("recording.cameraDenied"));
495+
}
470496
}
471497

472498
stream.current = new MediaStream();

src/i18n/locales/en/editor.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"microphoneDenied": "Microphone access denied. Recording will continue without audio.",
3232
"cameraDenied": "Camera access denied. Recording will continue without webcam.",
3333
"cameraDisconnected": "Webcam disconnected.",
34+
"cameraNotFound": "Camera not found.",
3435
"permissionDenied": "Recording permission denied. Please allow screen recording."
3536
}
3637
}

src/i18n/locales/es/editor.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"microphoneDenied": "Acceso al micrófono denegado. La grabación continuará sin audio.",
3232
"cameraDenied": "Acceso a la cámara denegado. La grabación continuará sin cámara web.",
3333
"cameraDisconnected": "Cámara web desconectada.",
34+
"cameraNotFound": "Cámara no encontrada.",
3435
"permissionDenied": "Permiso de grabación denegado. Por favor permite la grabación de pantalla."
3536
}
3637
}

src/i18n/locales/zh-CN/editor.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"microphoneDenied": "麦克风权限被拒绝。录制将继续,但不包含音频。",
3232
"cameraDenied": "摄像头权限被拒绝。录制将继续,但不包含摄像头画面。",
3333
"cameraDisconnected": "摄像头已断开连接。",
34+
"cameraNotFound": "未找到摄像头。",
3435
"permissionDenied": "录屏权限被拒绝。请允许屏幕录制。"
3536
}
3637
}

0 commit comments

Comments
 (0)