// components/RelayManagement.tsx import React, { useEffect, useState } from 'react'; import { View, Text, FlatList, TouchableOpacity, Modal, ActivityIndicator, TextInput, SafeAreaView, KeyboardAvoidingView, Platform } from 'react-native'; import { useRelayStore } from '@/lib/stores/relayStore'; import { Switch } from '@/components/ui/switch'; import { Button } from '@/components/ui/button'; import { X, RefreshCw, PlusCircle, AlertTriangle } from 'lucide-react-native'; import { RelayWithStatus } from '@/lib/db/services/RelayService'; interface RelayManagementProps { isVisible: boolean; onClose: () => void; } export default function RelayManagement({ isVisible, onClose }: RelayManagementProps) { const relays = useRelayStore(state => state.relays); const isLoading = useRelayStore(state => state.isLoading); const isSaving = useRelayStore(state => state.isSaving); const loadRelays = useRelayStore(state => state.loadRelays); const updateRelay = useRelayStore(state => state.updateRelay); const applyChanges = useRelayStore(state => state.applyChanges); const resetToDefaults = useRelayStore(state => state.resetToDefaults); const addRelay = useRelayStore(state => state.addRelay); const [newRelayUrl, setNewRelayUrl] = useState(''); const [showAddRelay, setShowAddRelay] = useState(false); const [confirmReset, setConfirmReset] = useState(false); const [hasUnappliedChanges, setHasUnappliedChanges] = useState(false); useEffect(() => { if (isVisible) { loadRelays(); } }, [isVisible]); // Track if there are unapplied changes const handleRelayUpdate = (url: string, changes: Partial) => { updateRelay(url, changes); setHasUnappliedChanges(true); }; // Handle applying changes const handleApplyChanges = async () => { const success = await applyChanges(); if (success) { setHasUnappliedChanges(false); // Success notification could be added here } }; // Add new relay const handleAddRelay = async () => { if (!newRelayUrl || !newRelayUrl.startsWith('wss://')) { alert('Please enter a valid relay URL starting with wss://'); return; } try { await addRelay(newRelayUrl); setNewRelayUrl(''); setShowAddRelay(false); setHasUnappliedChanges(true); } catch (error) { alert(`Failed to add relay: ${error instanceof Error ? error.message : String(error)}`); } }; // Reset to defaults with confirmation const handleResetToDefaults = async () => { if (confirmReset) { await resetToDefaults(); setConfirmReset(false); setHasUnappliedChanges(true); } else { setConfirmReset(true); // Auto-reset the confirmation after 3 seconds setTimeout(() => setConfirmReset(false), 3000); } }; // Status indicator color const getStatusColor = (status: string): string => { switch (status) { case 'connected': return '#10b981'; // Green case 'connecting': return '#f59e0b'; // Amber case 'error': case 'disconnected': return '#ef4444'; // Red default: return '#6b7280'; // Gray } }; // Render a relay item const renderRelayItem = ({ item }: { item: RelayWithStatus }) => ( {item.url} {item.status} Read handleRelayUpdate(item.url, { read: !item.read })} /> Write handleRelayUpdate(item.url, { write: !item.write })} /> ); // Main Render return ( {/* Header */} Relay Management {/* Content */} {isLoading ? ( Loading relays... ) : ( <> {/* Summary */} {relays.length} Relays ({relays.filter(r => r.status === 'connected').length} Connected) {/* Relay List */} {relays.length === 0 ? ( No relays configured ) : ( item.url} ListEmptyComponent={ No relays found } contentContainerStyle={{ paddingBottom: showAddRelay ? 180 : 100 }} /> )} {/* Add Relay Form */} {showAddRelay && ( Add New Relay )} )} {/* Footer */} ); }