diff options
author | Hailey <me@haileyok.com> | 2024-05-02 13:54:17 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-02 13:54:17 -0700 |
commit | 8ba1b10ce0d278a88e37d6b6c277a41673392877 (patch) | |
tree | 1e44ec05c427aaa124077b6fb9ce01c831daa8b3 /src/components/dms/ActionsWrapper.tsx | |
parent | 6da18e3dcffaf72a03bde8a205a596b4b3366b86 (diff) | |
download | voidsky-8ba1b10ce0d278a88e37d6b6c277a41673392877.tar.zst |
[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 <mozzius@protonmail.com>
Diffstat (limited to 'src/components/dms/ActionsWrapper.tsx')
-rw-r--r-- | src/components/dms/ActionsWrapper.tsx | 82 |
1 files changed, 82 insertions, 0 deletions
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 ( + <View + style={[ + { + maxWidth: '65%', + }, + isFromSelf ? a.self_end : a.self_start, + ]}> + <AnimatedPressable + style={animatedStyle} + unstable_pressDelay={200} + onPressIn={grow} + onTouchEnd={shrink}> + {children} + </AnimatedPressable> + <MessageMenu message={message} control={menuControl} hideTrigger={true} /> + </View> + ) +} |