about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--patches/react-native-pager-view+6.6.1.patch72
-rw-r--r--src/view/com/pager/Pager.tsx42
2 files changed, 74 insertions, 40 deletions
diff --git a/patches/react-native-pager-view+6.6.1.patch b/patches/react-native-pager-view+6.6.1.patch
new file mode 100644
index 000000000..8e94570cf
--- /dev/null
+++ b/patches/react-native-pager-view+6.6.1.patch
@@ -0,0 +1,72 @@
+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 772cb1715..f62bffc53 100644
--- a/src/view/com/pager/Pager.tsx
+++ b/src/view/com/pager/Pager.tsx
@@ -1,4 +1,4 @@
-import React, {Children, forwardRef, useCallback, useContext} from 'react'
+import React, {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,7 +17,6 @@ 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'
 
@@ -149,11 +148,7 @@ export const Pager = forwardRef<PagerRef, React.PropsWithChildren<Props>>(
             style={[a.flex_1]}
             initialPage={initialPage}
             onPageScroll={handlePageScroll}>
-            {isAndroid
-              ? Children.map(children, child => (
-                  <CaptureSwipesAndroid>{child}</CaptureSwipesAndroid>
-                ))
-              : children}
+            {children}
           </AnimatedPagerView>
         </GestureDetector>
       </View>
@@ -161,39 +156,6 @@ 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