feat: implement tray functionality with status updates and localization support

This commit is contained in:
duanshuwen
2026-04-22 07:19:53 +08:00
parent 197f644d53
commit be8298af2f
6 changed files with 341 additions and 120 deletions

View File

@@ -1,100 +0,0 @@
import { Tray, Menu, ipcMain, app } from 'electron'
import { createTranslator, createLogo } from '@electron/utils'
import { CONFIG_KEYS, IPC_EVENTS, WINDOW_NAMES, MAIN_WIN_SIZE } from '@runtime/lib/constants'
import logManager from '@electron/service/logger'
// TODO: shortcutManager
import windowManager from '@electron/service/window-service'
import configManager from '@electron/service/config-service'
let t: ReturnType<typeof createTranslator> = createTranslator();
class TrayService {
private static _instance: TrayService;
private _tray: Tray | null = null;
private _removeLanguageListener?: () => void;
private _setupLanguageChangeListener() {
this._removeLanguageListener = configManager.onConfigChange((config) => {
if (!config[CONFIG_KEYS.LANGUAGE]) return;
// 切换语言后,重新创建翻译器
t = createTranslator();
if (this._tray) {
this._updateTray();
}
})
}
private _updateTray() {
if (!this._tray) {
this._tray = new Tray(createLogo());
}
const showWindow = () => {
const mainWindow = windowManager.get(WINDOW_NAMES.MAIN);
if (mainWindow && !mainWindow?.isDestroyed() && mainWindow?.isVisible() && !mainWindow?.isFocused()) {
return mainWindow.focus();
}
if (mainWindow?.isMinimized()) {
return mainWindow?.restore();
}
if (mainWindow?.isVisible() && mainWindow?.isFocused()) return;
windowManager.create(WINDOW_NAMES.MAIN, MAIN_WIN_SIZE);
}
this._tray.setToolTip(t('tray.tooltip') ?? 'Diona Application');
// TODO: 依赖快捷键Service
this._tray.setContextMenu(Menu.buildFromTemplate([
{ label: t('tray.showWindow'), accelerator: 'CmdOrCtrl+N', click: showWindow },
{ type: 'separator' },
{ label: t('settings.title'), click: () => ipcMain.emit(`${IPC_EVENTS.OPEN_WINDOW}:${WINDOW_NAMES.SETTING}`) },
{ role: 'quit', label: t('tray.exit') }
]));
this._tray.removeAllListeners('click');
this._tray.on('click', showWindow);
}
private constructor() {
this._setupLanguageChangeListener();
logManager.info('TrayService initialized successfully.');
}
public static getInstance() {
if (!this._instance) {
this._instance = new TrayService();
}
return this._instance;
}
public create() {
if (this._tray) return;
this._updateTray();
app.on('quit', () => {
this.destroy();
//TODO: 移除快捷键
})
}
public destroy() {
this._tray?.destroy();
this._tray = null;
//TODO: 移除快捷键
if (this._removeLanguageListener) {
this._removeLanguageListener();
this._removeLanguageListener = void 0;
}
}
}
export const trayManager = TrayService.getInstance();
export default trayManager;

View File

@@ -47,18 +47,7 @@ export class AppUpdater {
}
private registerHandlers() {
ipcMain.handle(IPC_EVENTS.UPDATE_CHECK, () => {
if (app.isPackaged) {
return autoUpdater.checkForUpdates();
} else {
// 在开发环境下模拟
this.sendToRenderer(IPC_EVENTS.UPDATE_STATUS_CHANGED, { status: 'checking' });
setTimeout(() => {
this.sendToRenderer(IPC_EVENTS.UPDATE_STATUS_CHANGED, { status: 'not-available' });
}, 1500);
return null;
}
});
ipcMain.handle(IPC_EVENTS.UPDATE_CHECK, () => this.checkForUpdates());
ipcMain.handle(IPC_EVENTS.UPDATE_DOWNLOAD, () => {
if (app.isPackaged) {
@@ -78,6 +67,18 @@ export class AppUpdater {
return app.getVersion();
});
}
public checkForUpdates() {
if (app.isPackaged) {
return autoUpdater.checkForUpdates();
}
this.sendToRenderer(IPC_EVENTS.UPDATE_STATUS_CHANGED, { status: 'checking' });
setTimeout(() => {
this.sendToRenderer(IPC_EVENTS.UPDATE_STATUS_CHANGED, { status: 'not-available' });
}, 1500);
return null;
}
}
export const appUpdater = AppUpdater.getInstance();