forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {memo, useMemo} from 'react'
2import * as ExpoClipboard from 'expo-clipboard'
3import {AtUri} 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 {makeProfileLink} from '#/lib/routes/links'
10import {type NavigationProp} from '#/lib/routes/types'
11import {shareText, shareUrl} from '#/lib/sharing'
12import {toShareUrl} from '#/lib/strings/url-helpers'
13import {useProfileShadow} from '#/state/cache/profile-shadow'
14import {useSession} from '#/state/session'
15import * as Toast from '#/view/com/util/Toast'
16import {atoms as a} from '#/alf'
17import {Admonition} from '#/components/Admonition'
18import {useDialogControl} from '#/components/Dialog'
19import {SendViaChatDialog} from '#/components/dms/dialogs/ShareViaChatDialog'
20import {ArrowOutOfBoxModified_Stroke2_Corner2_Rounded as ArrowOutOfBoxIcon} from '#/components/icons/ArrowOutOfBox'
21import {ChainLink_Stroke2_Corner0_Rounded as ChainLinkIcon} from '#/components/icons/ChainLink'
22import {Clipboard_Stroke2_Corner2_Rounded as ClipboardIcon} from '#/components/icons/Clipboard'
23import {PaperPlane_Stroke2_Corner0_Rounded as PaperPlaneIcon} from '#/components/icons/PaperPlane'
24import * as Menu from '#/components/Menu'
25import {useAgeAssurance} from '#/ageAssurance'
26import {useAnalytics} from '#/analytics'
27import {IS_IOS} from '#/env'
28import {useDevMode} from '#/storage/hooks/dev-mode'
29import {RecentChats} from './RecentChats'
30import {type ShareMenuItemsProps} from './ShareMenuItems.types'
31
32let ShareMenuItems = ({
33 post,
34 onShare: onShareProp,
35}: ShareMenuItemsProps): React.ReactNode => {
36 const ax = useAnalytics()
37 const {hasSession} = useSession()
38 const {_} = useLingui()
39 const navigation = useNavigation<NavigationProp>()
40 const sendViaChatControl = useDialogControl()
41 const [devModeEnabled] = useDevMode()
42 const aa = useAgeAssurance()
43
44 const postUri = post.uri
45 const postAuthor = useProfileShadow(post.author)
46
47 const href = useMemo(() => {
48 const urip = new AtUri(postUri)
49 return makeProfileLink(postAuthor, 'post', urip.rkey)
50 }, [postUri, postAuthor])
51
52 const hideInPWI = useMemo(() => {
53 return !!postAuthor.labels?.find(
54 label => label.val === '!no-unauthenticated',
55 )
56 }, [postAuthor])
57
58 const onSharePost = () => {
59 ax.metric('share:press:nativeShare', {})
60 const url = toShareUrl(href)
61 shareUrl(url)
62 onShareProp()
63 }
64
65 const onCopyLink = async () => {
66 ax.metric('share:press:copyLink', {})
67 const url = toShareUrl(href)
68 if (IS_IOS) {
69 // iOS only
70 await ExpoClipboard.setUrlAsync(url)
71 } else {
72 await ExpoClipboard.setStringAsync(url)
73 }
74 Toast.show(_(msg`Copied to clipboard`), 'clipboard-check')
75 onShareProp()
76 }
77
78 const onSelectChatToShareTo = (conversation: string) => {
79 navigation.navigate('MessagesConversation', {
80 conversation,
81 embed: postUri,
82 })
83 }
84
85 const onShareATURI = () => {
86 shareText(postUri)
87 }
88
89 const onShareAuthorDID = () => {
90 shareText(postAuthor.did)
91 }
92
93 return (
94 <>
95 <Menu.Outer>
96 {hasSession && aa.state.access === aa.Access.Full && (
97 <Menu.Group>
98 <Menu.ContainerItem>
99 <RecentChats postUri={postUri} />
100 </Menu.ContainerItem>
101 <Menu.Item
102 testID="postDropdownSendViaDMBtn"
103 label={_(msg`Send via direct message`)}
104 onPress={() => {
105 ax.metric('share:press:openDmSearch', {})
106 sendViaChatControl.open()
107 }}>
108 <Menu.ItemText>
109 <Trans>Send via direct message</Trans>
110 </Menu.ItemText>
111 <Menu.ItemIcon icon={PaperPlaneIcon} position="right" />
112 </Menu.Item>
113 </Menu.Group>
114 )}
115
116 <Menu.Group>
117 <Menu.Item
118 testID="postDropdownShareBtn"
119 label={_(msg`Share via...`)}
120 onPress={onSharePost}>
121 <Menu.ItemText>
122 <Trans>Share via...</Trans>
123 </Menu.ItemText>
124 <Menu.ItemIcon icon={ArrowOutOfBoxIcon} position="right" />
125 </Menu.Item>
126
127 <Menu.Item
128 testID="postDropdownShareBtn"
129 label={_(msg`Copy link to post`)}
130 onPress={onCopyLink}>
131 <Menu.ItemText>
132 <Trans>Copy link to post</Trans>
133 </Menu.ItemText>
134 <Menu.ItemIcon icon={ChainLinkIcon} position="right" />
135 </Menu.Item>
136 </Menu.Group>
137
138 {hideInPWI && (
139 <Menu.Group>
140 <Menu.ContainerItem>
141 <Admonition
142 type="warning"
143 style={[a.flex_1, a.border_0, a.p_0, a.bg_transparent]}>
144 <Trans>This post is only visible to logged-in users.</Trans>
145 </Admonition>
146 </Menu.ContainerItem>
147 </Menu.Group>
148 )}
149
150 {devModeEnabled && (
151 <Menu.Group>
152 <Menu.Item
153 testID="postAtUriShareBtn"
154 label={_(msg`Share post at:// URI`)}
155 onPress={onShareATURI}>
156 <Menu.ItemText>
157 <Trans>Share post at:// URI</Trans>
158 </Menu.ItemText>
159 <Menu.ItemIcon icon={ClipboardIcon} position="right" />
160 </Menu.Item>
161 <Menu.Item
162 testID="postAuthorDIDShareBtn"
163 label={_(msg`Share author DID`)}
164 onPress={onShareAuthorDID}>
165 <Menu.ItemText>
166 <Trans>Share author DID</Trans>
167 </Menu.ItemText>
168 <Menu.ItemIcon icon={ClipboardIcon} position="right" />
169 </Menu.Item>
170 </Menu.Group>
171 )}
172 </Menu.Outer>
173
174 <SendViaChatDialog
175 control={sendViaChatControl}
176 onSelectChat={onSelectChatToShareTo}
177 />
178 </>
179 )
180}
181ShareMenuItems = memo(ShareMenuItems)
182export {ShareMenuItems}