From 0ec2b08a9a1db6fa35fab8d505b5bdc2d3709a8a Mon Sep 17 00:00:00 2001 From: Dara Adedeji <76637177+SunkenInTime@users.noreply.github.com> Date: Tue, 15 Sep 2026 19:27:01 -0700 Subject: [PATCH] fix(mobile): bare t3code:// links no longer reset navigation to Home (#12002) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- apps/mobile/src/App.tsx | 10 ++-------- apps/mobile/src/lib/appLinking.test.ts | 27 ++++++++++++++++++++++++++ apps/mobile/src/lib/appLinking.ts | 17 ++++++++++++++++ 3 files changed, 46 insertions(+), 8 deletions(-) create mode 100644 apps/mobile/src/lib/appLinking.test.ts create mode 100644 apps/mobile/src/lib/appLinking.ts diff --git a/apps/mobile/src/App.tsx b/apps/mobile/src/App.tsx index 897dae47d57f38e4cb3648e9e81fac965c4c98d6..7b2c0318f9fb8eb0bc2ef4d936b6c57f9a16babc 100644 --- a/apps/mobile/src/App.tsx +++ b/apps/mobile/src/App.tsx @@ -22,6 +22,7 @@ import { RootStack } from "./Stack"; import { appAtomRegistry } from "./state/atom-registry"; import { OverlayPortalHost } from "./components/OverlayPortal"; import { appBlurTargetRef } from "./lib/appBlurTarget"; +import { shouldHandleAppLink } from "./lib/appLinking"; import { useMobileNavigationTheme } from "./lib/useMobileNavigationTheme"; import { SubscriptionUsageCoordinator } from "./widgets/SubscriptionUsageCoordinator"; @@ -40,14 +41,7 @@ const appLinking = { prefixes: [Linking.createURL("/"), "t3code://", "t3code-dev://", "t3code-preview://"], // Keep the compact thread list available beneath a directly opened thread. config: { initialRouteName: "Home" }, - // The Expo dev client launches the app via - // ://expo-development-client/?url= — that URL addresses - // the launcher, not app navigation. Without this filter it falls through - // to the NotFound wildcard route on every dev launch. - // expo-sharing uses a private lifecycle URL only to wake the app. The - // persisted share inbox below owns navigation once the payload is durable. - filter: (url: string) => - !url.includes("expo-development-client") && !url.includes("://expo-sharing"), + filter: shouldHandleAppLink, }; const Navigation = createStaticNavigation(RootStack); diff --git a/apps/mobile/src/lib/appLinking.test.ts b/apps/mobile/src/lib/appLinking.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..62781ce5d4b672dda2907b6d45d22ba5050e60b5 --- /dev/null +++ b/apps/mobile/src/lib/appLinking.test.ts @@ -0,0 +1,27 @@ +import { describe, expect, it } from "vite-plus/test"; + +import { shouldHandleAppLink } from "./appLinking"; + +describe("shouldHandleAppLink", () => { + it.each(["t3code://", "t3code:///", "t3code-dev://", "t3code-preview://"])( + "ignores scheme-only URL %s", + (url) => { + expect(shouldHandleAppLink(url)).toBe(false); + }, + ); + + it.each([ + "t3code://threads/env-1/thread-1", + "t3code://pair?pairingUrl=x", + "t3code-dev://settings/usage?tab=limits", + ])("handles path-bearing URL %s", (url) => { + expect(shouldHandleAppLink(url)).toBe(true); + }); + + it.each(["t3code://expo-development-client/?url=x", "t3code://expo-sharing/anything"])( + "ignores lifecycle URL %s", + (url) => { + expect(shouldHandleAppLink(url)).toBe(false); + }, + ); +}); diff --git a/apps/mobile/src/lib/appLinking.ts b/apps/mobile/src/lib/appLinking.ts new file mode 100644 index 0000000000000000000000000000000000000000..16c74686880214596edc984d35f3e707799d9ee0 --- /dev/null +++ b/apps/mobile/src/lib/appLinking.ts @@ -0,0 +1,17 @@ +/** + * The Expo dev client launches the app via + * ://expo-development-client/?url= — that URL addresses + * the launcher, not app navigation. Without this filter it falls through + * to the NotFound wildcard route on every dev launch. + * expo-sharing uses a private lifecycle URL only to wake the app. The + * persisted share inbox in App.tsx owns navigation once the payload is durable. + * A scheme-only URL, as sent by iOS dictation keyboards returning to the app, + * only wakes the app and must not reset navigation to Home. + */ +export function shouldHandleAppLink(url: string): boolean { + return ( + !url.includes("expo-development-client") && + !url.includes("://expo-sharing") && + !/^t3code(-dev|-preview)?:\/*$/.test(url) + ); +} -- 2.54.0