refactor(ui): merge sync into ProxyStatusWidget

- add sync icon button to widget header

- show inline sync status (Ready/No Config)

- remove separate SyncStatusCard from cliproxy page

- reduces vertical space, better UX
This commit is contained in:
kaitranntt
2026-01-28 11:57:22 -05:00
parent 32dbd5e174
commit 37616348f8
2 changed files with 38 additions and 7 deletions
@@ -24,6 +24,9 @@ import {
Settings,
X,
Download,
FileDown,
Check,
AlertCircle,
} from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
@@ -57,6 +60,7 @@ import {
useInstallVersion,
useRestartProxy,
} from '@/hooks/use-cliproxy';
import { useSyncStatus, useExecuteSync } from '@/hooks/use-cliproxy-sync';
import { cn } from '@/lib/utils';
/** Client-side semver comparison (true if a > b) */
@@ -152,6 +156,10 @@ export function ProxyStatusWidget() {
const restartProxy = useRestartProxy();
const installVersion = useInstallVersion();
// Sync functionality
const { data: syncStatus } = useSyncStatus();
const { mutate: executeSync, isPending: isSyncing } = useExecuteSync();
// Version picker state (expanded section)
const [isExpanded, setIsExpanded] = useState(false);
const [selectedVersion, setSelectedVersion] = useState<string>('');
@@ -180,11 +188,16 @@ export function ProxyStatusWidget() {
stopProxy.isPending ||
restartProxy.isPending ||
installVersion.isPending ||
isBackendSwitching;
isBackendSwitching ||
isSyncing;
const hasUpdate = updateCheck?.hasUpdate ?? false;
const isUnstable = updateCheck?.isStable === false;
const currentVersion = updateCheck?.currentVersion;
// Sync status
const isSyncConfigured = syncStatus?.configured ?? false;
const syncStatusText = isSyncConfigured ? 'Sync Ready' : 'No Config';
// Target version for update/downgrade badge
const targetVersion = isUnstable
? updateCheck?.maxStableVersion || versionsData?.latestStable
@@ -295,6 +308,13 @@ export function ProxyStatusWidget() {
<RefreshCw className="w-3 h-3 animate-spin text-muted-foreground" />
) : isRunning ? (
<>
<IconButton
icon={isSyncing ? RefreshCw : FileDown}
tooltip="Sync profiles to CLIProxy"
onClick={() => executeSync()}
disabled={!isSyncConfigured || isActioning}
isPending={isSyncing}
/>
<IconButton
icon={RotateCw}
tooltip="Restart"
@@ -375,6 +395,23 @@ export function ProxyStatusWidget() {
</div>
)}
{/* Sync status row */}
<div className="mt-2 flex items-center gap-1.5 text-xs">
{isSyncConfigured ? (
<Check className="w-3 h-3 text-green-600 dark:text-green-400" />
) : (
<AlertCircle className="w-3 h-3 text-muted-foreground" />
)}
<span
className={cn(
'text-xs',
isSyncConfigured ? 'text-green-600 dark:text-green-400' : 'text-muted-foreground'
)}
>
{syncStatusText}
</span>
</div>
{/* Expanded section: Version Management (available even when not running) */}
<Collapsible open={isExpanded} onOpenChange={setIsExpanded}>
<CollapsibleContent className="mt-3 pt-3 border-t border-muted">
-6
View File
@@ -16,7 +16,6 @@ import { AddAccountDialog } from '@/components/account/add-account-dialog';
import { ProviderEditor } from '@/components/cliproxy/provider-editor';
import { ProviderLogo } from '@/components/cliproxy/provider-logo';
import { ProxyStatusWidget } from '@/components/monitoring/proxy-status-widget';
import { SyncStatusCard } from '@/components/cliproxy/sync/sync-status-card';
import {
useCliproxy,
useCliproxyAuth,
@@ -374,11 +373,6 @@ export function CliproxyPage() {
<ProxyStatusWidget />
</div>
{/* Sync Status Card */}
<div className="p-3 border-t">
<SyncStatusCard />
</div>
{/* Footer Stats */}
<div className="p-3 border-t bg-background text-xs text-muted-foreground">
<div className="flex items-center justify-between">