Bluesky app fork with some witchin' additions 馃挮
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 271 lines 8.9 kB view raw
1import {memo, useMemo} from 'react' 2import * as ExpoClipboard from 'expo-clipboard' 3import {AtUri} from '@atproto/api' 4import {isIOS} from '@bsky.app/alf' 5import {msg} from '@lingui/core/macro' 6import {useLingui} from '@lingui/react' 7import {Trans} from '@lingui/react/macro' 8import {useNavigation} from '@react-navigation/native' 9 10import {useOpenLink} from '#/lib/hooks/useOpenLink' 11import {makeProfileLink} from '#/lib/routes/links' 12import {type NavigationProp} from '#/lib/routes/types' 13import {shareText, shareUrl} from '#/lib/sharing' 14import {toShareUrl, toShareUrlBsky} from '#/lib/strings/url-helpers' 15import {useProfileShadow} from '#/state/cache/profile-shadow' 16import {useShowExternalShareButtons} from '#/state/preferences/external-share-buttons' 17import {useSession} from '#/state/session' 18import {atoms as a} from '#/alf' 19import {Admonition} from '#/components/Admonition' 20import {useDialogControl} from '#/components/Dialog' 21import {SendViaChatDialog} from '#/components/dms/dialogs/ShareViaChatDialog' 22import {ArrowOutOfBoxModified_Stroke2_Corner2_Rounded as ArrowOutOfBoxIcon} from '#/components/icons/ArrowOutOfBox' 23import {ChainLink_Stroke2_Corner0_Rounded as ChainLinkIcon} from '#/components/icons/ChainLink' 24import {Clipboard_Stroke2_Corner2_Rounded as ClipboardIcon} from '#/components/icons/Clipboard' 25import {PaperPlane_Stroke2_Corner0_Rounded as PaperPlaneIcon} from '#/components/icons/PaperPlane' 26import {SquareArrowTopRight_Stroke2_Corner0_Rounded as ExternalIcon} from '#/components/icons/SquareArrowTopRight' 27import * as Menu from '#/components/Menu' 28import * as Toast from '#/components/Toast' 29import {useAgeAssurance} from '#/ageAssurance' 30import {useAnalytics} from '#/analytics' 31import {IS_IOS} from '#/env' 32import {useDevMode} from '#/storage/hooks/dev-mode' 33import {RecentChats} from './RecentChats' 34import {type ShareMenuItemsProps} from './ShareMenuItems.types' 35 36let ShareMenuItems = ({ 37 post, 38 onShare: onShareProp, 39}: ShareMenuItemsProps): React.ReactNode => { 40 const ax = useAnalytics() 41 const {hasSession} = useSession() 42 const {_} = useLingui() 43 const navigation = useNavigation<NavigationProp>() 44 const sendViaChatControl = useDialogControl() 45 const [devModeEnabled] = useDevMode() 46 const aa = useAgeAssurance() 47 const openLink = useOpenLink() 48 49 const postUri = post.uri 50 const postAuthor = useProfileShadow(post.author) 51 52 const href = useMemo(() => { 53 const urip = new AtUri(postUri) 54 return makeProfileLink(postAuthor, 'post', urip.rkey) 55 }, [postUri, postAuthor]) 56 57 const hideInPWI = useMemo(() => { 58 return !!postAuthor.labels?.find( 59 label => label.val === '!no-unauthenticated', 60 ) 61 }, [postAuthor]) 62 63 const onSharePost = () => { 64 ax.metric('share:press:nativeShare', {}) 65 const url = toShareUrl(href) 66 shareUrl(url) 67 onShareProp() 68 } 69 70 const onSharePostBsky = () => { 71 ax.metric('share:press:nativeShare', {}) 72 const url = toShareUrlBsky(href) 73 shareUrl(url) 74 onShareProp() 75 } 76 77 const onCopyLink = async () => { 78 ax.metric('share:press:copyLink', {}) 79 const url = toShareUrl(href) 80 if (IS_IOS) { 81 // iOS only 82 await ExpoClipboard.setUrlAsync(url) 83 } else { 84 await ExpoClipboard.setStringAsync(url) 85 } 86 Toast.show(_(msg`Copied to clipboard`), { 87 type: 'success', 88 }) 89 onShareProp() 90 } 91 92 const onCopyLinkBsky = async () => { 93 ax.metric('share:press:copyLink', {}) 94 const url = toShareUrlBsky(href) 95 if (isIOS) { 96 // iOS only 97 await ExpoClipboard.setUrlAsync(url) 98 } else { 99 await ExpoClipboard.setStringAsync(url) 100 } 101 Toast.show(_(msg`Copied to clipboard`), 'clipboard-check') 102 onShareProp() 103 } 104 105 const onSelectChatToShareTo = (conversation: string) => { 106 navigation.navigate('MessagesConversation', { 107 conversation, 108 embed: postUri, 109 }) 110 } 111 112 const onShareATURI = () => { 113 shareText(postUri) 114 } 115 116 const onShareAuthorDID = () => { 117 shareText(postAuthor.did) 118 } 119 120 const showExternalShareButtons = useShowExternalShareButtons() 121 const isBridgedPost = 122 !!post.record.bridgyOriginalUrl || !!post.record.fediverseId 123 const originalPostUrl = (post.record.bridgyOriginalUrl || 124 post.record.fediverseId) as string | undefined 125 126 const onOpenOriginalPost = () => { 127 if (originalPostUrl) { 128 openLink(originalPostUrl, true) 129 } 130 } 131 132 const onOpenPostInPdsls = () => { 133 openLink(`https://pdsls.dev/${post.uri}`, true) 134 } 135 136 return ( 137 <> 138 <Menu.Outer> 139 {hasSession && aa.state.access === aa.Access.Full && ( 140 <Menu.Group> 141 <Menu.ContainerItem> 142 <RecentChats postUri={postUri} /> 143 </Menu.ContainerItem> 144 <Menu.Item 145 testID="postDropdownSendViaDMBtn" 146 label={_(msg`Send via direct message`)} 147 onPress={() => { 148 ax.metric('share:press:openDmSearch', {}) 149 sendViaChatControl.open() 150 }}> 151 <Menu.ItemText> 152 <Trans>Send via direct message</Trans> 153 </Menu.ItemText> 154 <Menu.ItemIcon icon={PaperPlaneIcon} position="right" /> 155 </Menu.Item> 156 </Menu.Group> 157 )} 158 159 {showExternalShareButtons && ( 160 <Menu.Group> 161 {isBridgedPost && ( 162 <Menu.Item 163 testID="postDropdownOpenOriginalPost" 164 label={_(msg`Open original post`)} 165 onPress={onOpenOriginalPost}> 166 <Menu.ItemText> 167 <Trans>Open original post</Trans> 168 </Menu.ItemText> 169 <Menu.ItemIcon icon={ExternalIcon} position="right" /> 170 </Menu.Item> 171 )} 172 173 <Menu.Item 174 testID="postDropdownOpenInPdsls" 175 label={_(msg`Open post in PDSls`)} 176 onPress={onOpenPostInPdsls}> 177 <Menu.ItemText> 178 <Trans>Open post in PDSls</Trans> 179 </Menu.ItemText> 180 <Menu.ItemIcon icon={ExternalIcon} position="right" /> 181 </Menu.Item> 182 </Menu.Group> 183 )} 184 185 <Menu.Group> 186 <Menu.Item 187 testID="postDropdownShareBtn" 188 label={_(msg`Share via...`)} 189 onPress={onSharePost}> 190 <Menu.ItemText> 191 <Trans>Share via...</Trans> 192 </Menu.ItemText> 193 <Menu.ItemIcon icon={ArrowOutOfBoxIcon} position="right" /> 194 </Menu.Item> 195 196 <Menu.Item 197 testID="postDropdownShareBtn" 198 label={_(msg`Share via bsky.app...`)} 199 onPress={onSharePostBsky}> 200 <Menu.ItemText> 201 <Trans>Share via bsky.app...</Trans> 202 </Menu.ItemText> 203 <Menu.ItemIcon icon={ArrowOutOfBoxIcon} position="right" /> 204 </Menu.Item> 205 206 <Menu.Item 207 testID="postDropdownShareBtn" 208 label={_(msg`Copy link to post`)} 209 onPress={onCopyLink}> 210 <Menu.ItemText> 211 <Trans>Copy link to post</Trans> 212 </Menu.ItemText> 213 <Menu.ItemIcon icon={ChainLinkIcon} position="right" /> 214 </Menu.Item> 215 216 <Menu.Item 217 testID="postDropdownShareBtn" 218 label={_(msg`Copy via bsky.app`)} 219 onPress={onCopyLinkBsky}> 220 <Menu.ItemText> 221 <Trans>Copy via bsky.app</Trans> 222 </Menu.ItemText> 223 <Menu.ItemIcon icon={ChainLinkIcon} position="right" /> 224 </Menu.Item> 225 </Menu.Group> 226 227 {hideInPWI && ( 228 <Menu.Group> 229 <Menu.ContainerItem> 230 <Admonition 231 type="warning" 232 style={[a.flex_1, a.border_0, a.p_0, a.bg_transparent]}> 233 <Trans>This post is only visible to logged-in users.</Trans> 234 </Admonition> 235 </Menu.ContainerItem> 236 </Menu.Group> 237 )} 238 239 {devModeEnabled && ( 240 <Menu.Group> 241 <Menu.Item 242 testID="postAtUriShareBtn" 243 label={_(msg`Share post at:// URI`)} 244 onPress={onShareATURI}> 245 <Menu.ItemText> 246 <Trans>Share post at:// URI</Trans> 247 </Menu.ItemText> 248 <Menu.ItemIcon icon={ClipboardIcon} position="right" /> 249 </Menu.Item> 250 <Menu.Item 251 testID="postAuthorDIDShareBtn" 252 label={_(msg`Share author DID`)} 253 onPress={onShareAuthorDID}> 254 <Menu.ItemText> 255 <Trans>Share author DID</Trans> 256 </Menu.ItemText> 257 <Menu.ItemIcon icon={ClipboardIcon} position="right" /> 258 </Menu.Item> 259 </Menu.Group> 260 )} 261 </Menu.Outer> 262 263 <SendViaChatDialog 264 control={sendViaChatControl} 265 onSelectChat={onSelectChatToShareTo} 266 /> 267 </> 268 ) 269} 270ShareMenuItems = memo(ShareMenuItems) 271export {ShareMenuItems}