mirror of
https://github.com/davidkaya/aryx.git
synced 2026-08-26 21:03:58 +02:00
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:
@@ -151,7 +151,7 @@ export class AutoUpdateService {
|
|||||||
};
|
};
|
||||||
|
|
||||||
private readonly notAvailableListener = () => {
|
private readonly notAvailableListener = () => {
|
||||||
this.publishStatus({ state: 'idle' });
|
this.publishStatus({ state: 'up-to-date' });
|
||||||
};
|
};
|
||||||
|
|
||||||
private readonly progressListener = (progress: AutoUpdateProgressLike) => {
|
private readonly progressListener = (progress: AutoUpdateProgressLike) => {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useEffect, useState, type ReactNode } from 'react';
|
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 { CopilotStatusCard } from '@renderer/components/CopilotStatusCard';
|
||||||
import { PatternEditor } from '@renderer/components/PatternEditor';
|
import { PatternEditor } from '@renderer/components/PatternEditor';
|
||||||
@@ -859,6 +859,8 @@ function TroubleshootingSection({
|
|||||||
switch (updateStatus.state) {
|
switch (updateStatus.state) {
|
||||||
case 'checking':
|
case 'checking':
|
||||||
return 'Checking for updates…';
|
return 'Checking for updates…';
|
||||||
|
case 'up-to-date':
|
||||||
|
return 'Up to date';
|
||||||
case 'available':
|
case 'available':
|
||||||
return `Update available: v${updateStatus.version ?? 'unknown'}`;
|
return `Update available: v${updateStatus.version ?? 'unknown'}`;
|
||||||
case 'downloading':
|
case 'downloading':
|
||||||
@@ -876,6 +878,8 @@ function TroubleshootingSection({
|
|||||||
switch (updateStatus.state) {
|
switch (updateStatus.state) {
|
||||||
case 'checking':
|
case 'checking':
|
||||||
return 'Contacting the update server…';
|
return 'Contacting the update server…';
|
||||||
|
case 'up-to-date':
|
||||||
|
return 'You are running the latest version of Aryx.';
|
||||||
case 'available':
|
case 'available':
|
||||||
case 'downloading':
|
case 'downloading':
|
||||||
return 'A new version is being downloaded and will be installed automatically.';
|
return 'A new version is being downloaded and will be installed automatically.';
|
||||||
@@ -922,11 +926,13 @@ function TroubleshootingSection({
|
|||||||
onClick={() => void handleCheckForUpdates()}
|
onClick={() => void handleCheckForUpdates()}
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
<span className="text-[var(--color-text-muted)] transition-all duration-200 group-hover:text-[var(--color-text-secondary)]">
|
<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)]'}`}>
|
||||||
<RefreshCw className={`size-4 ${isChecking ? 'animate-spin' : ''}`} />
|
{updateStatus.state === 'up-to-date'
|
||||||
|
? <CircleCheck className="size-4" />
|
||||||
|
: <RefreshCw className={`size-4 ${isChecking ? 'animate-spin' : ''}`} />}
|
||||||
</span>
|
</span>
|
||||||
<div className="min-w-0 flex-1">
|
<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()}
|
{getUpdateLabel()}
|
||||||
</span>
|
</span>
|
||||||
<p className="mt-0.5 text-[12px] text-[var(--color-text-muted)]">{getUpdateDescription()}</p>
|
<p className="mt-0.5 text-[12px] text-[var(--color-text-muted)]">{getUpdateDescription()}</p>
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ export interface SetTerminalHeightInput {
|
|||||||
height?: number;
|
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 {
|
export interface UpdateDownloadProgress {
|
||||||
bytesPerSecond: number;
|
bytesPerSecond: number;
|
||||||
|
|||||||
@@ -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', () => {
|
test('reports updater errors and only installs once an update is downloaded', () => {
|
||||||
const updater = new FakeUpdater();
|
const updater = new FakeUpdater();
|
||||||
const service = new AutoUpdateService({ isPackaged: true, updater });
|
const service = new AutoUpdateService({ isPackaged: true, updater });
|
||||||
|
|||||||
Reference in New Issue
Block a user