about summary refs log tree commit diff
path: root/src/screens/Settings/components/CopyButton.tsx
blob: 5bc9e84c553c04854b99e09440acec6dda1199f1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import {useCallback, useEffect, useState} from 'react'
import {type GestureResponderEvent, View} from 'react-native'
import Animated, {
  FadeOutUp,
  useReducedMotion,
  ZoomIn,
} from 'react-native-reanimated'
import * as Clipboard from 'expo-clipboard'
import {Trans} from '@lingui/macro'

import {atoms as a, useTheme} from '#/alf'
import {Button, type ButtonProps} from '#/components/Button'
import {Text} from '#/components/Typography'

export function CopyButton({
  style,
  value,
  onPress: onPressProp,
  ...props
}: ButtonProps & {value: string}) {
  const [hasBeenCopied, setHasBeenCopied] = useState(false)
  const t = useTheme()
  const isReducedMotionEnabled = useReducedMotion()

  useEffect(() => {
    if (hasBeenCopied) {
      const timeout = setTimeout(
        () => setHasBeenCopied(false),
        isReducedMotionEnabled ? 2000 : 100,
      )
      return () => clearTimeout(timeout)
    }
  }, [hasBeenCopied, isReducedMotionEnabled])

  const onPress = useCallback(
    (evt: GestureResponderEvent) => {
      Clipboard.setStringAsync(value)
      setHasBeenCopied(true)
      onPressProp?.(evt)
    },
    [value, onPressProp],
  )

  return (
    <View style={[a.relative]}>
      {hasBeenCopied && (
        <Animated.View
          entering={ZoomIn.duration(100)}
          exiting={FadeOutUp.duration(2000)}
          style={[
            a.absolute,
            {bottom: '100%', right: 0},
            a.justify_center,
            a.gap_sm,
            a.z_10,
            a.pb_sm,
          ]}
          pointerEvents="none">
          <Text
            style={[
              a.font_bold,
              a.text_right,
              a.text_md,
              t.atoms.text_contrast_high,
            ]}>
            <Trans>Copied!</Trans>
          </Text>
        </Animated.View>
      )}
      <Button
        style={[a.flex_1, a.justify_between, style]}
        onPress={onPress}
        {...props}
      />
    </View>
  )
}