diff --git a/src/components/ConnectionStatus.vue b/src/components/ConnectionStatus.vue index 6d76609..96faa89 100644 --- a/src/components/ConnectionStatus.vue +++ b/src/components/ConnectionStatus.vue @@ -1,21 +1,122 @@ \ No newline at end of file + + + \ No newline at end of file diff --git a/src/stores/nostr.ts b/src/stores/nostr.ts index 026dca8..d4f1f0a 100644 --- a/src/stores/nostr.ts +++ b/src/stores/nostr.ts @@ -50,6 +50,10 @@ async function withTimeout(promise: Promise, timeoutMs: number = 10000): P // Add to state const connectionStatus = ref<'connected' | 'connecting' | 'disconnected'>('disconnected') +const hasUnreadMessages = ref(false) +const viewedMessageIds = ref>(new Set( + JSON.parse(localStorage.getItem('nostr_viewed_messages') || '[]') +)) // Update in connect function async function connectToRelay(url: string) { @@ -224,6 +228,10 @@ export const useNostrStore = defineStore('nostr', () => { activeChat.value = null localStorage.removeItem('nostr_messages') localStorage.removeItem('nostr_account') + hasUnreadMessages.value = false + localStorage.removeItem('nostr_unread_messages') + viewedMessageIds.value.clear() + localStorage.removeItem('nostr_viewed_messages') } const addMessage = async (pubkey: string, message: DirectMessage) => { @@ -232,25 +240,28 @@ export const useNostrStore = defineStore('nostr', () => { return } - // Add message ID to processed set processedMessageIds.value.add(message.id) - - // Add message to the map const userMessages = messages.value.get(pubkey) || [] - // Check for duplicates by content and timestamp (backup check) + // Check for duplicates const isDuplicate = userMessages.some(msg => msg.content === message.content && Math.abs(msg.created_at - message.created_at) < 1 ) if (!isDuplicate) { - messages.value.set(pubkey, [...userMessages, message]) + messages.value.set(pubkey, [...userMessages, message].sort((a, b) => + a.created_at - b.created_at + )) - // Sort messages by timestamp - const sortedMessages = messages.value.get(pubkey) || [] - sortedMessages.sort((a, b) => a.created_at - b.created_at) - messages.value.set(pubkey, sortedMessages) + // Only set unread if: + // 1. Message came from websocket (not storage) + // 2. Not from current chat + // 3. Not sent by us + if (!message.fromStorage && pubkey !== activeChat.value && !message.sent) { + console.log('New unread message received:', { pubkey, messageId: message.id }) + hasUnreadMessages.value = true + } } } @@ -340,11 +351,11 @@ export const useNostrStore = defineStore('nostr', () => { pubkey: event.pubkey, content: decrypted, created_at: event.created_at, - sent: false + sent: false, + fromStorage: false // Mark as not from storage } await addMessage(event.pubkey, dm) - processedMessageIds.value.add(event.id) } catch (err) { console.error('Failed to decrypt received message:', err) } @@ -374,7 +385,6 @@ export const useNostrStore = defineStore('nostr', () => { } await addMessage(targetPubkey, dm) - processedMessageIds.value.add(event.id) } catch (err) { console.error('Failed to decrypt sent message:', err) } @@ -564,6 +574,30 @@ export const useNostrStore = defineStore('nostr', () => { window.addEventListener('focus', handleVisibilityChange) } + // Add function to clear unread state + function clearUnreadMessages() { + hasUnreadMessages.value = false + localStorage.setItem('nostr_unread_messages', 'false') + + // Mark all current chat messages as viewed + if (activeChat.value) { + const chatMessages = messages.value.get(activeChat.value) || [] + chatMessages.forEach(msg => { + viewedMessageIds.value.add(msg.id) + }) + // Persist viewed message IDs + localStorage.setItem('nostr_viewed_messages', + JSON.stringify(Array.from(viewedMessageIds.value)) + ) + } + } + + // Add to watch section + watch(activeChat, () => { + // Clear unread messages when changing to a chat + clearUnreadMessages() + }) + return { account, profiles, @@ -580,5 +614,7 @@ export const useNostrStore = defineStore('nostr', () => { loadProfiles, connectionStatus, hasActiveSubscription, + hasUnreadMessages, + clearUnreadMessages, } }) \ No newline at end of file diff --git a/src/types/nostr.ts b/src/types/nostr.ts index b34905c..091392d 100644 --- a/src/types/nostr.ts +++ b/src/types/nostr.ts @@ -34,4 +34,5 @@ export interface DirectMessage { content: string created_at: number sent: boolean + fromStorage?: boolean } \ No newline at end of file