about summary refs log tree commit diff
diff options
context:
space:
mode:
authordan <dan.abramov@gmail.com>2025-01-20 01:03:42 +0000
committerGitHub <noreply@github.com>2025-01-20 01:03:42 +0000
commitcb020655504dd0d39f8e91fd517f14dc4a82c307 (patch)
treeb6d4be88f59a318ae7a49c3d1ffcfd29884347f0
parent3e0ac0a0668b5906d7b81dbc075cfd04ba89911c (diff)
downloadvoidsky-cb020655504dd0d39f8e91fd517f14dc4a82c307.tar.zst
Revert "[Android] Fix taps triggering while swiping (#7459)" (#7498)
This reverts commit 5130d19ebdb3267f58e2b6407eb5c4f95107887c.
-rw-r--r--patches/react-native-pager-view+6.6.1.patch72
-rw-r--r--src/view/com/pager/Pager.tsx42
2 files changed, 40 insertions, 74 deletions
diff --git a/patches/react-native-pager-view+6.6.1.patch b/patches/react-native-pager-view+6.6.1.patch
deleted file mode 100644
index 8e94570cf..000000000
--- a/patches/react-native-pager-view+6.6.1.patch
+++ /dev/null
@@ -1,72 +0,0 @@
-diff --git a/node_modules/react-native-pager-view/android/build/tmp/kotlin-classes/debug/com/reactnativepagerview/NestedScrollableHost.class b/node_modules/react-native-pager-view/android/build/tmp/kotlin-classes/debug/com/reactnativepagerview/NestedScrollableHost.class
-new file mode 100644
-index 0000000..b64fccc
-Binary files /dev/null and b/node_modules/react-native-pager-view/android/build/tmp/kotlin-classes/debug/com/reactnativepagerview/NestedScrollableHost.class differ
-diff --git a/node_modules/react-native-pager-view/android/src/main/java/com/reactnativepagerview/NestedScrollableHost.kt b/node_modules/react-native-pager-view/android/src/main/java/com/reactnativepagerview/NestedScrollableHost.kt
-index 91d9946..87b58d0 100644
---- a/node_modules/react-native-pager-view/android/src/main/java/com/reactnativepagerview/NestedScrollableHost.kt
-+++ b/node_modules/react-native-pager-view/android/src/main/java/com/reactnativepagerview/NestedScrollableHost.kt
-@@ -8,6 +8,7 @@ import android.view.ViewConfiguration
- import android.widget.FrameLayout
- import androidx.viewpager2.widget.ViewPager2
- import androidx.viewpager2.widget.ViewPager2.ORIENTATION_HORIZONTAL
-+import com.facebook.react.uimanager.events.NativeGestureUtil
- import kotlin.math.absoluteValue
- import kotlin.math.sign
- 
-@@ -27,6 +28,7 @@ class NestedScrollableHost : FrameLayout {
-   private var touchSlop = 0
-   private var initialX = 0f
-   private var initialY = 0f
-+  private var nativeGestureStarted: Boolean = false
-   private val parentViewPager: ViewPager2?
-     get() {
-       var v: View? = parent as? View
-@@ -57,17 +59,14 @@ class NestedScrollableHost : FrameLayout {
-   }
- 
-   private fun handleInterceptTouchEvent(e: MotionEvent) {
--    val orientation = parentViewPager?.orientation ?: return
--
--    // Early return if child can't scroll in same direction as parent
--    if (!canChildScroll(orientation, -1f) && !canChildScroll(orientation, 1f)) {
--      return
--    }
-+    val orientation = parentViewPager?.orientation
- 
-     if (e.action == MotionEvent.ACTION_DOWN) {
-       initialX = e.x
-       initialY = e.y
--      parent.requestDisallowInterceptTouchEvent(true)
-+      if (orientation != null) {
-+        parent.requestDisallowInterceptTouchEvent(true)
-+      }
-     } else if (e.action == MotionEvent.ACTION_MOVE) {
-       val dx = e.x - initialX
-       val dy = e.y - initialY
-@@ -78,6 +77,10 @@ class NestedScrollableHost : FrameLayout {
-       val scaledDy = dy.absoluteValue * if (isVpHorizontal) 1f else .5f
- 
-       if (scaledDx > touchSlop || scaledDy > touchSlop) {
-+        NativeGestureUtil.notifyNativeGestureStarted(this, e)
-+        nativeGestureStarted = true
-+
-+        if (orientation == null) return
-         if (isVpHorizontal == (scaledDy > scaledDx)) {
-           // Gesture is perpendicular, allow all parents to intercept
-           parent.requestDisallowInterceptTouchEvent(false)
-@@ -94,4 +97,14 @@ class NestedScrollableHost : FrameLayout {
-       }
-     }
-   }
-+
-+  override fun onTouchEvent(e: MotionEvent): Boolean {
-+    if (e.actionMasked == MotionEvent.ACTION_UP) {
-+      if (nativeGestureStarted) {
-+        NativeGestureUtil.notifyNativeGestureEnded(this, e)
-+        nativeGestureStarted = false
-+      }
-+    }
-+    return super.onTouchEvent(e)
-+  }
- }
diff --git a/src/view/com/pager/Pager.tsx b/src/view/com/pager/Pager.tsx
index f62bffc53..772cb1715 100644
--- a/src/view/com/pager/Pager.tsx
+++ b/src/view/com/pager/Pager.tsx
@@ -1,4 +1,4 @@
-import React, {forwardRef, useCallback, useContext} from 'react'
+import React, {Children, forwardRef, useCallback, useContext} from 'react'
 import {View} from 'react-native'
 import {DrawerGestureContext} from 'react-native-drawer-layout'
 import {Gesture, GestureDetector} from 'react-native-gesture-handler'
@@ -17,6 +17,7 @@ import Animated, {
 } from 'react-native-reanimated'
 import {useFocusEffect} from '@react-navigation/native'
 
+import {isAndroid} from '#/platform/detection'
 import {useSetDrawerSwipeDisabled} from '#/state/shell'
 import {atoms as a, native} from '#/alf'
 
@@ -148,7 +149,11 @@ export const Pager = forwardRef<PagerRef, React.PropsWithChildren<Props>>(
             style={[a.flex_1]}
             initialPage={initialPage}
             onPageScroll={handlePageScroll}>
-            {children}
+            {isAndroid
+              ? Children.map(children, child => (
+                  <CaptureSwipesAndroid>{child}</CaptureSwipesAndroid>
+                ))
+              : children}
           </AnimatedPagerView>
         </GestureDetector>
       </View>
@@ -156,6 +161,39 @@ export const Pager = forwardRef<PagerRef, React.PropsWithChildren<Props>>(
   },
 )
 
+// HACK.
+// This works around https://github.com/callstack/react-native-pager-view/issues/960.
+// It appears that the Pressables inside the pager get confused if there's enough work
+// happening on the JS thread, and mistakingly interpret a pager swipe as a tap.
+// We can prevent this by stealing all horizontal movements from the tree inside.
+function CaptureSwipesAndroid({children}: {children: React.ReactNode}) {
+  const lastTouchStart = React.useRef<{x: number; y: number} | null>(null)
+  return (
+    <View
+      onTouchStart={e => {
+        lastTouchStart.current = {
+          x: e.nativeEvent.pageX,
+          y: e.nativeEvent.pageY,
+        }
+      }}
+      onMoveShouldSetResponderCapture={e => {
+        const coords = lastTouchStart.current
+        if (!coords) {
+          return false
+        }
+        const dx = Math.abs(e.nativeEvent.pageX - coords.x)
+        if (dx > 0) {
+          // This is a horizontal movement and will result in a swipe.
+          // Prevent pager children from receiving this touch.
+          return true
+        }
+        return false
+      }}>
+      {children}
+    </View>
+  )
+}
+
 function usePagerHandlers(
   handlers: {
     onPageScroll: (e: PagerViewOnPageScrollEventData) => void