From 71f734197456a0b9df13296e4106feb1caa09d8c Mon Sep 17 00:00:00 2001 From: boksbc Date: Mon, 11 May 2026 22:01:28 +0200 Subject: [PATCH] fix: prevent IPC listener leak in preload, fix hud-show race on cold start Co-Authored-By: Claude Sonnet 4.6 --- electron/hud.js | 24 ++++++++++++++++++++++-- electron/preload.js | 25 ++++++++++++++++++++----- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/electron/hud.js b/electron/hud.js index 74b04d1..4c5f234 100644 --- a/electron/hud.js +++ b/electron/hud.js @@ -3,6 +3,8 @@ const path = require('path'); const HUD_URL = process.env.FOX_HUD_URL || 'https://fox.pxo.at/hud'; let hudWindow = null; +let hudLoaded = false; +let pendingShow = false; function createHud() { const { width, height } = screen.getPrimaryDisplay().workAreaSize; @@ -29,8 +31,22 @@ function createHud() { hudWindow.setAlwaysOnTop(true, 'screen-saver'); hudWindow.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true }); + + hudWindow.webContents.once('did-finish-load', () => { + hudLoaded = true; + if (pendingShow) { + pendingShow = false; + hudWindow.webContents.send('hud-show'); + } + }); + hudWindow.loadURL(HUD_URL); - hudWindow.on('closed', () => { hudWindow = null; }); + + hudWindow.on('closed', () => { + hudWindow = null; + hudLoaded = false; + pendingShow = false; + }); return hudWindow; } @@ -39,7 +55,11 @@ function showHud() { if (!hudWindow) createHud(); hudWindow.show(); hudWindow.focus(); - hudWindow.webContents.send('hud-show'); + if (hudLoaded) { + hudWindow.webContents.send('hud-show'); + } else { + pendingShow = true; + } } function hideHud() { diff --git a/electron/preload.js b/electron/preload.js index b113a5b..7ebe65d 100644 --- a/electron/preload.js +++ b/electron/preload.js @@ -4,9 +4,24 @@ contextBridge.exposeInMainWorld('foxBridge', { sendMessage: (text) => ipcRenderer.send('send-message', text), hideHud: () => ipcRenderer.send('hide-hud'), macCommand: (cmd) => ipcRenderer.invoke('mac-command', cmd), - onFoxAction: (cb) => ipcRenderer.on('fox-action', (_, data) => cb(data)), - onHudShow: (cb) => ipcRenderer.on('hud-show', () => cb()), - onHudHide: (cb) => ipcRenderer.on('hud-hide', () => cb()), - onStartListening: (cb) => ipcRenderer.on('start-listening', () => cb()), - onPlayAudio: (cb) => ipcRenderer.on('play-audio', (_, url) => cb(url)), + onFoxAction: (cb) => { + ipcRenderer.removeAllListeners('fox-action'); + ipcRenderer.on('fox-action', (_, data) => cb(data)); + }, + onHudShow: (cb) => { + ipcRenderer.removeAllListeners('hud-show'); + ipcRenderer.on('hud-show', () => cb()); + }, + onHudHide: (cb) => { + ipcRenderer.removeAllListeners('hud-hide'); + ipcRenderer.on('hud-hide', () => cb()); + }, + onStartListening: (cb) => { + ipcRenderer.removeAllListeners('start-listening'); + ipcRenderer.on('start-listening', () => cb()); + }, + onPlayAudio: (cb) => { + ipcRenderer.removeAllListeners('play-audio'); + ipcRenderer.on('play-audio', (_, url) => cb(url)); + }, });