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

Configure Feed

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

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