/** * 系统托盘:应用常驻入口 * Windows:关闭窗口后靠托盘活着,单击托盘还原窗口 * mac:托盘(菜单栏图标)仅提供快捷菜单,窗口恢复主要靠 Dock 的 activate 事件 */ import { app, Menu, nativeImage, Tray } from 'electron'; import { PRODUCT_NAME } from './config'; import { appState } from './state'; import { checkUpdateManually } from './updater'; import { getAutoLaunchEnabled, getResourcePath, setAutoLaunchEnabled } from './utils'; import { showMainWindow } from './window'; /** 托盘单例(必须持有引用,否则会被 GC 导致图标消失) */ let tray: null | Tray = null; /** * 创建托盘图标与菜单 * 托盘直接用品牌应用图标缩小(resources/icon.png,年糕猫+奶酪) */ export function createTray(): Tray { // TODO(待确认):mac 后续可换 Template 单色托盘图(setTemplateImage 随菜单栏深浅色自动反色) const icon = nativeImage .createFromPath(getResourcePath('icon.png')) .resize({ height: 16, width: 16 }); tray = new Tray(icon); tray.setToolTip(PRODUCT_NAME); refreshTrayMenu(); // Windows 惯例:单击托盘直接还原主窗口;mac 惯例是单击弹菜单,不抢行为 if (process.platform !== 'darwin') { tray.on('click', () => showMainWindow()); } return tray; } /** * 重建托盘右键菜单 * 单独导出是因为「开机自启」勾选状态可能被渲染层(desktopAPI.setAutoLaunch)改掉, * 改完需要同步刷新菜单勾选态 */ export function refreshTrayMenu(): void { if (!tray) return; const menu = Menu.buildFromTemplate([ { click: () => showMainWindow(), label: '显示主窗口' }, { type: 'separator' }, { checked: getAutoLaunchEnabled(), click: (item) => { setAutoLaunchEnabled(item.checked); }, label: '开机自启', type: 'checkbox', }, { click: () => checkUpdateManually(), label: '检查更新' }, { type: 'separator' }, { click: () => { // 标记真正退出,绕过窗口 close 事件里的「隐藏到托盘」拦截 appState.quitting = true; app.quit(); }, label: '退出', }, ]); tray.setContextMenu(menu); }