Files
bsky-social-app/patches/@bsky.app__expo-scroll-edge-effect.patch.md
T
2026-07-22 16:48:55 +02:00

45 lines
2.2 KiB
Markdown

# @bsky.app\_\_expo-scroll-edge-effect.patch
Fixes the iOS 26 scroll edge effect (the blur under the status bar) failing to
attach on the New Architecture (Fabric).
## Why
The native view resolves the target scroll view by React tag:
`scrollViewTag` (published from JS when the scroll view mounts) ->
`appContext.findView(withTag:)` -> attach a `UIScrollEdgeElementContainerInteraction`.
On Paper this resolved on the first try, because view-by-tag registration was
serialized through the single UIManager batch pipeline - by the time the tag
prop reached native, the scroll view was already in the registry.
On Fabric there is no synchronous tag->view registry. The scroll view's
`ComponentView` is registered when its mount transaction is applied, which is
deferred relative to the JS commit that set the tag. So the one-shot
`resolveScrollView` runs before the view is mounted and returns nil, the
interaction never attaches, and the blur is lost. (The un-gated case happened to
work only because the header's `didMoveToWindow` provided a late second attempt;
a list mounted later - e.g. behind an `isActive` gate - had no such retry.)
## What it does
Makes resolution event-driven and self-healing instead of one-shot:
- When `resolveScrollView` returns nil, it bumps a bounded counter and calls
`setNeedsLayout()`; `layoutSubviews()` re-attempts as sibling views mount, so
it retries exactly when the scroll view actually appears - no fixed timer.
- `isAttached` stops re-running once resolved (no teardown/re-attach churn).
- `resolveAttempts` / `maxResolveAttempts` bound the retries so a
permanently-absent scroll view (list not rendered) cannot spin layout forever.
- The budget is reset on every "fresh" trigger (prop change, entering the
window) via `scheduleResolve()`, so each new tag gets a full retry budget.
## Notes
- iOS only; gated behind `#available(iOS 26, *)`.
- This mirrors how `react-native-screens` handles the same effect on Fabric
(resolve from the live view hierarchy and re-apply on mount/layout lifecycle
rather than a single tag lookup). A cleaner long-term fix would move
resolution to the scroll-view side, but this is the minimal change to the
existing tag-based design.