about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/view/com/pager/FixedTouchableHighlight.tsx42
-rw-r--r--src/view/com/util/Link.tsx25
-rw-r--r--src/view/screens/PostThread.tsx16
3 files changed, 74 insertions, 9 deletions
diff --git a/src/view/com/pager/FixedTouchableHighlight.tsx b/src/view/com/pager/FixedTouchableHighlight.tsx
new file mode 100644
index 000000000..d07196975
--- /dev/null
+++ b/src/view/com/pager/FixedTouchableHighlight.tsx
@@ -0,0 +1,42 @@
+// FixedTouchableHighlight.tsx
+import React, {ComponentProps, useRef} from 'react'
+import {GestureResponderEvent, TouchableHighlight} from 'react-native'
+
+type Position = {pageX: number; pageY: number}
+
+export default function FixedTouchableHighlight({
+  onPress,
+  onPressIn,
+  ...props
+}: ComponentProps<typeof TouchableHighlight>) {
+  const _touchActivatePositionRef = useRef<Position | null>(null)
+
+  function _onPressIn(e: GestureResponderEvent) {
+    const {pageX, pageY} = e.nativeEvent
+
+    _touchActivatePositionRef.current = {
+      pageX,
+      pageY,
+    }
+
+    onPressIn?.(e)
+  }
+
+  function _onPress(e: GestureResponderEvent) {
+    const {pageX, pageY} = e.nativeEvent
+
+    const absX = Math.abs(_touchActivatePositionRef.current?.pageX! - pageX)
+    const absY = Math.abs(_touchActivatePositionRef.current?.pageY! - pageY)
+
+    const dragged = absX > 2 || absY > 2
+    if (!dragged) {
+      onPress?.(e)
+    }
+  }
+
+  return (
+    <TouchableHighlight onPressIn={_onPressIn} onPress={_onPress} {...props}>
+      {props.children}
+    </TouchableHighlight>
+  )
+}
diff --git a/src/view/com/util/Link.tsx b/src/view/com/util/Link.tsx
index 7ff896344..1dec97e78 100644
--- a/src/view/com/util/Link.tsx
+++ b/src/view/com/util/Link.tsx
@@ -5,11 +5,11 @@ import {
   GestureResponderEvent,
   Platform,
   StyleProp,
-  TouchableWithoutFeedback,
-  TouchableOpacity,
   TextStyle,
   View,
   ViewStyle,
+  TouchableOpacity,
+  TouchableWithoutFeedback,
 } from 'react-native'
 import {
   useLinkProps,
@@ -22,8 +22,9 @@ import {NavigationProp} from 'lib/routes/types'
 import {router} from '../../../routes'
 import {useStores, RootStoreModel} from 'state/index'
 import {convertBskyAppUrlIfNeeded, isExternalUrl} from 'lib/strings/url-helpers'
-import {isDesktopWeb} from 'platform/detection'
+import {isAndroid, isDesktopWeb} from 'platform/detection'
 import {sanitizeUrl} from '@braintree/sanitize-url'
+import FixedTouchableHighlight from '../pager/FixedTouchableHighlight'
 
 type Event =
   | React.MouseEvent<HTMLAnchorElement, MouseEvent>
@@ -65,6 +66,24 @@ export const Link = observer(function Link({
   )
 
   if (noFeedback) {
+    if (isAndroid) {
+      // workaround for Android not working well with left/right swipe gestures and TouchableWithoutFeedback
+      // https://github.com/callstack/react-native-pager-view/issues/424
+      return (
+        <FixedTouchableHighlight
+          testID={testID}
+          onPress={onPress}
+          // @ts-ignore web only -prf
+          href={asAnchor ? sanitizeUrl(href) : undefined}
+          accessible={accessible}
+          accessibilityRole="link"
+          {...props}>
+          <View style={style}>
+            {children ? children : <Text>{title || 'link'}</Text>}
+          </View>
+        </FixedTouchableHighlight>
+      )
+    }
     return (
       <TouchableWithoutFeedback
         testID={testID}
diff --git a/src/view/screens/PostThread.tsx b/src/view/screens/PostThread.tsx
index e3ceb0bef..86b2d3027 100644
--- a/src/view/screens/PostThread.tsx
+++ b/src/view/screens/PostThread.tsx
@@ -1,5 +1,5 @@
 import React, {useMemo} from 'react'
-import {StyleSheet, View} from 'react-native'
+import {InteractionManager, StyleSheet, View} from 'react-native'
 import {useFocusEffect} from '@react-navigation/native'
 import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
 import {makeRecordUri} from 'lib/strings/url-helpers'
@@ -31,11 +31,15 @@ export const PostThreadScreen = withAuthRequired(({route}: Props) => {
     React.useCallback(() => {
       store.shell.setMinimalShellMode(false)
       const threadCleanup = view.registerListeners()
-      if (!view.hasLoaded && !view.isLoading) {
-        view.setup().catch(err => {
-          store.log.error('Failed to fetch thread', err)
-        })
-      }
+
+      InteractionManager.runAfterInteractions(() => {
+        if (!view.hasLoaded && !view.isLoading) {
+          view.setup().catch(err => {
+            store.log.error('Failed to fetch thread', err)
+          })
+        }
+      })
+
       return () => {
         threadCleanup()
       }