Repository navigation
mobile: stop typing prune ticks from rebuilding channel pages - #8695
Conversation
The typing prune timer published a new list every second while anyone was typing, and the channel and thread pages watched the whole list, so each tick rebuilt the page and its message list. Publish only when the visible entries change, and have pages select a value-equal view that excludes the current user's own echoed indicator. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Tom Brow <[email protected]>
|
@codex review |
|
@buzz-security-review 5ff7541 |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
🔐 Codex Security Review
Review SummaryOverall Risk: NONE
FindingsNo concrete security, correctness, or reliability findings were identified. Notes
Generated by Codex Security Review | |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5ff7541314
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Channel and thread pages now watch one visibleTypingProvider, and a test checks that the user's own echoed indicator does not notify it while another user's typing does. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Tom Brow <[email protected]>
|
@codex review |
|
@buzz-security-review 8b8a168 |
|
Codex Review: Didn't find any major issues. Another round soon, please! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
wesbillman
left a comment
There was a problem hiding this comment.
🤖 Carl, an automated reviewer, commenting via Wes's GitHub account.
Verdict: no blockers at 8b8a168. This is a comment, not an approval.
The change is well scoped. _prune() now publishes only when the visible list changes, and the pages select a value-equal VisibleTyping. Self-echo refreshes no longer rebuild the channel or thread page, and expiry and removal still publish from the prune timer.
What we checked:
- Riverpod lifecycle (3.1.0 as locked).
ref.watchgets a fresh.select(...)on every build.flutter_riverpodinstalls the new subscription before it closes the old one, so rebuilds never hitonCancel/onResumeor the 30 s detach. A local widget probe confirmed this: 40 rebuilds over 40 simulated seconds, zero cancel/resume, one relay subscription, real unmount detached at 30 s. - Consumers of the old 1 s tick. The reply-handoff hook still checks its deadlines whenever it runs. It gets fresh input when messages change and when entries expire. Inline dots and thread shimmer run their own animations. We found nothing that needs an unchanged list republished every second. Date headings and retention labels read the clock during build, but they already went stale whenever nobody was typing, so that isn't new.
Validation gap, not blocking: the new tests run at the provider/selector level. No page-level test exercises quiet ticks, then natural expiry, then a reply through the real notifier. If you want that, extending an existing channel_detail_page_test.dart typing journey would cover it better than more provider tests.
Remaining gates: Mobile Swift (Native) is still pending. The Codex Security Review run was cancelled and never posted a review. Neither is caused by this diff.
Summary
Typing in the mobile composer felt slower than a native iOS text field. A device trace on an iPhone 12 mini showed the cause: while anyone in the channel is typing, the whole channel page rebuilds once per second, including the visible message list.
ChannelTypingNotifier._prune()runs on a 1 s timer and assigned a new list tostateon every tick, even when nothing had changed._ResolvedChannelDetailPagewatched the whole list and only filtered out the current user afterwards, so every tick rebuilt the page and itsPositionedList(12 to 35 ms per frame, 8 to 19 ms for the message list alone).In a 30-key trace, 33 of the 35 frames over 12 ms were these rebuilds, 1.00 s apart.
Fix
_prune()publishes only when the visible entries change.TypingEntrynow compares by value.visibleTypingProvider, aVisibleTypingvalue that already excludes the current user and applies the page's scope. Your own echo refreshes its expiry every 3 s, which used to rebuild the page. Now it doesn't.Other
channelTypingProviderconsumers are unchanged.Related issue
None found.
Testing
Provider tests: a typing entry held across five prune ticks notifies listeners once, and the pages' shared
visibleTypingProvideris not notified by the user's own refreshed echo but is by another user. Breaking either guard fails its test.just mobile-checkandjust mobile-testpass at 8b8a168.Device trace on an iPhone 12 mini: 30 keys typed into a channel composer, Profile builds with build tracing on both sides. Control is 6661d59, which has the same page code as main.
The test driver turns on accessibility, so semantics runs on every frame in both traces. About 1 key in 4 still has a slow frame with about 1 ms of build and 2 ms of raster. A Time Profiler capture put that time in the driver's accessibility queries on the main thread (52% of main-thread samples while typing, none before the first automated tap), so it is a test-harness artifact rather than app work.
Dictation on an iPhone SE (2nd gen): a 15 s paragraph dictated into a channel composer, Profile builds with build tracing.
Each dictation update costs about 1 ms. The caret stayed at the end and nothing flickered on either build.
buzz-review-completed
🤖 Generated with Claude Code