"use client"; import { useState, useEffect, useRef } from "react"; import PropTypes from "prop-types"; import { Badge, Toggle } from "@/shared/components"; import CooldownTimer from "./CooldownTimer"; export default function ConnectionRow({ connection, proxyPools, isOAuth, isFirst, isLast, onMoveUp, onMoveDown, onToggleActive, onUpdateProxy, onEdit, onDelete }) { const [showProxyDropdown, setShowProxyDropdown] = useState(false); const [updatingProxy, setUpdatingProxy] = useState(false); const proxyDropdownRef = useRef(null); const proxyPoolMap = new Map((proxyPools || []).map((pool) => [pool.id, pool])); const boundProxyPoolId = connection.providerSpecificData?.proxyPoolId || null; const boundProxyPool = boundProxyPoolId ? proxyPoolMap.get(boundProxyPoolId) : null; const hasLegacyProxy = connection.providerSpecificData?.connectionProxyEnabled === true && !!connection.providerSpecificData?.connectionProxyUrl; const hasAnyProxy = !!boundProxyPoolId || hasLegacyProxy; const proxyDisplayText = boundProxyPool ? `Pool: ${boundProxyPool.name}` : boundProxyPoolId ? `Pool: ${boundProxyPoolId} (inactive/missing)` : hasLegacyProxy ? `Legacy: ${connection.providerSpecificData?.connectionProxyUrl}` : ""; let maskedProxyUrl = ""; if (boundProxyPool?.proxyUrl || connection.providerSpecificData?.connectionProxyUrl) { const rawProxyUrl = boundProxyPool?.proxyUrl || connection.providerSpecificData?.connectionProxyUrl; try { const parsed = new URL(rawProxyUrl); maskedProxyUrl = `${parsed.protocol}//${parsed.hostname}${parsed.port ? `:${parsed.port}` : ""}`; } catch { maskedProxyUrl = rawProxyUrl; } } const noProxyText = boundProxyPool?.noProxy || connection.providerSpecificData?.connectionNoProxy || ""; let proxyBadgeVariant = "default"; if (boundProxyPool?.isActive === true) { proxyBadgeVariant = "success"; } else if (boundProxyPoolId || hasLegacyProxy) { proxyBadgeVariant = "error"; } // Close dropdown when clicking outside useEffect(() => { if (!showProxyDropdown) return; const handler = (e) => { if (proxyDropdownRef.current && !proxyDropdownRef.current.contains(e.target)) { setShowProxyDropdown(false); } }; document.addEventListener("mousedown", handler); return () => document.removeEventListener("mousedown", handler); }, [showProxyDropdown]); const handleSelectProxy = async (poolId) => { setUpdatingProxy(true); try { await onUpdateProxy(poolId === "__none__" ? null : poolId); } finally { setUpdatingProxy(false); setShowProxyDropdown(false); } }; const displayName = isOAuth ? connection.name || connection.email || connection.displayName || "OAuth Account" : connection.name; // Use useState + useEffect for impure Date.now() to avoid calling during render const [isCooldown, setIsCooldown] = useState(false); // Get earliest model lock timestamp (useEffect handles the Date.now() comparison) const modelLockUntil = Object.entries(connection) .filter(([k]) => k.startsWith("modelLock_")) .map(([, v]) => v) .filter(v => !!v) .sort()[0] || null; useEffect(() => { const checkCooldown = () => { const until = Object.entries(connection) .filter(([k]) => k.startsWith("modelLock_")) .map(([, v]) => v) .filter(v => v && new Date(v).getTime() > Date.now()) .sort()[0] || null; setIsCooldown(!!until); }; checkCooldown(); const interval = modelLockUntil ? setInterval(checkCooldown, 1000) : null; return () => { if (interval) clearInterval(interval); }; }, [modelLockUntil]); // Determine effective status (override unavailable if cooldown expired) const effectiveStatus = (connection.testStatus === "unavailable" && !isCooldown) ? "active" // Cooldown expired u2192 treat as active : connection.testStatus; const getStatusVariant = () => { if (connection.isActive === false) return "default"; if (effectiveStatus === "active" || effectiveStatus === "success") return "success"; if (effectiveStatus === "error" || effectiveStatus === "expired" || effectiveStatus === "unavailable") return "error"; return "default"; }; return (
{/* Priority arrows */}
{isOAuth ? "lock" : "key"}

{displayName}

{connection.isActive === false ? "disabled" : (effectiveStatus || "Unknown")} {hasAnyProxy && ( Proxy )} {isCooldown && connection.isActive !== false && } {connection.lastError && connection.isActive !== false && ( {connection.lastError} )} #{connection.priority} {connection.globalPriority && ( Auto: {connection.globalPriority} )}
{hasAnyProxy && (
{proxyDisplayText} {maskedProxyUrl && ( {maskedProxyUrl} )} {noProxyText && ( no_proxy: {noProxyText} )}
)}
{/* Proxy button with inline dropdown */} {(proxyPools || []).length > 0 && (
{showProxyDropdown && (
{(proxyPools || []).map((pool) => ( ))}
)}
)}
); } ConnectionRow.propTypes = { connection: PropTypes.shape({ id: PropTypes.string, name: PropTypes.string, email: PropTypes.string, displayName: PropTypes.string, modelLockUntil: PropTypes.string, testStatus: PropTypes.string, isActive: PropTypes.bool, lastError: PropTypes.string, priority: PropTypes.number, globalPriority: PropTypes.number, }).isRequired, proxyPools: PropTypes.arrayOf(PropTypes.shape({ id: PropTypes.string, name: PropTypes.string, proxyUrl: PropTypes.string, noProxy: PropTypes.string, isActive: PropTypes.bool, })), isOAuth: PropTypes.bool.isRequired, isFirst: PropTypes.bool.isRequired, isLast: PropTypes.bool.isRequired, onMoveUp: PropTypes.func.isRequired, onMoveDown: PropTypes.func.isRequired, onToggleActive: PropTypes.func.isRequired, onUpdateProxy: PropTypes.func, onEdit: PropTypes.func.isRequired, onDelete: PropTypes.func.isRequired, };