import React from 'react'; import { AlertTriangle, ChevronDown, ChevronUp, ExternalLink, RefreshCw, Wrench, XCircle, } from 'lucide-react'; import { useTmuxInstallerBanner } from '../hooks/useTmuxInstallerBanner'; const SUMMARY_TITLE = 'tmux is not installed'; const BANNER_MIN_H = 'min-h-[4.25rem]'; const SourceLink = ({ label, url, onOpen, }: { label: string; url: string; onOpen: (url: string) => Promise; }): React.JSX.Element => ( ); export function TmuxInstallerBannerView(): React.JSX.Element | null { const { viewModel, install, cancel, submitInput, refresh, toggleDetails, openExternal } = useTmuxInstallerBanner(); const [expanded, setExpanded] = React.useState(false); const [inputValue, setInputValue] = React.useState(''); const [manualHintsExpanded, setManualHintsExpanded] = React.useState(false); const previousPhaseRef = React.useRef(viewModel.phase); React.useEffect(() => { if (!viewModel.acceptsInput) { setInputValue(''); } }, [viewModel.acceptsInput]); React.useEffect(() => { if (!viewModel.manualHintsCollapsible) { setManualHintsExpanded(false); } }, [viewModel.manualHintsCollapsible]); React.useEffect(() => { const previousPhase = previousPhaseRef.current; const becameActive = previousPhase === 'idle' && viewModel.phase !== 'idle' && viewModel.phase !== 'completed' && viewModel.phase !== 'cancelled'; if (becameActive) { setExpanded(true); } previousPhaseRef.current = viewModel.phase; }, [viewModel.phase]); if (!viewModel.visible) { return null; } const manualHintsVisible = viewModel.manualHints.length > 0 && (!viewModel.manualHintsCollapsible || manualHintsExpanded); return (
{expanded && (
{viewModel.title !== SUMMARY_TITLE && (
{viewModel.title}
)}

{viewModel.body}

{viewModel.benefitsBody && (
{viewModel.benefitsBody}
)} {(viewModel.platformLabel || viewModel.locationLabel || viewModel.runtimeReadyLabel || viewModel.versionLabel || viewModel.phase !== 'idle') && (
{viewModel.platformLabel && ( Detected OS: {viewModel.platformLabel} )} {viewModel.locationLabel && ( Runtime path: {viewModel.locationLabel} )} {viewModel.runtimeReadyLabel && ( {viewModel.runtimeReadyLabel} )} {viewModel.versionLabel && ( {viewModel.versionLabel} )} {viewModel.phase !== 'idle' && ( Phase: {viewModel.phase} )}
)}
{viewModel.installSupported && ( )} {viewModel.canCancel && ( )} {viewModel.primaryGuideUrl && ( )} {viewModel.manualHintsCollapsible && ( )} {viewModel.showRefreshButton && ( )}
{viewModel.progressPercent !== null && (
Installer progress {viewModel.progressPercent}%
)} {viewModel.acceptsInput && (
{ event.preventDefault(); void (async () => { const submitted = await submitInput(inputValue); if (submitted) { setInputValue(''); } })(); }} > setInputValue(event.target.value)} placeholder={viewModel.inputPrompt ?? 'Send input to the installer'} className="min-w-0 flex-1 rounded-md border px-3 py-2 text-sm" style={{ borderColor: 'var(--color-border)', backgroundColor: 'rgba(0, 0, 0, 0.12)', color: 'var(--color-text)', }} autoComplete="current-password" />
{viewModel.inputSecret && (
Password input is sent directly to the installer terminal and is not added to the log output.
)}
)} {manualHintsVisible && (
{viewModel.manualHints.map((hint) => (
{hint.title}
{hint.description}
{hint.command && ( {hint.command} )} {hint.url && (
)}
))}
)} {(viewModel.logs.length > 0 || viewModel.error) && (
{viewModel.detailsOpen && (
                  {[viewModel.error, ...viewModel.logs].filter(Boolean).join('\n')}
                
)}
)}
)}
); }