fix: improve relay state tracking and add relay type indicators

State Tracking Fixes:
- Sync connection state for ALL relays in query, not just initialized ones
- Defensively initialize missing relay states during sync
- Handle events from unknown relays (defensive initialization)
- Add debug console logs to track state transitions

Relay Type Indicators:
- Explicit relays: Blue link icon (relays specified directly)
- Outbox relays: Purple sparkles (NIP-65 selected)
- Fallback relays: Gray inbox icon (fallback when outbox incomplete)
- Each type has tooltip explaining source

This should fix:
- "0/4 relays but events coming in" bug
- "Stuck in LOADING" when events are arriving
- Missing visibility for relay source types

Tests: 634/634 passing
This commit is contained in:
Claude
2025-12-22 16:36:56 +00:00
parent c9bf2fe599
commit 70651ae29f
2 changed files with 103 additions and 23 deletions

View File

@@ -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: (
<Tooltip>
<TooltipTrigger asChild>
<LinkIcon className="size-3 text-blue-500" />
</TooltipTrigger>
<TooltipContent>Explicit relay</TooltipContent>
</Tooltip>
),
outbox: (
<Tooltip>
<TooltipTrigger asChild>
<Sparkles className="size-3 text-purple-500" />
</TooltipTrigger>
<TooltipContent>NIP-65 Outbox relay</TooltipContent>
</Tooltip>
),
fallback: (
<Tooltip>
<TooltipTrigger asChild>
<Inbox className="size-3 text-muted-foreground/60" />
</TooltipTrigger>
<TooltipContent>Fallback relay</TooltipContent>
</Tooltip>
),
}[relayType];
return (
<div
key={url}
@@ -1027,6 +1065,9 @@ export default function ReqViewer({
className="flex-1 truncate font-mono text-foreground/80"
/>
<div className="flex items-center gap-1.5 flex-shrink-0 text-muted-foreground">
{/* Relay type indicator */}
{typeIcon}
{/* Event count */}
{reqState && reqState.eventCount > 0 && (
<Tooltip>
@@ -1087,13 +1128,6 @@ export default function ReqViewer({
</Tooltip>
)}
{/* Fallback indicator */}
{nip65Info && nip65Info.isFallback && (
<span className="text-[10px] text-muted-foreground/60">
fallback
</span>
)}
{/* Auth icon */}
{authIcon && (
<Tooltip>