fix: add up-to-date state so Check for updates gives visible feedback

When electron-updater reports no update available, the service now
transitions to 'up-to-date' instead of reverting silently to 'idle'.
The troubleshooting UI shows a green check icon, 'Up to date' label,
and 'You are running the latest version of Aryx.' description.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
David Kaya
2026-03-30 10:20:05 +02:00
co-authored by Copilot
parent cbcf239a0a
commit 33b293271e
4 changed files with 28 additions and 6 deletions
+1 -1
View File
@@ -151,7 +151,7 @@ export class AutoUpdateService {
};
private readonly notAvailableListener = () => {
this.publishStatus({ state: 'idle' });
this.publishStatus({ state: 'up-to-date' });
};
private readonly progressListener = (progress: AutoUpdateProgressLike) => {
+10 -4
View File
@@ -1,5 +1,5 @@
import { useEffect, useState, type ReactNode } from 'react';
import { ChevronLeft, ChevronRight, Code, Cpu, FolderOpen, Palette, Plus, RefreshCw, Server, TriangleAlert, Workflow, Wrench } from 'lucide-react';
import { ChevronLeft, ChevronRight, CircleCheck, Code, Cpu, FolderOpen, Palette, Plus, RefreshCw, Server, TriangleAlert, Workflow, Wrench } from 'lucide-react';
import { CopilotStatusCard } from '@renderer/components/CopilotStatusCard';
import { PatternEditor } from '@renderer/components/PatternEditor';
@@ -859,6 +859,8 @@ function TroubleshootingSection({
switch (updateStatus.state) {
case 'checking':
return 'Checking for updates…';
case 'up-to-date':
return 'Up to date';
case 'available':
return `Update available: v${updateStatus.version ?? 'unknown'}`;
case 'downloading':
@@ -876,6 +878,8 @@ function TroubleshootingSection({
switch (updateStatus.state) {
case 'checking':
return 'Contacting the update server…';
case 'up-to-date':
return 'You are running the latest version of Aryx.';
case 'available':
case 'downloading':
return 'A new version is being downloaded and will be installed automatically.';
@@ -922,11 +926,13 @@ function TroubleshootingSection({
onClick={() => void handleCheckForUpdates()}
type="button"
>
<span className="text-[var(--color-text-muted)] transition-all duration-200 group-hover:text-[var(--color-text-secondary)]">
<RefreshCw className={`size-4 ${isChecking ? 'animate-spin' : ''}`} />
<span className={`transition-all duration-200 ${updateStatus.state === 'up-to-date' ? 'text-[var(--color-status-success)]' : 'text-[var(--color-text-muted)] group-hover:text-[var(--color-text-secondary)]'}`}>
{updateStatus.state === 'up-to-date'
? <CircleCheck className="size-4" />
: <RefreshCw className={`size-4 ${isChecking ? 'animate-spin' : ''}`} />}
</span>
<div className="min-w-0 flex-1">
<span className={`text-[13px] font-medium ${updateStatus.state === 'error' ? 'text-[var(--color-status-error)]' : 'text-[var(--color-text-primary)]'}`}>
<span className={`text-[13px] font-medium ${updateStatus.state === 'error' ? 'text-[var(--color-status-error)]' : updateStatus.state === 'up-to-date' ? 'text-[var(--color-status-success)]' : 'text-[var(--color-text-primary)]'}`}>
{getUpdateLabel()}
</span>
<p className="mt-0.5 text-[12px] text-[var(--color-text-muted)]">{getUpdateDescription()}</p>
+1 -1
View File
@@ -175,7 +175,7 @@ export interface SetTerminalHeightInput {
height?: number;
}
export type UpdateStatusState = 'idle' | 'checking' | 'available' | 'downloading' | 'downloaded' | 'error';
export type UpdateStatusState = 'idle' | 'checking' | 'up-to-date' | 'available' | 'downloading' | 'downloaded' | 'error';
export interface UpdateDownloadProgress {
bytesPerSecond: number;
+16
View File
@@ -148,6 +148,22 @@ describe('AutoUpdateService', () => {
]);
});
test('transitions to up-to-date when no update is available', () => {
const updater = new FakeUpdater();
const service = new AutoUpdateService({ isPackaged: true, updater });
const statuses: UpdateStatus[] = [];
service.onStatus((status) => statuses.push(status));
updater.emit('checking-for-update');
updater.emit('update-not-available', {});
expect(statuses).toEqual([
{ state: 'checking' },
{ state: 'up-to-date' },
]);
expect(service.getStatus()).toEqual({ state: 'up-to-date' });
});
test('reports updater errors and only installs once an update is downloaded', () => {
const updater = new FakeUpdater();
const service = new AutoUpdateService({ isPackaged: true, updater });