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 {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}