From 6990793e695338f1c959c98033ae313e28008586 Mon Sep 17 00:00:00 2001 From: Haze <709547807@qq.com> Date: Wed, 25 Feb 2026 20:10:09 +0800 Subject: [PATCH] Fix/chore fix on macos (#169) --- electron/main/index.ts | 14 ++++++++++++-- electron/main/updater.ts | 19 ++++++++++++++++++- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/electron/main/index.ts b/electron/main/index.ts index 198f58c1e..bc55a0e0c 100644 --- a/electron/main/index.ts +++ b/electron/main/index.ts @@ -205,6 +205,10 @@ app.whenReady().then(() => { app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) { mainWindow = createWindow(); + } else if (mainWindow && !mainWindow.isDestroyed()) { + // On macOS, clicking the dock icon should show the window if it's hidden + mainWindow.show(); + mainWindow.focus(); } }); }); @@ -215,9 +219,15 @@ app.on('window-all-closed', () => { } }); -app.on('before-quit', async () => { +app.on('before-quit', () => { isQuitting = true; - await gatewayManager.stop(); + // Fire-and-forget: do not await gatewayManager.stop() here. + // Awaiting inside a before-quit handler can stall Electron's + // replyToApplicationShouldTerminate: call when the quit is initiated + // by Squirrel.Mac (quitAndInstall), preventing the app from ever exiting. + void gatewayManager.stop().catch((err) => { + logger.warn('gatewayManager.stop() error during quit:', err); + }); }); // Export for testing diff --git a/electron/main/updater.ts b/electron/main/updater.ts index 62584c27f..da2fe1154 100644 --- a/electron/main/updater.ts +++ b/electron/main/updater.ts @@ -8,6 +8,7 @@ */ import { autoUpdater, UpdateInfo, ProgressInfo, UpdateDownloadedEvent } from 'electron-updater'; import { BrowserWindow, app, ipcMain } from 'electron'; +import { logger } from '../utils/logger'; import { EventEmitter } from 'events'; /** Base CDN URL (without trailing channel path) */ @@ -53,7 +54,11 @@ export class AppUpdater extends EventEmitter { // Configure auto-updater autoUpdater.autoDownload = false; - autoUpdater.autoInstallOnAppQuit = true; + // Set to false so quitAndInstall() always goes through the explicit + // nativeUpdater.checkForUpdates() → nativeUpdater.quitAndInstall() path, + // avoiding a race condition where squirrelDownloadedUpdate is false at + // click time and the else-branch silently does nothing. + autoUpdater.autoInstallOnAppQuit = false; // Use logger autoUpdater.logger = { @@ -206,7 +211,19 @@ export class AppUpdater extends EventEmitter { * Install update and restart app */ quitAndInstall(): void { + logger.info('[Updater] quitAndInstall called – invoking autoUpdater.quitAndInstall()'); autoUpdater.quitAndInstall(); + + // Safety fallback: if Squirrel.Mac's relaunchToInstallUpdate doesn't trigger + // app.quit() within 5 seconds (race condition or staging delay), force-quit + // so ShipIt can proceed with the installation. The update will be installed + // but the app won't auto-relaunch; the user will need to open it manually. + const safetyTimer = setTimeout(() => { + logger.warn('[Updater] quitAndInstall safety timer fired – forcing app.quit()'); + app.quit(); + }, 5000); + // Clear the timer if the normal before-quit path fires first + app.once('before-quit', () => clearTimeout(safetyTimer)); } /**