Repository navigation
fix(mobile): steady New DM picker rows and animate picks - #9249
Conversation
Every state update from Dart reloads the native member picker, which built fresh cells showing the initials fallback and fetched each avatar again over the platform channel, so avatars blinked whenever results refreshed, most visibly right after foregrounding. Keep loaded avatars by key and draw them at once when a cell is rebuilt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: studio <dc2fc481343672df31a689840c09299972e704dac592e0da6f18486646a7ee3e@buzz.block.builderlab.xyz> Signed-off-by: Tom Brow <tomb@squareup.com>
Flutter pushes the picker's whole state on every rebuild, and each push reloaded every visible row with fresh, unreused cells. Drop identical states, apply the rest as a diffable snapshot that redraws only changed rows in reused cells, and animate a member's row moving between the chosen and result sections when it is picked or removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: studio <dc2fc481343672df31a689840c09299972e704dac592e0da6f18486646a7ee3e@buzz.block.builderlab.xyz> Signed-off-by: Tom Brow <tomb@squareup.com>
A second tap could reach Flutter before the rebuild that reflected the first, and both toggles read the selection captured at build time, so the same person was added twice. The diffed native table traps on a duplicate row. Read the current selection instead, and fail loudly if a shown member row is missing from the state. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: studio <dc2fc481343672df31a689840c09299972e704dac592e0da6f18486646a7ee3e@buzz.block.builderlab.xyz> Signed-off-by: Tom Brow <tomb@squareup.com>
Codex Review Summary: ✅ CompletedThis 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: c8b7672aa2
ℹ️ 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".
| loadAvatar(pubkey, key) { [weak self, weak cell] data in | ||
| guard let data, let image = UIImage(data: data) else { return } | ||
| let avatar = image.withRenderingMode(.alwaysOriginal) | ||
| self?.avatars[key] = avatar |
There was a problem hiding this comment.
In the iOS New DM/Add Members sheet, every distinct avatar encountered across successive searches is retained in avatars until the sheet closes. The Dart-side cache deliberately evicts after 64 entries, but this decoded UIImage cache has no corresponding limit, so browsing many results in a large community can make memory usage grow monotonically. Use a bounded eviction policy or NSCache while retaining enough recent entries to prevent the avatar blink.
AGENTS.md reference: AGENTS.md:L249-L257
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
🤖 Fixed in a2ea37f: the cache is now an NSCache capped at 64 entries, matching the Dart side.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: studio <dc2fc481343672df31a689840c09299972e704dac592e0da6f18486646a7ee3e@buzz.block.builderlab.xyz> Signed-off-by: Tom Brow <tomb@squareup.com>
|
🤖 Meli, Tyler’s AI agent, posting on his explicit behalf. The production UIKit picker assertions pass, including changed-row redraw, no repeated avatar fetch, immediate cached-image rendering, identity and accessibility. The full mobile suite also passed. The remaining concern is incomplete full-app visual verification: please complete a main/PR New DM selection and search sequence to check row updates, selected state and avatar rendering in the actual sheet. This is a validation gap, not a confirmed code defect. Reviewed head: |
|
🤖 Thanks, Tyler. I ran the full-app check: the same New DM selection and search sequence on a clone of the same signed-in simulator, on |
kazemek21
left a comment
There was a problem hiding this comment.
Kyle reviewed this PR and the Nexus review-tracker notes and approved with no comments.
Posted by Codex (gpt-6.1-sol) on behalf of kylez
…ction-p * origin/main: (111 commits) feat(mobile): tag the reacted-to message author on reactions (#9141) fix(mobile): steady New DM picker rows and animate picks (#9249) perf(mobile): keep remote images on disk and show small ones as thumbnails (#9158) fix(relay): deliver slow cross-node events late instead of closing their recipients (#9235) fix(mobile): read only shown events from filtered Activity rows (#9215) fix(mobile): show the channel name as the notification subtitle (#9173) fix(mobile): keep Home's header clean under sheets (#9152) fix(mobile): show already-loaded custom emoji in the iOS reactions sheet (#9150) mobile: add follow and remind actions to inbox row menu (#9142) fix(mobile): start no threads in Solo chats (#9123) mobile: persist user profiles so names and avatars render on launch (#9116) fix(mobile): keep a sent thread reply above the composer (#9026) [buzz] Recover database pool capacity after stalled connections (#9267) feat: send a User-Agent on relay WebSocket upgrades (#9246) Record why relay connections close and quiet close warnings (#9245) fix(relay): say "channel owner or admin" in the call_webhook save refusal (#9169) feat(mobile): consolidate Solo chat settings in one sheet (#9255) fix(cli): preserve attachments across successive edits (#9226) fix(mobile): swipe left to reply so swipe-back keeps rightward drags (#9127) mobile: long-press a message link for open, copy and share (#9135) ... Signed-off-by: Matthew Boston <mboston@squareup.com>
…-profile * origin/main: (307 commits) fix: inline ARM64 atomics in Sprig image build (#9291) fix(mobile): show observed thread replies in Activity (#9286) Enable mobile huddles with Codex agents (#9269) fix(mobile): read mentions taller than the screen (#9243) test(relay): give every media e2e upload its own blob hash (#9272) Add invite preview video and fallback poster (#9282) NEXUS-4336: Wait for desktop-provider socket ownership proof (#9270) fix: unblock image audit with patched MCP SDK (#9287) feat(ci): allow admin dispatch of desktop candidate validation (#9288) feat(mobile): tag the reacted-to message author on reactions (#9141) fix(mobile): steady New DM picker rows and animate picks (#9249) perf(mobile): keep remote images on disk and show small ones as thumbnails (#9158) fix(relay): deliver slow cross-node events late instead of closing their recipients (#9235) fix(mobile): read only shown events from filtered Activity rows (#9215) fix(mobile): show the channel name as the notification subtitle (#9173) fix(mobile): keep Home's header clean under sheets (#9152) fix(mobile): show already-loaded custom emoji in the iOS reactions sheet (#9150) mobile: add follow and remind actions to inbox row menu (#9142) fix(mobile): start no threads in Solo chats (#9123) mobile: persist user profiles so names and avatars render on launch (#9116) ... Signed-off-by: Franco Sola <fsola@squareup.com> # Conflicts: # docs/nips/NIP-FA.md # docs/nips/NIP-FI.md
…e-mode * origin/main: (36 commits) feat(relay): let an operator mint invites for a community owner or admin (#9265) fix: inline ARM64 atomics in Sprig image build (#9291) fix(mobile): show observed thread replies in Activity (#9286) Enable mobile huddles with Codex agents (#9269) fix(mobile): read mentions taller than the screen (#9243) test(relay): give every media e2e upload its own blob hash (#9272) Add invite preview video and fallback poster (#9282) NEXUS-4336: Wait for desktop-provider socket ownership proof (#9270) fix: unblock image audit with patched MCP SDK (#9287) feat(ci): allow admin dispatch of desktop candidate validation (#9288) feat(mobile): tag the reacted-to message author on reactions (#9141) fix(mobile): steady New DM picker rows and animate picks (#9249) perf(mobile): keep remote images on disk and show small ones as thumbnails (#9158) fix(relay): deliver slow cross-node events late instead of closing their recipients (#9235) fix(mobile): read only shown events from filtered Activity rows (#9215) fix(mobile): show the channel name as the notification subtitle (#9173) fix(mobile): keep Home's header clean under sheets (#9152) fix(mobile): show already-loaded custom emoji in the iOS reactions sheet (#9150) mobile: add follow and remind actions to inbox row menu (#9142) fix(mobile): start no threads in Solo chats (#9123) ... Signed-off-by: Will Pfleger <wpfleger@block.xyz>
On iOS, the New DM (and Add Members) picker is a native UIKit sheet that Flutter drives by pushing the picker's whole state on every rebuild. Each push called
reloadData, which rebuilt every visible row in a fresh, unreused cell showing the initials fallback, then fetched each avatar again over the platform channel. So whenever anything refreshed (several refreshes land right after foregrounding), every avatar blinked to its initial for a frame or two. Picks also jumped instantly from the results to the chosen section.Now the picker:
Flutter's toggle handlers in both pickers now read the current selection rather than the one captured at build time. A fast second tap could otherwise add the same person twice, which the diffed table would reject.
Validation
scripts/test-mobile-member-picker.sh), extended: after an avatar loads, a changed row is redrawn with that avatar and requests nothing more. The avatar check fails onmainand passes here; the existing identity and accessibility checks still pass with the diffable table.main's fix for the right-drag link tests.Full-app comparison,
mainvs this PRThe same scripted New DM sequence on a clone of the same signed-in simulator (iPhone 17 Pro, iOS 27), first on
main(65e8643) and then on this PR (330805c): pick george, then glm; search "ju", pick judge, clear the search; remove george; background and reopen the app. The list shows only agents, no people.Both builds end in the same state: each pick moves into the selected section with its check mark, search narrows to one result and clearing it restores the full list, the removed pick returns to the list, and every avatar keeps rendering after the app reopens. Sampled at 6 frames per second around the reopen, neither build fell back to initials in this run. The visible difference is motion: on
maina picked row jumps into the selected section, and here it animates there.Before (
main):main-annotated.mp4
After (this PR):
pr-annotated.mp4
Before merge
mainonce main's link swipe tests are fixed (they were fixed by #9255 Solo chat settings), so Mobile Checks can pass.buzz-review-completed
🤖 Generated with Claude Code