Skip to content

fix(mobile): build channel section rows lazily - #9401

Merged
brow merged 2 commits into
mainfrom
mfransen/lazy-channel-rows
Nov 12, 2026
Merged

brow merged 2 commits into
mainfrom
mfransen/lazy-channel-rows

Conversation

@michaelfransen

@michaelfransen michaelfransen commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Improve scrolling performance in the Messages channel list by building Solo and Team rows only as needed. Sections currently mount all their rows as one scroll item, which causes long UI stalls with large channel lists.

In manual iPhone runs with 500 channels, maximum observed Flutter UI work fell from 65.5 ms to 4.2 ms after adding lazy rows to a build with header isolation (#9400). The tester reported much smoother scrolling. This was an exploratory comparison with different gestures, not a controlled benchmark of this independent branch.

Use stable channel keys and retain section controls, sorting, and collapse animations. Clip the sliver extent during collapse so the animation does not mount the entire section. The shared transition supports downward vertical lists.

This is an independent production-only change. Test fixtures and diagnostic instrumentation are excluded; regression checks were run locally and are not included in this PR.

Related issue

Related: #5911 addresses scrolling behavior inside conversations. This change addresses eager row mounting in the Messages channel inventory. No matching open PR or issue was identified in the focused duplicate search.

Testing

On a physical iPhone with 500 channels against an isolated local relay, maximum Flutter UI work fell from 65.5 ms to 4.2 ms after adding lazy rows to a build that already isolated header rebuilds. The tester reported much smoother scrolling. Gestures differed between runs, so this is not a controlled benchmark or an isolated measurement of this branch on its own. The device run preceded the refresh onto current main.

Local-only regression journeys passed 12 tests on this independent branch. They cover page laziness and updates, variable-height rows, large text, the last row, collapse reversal, reduced motion, and semantics. These checks are excluded from the commit.

Smaller visible jumps remain under investigation; this PR does not claim to resolve them.

Generated with Codex

Mount Solo and Team rows as lazy slivers while preserving section
controls, sorting, and clipped collapse transitions.

Co-authored-by: Karl <9e8471f7b792e46c9c100840959dc71c660786c79c2a3165dbcaf58f52c4266e@buzz.block.builderlab.xyz>
Signed-off-by: Michael Fransen <[email protected]>
@michaelfransen
michaelfransen marked this pull request as ready for review November 12, 2026 17:25
@michaelfransen
michaelfransen requested a review from a team as a code owner November 12, 2026 17:25
@github-actions github-actions Bot added the codex-security-review-current The posted Codex security review matches its recorded range. label Nov 12, 2026
@github-actions

github-actions Bot commented Nov 12, 2026 •

Copy link
Copy Markdown

🔐 Codex Security Review

Note: This is an automated, security-focused review generated by Codex.
Use it as a supplement to human review; false positives are possible.

Scope

  • Exact PR diff: 745d2a86e01c0c9781793d98c881858e9136f091...7ad776f8f7a17a9cb6cfec0d5c5bd28e760982d1
  • Model: gpt-6.1-sol

💡 Click "edited" above to see earlier reviews for this PR.


Review Summary

Overall Risk: NONE

No concrete security, correctness, or reliability findings identified in the authorized PR range.

Findings

No concrete security, correctness, or reliability findings were identified.

Notes

  • Review was limited to read-only source and history inspection. Builds and tests were not executed.

Generated by Codex Security Review |
Requested by: @michaelfransen |
Workflow run

@brow brow left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 The pre-review recommends landing this with one small fix, #9416 (sliver semantics clip): without it, while a section opens, rows not yet revealed are reachable screen-reader nodes for the duration of the animation, which the old section body excluded. Please merge the fix into your branch (it needs no approval there, since the review rules cover only main and the release branches); this PR is then approved and merged on Tom's go-ahead. Report: buzz://message?channel=e71f9a2a-ac46-473d-a24e-5e16fd8cb7b1&id=689a3f16b435c66e0a9bc59d2541fe25233730e9af5eb6f050686e02ff901c27

…9416)

