about summary refs log tree commit diff
path: root/src/components/dms/ActionsWrapper.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/dms/ActionsWrapper.tsx')
-rw-r--r--src/components/dms/ActionsWrapper.tsx74
1 files changed, 38 insertions, 36 deletions
diff --git a/src/components/dms/ActionsWrapper.tsx b/src/components/dms/ActionsWrapper.tsx
index 3b9a56bdc..a349c3cfa 100644
--- a/src/components/dms/ActionsWrapper.tsx
+++ b/src/components/dms/ActionsWrapper.tsx
@@ -1,5 +1,6 @@
 import React from 'react'
-import {Keyboard, Pressable, View} from 'react-native'
+import {Keyboard} from 'react-native'
+import {Gesture, GestureDetector} from 'react-native-gesture-handler'
 import Animated, {
   cancelAnimation,
   runOnJS,
@@ -15,8 +16,6 @@ import {atoms as a} from '#/alf'
 import {MessageMenu} from '#/components/dms/MessageMenu'
 import {useMenuControl} from '#/components/Menu'
 
-const AnimatedPressable = Animated.createAnimatedComponent(Pressable)
-
 export function ActionsWrapper({
   message,
   isFromSelf,
@@ -30,56 +29,59 @@ export function ActionsWrapper({
   const menuControl = useMenuControl()
 
   const scale = useSharedValue(1)
-  const animationDidComplete = useSharedValue(false)
 
   const animatedStyle = useAnimatedStyle(() => ({
     transform: [{scale: scale.value}],
   }))
 
-  // Reanimated's `runOnJS` doesn't like refs, so we can't use `runOnJS(menuControl.open)()`. Instead, we'll use this
-  // function
   const open = React.useCallback(() => {
+    playHaptic()
     Keyboard.dismiss()
     menuControl.open()
-  }, [menuControl])
+  }, [menuControl, playHaptic])
 
   const shrink = React.useCallback(() => {
     'worklet'
     cancelAnimation(scale)
-    scale.value = withTiming(1, {duration: 200}, () => {
-      animationDidComplete.value = false
-    })
-  }, [animationDidComplete, scale])
+    scale.value = withTiming(1, {duration: 200})
+  }, [scale])
 
-  const grow = React.useCallback(() => {
-    'worklet'
-    scale.value = withTiming(1.05, {duration: 450}, finished => {
-      if (!finished) return
-      animationDidComplete.value = true
-      runOnJS(playHaptic)()
-      runOnJS(open)()
+  const doubleTapGesture = Gesture.Tap()
+    .numberOfTaps(2)
+    .hitSlop(HITSLOP_10)
+    .onEnd(open)
 
-      shrink()
+  const pressAndHoldGesture = Gesture.LongPress()
+    .onStart(() => {
+      scale.value = withTiming(1.05, {duration: 200}, finished => {
+        if (!finished) return
+        runOnJS(open)()
+        shrink()
+      })
     })
-  }, [scale, animationDidComplete, playHaptic, shrink, open])
+    .onTouchesUp(shrink)
+    .onTouchesMove(shrink)
+    .cancelsTouchesInView(false)
+    .runOnJS(true)
+
+  const composedGestures = Gesture.Exclusive(
+    doubleTapGesture,
+    pressAndHoldGesture,
+  )
 
   return (
-    <View
-      style={[
-        {
-          maxWidth: '80%',
-        },
-        isFromSelf ? a.self_end : a.self_start,
-      ]}>
-      <AnimatedPressable
-        style={animatedStyle}
-        unstable_pressDelay={200}
-        onPressIn={grow}
-        onTouchEnd={shrink}
-        hitSlop={HITSLOP_10}>
+    <GestureDetector gesture={composedGestures}>
+      <Animated.View
+        style={[
+          {
+            maxWidth: '80%',
+          },
+          isFromSelf ? a.self_end : a.self_start,
+          animatedStyle,
+        ]}>
         {children}
-      </AnimatedPressable>
-      <MessageMenu message={message} control={menuControl} />
-    </View>
+        <MessageMenu message={message} control={menuControl} />
+      </Animated.View>
+    </GestureDetector>
   )
 }