Default editor cursor off for browser recordings

This commit is contained in:
webadderall
2026-05-02 20:18:17 +10:00
parent 3e871b924d
commit 26c15958e8
6 changed files with 48 additions and 12 deletions
+19 -7
View File
@@ -400,16 +400,28 @@ interface Window {
}>;
setCurrentVideoPath: (
path: string,
options?: { preserveProjectPath?: boolean },
options?: {
preserveProjectPath?: boolean;
hideOverlayCursorByDefault?: boolean;
},
) => Promise<{ success: boolean; webcamPath: string | null }>;
setCurrentRecordingSession: (session: {
videoPath: string;
webcamPath?: string | null;
timeOffsetMs?: number;
}, options?: { preserveProjectPath?: boolean }) => Promise<{ success: boolean }>;
setCurrentRecordingSession: (
session: {
videoPath: string;
webcamPath?: string | null;
timeOffsetMs?: number;
hideOverlayCursorByDefault?: boolean;
},
options?: { preserveProjectPath?: boolean },
) => Promise<{ success: boolean }>;
getCurrentRecordingSession: () => Promise<{
success: boolean;
session?: { videoPath: string; webcamPath?: string | null; timeOffsetMs?: number };
session?: {
videoPath: string;
webcamPath?: string | null;
timeOffsetMs?: number;
hideOverlayCursorByDefault?: boolean;
};
}>;
getCurrentVideoPath: () => Promise<{ success: boolean; path?: string }>;
clearCurrentVideoPath: () => Promise<{ success: boolean }>;
+13 -3
View File
@@ -45,6 +45,10 @@ function normalizeRecordingTimeOffsetMs(value: unknown): number {
return typeof value === "number" && Number.isFinite(value) ? Math.round(value) : 0;
}
function normalizeBoolean(value: unknown, fallback = false): boolean {
return typeof value === "boolean" ? value : fallback;
}
/**
* Produces a filesystem-safe project base name without the project extension.
*/
@@ -527,7 +531,7 @@ export function registerProjectHandlers() {
return { success: false, error: String(error), message: 'Failed to open projects folder.' }
}
})
ipcMain.handle('set-current-video-path', async (_, path: string, options?: { preserveProjectPath?: boolean }) => {
ipcMain.handle('set-current-video-path', async (_, path: string, options?: { preserveProjectPath?: boolean; hideOverlayCursorByDefault?: boolean }) => {
setCurrentVideoPath(normalizeVideoSourcePath(path) ?? path)
approveUserPath(currentVideoPath)
const resolvedSession = await resolveRecordingSession(currentVideoPath)
@@ -537,7 +541,12 @@ export function registerProjectHandlers() {
timeOffsetMs: 0,
}
setCurrentRecordingSession(resolvedSession)
setCurrentRecordingSession({
...resolvedSession,
hideOverlayCursorByDefault:
normalizeBoolean(options?.hideOverlayCursorByDefault) ||
normalizeBoolean(resolvedSession.hideOverlayCursorByDefault),
})
await replaceApprovedSessionLocalReadPaths([
resolvedSession.videoPath,
resolvedSession.webcamPath,
@@ -553,13 +562,14 @@ export function registerProjectHandlers() {
return { success: true, webcamPath: resolvedSession.webcamPath ?? null }
})
ipcMain.handle('set-current-recording-session', async (_, session: { videoPath: string; webcamPath?: string | null; timeOffsetMs?: number }, options?: { preserveProjectPath?: boolean }) => {
ipcMain.handle('set-current-recording-session', async (_, session: { videoPath: string; webcamPath?: string | null; timeOffsetMs?: number; hideOverlayCursorByDefault?: boolean }, options?: { preserveProjectPath?: boolean }) => {
const normalizedVideoPath = normalizeVideoSourcePath(session.videoPath) ?? session.videoPath
setCurrentVideoPath(normalizedVideoPath)
setCurrentRecordingSession({
videoPath: normalizedVideoPath,
webcamPath: normalizeVideoSourcePath(session.webcamPath ?? null),
timeOffsetMs: normalizeRecordingTimeOffsetMs(session.timeOffsetMs),
hideOverlayCursorByDefault: normalizeBoolean(session.hideOverlayCursorByDefault),
});
await replaceApprovedSessionLocalReadPaths([
currentRecordingSession!.videoPath,
+1
View File
@@ -47,6 +47,7 @@ export type RecordingSessionData = {
videoPath: string;
webcamPath?: string | null;
timeOffsetMs?: number;
hideOverlayCursorByDefault?: boolean;
};
export type PauseSegment = {
+1
View File
@@ -437,6 +437,7 @@ contextBridge.exposeInMainWorld("electronAPI", {
videoPath: string;
webcamPath?: string | null;
timeOffsetMs?: number;
hideOverlayCursorByDefault?: boolean;
}, options?: { preserveProjectPath?: boolean }) => {
return ipcRenderer.invoke("set-current-recording-session", session, options);
},
@@ -2005,6 +2005,9 @@ export default function VideoEditor() {
pendingFreshRecordingAutoZoomPathRef.current = autoApplyFreshRecordingAutoZooms
? sourceVideoUrl
: null;
if (sessionResult.session.hideOverlayCursorByDefault) {
setShowCursor(false);
}
setWebcam((prev) => ({
...prev,
enabled: Boolean(sessionResult.session?.webcamPath),
+11 -2
View File
@@ -154,6 +154,7 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
const micFallbackRecorder = useRef<MediaRecorder | null>(null);
const micFallbackChunks = useRef<Blob[]>([]);
const micFallbackStartDelayMs = useRef<number | null>(null);
const hideEditorOverlayCursorByDefault = useRef(false);
const notifyRecordingFinalizationFailure = useCallback(async (message: string) => {
setFinalizing(false);
@@ -397,21 +398,27 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
const finalizeRecordingSession = useCallback(
async (videoPath: string, webcamPath: string | null) => {
const shouldHideOverlayCursor = hideEditorOverlayCursorByDefault.current;
try {
if (webcamPath) {
await window.electronAPI.setCurrentRecordingSession({
videoPath,
webcamPath,
timeOffsetMs: webcamTimeOffsetMs.current,
hideOverlayCursorByDefault: shouldHideOverlayCursor,
});
} else {
await window.electronAPI.setCurrentVideoPath(videoPath);
await window.electronAPI.setCurrentVideoPath(videoPath, {
hideOverlayCursorByDefault: shouldHideOverlayCursor,
});
}
} catch (error) {
console.error("Failed to persist recording session metadata:", error);
try {
await window.electronAPI.setCurrentVideoPath(videoPath);
await window.electronAPI.setCurrentVideoPath(videoPath, {
hideOverlayCursorByDefault: shouldHideOverlayCursor,
});
} catch (fallbackError) {
console.error("Failed to persist fallback video path:", fallbackError);
}
@@ -908,6 +915,7 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
try {
const platform = await window.electronAPI.getPlatform();
hideEditorOverlayCursorByDefault.current = false;
const existingSource = await window.electronAPI.getSelectedSource();
const selectedSource =
existingSource ?? (platform === "linux" ? LINUX_PORTAL_SOURCE : null);
@@ -1096,6 +1104,7 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
const wantsAudioCapture = microphoneEnabled || systemAudioEnabled;
const browserCaptureSource = await resolveBrowserCaptureSource(selectedSource);
hideEditorOverlayCursorByDefault.current = true;
if (
browserCaptureSource?.id?.startsWith("screen:fallback:") ||