From 46e1e5cee6f0670444da4e1c64a26d8247cf49ec Mon Sep 17 00:00:00 2001
From: dan <dan.abramov@gmail.com>
Date: Tue, 10 Dec 2024 04:40:40 +0000
Subject: Fix drawer swipe (#7007)

* Fix drawer swipe

* Remove existing setDrawerSwipeDisabled management

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.

* Move setDrawerSwipeDisabled logic into Pager

* Remove win/2 threshold

It feels super arbitrary and breaks muscle memory. If the gesture is reliable, we shouldn't need it.

* Maybe work around iOS freeze

* Tweak gestures, add comments

* Tune gestures
---
 src/view/shell/index.tsx | 28 ++++++++++++++++++++++++++--
 1 file changed, 26 insertions(+), 2 deletions(-)

(limited to 'src/view/shell/index.tsx')

diff --git a/src/view/shell/index.tsx b/src/view/shell/index.tsx
index 8dbbbea6f..179e8858e 100644
--- a/src/view/shell/index.tsx
+++ b/src/view/shell/index.tsx
@@ -90,6 +90,7 @@ function ShellInner() {
     }
   }, [dedupe, navigation])
 
+  const swipeEnabled = !canGoBack && hasSession && !isDrawerSwipeDisabled
   return (
     <>
       <View style={[a.h_full]}>
@@ -98,12 +99,35 @@ function ShellInner() {
           <Drawer
             renderDrawerContent={renderDrawerContent}
             drawerStyle={{width: Math.min(400, winDim.width * 0.8)}}
+            configureGestureHandler={handler => {
+              if (swipeEnabled) {
+                if (isDrawerOpen) {
+                  return handler.activeOffsetX([-1, 1])
+                } else {
+                  return (
+                    handler
+                      // Any movement to the left is a pager swipe
+                      // so fail the drawer gesture immediately.
+                      .failOffsetX(-1)
+                      // Don't rush declaring that a movement to the right
+                      // is a drawer swipe. It could be a vertical scroll.
+                      .activeOffsetX(5)
+                  )
+                }
+              } else {
+                // Fail the gesture immediately.
+                // This seems more reliable than the `swipeEnabled` prop.
+                // With `swipeEnabled` alone, the gesture may freeze after toggling off/on.
+                return handler.failOffsetX([0, 0]).failOffsetY([0, 0])
+              }
+            }}
             open={isDrawerOpen}
             onOpen={onOpenDrawer}
             onClose={onCloseDrawer}
-            swipeEdgeWidth={winDim.width / 2}
+            swipeEdgeWidth={winDim.width}
+            swipeMinVelocity={100}
+            swipeMinDistance={10}
             drawerType={isIOS ? 'slide' : 'front'}
-            swipeEnabled={!canGoBack && hasSession && !isDrawerSwipeDisabled}
             overlayStyle={{
               backgroundColor: select(t.name, {
                 light: 'rgba(0, 57, 117, 0.1)',
-- 
cgit 1.4.1

