import { useStore } from '@nanostores/react' import { Button } from '@/components/ui/button' import type { DesktopRegistryConnection } from '@/global' import { useI18n } from '@/i18n' import { Download, Loader2 } from '@/lib/icons' import { $connectionsRegistry } from '@/store/connections' import { $managedUpdates, managedUpdatesSupported, type ManagedUpdateState, runManagedUpdate } from '@/store/managed-updates' import { ListRow, Pill, SectionHeading } from './primitives' function stateTone(state: ManagedUpdateState | undefined): 'muted' | 'primary' | 'warn' { if (!state || state.status === 'idle') { return 'muted' } if (state.status === 'updating' || state.status === 'updated') { return 'primary' } return 'warn' } function sshTarget(connection: DesktopRegistryConnection): string | null { if (!connection.host) { return null } return connection.user ? `${connection.user}@${connection.host}` : connection.host } /** Per-connection driver for #95942's transactional SSH update engine: one * Update button per registered Desktop-managed SSH install, a single honest * in-flight state (the engine exposes no streaming progress channel), and the * correlated receipt once it lands. */ export function ManagedUpdatesSection() { const { t } = useI18n() const m = t.settings.managedUpdates const registry = useStore($connectionsRegistry) const states = useStore($managedUpdates) const sshConnections = (registry?.connections ?? []).filter(connection => connection.kind === 'ssh') // Fail closed: no section on an Electron main without the transactional // bridge, and nothing to drive when no SSH install is registered. if (!managedUpdatesSupported() || sshConnections.length === 0) { return null } const statusLabel = (state: ManagedUpdateState | undefined): string | null => { switch (state?.status) { case 'failed': return m.failed case 'partial': return m.partial case 'refused': return state.alreadyRunning ? m.alreadyRunning : m.refused case 'updated': return m.updated case 'updating': return m.updating default: return null } } const receiptLine = (state: ManagedUpdateState): string | null => { if (!state.receipt) { return null } const parts = [m.receipt(state.receipt.correlationId.slice(0, 8), state.receipt.outcome)] if (state.receipt.preVersion && state.receipt.postVersion) { parts.push(m.receiptVersions(state.receipt.preVersion, state.receipt.postVersion)) } if (state.receipt.stopReason) { parts.push(state.receipt.stopReason) } return parts.join(' ยท ') } return (

{m.intro}

{sshConnections.map(connection => { const state = states[connection.id] const updating = state?.status === 'updating' const label = statusLabel(state) const receipt = state ? receiptLine(state) : null const restored = state?.scopes.filter(scope => scope.restored).map(scope => scope.profile) ?? [] const unrestored = state?.scopes.filter(scope => !scope.restored) ?? [] return ( {m.updating} ) : ( ) } below={ state && (updating || state.message || receipt || state.scopes.length > 0) ? (
{updating ?

{m.progress}

: null} {!updating && state.message ?

{state.message}

: null} {receipt ?

{receipt}

: null} {!updating && restored.length > 0 ?

{m.scopesRestored(restored.join(', '))}

: null} {!updating && unrestored.map(scope => (

{m.scopeNotRestored(scope.profile, scope.error ?? m.failed)}

))}
) : null } description={sshTarget(connection) ?? m.sshConnection} key={connection.id} title={ {connection.label} {label ? {label} : null} } /> ) })}
) }