签名 & 公证: - build/entitlements.mac.plist, build/entitlements.mac.inherit.plist — Electron hardened runtime 所需权限(JIT、unsigned memory、disable library validation) - electron-builder.yml — 启用 hardenedRuntime、entitlements、notarize: true - scripts/after-sign.js — 环境变量 + codesign -d 双重检测,有 Developer ID 时跳过 ad-hoc;无证书时 fallback ad-hoc - .github/workflows/build.yml — 映射签名 secrets(MAC_CERT_P12_BASE64 等),验证步骤断言 Developer ID Authority + TeamIdentifier,遍历双架构 .app 原生热更新: - electron/updater.ts — 从 no-op 重写为完整 electron-updater 实现(autoDownload:false, IPC handlers, 启动 10s 延迟检查) - electron/preload.ts — 恢复 updater IPC bridge - src/components/layout/AppShell.tsx — 运行时检测 native updater,useEffect 监听 updater:status 事件,native 优先 + browser fallback 其他: - README_CN.md — 更新自动更新功能描述 - package.json — 版本号升至 0.23.0 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
71 lines
1.7 KiB
TypeScript
71 lines
1.7 KiB
TypeScript
import { autoUpdater } from 'electron-updater';
|
|
import { BrowserWindow, ipcMain } from 'electron';
|
|
|
|
let win: BrowserWindow | null = null;
|
|
|
|
function sendStatus(data: {
|
|
status: string;
|
|
info?: unknown;
|
|
progress?: unknown;
|
|
error?: string;
|
|
}) {
|
|
if (win && !win.isDestroyed()) {
|
|
win.webContents.send('updater:status', data);
|
|
}
|
|
}
|
|
|
|
export function initAutoUpdater(_win: BrowserWindow) {
|
|
win = _win;
|
|
|
|
autoUpdater.autoDownload = false;
|
|
autoUpdater.autoInstallOnAppQuit = true;
|
|
|
|
autoUpdater.on('checking-for-update', () => {
|
|
sendStatus({ status: 'checking' });
|
|
});
|
|
|
|
autoUpdater.on('update-available', (info) => {
|
|
sendStatus({ status: 'available', info });
|
|
});
|
|
|
|
autoUpdater.on('update-not-available', (info) => {
|
|
sendStatus({ status: 'not-available', info });
|
|
});
|
|
|
|
autoUpdater.on('download-progress', (progress) => {
|
|
sendStatus({ status: 'downloading', progress });
|
|
});
|
|
|
|
autoUpdater.on('update-downloaded', (info) => {
|
|
sendStatus({ status: 'downloaded', info });
|
|
});
|
|
|
|
autoUpdater.on('error', (err) => {
|
|
sendStatus({ status: 'error', error: err?.message ?? String(err) });
|
|
});
|
|
|
|
// IPC handlers
|
|
ipcMain.handle('updater:check', async () => {
|
|
return autoUpdater.checkForUpdates();
|
|
});
|
|
|
|
ipcMain.handle('updater:download', async () => {
|
|
return autoUpdater.downloadUpdate();
|
|
});
|
|
|
|
ipcMain.handle('updater:quit-and-install', () => {
|
|
autoUpdater.quitAndInstall();
|
|
});
|
|
|
|
// Delayed initial check (10 seconds after launch)
|
|
setTimeout(() => {
|
|
autoUpdater.checkForUpdates().catch((err) => {
|
|
console.log('[updater] Initial update check failed:', err?.message ?? err);
|
|
});
|
|
}, 10_000);
|
|
}
|
|
|
|
export function setUpdaterWindow(_win: BrowserWindow) {
|
|
win = _win;
|
|
}
|