fix(recording): keep live webcam preview visible

This commit is contained in:
wiiiii123
2026-07-11 02:02:24 +07:00
parent 641d2230a4
commit f8ccb5cbcc
6 changed files with 85 additions and 2 deletions
+1
View File
@@ -209,6 +209,7 @@ interface Window {
hudOverlayHide: () => void;
hudOverlayClose: () => void;
hudOverlayRendererReady: () => void;
hudOverlaySetWebcamPreviewVisible: (visible: boolean) => void;
getHudOverlayCaptureProtection: () => Promise<{ success: boolean; enabled: boolean }>;
getHudOverlayMousePassthroughSupported: () => Promise<{
success: boolean;
+33
View File
@@ -3,6 +3,7 @@ import { describe, expect, it } from "vitest";
import {
getHudOverlayWindowBounds,
resizeHudOverlayFallbackBounds,
shouldExpandHudOverlayFallback,
} from "./hudOverlayBounds";
describe("getHudOverlayWindowBounds", () => {
@@ -143,3 +144,35 @@ describe("resizeHudOverlayFallbackBounds", () => {
});
});
});
describe("shouldExpandHudOverlayFallback", () => {
it("expands while recording only when the floating webcam preview is visible", () => {
expect(
shouldExpandHudOverlayFallback({
fallbackExpanded: false,
recordingActive: true,
webcamPreviewVisible: true,
}),
).toBe(true);
});
it("keeps the compact recording fallback when there is no webcam preview", () => {
expect(
shouldExpandHudOverlayFallback({
fallbackExpanded: false,
recordingActive: true,
webcamPreviewVisible: false,
}),
).toBe(false);
});
it("preserves manual fallback expansion outside recording", () => {
expect(
shouldExpandHudOverlayFallback({
fallbackExpanded: true,
recordingActive: false,
webcamPreviewVisible: false,
}),
).toBe(true);
});
});
+13
View File
@@ -37,6 +37,19 @@ export function getHudOverlayWindowBounds(
height,
};
}
export function shouldExpandHudOverlayFallback({
fallbackExpanded,
recordingActive,
webcamPreviewVisible,
}: {
fallbackExpanded: boolean;
recordingActive: boolean;
webcamPreviewVisible: boolean;
}): boolean {
return fallbackExpanded || (recordingActive && webcamPreviewVisible);
}
export function resizeHudOverlayFallbackBounds(
workArea: HudOverlayWorkArea,
currentBounds: HudOverlayWorkArea,
+3
View File
@@ -182,6 +182,9 @@ contextBridge.exposeInMainWorld("electronAPI", {
hudOverlayRendererReady: () => {
ipcRenderer.send("hud-overlay-renderer-ready");
},
hudOverlaySetWebcamPreviewVisible: (visible: boolean) => {
ipcRenderer.send("hud-overlay-set-webcam-preview-visible", visible);
},
getHudOverlayCaptureProtection: () => {
return ipcRenderer.invoke("get-hud-overlay-capture-protection");
},
+25 -2
View File
@@ -5,7 +5,11 @@ import path from "node:path";
import { fileURLToPath } from "node:url";
import { app, BrowserWindow, ipcMain } from "electron";
import { USER_DATA_PATH } from "./appPaths";
import { getHudOverlayWindowBounds, resizeHudOverlayFallbackBounds } from "./hudOverlayBounds";
import {
getHudOverlayWindowBounds,
resizeHudOverlayFallbackBounds,
shouldExpandHudOverlayFallback,
} from "./hudOverlayBounds";
import { getPackagedRendererBaseUrl } from "./rendererServer";
const electronWindowsDir = path.dirname(fileURLToPath(import.meta.url));
@@ -30,6 +34,7 @@ let hudOverlayIgnoringMouse = true;
let hudOverlaySourceSelectionActive = false;
let hudOverlayMouseReassertTimer: NodeJS.Timeout | null = null;
let hudOverlayRecordingActive = false;
let hudOverlayWebcamPreviewVisible = false;
let countdownWindow: BrowserWindow | null = null;
let updateToastWindow: BrowserWindow | null = null;
@@ -190,10 +195,15 @@ function getHudOverlayDisplay() {
function getHudOverlayBounds() {
const { workArea } = getHudOverlayDisplay();
const fallbackExpanded = shouldExpandHudOverlayFallback({
fallbackExpanded: hudOverlayFallbackExpanded,
recordingActive: hudOverlayRecordingActive,
webcamPreviewVisible: hudOverlayWebcamPreviewVisible,
});
return getHudOverlayWindowBounds(
workArea,
isHudOverlayMousePassthroughSupported() && !hudOverlayRecordingActive,
hudOverlayFallbackExpanded,
fallbackExpanded,
);
}
@@ -410,6 +420,18 @@ ipcMain.handle("get-hud-overlay-mouse-passthrough-supported", () => {
};
});
ipcMain.on("hud-overlay-set-webcam-preview-visible", (_event, visible: boolean) => {
const nextVisible = Boolean(visible);
if (hudOverlayWebcamPreviewVisible === nextVisible) {
return;
}
hudOverlayWebcamPreviewVisible = nextVisible;
if (hudOverlayRecordingActive) {
applyHudOverlayBounds();
}
});
ipcMain.handle("set-hud-overlay-capture-protection", (_event, enabled: boolean) => {
loadHudOverlayCaptureProtectionSetting();
hudOverlayHiddenFromCapture = Boolean(enabled);
@@ -432,6 +454,7 @@ ipcMain.handle("set-hud-overlay-capture-protection", (_event, enabled: boolean)
export function createHudOverlayWindow(): BrowserWindow {
loadHudOverlayCaptureProtectionSetting();
hudOverlayFallbackExpanded = false;
hudOverlayWebcamPreviewVisible = false;
const initialBounds = getHudOverlayBounds();
let hasShownHudWindow = false;
+10
View File
@@ -152,6 +152,16 @@ function LaunchWindowContent() {
hudOverlayMousePassthroughSupported,
});
useEffect(() => {
window.electronAPI?.hudOverlaySetWebcamPreviewVisible?.(showRecordingWebcamPreview);
}, [showRecordingWebcamPreview]);
useEffect(() => {
return () => {
window.electronAPI?.hudOverlaySetWebcamPreviewVisible?.(false);
};
}, []);
const {
recordingHudOffset,
isHudDragging,