mirror of
https://github.com/Luchexx/wacrm.git
synced 2026-11-02 17:29:45 +00:00
fix(inbox): clear unread badge instantly when opening a conversation
The badge used to linger for the duration of the click → unread-reset effect → server UPDATE → realtime UPDATE → setState round-trip — long enough to be noticeable, and visible indefinitely if the realtime UPDATE was ever dropped. There was also a brief flicker when a customer sent a new message while the user was already viewing the thread: the webhook bumps unread_count on the server, the realtime UPDATE arrives at the client and overwrites the local 0 with a positive value for the ~100ms it takes the reset effect's server UPDATE to round-trip back. Fix in two places: 1. handleSelectConversation (and the deep-link auto-select path) optimistically zero the list copy's unread_count immediately. We deliberately do *not* touch activeConversation.unread_count — the reset effect inside MessageThread keys off that value to decide whether to fire the server UPDATE, so zeroing it locally would silently skip the persist. 2. handleConversationEvent UPDATE suppresses the incoming unread_count for the currently-active conv. Non-active convs take the value as-is; the active one stays at 0 until the user navigates away. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
3de2da6cca
commit
4e3bb707d2
@ -235,8 +235,22 @@ export default function InboxPage() {
|
||||
|
||||
if (event.eventType === "UPDATE") {
|
||||
if (knownConvIdsRef.current.has(conv.id)) {
|
||||
// If this UPDATE is for the conv the user is currently viewing,
|
||||
// suppress the incoming unread_count — the user is reading it
|
||||
// RIGHT NOW, so any positive value would just flicker the badge
|
||||
// back on for the ~100ms it takes for the reset effect's server
|
||||
// UPDATE to round-trip. Non-active convs take the value as-is.
|
||||
const isActive = activeConversation?.id === conv.id;
|
||||
setConversations((prev) =>
|
||||
prev.map((c) => (c.id === conv.id ? { ...c, ...conv } : c)),
|
||||
prev.map((c) =>
|
||||
c.id === conv.id
|
||||
? {
|
||||
...c,
|
||||
...conv,
|
||||
unread_count: isActive ? 0 : conv.unread_count,
|
||||
}
|
||||
: c,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
// UPDATE arrived before the INSERT (or after a missed INSERT)
|
||||
@ -339,6 +353,17 @@ export default function InboxPage() {
|
||||
setActiveConversation(match);
|
||||
setActiveContact(match.contact ?? null);
|
||||
setMessages([]);
|
||||
// Mirror the optimistic unread reset that handleSelectConversation
|
||||
// does — the user just deep-linked into this conv, treat that the
|
||||
// same as a click. Leaves activeConversation.unread_count alone so
|
||||
// the MessageThread reset effect still fires the server UPDATE.
|
||||
if (match.unread_count > 0) {
|
||||
setConversations((prev) =>
|
||||
prev.map((c) =>
|
||||
c.id === match.id ? { ...c, unread_count: 0 } : c,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -355,6 +380,22 @@ export default function InboxPage() {
|
||||
setActiveConversation(conv);
|
||||
setActiveContact(conv.contact ?? null);
|
||||
setMessages([]);
|
||||
// Optimistically clear the unread badge for this conv. The
|
||||
// server-side reset is fired by the unread-reset effect inside
|
||||
// MessageThread (which reads activeConversation.unread_count, not
|
||||
// the list copy — so we deliberately leave that intact below to
|
||||
// keep the effect firing), and the realtime UPDATE that comes
|
||||
// back will sync to 0 again as a no-op. Zeroing the list copy
|
||||
// here means the user sees the badge disappear the instant they
|
||||
// click instead of waiting for the round-trip — and it persists
|
||||
// even if the realtime UPDATE is dropped.
|
||||
setConversations((prev) =>
|
||||
prev.map((c) =>
|
||||
c.id === conv.id && c.unread_count > 0
|
||||
? { ...c, unread_count: 0 }
|
||||
: c,
|
||||
),
|
||||
);
|
||||
// Record the selection on the deep-link ref BEFORE we change the
|
||||
// URL. The router.replace below flips `deepLinkConvId`, which can
|
||||
// in turn cause ConversationList to refetch and eventually call
|
||||
|
||||
Loading…
Reference in New Issue
Block a user