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