diff --git a/src/components/Link.tsx b/src/components/Link.tsx index a2e952a6..d8ac829b 100644 --- a/src/components/Link.tsx +++ b/src/components/Link.tsx @@ -12,7 +12,8 @@ import { isExternalUrl, linkRequiresWarning, } from '#/lib/strings/url-helpers' -import {isNative, isWeb} from '#/platform/detection' +import {isNative} from '#/platform/detection' +import {shouldClickOpenNewTab} from '#/platform/urls' import {useModalControls} from '#/state/modals' import {useOpenLink} from '#/state/preferences/in-app-browser' import {useNavigationDeduped} from 'lib/hooks/useNavigationDeduped' @@ -116,16 +117,7 @@ export function useLink({ if (isExternal) { openLink(href) } else { - /** - * A `GestureResponderEvent`, but cast to `any` to avoid using a bunch - * of @ts-ignore below. - */ - const event = e as any - const isMiddleClick = isWeb && event.button === 1 - const isMetaKey = - isWeb && - (event.metaKey || event.altKey || event.ctrlKey || event.shiftKey) - const shouldOpenInNewTab = isMetaKey || isMiddleClick + const shouldOpenInNewTab = shouldClickOpenNewTab(e) if (isBskyDownloadUrl(href)) { shareUrl(BSKY_DOWNLOAD_URL) diff --git a/src/platform/urls.tsx b/src/platform/urls.tsx index fd844d93..fd9d297a 100644 --- a/src/platform/urls.tsx +++ b/src/platform/urls.tsx @@ -1,4 +1,5 @@ -import {Linking} from 'react-native' +import {GestureResponderEvent, Linking} from 'react-native' + import {isNative, isWeb} from './detection' export async function getInitialURL(): Promise { @@ -23,3 +24,15 @@ export function clearHash() { window.location.hash = '' } } + +export function shouldClickOpenNewTab(e: GestureResponderEvent) { + /** + * A `GestureResponderEvent`, but cast to `any` to avoid using a bunch + * of @ts-ignore below. + */ + const event = e as any + const isMiddleClick = isWeb && event.button === 1 + const isMetaKey = + isWeb && (event.metaKey || event.altKey || event.ctrlKey || event.shiftKey) + return isMetaKey || isMiddleClick +} diff --git a/src/view/com/feeds/FeedSourceCard.tsx b/src/view/com/feeds/FeedSourceCard.tsx index 589f674b..a6178943 100644 --- a/src/view/com/feeds/FeedSourceCard.tsx +++ b/src/view/com/feeds/FeedSourceCard.tsx @@ -1,5 +1,12 @@ import React from 'react' -import {Pressable, StyleProp, StyleSheet, View, ViewStyle} from 'react-native' +import { + Linking, + Pressable, + StyleProp, + StyleSheet, + View, + ViewStyle, +} from 'react-native' import {AtUri} from '@atproto/api' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {msg, Plural, Trans} from '@lingui/macro' @@ -26,6 +33,7 @@ import {RichText} from '#/components/RichText' import {Text} from '../util/text/Text' import {UserAvatar} from '../util/UserAvatar' import hairlineWidth = StyleSheet.hairlineWidth +import {shouldClickOpenNewTab} from '#/platform/urls' export function FeedSourceCard({ feedUri, @@ -203,17 +211,30 @@ export function FeedSourceCardLoaded({ style, {borderTopWidth: hideTopBorder ? 0 : hairlineWidth}, ]} - onPress={() => { + onPress={e => { + const shouldOpenInNewTab = shouldClickOpenNewTab(e) if (feed.type === 'feed') { - navigation.push('ProfileFeed', { - name: feed.creatorDid, - rkey: new AtUri(feed.uri).rkey, - }) + if (shouldOpenInNewTab) { + Linking.openURL( + `/profile/${feed.creatorDid}/feed/${new AtUri(feed.uri).rkey}`, + ) + } else { + navigation.push('ProfileFeed', { + name: feed.creatorDid, + rkey: new AtUri(feed.uri).rkey, + }) + } } else if (feed.type === 'list') { - navigation.push('ProfileList', { - name: feed.creatorDid, - rkey: new AtUri(feed.uri).rkey, - }) + if (shouldOpenInNewTab) { + Linking.openURL( + `/profile/${feed.creatorDid}/lists/${new AtUri(feed.uri).rkey}`, + ) + } else { + navigation.push('ProfileList', { + name: feed.creatorDid, + rkey: new AtUri(feed.uri).rkey, + }) + } } }} key={feed.uri}>