Show found desktop updates after manual checks (#1815)

* fix(desktop): report found app updates during manual checks

Manual checks could reuse cached update state while the renderer discarded pending update details. Keep found update versions visible while downloads prepare, and reserve install affordances for ready updates.

* test(desktop): cover manual update retry after errors

* fix(desktop): keep ready updates ready on recheck
This commit is contained in:
Mohamed Boudra
2026-06-30 08:12:15 +02:00
committed by GitHub
parent 5fc53c576e
commit 7c6152663e
16 changed files with 209 additions and 16 deletions
@@ -114,15 +114,17 @@ describe("desktop app updater — check", () => {
});
});
it("reports 'pending' when the check resolves with an update that is not yet downloaded", async () => {
it("reports the found update while it is still preparing", async () => {
const { updater, port } = createUpdater();
port.nextCheckResult(buildFakeCheckResult({ hasUpdate: true, readyToInstall: false }));
port.nextCheckResult(
buildFakeCheckResult({ hasUpdate: true, readyToInstall: false, latestVersion: "1.2.3" }),
);
await updater.checkForUpdates({ releaseChannel: "stable" });
expect(updater.getSnapshot()).toMatchObject({
status: "pending",
availableUpdate: null,
availableUpdate: { latestVersion: "1.2.3", readyToInstall: false },
});
});
@@ -408,17 +410,17 @@ describe("formatStatusText", () => {
).toBe("Update ready: v1.2.3");
});
it("keeps manual check feedback visible while an update is pending", () => {
it("shows the found version while an update is pending", () => {
expect(
formatStatusText({
status: "pending",
availableUpdate: null,
availableUpdate: buildFakeCheckResult({ latestVersion: "1.2.3" }),
installMessage: null,
lastCheckedAt: 42,
formatVersion,
formatLastCheckedAt,
}),
).toBe("We'll let you know when the update is ready. Last checked at time-42.");
).toBe("Update found: v1.2.3. Downloading... Last checked at time-42.");
});
it("keeps manual check feedback visible when an update is available", () => {
@@ -137,6 +137,18 @@ export function formatStatusText(input: {
}
if (status === "pending") {
if (availableUpdate?.latestVersion) {
return i18n.t(
lastCheckedAt != null
? "desktop.updates.status.pendingWithVersionAndLastChecked"
: "desktop.updates.status.pendingWithVersion",
{
version: formatVersion(availableUpdate.latestVersion),
time: lastCheckedAt != null ? formatLastCheckedAt(lastCheckedAt) : undefined,
},
);
}
if (lastCheckedAt != null) {
return i18n.t("desktop.updates.status.pendingWithLastChecked", {
time: formatLastCheckedAt(lastCheckedAt),
@@ -244,7 +256,7 @@ export function createDesktopAppUpdater(deps: DesktopAppUpdaterDeps): DesktopApp
nextAvailable = result;
} else if (result.hasUpdate) {
nextStatus = "pending";
nextAvailable = null;
nextAvailable = result;
} else {
nextStatus = "up-to-date";
nextAvailable = null;