Files
Netcatty/components/terminal/TerminalConnectionDialog.tsx
T
LAPTOP-O016UC3M\Qi Chen 5a687667b5 Improves code consistency and formatting across components
Refactors code for consistent indentation, spacing, and style.
Enhances readability and maintainability by aligning formatting.
No logic changes; only visual and stylistic improvements applied.
2025-12-11 17:08:03 +08:00

150 lines
6.4 KiB
TypeScript

/**
* Terminal Connection Dialog
* Full connection overlay with host info, progress indicator, and auth/progress content
*/
import { User } from 'lucide-react';
import React from 'react';
import { cn } from '../../lib/utils';
import { Host, SSHKey } from '../../types';
import { DistroAvatar } from '../DistroAvatar';
import { Button } from '../ui/button';
import { TerminalAuthDialog, TerminalAuthDialogProps } from './TerminalAuthDialog';
import { TerminalConnectionProgress, TerminalConnectionProgressProps } from './TerminalConnectionProgress';
export interface ChainProgress {
currentHop: number;
totalHops: number;
currentHostLabel: string;
}
export interface TerminalConnectionDialogProps {
host: Host;
status: 'connecting' | 'connected' | 'disconnected';
error: string | null;
progressValue: number;
chainProgress: ChainProgress | null;
needsAuth: boolean;
showLogs: boolean;
_setShowLogs: (show: boolean) => void;
// Auth dialog props
authProps: Omit<TerminalAuthDialogProps, 'keys'>;
keys: SSHKey[];
// Progress props
progressProps: Omit<TerminalConnectionProgressProps, 'status' | 'error' | 'showLogs' | '_setShowLogs'>;
}
export const TerminalConnectionDialog: React.FC<TerminalConnectionDialogProps> = ({
host,
status,
error,
progressValue,
chainProgress,
needsAuth,
showLogs,
_setShowLogs: setShowLogs, // Rename back to setShowLogs for internal use
authProps,
keys,
progressProps,
}) => {
const hasError = Boolean(error);
const isConnecting = status === 'connecting';
return (
<div className={cn(
"absolute inset-0 z-20 flex items-center justify-center",
needsAuth ? "bg-black" : "bg-black/30"
)}>
<div className="w-[560px] max-w-[90vw] bg-background/95 border border-border/60 rounded-2xl shadow-xl p-6 space-y-4">
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
<DistroAvatar host={host} fallback={host.label.slice(0, 2).toUpperCase()} className="h-10 w-10" />
<div>
{/* Show chain progress if available */}
{chainProgress ? (
<>
<div className="text-sm font-semibold">
<span className="text-muted-foreground">Chain</span>{' '}
<span className="font-bold">{chainProgress.currentHop}</span>{' '}
<span className="text-muted-foreground">of</span>{' '}
<span>{chainProgress.totalHops}:</span>{' '}
<span>{chainProgress.currentHostLabel}</span>
</div>
<div className="text-[11px] text-muted-foreground font-mono">
SSH {host.hostname}:{host.port || 22}
</div>
</>
) : (
<>
<div className="text-sm font-semibold">{host.label}</div>
<div className="text-[11px] text-muted-foreground font-mono">
SSH {host.hostname}:{host.port || 22}
</div>
</>
)}
</div>
</div>
{!needsAuth && (
<Button
size="sm"
variant="outline"
className="h-8 text-xs"
onClick={() => setShowLogs(!showLogs)}
>
{showLogs ? 'Hide logs' : 'Show logs'}
</Button>
)}
</div>
{/* Progress indicator - icons with progress bar below */}
<div className="space-y-2">
<div className="flex items-center gap-3">
<div className={cn(
"h-8 w-8 rounded-full flex items-center justify-center flex-shrink-0",
needsAuth
? "bg-primary text-primary-foreground"
: hasError
? "bg-destructive/20 text-destructive"
: isConnecting
? "bg-primary/15 text-primary"
: "bg-muted text-muted-foreground"
)}>
<User size={14} />
</div>
<div className="flex-1 h-1.5 rounded-full bg-border/60 overflow-hidden relative">
<div
className={cn(
"absolute inset-y-0 left-0 rounded-full transition-all duration-300",
error ? "bg-destructive" : "bg-primary"
)}
style={{
width: needsAuth ? '0%' : status === 'connecting' ? `${progressValue}%` : error ? '100%' : '100%',
}}
/>
</div>
<div className={cn(
"h-8 w-8 rounded-full flex items-center justify-center flex-shrink-0",
hasError ? "bg-destructive/20 text-destructive" : "bg-muted text-muted-foreground"
)}>
{'>_'}
</div>
</div>
</div>
{needsAuth ? (
<TerminalAuthDialog {...authProps} keys={keys} />
) : (
<TerminalConnectionProgress
status={status}
error={error}
showLogs={showLogs}
_setShowLogs={setShowLogs}
{...progressProps}
/>
)}
</div>
</div>
);
};
export default TerminalConnectionDialog;