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