Skip to content

fix: widgets on a kept-alive page that is not showing get no outline - #29

Merged
Harrys76 merged 1 commit into
mainfrom
fix/kept-alive-highlights
Oct 27, 2026
Merged

Harrys76 merged 1 commit into
mainfrom
fix/kept-alive-highlights

Conversation

@Harrys76

Copy link
Copy Markdown
Owner

Widgets on a kept-alive page that is not showing (another tab of a TabBarView) no longer get an outline, a marker or a step. Found while recording the 1.0 launch film on the iPhone 12, after 1.0.0 was tagged and before it reached pub.dev.

The bug

On the Chat App demo (six kept-alive conversation tabs), the crosshair on Oversized Images started on an image of a tab that was not showing. The bar said "Showing Image · 1 of 61", with 61 counting the images of every tab, nothing visible was outlined, and the outline's label sat at the bottom edge of the screen.

Cause

A sliver list does not paint a kept-alive child outside its viewport and gives it a zero paint transform (RenderSliverMultiBoxAdaptor.applyPaintTransform calls transform.setZero()). localToGlobal then divides by zero, so the child's global position is NaN. A NaN rect passes Rect.overlaps, because every comparison with NaN is false, so the first-on-screen step (sleuth_controller.dart), the bar's "Showing" state (floating_issues_card.dart) and the outline painter (highlight_overlay.dart) all took it as visible. A VM-service read of the controller's highlights on the device showed a NaN rect for every image of the tabs not shown.

Fix

  • getGlobalRect returns null for a rect that is not finite, as it does for one it cannot measure. Its 19 callers already skip null, so the detectors leave those widgets without a highlight, and the step count and the bar follow.
  • SimpleStructuralDetector measured with localToGlobal directly and now goes through getGlobalRect.

Tests

Three tests build a TabBarView with kept-alive pages and switch tabs: getGlobalRect returns null for the page that is not showing, the painter detector outlines only the shown page's painter, and a custom detector reports both widgets but outlines one. Each fails without the fix.

Checks

  • iPhone 12, Chat App, same flow: "Showing Image · 1 of 8", the outline on a visible avatar, the bar at the top away from it, and no NaN rect among the 8 highlights.
  • 5,102 tests on 3.47.6 and on the 3.32.8 floor, 44 benchmarks, 353 example tests, analyze, format and dartdoc clean, publish dry run 0 warnings. Codex review clean.

After merge

v1.0.0 is tagged and has a GitHub Release, but 1.0.0 is not on pub.dev yet. The tag moves to this PR's merge commit and the release notes gain the Fixed line, so the published 1.0.0 includes the fix.

🤖 Generated with Claude Code

A sliver list does not paint a kept-alive child outside its viewport,
such as another tab of a TabBarView, and gives it a zero paint
transform. Its global position then comes out NaN, and a NaN rect
passes Rect.overlaps, so every on-screen check took it as visible. On
the Chat App demo (six kept-alive tabs) the Oversized Images crosshair
started on an image of another tab, the bar said "Showing Image · 1 of
61" with 61 counting every tab, and the outline's label sat at the
screen's bottom edge. Read on an iPhone 12: every image of the tabs not
shown had a NaN rect.

getGlobalRect returns null for a rect that is not finite, as it does
for one it cannot measure; its 19 callers already skip null, so those
widgets get no highlight, marker or step. SimpleStructuralDetector
measured with localToGlobal directly and now goes through
getGlobalRect. Three tests build a TabBarView with kept-alive pages:
getGlobalRect, the painter detector and a custom detector each leave
the page that is not showing out, and each fails without the fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Harrys76
Harrys76 merged commit 765eef9 into main Oct 27, 2026
6 checks passed
@Harrys76
Harrys76 deleted the fix/kept-alive-highlights branch October 27, 2026 02:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant