1 |
|
2 | import { Linking, NativeModules, Platform } from 'react-native';
|
3 | import invariant from 'invariant';
|
4 |
|
5 | const { ExponentWebBrowser } = NativeModules;
|
6 |
|
7 | type RedirectEvent = {
|
8 | url: 'string',
|
9 | };
|
10 |
|
11 | async function openBrowserAsync(
|
12 | url: string
|
13 | ): Promise<{ type: 'cancel' | 'dismissed' }> {
|
14 | return ExponentWebBrowser.openBrowserAsync(url);
|
15 | }
|
16 |
|
17 | function dismissBrowser(): void {
|
18 | ExponentWebBrowser.dismissBrowser();
|
19 | }
|
20 |
|
21 | async function openAuthSessionAsync(
|
22 | url: string,
|
23 | redirectUrl: string
|
24 | ): Promise<any> {
|
25 | if (_authSessionIsNativelySupported()) {
|
26 | return ExponentWebBrowser.openAuthSessionAsync(url, redirectUrl);
|
27 | } else {
|
28 | return _openAuthSessionPolyfillAsync(url, redirectUrl);
|
29 | }
|
30 | }
|
31 |
|
32 | function dismissAuthSession(): void {
|
33 | if (_authSessionIsNativelySupported()) {
|
34 | ExponentWebBrowser.dismissAuthSession();
|
35 | } else {
|
36 | ExponentWebBrowser.dismissBrowser();
|
37 | }
|
38 | }
|
39 |
|
40 |
|
41 |
|
42 | function _authSessionIsNativelySupported() {
|
43 | if (Platform.OS === 'android') {
|
44 | return false;
|
45 | }
|
46 |
|
47 | const versionNumber = parseInt(Platform.Version, 10);
|
48 | return versionNumber >= 11;
|
49 | }
|
50 |
|
51 | let _redirectHandler;
|
52 | async function _openAuthSessionPolyfillAsync(startUrl, returnUrl) {
|
53 | invariant(
|
54 | !_redirectHandler,
|
55 | 'WebBrowser.openAuthSessionAsync is in a bad state. _redirectHandler is defined when it should not be.'
|
56 | );
|
57 |
|
58 | let result;
|
59 | let error;
|
60 | try {
|
61 | result = await Promise.race([
|
62 | openBrowserAsync(startUrl),
|
63 | _waitForRedirectAsync(returnUrl),
|
64 | ]);
|
65 | } catch (e) {
|
66 | error = e;
|
67 | }
|
68 |
|
69 | dismissBrowser();
|
70 | Linking.removeEventListener('url', _redirectHandler);
|
71 | _redirectHandler = null;
|
72 |
|
73 | if (error) {
|
74 | throw error;
|
75 | } else {
|
76 | return result;
|
77 | }
|
78 | }
|
79 |
|
80 | function _waitForRedirectAsync(returnUrl) {
|
81 | return new Promise(resolve => {
|
82 | _redirectHandler = (event: RedirectEvent) => {
|
83 | if (event.url.startsWith(returnUrl)) {
|
84 | resolve({ url: event.url, type: 'success' });
|
85 | }
|
86 | };
|
87 |
|
88 | Linking.addEventListener('url', _redirectHandler);
|
89 | });
|
90 | }
|
91 |
|
92 | export default {
|
93 | openBrowserAsync,
|
94 | openAuthSessionAsync,
|
95 | dismissBrowser,
|
96 | dismissAuthSession,
|
97 | };
|