diff --git a/packages/electron/main.mjs b/packages/electron/main.mjs index c45f23ad..1b3024c7 100644 --- a/packages/electron/main.mjs +++ b/packages/electron/main.mjs @@ -1355,6 +1355,17 @@ const setupAutoUpdater = () => { }, })); }); + + autoUpdater.on('update-downloaded', (info) => { + log.info(`[electron] update-downloaded version=${info?.version || 'unknown'}`); + if (state.pendingUpdate) { + state.pendingUpdate.downloaded = true; + } + }); + + autoUpdater.on('error', (err) => { + log.error('[electron] autoUpdater error', err); + }); }; const parseRelevantChangelogNotes = async (fromVersion, toVersion) => { @@ -1892,14 +1903,26 @@ const handleInvoke = async (browserWindow, command, args = {}) => { })); return null; - case 'desktop_restart': - if (state.pendingUpdate?.downloaded && app.isPackaged) { - autoUpdater.quitAndInstall(false, true); - return null; - } - app.relaunch(); - app.exit(0); + case 'desktop_restart': { + const applyUpdate = Boolean(state.pendingUpdate?.downloaded && app.isPackaged); + log.info(`[electron] desktop_restart applyUpdate=${applyUpdate} packaged=${app.isPackaged}`); + // Defer so the IPC reply flushes before the app starts shutting down. + // Without this, quitAndInstall() can race with the renderer's pending + // invoke and the restart appears to do nothing from the UI side. + setImmediate(() => { + try { + if (applyUpdate) { + autoUpdater.quitAndInstall(false, true); + } else { + app.relaunch(); + app.exit(0); + } + } catch (err) { + log.error('[electron] desktop_restart failed', err); + } + }); return null; + } case 'desktop_get_lan_address': return await detectLanIPv4Address(); diff --git a/packages/ui/src/stores/useUpdateStore.ts b/packages/ui/src/stores/useUpdateStore.ts index 8f3c167b..795efb3e 100644 --- a/packages/ui/src/stores/useUpdateStore.ts +++ b/packages/ui/src/stores/useUpdateStore.ts @@ -244,6 +244,10 @@ export const useUpdateStore = create()((set, get) => ({ ? { ...state.info, ...desktopInfo, + // Keep the richer sidecar-sourced changelog; desktopInfo.body is + // often the bare "See release notes at..." fallback from the + // updater and would otherwise clobber the nice changelog. + body: state.info.body || desktopInfo.body, available: state.info.available, } : desktopInfo,