Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix drawer swipe #7007

Merged
merged 7 commits into from
Dec 10, 2024
Merged

Fix drawer swipe #7007

merged 7 commits into from
Dec 10, 2024

Conversation

gaearon
Copy link
Collaborator

@gaearon gaearon commented Dec 7, 2024

See main insight in software-mansion/react-native-gesture-handler#3266 (comment).

New approach relies on react-navigation/react-navigation#12326 which I expect to get merged soon.

Test Plan

  • Try swiping between tabs on Home and Profile
    • Verify the drawer gesture only activates on the first page, and that the pager takes over on other pages
    • Verify the drawer gesture doesn't steal vertical scrolling
    • Try to switch pages fast, in different ways, spam the left/right gesture
      • Note that it won't immediately open the drawer if you just arrived to the first tab without resting. That's kind of intentional to disambiguate pager swipes and intentional drawer swipe. Maybe fixable but let's not fix that yet.
  • Switch between Home and Profile, or Home and Notifications
    • Verify only the current screen's selection determines whether the gesture is enabled
      • For example, open second tab on Home but first tab on Profile. Second tab on Home should disable it (because it's second) but only while you're on Home. First tab on Profile should enable it (because it's first), but only while you're on Profile. Switching between Home and Profile should update the gesture activeness just like switching between pager tabs on those respective root tabs.
    • Verify that the gesture never activates if the nav stack has something on it
    • Verify root screens without tabs (notifications, chat) always have the gesture enabled

Copy link

github-actions bot commented Dec 7, 2024

Old size New size Diff
7.74 MB 7.74 MB -206 B (-0.00%)

This is already pretty error-prone. And with tracking whether we're idle it's going to get more complicated. Let's pause and think.
It feels super arbitrary and breaks muscle memory. If the gesture is reliable, we shouldn't need it.
@arcalinea arcalinea temporarily deployed to fix-drawer-fr - social-app PR #7007 December 10, 2024 03:30 — with Render Destroyed
@arcalinea arcalinea temporarily deployed to fix-drawer-fr - social-app PR #7007 December 10, 2024 03:43 — with Render Destroyed
@gaearon gaearon marked this pull request as ready for review December 10, 2024 04:02
@gaearon gaearon merged commit 46e1e5c into main Dec 10, 2024
6 checks passed
@gaearon gaearon deleted the fix-drawer-fr branch December 10, 2024 04:40
satya164 pushed a commit to react-navigation/react-navigation that referenced this pull request Dec 11, 2024
**Motivation**

The drawer gesture can conflict with other gestures in the app. To
coordinate multiple gestures, the app code can use APIs like
`requireExternalGestureToFail`. However, since the gesture is hidden in
the library, this is not currently possible without patching. This
exposes the gesture to the app code so you can use
`requireExternalGestureToFail` with it.

```js
import { DrawerGestureContext } from 'react-native-drawer-layout';

// ...
const drawerGesture = useContext(DrawerGestureContext)
const nativeGesture = Gesture.Native()
  .requireExternalGestureToFail(drawerGesture)

// ...

<GestureDetector gesture={nativeGesture}>
  <PagerView
    // ...
  />
</GestureDetector>
```

Note that the existing `configureGestureHandler` is not enough because
we need it in the other direction: *other* gestures (deeper in the app)
need access to it. It would not be possible to capture it in a closure
because by the point `configureGestureHandler` runs, the owner component
has already executed and passed the data down.

<s>I opted to use a render prop instead of actually creating a context
in order to keep this addition zero-cost. If this was a context exposed
by the library, we'd have to either memoize the `pan` gesture (to avoid
it getting redefined on drawer re-renders) or we'd have to pay the price
of React doing a context search traversal every time it changes. Seems
unfortunate if the majority of this library's users don't care about the
gesture. Render prop lets the app decide whether it cares.</s>

Re-done as context as requested in review. Added some memoization to
avoid it changing on every render.

**Test plan**

Verify you're able to access `gesture` on mobile. On web, it should be
`undefined`.

Verify you can use it with RNGH APIs as usual. For example,
bluesky-social/social-app#7007 fixes a
longstanding problem with the Bluesky app — the drawer swipe barely
worked on iOS. The reason it has been broken for the last two years is
because this library did not expose the gesture, and we did not know
that it needs to be coordinated.
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.

3 participants