import { useState, useCallback } from "react"; import { View, Platform, Modal, Pressable, ScrollView } from "react-native"; import * as Clipboard from "expo-clipboard"; import { Shield, AlertTriangle, Copy, Check } from "lucide-react-native"; import { Button, Text } from "@/app/components/ui"; import { useThemeColor } from "@/app/contexts/ThemeContext"; import type { HostKeyData } from "@/app/tabs/sessions/terminal/NativeWebSocketManager"; interface HostKeyVerificationDialogProps { visible: boolean; scenario: "new" | "changed"; data: HostKeyData | null; onAccept: () => void; onReject: () => void; } const formatFingerprint = (fp: string) => fp.match(/.{1,2}/g)?.join(":") ?? fp; function FingerprintRow({ label, algorithm, fingerprint, keyType, }: { label: string; algorithm: string; fingerprint: string; keyType: string; }) { const color = useThemeColor(); const [copied, setCopied] = useState(false); const handleCopy = useCallback(async () => { try { await Clipboard.setStringAsync(formatFingerprint(fingerprint)); setCopied(true); setTimeout(() => setCopied(false), 2000); } catch {} }, [fingerprint]); return ( {label} {algorithm.toUpperCase()} ({keyType}) {formatFingerprint(fingerprint)} ); } export function HostKeyVerificationDialog({ visible, scenario, data, onAccept, onReject, }: HostKeyVerificationDialogProps) { const color = useThemeColor(); const isChanged = scenario === "changed"; const hostLabel = data ? `${data.hostname ?? data.ip}:${data.port}` : ""; return ( e.stopPropagation()} > {/* Card with scenario-aware border */} {/* Header */} {isChanged ? ( ) : ( )} {isChanged ? "Host Key Changed!" : "Verify Host Key"} {hostLabel} {/* Body */} {/* Status banner */} {isChanged ? "The host's SSH key has changed since your last connection. This could indicate a security risk." : "You are connecting to this host for the first time. Verify the fingerprint before trusting."} {/* Fingerprints */} {data && isChanged && data.oldFingerprint ? ( <> ) : data ? ( ) : null} {/* Footer */} ); }