about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorSamuel Newman <mozzius@protonmail.com>2025-06-18 19:25:14 +0300
committerGitHub <noreply@github.com>2025-06-18 09:25:14 -0700
commit06ebd2964ab68aa295f3385c188f40c33e3e0a23 (patch)
treec673a1770bce1d313666b5e9f77cea6e7c5d8239 /src
parent3304cd04249a2c39fa628b0339d6770bd26f8392 (diff)
downloadvoidsky-06ebd2964ab68aa295f3385c188f40c33e3e0a23.tar.zst
Fix linking to specific search results (#8520)
* fix linking to bsky.app/search?q=xyz

* add name to comment

* skip if notfound
Diffstat (limited to 'src')
-rw-r--r--src/components/Link.tsx43
-rw-r--r--src/lib/hooks/useNavigationDeduped.ts4
-rw-r--r--src/lib/strings/url-helpers.ts5
3 files changed, 45 insertions, 7 deletions
diff --git a/src/components/Link.tsx b/src/components/Link.tsx
index d0f8678ff..28cd19418 100644
--- a/src/components/Link.tsx
+++ b/src/components/Link.tsx
@@ -9,7 +9,7 @@ import {
 import {BSKY_DOWNLOAD_URL} from '#/lib/constants'
 import {useNavigationDeduped} from '#/lib/hooks/useNavigationDeduped'
 import {useOpenLink} from '#/lib/hooks/useOpenLink'
-import {type AllNavigatorParams} from '#/lib/routes/types'
+import {type AllNavigatorParams, type RouteParams} from '#/lib/routes/types'
 import {shareUrl} from '#/lib/sharing'
 import {
   convertBskyAppUrlIfNeeded,
@@ -155,15 +155,44 @@ export function useLink({
           } else {
             closeModal() // close any active modals
 
+            const [screen, params] = router.matchPath(href) as [
+              screen: keyof AllNavigatorParams,
+              params?: RouteParams,
+            ]
+
+            // does not apply to web's flat navigator
+            if (isNative && screen !== 'NotFound') {
+              const state = navigation.getState()
+              // if screen is not in the current navigator, it means it's
+              // most likely a tab screen
+              if (!state.routeNames.includes(screen)) {
+                const parent = navigation.getParent()
+                if (
+                  parent &&
+                  parent.getState().routeNames.includes(`${screen}Tab`)
+                ) {
+                  // yep, it's a tab screen. i.e. SearchTab
+                  // thus we need to navigate to the child screen
+                  // via the parent navigator
+                  // see https://reactnavigation.org/docs/upgrading-from-6.x/#changes-to-the-navigate-action
+                  // TODO: can we support the other kinds of actions? push/replace -sfn
+
+                  // @ts-expect-error include does not narrow the type unfortunately
+                  parent.navigate(`${screen}Tab`, {screen, params})
+                  return
+                } else {
+                  // will probably fail, but let's try anyway
+                }
+              }
+            }
+
             if (action === 'push') {
-              navigation.dispatch(StackActions.push(...router.matchPath(href)))
+              navigation.dispatch(StackActions.push(screen, params))
             } else if (action === 'replace') {
-              navigation.dispatch(
-                StackActions.replace(...router.matchPath(href)),
-              )
+              navigation.dispatch(StackActions.replace(screen, params))
             } else if (action === 'navigate') {
-              // @ts-ignore
-              navigation.navigate(...router.matchPath(href))
+              // @ts-expect-error not typed
+              navigation.navigate(screen, params)
             } else {
               throw Error('Unsupported navigator action.')
             }
diff --git a/src/lib/hooks/useNavigationDeduped.ts b/src/lib/hooks/useNavigationDeduped.ts
index dc18742c0..136e5fb96 100644
--- a/src/lib/hooks/useNavigationDeduped.ts
+++ b/src/lib/hooks/useNavigationDeduped.ts
@@ -14,6 +14,7 @@ export type DebouncedNavigationProp = Pick<
   | 'dispatch'
   | 'goBack'
   | 'getState'
+  | 'getParent'
 >
 
 export function useNavigationDeduped() {
@@ -46,6 +47,9 @@ export function useNavigationDeduped() {
       getState: () => {
         return navigation.getState()
       },
+      getParent: (...args: Parameters<typeof navigation.getParent>) => {
+        return navigation.getParent(...args)
+      },
     }),
     [dedupe, navigation],
   )
diff --git a/src/lib/strings/url-helpers.ts b/src/lib/strings/url-helpers.ts
index ad194714a..288f428c1 100644
--- a/src/lib/strings/url-helpers.ts
+++ b/src/lib/strings/url-helpers.ts
@@ -193,6 +193,11 @@ export function convertBskyAppUrlIfNeeded(url: string): string {
         return startUriToStarterPackUri(urlp.pathname)
       }
 
+      // special-case search links
+      if (urlp.pathname === '/search') {
+        return `/search?q=${urlp.searchParams.get('q')}`
+      }
+
       return urlp.pathname
     } catch (e) {
       console.error('Unexpected error in convertBskyAppUrlIfNeeded()', e)