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