tweak link handling (#7857)
This commit is contained in:
+13
-1
@@ -69,6 +69,11 @@ type BaseLinkProps = Pick<
|
||||
* Native-only attribute. If true, will open the share sheet on long press.
|
||||
*/
|
||||
shareOnLongPress?: boolean
|
||||
|
||||
/**
|
||||
* Whether the link should be opened through the redirect proxy.
|
||||
*/
|
||||
shouldProxy?: boolean
|
||||
}
|
||||
|
||||
export function useLink({
|
||||
@@ -80,9 +85,11 @@ export function useLink({
|
||||
onLongPress: outerOnLongPress,
|
||||
shareOnLongPress,
|
||||
overridePresentation,
|
||||
shouldProxy,
|
||||
}: BaseLinkProps & {
|
||||
displayText: string
|
||||
overridePresentation?: boolean
|
||||
shouldProxy?: boolean
|
||||
}) {
|
||||
const navigation = useNavigationDeduped()
|
||||
const {href} = useLinkProps<AllNavigatorParams>({
|
||||
@@ -118,7 +125,7 @@ export function useLink({
|
||||
})
|
||||
} else {
|
||||
if (isExternal) {
|
||||
openLink(href, overridePresentation)
|
||||
openLink(href, overridePresentation, shouldProxy)
|
||||
} else {
|
||||
const shouldOpenInNewTab = shouldClickOpenNewTab(e)
|
||||
|
||||
@@ -161,6 +168,7 @@ export function useLink({
|
||||
action,
|
||||
navigation,
|
||||
overridePresentation,
|
||||
shouldProxy,
|
||||
],
|
||||
)
|
||||
|
||||
@@ -219,6 +227,7 @@ export function Link({
|
||||
onPress: outerOnPress,
|
||||
onLongPress: outerOnLongPress,
|
||||
download,
|
||||
shouldProxy,
|
||||
...rest
|
||||
}: LinkProps) {
|
||||
const {href, isExternal, onPress, onLongPress} = useLink({
|
||||
@@ -227,6 +236,7 @@ export function Link({
|
||||
action,
|
||||
onPress: outerOnPress,
|
||||
onLongPress: outerOnLongPress,
|
||||
shouldProxy: shouldProxy,
|
||||
})
|
||||
|
||||
return (
|
||||
@@ -279,6 +289,7 @@ export function InlineLinkText({
|
||||
shareOnLongPress,
|
||||
disableUnderline,
|
||||
overridePresentation,
|
||||
shouldProxy,
|
||||
...rest
|
||||
}: InlineLinkProps) {
|
||||
const t = useTheme()
|
||||
@@ -292,6 +303,7 @@ export function InlineLinkText({
|
||||
onLongPress: outerOnLongPress,
|
||||
shareOnLongPress,
|
||||
overridePresentation,
|
||||
shouldProxy: shouldProxy,
|
||||
})
|
||||
const {
|
||||
state: hovered,
|
||||
|
||||
@@ -23,6 +23,7 @@ export type RichTextProps = TextStyleProp &
|
||||
onLinkPress?: LinkProps['onPress']
|
||||
interactiveStyle?: TextStyle
|
||||
emojiMultiplier?: number
|
||||
shouldProxyLinks?: boolean
|
||||
}
|
||||
|
||||
export function RichText({
|
||||
@@ -39,6 +40,7 @@ export function RichText({
|
||||
emojiMultiplier = 1.85,
|
||||
onLayout,
|
||||
onTextLayout,
|
||||
shouldProxyLinks,
|
||||
}: RichTextProps) {
|
||||
const richText = React.useMemo(
|
||||
() =>
|
||||
@@ -110,6 +112,7 @@ export function RichText({
|
||||
style={interactiveStyles}
|
||||
// @ts-ignore TODO
|
||||
dataSet={WORD_WRAP}
|
||||
shouldProxy={shouldProxyLinks}
|
||||
onPress={onLinkPress}>
|
||||
{segment.text}
|
||||
</InlineLinkText>
|
||||
@@ -128,6 +131,7 @@ export function RichText({
|
||||
// @ts-ignore TODO
|
||||
dataSet={WORD_WRAP}
|
||||
shareOnLongPress
|
||||
shouldProxy={shouldProxyLinks}
|
||||
onPress={onLinkPress}
|
||||
emoji>
|
||||
{toShortUrl(segment.text)}
|
||||
|
||||
@@ -5,6 +5,7 @@ import * as WebBrowser from 'expo-web-browser'
|
||||
import {logEvent} from '#/lib/statsig/statsig'
|
||||
import {
|
||||
createBskyAppAbsoluteUrl,
|
||||
createProxiedUrl,
|
||||
isBskyAppUrl,
|
||||
isBskyRSSUrl,
|
||||
isRelativeUrl,
|
||||
@@ -23,7 +24,7 @@ export function useOpenLink() {
|
||||
const sheetWrapper = useSheetWrapper()
|
||||
|
||||
const openLink = useCallback(
|
||||
async (url: string, override?: boolean) => {
|
||||
async (url: string, override?: boolean, shouldProxy?: boolean) => {
|
||||
if (isBskyRSSUrl(url) && isRelativeUrl(url)) {
|
||||
url = createBskyAppAbsoluteUrl(url)
|
||||
}
|
||||
@@ -33,6 +34,10 @@ export function useOpenLink() {
|
||||
domain: toNiceDomain(url),
|
||||
url,
|
||||
})
|
||||
|
||||
if (shouldProxy) {
|
||||
url = createProxiedUrl(url)
|
||||
}
|
||||
}
|
||||
|
||||
if (isNative && !url.startsWith('mailto:')) {
|
||||
|
||||
@@ -320,6 +320,21 @@ export function createBskyAppAbsoluteUrl(path: string): string {
|
||||
return `${BSKY_APP_HOST.replace(/\/$/, '')}/${sanitizedPath}`
|
||||
}
|
||||
|
||||
export function createProxiedUrl(url: string): string {
|
||||
let u
|
||||
try {
|
||||
u = URL.parse(url)
|
||||
} catch {
|
||||
return url
|
||||
}
|
||||
|
||||
if (u?.protocol !== 'http:' && u?.protocol !== 'https:') {
|
||||
return url
|
||||
}
|
||||
|
||||
return `https://go.bsky.app/redirect?u=${url}`
|
||||
}
|
||||
|
||||
export function isShortLink(url: string): boolean {
|
||||
return url.startsWith('https://go.bsky.app/')
|
||||
}
|
||||
|
||||
@@ -375,6 +375,7 @@ let PostThreadItemLoaded = ({
|
||||
value={richText}
|
||||
style={[a.flex_1, a.text_xl]}
|
||||
authorHandle={post.author.handle}
|
||||
shouldProxyLinks={true}
|
||||
/>
|
||||
) : undefined}
|
||||
{post.embed && (
|
||||
@@ -590,6 +591,7 @@ let PostThreadItemLoaded = ({
|
||||
style={[a.flex_1, a.text_md]}
|
||||
numberOfLines={limitLines ? MAX_POST_LINES : undefined}
|
||||
authorHandle={post.author.handle}
|
||||
shouldProxyLinks={true}
|
||||
/>
|
||||
</View>
|
||||
) : undefined}
|
||||
|
||||
@@ -234,6 +234,7 @@ function PostInner({
|
||||
numberOfLines={limitLines ? MAX_POST_LINES : undefined}
|
||||
style={[a.flex_1, a.text_md]}
|
||||
authorHandle={post.author.handle}
|
||||
shouldProxyLinks={true}
|
||||
/>
|
||||
</View>
|
||||
) : undefined}
|
||||
|
||||
@@ -506,6 +506,7 @@ let PostContent = ({
|
||||
numberOfLines={limitLines ? MAX_POST_LINES : undefined}
|
||||
style={[a.flex_1, a.text_md]}
|
||||
authorHandle={postAuthor.handle}
|
||||
shouldProxyLinks={true}
|
||||
/>
|
||||
</View>
|
||||
) : undefined}
|
||||
|
||||
@@ -70,6 +70,7 @@ export const ExternalLinkEmbed = ({
|
||||
<Link
|
||||
label={link.title || _(msg`Open link to ${niceUrl}`)}
|
||||
to={link.uri}
|
||||
shouldProxy={true}
|
||||
onPress={onOpen}
|
||||
onLongPress={onShareExternal}>
|
||||
{({hovered}) => (
|
||||
|
||||
Reference in New Issue
Block a user