fix(mobile): merge relay recounts with locally seen thread replies - #4633
Open
brow wants to merge 1 commit into
Open
fix(mobile): merge relay recounts with locally seen thread replies#4633brow wants to merge 1 commit into
brow wants to merge 1 commit into
Conversation
A message's "N replies" badge could stall at a stale count, or stay missing, after a reply arrived. Once the relay sent any positive thread recount, `_buildSummary` returned it and ignored replies this client had already received, so a delayed or lost recount, or a reply landing after the recount was taken, left the badge behind. Merge the two sources instead: take the higher reply count, the later last-reply time, and a combined participant list. Relay timestamps have one-second precision, so an equal timestamp is no proof the recount already included a locally observed reply, which is why the counts are compared rather than the times alone. Desktop already merges this way (`mergeThreadSummaries` in threadPanel.ts). Replies also have to survive in the channel window store for the local half of that merge to see anything, so stop dropping them in `_mergeWindowEventIntoStore`. They are still filtered out of the main timeline at render, and read state already ignores them. Co-authored-by: Tom Brow <tomb@block.xyz> Signed-off-by: Tom Brow <tomb@block.xyz>
brow
marked this pull request as ready for review
August 3, 2026 23:27
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Why
On mobile, the "N replies" badge under a channel message can stall at a stale count or remain missing after a reply arrives. This makes the badge unreliable and can cause people to miss replies.
The badge has two inputs: best-effort recounts from the relay and replies the client sees arrive. Mobile previously let any positive relay recount override the local view, while also discarding replies from its local message store. A delayed or lost recount, or a reply received after the recount, could therefore leave the badge behind.
This change combines both inputs by using the higher reply count, the later last-reply time, and a merged participant list. Relay timestamps have one-second precision, so equal timestamps do not prove that a recount included a locally observed reply. Comparing counts preserves that reply instead of trusting recency alone. Desktop already uses this merge behavior.
Validation
At commit
4e3356636f5ad62e8f07910af305c532186c6c08with a clean worktree:flutter testfor mobile: 1105 passed, 1 skippedflutter analyzefor mobile: no issues foundAdded tests:
timeline_message_test.dart, covering relay-only recounts, a reply newer than the recount, a reply in the same second as the recount, a lost recount, a zero recount, nested replies at the root and at the reply they answer, a deleted reply, and participant merging and capping.channel_messages_provider_test.dart, covering a live reply reaching the store while staying out of the main timeline, and a reply newer than the relay recount raising the badge.