Files
bsky-social-app/src/screens/Messages/components/CopyTextButton.tsx
T
Eric Bailey cdb8d4bfb8 Group Clops Feature Branch (#10360)
Co-authored-by: DS Boyce <260543580+ds-boyce@users.noreply.github.com>
Co-authored-by: Samuel Newman <mozzius@protonmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-24 11:38:50 -07:00

91 lines
2.4 KiB
TypeScript

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/react/macro'
import {atoms as a, useTheme} from '#/alf'
import {Button, ButtonIcon, type ButtonProps} from '#/components/Button'
import {SquareBehindSquare_Stroke2_Corner2_Rounded as CopyIcon} from '#/components/icons/SquareBehindSquare4'
import {Text} from '#/components/Typography'
export function CopyTextButton({
children,
disabled,
style,
value,
onPress: onPressProp,
...props
}: ButtonProps & {value: string}) {
const t = useTheme()
const [hasBeenCopied, setHasBeenCopied] = useState(false)
const isReducedMotionEnabled = useReducedMotion()
useEffect(() => {
if (hasBeenCopied) {
const timeout = setTimeout(
() => setHasBeenCopied(false),
isReducedMotionEnabled ? 2000 : 100,
)
return () => clearTimeout(timeout)
}
}, [hasBeenCopied, isReducedMotionEnabled])
const onPress = useCallback(
(evt: GestureResponderEvent) => {
void 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_medium,
a.text_right,
a.text_sm,
t.atoms.text_contrast_high,
]}>
<Trans>Copied!</Trans>
</Text>
</Animated.View>
)}
<Button
color="secondary"
disabled={disabled}
style={[a.flex_1, a.justify_between, {borderRadius: 10}, style]}
onPress={onPress}
{...props}>
{context => (
<View style={[a.flex_1, a.flex_row, a.justify_between, a.p_md]}>
{typeof children === 'function' ? children(context) : children}
{disabled ? null : <ButtonIcon icon={CopyIcon} size="lg" />}
</View>
)}
</Button>
</View>
)
}