Bluesky app fork with some witchin' additions 馃挮
at readme-update 247 lines 7.9 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 {useOpenLink} from '#/lib/hooks/useOpenLink' 8import {makeProfileLink} from '#/lib/routes/links' 9import {type NavigationProp} from '#/lib/routes/types' 10import {shareText, shareUrl} from '#/lib/sharing' 11import {toShareUrl, toShareUrlBsky} from '#/lib/strings/url-helpers' 12import {useProfileShadow} from '#/state/cache/profile-shadow' 13import {useShowExternalShareButtons} from '#/state/preferences/external-share-buttons' 14import {useSession} from '#/state/session' 15import {useBreakpoints} from '#/alf' 16import {useDialogControl} from '#/components/Dialog' 17import {EmbedDialog} from '#/components/dialogs/Embed' 18import {SendViaChatDialog} from '#/components/dms/dialogs/ShareViaChatDialog' 19import {ChainLink_Stroke2_Corner0_Rounded as ChainLinkIcon} from '#/components/icons/ChainLink' 20import {Clipboard_Stroke2_Corner2_Rounded as ClipboardIcon} from '#/components/icons/Clipboard' 21import {CodeBrackets_Stroke2_Corner0_Rounded as CodeBracketsIcon} from '#/components/icons/CodeBrackets' 22import {PaperPlane_Stroke2_Corner0_Rounded as Send} from '#/components/icons/PaperPlane' 23import {SquareArrowTopRight_Stroke2_Corner0_Rounded as ExternalIcon} from '#/components/icons/SquareArrowTopRight' 24import * as Menu from '#/components/Menu' 25import {useAgeAssurance} from '#/ageAssurance' 26import {useAnalytics} from '#/analytics' 27import {IS_WEB} from '#/env' 28import {useDevMode} from '#/storage/hooks/dev-mode' 29import {type ShareMenuItemsProps} from './ShareMenuItems.types' 30 31let ShareMenuItems = ({ 32 post, 33 record, 34 timestamp, 35 onShare: onShareProp, 36}: ShareMenuItemsProps): React.ReactNode => { 37 const ax = useAnalytics() 38 const {hasSession} = useSession() 39 const {gtMobile} = useBreakpoints() 40 const {_} = useLingui() 41 const navigation = useNavigation<NavigationProp>() 42 const embedPostControl = useDialogControl() 43 const sendViaChatControl = useDialogControl() 44 const [devModeEnabled] = useDevMode() 45 const aa = useAgeAssurance() 46 const openLink = useOpenLink() 47 48 const postUri = post.uri 49 const postCid = post.cid 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 onCopyLink = () => { 64 ax.metric('share:press:copyLink', {}) 65 const url = toShareUrl(href) 66 shareUrl(url) 67 onShareProp() 68 } 69 70 const onCopyLinkBsky = () => { 71 ax.metric('share:press:copyLink', {}) 72 const url = toShareUrlBsky(href) 73 shareUrl(url) 74 onShareProp() 75 } 76 77 const onSelectChatToShareTo = (conversation: string) => { 78 ax.metric('share:press:dmSelected', {}) 79 navigation.navigate('MessagesConversation', { 80 conversation, 81 embed: postUri, 82 }) 83 } 84 85 const canEmbed = IS_WEB && gtMobile && !hideInPWI 86 87 const onShareATURI = () => { 88 shareText(postUri) 89 } 90 91 const onShareAuthorDID = () => { 92 shareText(postAuthor.did) 93 } 94 95 const showExternalShareButtons = useShowExternalShareButtons() 96 const isBridgedPost = 97 !!post.record.bridgyOriginalUrl || !!post.record.fediverseId 98 const originalPostUrl = (post.record.bridgyOriginalUrl || 99 post.record.fediverseId) as string | undefined 100 101 const onOpenOriginalPost = () => { 102 if (originalPostUrl) { 103 openLink(originalPostUrl, true) 104 } 105 } 106 107 const onOpenPostInPdsls = () => { 108 openLink(`https://pdsls.dev/${post.uri}`, true) 109 } 110 111 const copyLinkItem = ( 112 <Menu.Group> 113 <Menu.Item 114 testID="postDropdownShareBtn" 115 label={_(msg`Copy link to post`)} 116 onPress={onCopyLink}> 117 <Menu.ItemText> 118 <Trans>Copy link to skeet</Trans> 119 </Menu.ItemText> 120 <Menu.ItemIcon icon={ChainLinkIcon} position="right" /> 121 </Menu.Item> 122 <Menu.Item 123 testID="postDropdownShareBtn" 124 label={_(msg`Copy link to post`)} 125 onPress={onCopyLinkBsky}> 126 <Menu.ItemText> 127 <Trans>Copy via bsky.app</Trans> 128 </Menu.ItemText> 129 <Menu.ItemIcon icon={ChainLinkIcon} position="right" /> 130 </Menu.Item> 131 </Menu.Group> 132 ) 133 134 return ( 135 <> 136 <Menu.Outer> 137 {copyLinkItem} 138 139 {showExternalShareButtons && isBridgedPost && ( 140 <Menu.Item 141 testID="postDropdownOpenOriginalPost" 142 label={_(msg`Open original post`)} 143 onPress={onOpenOriginalPost}> 144 <Menu.ItemText> 145 <Trans>Open original skeet</Trans> 146 </Menu.ItemText> 147 <Menu.ItemIcon icon={ExternalIcon} position="right" /> 148 </Menu.Item> 149 )} 150 151 {showExternalShareButtons && ( 152 <Menu.Item 153 testID="postDropdownOpenInPdsls" 154 label={_(msg`Open post in PDSls`)} 155 onPress={onOpenPostInPdsls}> 156 <Menu.ItemText> 157 <Trans>Open skeet in PDSls</Trans> 158 </Menu.ItemText> 159 <Menu.ItemIcon icon={ExternalIcon} position="right" /> 160 </Menu.Item> 161 )} 162 163 {hasSession && aa.state.access === aa.Access.Full && ( 164 <Menu.Item 165 testID="postDropdownSendViaDMBtn" 166 label={_(msg`Send via direct message`)} 167 onPress={() => { 168 ax.metric('share:press:openDmSearch', {}) 169 sendViaChatControl.open() 170 }}> 171 <Menu.ItemText> 172 <Trans>Send via direct message</Trans> 173 </Menu.ItemText> 174 <Menu.ItemIcon icon={Send} position="right" /> 175 </Menu.Item> 176 )} 177 178 {canEmbed && ( 179 <Menu.Item 180 testID="postDropdownEmbedBtn" 181 label={_(msg`Embed post`)} 182 onPress={() => { 183 ax.metric('share:press:embed', {}) 184 embedPostControl.open() 185 }}> 186 <Menu.ItemText>{_(msg`Embed skeet`)}</Menu.ItemText> 187 <Menu.ItemIcon icon={CodeBracketsIcon} position="right" /> 188 </Menu.Item> 189 )} 190 191 {false && hideInPWI && ( 192 <> 193 {hasSession && <Menu.Divider />} 194 {copyLinkItem} 195 <Menu.LabelText style={{maxWidth: 220}}> 196 <Trans> 197 Note: This skeet is only visible to logged-in users. 198 </Trans> 199 </Menu.LabelText> 200 </> 201 )} 202 203 {devModeEnabled && ( 204 <> 205 <Menu.Divider /> 206 <Menu.Item 207 testID="postAtUriShareBtn" 208 label={_(msg`Copy post at:// URI`)} 209 onPress={onShareATURI}> 210 <Menu.ItemText> 211 <Trans>Copy skeet at:// URI</Trans> 212 </Menu.ItemText> 213 <Menu.ItemIcon icon={ClipboardIcon} position="right" /> 214 </Menu.Item> 215 <Menu.Item 216 testID="postAuthorDIDShareBtn" 217 label={_(msg`Copy author DID`)} 218 onPress={onShareAuthorDID}> 219 <Menu.ItemText> 220 <Trans>Copy author DID</Trans> 221 </Menu.ItemText> 222 <Menu.ItemIcon icon={ClipboardIcon} position="right" /> 223 </Menu.Item> 224 </> 225 )} 226 </Menu.Outer> 227 228 {canEmbed && ( 229 <EmbedDialog 230 control={embedPostControl} 231 postCid={postCid} 232 postUri={postUri} 233 record={record} 234 postAuthor={postAuthor} 235 timestamp={timestamp} 236 /> 237 )} 238 239 <SendViaChatDialog 240 control={sendViaChatControl} 241 onSelectChat={onSelectChatToShareTo} 242 /> 243 </> 244 ) 245} 246ShareMenuItems = memo(ShareMenuItems) 247export {ShareMenuItems}