diff options
author | Eric Bailey <git@esb.lol> | 2024-05-20 18:56:44 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-20 16:56:44 -0700 |
commit | a7b0242cc8aaf09273abe20903e88e59a4acd1a7 (patch) | |
tree | 9e3f21bcf0def435877e2a1a9c5fc8eedc6c7950 /src/components/dms/ChatEmptyPill.tsx | |
parent | 6dde48756366008a897bfffdcec6c1756df59ef4 (diff) | |
download | voidsky-a7b0242cc8aaf09273abe20903e88e59a4acd1a7.tar.zst |
[🐴] Empty chat prompt (#4132)
* Add empty chat pill * Tweak padding * move to `components`, place inside `KeyboardStickyView` * cleanup unused vars * add a new animation type * (unrelated) add haptic to long press * adjust shrink and pop --------- Co-authored-by: Hailey <me@haileyok.com>
Diffstat (limited to 'src/components/dms/ChatEmptyPill.tsx')
-rw-r--r-- | src/components/dms/ChatEmptyPill.tsx | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/src/components/dms/ChatEmptyPill.tsx b/src/components/dms/ChatEmptyPill.tsx new file mode 100644 index 000000000..a6c4906a6 --- /dev/null +++ b/src/components/dms/ChatEmptyPill.tsx @@ -0,0 +1,98 @@ +import React from 'react' +import {Pressable, View} from 'react-native' +import Animated, { + runOnJS, + useAnimatedStyle, + useSharedValue, + withTiming, +} from 'react-native-reanimated' +import {msg} from '@lingui/macro' +import {useLingui} from '@lingui/react' + +import {ScaleAndFadeIn} from 'lib/custom-animations/ScaleAndFade' +import {ShrinkAndPop} from 'lib/custom-animations/ShrinkAndPop' +import {useHaptics} from 'lib/haptics' +import {isWeb} from 'platform/detection' +import {atoms as a, useTheme} from '#/alf' +import {Text} from '#/components/Typography' + +const AnimatedPressable = Animated.createAnimatedComponent(Pressable) + +let lastIndex = 0 + +export function ChatEmptyPill() { + const t = useTheme() + const {_} = useLingui() + const playHaptic = useHaptics() + const [promptIndex, setPromptIndex] = React.useState(lastIndex) + + const scale = useSharedValue(1) + + const prompts = React.useMemo(() => { + return [ + _(msg`Say hello!`), + _(msg`Share your favorite feed!`), + _(msg`Tell a joke!`), + _(msg`Share a fun fact!`), + _(msg`Share a cool story!`), + _(msg`Send a neat website!`), + _(msg`Clip 🐴 clop 🐴`), + ] + }, [_]) + + const onPressIn = React.useCallback(() => { + if (isWeb) return + scale.value = withTiming(1.075, {duration: 100}) + }, [scale]) + + const onPressOut = React.useCallback(() => { + if (isWeb) return + scale.value = withTiming(1, {duration: 100}) + }, [scale]) + + const onPress = React.useCallback(() => { + runOnJS(playHaptic)() + let randomPromptIndex = Math.floor(Math.random() * prompts.length) + while (randomPromptIndex === lastIndex) { + randomPromptIndex = Math.floor(Math.random() * prompts.length) + } + setPromptIndex(randomPromptIndex) + lastIndex = randomPromptIndex + }, [playHaptic, prompts.length]) + + const animatedStyle = useAnimatedStyle(() => ({ + transform: [{scale: scale.value}], + })) + + return ( + <View + style={[ + a.absolute, + a.w_full, + a.z_10, + a.align_center, + { + bottom: 70, + }, + ]}> + <AnimatedPressable + style={[ + a.px_xl, + a.py_md, + a.rounded_full, + t.atoms.bg_contrast_25, + a.align_center, + animatedStyle, + ]} + entering={ScaleAndFadeIn} + exiting={ShrinkAndPop} + onPress={onPress} + onPressIn={onPressIn} + onPressOut={onPressOut}> + <Text style={[a.font_bold, a.pointer_events_none]} selectable={false}> + {prompts[promptIndex]} + </Text> + </AnimatedPressable> + </View> + ) +} |