Files
xk-admin/apps/desktop/src/main/tray.ts

110 lines
3.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { app, Menu, nativeImage, Tray } from 'electron';
import log from 'electron-log/main';
import { getAutoLaunchEnabled, setAutoLaunchEnabled } from './auto-launch';
import { promptAndClearCache } from './cache';
import { getResourcePath } from './config';
import { checkForUpdates } from './updater';
import { getMainWindow, markQuitting, showMainWindow } from './window';
/**
* 系统托盘:应用常驻入口
* - Windows 单击托盘图标恢复主窗口;mac 单击弹出菜单(跟随平台惯例)
* - 菜单:显示主窗口 / 开机自启 / 重新启动 / 切换账号 / 清除缓存 / 检查更新 / 退出
* 注意:托盘实例必须保持模块级引用,否则会被 GC 导致图标消失(Electron 经典坑)
*/
let tray: Tray | null = null;
/** 重新启动整个 Electron 进程(保留启动参数,常用于卡死/配置变更后自愈) */
function restartApp(): void {
markQuitting();
app.relaunch();
app.exit(0);
}
/** 唤起主窗口并通知渲染端打开「切换账号」弹窗(未登录时弹窗自行失败即可) */
function openSwitchAccount(): void {
showMainWindow();
getMainWindow()?.webContents.send('desktop:open-switch-account');
}
/** 构建托盘菜单:开机自启是动态勾选项,每次状态变化后需重建菜单 */
function buildTrayMenu(): Menu {
return Menu.buildFromTemplate([
{
label: '显示主窗口',
click: () => showMainWindow(),
},
{ type: 'separator' },
{
label: '开机自启',
type: 'checkbox',
checked: getAutoLaunchEnabled(),
// 开发模式登录项无意义,置灰避免误操作
enabled: app.isPackaged,
click: (menuItem) => {
setAutoLaunchEnabled(menuItem.checked);
refreshTrayMenu();
},
},
{
label: '重新启动',
click: () => restartApp(),
},
{
label: '切换账号',
click: () => openSwitchAccount(),
},
{
label: '清除缓存',
click: () => {
void promptAndClearCache();
},
},
{
label: '检查更新',
click: () => checkForUpdates(true),
},
{ type: 'separator' },
{
label: '退出',
click: () => {
// 先标记退出,放行主窗口 close 拦截,再走正常退出流程
markQuitting();
app.quit();
},
},
]);
}
/** 刷新托盘菜单(开机自启状态从渲染端 IPC 修改后也要同步勾选态) */
export function refreshTrayMenu(): void {
tray?.setContextMenu(buildTrayMenu());
}
/**
* 创建系统托盘
* 图标用打包的应用图标缩放(mac 菜单栏建议 18px、Windows 托盘 16px 的倍数由系统处理)
* TODO(待确认):正式图标到位后,mac 建议换单色 Template 图以适配深浅菜单栏
*/
export function createTray(): void {
try {
const icon = nativeImage.createFromPath(getResourcePath('icon.png'));
const trayIcon =
process.platform === 'darwin'
? icon.resize({ width: 18, height: 18 })
: icon.resize({ width: 16, height: 16 });
tray = new Tray(trayIcon);
tray.setToolTip('萧康云医');
tray.setContextMenu(buildTrayMenu());
// Windows 单击直接唤起主窗口;mac 上设置了 contextMenu 后单击默认弹菜单,不重复绑定
if (process.platform === 'win32') {
tray.on('click', () => showMainWindow());
}
} catch (error) {
// 托盘创建失败(图标缺失等)不阻塞应用启动,仅损失常驻入口
log.error('创建系统托盘失败', error);
}
}