forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {useCallback, useEffect, useState} from 'react'
2import {type GestureResponderEvent, View} from 'react-native'
3import Animated, {
4 FadeOutUp,
5 useReducedMotion,
6 ZoomIn,
7} from 'react-native-reanimated'
8import * as Clipboard from 'expo-clipboard'
9import {Trans} from '@lingui/react/macro'
10
11import {atoms as a, useTheme} from '#/alf'
12import {Button, ButtonIcon, type ButtonProps} from '#/components/Button'
13import {SquareBehindSquare_Stroke2_Corner2_Rounded as CopyIcon} from '#/components/icons/SquareBehindSquare4'
14import {Text} from '#/components/Typography'
15
16export function CopyTextButton({
17 children,
18 disabled,
19 style,
20 value,
21 onPress: onPressProp,
22 ...props
23}: ButtonProps & {value: string}) {
24 const t = useTheme()
25
26 const [hasBeenCopied, setHasBeenCopied] = useState(false)
27
28 const isReducedMotionEnabled = useReducedMotion()
29
30 useEffect(() => {
31 if (hasBeenCopied) {
32 const timeout = setTimeout(
33 () => setHasBeenCopied(false),
34 isReducedMotionEnabled ? 2000 : 100,
35 )
36 return () => clearTimeout(timeout)
37 }
38 }, [hasBeenCopied, isReducedMotionEnabled])
39
40 const onPress = useCallback(
41 (evt: GestureResponderEvent) => {
42 void Clipboard.setStringAsync(value)
43 setHasBeenCopied(true)
44 onPressProp?.(evt)
45 },
46 [value, onPressProp],
47 )
48
49 return (
50 <View style={[a.relative]}>
51 {hasBeenCopied && (
52 <Animated.View
53 entering={ZoomIn.duration(100)}
54 exiting={FadeOutUp.duration(2000)}
55 style={[
56 a.absolute,
57 {bottom: '100%', right: 0},
58 a.justify_center,
59 a.gap_sm,
60 a.z_10,
61 a.pb_sm,
62 ]}
63 pointerEvents="none">
64 <Text
65 style={[
66 a.font_medium,
67 a.text_right,
68 a.text_sm,
69 t.atoms.text_contrast_high,
70 ]}>
71 <Trans>Copied!</Trans>
72 </Text>
73 </Animated.View>
74 )}
75 <Button
76 color="secondary"
77 disabled={disabled}
78 style={[a.flex_1, a.justify_between, {borderRadius: 10}, style]}
79 onPress={onPress}
80 {...props}>
81 {context => (
82 <View style={[a.flex_1, a.flex_row, a.justify_between, a.p_md]}>
83 {typeof children === 'function' ? children(context) : children}
84 {disabled ? null : <ButtonIcon icon={CopyIcon} size="lg" />}
85 </View>
86 )}
87 </Button>
88 </View>
89 )
90}