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