feat: Enhance Nostr chat debugging and unread message management

- Introduce debug functions in ChatComponent for resetting unread counts and displaying unread message details for specific peers, improving troubleshooting capabilities.
- Update unread count management in useNostrChat to ensure accurate tracking and storage of unread messages, including recalculating counts based on message timestamps.
- Implement logic to prevent duplicate message processing and enhance overall message handling efficiency.
This commit is contained in:
padreug 2025-08-10 17:18:36 +02:00
parent 94c85e3a0e
commit de918419fa
2 changed files with 176 additions and 31 deletions

View file

@ -189,43 +189,88 @@ export function useNostrChat() {
// Update unread count for a peer
const updateUnreadCount = (peerPubkey: string, count: number): void => {
const current = unreadCounts.value.get(peerPubkey) || 0
unreadCounts.value.set(peerPubkey, current + count)
if (count > 0) {
unreadCounts.value.set(peerPubkey, count)
} else {
unreadCounts.value.delete(peerPubkey)
}
// Force reactivity
unreadCounts.value = new Map(unreadCounts.value)
// Save to localStorage
const unreadData = getUnreadData(peerPubkey)
unreadData.unreadCount = current + count
unreadData.unreadCount = count
saveUnreadData(peerPubkey, unreadData)
}
// Mark messages as read for a peer
const markMessagesAsRead = (peerPubkey: string): void => {
const current = unreadCounts.value.get(peerPubkey) || 0
if (current > 0) {
unreadCounts.value.set(peerPubkey, 0)
// Save to localStorage
const unreadData = getUnreadData(peerPubkey)
unreadData.unreadCount = 0
unreadData.lastReadTimestamp = Date.now()
saveUnreadData(peerPubkey, unreadData)
const currentTimestamp = Math.floor(Date.now() / 1000)
// Update last read timestamp, reset unread count, and clear processed message IDs
const updatedData: UnreadMessageData = {
lastReadTimestamp: currentTimestamp,
unreadCount: 0,
processedMessageIds: new Set() // Clear processed messages when marking as read
}
saveUnreadData(peerPubkey, updatedData)
updateUnreadCount(peerPubkey, 0)
// Also clear any processed message IDs from the global set that might be from this peer
// This helps prevent duplicate message issues
console.log(`Marked messages as read for peer: ${peerPubkey}`)
}
// Load unread counts from localStorage
// const loadUnreadCounts = (): void => {
// try {
// // Load unread counts for all peers we have messages for
// for (const [peerPubkey] of messages.value) {
// const unreadData = getUnreadData(peerPubkey)
// if (unreadData.unreadCount > 0) {
// unreadCounts.value.set(peerPubkey, unreadData.unreadCount)
// }
// }
// } catch (error) {
// console.warn('Failed to load unread counts:', error)
// }
// }
const loadUnreadCounts = (): void => {
try {
const keys = Object.keys(localStorage).filter(key =>
key.startsWith(`${UNREAD_MESSAGES_KEY}-`)
)
console.log('Loading unread counts from localStorage. Found keys:', keys)
for (const key of keys) {
const peerPubkey = key.replace(`${UNREAD_MESSAGES_KEY}-`, '')
const unreadData = getUnreadData(peerPubkey)
// Recalculate unread count based on actual messages and lastReadTimestamp
const peerMessages = messages.value.get(peerPubkey) || []
let actualUnreadCount = 0
for (const message of peerMessages) {
// Only count messages not sent by us and created after last read timestamp
if (!message.sent && message.created_at > unreadData.lastReadTimestamp) {
actualUnreadCount++
}
}
// Update the stored count to match reality
if (actualUnreadCount !== unreadData.unreadCount) {
console.log(`Correcting unread count for peer ${peerPubkey}: stored=${unreadData.unreadCount}, actual=${actualUnreadCount}`)
unreadData.unreadCount = actualUnreadCount
saveUnreadData(peerPubkey, unreadData)
}
console.log(`Peer ${peerPubkey}:`, {
lastReadTimestamp: unreadData.lastReadTimestamp,
unreadCount: unreadData.unreadCount,
processedMessageIdsCount: unreadData.processedMessageIds.size,
messageCount: peerMessages.length
})
if (actualUnreadCount > 0) {
unreadCounts.value.set(peerPubkey, actualUnreadCount)
}
}
} catch (error) {
console.warn('Failed to load unread counts:', error)
}
}
// Initialize unread counts on startup
loadUnreadCounts()
// Clear unread count for a peer
// const clearUnreadCount = (peerPubkey: string): void => {
@ -247,6 +292,22 @@ export function useNostrChat() {
unreadData.unreadCount = 0
saveUnreadData(peerPubkey, unreadData)
}
// Also clear from localStorage for all stored keys
try {
const keys = Object.keys(localStorage).filter(key =>
key.startsWith(`${UNREAD_MESSAGES_KEY}-`)
)
for (const key of keys) {
const peerPubkey = key.replace(`${UNREAD_MESSAGES_KEY}-`, '')
const unreadData = getUnreadData(peerPubkey)
unreadData.unreadCount = 0
saveUnreadData(peerPubkey, unreadData)
}
} catch (error) {
console.warn('Failed to clear unread counts from localStorage:', error)
}
}
// Clear processed message IDs for a peer
@ -509,6 +570,12 @@ export function useNostrChat() {
return
}
// Check if we've already processed this message to prevent duplicates
if (processedMessageIds.value.has(event.id)) {
console.log('Message already processed, skipping:', event.id)
return
}
try {
// For NIP-04 direct messages, always use peerPubkey as the second argument
// This is the public key of the other party in the conversation
@ -550,17 +617,36 @@ export function useNostrChat() {
}
messages.value.get(peerPubkey)!.push(message)
// Mark as unread if not sent by us
// Mark as unread if not sent by us AND created after last read timestamp
if (!isSentByMe) {
// For now, just update the unread count
// TODO: Implement proper unread message tracking
const currentCount = unreadCounts.value.get(peerPubkey) || 0
updateUnreadCount(peerPubkey, currentCount + 1)
const unreadData = getUnreadData(peerPubkey)
// Only count as unread if message was created after last read timestamp
if (event.created_at > unreadData.lastReadTimestamp) {
// Increment the unread count for this peer
const currentCount = unreadCounts.value.get(peerPubkey) || 0
const newCount = currentCount + 1
unreadCounts.value.set(peerPubkey, newCount)
// Force reactivity
unreadCounts.value = new Map(unreadCounts.value)
// Save to localStorage
unreadData.unreadCount = newCount
saveUnreadData(peerPubkey, unreadData)
console.log(`Message marked as unread for peer ${peerPubkey}. Count: ${newCount}`)
} else {
console.log(`Message not marked as unread (created before last read): ${event.created_at} <= ${unreadData.lastReadTimestamp}`)
}
}
// Update latest message timestamp
updateLatestMessageTimestamp(peerPubkey, event.created_at)
// Mark this message as processed to prevent duplicates
processedMessageIds.value.add(event.id)
// Trigger callback if set
if (onMessageAdded.value) {
onMessageAdded.value(peerPubkey)
@ -813,6 +899,7 @@ export function useNostrChat() {
clearAllUnreadCounts,
clearProcessedMessageIds,
debugUnreadData,
getUnreadData,
// Timestamp methods (for sorting)
getLatestMessageTimestamp,