expo-linking 3.0.0 → 3.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/README.md +3 -3
- package/build/ExpoLinking.d.ts +1 -0
- package/build/ExpoLinking.d.ts.map +1 -0
- package/build/ExpoLinking.web.d.ts +4 -1
- package/build/ExpoLinking.web.d.ts.map +1 -0
- package/build/ExpoLinking.web.js +13 -0
- package/build/ExpoLinking.web.js.map +1 -1
- package/build/Linking.d.ts +9 -4
- package/build/Linking.d.ts.map +1 -0
- package/build/Linking.js +11 -7
- package/build/Linking.js.map +1 -1
- package/build/Linking.types.d.ts +1 -0
- package/build/Linking.types.d.ts.map +1 -0
- package/build/Schemes.d.ts +5 -1
- package/build/Schemes.d.ts.map +1 -0
- package/build/Schemes.js +26 -26
- package/build/Schemes.js.map +1 -1
- package/package.json +4 -4
- package/src/ExpoLinking.web.ts +15 -1
- package/src/Linking.ts +14 -9
- package/src/Schemes.ts +26 -28
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,32 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 3.2.1 — 2022-07-16
|
|
14
|
+
|
|
15
|
+
_This version does not introduce any user-facing changes._
|
|
16
|
+
|
|
17
|
+
## 3.2.0 — 2022-07-07
|
|
18
|
+
|
|
19
|
+
### 🐛 Bug fixes
|
|
20
|
+
|
|
21
|
+
- Fix bug in isExpoHosted for new manifests. ([#17402](https://github.com/expo/expo/pull/17402) by [@wschurman](https://github.com/wschurman))
|
|
22
|
+
- Fix `addEventListener` not returning a subscription on web. ([#17925](https://github.com/expo/expo/pull/17925) by [@EvanBacon](https://github.com/EvanBacon))
|
|
23
|
+
|
|
24
|
+
## 3.1.0 — 2022-04-18
|
|
25
|
+
|
|
26
|
+
### 🎉 New features
|
|
27
|
+
|
|
28
|
+
- `addEventListener` returns `EmitterSubscription` rather than `void` ([#17014](https://github.com/expo/expo/pull/17014) by [@frankcalise](https://github.com/frankcalise))
|
|
29
|
+
|
|
30
|
+
### 🐛 Bug fixes
|
|
31
|
+
|
|
32
|
+
- `addEventListener` and `removeEventListener` only accept `'url'` as `type` param, rather than `string`
|
|
33
|
+
- `useURL` hook now cleans up `addEventListener` via `remove` rather than `removeEventListener` ([#17014](https://github.com/expo/expo/pull/17014) by [@frankcalise](https://github.com/frankcalise))
|
|
34
|
+
|
|
35
|
+
### 💡 Others
|
|
36
|
+
|
|
37
|
+
- Export public `Schemes` methods in main file. ([#17058](https://github.com/expo/expo/pull/17058) by [@Simek](https://github.com/Simek))
|
|
38
|
+
|
|
13
39
|
## 3.0.0 — 2021-12-03
|
|
14
40
|
|
|
15
41
|
### 🛠 Breaking changes
|
package/README.md
CHANGED
|
@@ -4,12 +4,12 @@ Create and open deep links universally.
|
|
|
4
4
|
|
|
5
5
|
# API documentation
|
|
6
6
|
|
|
7
|
-
- [Documentation for the
|
|
8
|
-
- [Documentation for the latest stable release](https://docs.expo.
|
|
7
|
+
- [Documentation for the main branch](https://github.com/expo/expo/blob/main/docs/pages/versions/unversioned/sdk/linking.md)
|
|
8
|
+
- [Documentation for the latest stable release](https://docs.expo.dev/versions/latest/sdk/linking/)
|
|
9
9
|
|
|
10
10
|
# Installation in managed Expo projects
|
|
11
11
|
|
|
12
|
-
For
|
|
12
|
+
For [managed](https://docs.expo.dev/versions/latest/introduction/managed-vs-bare/) Expo projects, please follow the installation instructions in the [API documentation for the latest stable release](https://docs.expo.dev/versions/latest/sdk/asset/). If you follow the link and there is no documentation available then this library is not yet usable within managed projects — it is likely to be included in an upcoming Expo SDK release.
|
|
13
13
|
|
|
14
14
|
# Installation in bare React Native projects
|
|
15
15
|
|
package/build/ExpoLinking.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoLinking.d.ts","sourceRoot":"","sources":["../src/ExpoLinking.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,eAAe,OAAO,CAAC"}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { URLListener } from './Linking.types';
|
|
2
2
|
declare const _default: {
|
|
3
|
-
addEventListener(type: 'url', listener: URLListener):
|
|
3
|
+
addEventListener(type: 'url', listener: URLListener): {
|
|
4
|
+
remove(): void;
|
|
5
|
+
};
|
|
4
6
|
removeEventListener(type: 'url', listener: URLListener): void;
|
|
5
7
|
canOpenURL(url: string): Promise<boolean>;
|
|
6
8
|
getInitialURL(): Promise<string>;
|
|
7
9
|
openURL(url: string): Promise<void>;
|
|
8
10
|
};
|
|
9
11
|
export default _default;
|
|
12
|
+
//# sourceMappingURL=ExpoLinking.web.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoLinking.web.d.ts","sourceRoot":"","sources":["../src/ExpoLinking.web.ts"],"names":[],"mappings":"AAGA,OAAO,EAAqB,WAAW,EAAE,MAAM,iBAAiB,CAAC;;2BAOxC,KAAK,YAAY,WAAW,GAAG;QAAE,MAAM,IAAI,IAAI,CAAA;KAAE;8BAqB9C,KAAK,YAAY,WAAW,GAAG,IAAI;oBAmBvC,MAAM,GAAG,QAAQ,OAAO,CAAC;qBAKxB,QAAQ,MAAM,CAAC;iBAKnB,MAAM,GAAG,QAAQ,IAAI,CAAC;;AAnD3C,wBAyDE"}
|
package/build/ExpoLinking.web.js
CHANGED
|
@@ -4,12 +4,25 @@ const EventTypes = ['url'];
|
|
|
4
4
|
const listeners = [];
|
|
5
5
|
export default {
|
|
6
6
|
addEventListener(type, listener) {
|
|
7
|
+
// Do nothing in Node.js environments
|
|
8
|
+
if (!Platform.isDOMAvailable) {
|
|
9
|
+
return { remove() { } };
|
|
10
|
+
}
|
|
7
11
|
invariant(EventTypes.indexOf(type) !== -1, `Linking.addEventListener(): ${type} is not a valid event`);
|
|
8
12
|
const nativeListener = (nativeEvent) => listener({ url: window.location.href, nativeEvent });
|
|
9
13
|
listeners.push({ listener, nativeListener });
|
|
10
14
|
window.addEventListener('message', nativeListener, false);
|
|
15
|
+
return {
|
|
16
|
+
remove: () => {
|
|
17
|
+
this.removeEventListener(type, listener);
|
|
18
|
+
},
|
|
19
|
+
};
|
|
11
20
|
},
|
|
12
21
|
removeEventListener(type, listener) {
|
|
22
|
+
// Do nothing in Node.js environments
|
|
23
|
+
if (!Platform.isDOMAvailable) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
13
26
|
invariant(EventTypes.indexOf(type) !== -1, `Linking.removeEventListener(): ${type} is not a valid event.`);
|
|
14
27
|
const listenerIndex = listeners.findIndex((pair) => pair.listener === listener);
|
|
15
28
|
invariant(listenerIndex !== -1, 'Linking.removeEventListener(): cannot remove an unregistered event listener.');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoLinking.web.js","sourceRoot":"","sources":["../src/ExpoLinking.web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,SAAS,MAAM,WAAW,CAAC;AAIlC,MAAM,UAAU,GAAG,CAAC,KAAK,CAAC,CAAC;AAE3B,MAAM,SAAS,GAAmE,EAAE,CAAC;AAErF,eAAe;IACb,gBAAgB,CAAC,IAAW,EAAE,QAAqB;QACjD,SAAS,CACP,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAC/B,+BAA+B,IAAI,uBAAuB,CAC3D,CAAC;QACF,MAAM,cAAc,GAAsB,CAAC,WAAW,EAAE,EAAE,CACxD,QAAQ,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;QACvD,SAAS,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC,CAAC;QAC7C,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,cAAc,EAAE,KAAK,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"ExpoLinking.web.js","sourceRoot":"","sources":["../src/ExpoLinking.web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,SAAS,MAAM,WAAW,CAAC;AAIlC,MAAM,UAAU,GAAG,CAAC,KAAK,CAAC,CAAC;AAE3B,MAAM,SAAS,GAAmE,EAAE,CAAC;AAErF,eAAe;IACb,gBAAgB,CAAC,IAAW,EAAE,QAAqB;QACjD,qCAAqC;QACrC,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE;YAC5B,OAAO,EAAE,MAAM,KAAI,CAAC,EAAE,CAAC;SACxB;QAED,SAAS,CACP,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAC/B,+BAA+B,IAAI,uBAAuB,CAC3D,CAAC;QACF,MAAM,cAAc,GAAsB,CAAC,WAAW,EAAE,EAAE,CACxD,QAAQ,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;QACvD,SAAS,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC,CAAC;QAC7C,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,cAAc,EAAE,KAAK,CAAC,CAAC;QAC1D,OAAO;YACL,MAAM,EAAE,GAAG,EAAE;gBACX,IAAI,CAAC,mBAAmB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YAC3C,CAAC;SACF,CAAC;IACJ,CAAC;IAED,mBAAmB,CAAC,IAAW,EAAE,QAAqB;QACpD,qCAAqC;QACrC,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE;YAC5B,OAAO;SACR;QACD,SAAS,CACP,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAC/B,kCAAkC,IAAI,wBAAwB,CAC/D,CAAC;QACF,MAAM,aAAa,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;QAChF,SAAS,CACP,aAAa,KAAK,CAAC,CAAC,EACpB,8EAA8E,CAC/E,CAAC;QACF,MAAM,cAAc,GAAG,SAAS,CAAC,aAAa,CAAC,CAAC,cAAc,CAAC;QAC/D,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,cAAc,EAAE,KAAK,CAAC,CAAC;QAC7D,SAAS,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,GAAW;QAC1B,uFAAuF;QACvF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,aAAa;QACjB,IAAI,CAAC,QAAQ,CAAC,cAAc;YAAE,OAAO,EAAE,CAAC;QACxC,OAAO,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,GAAW;QACvB,IAAI,QAAQ,CAAC,cAAc,EAAE;YAC3B,aAAa;YACb,MAAM,CAAC,QAAQ,GAAG,IAAI,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE,CAAC;SAC5D;IACH,CAAC;CACF,CAAC","sourcesContent":["import { Platform } from 'expo-modules-core';\nimport invariant from 'invariant';\n\nimport { NativeURLListener, URLListener } from './Linking.types';\n\nconst EventTypes = ['url'];\n\nconst listeners: { listener: URLListener; nativeListener: NativeURLListener }[] = [];\n\nexport default {\n addEventListener(type: 'url', listener: URLListener): { remove(): void } {\n // Do nothing in Node.js environments\n if (!Platform.isDOMAvailable) {\n return { remove() {} };\n }\n\n invariant(\n EventTypes.indexOf(type) !== -1,\n `Linking.addEventListener(): ${type} is not a valid event`\n );\n const nativeListener: NativeURLListener = (nativeEvent) =>\n listener({ url: window.location.href, nativeEvent });\n listeners.push({ listener, nativeListener });\n window.addEventListener('message', nativeListener, false);\n return {\n remove: () => {\n this.removeEventListener(type, listener);\n },\n };\n },\n\n removeEventListener(type: 'url', listener: URLListener): void {\n // Do nothing in Node.js environments\n if (!Platform.isDOMAvailable) {\n return;\n }\n invariant(\n EventTypes.indexOf(type) !== -1,\n `Linking.removeEventListener(): ${type} is not a valid event.`\n );\n const listenerIndex = listeners.findIndex((pair) => pair.listener === listener);\n invariant(\n listenerIndex !== -1,\n 'Linking.removeEventListener(): cannot remove an unregistered event listener.'\n );\n const nativeListener = listeners[listenerIndex].nativeListener;\n window.removeEventListener('message', nativeListener, false);\n listeners.splice(listenerIndex, 1);\n },\n\n async canOpenURL(url: string): Promise<boolean> {\n // In reality this should be able to return false for links like `chrome://` on chrome.\n return true;\n },\n\n async getInitialURL(): Promise<string> {\n if (!Platform.isDOMAvailable) return '';\n return window.location.href;\n },\n\n async openURL(url: string): Promise<void> {\n if (Platform.isDOMAvailable) {\n // @ts-ignore\n window.location = new URL(url, window.location).toString();\n }\n },\n};\n"]}
|
package/build/Linking.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { EmitterSubscription } from 'react-native';
|
|
1
2
|
import { CreateURLOptions, ParsedURL, QueryParams, SendIntentExtras, URLListener } from './Linking.types';
|
|
2
3
|
/**
|
|
3
4
|
* Create a URL that works for the environment the app is currently running in.
|
|
@@ -54,17 +55,20 @@ export declare function parse(url: string): ParsedURL;
|
|
|
54
55
|
* @param type The only valid type is `'url'`.
|
|
55
56
|
* @param handler An [`URLListener`](#urllistener) function that takes an `event` object of the type
|
|
56
57
|
* [`EventType`](#eventype).
|
|
58
|
+
* @return An EmitterSubscription that has the remove method from EventSubscription
|
|
57
59
|
* @see [React Native Docs Linking page](https://reactnative.dev/docs/linking#addeventlistener).
|
|
58
60
|
*/
|
|
59
|
-
export declare function addEventListener(type:
|
|
61
|
+
export declare function addEventListener(type: 'url', handler: URLListener): EmitterSubscription;
|
|
60
62
|
/**
|
|
61
63
|
* Remove a handler by passing the `url` event type and the handler.
|
|
62
64
|
* @param type The only valid type is `'url'`.
|
|
63
65
|
* @param handler An [`URLListener`](#urllistener) function that takes an `event` object of the type
|
|
64
66
|
* [`EventType`](#eventype).
|
|
65
67
|
* @see [React Native Docs Linking page](https://reactnative.dev/docs/linking#removeeventlistener).
|
|
68
|
+
*
|
|
69
|
+
* @deprecated Call `remove()` on the return value of `addEventListener()` instead.
|
|
66
70
|
*/
|
|
67
|
-
export declare function removeEventListener(type:
|
|
71
|
+
export declare function removeEventListener(type: 'url', handler: URLListener): void;
|
|
68
72
|
/**
|
|
69
73
|
* Helper method which wraps React Native's `Linking.getInitialURL()` in `Linking.parse()`.
|
|
70
74
|
* Parses the deep link information out of the URL used to open the experience initially.
|
|
@@ -75,14 +79,13 @@ export declare function removeEventListener(type: string, handler: URLListener):
|
|
|
75
79
|
export declare function parseInitialURLAsync(): Promise<ParsedURL>;
|
|
76
80
|
/**
|
|
77
81
|
* Launch an Android intent with extras.
|
|
78
|
-
* > Use [IntentLauncher](
|
|
82
|
+
* > Use [IntentLauncher](./intent-launcher) instead, `sendIntent` is only included in
|
|
79
83
|
* > `Linking` for API compatibility with React Native's Linking API.
|
|
80
84
|
* @platform android
|
|
81
85
|
*/
|
|
82
86
|
export declare function sendIntent(action: string, extras?: SendIntentExtras[]): Promise<void>;
|
|
83
87
|
/**
|
|
84
88
|
* Open the operating system settings app and displays the app’s custom settings, if it has any.
|
|
85
|
-
* @platform ios
|
|
86
89
|
*/
|
|
87
90
|
export declare function openSettings(): Promise<void>;
|
|
88
91
|
/**
|
|
@@ -116,3 +119,5 @@ export declare function canOpenURL(url: string): Promise<boolean>;
|
|
|
116
119
|
*/
|
|
117
120
|
export declare function useURL(): string | null;
|
|
118
121
|
export * from './Linking.types';
|
|
122
|
+
export * from './Schemes';
|
|
123
|
+
//# sourceMappingURL=Linking.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Linking.d.ts","sourceRoot":"","sources":["../src/Linking.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAInD,OAAO,EACL,gBAAgB,EAChB,SAAS,EACT,WAAW,EACX,gBAAgB,EAChB,WAAW,EACZ,MAAM,iBAAiB,CAAC;AAqEzB;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,OAAO,CAAC,IAAI,GAAE,MAAW,EAAE,WAAW,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAE7F;AAGD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,EAAE,MAAM,EAAE,WAAgB,EAAE,eAAuB,EAAE,GAAE,gBAAqB,GAC3E,MAAM,CAgER;AAGD;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CA6C5C;AAGD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,GAAG,mBAAmB,CAEvF;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI,CAE3E;AAGD;;;;;;GAMG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,SAAS,CAAC,CAY/D;AAGD;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAK3F;AAGD;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAQlD;AAGD;;;GAGG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAE5D;AAGD;;;;;;;GAOG;AACH,wBAAsB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGxD;AAGD;;;;;;;;;GASG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAG9D;AAGD;;;GAGG;AACH,wBAAgB,MAAM,IAAI,MAAM,GAAG,IAAI,CActC;AAED,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC"}
|
package/build/Linking.js
CHANGED
|
@@ -30,7 +30,8 @@ function isExpoHosted() {
|
|
|
30
30
|
const hostUri = getHostUri();
|
|
31
31
|
return !!(hostUri &&
|
|
32
32
|
(/^(.*\.)?(expo\.io|exp\.host|exp\.direct|expo\.test)(:.*)?(\/.*)?$/.test(hostUri) ||
|
|
33
|
-
Constants.manifest?.developer
|
|
33
|
+
Constants.manifest?.developer ||
|
|
34
|
+
Constants.manifest2?.extra?.expoGo?.developer));
|
|
34
35
|
}
|
|
35
36
|
function removeScheme(url) {
|
|
36
37
|
return url.replace(/^[a-zA-Z0-9+.-]+:\/\//, '');
|
|
@@ -154,7 +155,7 @@ export function createURL(path, { scheme, queryParams = {}, isTripleSlashed = fa
|
|
|
154
155
|
paramsFromHostUri = parsedParams;
|
|
155
156
|
}
|
|
156
157
|
}
|
|
157
|
-
catch
|
|
158
|
+
catch { }
|
|
158
159
|
queryParams = {
|
|
159
160
|
...queryParams,
|
|
160
161
|
...paramsFromHostUri,
|
|
@@ -218,10 +219,11 @@ export function parse(url) {
|
|
|
218
219
|
* @param type The only valid type is `'url'`.
|
|
219
220
|
* @param handler An [`URLListener`](#urllistener) function that takes an `event` object of the type
|
|
220
221
|
* [`EventType`](#eventype).
|
|
222
|
+
* @return An EmitterSubscription that has the remove method from EventSubscription
|
|
221
223
|
* @see [React Native Docs Linking page](https://reactnative.dev/docs/linking#addeventlistener).
|
|
222
224
|
*/
|
|
223
225
|
export function addEventListener(type, handler) {
|
|
224
|
-
NativeLinking.addEventListener(type, handler);
|
|
226
|
+
return NativeLinking.addEventListener(type, handler);
|
|
225
227
|
}
|
|
226
228
|
/**
|
|
227
229
|
* Remove a handler by passing the `url` event type and the handler.
|
|
@@ -229,6 +231,8 @@ export function addEventListener(type, handler) {
|
|
|
229
231
|
* @param handler An [`URLListener`](#urllistener) function that takes an `event` object of the type
|
|
230
232
|
* [`EventType`](#eventype).
|
|
231
233
|
* @see [React Native Docs Linking page](https://reactnative.dev/docs/linking#removeeventlistener).
|
|
234
|
+
*
|
|
235
|
+
* @deprecated Call `remove()` on the return value of `addEventListener()` instead.
|
|
232
236
|
*/
|
|
233
237
|
export function removeEventListener(type, handler) {
|
|
234
238
|
NativeLinking.removeEventListener(type, handler);
|
|
@@ -256,7 +260,7 @@ export async function parseInitialURLAsync() {
|
|
|
256
260
|
// @needsAudit
|
|
257
261
|
/**
|
|
258
262
|
* Launch an Android intent with extras.
|
|
259
|
-
* > Use [IntentLauncher](
|
|
263
|
+
* > Use [IntentLauncher](./intent-launcher) instead, `sendIntent` is only included in
|
|
260
264
|
* > `Linking` for API compatibility with React Native's Linking API.
|
|
261
265
|
* @platform android
|
|
262
266
|
*/
|
|
@@ -269,7 +273,6 @@ export async function sendIntent(action, extras) {
|
|
|
269
273
|
// @needsAudit
|
|
270
274
|
/**
|
|
271
275
|
* Open the operating system settings app and displays the app’s custom settings, if it has any.
|
|
272
|
-
* @platform ios
|
|
273
276
|
*/
|
|
274
277
|
export async function openSettings() {
|
|
275
278
|
if (Platform.OS === 'web') {
|
|
@@ -328,10 +331,11 @@ export function useURL() {
|
|
|
328
331
|
}
|
|
329
332
|
useEffect(() => {
|
|
330
333
|
getInitialURL().then((url) => setLink(url));
|
|
331
|
-
addEventListener('url', onChange);
|
|
332
|
-
return () =>
|
|
334
|
+
const subscription = addEventListener('url', onChange);
|
|
335
|
+
return () => subscription.remove();
|
|
333
336
|
}, []);
|
|
334
337
|
return url;
|
|
335
338
|
}
|
|
336
339
|
export * from './Linking.types';
|
|
340
|
+
export * from './Schemes';
|
|
337
341
|
//# sourceMappingURL=Linking.js.map
|
package/build/Linking.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Linking.js","sourceRoot":"","sources":["../src/Linking.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,SAAS,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,GAAG,MAAM,WAAW,CAAC;AAE5B,OAAO,aAAa,MAAM,eAAe,CAAC;AAQ1C,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE3D,SAAS,WAAW,CAAC,GAAW;IAC9B,SAAS,CAAC,OAAO,GAAG,KAAK,QAAQ,EAAE,wCAAwC,GAAG,GAAG,CAAC,CAAC;IACnF,SAAS,CAAC,GAAG,EAAE,8BAA8B,CAAC,CAAC;AACjD,CAAC;AAED,SAAS,UAAU;IACjB,IAAI,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE;QAC/B,OAAO,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC;KACnC;SAAM,IAAI,SAAS,CAAC,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE;QAC1D,OAAO,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC;KACrD;SAAM,IAAI,CAAC,eAAe,EAAE,EAAE;QAC7B,mEAAmE;QACnE,gFAAgF;QAChF,OAAO,YAAY,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;KACxE;SAAM;QACL,OAAO,IAAI,CAAC;KACb;AACH,CAAC;AAED,SAAS,YAAY;IACnB,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,OAAO,CAAC,CAAC,CACP,OAAO;QACP,CAAC,mEAAmE,CAAC,IAAI,CAAC,OAAO,CAAC;YAChF,SAAS,CAAC,QAAQ,EAAE,SAAS,CAAC,CACjC,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,GAAW;IAC/B,OAAO,GAAG,CAAC,OAAO,CAAC,uBAAuB,EAAE,EAAE,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,UAAU,CAAC,GAAW;IAC7B,OAAO,GAAG,CAAC,OAAO,CAAC,qCAAqC,EAAE,EAAE,CAAC,CAAC;AAChE,CAAC;AAED,SAAS,kBAAkB,CAAC,GAAW;IACrC,OAAO,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,iCAAiC,CAAC,GAAW;IACpD,OAAO,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAa,EAAE,YAAqB;IAC/D,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACrC,IAAI,QAAQ,IAAI,CAAC,YAAY,EAAE;QAC7B,OAAO,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;KAC7C;SAAM,IAAI,CAAC,QAAQ,IAAI,YAAY,EAAE;QACpC,OAAO,GAAG,KAAK,GAAG,CAAC;KACpB;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAa,EAAE,YAAqB;IAC9D,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IACvC,IAAI,QAAQ,IAAI,CAAC,YAAY,EAAE;QAC7B,OAAO,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;KAC3B;SAAM,IAAI,CAAC,QAAQ,IAAI,YAAY,EAAE;QACpC,OAAO,IAAI,KAAK,EAAE,CAAC;KACpB;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,cAAc;AACd;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,OAAO,CAAC,OAAe,EAAE,EAAE,WAAyB,EAAE,MAAe;IACnF,OAAO,SAAS,CAAC,IAAI,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC;AACzE,CAAC;AAED,cAAc;AACd;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,SAAS,CACvB,IAAY,EACZ,EAAE,MAAM,EAAE,WAAW,GAAG,EAAE,EAAE,eAAe,GAAG,KAAK,KAAuB,EAAE;IAE5E,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE;QACzB,IAAI,CAAC,QAAQ,CAAC,cAAc;YAAE,OAAO,EAAE,CAAC;QAExC,MAAM,MAAM,GAAG,mBAAmB,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAClE,IAAI,WAAW,GAAG,EAAE,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QAC5C,IAAI,WAAW,EAAE;YACf,WAAW,GAAG,IAAI,WAAW,EAAE,CAAC;SACjC;QAED,IAAI,UAAU,GAAG,IAAI,CAAC;QACtB,IAAI,UAAU;YAAE,UAAU,GAAG,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAE5D,OAAO,SAAS,CAAC,GAAG,MAAM,GAAG,UAAU,GAAG,WAAW,EAAE,CAAC,CAAC;KAC1D;IAED,MAAM,cAAc,GAAG,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IAEjD,IAAI,OAAO,GAAG,UAAU,EAAE,IAAI,EAAE,CAAC;IAEjC,IAAI,eAAe,EAAE,IAAI,YAAY,EAAE,EAAE;QACvC,OAAO,GAAG,EAAE,CAAC;KACd;IAED,IAAI,IAAI,EAAE;QACR,IAAI,YAAY,EAAE,IAAI,OAAO,EAAE;YAC7B,IAAI,GAAG,OAAO,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;SAC1C;QACD,IAAI,eAAe,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;YAC5C,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;SACnB;KACF;SAAM;QACL,IAAI,GAAG,EAAE,CAAC;KACX;IAED,6EAA6E;IAC7E,uBAAuB;IACvB,IAAI,WAAW,GAAG,EAAE,CAAC;IACrB,MAAM,sBAAsB,GAAG,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IAC3D,IAAI,sBAAsB,EAAE;QAC1B,OAAO,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;QACpC,WAAW,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;QACxC,IAAI,iBAAiB,GAAG,EAAE,CAAC;QAC3B,IAAI;YACF,MAAM,YAAY,GAAG,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YAC3C,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE;gBACpC,iBAAiB,GAAG,YAAY,CAAC;aAClC;SACF;QAAC,OAAO,CAAC,EAAE,GAAE;QACd,WAAW,GAAG;YACZ,GAAG,WAAW;YACd,GAAG,iBAAiB;SACrB,CAAC;KACH;IACD,WAAW,GAAG,EAAE,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IACxC,IAAI,WAAW,EAAE;QACf,WAAW,GAAG,IAAI,WAAW,EAAE,CAAC;KACjC;IAED,OAAO,GAAG,kBAAkB,CAAC,OAAO,EAAE,CAAC,eAAe,CAAC,CAAC;IAExD,OAAO,SAAS,CACd,GAAG,cAAc,IAAI,eAAe,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,OAAO,GAAG,IAAI,GAAG,WAAW,EAAE,CAClF,CAAC;AACJ,CAAC;AAED,cAAc;AACd;;;;GAIG;AACH,MAAM,UAAU,KAAK,CAAC,GAAW;IAC/B,WAAW,CAAC,GAAG,CAAC,CAAC;IAEjB,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,sBAAsB,CAAC,IAAI,CAAC,CAAC;IAErD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,KAAK,EAAE;QAChC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAE,CAAC,CAAC;KAChE;IACD,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC;IAEjC,MAAM,OAAO,GAAG,UAAU,EAAE,IAAI,EAAE,CAAC;IACnC,MAAM,eAAe,GAAG,UAAU,CAAC,iCAAiC,CAAC,OAAO,CAAC,CAAC,CAAC;IAE/E,IAAI,IAAI,GAAG,MAAM,CAAC,QAAQ,IAAI,IAAI,CAAC;IACnC,IAAI,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,IAAI,CAAC;IACvC,IAAI,MAAM,GAAG,MAAM,CAAC,QAAQ,IAAI,IAAI,CAAC;IAErC,IAAI,MAAM,EAAE;QACV,sBAAsB;QACtB,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;KACjD;IAED,IAAI,IAAI,EAAE;QACR,IAAI,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;QAEhC,IAAI,UAAU,GAAkB,IAAI,CAAC;QACrC,IAAI,eAAe,EAAE;YACnB,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACzC,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;SACvD;QAED,IAAI,YAAY,EAAE,IAAI,CAAC,eAAe,EAAE,IAAI,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE;YACrF,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YACzC,QAAQ,GAAG,IAAI,CAAC;SACjB;aAAM,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE;YACjC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;SAC9C;KACF;IAED,OAAO;QACL,QAAQ;QACR,IAAI;QACJ,WAAW;QACX,MAAM;KACP,CAAC;AACJ,CAAC;AAED,cAAc;AACd;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY,EAAE,OAAoB;IACjE,aAAa,CAAC,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAChD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY,EAAE,OAAoB;IACpE,aAAa,CAAC,mBAAmB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AACnD,CAAC;AAED,cAAc;AACd;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,MAAM,UAAU,GAAG,MAAM,aAAa,CAAC,aAAa,EAAE,CAAC;IACvD,IAAI,CAAC,UAAU,EAAE;QACf,OAAO;YACL,MAAM,EAAE,IAAI;YACZ,QAAQ,EAAE,IAAI;YACd,IAAI,EAAE,IAAI;YACV,WAAW,EAAE,IAAI;SAClB,CAAC;KACH;IAED,OAAO,KAAK,CAAC,UAAU,CAAC,CAAC;AAC3B,CAAC;AAED,cAAc;AACd;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAc,EAAE,MAA2B;IAC1E,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,EAAE;QAC7B,OAAO,MAAM,aAAa,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACvD;IACD,MAAM,IAAI,mBAAmB,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;AACzD,CAAC;AAED,cAAc;AACd;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE;QACzB,MAAM,IAAI,mBAAmB,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;KAC1D;IACD,IAAI,aAAa,CAAC,YAAY,EAAE;QAC9B,OAAO,MAAM,aAAa,CAAC,YAAY,EAAE,CAAC;KAC3C;IACD,MAAM,OAAO,CAAC,eAAe,CAAC,CAAC;AACjC,CAAC;AAED,cAAc;AACd;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,OAAO,CAAC,MAAM,aAAa,CAAC,aAAa,EAAE,CAAC,IAAI,IAAI,CAAC;AACvD,CAAC;AAED,cAAc;AACd;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,GAAW;IACvC,WAAW,CAAC,GAAG,CAAC,CAAC;IACjB,OAAO,MAAM,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AAC1C,CAAC;AAED,cAAc;AACd;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAW;IAC1C,WAAW,CAAC,GAAG,CAAC,CAAC;IACjB,OAAO,MAAM,aAAa,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;AAC7C,CAAC;AAED,cAAc;AACd;;;GAGG;AACH,MAAM,UAAU,MAAM;IACpB,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAErD,SAAS,QAAQ,CAAC,KAAsB;QACtC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACrB,CAAC;IAED,SAAS,CAAC,GAAG,EAAE;QACb,aAAa,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5C,gBAAgB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QAClC,OAAO,GAAG,EAAE,CAAC,mBAAmB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACpD,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,GAAG,CAAC;AACb,CAAC;AAED,cAAc,iBAAiB,CAAC","sourcesContent":["import Constants from 'expo-constants';\nimport { Platform, UnavailabilityError } from 'expo-modules-core';\nimport invariant from 'invariant';\nimport qs from 'qs';\nimport { useEffect, useState } from 'react';\nimport URL from 'url-parse';\n\nimport NativeLinking from './ExpoLinking';\nimport {\n CreateURLOptions,\n ParsedURL,\n QueryParams,\n SendIntentExtras,\n URLListener,\n} from './Linking.types';\nimport { hasCustomScheme, resolveScheme } from './Schemes';\n\nfunction validateURL(url: string): void {\n invariant(typeof url === 'string', 'Invalid URL: should be a string. Was: ' + url);\n invariant(url, 'Invalid URL: cannot be empty');\n}\n\nfunction getHostUri(): string | null {\n if (Constants.manifest?.hostUri) {\n return Constants.manifest.hostUri;\n } else if (Constants.manifest2?.extra?.expoClient?.hostUri) {\n return Constants.manifest2.extra.expoClient.hostUri;\n } else if (!hasCustomScheme()) {\n // we're probably not using up-to-date xdl, so just fake it for now\n // we have to remove the /--/ on the end since this will be inserted again later\n return removeScheme(Constants.linkingUri).replace(/\\/--($|\\/.*$)/, '');\n } else {\n return null;\n }\n}\n\nfunction isExpoHosted(): boolean {\n const hostUri = getHostUri();\n return !!(\n hostUri &&\n (/^(.*\\.)?(expo\\.io|exp\\.host|exp\\.direct|expo\\.test)(:.*)?(\\/.*)?$/.test(hostUri) ||\n Constants.manifest?.developer)\n );\n}\n\nfunction removeScheme(url: string): string {\n return url.replace(/^[a-zA-Z0-9+.-]+:\\/\\//, '');\n}\n\nfunction removePort(url: string): string {\n return url.replace(/(?=([a-zA-Z0-9+.-]+:\\/\\/)?[^/]):\\d+/, '');\n}\n\nfunction removeLeadingSlash(url: string): string {\n return url.replace(/^\\//, '');\n}\n\nfunction removeTrailingSlashAndQueryString(url: string): string {\n return url.replace(/\\/?\\?.*$/, '');\n}\n\nfunction ensureTrailingSlash(input: string, shouldAppend: boolean): string {\n const hasSlash = input.endsWith('/');\n if (hasSlash && !shouldAppend) {\n return input.substring(0, input.length - 1);\n } else if (!hasSlash && shouldAppend) {\n return `${input}/`;\n }\n return input;\n}\n\nfunction ensureLeadingSlash(input: string, shouldAppend: boolean): string {\n const hasSlash = input.startsWith('/');\n if (hasSlash && !shouldAppend) {\n return input.substring(1);\n } else if (!hasSlash && shouldAppend) {\n return `/${input}`;\n }\n return input;\n}\n\n// @needsAudit\n/**\n * Create a URL that works for the environment the app is currently running in.\n * The scheme in bare and standalone must be defined in the app.json under `expo.scheme`.\n *\n * # Examples\n * - Bare: empty string\n * - Standalone, Custom: `yourscheme:///path`\n * - Web (dev): `https://localhost:19006/path`\n * - Web (prod): `https://myapp.com/path`\n * - Expo Client (dev): `exp://128.0.0.1:19000/--/path`\n * - Expo Client (prod): `exp://exp.host/@yourname/your-app/--/path`\n *\n * @param path addition path components to append to the base URL.\n * @param queryParams An object with a set of query parameters. These will be merged with any\n * Expo-specific parameters that are needed (e.g. release channel) and then appended to the URL\n * as a query string.\n * @param scheme Optional URI protocol to use in the URL `<scheme>:///`, when `undefined` the scheme\n * will be chosen from the Expo config (`app.config.js` or `app.json`).\n * @return A URL string which points to your app with the given deep link information.\n * @deprecated An alias for [`createURL()`](#linkingcreateurlpath-namedparameters). This method is\n * deprecated and will be removed in a future SDK version.\n */\nexport function makeUrl(path: string = '', queryParams?: QueryParams, scheme?: string): string {\n return createURL(path, { queryParams, scheme, isTripleSlashed: true });\n}\n\n// @needsAudit\n/**\n * Helper method for constructing a deep link into your app, given an optional path and set of query\n * parameters. Creates a URI scheme with two slashes by default.\n *\n * The scheme in bare and standalone must be defined in the Expo config (`app.config.js` or `app.json`)\n * under `expo.scheme`.\n *\n * # Examples\n * - Bare: `<scheme>://path` - uses provided scheme or scheme from Expo config `scheme`.\n * - Standalone, Custom: `yourscheme://path`\n * - Web (dev): `https://localhost:19006/path`\n * - Web (prod): `https://myapp.com/path`\n * - Expo Client (dev): `exp://128.0.0.1:19000/--/path`\n * - Expo Client (prod): `exp://exp.host/@yourname/your-app/--/path`\n *\n * @param path Addition path components to append to the base URL.\n * @param namedParameters Additional options object.\n * @return A URL string which points to your app with the given deep link information.\n */\nexport function createURL(\n path: string,\n { scheme, queryParams = {}, isTripleSlashed = false }: CreateURLOptions = {}\n): string {\n if (Platform.OS === 'web') {\n if (!Platform.isDOMAvailable) return '';\n\n const origin = ensureTrailingSlash(window.location.origin, false);\n let queryString = qs.stringify(queryParams);\n if (queryString) {\n queryString = `?${queryString}`;\n }\n\n let outputPath = path;\n if (outputPath) outputPath = ensureLeadingSlash(path, true);\n\n return encodeURI(`${origin}${outputPath}${queryString}`);\n }\n\n const resolvedScheme = resolveScheme({ scheme });\n\n let hostUri = getHostUri() || '';\n\n if (hasCustomScheme() && isExpoHosted()) {\n hostUri = '';\n }\n\n if (path) {\n if (isExpoHosted() && hostUri) {\n path = `/--/${removeLeadingSlash(path)}`;\n }\n if (isTripleSlashed && !path.startsWith('/')) {\n path = `/${path}`;\n }\n } else {\n path = '';\n }\n\n // merge user-provided query params with any that were already in the hostUri\n // e.g. release-channel\n let queryString = '';\n const queryStringMatchResult = hostUri.match(/(.*)\\?(.+)/);\n if (queryStringMatchResult) {\n hostUri = queryStringMatchResult[1];\n queryString = queryStringMatchResult[2];\n let paramsFromHostUri = {};\n try {\n const parsedParams = qs.parse(queryString);\n if (typeof parsedParams === 'object') {\n paramsFromHostUri = parsedParams;\n }\n } catch (e) {}\n queryParams = {\n ...queryParams,\n ...paramsFromHostUri,\n };\n }\n queryString = qs.stringify(queryParams);\n if (queryString) {\n queryString = `?${queryString}`;\n }\n\n hostUri = ensureLeadingSlash(hostUri, !isTripleSlashed);\n\n return encodeURI(\n `${resolvedScheme}:${isTripleSlashed ? '/' : ''}/${hostUri}${path}${queryString}`\n );\n}\n\n// @needsAudit\n/**\n * Helper method for parsing out deep link information from a URL.\n * @param url A URL that points to the currently running experience (e.g. an output of `Linking.createURL()`).\n * @return A `ParsedURL` object.\n */\nexport function parse(url: string): ParsedURL {\n validateURL(url);\n\n const parsed = URL(url, /* parseQueryString */ true);\n\n for (const param in parsed.query) {\n parsed.query[param] = decodeURIComponent(parsed.query[param]!);\n }\n const queryParams = parsed.query;\n\n const hostUri = getHostUri() || '';\n const hostUriStripped = removePort(removeTrailingSlashAndQueryString(hostUri));\n\n let path = parsed.pathname || null;\n let hostname = parsed.hostname || null;\n let scheme = parsed.protocol || null;\n\n if (scheme) {\n // Remove colon at end\n scheme = scheme.substring(0, scheme.length - 1);\n }\n\n if (path) {\n path = removeLeadingSlash(path);\n\n let expoPrefix: string | null = null;\n if (hostUriStripped) {\n const parts = hostUriStripped.split('/');\n expoPrefix = parts.slice(1).concat(['--/']).join('/');\n }\n\n if (isExpoHosted() && !hasCustomScheme() && expoPrefix && path.startsWith(expoPrefix)) {\n path = path.substring(expoPrefix.length);\n hostname = null;\n } else if (path.indexOf('+') > -1) {\n path = path.substring(path.indexOf('+') + 1);\n }\n }\n\n return {\n hostname,\n path,\n queryParams,\n scheme,\n };\n}\n\n// @needsAudit\n/**\n * Add a handler to `Linking` changes by listening to the `url` event type and providing the handler.\n * It is recommended to use the [`useURL()`](#useurl) hook instead.\n * @param type The only valid type is `'url'`.\n * @param handler An [`URLListener`](#urllistener) function that takes an `event` object of the type\n * [`EventType`](#eventype).\n * @see [React Native Docs Linking page](https://reactnative.dev/docs/linking#addeventlistener).\n */\nexport function addEventListener(type: string, handler: URLListener): void {\n NativeLinking.addEventListener(type, handler);\n}\n\n/**\n * Remove a handler by passing the `url` event type and the handler.\n * @param type The only valid type is `'url'`.\n * @param handler An [`URLListener`](#urllistener) function that takes an `event` object of the type\n * [`EventType`](#eventype).\n * @see [React Native Docs Linking page](https://reactnative.dev/docs/linking#removeeventlistener).\n */\nexport function removeEventListener(type: string, handler: URLListener): void {\n NativeLinking.removeEventListener(type, handler);\n}\n\n// @needsAudit\n/**\n * Helper method which wraps React Native's `Linking.getInitialURL()` in `Linking.parse()`.\n * Parses the deep link information out of the URL used to open the experience initially.\n * If no link opened the app, all the fields will be `null`.\n * > On the web it parses the current window URL.\n * @return A promise that resolves with `ParsedURL` object.\n */\nexport async function parseInitialURLAsync(): Promise<ParsedURL> {\n const initialUrl = await NativeLinking.getInitialURL();\n if (!initialUrl) {\n return {\n scheme: null,\n hostname: null,\n path: null,\n queryParams: null,\n };\n }\n\n return parse(initialUrl);\n}\n\n// @needsAudit\n/**\n * Launch an Android intent with extras.\n * > Use [IntentLauncher](../intent-launcher) instead, `sendIntent` is only included in\n * > `Linking` for API compatibility with React Native's Linking API.\n * @platform android\n */\nexport async function sendIntent(action: string, extras?: SendIntentExtras[]): Promise<void> {\n if (Platform.OS === 'android') {\n return await NativeLinking.sendIntent(action, extras);\n }\n throw new UnavailabilityError('Linking', 'sendIntent');\n}\n\n// @needsAudit\n/**\n * Open the operating system settings app and displays the app’s custom settings, if it has any.\n * @platform ios\n */\nexport async function openSettings(): Promise<void> {\n if (Platform.OS === 'web') {\n throw new UnavailabilityError('Linking', 'openSettings');\n }\n if (NativeLinking.openSettings) {\n return await NativeLinking.openSettings();\n }\n await openURL('app-settings:');\n}\n\n// @needsAudit\n/**\n * Get the URL that was used to launch the app if it was launched by a link.\n * @return The URL string that launched your app, or `null`.\n */\nexport async function getInitialURL(): Promise<string | null> {\n return (await NativeLinking.getInitialURL()) ?? null;\n}\n\n// @needsAudit\n/**\n * Attempt to open the given URL with an installed app. See the [Linking guide](/guides/linking)\n * for more information.\n * @param url A URL for the operating system to open, eg: `tel:5555555`, `exp://`.\n * @return A `Promise` that is fulfilled with `true` if the link is opened operating system\n * automatically or the user confirms the prompt to open the link. The `Promise` rejects if there\n * are no applications registered for the URL or the user cancels the dialog.\n */\nexport async function openURL(url: string): Promise<true> {\n validateURL(url);\n return await NativeLinking.openURL(url);\n}\n\n// @needsAudit\n/**\n * Determine whether or not an installed app can handle a given URL.\n * On web this always returns `true` because there is no API for detecting what URLs can be opened.\n * @param url The URL that you want to test can be opened.\n * @return A `Promise` object that is fulfilled with `true` if the URL can be handled, otherwise it\n * `false` if not.\n *\n * The `Promise` will reject on Android if it was impossible to check if the URL can be opened, and\n * on iOS if you didn't [add the specific scheme in the `LSApplicationQueriesSchemes` key inside **Info.plist**](/guides/linking#opening-links-to-other-apps).\n */\nexport async function canOpenURL(url: string): Promise<boolean> {\n validateURL(url);\n return await NativeLinking.canOpenURL(url);\n}\n\n// @needsAudit\n/**\n * Returns the initial URL followed by any subsequent changes to the URL.\n * @return Returns the initial URL or `null`.\n */\nexport function useURL(): string | null {\n const [url, setLink] = useState<string | null>(null);\n\n function onChange(event: { url: string }) {\n setLink(event.url);\n }\n\n useEffect(() => {\n getInitialURL().then((url) => setLink(url));\n addEventListener('url', onChange);\n return () => removeEventListener('url', onChange);\n }, []);\n\n return url;\n}\n\nexport * from './Linking.types';\n"]}
|
|
1
|
+
{"version":3,"file":"Linking.js","sourceRoot":"","sources":["../src/Linking.ts"],"names":[],"mappings":"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","sourcesContent":["import Constants from 'expo-constants';\nimport { Platform, UnavailabilityError } from 'expo-modules-core';\nimport invariant from 'invariant';\nimport qs from 'qs';\nimport { useEffect, useState } from 'react';\nimport { EmitterSubscription } from 'react-native';\nimport URL from 'url-parse';\n\nimport NativeLinking from './ExpoLinking';\nimport {\n CreateURLOptions,\n ParsedURL,\n QueryParams,\n SendIntentExtras,\n URLListener,\n} from './Linking.types';\nimport { hasCustomScheme, resolveScheme } from './Schemes';\n\nfunction validateURL(url: string): void {\n invariant(typeof url === 'string', 'Invalid URL: should be a string. Was: ' + url);\n invariant(url, 'Invalid URL: cannot be empty');\n}\n\nfunction getHostUri(): string | null {\n if (Constants.manifest?.hostUri) {\n return Constants.manifest.hostUri;\n } else if (Constants.manifest2?.extra?.expoClient?.hostUri) {\n return Constants.manifest2.extra.expoClient.hostUri;\n } else if (!hasCustomScheme()) {\n // we're probably not using up-to-date xdl, so just fake it for now\n // we have to remove the /--/ on the end since this will be inserted again later\n return removeScheme(Constants.linkingUri).replace(/\\/--($|\\/.*$)/, '');\n } else {\n return null;\n }\n}\n\nfunction isExpoHosted(): boolean {\n const hostUri = getHostUri();\n return !!(\n hostUri &&\n (/^(.*\\.)?(expo\\.io|exp\\.host|exp\\.direct|expo\\.test)(:.*)?(\\/.*)?$/.test(hostUri) ||\n Constants.manifest?.developer ||\n Constants.manifest2?.extra?.expoGo?.developer)\n );\n}\n\nfunction removeScheme(url: string): string {\n return url.replace(/^[a-zA-Z0-9+.-]+:\\/\\//, '');\n}\n\nfunction removePort(url: string): string {\n return url.replace(/(?=([a-zA-Z0-9+.-]+:\\/\\/)?[^/]):\\d+/, '');\n}\n\nfunction removeLeadingSlash(url: string): string {\n return url.replace(/^\\//, '');\n}\n\nfunction removeTrailingSlashAndQueryString(url: string): string {\n return url.replace(/\\/?\\?.*$/, '');\n}\n\nfunction ensureTrailingSlash(input: string, shouldAppend: boolean): string {\n const hasSlash = input.endsWith('/');\n if (hasSlash && !shouldAppend) {\n return input.substring(0, input.length - 1);\n } else if (!hasSlash && shouldAppend) {\n return `${input}/`;\n }\n return input;\n}\n\nfunction ensureLeadingSlash(input: string, shouldAppend: boolean): string {\n const hasSlash = input.startsWith('/');\n if (hasSlash && !shouldAppend) {\n return input.substring(1);\n } else if (!hasSlash && shouldAppend) {\n return `/${input}`;\n }\n return input;\n}\n\n// @needsAudit\n/**\n * Create a URL that works for the environment the app is currently running in.\n * The scheme in bare and standalone must be defined in the app.json under `expo.scheme`.\n *\n * # Examples\n * - Bare: empty string\n * - Standalone, Custom: `yourscheme:///path`\n * - Web (dev): `https://localhost:19006/path`\n * - Web (prod): `https://myapp.com/path`\n * - Expo Client (dev): `exp://128.0.0.1:19000/--/path`\n * - Expo Client (prod): `exp://exp.host/@yourname/your-app/--/path`\n *\n * @param path addition path components to append to the base URL.\n * @param queryParams An object with a set of query parameters. These will be merged with any\n * Expo-specific parameters that are needed (e.g. release channel) and then appended to the URL\n * as a query string.\n * @param scheme Optional URI protocol to use in the URL `<scheme>:///`, when `undefined` the scheme\n * will be chosen from the Expo config (`app.config.js` or `app.json`).\n * @return A URL string which points to your app with the given deep link information.\n * @deprecated An alias for [`createURL()`](#linkingcreateurlpath-namedparameters). This method is\n * deprecated and will be removed in a future SDK version.\n */\nexport function makeUrl(path: string = '', queryParams?: QueryParams, scheme?: string): string {\n return createURL(path, { queryParams, scheme, isTripleSlashed: true });\n}\n\n// @needsAudit\n/**\n * Helper method for constructing a deep link into your app, given an optional path and set of query\n * parameters. Creates a URI scheme with two slashes by default.\n *\n * The scheme in bare and standalone must be defined in the Expo config (`app.config.js` or `app.json`)\n * under `expo.scheme`.\n *\n * # Examples\n * - Bare: `<scheme>://path` - uses provided scheme or scheme from Expo config `scheme`.\n * - Standalone, Custom: `yourscheme://path`\n * - Web (dev): `https://localhost:19006/path`\n * - Web (prod): `https://myapp.com/path`\n * - Expo Client (dev): `exp://128.0.0.1:19000/--/path`\n * - Expo Client (prod): `exp://exp.host/@yourname/your-app/--/path`\n *\n * @param path Addition path components to append to the base URL.\n * @param namedParameters Additional options object.\n * @return A URL string which points to your app with the given deep link information.\n */\nexport function createURL(\n path: string,\n { scheme, queryParams = {}, isTripleSlashed = false }: CreateURLOptions = {}\n): string {\n if (Platform.OS === 'web') {\n if (!Platform.isDOMAvailable) return '';\n\n const origin = ensureTrailingSlash(window.location.origin, false);\n let queryString = qs.stringify(queryParams);\n if (queryString) {\n queryString = `?${queryString}`;\n }\n\n let outputPath = path;\n if (outputPath) outputPath = ensureLeadingSlash(path, true);\n\n return encodeURI(`${origin}${outputPath}${queryString}`);\n }\n\n const resolvedScheme = resolveScheme({ scheme });\n\n let hostUri = getHostUri() || '';\n\n if (hasCustomScheme() && isExpoHosted()) {\n hostUri = '';\n }\n\n if (path) {\n if (isExpoHosted() && hostUri) {\n path = `/--/${removeLeadingSlash(path)}`;\n }\n if (isTripleSlashed && !path.startsWith('/')) {\n path = `/${path}`;\n }\n } else {\n path = '';\n }\n\n // merge user-provided query params with any that were already in the hostUri\n // e.g. release-channel\n let queryString = '';\n const queryStringMatchResult = hostUri.match(/(.*)\\?(.+)/);\n if (queryStringMatchResult) {\n hostUri = queryStringMatchResult[1];\n queryString = queryStringMatchResult[2];\n let paramsFromHostUri = {};\n try {\n const parsedParams = qs.parse(queryString);\n if (typeof parsedParams === 'object') {\n paramsFromHostUri = parsedParams;\n }\n } catch {}\n queryParams = {\n ...queryParams,\n ...paramsFromHostUri,\n };\n }\n queryString = qs.stringify(queryParams);\n if (queryString) {\n queryString = `?${queryString}`;\n }\n\n hostUri = ensureLeadingSlash(hostUri, !isTripleSlashed);\n\n return encodeURI(\n `${resolvedScheme}:${isTripleSlashed ? '/' : ''}/${hostUri}${path}${queryString}`\n );\n}\n\n// @needsAudit\n/**\n * Helper method for parsing out deep link information from a URL.\n * @param url A URL that points to the currently running experience (e.g. an output of `Linking.createURL()`).\n * @return A `ParsedURL` object.\n */\nexport function parse(url: string): ParsedURL {\n validateURL(url);\n\n const parsed = URL(url, /* parseQueryString */ true);\n\n for (const param in parsed.query) {\n parsed.query[param] = decodeURIComponent(parsed.query[param]!);\n }\n const queryParams = parsed.query;\n\n const hostUri = getHostUri() || '';\n const hostUriStripped = removePort(removeTrailingSlashAndQueryString(hostUri));\n\n let path = parsed.pathname || null;\n let hostname = parsed.hostname || null;\n let scheme = parsed.protocol || null;\n\n if (scheme) {\n // Remove colon at end\n scheme = scheme.substring(0, scheme.length - 1);\n }\n\n if (path) {\n path = removeLeadingSlash(path);\n\n let expoPrefix: string | null = null;\n if (hostUriStripped) {\n const parts = hostUriStripped.split('/');\n expoPrefix = parts.slice(1).concat(['--/']).join('/');\n }\n\n if (isExpoHosted() && !hasCustomScheme() && expoPrefix && path.startsWith(expoPrefix)) {\n path = path.substring(expoPrefix.length);\n hostname = null;\n } else if (path.indexOf('+') > -1) {\n path = path.substring(path.indexOf('+') + 1);\n }\n }\n\n return {\n hostname,\n path,\n queryParams,\n scheme,\n };\n}\n\n// @needsAudit\n/**\n * Add a handler to `Linking` changes by listening to the `url` event type and providing the handler.\n * It is recommended to use the [`useURL()`](#useurl) hook instead.\n * @param type The only valid type is `'url'`.\n * @param handler An [`URLListener`](#urllistener) function that takes an `event` object of the type\n * [`EventType`](#eventype).\n * @return An EmitterSubscription that has the remove method from EventSubscription\n * @see [React Native Docs Linking page](https://reactnative.dev/docs/linking#addeventlistener).\n */\nexport function addEventListener(type: 'url', handler: URLListener): EmitterSubscription {\n return NativeLinking.addEventListener(type, handler);\n}\n\n/**\n * Remove a handler by passing the `url` event type and the handler.\n * @param type The only valid type is `'url'`.\n * @param handler An [`URLListener`](#urllistener) function that takes an `event` object of the type\n * [`EventType`](#eventype).\n * @see [React Native Docs Linking page](https://reactnative.dev/docs/linking#removeeventlistener).\n *\n * @deprecated Call `remove()` on the return value of `addEventListener()` instead.\n */\nexport function removeEventListener(type: 'url', handler: URLListener): void {\n NativeLinking.removeEventListener(type, handler);\n}\n\n// @needsAudit\n/**\n * Helper method which wraps React Native's `Linking.getInitialURL()` in `Linking.parse()`.\n * Parses the deep link information out of the URL used to open the experience initially.\n * If no link opened the app, all the fields will be `null`.\n * > On the web it parses the current window URL.\n * @return A promise that resolves with `ParsedURL` object.\n */\nexport async function parseInitialURLAsync(): Promise<ParsedURL> {\n const initialUrl = await NativeLinking.getInitialURL();\n if (!initialUrl) {\n return {\n scheme: null,\n hostname: null,\n path: null,\n queryParams: null,\n };\n }\n\n return parse(initialUrl);\n}\n\n// @needsAudit\n/**\n * Launch an Android intent with extras.\n * > Use [IntentLauncher](./intent-launcher) instead, `sendIntent` is only included in\n * > `Linking` for API compatibility with React Native's Linking API.\n * @platform android\n */\nexport async function sendIntent(action: string, extras?: SendIntentExtras[]): Promise<void> {\n if (Platform.OS === 'android') {\n return await NativeLinking.sendIntent(action, extras);\n }\n throw new UnavailabilityError('Linking', 'sendIntent');\n}\n\n// @needsAudit\n/**\n * Open the operating system settings app and displays the app’s custom settings, if it has any.\n */\nexport async function openSettings(): Promise<void> {\n if (Platform.OS === 'web') {\n throw new UnavailabilityError('Linking', 'openSettings');\n }\n if (NativeLinking.openSettings) {\n return await NativeLinking.openSettings();\n }\n await openURL('app-settings:');\n}\n\n// @needsAudit\n/**\n * Get the URL that was used to launch the app if it was launched by a link.\n * @return The URL string that launched your app, or `null`.\n */\nexport async function getInitialURL(): Promise<string | null> {\n return (await NativeLinking.getInitialURL()) ?? null;\n}\n\n// @needsAudit\n/**\n * Attempt to open the given URL with an installed app. See the [Linking guide](/guides/linking)\n * for more information.\n * @param url A URL for the operating system to open, eg: `tel:5555555`, `exp://`.\n * @return A `Promise` that is fulfilled with `true` if the link is opened operating system\n * automatically or the user confirms the prompt to open the link. The `Promise` rejects if there\n * are no applications registered for the URL or the user cancels the dialog.\n */\nexport async function openURL(url: string): Promise<true> {\n validateURL(url);\n return await NativeLinking.openURL(url);\n}\n\n// @needsAudit\n/**\n * Determine whether or not an installed app can handle a given URL.\n * On web this always returns `true` because there is no API for detecting what URLs can be opened.\n * @param url The URL that you want to test can be opened.\n * @return A `Promise` object that is fulfilled with `true` if the URL can be handled, otherwise it\n * `false` if not.\n *\n * The `Promise` will reject on Android if it was impossible to check if the URL can be opened, and\n * on iOS if you didn't [add the specific scheme in the `LSApplicationQueriesSchemes` key inside **Info.plist**](/guides/linking#opening-links-to-other-apps).\n */\nexport async function canOpenURL(url: string): Promise<boolean> {\n validateURL(url);\n return await NativeLinking.canOpenURL(url);\n}\n\n// @needsAudit\n/**\n * Returns the initial URL followed by any subsequent changes to the URL.\n * @return Returns the initial URL or `null`.\n */\nexport function useURL(): string | null {\n const [url, setLink] = useState<string | null>(null);\n\n function onChange(event: { url: string }) {\n setLink(event.url);\n }\n\n useEffect(() => {\n getInitialURL().then((url) => setLink(url));\n const subscription = addEventListener('url', onChange);\n return () => subscription.remove();\n }, []);\n\n return url;\n}\n\nexport * from './Linking.types';\nexport * from './Schemes';\n"]}
|
package/build/Linking.types.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Linking.types.d.ts","sourceRoot":"","sources":["../src/Linking.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AAG9B,oBAAY,WAAW,GAAG,QAAQ,CAAC;AAGnC,oBAAY,SAAS,GAAG;IACtB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;OAEG;IACH,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB;;OAEG;IACH,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;CACjC,CAAC;AAGF,oBAAY,gBAAgB,GAAG;IAC7B;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AAGF,oBAAY,SAAS,GAAG;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,YAAY,CAAC;CAC5B,CAAC;AAGF,oBAAY,WAAW,GAAG,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;AAGrD,oBAAY,iBAAiB,GAAG,CAAC,WAAW,EAAE,YAAY,KAAK,IAAI,CAAC;AAGpE,oBAAY,gBAAgB,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC"}
|
package/build/Schemes.d.ts
CHANGED
|
@@ -9,8 +9,12 @@ export declare function hasCustomScheme(): boolean;
|
|
|
9
9
|
* - Android: scheme -> android.scheme -> android.package
|
|
10
10
|
*/
|
|
11
11
|
export declare function collectManifestSchemes(): string[];
|
|
12
|
+
/**
|
|
13
|
+
* Ensure the user has linked the expo-constants manifest in bare workflow.
|
|
14
|
+
*/
|
|
12
15
|
export declare function hasConstantsManifest(): boolean;
|
|
13
|
-
export declare function resolveScheme(
|
|
16
|
+
export declare function resolveScheme(options: {
|
|
14
17
|
scheme?: string;
|
|
15
18
|
isSilent?: boolean;
|
|
16
19
|
}): string;
|
|
20
|
+
//# sourceMappingURL=Schemes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Schemes.d.ts","sourceRoot":"","sources":["../src/Schemes.ts"],"names":[],"mappings":"AAMA,wBAAgB,eAAe,IAAI,OAAO,CAWzC;AAkCD;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,EAAE,CAuBjD;AAeD;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAK9C;AAGD,wBAAgB,aAAa,CAAC,OAAO,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAiGtF"}
|
package/build/Schemes.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import Constants, { ExecutionEnvironment } from 'expo-constants';
|
|
2
2
|
import { Platform } from 'expo-modules-core';
|
|
3
|
-
const LINKING_GUIDE_URL = `https://docs.expo.
|
|
3
|
+
const LINKING_GUIDE_URL = `https://docs.expo.dev/guides/linking/`;
|
|
4
|
+
// @docsMissing
|
|
4
5
|
export function hasCustomScheme() {
|
|
5
6
|
if (Constants.executionEnvironment === ExecutionEnvironment.Bare) {
|
|
6
7
|
// Bare always uses a custom scheme.
|
|
@@ -56,17 +57,14 @@ export function collectManifestSchemes() {
|
|
|
56
57
|
// They'll be added when we drop support for `expo build` or decide
|
|
57
58
|
// to have them only work with `eas build`.
|
|
58
59
|
const platformManifest = Platform.select({
|
|
59
|
-
ios: Constants.
|
|
60
|
-
android: Constants.
|
|
60
|
+
ios: Constants.expoConfig?.ios,
|
|
61
|
+
android: Constants.expoConfig?.android,
|
|
61
62
|
web: {},
|
|
62
63
|
}) ?? {};
|
|
63
|
-
const schemes = getSchemes(Constants.
|
|
64
|
+
const schemes = getSchemes(Constants.expoConfig);
|
|
64
65
|
// Add the detached scheme after the manifest scheme for legacy ExpoKit support.
|
|
65
|
-
if (Constants.
|
|
66
|
-
schemes.push(Constants.
|
|
67
|
-
}
|
|
68
|
-
if (Constants.manifest2?.extra?.expoClient?.detach?.scheme) {
|
|
69
|
-
schemes.push(Constants.manifest2.extra.expoClient.detach.scheme);
|
|
66
|
+
if (Constants.expoConfig?.detach?.scheme) {
|
|
67
|
+
schemes.push(Constants.expoConfig.detach.scheme);
|
|
70
68
|
}
|
|
71
69
|
// Add the unimplemented platform schemes last.
|
|
72
70
|
schemes.push(...getSchemes(platformManifest));
|
|
@@ -76,27 +74,29 @@ function getNativeAppIdScheme() {
|
|
|
76
74
|
// Add the native application identifier to the list of schemes for parity with `expo build`.
|
|
77
75
|
// The native app id has been added to builds for a long time to support Google Sign-In.
|
|
78
76
|
return (Platform.select({
|
|
79
|
-
ios: Constants.
|
|
80
|
-
Constants.manifest2?.extra?.expoClient?.ios?.bundleIdentifier,
|
|
77
|
+
ios: Constants.expoConfig?.ios?.bundleIdentifier,
|
|
81
78
|
// TODO: This may change to android.applicationId in the future.
|
|
82
|
-
android: Constants.
|
|
83
|
-
Constants.manifest2?.extra?.expoClient?.android?.package,
|
|
79
|
+
android: Constants.expoConfig?.android?.package,
|
|
84
80
|
}) ?? null);
|
|
85
81
|
}
|
|
82
|
+
// @needsAudit
|
|
83
|
+
/**
|
|
84
|
+
* Ensure the user has linked the expo-constants manifest in bare workflow.
|
|
85
|
+
*/
|
|
86
86
|
export function hasConstantsManifest() {
|
|
87
|
-
// Ensure the user has linked the expo-constants manifest in bare workflow.
|
|
88
87
|
return (!!Object.keys(Constants.manifest ?? {}).length ||
|
|
89
88
|
!!Object.keys(Constants.manifest2 ?? {}).length);
|
|
90
89
|
}
|
|
91
|
-
|
|
90
|
+
// @docsMissing
|
|
91
|
+
export function resolveScheme(options) {
|
|
92
92
|
if (Constants.executionEnvironment !== ExecutionEnvironment.StoreClient &&
|
|
93
93
|
!hasConstantsManifest()) {
|
|
94
|
-
throw new Error(`expo-linking needs access to the expo-constants manifest (app.json or app.config.js) to determine what URI scheme to use. Setup the manifest and rebuild: https://github.com/expo/expo/blob/
|
|
94
|
+
throw new Error(`expo-linking needs access to the expo-constants manifest (app.json or app.config.js) to determine what URI scheme to use. Setup the manifest and rebuild: https://github.com/expo/expo/blob/main/packages/expo-constants/README.md`);
|
|
95
95
|
}
|
|
96
96
|
const manifestSchemes = collectManifestSchemes();
|
|
97
97
|
const nativeAppId = getNativeAppIdScheme();
|
|
98
98
|
if (!manifestSchemes.length) {
|
|
99
|
-
if (__DEV__ && !
|
|
99
|
+
if (__DEV__ && !options.isSilent) {
|
|
100
100
|
// Assert a config warning if no scheme is setup yet. `isSilent` is used for warnings, but we'll ignore it for exceptions.
|
|
101
101
|
console.warn(`Linking requires a build-time setting \`scheme\` in the project's Expo config (app.config.js or app.json) for production apps, if it's left blank, your app may crash. The scheme does not apply to development in the Expo client but you should add it as soon as you start working with Linking to avoid creating a broken build. Learn more: ${LINKING_GUIDE_URL}`);
|
|
102
102
|
}
|
|
@@ -107,10 +107,10 @@ export function resolveScheme(props) {
|
|
|
107
107
|
}
|
|
108
108
|
// In the Expo client...
|
|
109
109
|
if (Constants.executionEnvironment === ExecutionEnvironment.StoreClient) {
|
|
110
|
-
if (
|
|
110
|
+
if (options.scheme) {
|
|
111
111
|
// This enables users to use the fb or google redirects on iOS in the Expo client.
|
|
112
|
-
if (EXPO_CLIENT_SCHEMES.includes(
|
|
113
|
-
return
|
|
112
|
+
if (EXPO_CLIENT_SCHEMES.includes(options.scheme)) {
|
|
113
|
+
return options.scheme;
|
|
114
114
|
}
|
|
115
115
|
// Silently ignore to make bare workflow development easier.
|
|
116
116
|
}
|
|
@@ -118,26 +118,26 @@ export function resolveScheme(props) {
|
|
|
118
118
|
return 'exp';
|
|
119
119
|
}
|
|
120
120
|
const schemes = [...manifestSchemes, nativeAppId].filter(Boolean);
|
|
121
|
-
if (
|
|
121
|
+
if (options.scheme) {
|
|
122
122
|
if (__DEV__) {
|
|
123
123
|
// Bare workflow development assertion about the provided scheme matching the Expo config.
|
|
124
|
-
if (!schemes.includes(
|
|
124
|
+
if (!schemes.includes(options.scheme) && !options.isSilent) {
|
|
125
125
|
// TODO: Will this cause issues for things like Facebook or Google that use `reversed-client-id://` or `fb<FBID>:/`?
|
|
126
126
|
// Traditionally these APIs don't use the Linking API directly.
|
|
127
|
-
console.warn(`The provided Linking scheme '${
|
|
127
|
+
console.warn(`The provided Linking scheme '${options.scheme}' does not appear in the list of possible URI schemes in your Expo config. Expected one of: ${schemes
|
|
128
128
|
.map((scheme) => `'${scheme}'`)
|
|
129
129
|
.join(', ')}`);
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
132
|
// Return the user provided value.
|
|
133
|
-
return
|
|
133
|
+
return options.scheme;
|
|
134
134
|
}
|
|
135
135
|
// If no scheme is provided, we'll guess what the scheme is based on the manifest.
|
|
136
136
|
// This is to attempt to keep managed apps working across expo build and EAS build.
|
|
137
137
|
// EAS build ejects the app before building it so we can assume that the user will
|
|
138
138
|
// be using one of defined schemes.
|
|
139
139
|
// If the native app id is the only scheme,
|
|
140
|
-
if (!!nativeAppId && !manifestSchemes.length && !
|
|
140
|
+
if (!!nativeAppId && !manifestSchemes.length && !options.isSilent) {
|
|
141
141
|
// Assert a config warning if no scheme is setup yet.
|
|
142
142
|
// This warning only applies to managed workflow EAS apps, as bare workflow
|
|
143
143
|
console.warn(`Linking requires a build-time setting \`scheme\` in the project's Expo config (app.config.js or app.json) for bare or production apps. Manually providing a \`scheme\` property can circumvent this warning. Using native app identifier as the scheme '${nativeAppId}'. Learn more: ${LINKING_GUIDE_URL}`);
|
|
@@ -154,7 +154,7 @@ export function resolveScheme(props) {
|
|
|
154
154
|
// Throw in production, use the __DEV__ flag so users can test this functionality with `expo start --no-dev`
|
|
155
155
|
throw new Error(errorMessage);
|
|
156
156
|
}
|
|
157
|
-
if (extraSchemes.length && !
|
|
157
|
+
if (extraSchemes.length && !options.isSilent) {
|
|
158
158
|
console.warn(`Linking found multiple possible URI schemes in your Expo config.\nUsing '${scheme}'. Ignoring: ${[
|
|
159
159
|
...extraSchemes,
|
|
160
160
|
nativeAppId,
|
package/build/Schemes.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Schemes.js","sourceRoot":"","sources":["../src/Schemes.ts"],"names":[],"mappings":"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","sourcesContent":["import Constants, { ExecutionEnvironment } from 'expo-constants';\nimport { Platform } from 'expo-modules-core';\n\nconst LINKING_GUIDE_URL = `https://docs.expo.io/guides/linking/`;\n\nexport function hasCustomScheme(): boolean {\n if (Constants.executionEnvironment === ExecutionEnvironment.Bare) {\n // Bare always uses a custom scheme.\n return true;\n } else if (Constants.executionEnvironment === ExecutionEnvironment.Standalone) {\n // Standalone uses a custom scheme when one is defined.\n const manifestSchemes = collectManifestSchemes();\n return !!manifestSchemes.length;\n }\n // Store client uses the default scheme.\n return false;\n}\n\ntype SchemeConfig = {\n scheme?: string | string[];\n};\n\nfunction getSchemes(config: SchemeConfig | null | undefined): string[] {\n if (config) {\n if (Array.isArray(config.scheme)) {\n const validate = (value: any): value is string => {\n return typeof value === 'string';\n };\n return config.scheme.filter<string>(validate);\n } else if (typeof config.scheme === 'string') {\n return [config.scheme];\n }\n }\n return [];\n}\n\n// Valid schemes for the Expo client.\nconst EXPO_CLIENT_SCHEMES = Platform.select({\n // Results from `npx uri-scheme list --info-path ios/Exponent/Supporting/Info.plist`\n ios: [\n 'exp',\n 'exps',\n 'fb1696089354000816',\n 'host.exp.exponent',\n 'com.googleusercontent.apps.603386649315-vp4revvrcgrcjme51ebuhbkbspl048l9',\n ],\n // Collected manually\n android: ['exp', 'exps'],\n});\n\n/**\n * Collect a list of platform schemes from the manifest.\n *\n * This method is based on the `Scheme` modules from `@expo/config-plugins`\n * which are used for collecting the schemes before prebuilding a native app.\n *\n * - iOS: scheme -> ios.scheme -> ios.bundleIdentifier\n * - Android: scheme -> android.scheme -> android.package\n */\nexport function collectManifestSchemes(): string[] {\n // ios.scheme, android.scheme, and scheme as an array are not yet added to the\n // Expo config spec, but there's no harm in adding them early.\n // They'll be added when we drop support for `expo build` or decide\n // to have them only work with `eas build`.\n const platformManifest =\n (Platform.select<any>({\n ios: Constants.manifest?.ios ?? Constants.manifest2?.extra?.expoClient?.ios,\n android: Constants.manifest?.android ?? Constants.manifest2?.extra?.expoClient?.android,\n web: {},\n }) as SchemeConfig) ?? {};\n\n const schemes = getSchemes(Constants.manifest ?? Constants.manifest2?.extra?.expoClient);\n\n // Add the detached scheme after the manifest scheme for legacy ExpoKit support.\n if (Constants.manifest?.detach?.scheme) {\n schemes.push(Constants.manifest.detach.scheme);\n }\n if (Constants.manifest2?.extra?.expoClient?.detach?.scheme) {\n schemes.push(Constants.manifest2.extra.expoClient.detach.scheme);\n }\n\n // Add the unimplemented platform schemes last.\n schemes.push(...getSchemes(platformManifest));\n\n return schemes;\n}\n\nfunction getNativeAppIdScheme(): string | null {\n // Add the native application identifier to the list of schemes for parity with `expo build`.\n // The native app id has been added to builds for a long time to support Google Sign-In.\n return (\n Platform.select({\n ios:\n Constants.manifest?.ios?.bundleIdentifier ??\n Constants.manifest2?.extra?.expoClient?.ios?.bundleIdentifier,\n // TODO: This may change to android.applicationId in the future.\n android:\n Constants.manifest?.android?.package ??\n Constants.manifest2?.extra?.expoClient?.android?.package,\n }) ?? null\n );\n}\n\nexport function hasConstantsManifest(): boolean {\n // Ensure the user has linked the expo-constants manifest in bare workflow.\n return (\n !!Object.keys(Constants.manifest ?? {}).length ||\n !!Object.keys(Constants.manifest2 ?? {}).length\n );\n}\n\nexport function resolveScheme(props: { scheme?: string; isSilent?: boolean }): string {\n if (\n Constants.executionEnvironment !== ExecutionEnvironment.StoreClient &&\n !hasConstantsManifest()\n ) {\n throw new Error(\n `expo-linking needs access to the expo-constants manifest (app.json or app.config.js) to determine what URI scheme to use. Setup the manifest and rebuild: https://github.com/expo/expo/blob/master/packages/expo-constants/README.md`\n );\n }\n\n const manifestSchemes = collectManifestSchemes();\n const nativeAppId = getNativeAppIdScheme();\n\n if (!manifestSchemes.length) {\n if (__DEV__ && !props.isSilent) {\n // Assert a config warning if no scheme is setup yet. `isSilent` is used for warnings, but we'll ignore it for exceptions.\n console.warn(\n `Linking requires a build-time setting \\`scheme\\` in the project's Expo config (app.config.js or app.json) for production apps, if it's left blank, your app may crash. The scheme does not apply to development in the Expo client but you should add it as soon as you start working with Linking to avoid creating a broken build. Learn more: ${LINKING_GUIDE_URL}`\n );\n } else if (!__DEV__ || Constants.executionEnvironment !== ExecutionEnvironment.StoreClient) {\n // Throw in production or when not in store client. Use the __DEV__ flag so users can test this functionality with `expo start --no-dev`,\n throw new Error(\n 'Cannot make a deep link into a standalone app with no custom scheme defined'\n );\n }\n }\n\n // In the Expo client...\n if (Constants.executionEnvironment === ExecutionEnvironment.StoreClient) {\n if (props.scheme) {\n // This enables users to use the fb or google redirects on iOS in the Expo client.\n if (EXPO_CLIENT_SCHEMES.includes(props.scheme)) {\n return props.scheme;\n }\n // Silently ignore to make bare workflow development easier.\n }\n // Fallback to the default client scheme.\n return 'exp';\n }\n\n const schemes = [...manifestSchemes, nativeAppId].filter(Boolean);\n\n if (props.scheme) {\n if (__DEV__) {\n // Bare workflow development assertion about the provided scheme matching the Expo config.\n if (!schemes.includes(props.scheme) && !props.isSilent) {\n // TODO: Will this cause issues for things like Facebook or Google that use `reversed-client-id://` or `fb<FBID>:/`?\n // Traditionally these APIs don't use the Linking API directly.\n console.warn(\n `The provided Linking scheme '${\n props.scheme\n }' does not appear in the list of possible URI schemes in your Expo config. Expected one of: ${schemes\n .map((scheme) => `'${scheme}'`)\n .join(', ')}`\n );\n }\n }\n // Return the user provided value.\n return props.scheme;\n }\n // If no scheme is provided, we'll guess what the scheme is based on the manifest.\n // This is to attempt to keep managed apps working across expo build and EAS build.\n // EAS build ejects the app before building it so we can assume that the user will\n // be using one of defined schemes.\n\n // If the native app id is the only scheme,\n if (!!nativeAppId && !manifestSchemes.length && !props.isSilent) {\n // Assert a config warning if no scheme is setup yet.\n // This warning only applies to managed workflow EAS apps, as bare workflow\n console.warn(\n `Linking requires a build-time setting \\`scheme\\` in the project's Expo config (app.config.js or app.json) for bare or production apps. Manually providing a \\`scheme\\` property can circumvent this warning. Using native app identifier as the scheme '${nativeAppId}'. Learn more: ${LINKING_GUIDE_URL}`\n );\n return nativeAppId;\n }\n // When the native app id is defined, it'll be added to the list of schemes, for most\n // users this will be unexpected behavior and cause all apps to warn when the Linking API\n // is used without a predefined scheme. For now, if the native app id is defined, require\n // at least one more scheme to be added before throwing a warning.\n // i.e. `scheme: ['foo', 'bar']` (unimplemented functionality).\n const [scheme, ...extraSchemes] = manifestSchemes;\n\n if (!scheme) {\n const errorMessage = `Linking requires a build-time setting \\`scheme\\` in the project's Expo config (app.config.js or app.json) for bare or production apps. Manually providing a \\`scheme\\` property can circumvent this error. Learn more: ${LINKING_GUIDE_URL}`;\n // Throw in production, use the __DEV__ flag so users can test this functionality with `expo start --no-dev`\n throw new Error(errorMessage);\n }\n if (extraSchemes.length && !props.isSilent) {\n console.warn(\n `Linking found multiple possible URI schemes in your Expo config.\\nUsing '${scheme}'. Ignoring: ${[\n ...extraSchemes,\n nativeAppId,\n ]\n .filter(Boolean)\n .join(', ')}.\\nPlease supply the preferred URI scheme to the Linking API.`\n );\n }\n return scheme;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"Schemes.js","sourceRoot":"","sources":["../src/Schemes.ts"],"names":[],"mappings":"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","sourcesContent":["import Constants, { ExecutionEnvironment } from 'expo-constants';\nimport { Platform } from 'expo-modules-core';\n\nconst LINKING_GUIDE_URL = `https://docs.expo.dev/guides/linking/`;\n\n// @docsMissing\nexport function hasCustomScheme(): boolean {\n if (Constants.executionEnvironment === ExecutionEnvironment.Bare) {\n // Bare always uses a custom scheme.\n return true;\n } else if (Constants.executionEnvironment === ExecutionEnvironment.Standalone) {\n // Standalone uses a custom scheme when one is defined.\n const manifestSchemes = collectManifestSchemes();\n return !!manifestSchemes.length;\n }\n // Store client uses the default scheme.\n return false;\n}\n\ntype SchemeConfig = {\n scheme?: string | string[];\n};\n\nfunction getSchemes(config: SchemeConfig | null | undefined): string[] {\n if (config) {\n if (Array.isArray(config.scheme)) {\n const validate = (value: any): value is string => {\n return typeof value === 'string';\n };\n return config.scheme.filter<string>(validate);\n } else if (typeof config.scheme === 'string') {\n return [config.scheme];\n }\n }\n return [];\n}\n\n// Valid schemes for the Expo client.\nconst EXPO_CLIENT_SCHEMES = Platform.select({\n // Results from `npx uri-scheme list --info-path ios/Exponent/Supporting/Info.plist`\n ios: [\n 'exp',\n 'exps',\n 'fb1696089354000816',\n 'host.exp.exponent',\n 'com.googleusercontent.apps.603386649315-vp4revvrcgrcjme51ebuhbkbspl048l9',\n ],\n // Collected manually\n android: ['exp', 'exps'],\n});\n\n/**\n * Collect a list of platform schemes from the manifest.\n *\n * This method is based on the `Scheme` modules from `@expo/config-plugins`\n * which are used for collecting the schemes before prebuilding a native app.\n *\n * - iOS: scheme -> ios.scheme -> ios.bundleIdentifier\n * - Android: scheme -> android.scheme -> android.package\n */\nexport function collectManifestSchemes(): string[] {\n // ios.scheme, android.scheme, and scheme as an array are not yet added to the\n // Expo config spec, but there's no harm in adding them early.\n // They'll be added when we drop support for `expo build` or decide\n // to have them only work with `eas build`.\n const platformManifest =\n (Platform.select<any>({\n ios: Constants.expoConfig?.ios,\n android: Constants.expoConfig?.android,\n web: {},\n }) as SchemeConfig) ?? {};\n\n const schemes = getSchemes(Constants.expoConfig);\n\n // Add the detached scheme after the manifest scheme for legacy ExpoKit support.\n if (Constants.expoConfig?.detach?.scheme) {\n schemes.push(Constants.expoConfig.detach.scheme);\n }\n\n // Add the unimplemented platform schemes last.\n schemes.push(...getSchemes(platformManifest));\n\n return schemes;\n}\n\nfunction getNativeAppIdScheme(): string | null {\n // Add the native application identifier to the list of schemes for parity with `expo build`.\n // The native app id has been added to builds for a long time to support Google Sign-In.\n return (\n Platform.select({\n ios: Constants.expoConfig?.ios?.bundleIdentifier,\n // TODO: This may change to android.applicationId in the future.\n android: Constants.expoConfig?.android?.package,\n }) ?? null\n );\n}\n\n// @needsAudit\n/**\n * Ensure the user has linked the expo-constants manifest in bare workflow.\n */\nexport function hasConstantsManifest(): boolean {\n return (\n !!Object.keys(Constants.manifest ?? {}).length ||\n !!Object.keys(Constants.manifest2 ?? {}).length\n );\n}\n\n// @docsMissing\nexport function resolveScheme(options: { scheme?: string; isSilent?: boolean }): string {\n if (\n Constants.executionEnvironment !== ExecutionEnvironment.StoreClient &&\n !hasConstantsManifest()\n ) {\n throw new Error(\n `expo-linking needs access to the expo-constants manifest (app.json or app.config.js) to determine what URI scheme to use. Setup the manifest and rebuild: https://github.com/expo/expo/blob/main/packages/expo-constants/README.md`\n );\n }\n\n const manifestSchemes = collectManifestSchemes();\n const nativeAppId = getNativeAppIdScheme();\n\n if (!manifestSchemes.length) {\n if (__DEV__ && !options.isSilent) {\n // Assert a config warning if no scheme is setup yet. `isSilent` is used for warnings, but we'll ignore it for exceptions.\n console.warn(\n `Linking requires a build-time setting \\`scheme\\` in the project's Expo config (app.config.js or app.json) for production apps, if it's left blank, your app may crash. The scheme does not apply to development in the Expo client but you should add it as soon as you start working with Linking to avoid creating a broken build. Learn more: ${LINKING_GUIDE_URL}`\n );\n } else if (!__DEV__ || Constants.executionEnvironment !== ExecutionEnvironment.StoreClient) {\n // Throw in production or when not in store client. Use the __DEV__ flag so users can test this functionality with `expo start --no-dev`,\n throw new Error(\n 'Cannot make a deep link into a standalone app with no custom scheme defined'\n );\n }\n }\n\n // In the Expo client...\n if (Constants.executionEnvironment === ExecutionEnvironment.StoreClient) {\n if (options.scheme) {\n // This enables users to use the fb or google redirects on iOS in the Expo client.\n if (EXPO_CLIENT_SCHEMES.includes(options.scheme)) {\n return options.scheme;\n }\n // Silently ignore to make bare workflow development easier.\n }\n // Fallback to the default client scheme.\n return 'exp';\n }\n\n const schemes = [...manifestSchemes, nativeAppId].filter(Boolean);\n\n if (options.scheme) {\n if (__DEV__) {\n // Bare workflow development assertion about the provided scheme matching the Expo config.\n if (!schemes.includes(options.scheme) && !options.isSilent) {\n // TODO: Will this cause issues for things like Facebook or Google that use `reversed-client-id://` or `fb<FBID>:/`?\n // Traditionally these APIs don't use the Linking API directly.\n console.warn(\n `The provided Linking scheme '${\n options.scheme\n }' does not appear in the list of possible URI schemes in your Expo config. Expected one of: ${schemes\n .map((scheme) => `'${scheme}'`)\n .join(', ')}`\n );\n }\n }\n // Return the user provided value.\n return options.scheme;\n }\n // If no scheme is provided, we'll guess what the scheme is based on the manifest.\n // This is to attempt to keep managed apps working across expo build and EAS build.\n // EAS build ejects the app before building it so we can assume that the user will\n // be using one of defined schemes.\n\n // If the native app id is the only scheme,\n if (!!nativeAppId && !manifestSchemes.length && !options.isSilent) {\n // Assert a config warning if no scheme is setup yet.\n // This warning only applies to managed workflow EAS apps, as bare workflow\n console.warn(\n `Linking requires a build-time setting \\`scheme\\` in the project's Expo config (app.config.js or app.json) for bare or production apps. Manually providing a \\`scheme\\` property can circumvent this warning. Using native app identifier as the scheme '${nativeAppId}'. Learn more: ${LINKING_GUIDE_URL}`\n );\n return nativeAppId;\n }\n // When the native app id is defined, it'll be added to the list of schemes, for most\n // users this will be unexpected behavior and cause all apps to warn when the Linking API\n // is used without a predefined scheme. For now, if the native app id is defined, require\n // at least one more scheme to be added before throwing a warning.\n // i.e. `scheme: ['foo', 'bar']` (unimplemented functionality).\n const [scheme, ...extraSchemes] = manifestSchemes;\n\n if (!scheme) {\n const errorMessage = `Linking requires a build-time setting \\`scheme\\` in the project's Expo config (app.config.js or app.json) for bare or production apps. Manually providing a \\`scheme\\` property can circumvent this error. Learn more: ${LINKING_GUIDE_URL}`;\n // Throw in production, use the __DEV__ flag so users can test this functionality with `expo start --no-dev`\n throw new Error(errorMessage);\n }\n if (extraSchemes.length && !options.isSilent) {\n console.warn(\n `Linking found multiple possible URI schemes in your Expo config.\\nUsing '${scheme}'. Ignoring: ${[\n ...extraSchemes,\n nativeAppId,\n ]\n .filter(Boolean)\n .join(', ')}.\\nPlease supply the preferred URI scheme to the Linking API.`\n );\n }\n return scheme;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-linking",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.1",
|
|
4
4
|
"description": "Create and open deep links universally",
|
|
5
5
|
"main": "build/Linking.js",
|
|
6
6
|
"types": "build/Linking.d.ts",
|
|
@@ -30,10 +30,10 @@
|
|
|
30
30
|
"license": "MIT",
|
|
31
31
|
"homepage": "https://docs.expo.dev/versions/latest/sdk/linking",
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"expo-constants": "~13.
|
|
33
|
+
"expo-constants": "~13.2.0",
|
|
34
34
|
"invariant": "^2.2.4",
|
|
35
35
|
"qs": "^6.9.1",
|
|
36
|
-
"url-parse": "^1.
|
|
36
|
+
"url-parse": "^1.5.9"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@types/qs": "^6.5.3",
|
|
@@ -42,5 +42,5 @@
|
|
|
42
42
|
"jest": {
|
|
43
43
|
"preset": "expo-module-scripts"
|
|
44
44
|
},
|
|
45
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "c6678c65b68e45062d49a2deea8e822f69388278"
|
|
46
46
|
}
|
package/src/ExpoLinking.web.ts
CHANGED
|
@@ -8,7 +8,12 @@ const EventTypes = ['url'];
|
|
|
8
8
|
const listeners: { listener: URLListener; nativeListener: NativeURLListener }[] = [];
|
|
9
9
|
|
|
10
10
|
export default {
|
|
11
|
-
addEventListener(type: 'url', listener: URLListener): void {
|
|
11
|
+
addEventListener(type: 'url', listener: URLListener): { remove(): void } {
|
|
12
|
+
// Do nothing in Node.js environments
|
|
13
|
+
if (!Platform.isDOMAvailable) {
|
|
14
|
+
return { remove() {} };
|
|
15
|
+
}
|
|
16
|
+
|
|
12
17
|
invariant(
|
|
13
18
|
EventTypes.indexOf(type) !== -1,
|
|
14
19
|
`Linking.addEventListener(): ${type} is not a valid event`
|
|
@@ -17,9 +22,18 @@ export default {
|
|
|
17
22
|
listener({ url: window.location.href, nativeEvent });
|
|
18
23
|
listeners.push({ listener, nativeListener });
|
|
19
24
|
window.addEventListener('message', nativeListener, false);
|
|
25
|
+
return {
|
|
26
|
+
remove: () => {
|
|
27
|
+
this.removeEventListener(type, listener);
|
|
28
|
+
},
|
|
29
|
+
};
|
|
20
30
|
},
|
|
21
31
|
|
|
22
32
|
removeEventListener(type: 'url', listener: URLListener): void {
|
|
33
|
+
// Do nothing in Node.js environments
|
|
34
|
+
if (!Platform.isDOMAvailable) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
23
37
|
invariant(
|
|
24
38
|
EventTypes.indexOf(type) !== -1,
|
|
25
39
|
`Linking.removeEventListener(): ${type} is not a valid event.`
|
package/src/Linking.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { Platform, UnavailabilityError } from 'expo-modules-core';
|
|
|
3
3
|
import invariant from 'invariant';
|
|
4
4
|
import qs from 'qs';
|
|
5
5
|
import { useEffect, useState } from 'react';
|
|
6
|
+
import { EmitterSubscription } from 'react-native';
|
|
6
7
|
import URL from 'url-parse';
|
|
7
8
|
|
|
8
9
|
import NativeLinking from './ExpoLinking';
|
|
@@ -39,7 +40,8 @@ function isExpoHosted(): boolean {
|
|
|
39
40
|
return !!(
|
|
40
41
|
hostUri &&
|
|
41
42
|
(/^(.*\.)?(expo\.io|exp\.host|exp\.direct|expo\.test)(:.*)?(\/.*)?$/.test(hostUri) ||
|
|
42
|
-
Constants.manifest?.developer
|
|
43
|
+
Constants.manifest?.developer ||
|
|
44
|
+
Constants.manifest2?.extra?.expoGo?.developer)
|
|
43
45
|
);
|
|
44
46
|
}
|
|
45
47
|
|
|
@@ -177,7 +179,7 @@ export function createURL(
|
|
|
177
179
|
if (typeof parsedParams === 'object') {
|
|
178
180
|
paramsFromHostUri = parsedParams;
|
|
179
181
|
}
|
|
180
|
-
} catch
|
|
182
|
+
} catch {}
|
|
181
183
|
queryParams = {
|
|
182
184
|
...queryParams,
|
|
183
185
|
...paramsFromHostUri,
|
|
@@ -255,10 +257,11 @@ export function parse(url: string): ParsedURL {
|
|
|
255
257
|
* @param type The only valid type is `'url'`.
|
|
256
258
|
* @param handler An [`URLListener`](#urllistener) function that takes an `event` object of the type
|
|
257
259
|
* [`EventType`](#eventype).
|
|
260
|
+
* @return An EmitterSubscription that has the remove method from EventSubscription
|
|
258
261
|
* @see [React Native Docs Linking page](https://reactnative.dev/docs/linking#addeventlistener).
|
|
259
262
|
*/
|
|
260
|
-
export function addEventListener(type:
|
|
261
|
-
NativeLinking.addEventListener(type, handler);
|
|
263
|
+
export function addEventListener(type: 'url', handler: URLListener): EmitterSubscription {
|
|
264
|
+
return NativeLinking.addEventListener(type, handler);
|
|
262
265
|
}
|
|
263
266
|
|
|
264
267
|
/**
|
|
@@ -267,8 +270,10 @@ export function addEventListener(type: string, handler: URLListener): void {
|
|
|
267
270
|
* @param handler An [`URLListener`](#urllistener) function that takes an `event` object of the type
|
|
268
271
|
* [`EventType`](#eventype).
|
|
269
272
|
* @see [React Native Docs Linking page](https://reactnative.dev/docs/linking#removeeventlistener).
|
|
273
|
+
*
|
|
274
|
+
* @deprecated Call `remove()` on the return value of `addEventListener()` instead.
|
|
270
275
|
*/
|
|
271
|
-
export function removeEventListener(type:
|
|
276
|
+
export function removeEventListener(type: 'url', handler: URLListener): void {
|
|
272
277
|
NativeLinking.removeEventListener(type, handler);
|
|
273
278
|
}
|
|
274
279
|
|
|
@@ -297,7 +302,7 @@ export async function parseInitialURLAsync(): Promise<ParsedURL> {
|
|
|
297
302
|
// @needsAudit
|
|
298
303
|
/**
|
|
299
304
|
* Launch an Android intent with extras.
|
|
300
|
-
* > Use [IntentLauncher](
|
|
305
|
+
* > Use [IntentLauncher](./intent-launcher) instead, `sendIntent` is only included in
|
|
301
306
|
* > `Linking` for API compatibility with React Native's Linking API.
|
|
302
307
|
* @platform android
|
|
303
308
|
*/
|
|
@@ -311,7 +316,6 @@ export async function sendIntent(action: string, extras?: SendIntentExtras[]): P
|
|
|
311
316
|
// @needsAudit
|
|
312
317
|
/**
|
|
313
318
|
* Open the operating system settings app and displays the app’s custom settings, if it has any.
|
|
314
|
-
* @platform ios
|
|
315
319
|
*/
|
|
316
320
|
export async function openSettings(): Promise<void> {
|
|
317
321
|
if (Platform.OS === 'web') {
|
|
@@ -376,11 +380,12 @@ export function useURL(): string | null {
|
|
|
376
380
|
|
|
377
381
|
useEffect(() => {
|
|
378
382
|
getInitialURL().then((url) => setLink(url));
|
|
379
|
-
addEventListener('url', onChange);
|
|
380
|
-
return () =>
|
|
383
|
+
const subscription = addEventListener('url', onChange);
|
|
384
|
+
return () => subscription.remove();
|
|
381
385
|
}, []);
|
|
382
386
|
|
|
383
387
|
return url;
|
|
384
388
|
}
|
|
385
389
|
|
|
386
390
|
export * from './Linking.types';
|
|
391
|
+
export * from './Schemes';
|
package/src/Schemes.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import Constants, { ExecutionEnvironment } from 'expo-constants';
|
|
2
2
|
import { Platform } from 'expo-modules-core';
|
|
3
3
|
|
|
4
|
-
const LINKING_GUIDE_URL = `https://docs.expo.
|
|
4
|
+
const LINKING_GUIDE_URL = `https://docs.expo.dev/guides/linking/`;
|
|
5
5
|
|
|
6
|
+
// @docsMissing
|
|
6
7
|
export function hasCustomScheme(): boolean {
|
|
7
8
|
if (Constants.executionEnvironment === ExecutionEnvironment.Bare) {
|
|
8
9
|
// Bare always uses a custom scheme.
|
|
@@ -64,19 +65,16 @@ export function collectManifestSchemes(): string[] {
|
|
|
64
65
|
// to have them only work with `eas build`.
|
|
65
66
|
const platformManifest =
|
|
66
67
|
(Platform.select<any>({
|
|
67
|
-
ios: Constants.
|
|
68
|
-
android: Constants.
|
|
68
|
+
ios: Constants.expoConfig?.ios,
|
|
69
|
+
android: Constants.expoConfig?.android,
|
|
69
70
|
web: {},
|
|
70
71
|
}) as SchemeConfig) ?? {};
|
|
71
72
|
|
|
72
|
-
const schemes = getSchemes(Constants.
|
|
73
|
+
const schemes = getSchemes(Constants.expoConfig);
|
|
73
74
|
|
|
74
75
|
// Add the detached scheme after the manifest scheme for legacy ExpoKit support.
|
|
75
|
-
if (Constants.
|
|
76
|
-
schemes.push(Constants.
|
|
77
|
-
}
|
|
78
|
-
if (Constants.manifest2?.extra?.expoClient?.detach?.scheme) {
|
|
79
|
-
schemes.push(Constants.manifest2.extra.expoClient.detach.scheme);
|
|
76
|
+
if (Constants.expoConfig?.detach?.scheme) {
|
|
77
|
+
schemes.push(Constants.expoConfig.detach.scheme);
|
|
80
78
|
}
|
|
81
79
|
|
|
82
80
|
// Add the unimplemented platform schemes last.
|
|
@@ -90,32 +88,32 @@ function getNativeAppIdScheme(): string | null {
|
|
|
90
88
|
// The native app id has been added to builds for a long time to support Google Sign-In.
|
|
91
89
|
return (
|
|
92
90
|
Platform.select({
|
|
93
|
-
ios:
|
|
94
|
-
Constants.manifest?.ios?.bundleIdentifier ??
|
|
95
|
-
Constants.manifest2?.extra?.expoClient?.ios?.bundleIdentifier,
|
|
91
|
+
ios: Constants.expoConfig?.ios?.bundleIdentifier,
|
|
96
92
|
// TODO: This may change to android.applicationId in the future.
|
|
97
|
-
android:
|
|
98
|
-
Constants.manifest?.android?.package ??
|
|
99
|
-
Constants.manifest2?.extra?.expoClient?.android?.package,
|
|
93
|
+
android: Constants.expoConfig?.android?.package,
|
|
100
94
|
}) ?? null
|
|
101
95
|
);
|
|
102
96
|
}
|
|
103
97
|
|
|
98
|
+
// @needsAudit
|
|
99
|
+
/**
|
|
100
|
+
* Ensure the user has linked the expo-constants manifest in bare workflow.
|
|
101
|
+
*/
|
|
104
102
|
export function hasConstantsManifest(): boolean {
|
|
105
|
-
// Ensure the user has linked the expo-constants manifest in bare workflow.
|
|
106
103
|
return (
|
|
107
104
|
!!Object.keys(Constants.manifest ?? {}).length ||
|
|
108
105
|
!!Object.keys(Constants.manifest2 ?? {}).length
|
|
109
106
|
);
|
|
110
107
|
}
|
|
111
108
|
|
|
112
|
-
|
|
109
|
+
// @docsMissing
|
|
110
|
+
export function resolveScheme(options: { scheme?: string; isSilent?: boolean }): string {
|
|
113
111
|
if (
|
|
114
112
|
Constants.executionEnvironment !== ExecutionEnvironment.StoreClient &&
|
|
115
113
|
!hasConstantsManifest()
|
|
116
114
|
) {
|
|
117
115
|
throw new Error(
|
|
118
|
-
`expo-linking needs access to the expo-constants manifest (app.json or app.config.js) to determine what URI scheme to use. Setup the manifest and rebuild: https://github.com/expo/expo/blob/
|
|
116
|
+
`expo-linking needs access to the expo-constants manifest (app.json or app.config.js) to determine what URI scheme to use. Setup the manifest and rebuild: https://github.com/expo/expo/blob/main/packages/expo-constants/README.md`
|
|
119
117
|
);
|
|
120
118
|
}
|
|
121
119
|
|
|
@@ -123,7 +121,7 @@ export function resolveScheme(props: { scheme?: string; isSilent?: boolean }): s
|
|
|
123
121
|
const nativeAppId = getNativeAppIdScheme();
|
|
124
122
|
|
|
125
123
|
if (!manifestSchemes.length) {
|
|
126
|
-
if (__DEV__ && !
|
|
124
|
+
if (__DEV__ && !options.isSilent) {
|
|
127
125
|
// Assert a config warning if no scheme is setup yet. `isSilent` is used for warnings, but we'll ignore it for exceptions.
|
|
128
126
|
console.warn(
|
|
129
127
|
`Linking requires a build-time setting \`scheme\` in the project's Expo config (app.config.js or app.json) for production apps, if it's left blank, your app may crash. The scheme does not apply to development in the Expo client but you should add it as soon as you start working with Linking to avoid creating a broken build. Learn more: ${LINKING_GUIDE_URL}`
|
|
@@ -138,10 +136,10 @@ export function resolveScheme(props: { scheme?: string; isSilent?: boolean }): s
|
|
|
138
136
|
|
|
139
137
|
// In the Expo client...
|
|
140
138
|
if (Constants.executionEnvironment === ExecutionEnvironment.StoreClient) {
|
|
141
|
-
if (
|
|
139
|
+
if (options.scheme) {
|
|
142
140
|
// This enables users to use the fb or google redirects on iOS in the Expo client.
|
|
143
|
-
if (EXPO_CLIENT_SCHEMES.includes(
|
|
144
|
-
return
|
|
141
|
+
if (EXPO_CLIENT_SCHEMES.includes(options.scheme)) {
|
|
142
|
+
return options.scheme;
|
|
145
143
|
}
|
|
146
144
|
// Silently ignore to make bare workflow development easier.
|
|
147
145
|
}
|
|
@@ -151,15 +149,15 @@ export function resolveScheme(props: { scheme?: string; isSilent?: boolean }): s
|
|
|
151
149
|
|
|
152
150
|
const schemes = [...manifestSchemes, nativeAppId].filter(Boolean);
|
|
153
151
|
|
|
154
|
-
if (
|
|
152
|
+
if (options.scheme) {
|
|
155
153
|
if (__DEV__) {
|
|
156
154
|
// Bare workflow development assertion about the provided scheme matching the Expo config.
|
|
157
|
-
if (!schemes.includes(
|
|
155
|
+
if (!schemes.includes(options.scheme) && !options.isSilent) {
|
|
158
156
|
// TODO: Will this cause issues for things like Facebook or Google that use `reversed-client-id://` or `fb<FBID>:/`?
|
|
159
157
|
// Traditionally these APIs don't use the Linking API directly.
|
|
160
158
|
console.warn(
|
|
161
159
|
`The provided Linking scheme '${
|
|
162
|
-
|
|
160
|
+
options.scheme
|
|
163
161
|
}' does not appear in the list of possible URI schemes in your Expo config. Expected one of: ${schemes
|
|
164
162
|
.map((scheme) => `'${scheme}'`)
|
|
165
163
|
.join(', ')}`
|
|
@@ -167,7 +165,7 @@ export function resolveScheme(props: { scheme?: string; isSilent?: boolean }): s
|
|
|
167
165
|
}
|
|
168
166
|
}
|
|
169
167
|
// Return the user provided value.
|
|
170
|
-
return
|
|
168
|
+
return options.scheme;
|
|
171
169
|
}
|
|
172
170
|
// If no scheme is provided, we'll guess what the scheme is based on the manifest.
|
|
173
171
|
// This is to attempt to keep managed apps working across expo build and EAS build.
|
|
@@ -175,7 +173,7 @@ export function resolveScheme(props: { scheme?: string; isSilent?: boolean }): s
|
|
|
175
173
|
// be using one of defined schemes.
|
|
176
174
|
|
|
177
175
|
// If the native app id is the only scheme,
|
|
178
|
-
if (!!nativeAppId && !manifestSchemes.length && !
|
|
176
|
+
if (!!nativeAppId && !manifestSchemes.length && !options.isSilent) {
|
|
179
177
|
// Assert a config warning if no scheme is setup yet.
|
|
180
178
|
// This warning only applies to managed workflow EAS apps, as bare workflow
|
|
181
179
|
console.warn(
|
|
@@ -195,7 +193,7 @@ export function resolveScheme(props: { scheme?: string; isSilent?: boolean }): s
|
|
|
195
193
|
// Throw in production, use the __DEV__ flag so users can test this functionality with `expo start --no-dev`
|
|
196
194
|
throw new Error(errorMessage);
|
|
197
195
|
}
|
|
198
|
-
if (extraSchemes.length && !
|
|
196
|
+
if (extraSchemes.length && !options.isSilent) {
|
|
199
197
|
console.warn(
|
|
200
198
|
`Linking found multiple possible URI schemes in your Expo config.\nUsing '${scheme}'. Ignoring: ${[
|
|
201
199
|
...extraSchemes,
|