修复群聊自己发消息后聊天列表出现虚假未读红点

reconcileMeSubs() 的周期性 me.getMeta(withLaterSub()) 拉取,对已知会话原有的
回归保护(seq<=prev.seq && unread>prev.unread) 只防得住"seq没变但unread变大"
这一种情形。自己在已打开的会话里发消息时:本地 confirmedReadSeq 会同步立即
更新(早于服务端),但发给服务端的 note read 是异步的;如果这次拉取的请求
恰好在发送前就已经在途,返回时 seq 已经真实前进(不满足 seq<=prev.seq)、
read 却还没追上,旧保护不生效,虚假的 unread 就被原样套用——哪怕这条消息
就是自己刚发的。

补一个独立的、无条件的兜底:用已有的 confirmedReadSeq 记录做下限,read 永远
不会被这次拉取拉回到低于"本客户端已确认看过的位置",与原有保护并存、不冲突。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Your Name
2026-09-24 18:02:25 +08:00
co-authored by Claude Sonnet 5
parent ef31eb2e88
commit 0ace395cfb
+18
View File
@@ -750,6 +750,24 @@ function reconcileMeSubs() {
c.unread = prev.unread;
notifyTopic(c.topic);
}
// Separate, real bug this same guard doesn't cover (live-confirmed 2026-09-24, reported
// directly): sending your OWN message into a topic that's already open bumps `confirmedReadSeq`
// synchronously (ConversationView's noteRead effect), long before the async `{note read}` this
// relies on has actually reached the server. A `{get}` already in flight since before that
// moment can come back with a real, ADVANCED `seq` (the new message the server just accepted)
// paired with a `read` that hasn't caught up server-side yet -- `seq <= prev.seq` above is
// false (seq genuinely changed), so that guard correctly doesn't fire, and this spurious
// `unread:1` gets applied verbatim even though the user is the one who just sent it. Clamp
// `read` to what THIS client already knows it has confirmed seeing, regardless of what the
// fetch says -- a floor, never pushes `read` past the server's own value when the server is
// genuinely ahead of this record (e.g. read from a different, already-synced device).
const confirmed = confirmedReadSeq.get(c.topic) || 0;
if (confirmed > (c.read || 0)) {
c.read = confirmed;
if ((c.recv || 0) < confirmed) c.recv = confirmed;
c.unread = Math.max(0, (c.seq || 0) - confirmed);
notifyTopic(c.topic);
}
}
})
.catch(() => {});