perf: remove launch source polling

Push selected-source changes from Electron to the launch window instead of polling every 500ms, reducing constant renderer and IPC churn. Also restore the TimelineEditor audio path narrowing fix so the current tree stays type-safe.
This commit is contained in:
webadderall committed 2026-03-22 21:03:26 +11:00
1 parent 6aa137c23f
commit bbd514efba
5 files changed
+43 -11

No files matched your search

+1
View File
@@ -39,6 +39,7 @@ interface Window {
selectSource: (source: any) => Promise<any>;
showSourceHighlight: (source: any) => Promise<{ success: boolean }>;
getSelectedSource: () => Promise<any>;
onSelectedSourceChanged: (callback: (source: any) => void) => () => void;
startNativeScreenRecording: (
source: any,
options?: {
+9
View File
@@ -43,6 +43,14 @@ function getScreen() {
return nodeRequire('electron').screen as typeof import('electron').screen
}
function broadcastSelectedSourceChange() {
for (const window of BrowserWindow.getAllWindows()) {
if (!window.isDestroyed()) {
window.webContents.send('selected-source-changed', selectedSource)
}
}
}
type SelectedSource = {
id?: string
name: string
@@ -2575,6 +2583,7 @@ export function registerIpcHandlers(
ipcMain.handle('select-source', (_, source: SelectedSource) => {
selectedSource = source
broadcastSelectedSourceChange()
stopWindowBoundsCapture()
const sourceSelectorWin = getSourceSelectorWindow()
if (sourceSelectorWin) {
+5
View File
@@ -49,6 +49,11 @@ contextBridge.exposeInMainWorld("electronAPI", {
getSelectedSource: () => {
return ipcRenderer.invoke("get-selected-source");
},
onSelectedSourceChanged: (callback: (source: any) => void) => {
const listener = (_event: Electron.IpcRendererEvent, payload: any) => callback(payload);
ipcRenderer.on("selected-source-changed", listener);
return () => ipcRenderer.removeListener("selected-source-changed", listener);
},
startNativeScreenRecording: (
source: any,
options?: {
+25 -10
View File
@@ -297,20 +297,35 @@ export function LaunchWindow() {
};
useEffect(() => {
const checkSelectedSource = async () => {
if (!window.electronAPI) return;
const source = await window.electronAPI.getSelectedSource();
if (source) {
let mounted = true;
const applySelectedSource = (source: { name?: string } | null | undefined) => {
if (!mounted) {
return;
}
if (source?.name) {
setSelectedSource(source.name);
setHasSelectedSource(true);
} else {
setSelectedSource("Screen");
setHasSelectedSource(false);
return;
}
setSelectedSource("Screen");
setHasSelectedSource(false);
};
void window.electronAPI.getSelectedSource().then((source) => {
applySelectedSource(source);
});
const cleanup = window.electronAPI.onSelectedSourceChanged((source) => {
applySelectedSource(source);
});
return () => {
mounted = false;
cleanup?.();
};
void checkSelectedSource();
const interval = setInterval(checkSelectedSource, 500);
return () => clearInterval(interval);
}, []);
useEffect(() => {
@@ -1179,9 +1179,11 @@ export default function TimelineEditor({
return;
}
const audioPath = result.path;
// Load the audio file to get its full duration
const audioDurationMs = await new Promise<number>((resolve) => {
const audio = new Audio(toFileUrl(result.path));
const audio = new Audio(toFileUrl(audioPath));
audio.addEventListener('loadedmetadata', () => {
resolve(Math.round(audio.duration * 1000));
});