Skip to content

fix(mobile): restore left nav drawer swipe on the feed - #14483

Merged
dylanjeffers merged 1 commit into
mainfrom
fix/mobile-feed-swipe-drawer
Jun 16, 2026
Merged

dylanjeffers merged 1 commit into
mainfrom
fix/mobile-feed-swipe-drawer

Conversation

@dylanjeffers

Copy link
Copy Markdown
Contributor

Summary

The For You / Latest swipe pager (#14473) wrapped the feed in a PagerView, which swallowed the horizontal swipe that opens the left nav drawer. The drawer's own full-width native swipe (swipeEdgeWidth: SCREEN_WIDTH) also competed with the pager, so:

  • a right-swipe on Latest opened the drawer instead of paging back to For You, and
  • gesture arbitration with the track tiles' tap gesture was flaky (swipes starting on a tile, and fast flings, often didn't register).

Changes

  • Disable the drawer's native swipe while the feed is focused and the drawer is closed (via setGesturesDisabled), re-enabled once the drawer is open so swipe-to-close still works, and restored on blur. This leaves the pager as the sole owner of horizontal paging.
  • Add a rightward-only pan on the For You page that opens the drawer, composed Gesture.Simultaneous with the pager's native gesture so fast flings aren't claimed by the pager before the pan activates.

Behavior

Page Swipe right Swipe left
For You Opens drawer (fast or slow, incl. from a track tile) → Latest
Latest → For You (nothing)

🤖 Generated with Claude Code

The For You/Latest swipe pager (#14473) swallowed the horizontal swipe
that opens the left nav drawer, and the drawer's own full-width native
swipe competed with the pager — so a right-swipe on Latest opened the
drawer instead of paging, and arbitration with track tiles was flaky.

- Disable the drawer's native swipe while the feed is focused and the
  drawer is closed (re-enabled when open so swipe-to-close still works),
  leaving the pager as the sole owner of horizontal paging.
- Add a rightward-only pan on the For You page that opens the drawer,
  composed simultaneously with the pager's native gesture so fast flings
  aren't claimed by the pager before the pan activates.

Result: For You right-swipe opens the drawer (fast or slow, including
from a track tile); For You left-swipe and Latest right-swipe page
between tabs as before.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Jun 16, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: de69cdb

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@dylanjeffers
dylanjeffers merged commit 5d9f6b6 into main Jun 16, 2026
1 check passed
@dylanjeffers
dylanjeffers deleted the fix/mobile-feed-swipe-drawer branch June 16, 2026 20:02
dylanjeffers added a commit that referenced this pull request Sep 24, 2026
…ical scrolls (#14601)

## Problem

Vertical scrolls with some sideways drift either do nothing or peek a
screen/drawer and snap back. Most noticeable on Weekly Rotation, but it
affects every nested screen and the root tabs. Three full-screen
horizontal recognizers compete with the list's scroll:

1. **Nested screens** — since #14205 (`animation: 'simple_push'` +
`customAnimationOnGesture`), react-native-screens uses its own
`RNSPanGestureRecognizer` for full-screen swipe-back. Upstream
`gestureRecognizerShouldBegin:` has no direction test, and once it
begins it refuses to run alongside the scroll view's pan. A drag whose
first ~10pt has any rightward component gets claimed as a back gesture.
Before #14205 iOS 26 used Apple's
`interactiveContentPopGestureRecognizer`, which yields to scroll views —
that's the "it used to work" state.
2. **Root tabs** — the drawer navigator's pan spanned the full screen
(`swipeEdgeWidth: SCREEN_WIDTH`) with hardcoded 5pt/5pt thresholds, so
it won any touch that moved sideways first.
3. **Feed / For You** — the drawer-opener pan from #14483 had no
`failOffsetY`, so 20pt of rightward drift anywhere in a long vertical
drag opened the drawer.

## Changes

- **`patches/react-native-screens+4.18.0.patch`** *(native — needs an
App Store release, not OTA)*: `RNSPanGestureRecognizer` may only begin
on a committed horizontal drag — ≥5pt toward dismissal and ≥2× the
cross-axis travel — evaluated once at the pan's activation threshold.
Clean horizontal swipes still pop; anything diagonal stays with the
scroll view.
- **`useOpenDrawerGesture`** *(OTA-able)*: one direction-locked
rightward pan (`activeOffsetX 20`, `failOffsetY ±12`) that opens the
left drawer from mid-screen. Used by Feed (replacing its inline pan) and
wrapped around every tab's stack in `AppTabScreen`, gated to root +
focused + not-now-playing.
- **`AppDrawerScreen`** *(OTA-able)*: the navigator's own swipe is kept
to a 40pt left edge; swipe-to-close is unaffected (`swipeEdgeWidth` only
applies while closed).

## Verification (iOS simulator, Release builds, iPhone 17 Pro / iOS
26.5)

Reproduced with a synthetic "thumb-arc" drag on the Weekly Rotation page
— 16ms samples starting ~15° from horizontal for the first ~13pt, then
straightening to vertical — starting on a loaded tile:

| Drag | Unpatched | This branch |
|---|---|---|
| Thumb-arc | **zero scroll**; header icon circles vanish (interactive
pop began and snapped back) | scrolls ~3 tiles |
| 30° fine-grained diagonal | ~185pt, no fling | ~310pt with fling |
| Fast coarse diagonal | scrolls | scrolls |

Also on this branch: Feed Latest ⇄ For You paging, mid-screen drawer
open on For You and Trending, drawer swipe-close, Track back-swipe, and
diagonal scrolls on Feed/Trending/Track all behave.

Fast drags never show the bug on either build (both recognizers cross
their thresholds in one event and the scroll view wins the tie); it's
the slow curved start that gets claimed.

## Notes

- Debug simulator builds abort on `react_native_assert(attempts < 1024)`
in `ShadowTree::commit` (via Reanimated's mount hook) when touching
tiles — unrelated to this change, but it makes Debug useless for testing
this; use Release.
- Xcode 27 refuses the pods with deployment targets < 15; that needs a
`post_install` bump in the Podfile and will come separately.
- `Podfile.lock` drift from `pod install` is intentionally not included.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant