From d48cbbeec0188040d1b169b6573fe7c963ba0abf Mon Sep 17 00:00:00 2001 From: padreug Date: Fri, 8 Aug 2025 21:59:25 +0200 Subject: [PATCH] feat: Add peer notification subscriptions in Nostr chat - Implement a new method to subscribe to peers for notifications without loading full message history. - Enhance the ChatComponent to automatically subscribe to peers when the connection is established. - Update the useNostrChat composable to include the new subscription method and handle notification events. - Improve logging for subscription status and errors to aid in debugging. --- src/components/nostr/ChatComponent.vue | 44 +++++++++++++++++++ src/composables/useNostrChat.ts | 61 ++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) diff --git a/src/components/nostr/ChatComponent.vue b/src/components/nostr/ChatComponent.vue index b27ede6..e054709 100644 --- a/src/components/nostr/ChatComponent.vue +++ b/src/components/nostr/ChatComponent.vue @@ -450,6 +450,7 @@ const { connect, disconnect, subscribeToPeer, + subscribeToPeerForNotifications, sendMessage: sendNostrMessage, onMessageAdded, markMessagesAsRead, @@ -502,6 +503,9 @@ const loadPeers = async () => { })) console.log(`Loaded ${peers.value.length} peers`) + + // Note: Subscriptions will be handled by the isConnected watcher + } catch (parseError) { console.error('JSON Parse Error for peers:', parseError) console.error('Response was:', responseText) @@ -514,6 +518,38 @@ const loadPeers = async () => { } } +// Subscribe to all peers for notifications (without loading full message history) +const subscribeToAllPeers = async () => { + if (!peers.value.length) { + console.log('No peers to subscribe to') + return + } + + // Wait for connection to be established + if (!isConnected.value) { + console.log('Waiting for connection to be established before subscribing to peers') + // Wait a bit for connection to establish + await new Promise(resolve => setTimeout(resolve, 1000)) + + if (!isConnected.value) { + console.warn('Still not connected, skipping peer subscriptions') + return + } + } + + console.log(`Subscribing to ${peers.value.length} peers for notifications`) + + for (const peer of peers.value) { + try { + // Subscribe to peer for notifications only (don't load full history) + await subscribeToPeerForNotifications(peer.pubkey) + console.log(`Successfully subscribed to notifications for peer: ${peer.pubkey}`) + } catch (error) { + console.warn(`Failed to subscribe to peer ${peer.pubkey}:`, error) + } + } +} + const refreshPeers = () => { loadPeers() } @@ -619,6 +655,14 @@ onUnmounted(() => { disconnect() }) +// Watch for connection state changes and subscribe to peers when connected +watch(isConnected, async (connected) => { + if (connected && peers.value.length > 0) { + console.log('Connection established, subscribing to peers for notifications') + await subscribeToAllPeers() + } +}) + // Watch for new messages and scroll to bottom watch(currentMessages, (newMessages, oldMessages) => { console.log('Messages changed:', { diff --git a/src/composables/useNostrChat.ts b/src/composables/useNostrChat.ts index de795cb..23d677f 100644 --- a/src/composables/useNostrChat.ts +++ b/src/composables/useNostrChat.ts @@ -329,10 +329,70 @@ export function useNostrChat() { onevent(event) { console.log('Received live event:', event.id, 'author:', event.pubkey) handleIncomingMessage(event, peerPubkey) + }, + oneose() { + console.log('Subscription closed for peer:', peerPubkey) } } ) + + return sub + } + // Subscribe to a peer for notifications only (without loading full message history) + const subscribeToPeerForNotifications = async (peerPubkey: string) => { + if (!currentUser.value) { + console.warn('No user logged in - cannot subscribe to peer notifications') + return null + } + + // Check if we have a pool and are connected + if (!pool.value) { + console.warn('No pool available - initializing...') + initializePool() + } + + if (!isConnected.value) { + console.warn('Not connected to relays - attempting to connect...') + await connect() + } + + if (!pool.value) { + throw new Error('Failed to initialize Nostr pool') + } + + const myPubkey = currentUser.value.pubkey + + // Subscribe to new messages only (no historical messages) + const relayConfigs = getRelays() + console.log('Subscribing to notifications for peer:', peerPubkey, 'with my pubkey:', myPubkey) + + const sub = pool.value.subscribeMany( + relayConfigs.map(r => r.url), + [ + { + kinds: [4], + authors: [peerPubkey], + '#p': [myPubkey] + }, + { + kinds: [4], + authors: [myPubkey], + '#p': [peerPubkey] + } + ], + { + onevent(event) { + console.log('Received notification event:', event.id, 'author:', event.pubkey, 'for peer:', peerPubkey) + handleIncomingMessage(event, peerPubkey) + }, + oneose() { + console.log('Notification subscription closed for peer:', peerPubkey) + } + } + ) + + console.log('Successfully created notification subscription for peer:', peerPubkey) return sub } @@ -631,6 +691,7 @@ export function useNostrChat() { connect, disconnect, subscribeToPeer, + subscribeToPeerForNotifications, sendMessage, getMessages, clearMessages,