diff --git a/packages/native/package.json b/packages/native/package.json index b0006cd311..473de01c0c 100644 --- a/packages/native/package.json +++ b/packages/native/package.json @@ -38,6 +38,7 @@ }, "dependencies": { "@react-navigation/core": "^5.12.5", + "escape-string-regexp": "^4.0.0", "nanoid": "^3.1.12" }, "devDependencies": { @@ -70,4 +71,4 @@ ] ] } -} +} \ No newline at end of file diff --git a/packages/native/src/types.tsx b/packages/native/src/types.tsx index 0a098d8c39..43ac1bdc28 100644 --- a/packages/native/src/types.tsx +++ b/packages/native/src/types.tsx @@ -27,6 +27,12 @@ export type LinkingOptions = { * The prefixes are stripped from the URL before parsing them. * Usually they are the `scheme` + `host` (e.g. `myapp://chat?user=jane`) * Only applicable on Android and iOS. + * + * @example + * prefixes: [ + * "https://example.com", // Exact + * "https://*.example.com" // Match with any subdomain + * ] */ prefixes: string[]; /** diff --git a/packages/native/src/useLinking.native.tsx b/packages/native/src/useLinking.native.tsx index 22274f1260..a2719039a9 100644 --- a/packages/native/src/useLinking.native.tsx +++ b/packages/native/src/useLinking.native.tsx @@ -6,6 +6,7 @@ import { NavigationContainerRef, } from '@react-navigation/core'; import type { LinkingOptions } from './types'; +import escapeStringRegexp from 'escape-string-regexp'; let isUsingLinking = false; @@ -58,8 +59,16 @@ export default function useLinking( const extractPathFromURL = React.useCallback((url: string) => { for (const prefix of prefixesRef.current) { - if (url.startsWith(prefix)) { - return url.replace(prefix, ''); + const protocol = prefix.match(/^[^:]+:\/\//)?.[0] ?? ''; + const host = prefix.replace(protocol, ''); + const prefixRegex = new RegExp( + `^${escapeStringRegexp(protocol)}${host + .split('.') + .map((it) => (it === '*' ? '[^/]+' : escapeStringRegexp(it))) + .join('\\.')}` + ); + if (prefixRegex.test(url)) { + return url.replace(prefixRegex, ''); } }