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 {useEnableSquareButtons} from '#/state/preferences/enable-square-buttons'
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 enableSquareButtons = useEnableSquareButtons()
32
33 const {data: convoAvailability} = useGetConvoAvailabilityQuery(profile.did)
34 const {mutate: initiateConvo} = useGetConvoForMembers({
35 onSuccess: ({convo}) => {
36 ax.metric('chat:open', {logContext: 'ProfileHeader'})
37 navigation.navigate('MessagesConversation', {conversation: convo.id})
38 },
39 onError: () => {
40 Toast.show(_(msg`Failed to create conversation`))
41 },
42 })
43
44 const onPress = React.useCallback(() => {
45 if (!convoAvailability?.canChat) {
46 return
47 }
48
49 if (convoAvailability.convo) {
50 ax.metric('chat:open', {logContext: 'ProfileHeader'})
51 navigation.navigate('MessagesConversation', {
52 conversation: convoAvailability.convo.id,
53 })
54 } else {
55 ax.metric('chat:create', {logContext: 'ProfileHeader'})
56 initiateConvo([profile.did])
57 }
58 }, [ax, navigation, profile.did, initiateConvo, convoAvailability])
59
60 const wrappedOnPress = requireEmailVerification(onPress, {
61 instructions: [
62 <Trans key="message">
63 Before you can message another user, you must first verify your email.
64 </Trans>,
65 ],
66 })
67
68 if (!convoAvailability) {
69 // show pending state based on declaration
70 if (canBeMessaged(profile)) {
71 return (
72 <View
73 testID="dmBtnLoading"
74 aria-hidden={true}
75 style={[
76 a.justify_center,
77 a.align_center,
78 t.atoms.bg_contrast_25,
79 enableSquareButtons ? a.rounded_sm : a.rounded_full,
80 // Matches size of button below to avoid layout shift
81 {width: 33, height: 33},
82 ]}>
83 <Message style={[t.atoms.text, {opacity: 0.3}]} size="md" />
84 </View>
85 )
86 } else {
87 return null
88 }
89 }
90
91 if (convoAvailability.canChat) {
92 return (
93 <>
94 <Button
95 accessibilityRole="button"
96 testID="dmBtn"
97 size="small"
98 color="secondary"
99 variant="solid"
100 shape={enableSquareButtons ? 'square' : 'round'}
101 label={_(msg`Message ${profile.handle}`)}
102 style={[a.justify_center]}
103 onPress={wrappedOnPress}>
104 <ButtonIcon icon={Message} size="md" />
105 </Button>
106 </>
107 )
108 } else {
109 return null
110 }
111}