mirror of
https://github.com/hoornet/vega.git
synced 2026-05-13 21:28:36 -07:00
Dedup kind 3 follower notifications by pubkey
Kind 3 events are replaceable — the same follower generates a new event ID on every contact list update. Dedup by pubkey on load and merge to prevent the notifications list from filling with repeats.
This commit is contained in:
@@ -49,6 +49,24 @@ function migrateLegacyReadIds(): Set<string> {
|
|||||||
return new Set();
|
return new Set();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Dedup kind 3 (follower) events — keep only the newest per pubkey. */
|
||||||
|
function dedupFollowers(events: NDKEvent[]): NDKEvent[] {
|
||||||
|
const seenFollowers = new Map<string, NDKEvent>();
|
||||||
|
const result: NDKEvent[] = [];
|
||||||
|
for (const e of events) {
|
||||||
|
if (e.kind === 3) {
|
||||||
|
const existing = seenFollowers.get(e.pubkey);
|
||||||
|
if (!existing || (e.created_at ?? 0) > (existing.created_at ?? 0)) {
|
||||||
|
seenFollowers.set(e.pubkey, e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.push(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.push(...seenFollowers.values());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
export const useNotificationsStore = create<NotificationsState>((set, get) => ({
|
export const useNotificationsStore = create<NotificationsState>((set, get) => ({
|
||||||
notifications: [],
|
notifications: [],
|
||||||
unreadCount: 0,
|
unreadCount: 0,
|
||||||
@@ -83,9 +101,12 @@ export const useNotificationsStore = create<NotificationsState>((set, get) => ({
|
|||||||
} catch { /* skip malformed */ }
|
} catch { /* skip malformed */ }
|
||||||
}
|
}
|
||||||
|
|
||||||
const unreadCount = events.filter((e) => !readIds.has(e.id!)).length;
|
// Dedup kind 3 (follower) events by pubkey — keep only newest per person
|
||||||
debug.log("notif:db loaded", events.length, "notifications,", unreadCount, "unread");
|
const dedupedEvents = dedupFollowers(events);
|
||||||
set({ notifications: events, readIds, unreadCount, loading: false });
|
|
||||||
|
const unreadCount = dedupedEvents.filter((e) => !readIds.has(e.id!)).length;
|
||||||
|
debug.log("notif:db loaded", dedupedEvents.length, "notifications,", unreadCount, "unread");
|
||||||
|
set({ notifications: dedupedEvents, readIds, unreadCount, loading: false });
|
||||||
|
|
||||||
// Clear legacy localStorage read IDs now that DB is the source of truth
|
// Clear legacy localStorage read IDs now that DB is the source of truth
|
||||||
localStorage.removeItem(LEGACY_READ_KEY);
|
localStorage.removeItem(LEGACY_READ_KEY);
|
||||||
@@ -130,8 +151,8 @@ export const useNotificationsStore = create<NotificationsState>((set, get) => ({
|
|||||||
debug.log("notif:db saved", newEvents.length, "new mentions");
|
debug.log("notif:db saved", newEvents.length, "new mentions");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Combine, sort, cap
|
// Combine, dedup followers, sort, cap
|
||||||
const merged = [...existing, ...newEvents]
|
const merged = dedupFollowers([...existing, ...newEvents])
|
||||||
.sort((a, b) => (b.created_at ?? 0) - (a.created_at ?? 0))
|
.sort((a, b) => (b.created_at ?? 0) - (a.created_at ?? 0))
|
||||||
.slice(0, MAX_NOTIFICATIONS);
|
.slice(0, MAX_NOTIFICATIONS);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user