import { formatInstallButtonLabel, formatTmuxInstallerProgress, formatTmuxInstallerTitle, formatTmuxLocationLabel, formatTmuxOptionalBenefits, formatTmuxPlatformLabel, } from '@features/tmux-installer/renderer/utils/formatTmuxInstallerText'; import type { TmuxInstallerSnapshot, TmuxInstallHint, TmuxStatus, } from '@features/tmux-installer/contracts'; export interface TmuxInstallerBannerViewModel { visible: boolean; loading: boolean; title: string; body: string; benefitsBody: string | null; error: string | null; platformLabel: string | null; locationLabel: string | null; runtimeReadyLabel: string | null; versionLabel: string | null; phase: TmuxInstallerSnapshot['phase']; progressPercent: number | null; logs: string[]; manualHints: TmuxInstallHint[]; manualHintsCollapsible: boolean; primaryGuideUrl: string | null; installSupported: boolean; installDisabled: boolean; installLabel: string; installButtonPrimary: boolean; showRefreshButton: boolean; canCancel: boolean; acceptsInput: boolean; inputPrompt: string | null; inputSecret: boolean; detailsOpen: boolean; } interface AdaptInput { status: TmuxStatus | null; snapshot: TmuxInstallerSnapshot; loading: boolean; error: string | null; detailsOpen: boolean; } const RESTART_REQUIRED_PATTERNS = ['restart', 'reboot', 'перезагруз', 'требуется перезагрузка']; export class TmuxInstallerBannerAdapter { static create(): TmuxInstallerBannerAdapter { return new TmuxInstallerBannerAdapter(); } adapt(input: AdaptInput): TmuxInstallerBannerViewModel { const status = input.status; const snapshot = input.snapshot; const displayPhase = this.#resolveDisplayPhase(snapshot, status); const hasActiveInstallFlow = displayPhase !== 'idle' && displayPhase !== 'completed' && displayPhase !== 'cancelled'; const tmuxMissing = status ? !status.effective.available : !input.loading; const visible = hasActiveInstallFlow || (displayPhase !== 'completed' && !input.loading && tmuxMissing); const title = snapshot.message && (displayPhase === 'pending_external_elevation' || displayPhase === 'waiting_for_external_step' || displayPhase === 'needs_restart' || displayPhase === 'needs_manual_step') ? snapshot.message : formatTmuxInstallerTitle(displayPhase); const primaryGuideUrl = status?.autoInstall.manualHints.find((hint) => typeof hint.url === 'string')?.url ?? null; const body = input.error ?? snapshot.error ?? snapshot.detail ?? snapshot.message ?? status?.effective.detail ?? status?.wsl?.statusDetail ?? 'tmux improves persistent teammate reliability and cleaner recovery for long-running tasks.'; const benefitsBody = status && !status.effective.available ? formatTmuxOptionalBenefits(status.platform) : null; const runtimeReadyLabel = status ? status.effective.runtimeReady ? 'Ready for persistent teammates' : status.effective.available ? 'Installed, but not active yet' : null : null; const versionLabel = status?.effective.version ?? status?.host.version ?? status?.wsl?.tmuxVersion ?? null; const manualHints = status?.autoInstall.manualHints ?? []; const manualHintsCollapsible = status?.platform === 'win32' && manualHints.length > 0; const installLabel = displayPhase === 'idle' && status?.platform === 'win32' && status.autoInstall.strategy === 'wsl' && status.autoInstall.supported ? !status.wsl?.wslInstalled ? 'Install WSL' : !status.wsl?.distroName ? 'Install Ubuntu in WSL' : 'Install tmux in WSL' : formatInstallButtonLabel(displayPhase); const installDisabled = input.loading || displayPhase === 'preparing' || displayPhase === 'checking' || displayPhase === 'requesting_privileges' || displayPhase === 'pending_external_elevation' || displayPhase === 'waiting_for_external_step' || displayPhase === 'installing' || displayPhase === 'verifying'; const installButtonPrimary = !installDisabled && (installLabel.startsWith('Install') || installLabel.startsWith('Retry')); const showRefreshButton = !(status?.autoInstall.supported ?? false) || (installLabel !== 'Re-check' && installLabel !== 'Re-check after restart'); return { visible, loading: input.loading, title, body, benefitsBody, error: input.error ?? snapshot.error ?? status?.error ?? null, platformLabel: formatTmuxPlatformLabel(status?.platform ?? null), locationLabel: formatTmuxLocationLabel(status?.effective.location ?? null), runtimeReadyLabel, versionLabel, phase: displayPhase, progressPercent: formatTmuxInstallerProgress(displayPhase), logs: snapshot.logs, manualHints, manualHintsCollapsible, primaryGuideUrl, installSupported: status?.autoInstall.supported ?? false, installDisabled, installLabel, installButtonPrimary, showRefreshButton, canCancel: snapshot.canCancel, acceptsInput: snapshot.acceptsInput, inputPrompt: snapshot.inputPrompt, inputSecret: snapshot.inputSecret, detailsOpen: input.detailsOpen, }; } #resolveDisplayPhase( snapshot: TmuxInstallerSnapshot, status: TmuxStatus | null ): TmuxInstallerSnapshot['phase'] { if (snapshot.phase !== 'waiting_for_external_step') { return snapshot.phase; } const combinedSignals = [snapshot.message, snapshot.detail, status?.wsl?.statusDetail, ...snapshot.logs] .filter(Boolean) .join('\n') .toLowerCase(); const restartRequired = status?.wsl?.rebootRequired === true || RESTART_REQUIRED_PATTERNS.some((pattern) => combinedSignals.includes(pattern)); return restartRequired ? 'needs_restart' : snapshot.phase; } }