Files
zn-ai/electron/service/updater.ts
DEV_DSW 416399e7a8 feat: implement menu service for context menu management
feat: add provider API service for managing provider accounts and keys
feat: create provider runtime sync service for agent runtime management
feat: introduce script execution service for running automation scripts
feat: develop script store service for managing script metadata and storage
feat: implement theme service for managing application theme settings
feat: add updater service for handling application updates
feat: create window service for managing application windows and their states
2026-04-22 09:26:39 +08:00

85 lines
2.7 KiB
TypeScript

import { autoUpdater } from 'electron-updater';
import { BrowserWindow, ipcMain, app } from 'electron';
import { IPC_EVENTS } from '@runtime/lib/constants';
export class AppUpdater {
private mainWindow: BrowserWindow | null = null;
private static _instance: AppUpdater;
private _initialized: boolean = false;
private constructor() {
autoUpdater.autoDownload = false;
}
public init() {
if (this._initialized) return;
this._initialized = true;
this.setupListeners();
this.registerHandlers();
}
public static getInstance() {
if (!this._instance) {
this._instance = new AppUpdater();
}
return this._instance;
}
setMainWindow(window: BrowserWindow) {
this.mainWindow = window;
}
private setupListeners() {
autoUpdater.on('checking-for-update', () => this.sendToRenderer(IPC_EVENTS.UPDATE_STATUS_CHANGED, { status: 'checking' }));
autoUpdater.on('update-available', (info) => this.sendToRenderer(IPC_EVENTS.UPDATE_STATUS_CHANGED, { status: 'available', info }));
autoUpdater.on('update-not-available', () => this.sendToRenderer(IPC_EVENTS.UPDATE_STATUS_CHANGED, { status: 'not-available' }));
autoUpdater.on('download-progress', (progress) => this.sendToRenderer(IPC_EVENTS.UPDATE_STATUS_CHANGED, { status: 'downloading', progress }));
autoUpdater.on('update-downloaded', (info) => this.sendToRenderer(IPC_EVENTS.UPDATE_STATUS_CHANGED, { status: 'downloaded', info }));
autoUpdater.on('error', (error) => this.sendToRenderer(IPC_EVENTS.UPDATE_STATUS_CHANGED, { status: 'error', error: error.message }));
}
private sendToRenderer(channel: string, data: any) {
BrowserWindow.getAllWindows().forEach(win => {
if (!win.isDestroyed()) {
win.webContents.send(channel, data);
}
});
}
private registerHandlers() {
ipcMain.handle(IPC_EVENTS.UPDATE_CHECK, () => this.checkForUpdates());
ipcMain.handle(IPC_EVENTS.UPDATE_DOWNLOAD, () => {
if (app.isPackaged) {
return autoUpdater.downloadUpdate();
}
return null;
});
ipcMain.handle(IPC_EVENTS.UPDATE_INSTALL, () => {
if (app.isPackaged) {
return autoUpdater.quitAndInstall();
}
return null;
});
ipcMain.handle(IPC_EVENTS.UPDATE_VERSION, () => {
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();