UNPKG

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