fix: resolve duplicate notifications in notification center

Use compareEvents (which considers both created_at and id) instead of
simple created_at comparison for sorting events in timeline subscription
and load-more logic. This ensures consistent ordering with mergeTimelines
and handleNewEvent deduplication, preventing duplicates when events share
the same timestamp. Also add Set-based dedup in notification list memo
as an additional safety net.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
codytseng 2026-02-26 22:34:39 +08:00
parent d361ac60ab
commit da751fd73c
2 changed files with 11 additions and 5 deletions

View file

@ -213,7 +213,13 @@ const NotificationList = forwardRef((_, ref) => {
}, [timelineKey, until, pubkey, setEvents, setUntil])
const notifications = useMemo(() => {
const filteredEvents = events.filter((evt) => evt.pubkey !== pubkey)
const idSet = new Set<string>()
const filteredEvents = events.filter((evt) => {
if (evt.pubkey === pubkey) return false
if (idSet.has(evt.id)) return false
idSet.add(evt.id)
return true
})
if (storedEvents.length === 0) return filteredEvents
const filteredStoredEvents = storedEvents.filter((evt) => evt.pubkey !== pubkey)

View file

@ -408,7 +408,7 @@ class ClientService extends EventTarget {
events.push(evt)
})
})
return events.sort((a, b) => b.created_at - a.created_at).slice(0, limit)
return events.sort((a, b) => compareEvents(b, a)).slice(0, limit)
}
subscribe(
@ -655,11 +655,11 @@ class ClientService extends EventTarget {
return onEvents([...events], !!eosedAt)
}
if (!eosed) {
events = events.sort((a, b) => b.created_at - a.created_at).slice(0, filter.limit)
events = events.sort((a, b) => compareEvents(b, a)).slice(0, filter.limit)
return onEvents([...events.concat(cachedEvents).slice(0, filter.limit)], false)
}
events = events.sort((a, b) => b.created_at - a.created_at).slice(0, filter.limit)
events = events.sort((a, b) => compareEvents(b, a)).slice(0, filter.limit)
if (needSaveToDb) {
indexedDb.putEvents(
events.map((evt) => ({ event: evt, relays: this.getEventHints(evt.id) }))
@ -732,7 +732,7 @@ class ClientService extends EventTarget {
events.forEach((evt) => {
this.addEventToCache(evt)
})
events = events.sort((a, b) => b.created_at - a.created_at).slice(0, limit)
events = events.sort((a, b) => compareEvents(b, a)).slice(0, limit)
// Prevent concurrent requests from duplicating the same event
const lastRefCreatedAt = refs.length > 0 ? refs[refs.length - 1][1] : dayjs().unix()