import React, { useEffect, useRef } from "react"; import { useConnectionLog } from "./ConnectionLogContext.tsx"; import { useTranslation } from "react-i18next"; import { Button } from "@/components/ui/button.tsx"; import { ChevronDown, ChevronUp, Copy, Info, CheckCircle2, AlertTriangle, XCircle, } from "lucide-react"; import { toast } from "sonner"; interface ConnectionLogProps { isConnecting: boolean; isConnected: boolean; hasConnectionError: boolean; position: "top" | "bottom"; } export function ConnectionLog({ isConnecting, isConnected, hasConnectionError, position, }: ConnectionLogProps) { const { t } = useTranslation(); const { logs, clearLogs, isExpanded, toggleExpanded, setIsExpanded } = useConnectionLog(); const logContainerRef = useRef(null); const lastLogRef = useRef(null); useEffect(() => { if (hasConnectionError) { setIsExpanded(true); } }, [hasConnectionError, setIsExpanded]); useEffect(() => { if (isConnected && !hasConnectionError && !isConnecting) { clearLogs(); } }, [isConnected, hasConnectionError, isConnecting, clearLogs]); useEffect(() => { if (isExpanded && lastLogRef.current) { lastLogRef.current.scrollIntoView({ behavior: "smooth" }); } }, [logs, isExpanded]); const shouldShow = isConnecting || hasConnectionError || (logs.length > 0 && !isConnected); if (!shouldShow) { return null; } const copyLogsToClipboard = async () => { const logsText = logs .map((log) => { const time = log.timestamp.toLocaleTimeString(); return `[${time}] [${log.type.toUpperCase()}] ${log.message}`; }) .join("\n"); try { await navigator.clipboard.writeText(logsText); toast.success(t("terminal.connectionLogCopied")); } catch (error) { toast.error(t("terminal.connectionLogCopyFailed")); } }; const getIcon = (type: string) => { switch (type) { case "info": return ; case "success": return ; case "warning": return ; case "error": return ; default: return ; } }; const getTextColor = (type: string) => { switch (type) { case "info": return "text-blue-400"; case "success": return "text-green-400"; case "warning": return "text-yellow-400"; case "error": return "text-red-400"; default: return "text-muted-foreground"; } }; const borderClass = position === "bottom" && !isExpanded ? "border-t-2 border-border" : "border-b-2 border-border"; return (
{(isExpanded || hasConnectionError) && (
)}
{logs.length > 0 && ( )}
{isExpanded && (
{logs.length === 0 ? (
{isConnecting ? t("terminal.connectionLogConnecting") : t("terminal.connectionLogEmpty")}
) : (
{logs.map((log, index) => (
{log.timestamp.toLocaleTimeString()}
{getIcon(log.type)}
{log.message}
))}
)}
)}
); }