From edc47f2eb17abda883543990be9a6f860af34358 Mon Sep 17 00:00:00 2001 From: Hailey Date: Sat, 6 Jul 2024 22:19:15 -0700 Subject: [PATCH] ensure proper navigation --- src/components/Link.tsx | 49 +++++++++++++++++++++++++++++++++- src/lib/strings/url-helpers.ts | 30 +++++++++++++++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/src/components/Link.tsx b/src/components/Link.tsx index d8ac829b67..a8b478be78 100644 --- a/src/components/Link.tsx +++ b/src/components/Link.tsx @@ -1,5 +1,10 @@ import React from 'react' -import {GestureResponderEvent} from 'react-native' +import { + GestureResponderEvent, + Pressable, + StyleProp, + ViewStyle, +} from 'react-native' import {sanitizeUrl} from '@braintree/sanitize-url' import {StackActions, useLinkProps} from '@react-navigation/native' @@ -323,3 +328,45 @@ export function InlineLinkText({ ) } + +/** + * A Pressable that uses useLink to handle navigation. It is unstyled, so can be used in cases where the Button styles + * in Link are not desired. + * @param displayText + * @param style + * @param children + * @param rest + * @constructor + */ +export function BaseLink({ + displayText, + onPress: onPressOuter, + style, + children, + ...rest +}: { + style?: StyleProp + children: React.ReactNode + to: string + action: 'push' | 'replace' | 'navigate' + onPress?: () => false | void + shareOnLongPress?: boolean + label: string + displayText?: string +}) { + const {onPress, ...btnProps} = useLink({ + displayText: displayText ?? rest.to, + ...rest, + }) + return ( + { + onPressOuter?.() + onPress(e) + }} + {...btnProps}> + {children} + + ) +} diff --git a/src/lib/strings/url-helpers.ts b/src/lib/strings/url-helpers.ts index 948279fceb..0407df7571 100644 --- a/src/lib/strings/url-helpers.ts +++ b/src/lib/strings/url-helpers.ts @@ -5,6 +5,7 @@ import TLDs from 'tlds' import {logger} from '#/logger' import {BSKY_SERVICE} from 'lib/constants' import {isInvalidHandle} from 'lib/strings/handles' +import {startUriToStarterPackUri} from 'lib/strings/starter-pack' export const BSKY_APP_HOST = 'https://bsky.app' const BSKY_TRUSTED_HOSTS = [ @@ -152,6 +153,30 @@ export function isBskyListUrl(url: string): boolean { return false } +export function isBskyStartUrl(url: string): boolean { + if (isBskyAppUrl(url)) { + try { + const urlp = new URL(url) + return /start\/(?[^/]+)\/(?[^/]+)/i.test(urlp.pathname) + } catch { + console.error('Unexpected error in isBskyStartUrl()', url) + } + } + return false +} + +export function isBskyStarterPackUrl(url: string): boolean { + if (isBskyAppUrl(url)) { + try { + const urlp = new URL(url) + return /starter-pack\/(?[^/]+)\/(?[^/]+)/i.test(urlp.pathname) + } catch { + console.error('Unexpected error in isBskyStartUrl()', url) + } + } + return false +} + export function isBskyDownloadUrl(url: string): boolean { if (isExternalUrl(url)) { return false @@ -163,6 +188,11 @@ export function convertBskyAppUrlIfNeeded(url: string): string { if (isBskyAppUrl(url)) { try { const urlp = new URL(url) + + if (isBskyStartUrl(url)) { + return startUriToStarterPackUri(urlp.pathname) + } + return urlp.pathname } catch (e) { console.error('Unexpected error in convertBskyAppUrlIfNeeded()', e)