import { useEffect, useState } from "react"; import { XMarkIcon, UserIcon, GlobeAltIcon, ComputerDesktopIcon } from "@heroicons/react/20/solid"; import { Button } from "./Button"; type RequestType = "session_approval" | "primary_control"; interface UnifiedSessionRequest { id: string; // sessionId or requestId type: RequestType; source: "local" | "cloud" | string; // Allow string for IP addresses identity?: string; nickname?: string; } interface UnifiedSessionRequestDialogProps { request: UnifiedSessionRequest | null; onApprove: (id: string) => void | Promise; onDeny: (id: string) => void | Promise; onDismiss?: () => void; onClose: () => void; } export default function UnifiedSessionRequestDialog({ request, onApprove, onDeny, onDismiss, onClose }: UnifiedSessionRequestDialogProps) { const [timeRemaining, setTimeRemaining] = useState(0); const [isProcessing, setIsProcessing] = useState(false); const [hasTimedOut, setHasTimedOut] = useState(false); useEffect(() => { if (!request) return; const isSessionApproval = request.type === "session_approval"; const initialTime = isSessionApproval ? 60 : 0; // 60s for session approval, no timeout for primary control setTimeRemaining(initialTime); setIsProcessing(false); setHasTimedOut(false); // Only start timer for session approval requests if (isSessionApproval) { const timer = setInterval(() => { setTimeRemaining(prev => { const newTime = prev - 1; if (newTime <= 0) { clearInterval(timer); setHasTimedOut(true); return 0; } return newTime; }); }, 1000); return () => clearInterval(timer); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [request?.id, request?.type]); // Only depend on stable properties to avoid unnecessary re-renders // Handle auto-deny when timeout occurs useEffect(() => { if (hasTimedOut && !isProcessing && request) { setIsProcessing(true); Promise.resolve(onDeny(request.id)) .catch(error => { console.error("Failed to auto-deny request:", error); }) .finally(() => { onClose(); }); } }, [hasTimedOut, isProcessing, request, onDeny, onClose]); if (!request) return null; const isSessionApproval = request.type === "session_approval"; const isPrimaryControl = request.type === "primary_control"; // Determine if source is cloud, local, or IP address const getSourceInfo = () => { if (request.source === "cloud") { return { type: "cloud", label: "Cloud Session", icon: GlobeAltIcon, iconColor: "text-blue-500" }; } else if (request.source === "local") { return { type: "local", label: "Local Session", icon: ComputerDesktopIcon, iconColor: "text-green-500" }; } else { // Assume it's an IP address or hostname return { type: "ip", label: request.source, icon: ComputerDesktopIcon, iconColor: "text-green-500" }; } }; const sourceInfo = getSourceInfo(); const getTitle = () => { if (isSessionApproval) return "New Session Request"; if (isPrimaryControl) return "Primary Control Request"; return "Session Request"; }; const getDescription = () => { if (isSessionApproval) return "A new session is attempting to connect to this device:"; if (isPrimaryControl) return "A user is requesting primary control of this session:"; return "A user is making a request:"; }; return (

{getTitle()}

{getDescription()}

{/* Session type - always show with icon for both session approval and primary control */}
{sourceInfo.type === "cloud" ? "Cloud Session" : sourceInfo.type === "local" ? "Local Session" : `Local Session`} {sourceInfo.type === "ip" && ( ({sourceInfo.label}) )}
{/* Nickname - always show with icon for consistency */} {request.nickname && (
Nickname:{" "} {request.nickname}
)} {/* Identity/User */} {request.identity && (
{isSessionApproval ? (

Identity: {request.identity}

) : (

User:{" "} {request.identity}

)}
)}
{/* Security Note - only for session approval */} {isSessionApproval && (

Security Note: Only approve sessions you recognize. Approved sessions will have observer access and can request primary control.

)} {/* Auto-deny timer - only for session approval */} {isSessionApproval && (

Auto-deny in {timeRemaining} seconds

)}
{onDismiss && (
); }