Bluesky app fork with some witchin' additions 馃挮
at jean/pds-label 112 lines 3.6 kB view raw
1import React from 'react' 2import {View} from 'react-native' 3import {type AppBskyActorDefs} from '@atproto/api' 4import {msg} from '@lingui/core/macro' 5import {useLingui} from '@lingui/react' 6import {Trans} from '@lingui/react/macro' 7import {useNavigation} from '@react-navigation/native' 8 9import {useRequireEmailVerification} from '#/lib/hooks/useRequireEmailVerification' 10import {type NavigationProp} from '#/lib/routes/types' 11import {useEnableSquareButtons} from '#/state/preferences/enable-square-buttons' 12import {useGetConvoAvailabilityQuery} from '#/state/queries/messages/get-convo-availability' 13import {useGetConvoForMembers} from '#/state/queries/messages/get-convo-for-members' 14import * as Toast from '#/view/com/util/Toast' 15import {atoms as a, useTheme} from '#/alf' 16import {Button, ButtonIcon} from '#/components/Button' 17import {canBeMessaged} from '#/components/dms/util' 18import {Message_Stroke2_Corner0_Rounded as Message} from '#/components/icons/Message' 19import {useAnalytics} from '#/analytics' 20 21export function MessageProfileButton({ 22 profile, 23}: { 24 profile: AppBskyActorDefs.ProfileViewDetailed 25}) { 26 const {_} = useLingui() 27 const t = useTheme() 28 const ax = useAnalytics() 29 const navigation = useNavigation<NavigationProp>() 30 const requireEmailVerification = useRequireEmailVerification() 31 32 const enableSquareButtons = useEnableSquareButtons() 33 34 const {data: convoAvailability} = useGetConvoAvailabilityQuery(profile.did) 35 const {mutate: initiateConvo} = useGetConvoForMembers({ 36 onSuccess: ({convo}) => { 37 ax.metric('chat:open', {logContext: 'ProfileHeader'}) 38 navigation.navigate('MessagesConversation', {conversation: convo.id}) 39 }, 40 onError: () => { 41 Toast.show(_(msg`Failed to create conversation`)) 42 }, 43 }) 44 45 const onPress = React.useCallback(() => { 46 if (!convoAvailability?.canChat) { 47 return 48 } 49 50 if (convoAvailability.convo) { 51 ax.metric('chat:open', {logContext: 'ProfileHeader'}) 52 navigation.navigate('MessagesConversation', { 53 conversation: convoAvailability.convo.id, 54 }) 55 } else { 56 ax.metric('chat:create', {logContext: 'ProfileHeader'}) 57 initiateConvo([profile.did]) 58 } 59 }, [ax, navigation, profile.did, initiateConvo, convoAvailability]) 60 61 const wrappedOnPress = requireEmailVerification(onPress, { 62 instructions: [ 63 <Trans key="message"> 64 Before you can message another user, you must first verify your email. 65 </Trans>, 66 ], 67 }) 68 69 if (!convoAvailability) { 70 // show pending state based on declaration 71 if (canBeMessaged(profile)) { 72 return ( 73 <View 74 testID="dmBtnLoading" 75 aria-hidden={true} 76 style={[ 77 a.justify_center, 78 a.align_center, 79 t.atoms.bg_contrast_25, 80 enableSquareButtons ? a.rounded_sm : a.rounded_full, 81 // Matches size of button below to avoid layout shift 82 {width: 33, height: 33}, 83 ]}> 84 <Message style={[t.atoms.text, {opacity: 0.3}]} size="md" /> 85 </View> 86 ) 87 } else { 88 return null 89 } 90 } 91 92 if (convoAvailability.canChat) { 93 return ( 94 <> 95 <Button 96 accessibilityRole="button" 97 testID="dmBtn" 98 size="small" 99 color="secondary" 100 variant="solid" 101 shape={enableSquareButtons ? 'square' : 'round'} 102 label={_(msg`Message ${profile.handle}`)} 103 style={[a.justify_center]} 104 onPress={wrappedOnPress}> 105 <ButtonIcon icon={Message} size="md" /> 106 </Button> 107 </> 108 ) 109 } else { 110 return null 111 } 112}