chore: 禁用 native auto-updater,改为引导用户从 GitHub 下载

macOS 上 ad-hoc 签名无法通过 ShipIt 的 kSecCSStrictValidate 校验,
导致热更新始终失败。在获取 Apple 开发者证书之前,暂时禁用 native
auto-updater,改为 browser-mode 检查 GitHub Releases API:

- electron/updater.ts: 注释掉 electron-updater 逻辑,initAutoUpdater
  和 setUpdaterWindow 改为 no-op
- electron/preload.ts: 注释掉 updater IPC bridge,前端不再暴露
  window.electronAPI.updater
- AppShell.tsx: isNativeUpdater 硬编码为 false,移除 native IPC 订阅
  和 native check/download/quitAndInstall 逻辑;保留 browser-mode
  的 GitHub API 检查(mount 时 + 每 8 小时),发现新版本时弹窗引导
  用户跳转 GitHub Release 页面下载

设置页 UpdateCard 保持不变:「检查更新」按钮通过 /api/app/updates
查询 GitHub,有新版本时显示「查看发布」按钮跳转下载。

TODO: 获取 Apple 开发者证书后,取消注释恢复 native auto-updater。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
7418andClaude Opus 4.6 committed 2026-02-28 11:45:36 +08:00
1 parent 819f9f401a
commit ad34fe387b
3 files changed
+45 -248

No files matched your search

+13 -10
View File
@@ -25,14 +25,17 @@ contextBridge.exposeInMainWorld('electronAPI', {
return () => { ipcRenderer.removeListener('install:progress', listener); };
},
},
updater: {
checkForUpdates: () => ipcRenderer.invoke('updater:check'),
downloadUpdate: () => ipcRenderer.invoke('updater:download'),
quitAndInstall: () => ipcRenderer.invoke('updater:quit-and-install'),
onStatus: (callback: (data: unknown) => void) => {
const listener = (_event: unknown, data: unknown) => callback(data);
ipcRenderer.on('updater:status', listener);
return () => { ipcRenderer.removeListener('updater:status', listener); };
},
},
// Native auto-updater bridge — disabled (code signature issues on macOS).
// Users are directed to download from GitHub Releases.
// TODO: Re-enable after obtaining Apple Developer certificate.
// updater: {
// checkForUpdates: () => ipcRenderer.invoke('updater:check'),
// downloadUpdate: () => ipcRenderer.invoke('updater:download'),
// quitAndInstall: () => ipcRenderer.invoke('updater:quit-and-install'),
// onStatus: (callback: (data: unknown) => void) => {
// const listener = (_event: unknown, data: unknown) => callback(data);
// ipcRenderer.on('updater:status', listener);
// return () => { ipcRenderer.removeListener('updater:status', listener); };
// },
// },
});
+20 -127
View File
@@ -1,132 +1,25 @@
import { autoUpdater } from 'electron-updater';
// =============================================================================
// Native auto-updater (electron-updater) — DISABLED
//
// Temporarily disabled due to macOS code signature validation failures with
// ad-hoc signing. Users are directed to download from GitHub Releases instead.
// The browser-mode update check (via /api/app/updates) remains active in the
// frontend to notify users of new versions.
//
// TODO: Re-enable after obtaining an Apple Developer certificate for proper
// code signing, then uncomment this file and the calls in main.ts / preload.ts.
// =============================================================================
// import { autoUpdater } from 'electron-updater';
import type { BrowserWindow } from 'electron';
import { ipcMain, session } from 'electron';
// import { ipcMain, session } from 'electron';
let mainWindow: BrowserWindow | null = null;
function sendStatus(data: Record<string, unknown>) {
mainWindow?.webContents.send('updater:status', data);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export function initAutoUpdater(_win: BrowserWindow) {
console.log('[updater] Native auto-updater is disabled. Users should download updates from GitHub Releases.');
}
/**
* Resolve system proxy for GitHub and inject into electron-updater
* so that VPN / proxy tools are respected during update downloads.
*/
async function configureProxy() {
try {
const proxy = await session.defaultSession.resolveProxy('https://github.com');
// proxy returns "DIRECT" or "PROXY host:port" / "SOCKS5 host:port" etc.
if (proxy && proxy !== 'DIRECT') {
const match = proxy.match(/^(?:PROXY|HTTPS)\s+(.+)/i);
if (match) {
process.env.HTTPS_PROXY = `http://${match[1]}`;
console.log('[updater] Using system proxy:', process.env.HTTPS_PROXY);
}
const socksMatch = proxy.match(/^SOCKS5?\s+(.+)/i);
if (socksMatch) {
process.env.HTTPS_PROXY = `socks5://${socksMatch[1]}`;
console.log('[updater] Using system SOCKS proxy:', process.env.HTTPS_PROXY);
}
}
} catch (err) {
console.warn('[updater] Failed to resolve proxy:', err);
}
}
export function initAutoUpdater(win: BrowserWindow) {
mainWindow = win;
// Configuration — don't auto-download, let user trigger manually
autoUpdater.autoDownload = false;
autoUpdater.autoInstallOnAppQuit = true;
// Resolve and apply system proxy for update downloads
configureProxy();
// --- Events ---
autoUpdater.on('checking-for-update', () => {
sendStatus({ status: 'checking' });
});
autoUpdater.on('update-available', (info) => {
sendStatus({
status: 'available',
info: {
version: info.version,
releaseNotes: info.releaseNotes,
releaseName: info.releaseName,
releaseDate: info.releaseDate,
},
});
});
autoUpdater.on('update-not-available', () => {
sendStatus({ status: 'not-available' });
});
autoUpdater.on('download-progress', (progress) => {
sendStatus({
status: 'downloading',
progress: {
percent: progress.percent,
bytesPerSecond: progress.bytesPerSecond,
transferred: progress.transferred,
total: progress.total,
},
});
});
autoUpdater.on('update-downloaded', (info) => {
sendStatus({
status: 'downloaded',
info: {
version: info.version,
releaseNotes: info.releaseNotes,
releaseName: info.releaseName,
releaseDate: info.releaseDate,
},
});
});
autoUpdater.on('error', (err) => {
sendStatus({ status: 'error', error: err.message });
});
// --- IPC handlers ---
ipcMain.handle('updater:check', async () => {
return autoUpdater.checkForUpdates();
});
ipcMain.handle('updater:download', async () => {
try {
return await autoUpdater.downloadUpdate();
} catch (err) {
const message = err instanceof Error ? err.message : String(err);
console.error('[updater] Download failed:', message);
sendStatus({ status: 'error', error: message });
throw err;
}
});
ipcMain.handle('updater:quit-and-install', () => {
autoUpdater.quitAndInstall();
});
// Initial check after 10 seconds
setTimeout(() => {
autoUpdater.checkForUpdates().catch((err) => {
console.warn('[updater] Initial check failed:', err.message);
});
}, 10_000);
// Periodic check every 4 hours
setInterval(() => {
autoUpdater.checkForUpdates().catch((err) => {
console.warn('[updater] Periodic check failed:', err.message);
});
}, 4 * 60 * 60 * 1000);
}
export function setUpdaterWindow(win: BrowserWindow) {
mainWindow = win;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export function setUpdaterWindow(_win: BrowserWindow) {
// no-op while native updater is disabled
}