Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions apps/code/src/main/services/updates/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ export const UpdatesEvent = {

export type UpdatesStatusPayload = {
checking: boolean;
downloading?: boolean;
upToDate?: boolean;
updateReady?: boolean;
version?: string;
error?: string;
};
Expand Down
15 changes: 8 additions & 7 deletions apps/code/src/main/services/updates/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
type InstallUpdateOutput,
UpdatesEvent,
type UpdatesEvents,
type UpdatesStatusPayload,
} from "./schemas";

type CheckSource = "user" | "periodic";
Expand Down Expand Up @@ -101,6 +102,11 @@ export class UpdatesService extends TypedEventEmitter<UpdatesEvents> {
});
this.pendingNotification = true;
this.flushPendingNotification();
this.emitStatus({
checking: false,
updateReady: true,
version: this.downloadedVersion ?? undefined,
});
return { success: true };
}

Expand Down Expand Up @@ -203,7 +209,7 @@ export class UpdatesService extends TypedEventEmitter<UpdatesEvents> {
this.clearCheckTimeout();
log.info("Update available, downloading...");
// Keep checkingForUpdates true while downloading
// The download is now in progress
this.emitStatus({ checking: true, downloading: true });
}

private handleNoUpdate(): void {
Expand Down Expand Up @@ -265,12 +271,7 @@ export class UpdatesService extends TypedEventEmitter<UpdatesEvents> {
}
}

private emitStatus(status: {
checking: boolean;
upToDate?: boolean;
version?: string;
error?: string;
}): void {
private emitStatus(status: UpdatesStatusPayload): void {
this.emit(UpdatesEvent.Status, status);
}

Expand Down
6 changes: 4 additions & 2 deletions apps/code/src/renderer/components/UpdatePrompt.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -188,14 +188,16 @@ export function UpdatePrompt() {
{ id: CHECK_TOAST_ID, duration: 3000 },
);
} else if (status.checking === true) {
// Show checking toast
// Show checking/downloading toast
sonnerToast.custom(
() => (
<Card size="2">
<Flex gap="2" align="center">
<Spinner size="1" />
<Text size="2" weight="medium">
Checking for updates...
{status.downloading
? "Downloading update..."
: "Checking for updates..."}
</Text>
</Flex>
</Card>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ export function UpdatesSettings() {
message: "Checking for updates...",
type: "info",
});
} else if (result.errorCode === "already_checking") {
// A check is already in progress (e.g. boot check) — show spinner and wait
setUpdateStatus({ message: "Checking for updates...", type: "info" });
} else {
if (result.errorCode === "disabled") {
setUpdatesDisabled(true);
Expand Down Expand Up @@ -68,12 +71,22 @@ export function UpdatesSettings() {
useSubscription(
trpcReact.updates.onStatus.subscriptionOptions(undefined, {
onData: (status) => {
if (status.checking === false && status.upToDate) {
if (status.checking && status.downloading) {
setUpdateStatus({ message: "Downloading update...", type: "info" });
} else if (status.checking === false && status.upToDate) {
setUpdateStatus({
message: "You're on the latest version",
type: "success",
});
setCheckingForUpdates(false);
} else if (status.checking === false && status.updateReady) {
setUpdateStatus({
message: status.version
? `Update ${status.version} ready to install`
: "Update ready to install",
type: "success",
});
setCheckingForUpdates(false);
} else if (status.checking === false) {
setCheckingForUpdates(false);
}
Expand Down
Loading