fix(desktop): surface failed update installs

"Restart to Update" answered the renderer with null before the install was
attempted, so a rejected install only reached main.log and the button looked
dead. The apply-update path now keeps the IPC call open until the app quits or
autoUpdater reports the failure, rolls the quit/install flags back when the app
stays up, and the update dialog shows the real reason with a translated hint for
a rejected code signature.

Also settle the download promise on downloadUpdate() itself: an already cached
payload emits no 'update-downloaded', which left that promise pending with its
listeners attached on every retry.
This commit is contained in:
Iuliia Ivashko
2026-08-28 14:47:09 +03:00
parent 1760347dc7
commit 52d79cb368
19 changed files with 221 additions and 16 deletions
+9 -4
View File
@@ -11,6 +11,8 @@ import {
isVSCodeRuntime,
isWebRuntime,
} from '@/lib/desktop';
import { formatMessage, useI18nStore } from '@/lib/i18n/store';
import { getUpdateInstallErrorMessage } from '@/lib/updateInstallError';
import { runtimeFetch } from '@/lib/runtime-fetch';
import { getClientPlatform, isCapacitorApp } from '@/lib/platform';
@@ -314,15 +316,18 @@ export const useUpdateStore = create<UpdateStore>()((set, get) => ({
return;
}
set({ error: null });
try {
const ok = await restartToApplyUpdate();
if (!ok) {
throw new Error('Desktop restart only works on Local instance');
// No desktop bridge at all — the update was never installable here.
throw new Error(formatMessage(useI18nStore.getState().dictionary, 'updateDialog.error.restartUnavailable'));
}
} catch (error) {
set({
error: error instanceof Error ? error.message : 'Failed to restart',
});
// Keep the real installer failure; the dialog shows it and the button
// stays clickable for another attempt.
set({ error: getUpdateInstallErrorMessage(error instanceof Error ? error : new Error(String(error))) });
}
},