Bluesky app fork with some witchin' additions 馃挮
at 2ad84d7dfcefdb2a05b32fae284b2ade042b01b9 181 lines 6.0 kB view raw
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}