From 09908cfcb7691b19679c318f94fc278b64e734e6 Mon Sep 17 00:00:00 2001 From: 7418 <7418@openclaw.ai> Date: Fri, 27 Feb 2026 12:11:20 +0800 Subject: [PATCH] fix: resolve macOS build race condition and update download button unresponsive MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI 修复 (electron-builder.yml): - 移除 mac target 的 arch: [arm64, x64],改由 CI matrix 的 --arch flag 控制 - 根因:两个 macOS job 各自构建两个架构的 DMG,产生两个 draft release, 导致 release job 只发布了没有 DMG 的那个,macOS 产物丢失 下载按钮无响应修复: - electron/updater.ts: downloadUpdate IPC handler 加 try-catch, 失败时通过 sendStatus 发送 error 事件给前端,避免静默失败 - AppShell.tsx: downloadUpdate 回调点击后立即设置 downloadProgress=0 提供即时 UI 反馈;加 await + catch 处理下载失败并重置状态 - AppShell.tsx: error 事件处理中重置 downloadProgress 为 null, 使下载按钮在失败后重新出现 - UpdateDialog.tsx / GeneralSection.tsx: isDownloading 判断移除 > 0 条件, downloadProgress === 0 时也显示下载中状态,消除点击后无反馈的间隙 Co-Authored-By: Claude Opus 4.6 --- electron-builder.yml | 1 - electron/updater.ts | 9 ++++++++- src/components/layout/AppShell.tsx | 14 ++++++++++++-- src/components/layout/UpdateDialog.tsx | 2 +- src/components/settings/GeneralSection.tsx | 2 +- 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/electron-builder.yml b/electron-builder.yml index 75e0a58..7cbb8db 100644 --- a/electron-builder.yml +++ b/electron-builder.yml @@ -49,7 +49,6 @@ mac: artifactName: "${productName}-${version}-${arch}.${ext}" target: - target: dmg - arch: [arm64, x64] win: icon: build/icon.ico target: diff --git a/electron/updater.ts b/electron/updater.ts index 53b9120..adf2e91 100644 --- a/electron/updater.ts +++ b/electron/updater.ts @@ -98,7 +98,14 @@ export function initAutoUpdater(win: BrowserWindow) { }); ipcMain.handle('updater:download', async () => { - return autoUpdater.downloadUpdate(); + 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', () => { diff --git a/src/components/layout/AppShell.tsx b/src/components/layout/AppShell.tsx index d30c864..221a8de 100644 --- a/src/components/layout/AppShell.tsx +++ b/src/components/layout/AppShell.tsx @@ -280,6 +280,8 @@ export function AppShell({ children }: { children: React.ReactNode }) { case 'error': setChecking(false); + // Reset download progress so the download button re-appears + setUpdateInfo((prev) => prev ? { ...prev, downloadProgress: null } : prev); console.warn('[updater] Error:', event.error); break; } @@ -300,8 +302,16 @@ export function AppShell({ children }: { children: React.ReactNode }) { setShowDialog(false); }, []); - const downloadUpdate = useCallback(() => { - window.electronAPI?.updater?.downloadUpdate(); + const downloadUpdate = useCallback(async () => { + // Immediately show downloading state so user gets feedback + setUpdateInfo((prev) => prev ? { ...prev, downloadProgress: 0 } : prev); + try { + await window.electronAPI?.updater?.downloadUpdate(); + } catch (err) { + console.warn('[updater] Download failed:', err); + // Reset progress so the download button re-appears + setUpdateInfo((prev) => prev ? { ...prev, downloadProgress: null } : prev); + } }, []); const quitAndInstall = useCallback(() => { diff --git a/src/components/layout/UpdateDialog.tsx b/src/components/layout/UpdateDialog.tsx index 03f5703..b060578 100644 --- a/src/components/layout/UpdateDialog.tsx +++ b/src/components/layout/UpdateDialog.tsx @@ -20,7 +20,7 @@ export function UpdateDialog() { if (!updateInfo?.updateAvailable) return null; const { isNativeUpdate, readyToInstall, downloadProgress } = updateInfo; - const isDownloading = isNativeUpdate && !readyToInstall && downloadProgress != null && downloadProgress > 0; + const isDownloading = isNativeUpdate && !readyToInstall && downloadProgress != null; return ( { diff --git a/src/components/settings/GeneralSection.tsx b/src/components/settings/GeneralSection.tsx index de51573..c6c5c25 100644 --- a/src/components/settings/GeneralSection.tsx +++ b/src/components/settings/GeneralSection.tsx @@ -26,7 +26,7 @@ function UpdateCard() { const currentVersion = process.env.NEXT_PUBLIC_APP_VERSION || "0.0.0"; const isDownloading = updateInfo?.isNativeUpdate && !updateInfo.readyToInstall - && updateInfo.downloadProgress != null && updateInfo.downloadProgress > 0; + && updateInfo.downloadProgress != null; return (