feat(ui): add version sync timestamp to ProxyStatusWidget

- Show current CLIProxyAPI version (e.g., v6.5.53)
- Display "Synced Xm ago" with full timestamp on hover
- Extend API response to include checkedAt timestamp
This commit is contained in:
kaitranntt committed 2025-12-18 23:24:15 -05:00
1 parent 96762a9f6e
commit d43079b724
3 files changed
+37 -8

No files matched your search

+13 -8
View File
@@ -59,6 +59,7 @@ interface UpdateCheckResult {
currentVersion: string; currentVersion: string;
latestVersion: string; latestVersion: string;
fromCache: boolean; fromCache: boolean;
checkedAt: number; // Unix timestamp of last check
} }
/** Default configuration */ /** Default configuration */
@@ -172,19 +173,21 @@ export class BinaryManager {
const currentVersion = this.getInstalledVersion(); const currentVersion = this.getInstalledVersion();
// Try cache first // Try cache first
const cachedVersion = this.getCachedLatestVersion(); const cache = this.getVersionCache();
if (cachedVersion) { if (cache) {
this.log(`Using cached version: ${cachedVersion}`); this.log(`Using cached version: ${cache.latestVersion}`);
return { return {
hasUpdate: this.isNewerVersion(cachedVersion, currentVersion), hasUpdate: this.isNewerVersion(cache.latestVersion, currentVersion),
currentVersion, currentVersion,
latestVersion: cachedVersion, latestVersion: cache.latestVersion,
fromCache: true, fromCache: true,
checkedAt: cache.checkedAt,
}; };
} }
// Fetch from GitHub API // Fetch from GitHub API
const latestVersion = await this.fetchLatestVersion(); const latestVersion = await this.fetchLatestVersion();
const now = Date.now();
this.cacheLatestVersion(latestVersion); this.cacheLatestVersion(latestVersion);
return { return {
@@ -192,6 +195,7 @@ export class BinaryManager {
currentVersion, currentVersion,
latestVersion, latestVersion,
fromCache: false, fromCache: false,
checkedAt: now,
}; };
} }
@@ -287,9 +291,9 @@ export class BinaryManager {
} }
/** /**
* Get cached latest version if still valid * Get version cache data if still valid
*/ */
private getCachedLatestVersion(): string | null { private getVersionCache(): VersionCache | null {
const cachePath = this.getVersionCachePath(); const cachePath = this.getVersionCachePath();
if (!fs.existsSync(cachePath)) { if (!fs.existsSync(cachePath)) {
return null; return null;
@@ -301,7 +305,7 @@ export class BinaryManager {
// Check if cache is still valid // Check if cache is still valid
if (Date.now() - cache.checkedAt < VERSION_CACHE_DURATION_MS) { if (Date.now() - cache.checkedAt < VERSION_CACHE_DURATION_MS) {
return cache.latestVersion; return cache;
} }
// Cache expired // Cache expired
@@ -1001,6 +1005,7 @@ export interface CliproxyUpdateCheckResult {
currentVersion: string; currentVersion: string;
latestVersion: string; latestVersion: string;
fromCache: boolean; fromCache: boolean;
checkedAt: number; // Unix timestamp of last check
} }
/** /**
+23
View File
@@ -31,6 +31,17 @@ function formatUptime(startedAt?: string): string {
return `${minutes}m`; return `${minutes}m`;
} }
function formatTimeAgo(timestamp?: number): string {
if (!timestamp) return '';
const diff = Date.now() - timestamp;
const minutes = Math.floor(diff / (1000 * 60));
const hours = Math.floor(diff / (1000 * 60 * 60));
if (minutes < 1) return 'just now';
if (minutes < 60) return `${minutes}m ago`;
return `${hours}h ago`;
}
export function ProxyStatusWidget() { export function ProxyStatusWidget() {
const { data: status, isLoading } = useProxyStatus(); const { data: status, isLoading } = useProxyStatus();
const { data: updateCheck } = useCliproxyUpdateCheck(); const { data: updateCheck } = useCliproxyUpdateCheck();
@@ -167,6 +178,18 @@ export function ProxyStatusWidget() {
</Button> </Button>
</div> </div>
)} )}
{/* Version sync indicator */}
{updateCheck?.currentVersion && (
<div className="mt-2 pt-2 border-t border-muted flex items-center justify-between text-[10px] text-muted-foreground/70">
<span>v{updateCheck.currentVersion}</span>
{updateCheck.checkedAt && (
<span title={new Date(updateCheck.checkedAt).toLocaleString()}>
Synced {formatTimeAgo(updateCheck.checkedAt)}
</span>
)}
</div>
)}
</div> </div>
); );
} }
+1
View File
@@ -196,6 +196,7 @@ export interface CliproxyUpdateCheckResult {
currentVersion: string; currentVersion: string;
latestVersion: string; latestVersion: string;
fromCache: boolean; fromCache: boolean;
checkedAt: number; // Unix timestamp of last check
} }
// API // API