import React, { useState, useEffect, useRef } from 'react'; import { PlexConnectionSettings, PlexServerConnection, PlexLibrary } from '../types'; import { apiService } from '../services/api'; import { X, Server, Lock, User, Key, Globe, Eye, EyeOff, CheckCircle, Library, ChevronDown, ChevronRight, Settings, Loader2 } from 'lucide-react'; interface ConnectionModalProps { isOpen: boolean; onClose: () => void; onConnectSuccess: (serverInfo: PlexServerConnection) => void; onShowMessage: (message: string) => void; } const ConnectionModal: React.FC = ({ isOpen, onClose, onConnectSuccess, onShowMessage }) => { const [formData, setFormData] = useState({ protocol: 'http', address: '', port: '32400', token: '', username: '', password: '', timeout: 9 }); const [isConnecting, setIsConnecting] = useState(false); const [error, setError] = useState(null); const [showPassword, setShowPassword] = useState(false); const [showAdvanced, setShowAdvanced] = useState(false); // Post-connection state const [connectedServerInfo, setConnectedServerInfo] = useState(null); const [libraries, setLibraries] = useState([]); const [selectedLibraryId, setSelectedLibraryId] = useState(''); const abortControllerRef = useRef(null); // Reset state when opening useEffect(() => { if (isOpen) { setError(null); setConnectedServerInfo(null); setLibraries([]); setSelectedLibraryId(''); } return () => { // Cleanup any pending request if modal closes if (abortControllerRef.current) { abortControllerRef.current.abort(); } }; }, [isOpen]); if (!isOpen) return null; const handleChange = (e: React.ChangeEvent) => { const { name, value } = e.target; setFormData(prev => ({ ...prev, [name]: value })); }; const handleTimeoutChange = (e: React.ChangeEvent) => { const val = parseInt(e.target.value) || 0; setFormData(prev => ({ ...prev, timeout: val })); }; const handleLibraryChange = (e: React.ChangeEvent) => { const newId = e.target.value; setSelectedLibraryId(newId); const lib = libraries.find(l => l.id === newId); if (lib && connectedServerInfo) { const updatedInfo = { ...connectedServerInfo, libraryName: lib.title }; setConnectedServerInfo(updatedInfo); onConnectSuccess(updatedInfo); onShowMessage(`Library switched to ${lib.title}`); } }; const isTokenProvided = formData.token.trim().length > 0; const disabledInputClass = isTokenProvided ? "bg-gray-700/50 text-gray-500 line-through decoration-gray-500 cursor-not-allowed border-gray-700" : "bg-gray-800 text-gray-100 border-gray-600 focus:border-plex-orange focus:ring-1 focus:ring-plex-orange"; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); // If already connecting, this acts as Cancel if (isConnecting) { if (abortControllerRef.current) { abortControllerRef.current.abort(); abortControllerRef.current = null; setIsConnecting(false); setError("Connection cancelled by user."); } return; } setError(null); setIsConnecting(true); const abortController = new AbortController(); abortControllerRef.current = abortController; const result = await apiService.connectToPlex(formData, abortController.signal); // Only proceed if we weren't aborted/cancelled (though apiService handles error msg) if (abortController.signal.aborted) return; setIsConnecting(false); abortControllerRef.current = null; if (result.status === 'success' && result.data) { setFormData(prev => ({ ...prev, token: result.data.token, username: '', password: '' })); const info = result.data.serverInfo; setConnectedServerInfo(info); onShowMessage(`Successfully connected to ${info.name || 'Plex Server'}`); const libs = info.libraries || []; setLibraries(libs); if (libs.length > 0) { const defaultLib = libs[0]; setSelectedLibraryId(defaultLib.id); onConnectSuccess({ ...info, libraryName: defaultLib.title }); } else { onConnectSuccess(info); } } else { setError(result.message || "Connection failed"); } }; const isConnected = !!connectedServerInfo; return (
{/* Header */}

{isConnected ? 'Server Connected' : 'Connect Plex Server'}

{/* Body */}
{error && (
{error}
)} {/* Server Connection */}
{/* Authentication */}
{/* Token */}
{!isConnected && ( <>
— OR —
{/* Username */}
{/* Password */}
)}
{/* Advanced Options */} {!isConnected && (
{showAdvanced && (
)}
)} {!isConnected ? ( ) : (

Connected Successfully

)} {/* Library Selection - Appears after connection */} {isConnected && libraries.length > 0 && (
)}
); }; export default ConnectionModal;