From db2df8014d0cf517b8f34c89c80d43d4da08a9b6 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 12 Jan 2026 22:02:23 +0000 Subject: [PATCH] feat: show DM relays in NIP-17 chat RelaysDropdown - Added dmRelays field to ConversationMetadata type - NIP-17 adapter now includes combined relays from both participants - RelaysDropdown checks for dmRelays in addition to liveActivity/relayUrl --- src/components/chat/RelaysDropdown.tsx | 10 +++++++--- src/lib/chat/adapters/nip-17-adapter.ts | 6 +++++- src/types/chat.ts | 1 + 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/components/chat/RelaysDropdown.tsx b/src/components/chat/RelaysDropdown.tsx index b6c0927..4565540 100644 --- a/src/components/chat/RelaysDropdown.tsx +++ b/src/components/chat/RelaysDropdown.tsx @@ -22,13 +22,17 @@ export function RelaysDropdown({ conversation }: RelaysDropdownProps) { const { relays: relayStates } = useRelayState(); // Get relays for this conversation (immutable pattern) + // Priority: liveActivity relays > dmRelays > single relayUrl const liveActivityRelays = conversation.metadata?.liveActivity?.relays; + const dmRelays = conversation.metadata?.dmRelays; const relays: string[] = Array.isArray(liveActivityRelays) && liveActivityRelays.length > 0 ? liveActivityRelays - : conversation.metadata?.relayUrl - ? [conversation.metadata.relayUrl] - : []; + : Array.isArray(dmRelays) && dmRelays.length > 0 + ? dmRelays + : conversation.metadata?.relayUrl + ? [conversation.metadata.relayUrl] + : []; // Pre-compute normalized URLs and state lookups in a single pass (O(n)) const relayData = relays.map((url) => { diff --git a/src/lib/chat/adapters/nip-17-adapter.ts b/src/lib/chat/adapters/nip-17-adapter.ts index 165c333..27cafd5 100644 --- a/src/lib/chat/adapters/nip-17-adapter.ts +++ b/src/lib/chat/adapters/nip-17-adapter.ts @@ -163,11 +163,14 @@ export class Nip17Adapter extends ChatProtocolAdapter { // Fetch DM relays for both parties in parallel // (for self-chat, this fetches the same relays twice but that's fine) - await Promise.all([ + const [ownRelays, partnerRelays] = await Promise.all([ this.fetchDmRelays(activePubkey), this.fetchDmRelays(partnerPubkey), ]); + // Combine and deduplicate relays from both parties + const allRelays = [...new Set([...ownRelays, ...partnerRelays])]; + // Get display name for partner (the person we're chatting with) const metadataEvent = await this.getMetadata(partnerPubkey); const metadata = metadataEvent @@ -187,6 +190,7 @@ export class Nip17Adapter extends ChatProtocolAdapter { metadata: { encrypted: true, giftWrapped: true, + dmRelays: allRelays, }, unreadCount: 0, }; diff --git a/src/types/chat.ts b/src/types/chat.ts index 6d77c7f..15f67c0 100644 --- a/src/types/chat.ts +++ b/src/types/chat.ts @@ -64,6 +64,7 @@ export interface ConversationMetadata { // NIP-17 DM encrypted?: boolean; giftWrapped?: boolean; + dmRelays?: string[]; // DM inbox relays for the conversation } /**