revert: undo manual merge of PR #314

This commit is contained in:
Siddharth
2026-04-05 10:05:04 -07:00
parent 08f66c7c25
commit 475cbcd76c
6 changed files with 38 additions and 144 deletions
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "openscreen",
"version": "1.3.0",
"version": "1.2.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "openscreen",
"version": "1.3.0",
"version": "1.2.0",
"dependencies": {
"@fix-webm-duration/fix": "^1.0.1",
"@pixi/filter-drop-shadow": "^5.2.0",
+26 -27
View File
@@ -1,6 +1,6 @@
import { ChevronDown, Languages } from "lucide-react";
import { useEffect, useState } from "react";
import { BsPauseCircle, BsPlayCircle, BsRecordCircle } from "react-icons/bs";
import { BsRecordCircle } from "react-icons/bs";
import { FaRegStopCircle } from "react-icons/fa";
import { FaFolderOpen } from "react-icons/fa6";
import { FiMinus, FiX } from "react-icons/fi";
@@ -42,8 +42,6 @@ const ICON_CONFIG = {
micOff: { icon: MdMicOff, size: ICON_SIZE },
webcamOn: { icon: MdVideocam, size: ICON_SIZE },
webcamOff: { icon: MdVideocamOff, size: ICON_SIZE },
pause: { icon: BsPauseCircle, size: ICON_SIZE },
resume: { icon: BsPlayCircle, size: ICON_SIZE },
stop: { icon: FaRegStopCircle, size: ICON_SIZE },
restart: { icon: MdRestartAlt, size: ICON_SIZE },
cancel: { icon: MdCancel, size: ICON_SIZE },
@@ -81,10 +79,7 @@ export function LaunchWindow() {
const {
recording,
paused,
elapsedSeconds,
toggleRecording,
togglePaused,
restartRecording,
cancelRecording,
microphoneEnabled,
@@ -98,6 +93,8 @@ export function LaunchWindow() {
webcamDeviceId,
setWebcamDeviceId,
} = useScreenRecorder();
const [recordingStart, setRecordingStart] = useState<number | null>(null);
const [elapsed, setElapsed] = useState(0);
const showMicControls = microphoneEnabled && !recording;
const showWebcamControls = webcamEnabled && !recording;
@@ -152,6 +149,25 @@ export function LaunchWindow() {
}
}, [selectedCameraId, setWebcamDeviceId]);
useEffect(() => {
let timer: NodeJS.Timeout | null = null;
if (recording) {
if (!recordingStart) setRecordingStart(Date.now());
timer = setInterval(() => {
if (recordingStart) {
setElapsed(Math.floor((Date.now() - recordingStart) / 1000));
}
}, 1000);
} else {
setRecordingStart(null);
setElapsed(0);
if (timer) clearInterval(timer);
}
return () => {
if (timer) clearInterval(timer);
};
}, [recording, recordingStart]);
useEffect(() => {
if (!import.meta.env.DEV) {
return;
@@ -434,11 +450,7 @@ export function LaunchWindow() {
{/* Record/Stop group */}
<button
className={`flex items-center gap-0.5 rounded-full p-2 transition-colors duration-150 ${styles.electronNoDrag} ${
recording
? paused
? "bg-amber-500/10 hover:bg-amber-500/15"
: "animate-record-pulse bg-red-500/10"
: "bg-white/5 hover:bg-white/[0.08]"
recording ? "animate-record-pulse bg-red-500/10" : "bg-white/5 hover:bg-white/[0.08]"
}`}
onClick={toggleRecording}
disabled={!hasSelectedSource && !recording}
@@ -446,11 +458,9 @@ export function LaunchWindow() {
>
{recording ? (
<>
{getIcon("stop", paused ? "text-amber-400" : "text-red-400")}
<span
className={`${paused ? "text-amber-400" : "text-red-400"} text-xs font-semibold tabular-nums`}
>
{formatTimePadded(elapsedSeconds)}
{getIcon("stop", "text-red-400")}
<span className="text-red-400 text-xs font-semibold tabular-nums">
{formatTimePadded(elapsed)}
</span>
</>
) : (
@@ -458,17 +468,6 @@ export function LaunchWindow() {
)}
</button>
{recording && (
<Tooltip content={paused ? t("tooltips.resumeRecording") : t("tooltips.pauseRecording")}>
<button
className={`${hudIconBtnClasses} ${styles.electronNoDrag}`}
onClick={togglePaused}
>
{getIcon(paused ? "resume" : "pause", paused ? "text-amber-400" : "text-white/60")}
</button>
</Tooltip>
)}
{/* Restart recording */}
{recording && (
<Tooltip content={t("tooltips.restartRecording")}>
+10 -109
View File
@@ -41,10 +41,7 @@ const WEBCAM_TARGET_FRAME_RATE = 30;
type UseScreenRecorderReturn = {
recording: boolean;
paused: boolean;
elapsedSeconds: number;
toggleRecording: () => void;
togglePaused: () => void;
restartRecording: () => void;
cancelRecording: () => void;
microphoneEnabled: boolean;
@@ -89,8 +86,6 @@ function createRecorderHandle(stream: MediaStream, options: MediaRecorderOptions
export function useScreenRecorder(): UseScreenRecorderReturn {
const t = useScopedT("editor");
const [recording, setRecording] = useState(false);
const [paused, setPaused] = useState(false);
const [elapsedSeconds, setElapsedSeconds] = useState(0);
const [microphoneEnabled, setMicrophoneEnabled] = useState(false);
const [microphoneDeviceId, setMicrophoneDeviceId] = useState<string | undefined>(undefined);
const [webcamDeviceId, setWebcamDeviceId] = useState<string | undefined>(undefined);
@@ -103,20 +98,13 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
const microphoneStream = useRef<MediaStream | null>(null);
const webcamStream = useRef<MediaStream | null>(null);
const mixingContext = useRef<AudioContext | null>(null);
const startTime = useRef<number>(0);
const recordingId = useRef<number>(0);
const accumulatedDurationMs = useRef(0);
const segmentStartedAt = useRef<number | null>(null);
const finalizingRecordingId = useRef<number | null>(null);
const allowAutoFinalize = useRef(false);
const discardRecordingId = useRef<number | null>(null);
const restarting = useRef(false);
const getRecordingDurationMs = useCallback(() => {
const segmentDuration =
segmentStartedAt.current === null ? 0 : Date.now() - segmentStartedAt.current;
return accumulatedDurationMs.current + segmentDuration;
}, []);
const selectMimeType = () => {
const preferred = [
"video/webm;codecs=av1",
@@ -215,10 +203,6 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
teardownMedia();
setRecording(false);
setPaused(false);
setElapsedSeconds(0);
accumulatedDurationMs.current = 0;
segmentStartedAt.current = null;
window.electronAPI?.setRecordingState(false);
void (async () => {
@@ -290,7 +274,7 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
}
const activeWebcamRecorder = webcamRecorder.current;
const duration = getRecordingDurationMs();
const duration = Date.now() - startTime.current;
const activeRecordingId = recordingId.current;
finalizeRecording(
@@ -300,10 +284,7 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
activeRecordingId,
);
if (
activeScreenRecorder.recorder.state === "recording" ||
activeScreenRecorder.recorder.state === "paused"
) {
if (activeScreenRecorder.recorder.state === "recording") {
try {
activeScreenRecorder.recorder.stop();
} catch {
@@ -311,10 +292,7 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
}
}
if (activeWebcamRecorder) {
if (
activeWebcamRecorder.recorder.state === "recording" ||
activeWebcamRecorder.recorder.state === "paused"
) {
if (activeWebcamRecorder.recorder.state === "recording") {
try {
activeWebcamRecorder.recorder.stop();
} catch {
@@ -339,20 +317,14 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
restarting.current = false;
discardRecordingId.current = null;
if (
screenRecorder.current?.recorder.state === "recording" ||
screenRecorder.current?.recorder.state === "paused"
) {
if (screenRecorder.current?.recorder.state === "recording") {
try {
screenRecorder.current.recorder.stop();
} catch {
// Ignore recorder teardown errors during cleanup.
}
}
if (
webcamRecorder.current?.recorder.state === "recording" ||
webcamRecorder.current?.recorder.state === "paused"
) {
if (webcamRecorder.current?.recorder.state === "recording") {
try {
webcamRecorder.current.recorder.stop();
} catch {
@@ -547,12 +519,9 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
}
recordingId.current = Date.now();
accumulatedDurationMs.current = 0;
segmentStartedAt.current = Date.now();
startTime.current = recordingId.current;
allowAutoFinalize.current = true;
setRecording(true);
setPaused(false);
setElapsedSeconds(0);
window.electronAPI?.setRecordingState(true);
const activeScreenRecorder = screenRecorder.current;
@@ -568,7 +537,7 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
finalizeRecording(
activeScreenRecorder,
activeWebcamRecorder ?? null,
Math.max(0, getRecordingDurationMs()),
Math.max(0, Date.now() - startTime.current),
activeRecordingId,
);
},
@@ -584,56 +553,12 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
toast.error(errorMsg);
}
setRecording(false);
setPaused(false);
setElapsedSeconds(0);
accumulatedDurationMs.current = 0;
segmentStartedAt.current = null;
screenRecorder.current = null;
webcamRecorder.current = null;
teardownMedia();
}
};
const togglePaused = () => {
const activeScreenRecorder = screenRecorder.current?.recorder;
if (!activeScreenRecorder || activeScreenRecorder.state === "inactive") {
return;
}
const activeWebcamRecorder = webcamRecorder.current?.recorder;
if (activeScreenRecorder.state === "paused") {
try {
activeScreenRecorder.resume();
if (activeWebcamRecorder?.state === "paused") {
activeWebcamRecorder.resume();
}
segmentStartedAt.current = Date.now();
setPaused(false);
} catch (error) {
console.error("Failed to resume recording:", error);
}
return;
}
if (activeScreenRecorder.state !== "recording") {
return;
}
try {
accumulatedDurationMs.current = getRecordingDurationMs();
segmentStartedAt.current = null;
setElapsedSeconds(Math.floor(accumulatedDurationMs.current / 1000));
activeScreenRecorder.pause();
if (activeWebcamRecorder?.state === "recording") {
activeWebcamRecorder.pause();
}
setPaused(true);
} catch (error) {
console.error("Failed to pause recording:", error);
}
};
const toggleRecording = () => {
recording ? stopRecording.current() : startRecording();
};
@@ -642,7 +567,7 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
if (restarting.current) return;
const activeScreenRecorder = screenRecorder.current;
if (!activeScreenRecorder || activeScreenRecorder.recorder.state === "inactive") return;
if (!activeScreenRecorder || activeScreenRecorder.recorder.state !== "recording") return;
const activeWebcamRecorder = webcamRecorder.current;
const activeRecordingId = recordingId.current;
@@ -657,10 +582,7 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
}),
];
if (
activeWebcamRecorder?.recorder.state === "recording" ||
activeWebcamRecorder?.recorder.state === "paused"
) {
if (activeWebcamRecorder?.recorder.state === "recording") {
stopPromises.push(
new Promise<void>((resolve) => {
activeWebcamRecorder.recorder.addEventListener("stop", () => resolve(), {
@@ -691,30 +613,9 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
stopRecording.current();
};
useEffect(() => {
if (!recording) {
setElapsedSeconds(0);
return;
}
setElapsedSeconds(Math.floor(getRecordingDurationMs() / 1000));
if (paused) {
return;
}
const interval = window.setInterval(() => {
setElapsedSeconds(Math.floor(getRecordingDurationMs() / 1000));
}, 250);
return () => window.clearInterval(interval);
}, [getRecordingDurationMs, paused, recording]);
return {
recording,
paused,
elapsedSeconds,
toggleRecording,
togglePaused,
restartRecording,
cancelRecording,
microphoneEnabled,
-2
View File
@@ -4,8 +4,6 @@
"closeApp": "Close App",
"restartRecording": "Restart recording",
"cancelRecording": "Cancel recording",
"pauseRecording": "Pause recording",
"resumeRecording": "Resume recording",
"openVideoFile": "Open video file",
"openProject": "Open project"
},
-2
View File
@@ -4,8 +4,6 @@
"closeApp": "Cerrar aplicación",
"restartRecording": "Reiniciar grabación",
"cancelRecording": "Cancelar grabación",
"pauseRecording": "Pausar grabación",
"resumeRecording": "Reanudar grabación",
"openVideoFile": "Abrir archivo de video",
"openProject": "Abrir proyecto"
},
-2
View File
@@ -4,8 +4,6 @@
"closeApp": "关闭应用",
"restartRecording": "重新开始录制",
"cancelRecording": "取消录制",
"pauseRecording": "暂停录制",
"resumeRecording": "继续录制",
"openVideoFile": "打开视频文件",
"openProject": "打开项目"
},