diff --git a/src/components/ReqViewer.tsx b/src/components/ReqViewer.tsx index 7fb09f3..91a6d79 100644 --- a/src/components/ReqViewer.tsx +++ b/src/components/ReqViewer.tsx @@ -16,6 +16,9 @@ import { Loader2, Mail, Send, + Inbox, + Sparkles, + Link as LinkIcon, } from "lucide-react"; import { Virtuoso } from "react-virtuoso"; import { useReqTimelineEnhanced } from "@/hooks/useReqTimelineEnhanced"; @@ -1016,6 +1019,41 @@ export default function ReqViewer({ // Find NIP-65 info for this relay (if using outbox) const nip65Info = reasoning?.find((r) => r.relay === url); + // Determine relay type + const relayType = relays + ? "explicit" // Explicitly specified relays + : nip65Info && !nip65Info.isFallback + ? "outbox" // NIP-65 outbox relay + : "fallback"; // Fallback relay + + // Type indicator icon + const typeIcon = { + explicit: ( + + + + + Explicit relay + + ), + outbox: ( + + + + + NIP-65 Outbox relay + + ), + fallback: ( + + + + + Fallback relay + + ), + }[relayType]; + return (
+ {/* Relay type indicator */} + {typeIcon} + {/* Event count */} {reqState && reqState.eventCount > 0 && ( @@ -1087,13 +1128,6 @@ export default function ReqViewer({ )} - {/* Fallback indicator */} - {nip65Info && nip65Info.isFallback && ( - - fallback - - )} - {/* Auth icon */} {authIcon && ( diff --git a/src/hooks/useReqTimelineEnhanced.ts b/src/hooks/useReqTimelineEnhanced.ts index 33eac05..c6fe80e 100644 --- a/src/hooks/useReqTimelineEnhanced.ts +++ b/src/hooks/useReqTimelineEnhanced.ts @@ -98,29 +98,58 @@ export function useReqTimelineEnhanced( // Sync connection states from RelayStateManager // This runs whenever globalRelayStates updates useEffect(() => { + if (relays.length === 0) return; + setRelayStates((prev) => { const next = new Map(prev); let changed = false; - for (const [url, state] of prev) { + // Sync state for all relays in our query + for (const url of relays) { const globalState = globalRelayStates[url]; - if ( - globalState && - globalState.connectionState !== state.connectionState - ) { + const currentState = prev.get(url); + + // Initialize if relay not in map yet (shouldn't happen, but defensive) + if (!currentState) { next.set(url, { - ...state, + url, + connectionState: globalState?.connectionState || "pending", + subscriptionState: "waiting", + eventCount: 0, + connectedAt: globalState?.lastConnected, + disconnectedAt: globalState?.lastDisconnected, + }); + changed = true; + console.log( + "REQ Enhanced: Initialized missing relay state", + url, + globalState?.connectionState, + ); + } else if ( + globalState && + globalState.connectionState !== currentState.connectionState + ) { + // Update connection state if changed + next.set(url, { + ...currentState, connectionState: globalState.connectionState as any, connectedAt: globalState.lastConnected, disconnectedAt: globalState.lastDisconnected, }); changed = true; + console.log( + "REQ Enhanced: Connection state changed", + url, + currentState.connectionState, + "→", + globalState.connectionState, + ); } } return changed ? next : prev; }); - }, [globalRelayStates]); + }, [globalRelayStates, relays]); // Subscribe to events useEffect(() => { @@ -208,17 +237,34 @@ export function useReqTimelineEnhanced( if (relayUrl) { setRelayStates((prev) => { const state = prev.get(relayUrl); - if (!state) return prev; - const now = Date.now(); const next = new Map(prev); - next.set(relayUrl, { - ...state, - subscriptionState: "receiving", - eventCount: state.eventCount + 1, - firstEventAt: state.firstEventAt ?? now, - lastEventAt: now, - }); + + if (!state) { + // Relay not in map - initialize it (defensive) + console.warn( + "REQ Enhanced: Event from unknown relay, initializing", + relayUrl, + ); + next.set(relayUrl, { + url: relayUrl, + connectionState: "connected", + subscriptionState: "receiving", + eventCount: 1, + firstEventAt: now, + lastEventAt: now, + }); + } else { + // Update existing relay state + next.set(relayUrl, { + ...state, + subscriptionState: "receiving", + eventCount: state.eventCount + 1, + firstEventAt: state.firstEventAt ?? now, + lastEventAt: now, + }); + } + return next; }); }