From 8cbccaba9eee3e10763e66587e7d182a79c68cf3 Mon Sep 17 00:00:00 2001 From: nekketsuuu Date: Wed, 9 Sep 2026 23:36:36 +0900 Subject: [PATCH] fix: Register IPC handlers only once to avoid blank window createWindow() re-registered ipcMain.handle("getConfig") on every call, so the second call threw "Attempted to register a second handler" and skipped win.loadURL(), leaving a blank window. Register the handlers once per process and resolve the target window from the sender. --- src/main/window.ts | 67 ++++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/src/main/window.ts b/src/main/window.ts index ca324db..2e51dd0 100644 --- a/src/main/window.ts +++ b/src/main/window.ts @@ -25,23 +25,6 @@ const sendNativeThemeUpdate = (): void => { }); }; -let nativeThemeHandlersRegistered = false; - -const registerNativeThemeHandlers = (): void => { - if (nativeThemeHandlersRegistered) return; - - ipcMain.handle("getNativeTheme", () => getNativeThemeState()); - - ipcMain.handle("setThemeSource", (_event, themeSource: ThemeSettingType) => { - nativeTheme.themeSource = themeSource; - sendNativeThemeUpdate(); - return getNativeThemeState(); - }); - - nativeTheme.on("updated", sendNativeThemeUpdate); - nativeThemeHandlersRegistered = true; -}; - const shouldNotify = (setting: SettingType, isFocused: boolean) => { return ( setting.notification.enabled && @@ -51,26 +34,29 @@ const shouldNotify = (setting: SettingType, isFocused: boolean) => { ); }; -export async function createWindow(): Promise { - registerNativeThemeHandlers(); +let ipcHandlersRegistered = false; - const win = new electron.BrowserWindow({ - width: 1280, - height: 780, - title: "Bdash", - icon: path.join(__dirname, "..", "icon.png"), - webPreferences: { - nodeIntegration: true, - contextIsolation: false, - }, +const registerIpcHandlers = (): void => { + if (ipcHandlersRegistered) return; + ipcHandlersRegistered = true; + + ipcMain.handle("getNativeTheme", () => getNativeThemeState()); + + ipcMain.handle("setThemeSource", (_event, themeSource: ThemeSettingType) => { + nativeTheme.themeSource = themeSource; + sendNativeThemeUpdate(); + return getNativeThemeState(); }); + nativeTheme.on("updated", sendNativeThemeUpdate); + ipcMain.handle("getConfig", async () => Config); - ipcMain.on("queryCompleted", (_event, data) => { + ipcMain.on("queryCompleted", (event, data) => { const { success, title, runtime, rowCount, errorMessage, _setting } = data; + const win = BrowserWindow.fromWebContents(event.sender); - if (shouldNotify(_setting, win.isFocused())) { + if (shouldNotify(_setting, win?.isFocused() ?? false)) { const notificationTitle = success ? "✅️ Query completed" : "❌️ Query failed"; let notificationBody; @@ -93,13 +79,15 @@ export async function createWindow(): Promise { }); ipcMain.on("showUpdateQueryDialog", async (event) => { - const { response } = await dialog.showMessageBox(win, { + const win = BrowserWindow.fromWebContents(event.sender); + const options: electron.MessageBoxOptions = { message: "This query has been already shared.", type: "question", buttons: ["Cancel", "Share as a new query", "Update an existing query"], defaultId: 2, cancelId: 0, - }); + }; + const { response } = win ? await dialog.showMessageBox(win, options) : await dialog.showMessageBox(options); switch (response) { case 0: event.returnValue = "cancel"; @@ -112,6 +100,21 @@ export async function createWindow(): Promise { break; } }); +}; + +export async function createWindow(): Promise { + registerIpcHandlers(); + + const win = new electron.BrowserWindow({ + width: 1280, + height: 780, + title: "Bdash", + icon: path.join(__dirname, "..", "icon.png"), + webPreferences: { + nodeIntegration: true, + contextIsolation: false, + }, + }); await win.loadURL(`file://${__dirname}/../index.html`); win.once("closed", () => {