import React from "react"; import { Button } from "@/components/button.tsx"; import { useTranslation } from "react-i18next"; import { getHostPassword } from "@/main-axios.ts"; import { cn } from "@/lib/utils"; import { Home, SeparatorVertical, X, Terminal as TerminalIcon, Server as ServerIcon, Folder as FolderIcon, FolderOpen, User as UserIcon, Monitor as MonitorIcon, Eye as EyeIcon, MessagesSquare as MessageSquareIcon, Network, ArrowDownUp as TunnelIcon, Container as DockerIcon, Key, } from "lucide-react"; import { toast } from "sonner"; import type { SSHHost } from "@/types"; interface TabProps { tabType: string; title?: string; isActive?: boolean; isSplit?: boolean; onActivate?: () => void; onClose?: () => void; onSplit?: () => void; canSplit?: boolean; canClose?: boolean; disableActivate?: boolean; disableSplit?: boolean; disableClose?: boolean; isDragging?: boolean; isDragOver?: boolean; isValidDropTarget?: boolean; isHoveredDropTarget?: boolean; hostConfig?: SSHHost; onOpenFileManager?: () => void; } export function Tab({ tabType, title, isActive, isSplit = false, onActivate, onClose, onSplit, canSplit = false, canClose = false, disableActivate = false, disableSplit = false, disableClose = false, isDragging = false, isDragOver = false, isValidDropTarget = false, isHoveredDropTarget = false, hostConfig, onOpenFileManager, }: TabProps): React.ReactElement { const { t } = useTranslation(); const handleCopyPassword = async (e: React.MouseEvent) => { e.stopPropagation(); if (!hostConfig) return; const hasSshPw = hostConfig.authType === "password" && (hostConfig.hasPassword || hostConfig.password); const hasSudoPw = hostConfig.hasSudoPassword || hostConfig.sudoPassword; if (!hasSshPw && !hasSudoPw) return; const field = hasSshPw ? "password" : "sudoPassword"; const passwordToCopy = await getHostPassword(hostConfig.id, field); if (!passwordToCopy) { toast.error(t("nav.failedToCopyPassword")); return; } try { await navigator.clipboard.writeText(passwordToCopy); toast.success(t("nav.passwordCopied")); } catch { try { const textarea = document.createElement("textarea"); textarea.value = passwordToCopy; textarea.style.position = "fixed"; textarea.style.opacity = "0"; document.body.appendChild(textarea); textarea.select(); document.execCommand("copy"); document.body.removeChild(textarea); toast.success(t("nav.passwordCopied")); } catch { toast.error(t("nav.failedToCopyPassword")); } } }; const hasPassword = hostConfig && ((hostConfig.authType === "password" && (hostConfig.hasPassword || hostConfig.password)) || hostConfig.hasSudoPassword || hostConfig.sudoPassword); const getPasswordButtonTitle = () => { if (!hostConfig) return ""; const hasSshPw = hostConfig.authType === "password" && (hostConfig.hasPassword || hostConfig.password); const hasSudoPw = hostConfig.hasSudoPassword || hostConfig.sudoPassword; if (hasSshPw) { return t("nav.copyPassword"); } else if (hasSudoPw) { return t("nav.copySudoPassword"); } return t("nav.noPasswordAvailable"); }; const tabBaseClasses = cn( "relative flex items-center gap-1.5 px-3 w-full min-w-0", "rounded-t-lg border-t-2 border-l-2 border-r-2", "transition-all duration-150 h-[42px]", isDragOver && "bg-background/40 text-muted-foreground border-border opacity-60", isDragging && "opacity-70", isHoveredDropTarget && "bg-blue-500/20 border-blue-500 ring-2 ring-blue-500/50", !isHoveredDropTarget && isValidDropTarget && "border-blue-400/50 bg-background/90", !isDragOver && !isDragging && !isValidDropTarget && !isHoveredDropTarget && isActive && "bg-background text-foreground border-border z-10", !isDragOver && !isDragging && !isValidDropTarget && !isHoveredDropTarget && !isActive && "bg-background/80 text-muted-foreground border-border hover:bg-background/90", ); const splitTitle = (fullTitle: string): { base: string; suffix: string } => { const match = fullTitle.match(/^(.*?)(\s*\(\d+\))$/); if (match) { return { base: match[1], suffix: match[2] }; } return { base: fullTitle, suffix: "" }; }; if (tabType === "home") { return (