Fix for a regression found in review of [#9401 lazy section
rows](#9401). This PR targets that
PR's branch.

While a channel section opens, `CollapsibleSliverBody` clips painting to
the revealed extent, but its render object didn't report that clip to
the semantics compiler (`RenderProxySliver` inherits
`describeApproximatePaintClip => null`). Every mounted row under the
clip, including rows drawn beneath the following section, stayed a
reachable screen-reader node until the 220 ms animation finished. The
old `ClipRect`-based body reported its clip, so those rows were
excluded.

The fix reports the same rect that `paint` clips to while the section is
animating, and nothing once it's fully open.

**Pareto:** accessibility returns to the pre-#9401 behavior during the
expand animation; painting, layout and hit testing are unchanged, and
the fully open and collapsed states produce the same semantics tree as
before.

### Validation

- Added tests: `collapsible_sliver_body_test.dart` opens a 10-row
section and, one frame in, checks that screen readers reach exactly the
rows above the painted extent (rows 0 to 3), then that all ten are
reachable once open. It fails without the override (Row 4 reachable
while drawn below the clip).
- Full mobile suite and `just mobile-check` pass locally.
- No visible change, so no screenshots or app run; the change only
affects the semantics tree during the expand animation.

Signed-off-by: Tom Brow <[email protected]>
Co-authored-by: Tom Brow <[email protected]>
Co-authored-by: studio <dc2fc481343672df31a689840c09299972e704dac592e0da6f18486646a7ee3e@buzz.block.builderlab.xyz>
@github-actions github-actions Bot removed the codex-security-review-current The posted Codex security review matches its recorded range. label Nov 12, 2026
@michaelfransen
michaelfransen requested a review from brow November 12, 2026 20:35
@github-actions github-actions Bot added the codex-security-review-current The posted Codex security review matches its recorded range. label Nov 12, 2026
@brow
brow merged commit 2636e98 into main Nov 12, 2026
53 checks passed
@brow
brow deleted the mfransen/lazy-channel-rows branch November 12, 2026 20:56
michaelfransen added a commit that referenced this pull request Nov 12, 2026
## Summary

Improve scrolling performance in the Messages channel list by avoiding
unnecessary inventory rebuilds as the header moves. Keep scroll-driven
header state in a notifier and retain the inventory while the header
animates. Provider and parent updates still rebuild the inventory with
current channel data.

This complements the lazy-row optimization in #9401. In manual iPhone
runs with 500 channels, adding lazy rows on top of header isolation
reduced maximum observed Flutter UI work from **65.5 ms to 4.2 ms**.
That measurement reflects the added lazy-row change; no standalone
performance gain was established for header isolation.

This is an independent production-only change. Test fixtures and
diagnostic instrumentation are excluded; regression checks were run
locally and are not included in this PR.

### Related issue

Related: #5911 addresses scrolling behavior inside conversations. This
change addresses header-triggered rebuilds in the Messages channel
inventory. No matching open PR or issue was identified in the focused
duplicate search.

### Testing

Exercised Messages on a physical iPhone with 500 channels against an
isolated local relay. Header collapse and channel updates worked. This
change alone did not remove the large scroll stalls; lazy section rows
are a separate change. The device run preceded the refresh onto current
main.

Local-only regression checks passed 10 tests on this independent branch.
They verify stable inventory identity during header movement and visible
channel updates. These checks are excluded from the commit.

Remaining visible jumps are under investigation; this PR does not claim
to resolve them.

Generated with Codex

Signed-off-by: Michael Fransen <[email protected]>
Co-authored-by: Karl <9e8471f7b792e46c9c100840959dc71c660786c79c2a3165dbcaf58f52c4266e@buzz.block.builderlab.xyz>
ravarora2 added a commit that referenced this pull request Nov 12, 2026
…small

* origin/main:
  fix(mobile): build channel section rows lazily (#9401)
  fix(cli): treat a retried sidebar write the relay already stored as success (#9202)

Signed-off-by: Ravneet Arora <[email protected]>

This branch was successfully deployed

1 active deployment
codex-review — 7ad776f8 Deployed Nov 12, 2026 by michaelfransen via Run Codex Security Review #14667
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

codex-security-review-current The posted Codex security review matches its recorded range.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants