From 8ba1b10ce0d278a88e37d6b6c277a41673392877 Mon Sep 17 00:00:00 2001 From: Hailey Date: Thu, 2 May 2024 13:54:17 -0700 Subject: [Clipclops] Message actions for native and web (#3807) * haptic on long press * add animation to press and hold * eslint disable for now * adjust styles * dont trigger if animation is cancelled * organize * add a delete menu * reset scale automatically * message actions dialog cleanup center the trigger handle focus/unfocus better make triggers accessible weg dropdown menu add a wep specific wrapper decrease press delay add report button improve shrink logic use `self_end` instead of `margin: auto` rm extra `?` move `MessageItem` to `components` add delete button * rm some padding * update after merge * fix merge * web only types * fix crash * add an explanation * fix web types --------- Co-authored-by: Samuel Newman --- src/components/dms/ActionsWrapper.tsx | 82 +++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 src/components/dms/ActionsWrapper.tsx (limited to 'src/components/dms/ActionsWrapper.tsx') diff --git a/src/components/dms/ActionsWrapper.tsx b/src/components/dms/ActionsWrapper.tsx new file mode 100644 index 000000000..107e5eb8e --- /dev/null +++ b/src/components/dms/ActionsWrapper.tsx @@ -0,0 +1,82 @@ +import React, {useCallback} from 'react' +import {Pressable, View} from 'react-native' +import Animated, { + cancelAnimation, + runOnJS, + useAnimatedStyle, + useSharedValue, + withTiming, +} from 'react-native-reanimated' +import {ChatBskyConvoDefs} from '@atproto-labs/api' + +import {useHaptics} from 'lib/haptics' +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, + children, +}: { + message: ChatBskyConvoDefs.MessageView + isFromSelf: boolean + children: React.ReactNode +}) { + const playHaptic = useHaptics() + 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 = useCallback(() => { + menuControl.open() + }, [menuControl]) + + const shrink = useCallback(() => { + 'worklet' + cancelAnimation(scale) + scale.value = withTiming(1, {duration: 200}, () => { + animationDidComplete.value = false + }) + }, [animationDidComplete, scale]) + + const grow = React.useCallback(() => { + 'worklet' + scale.value = withTiming(1.05, {duration: 750}, finished => { + if (!finished) return + animationDidComplete.value = true + runOnJS(playHaptic)() + runOnJS(open)() + + shrink() + }) + }, [scale, animationDidComplete, playHaptic, shrink, open]) + + return ( + + + {children} + + + + ) +} -- cgit 1.4.1