mirror of
https://github.com/webadderallorg/Recordly.git
synced 2026-09-25 23:35:43 +00:00
fix(countdown): prevent overlapping timers with in-flight lock
- Add countdownInProgress flag in IPC handler to reject concurrent starts - Add countdownActive state in renderer to block re-entry - Disable Record button while countdown is active
This commit is contained in:
@@ -81,6 +81,7 @@ let cachedSystemCursorAssets: Record<string, SystemCursorAsset> | null = null
|
||||
let cachedSystemCursorAssetsSourceMtimeMs: number | null = null
|
||||
let countdownTimer: ReturnType<typeof setInterval> | null = null
|
||||
let countdownCancelled = false
|
||||
let countdownInProgress = false
|
||||
|
||||
type SystemCursorAsset = {
|
||||
dataUrl: string
|
||||
@@ -2767,6 +2768,11 @@ export function registerIpcHandlers(
|
||||
})
|
||||
|
||||
ipcMain.handle('start-countdown', async (_, seconds: number) => {
|
||||
if (countdownInProgress) {
|
||||
return { success: false, error: 'Countdown already in progress' }
|
||||
}
|
||||
|
||||
countdownInProgress = true
|
||||
countdownCancelled = false
|
||||
|
||||
const countdownWin = createCountdownWindow()
|
||||
@@ -2789,6 +2795,7 @@ export function registerIpcHandlers(
|
||||
countdownTimer = null
|
||||
}
|
||||
closeCountdownWindow()
|
||||
countdownInProgress = false
|
||||
resolve({ success: false, cancelled: true })
|
||||
return
|
||||
}
|
||||
@@ -2801,6 +2808,7 @@ export function registerIpcHandlers(
|
||||
countdownTimer = null
|
||||
}
|
||||
closeCountdownWindow()
|
||||
countdownInProgress = false
|
||||
resolve({ success: true })
|
||||
} else {
|
||||
const win = getCountdownWindow()
|
||||
@@ -2814,6 +2822,7 @@ export function registerIpcHandlers(
|
||||
|
||||
ipcMain.handle('cancel-countdown', () => {
|
||||
countdownCancelled = true
|
||||
countdownInProgress = false
|
||||
if (countdownTimer) {
|
||||
clearInterval(countdownTimer)
|
||||
countdownTimer = null
|
||||
|
||||
@@ -31,6 +31,7 @@ export function LaunchWindow() {
|
||||
const LOCALE_LABELS: Record<string, string> = { en: "EN", es: "ES", "zh-CN": "中文" };
|
||||
const {
|
||||
recording,
|
||||
countdownActive,
|
||||
toggleRecording,
|
||||
microphoneEnabled,
|
||||
setMicrophoneEnabled,
|
||||
@@ -283,7 +284,7 @@ export function LaunchWindow() {
|
||||
variant="link"
|
||||
size="sm"
|
||||
onClick={hasSelectedSource ? toggleRecording : openSourceSelector}
|
||||
disabled={!hasSelectedSource && !recording}
|
||||
disabled={countdownActive || (!hasSelectedSource && !recording)}
|
||||
className={`gap-1 text-white bg-transparent hover:bg-transparent px-0 text-xs ${styles.electronNoDrag}`}
|
||||
>
|
||||
{recording ? (
|
||||
|
||||
@@ -28,6 +28,7 @@ const MIC_GAIN_BOOST = 1.4;
|
||||
|
||||
type UseScreenRecorderReturn = {
|
||||
recording: boolean;
|
||||
countdownActive: boolean;
|
||||
toggleRecording: () => void;
|
||||
preparePermissions: (options?: { startup?: boolean }) => Promise<boolean>;
|
||||
isMacOS: boolean;
|
||||
@@ -44,6 +45,7 @@ type UseScreenRecorderReturn = {
|
||||
export function useScreenRecorder(): UseScreenRecorderReturn {
|
||||
const [recording, setRecording] = useState(false);
|
||||
const [starting, setStarting] = useState(false);
|
||||
const [countdownActive, setCountdownActive] = useState(false);
|
||||
const [isMacOS, setIsMacOS] = useState(false);
|
||||
const [microphoneEnabled, setMicrophoneEnabled] = useState(false);
|
||||
const [microphoneDeviceId, setMicrophoneDeviceId] = useState<string | undefined>(undefined);
|
||||
@@ -570,7 +572,7 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
|
||||
};
|
||||
|
||||
const toggleRecording = async () => {
|
||||
if (starting) {
|
||||
if (starting || countdownActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -581,9 +583,14 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
|
||||
|
||||
// Start recording with optional countdown
|
||||
if (countdownDelay > 0) {
|
||||
const result = await window.electronAPI.startCountdown(countdownDelay);
|
||||
if (!result.success || result.cancelled) {
|
||||
return;
|
||||
setCountdownActive(true);
|
||||
try {
|
||||
const result = await window.electronAPI.startCountdown(countdownDelay);
|
||||
if (!result.success || result.cancelled) {
|
||||
return;
|
||||
}
|
||||
} finally {
|
||||
setCountdownActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -592,6 +599,7 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
|
||||
|
||||
return {
|
||||
recording,
|
||||
countdownActive,
|
||||
toggleRecording,
|
||||
preparePermissions,
|
||||
isMacOS,
|
||||
|
||||
Reference in New Issue
Block a user