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:
parent
94c85e3a0e
commit
de918419fa
2 changed files with 176 additions and 31 deletions
|
|
@ -412,7 +412,10 @@ const {
|
|||
markMessagesAsRead,
|
||||
getUnreadCount,
|
||||
totalUnreadCount,
|
||||
getLatestMessageTimestamp
|
||||
getLatestMessageTimestamp,
|
||||
clearAllUnreadCounts,
|
||||
debugUnreadData,
|
||||
getUnreadData
|
||||
} = nostrChat
|
||||
|
||||
// Computed
|
||||
|
|
@ -602,6 +605,61 @@ const getPeerInitials = (peer: Peer) => {
|
|||
return peer.pubkey.slice(0, 2).toUpperCase()
|
||||
}
|
||||
|
||||
// Debug function to reset unread counts (can be called from browser console)
|
||||
const debugResetUnreadCounts = () => {
|
||||
console.log('🔧 Debug: Resetting all unread counts...')
|
||||
clearAllUnreadCounts()
|
||||
console.log('🔧 Debug: Unread counts reset. You may need to refresh the page to see the changes.')
|
||||
}
|
||||
|
||||
// Debug function to show unread count details for a specific peer
|
||||
const debugPeerUnreadCounts = (peerPubkey?: string) => {
|
||||
if (peerPubkey) {
|
||||
console.log(`🔧 Debug: Unread count details for peer ${peerPubkey}:`)
|
||||
debugUnreadData(peerPubkey)
|
||||
console.log(`Current unread count: ${getUnreadCount(peerPubkey)}`)
|
||||
|
||||
// Show timestamp details for debugging
|
||||
const peerMessages = messages.value.get(peerPubkey) || []
|
||||
const unreadData = getUnreadData(peerPubkey)
|
||||
console.log(`Last read timestamp: ${unreadData.lastReadTimestamp} (${new Date(unreadData.lastReadTimestamp * 1000).toLocaleString()})`)
|
||||
console.log(`Total messages: ${peerMessages.length}`)
|
||||
|
||||
// Show messages that would count as unread
|
||||
const unreadMessages = peerMessages.filter(msg => !msg.sent && msg.created_at > unreadData.lastReadTimestamp)
|
||||
console.log(`Messages that count as unread: ${unreadMessages.length}`)
|
||||
unreadMessages.forEach(msg => {
|
||||
console.log(` - ${msg.content.substring(0, 50)}... (${new Date(msg.created_at * 1000).toLocaleString()})`)
|
||||
})
|
||||
} else {
|
||||
console.log('🔧 Debug: All unread counts:')
|
||||
console.log('Total unread count:', totalUnreadCount.value)
|
||||
// Simplified peer iteration to avoid TypeScript issues
|
||||
const peerList = peers.value
|
||||
if (peerList && peerList.length > 0) {
|
||||
peerList.forEach((peer: any) => {
|
||||
const count = getUnreadCount(peer.pubkey)
|
||||
if (count > 0) {
|
||||
const name = peer.username || peer.pubkey.slice(0, 8)
|
||||
console.log(`${name}: ${count}`)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make debug functions available globally for browser console access
|
||||
if (typeof window !== 'undefined') {
|
||||
// Use type assertion to avoid TypeScript errors
|
||||
const globalWindow = window as any
|
||||
globalWindow.debugResetUnreadCounts = debugResetUnreadCounts
|
||||
globalWindow.debugPeerUnreadCounts = debugPeerUnreadCounts
|
||||
|
||||
console.log('🔧 Debug functions available:')
|
||||
console.log(' - debugResetUnreadCounts() - reset all unread counts')
|
||||
console.log(' - debugPeerUnreadCounts(peerPubkey?) - show unread count details')
|
||||
}
|
||||
|
||||
// Lifecycle
|
||||
onMounted(async () => {
|
||||
checkMobile()
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue