fix: close and recreate macOS windows safely

This commit is contained in:
鲨鱼辣椒 committed 2026-09-29 19:50:25 +08:00
1 parent f443f3bc66
commit b5e6c663ef
19 files changed
+1079 -172

No files matched your search

+27 -23
View File
@@ -2,10 +2,19 @@
* System Tray Management
* Creates and manages the system tray icon and menu
*/
import { Tray, Menu, BrowserWindow, app, nativeImage } from 'electron';
import { Tray, Menu, app, nativeImage } from 'electron';
import { join } from 'path';
import {
resolveMainWindow,
sendWhenWindowReady,
showMainWindow,
type EnsureMainWindow,
type MainWindowProvider,
} from './window-provider';
let tray: Tray | null = null;
let windowProvider: MainWindowProvider = () => null;
let ensureWindow: EnsureMainWindow | undefined;
/**
* Resolve the icons directory path (works in both dev and packaged mode)
@@ -20,7 +29,10 @@ function getIconsDir(): string {
/**
* Create system tray icon and menu
*/
export function createTray(mainWindow: BrowserWindow): Tray {
export function createTray(mainWindow: MainWindowProvider, ensureMainWindow?: EnsureMainWindow): Tray {
windowProvider = mainWindow;
ensureWindow = ensureMainWindow;
if (tray && !tray.isDestroyed()) return tray;
// Use platform-appropriate icon for system tray
const iconsDir = getIconsDir();
let iconPath: string;
@@ -60,9 +72,9 @@ export function createTray(mainWindow: BrowserWindow): Tray {
tray.setToolTip('Makelore - AI Assistant');
const showWindow = () => {
if (mainWindow.isDestroyed()) return;
mainWindow.show();
mainWindow.focus();
const window = resolveMainWindow(windowProvider) ?? ensureWindow?.() ?? null;
showMainWindow(window);
return window;
};
// Create context menu
@@ -93,17 +105,13 @@ export function createTray(mainWindow: BrowserWindow): Tray {
{
label: 'Open Chat',
click: () => {
if (mainWindow.isDestroyed()) return;
mainWindow.show();
mainWindow.webContents.send('navigate', '/');
sendWhenWindowReady(showWindow(), 'navigate', '/');
},
},
{
label: 'Open Settings',
click: () => {
if (mainWindow.isDestroyed()) return;
mainWindow.show();
mainWindow.webContents.send('navigate', '/settings');
sendWhenWindowReady(showWindow(), 'navigate', '/settings');
},
},
],
@@ -114,8 +122,7 @@ export function createTray(mainWindow: BrowserWindow): Tray {
{
label: 'Check for Updates...',
click: () => {
if (mainWindow.isDestroyed()) return;
mainWindow.webContents.send('update:check');
sendWhenWindowReady(showWindow(), 'update:check');
},
},
{
@@ -133,21 +140,16 @@ export function createTray(mainWindow: BrowserWindow): Tray {
// Click to show window (Windows/Linux)
tray.on('click', () => {
if (mainWindow.isDestroyed()) return;
if (mainWindow.isVisible()) {
mainWindow.hide();
const window = resolveMainWindow(windowProvider);
if (window?.isVisible()) {
window.hide();
} else {
mainWindow.show();
mainWindow.focus();
showWindow();
}
});
// Double-click to show window (Windows)
tray.on('double-click', () => {
if (mainWindow.isDestroyed()) return;
mainWindow.show();
mainWindow.focus();
});
tray.on('double-click', showWindow);
return tray;
}
@@ -168,5 +170,7 @@ export function destroyTray(): void {
if (tray) {
tray.destroy();
tray = null;
windowProvider = () => null;
ensureWindow = undefined;
}
}