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