Fix using screen names in Link (#8473)

* use our router in favour of useLinkBuilder

* test feature using Home header feeds button

* handle non-string params properly
This commit is contained in:
Samuel Newman
2025-06-11 20:12:05 +03:00
committed by GitHub
parent 269105371b
commit 7341294df6
4 changed files with 11 additions and 21 deletions
+3 -5
View File
@@ -4,7 +4,6 @@ import {sanitizeUrl} from '@braintree/sanitize-url'
import {
type LinkProps as RNLinkProps,
StackActions,
useLinkBuilder,
} from '@react-navigation/native'
import {BSKY_DOWNLOAD_URL} from '#/lib/constants'
@@ -95,20 +94,19 @@ export function useLink({
shouldProxy?: boolean
}) {
const navigation = useNavigationDeduped()
const {buildHref} = useLinkBuilder()
const href = useMemo(() => {
return typeof to === 'string'
? convertBskyAppUrlIfNeeded(sanitizeUrl(to))
: to.screen
? buildHref(to.screen, to.params)
? router.matchName(to.screen)?.build(to.params)
: to.href
? convertBskyAppUrlIfNeeded(sanitizeUrl(to.href))
: undefined
}, [to, buildHref])
}, [to])
if (!href) {
throw new Error(
'Link `to` prop must be a string or an object with `screen` and `params` properties',
'Could not resolve screen. Link `to` prop must be a string or an object with `screen` and `params` properties',
)
}
+4 -4
View File
@@ -1,4 +1,4 @@
import {Route, RouteParams} from './types'
import {type Route, type RouteParams} from './types'
export class Router {
routes: [string, Route][] = []
@@ -45,7 +45,7 @@ function createRoute(pattern: string): Route {
})
const matcherRe = new RegExp(`^${matcherReInternal}([?]|$)`, 'i')
return {
match(path: string) {
match(path) {
const {pathname, searchParams} = new URL(path, 'http://throwaway.com')
const addedParams = Object.fromEntries(searchParams.entries())
@@ -55,10 +55,10 @@ function createRoute(pattern: string): Route {
}
return undefined
},
build(params: Record<string, string>) {
build(params = {}) {
const str = pattern.replace(
/:([\w]+)/g,
(_m, name) => params[name] || 'undefined',
(_m, name) => params[encodeURIComponent(name)] || 'undefined',
)
let hasQp = false
+1 -1
View File
@@ -143,5 +143,5 @@ export type RouteParams = Record<string, string>
export type MatchResult = {params: RouteParams}
export type Route = {
match: (path: string) => MatchResult | undefined
build: (params: RouteParams) => string
build: (params?: Record<string, any>) => string
}
+3 -11
View File
@@ -1,4 +1,3 @@
import React from 'react'
import {View} from 'react-native'
import Animated from 'react-native-reanimated'
import {msg} from '@lingui/macro'
@@ -56,13 +55,8 @@ export function HomeHeaderLayoutMobile({
<PressableScale
targetScale={0.9}
onPress={() => {
emitSoftReset()
}}
onPressIn={() => {
playHaptic('Heavy')
}}
onPressOut={() => {
playHaptic('Light')
emitSoftReset()
}}>
<Logo width={30} />
</PressableScale>
@@ -72,7 +66,7 @@ export function HomeHeaderLayoutMobile({
{hasSession && (
<Link
testID="viewHeaderHomeFeedPrefsBtn"
to="/feeds"
to={{screen: 'Feeds'}}
hitSlop={HITSLOP_10}
label={_(msg`View your feeds and explore more`)}
size="small"
@@ -81,9 +75,7 @@ export function HomeHeaderLayoutMobile({
shape="square"
style={[
a.justify_center,
{
marginRight: -Layout.BUTTON_VISUAL_ALIGNMENT_OFFSET,
},
{marginRight: -Layout.BUTTON_VISUAL_ALIGNMENT_OFFSET},
]}>
<ButtonIcon icon={FeedsIcon} size="lg" />
</Link>