fix(scroll): take edge hints from a same-rect scrollable ancestor

Merged
AI
5h ago
+275-4

Summary

scroll top on the Android Settings home screen reached the top, then failed with scroll_edge_no_progress. The nested recycler_view reports hiddenContentAbove even at the top. The outer main_content_scrollable_container, with the identical rect, reports the real position.

As agreed in #3737 (option 1), scroll edge selection now stands a same-rect scrollable ancestor in for the scroller nested in it, so the chosen container, its scope and its verdict all come from the ancestor. Selecting the ancestor (not only reading its hints) keeps the nested list inside the scoped recapture runScrollEdgePasses makes. An ancestor stands in only when it reports a vertical edge hint, so a same-rect horizontal pager never replaces the vertical list on its page. Both ancestor walks guard against cyclic parentIndex chains. Snapshot hints are unchanged. Three files: scroll-edge-state/selection.ts, a regression fixture trimmed from the live Settings trees, and its tests.

Closes #3737

Validation

  • pnpm check:affected --run --head f4c2c2406 passes (exactCommit=true): format, lint, typecheck, layering, fallow, build, vitest-related.
  • Live, Pixel_7_API_36 emulator (API 36), android-helper 0.21.29-dev, same steps as the issue, main at 92db564a3 vs this branch (rerun at f4c2c2406):
StepmainThis branch
scroll downScrolled downScrolled down
scroll topscroll_edge_no_progressScrolled to top with 1 up pass
scroll bottomScrolled to bottomScrolled to bottom
scroll topscroll_edge_no_progressScrolled to top with 1 up pass
scroll top again—Already at top

Also live at f4c2c2406: scroll top on a freshly opened screen reports Already at top.

🤖 Generated with Claude Code