From e8190f19c25d04dba4af7c46dd52993f9a12773b Mon Sep 17 00:00:00 2001 From: Luca Colonnello Date: Sun, 22 Mar 2020 10:19:12 +0000 Subject: [PATCH] Store only if AppState is available instead of every state change --- packages/expo-web-browser/build/WebBrowser.js | 14 +++++++------- packages/expo-web-browser/build/WebBrowser.js.map | 2 +- packages/expo-web-browser/src/WebBrowser.ts | 15 +++++++-------- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/packages/expo-web-browser/build/WebBrowser.js b/packages/expo-web-browser/build/WebBrowser.js index e9f1c2ba1fd2d..d868197cf1d68 100644 --- a/packages/expo-web-browser/build/WebBrowser.js +++ b/packages/expo-web-browser/build/WebBrowser.js @@ -106,14 +106,14 @@ let _redirectHandler = null; // Store the `resolve` function from a Promise to fire when the AppState // returns to active let _onWebBrowserCloseAndroid = null; -// Store previous app state to check whether the listener has ever been attached -let _previousAppState = AppState.currentState; +// If the initial AppState.currentState is null, we assume that the first call to +// AppState#change event is not actually triggered by a real change, +// is triggered instead by the bridge capturing the current state +// (https://facebook.github.io/react-native/docs/appstate#basic-usage) +let _isAppStateAvailable = AppState.currentState !== null; function _onAppStateChangeAndroid(state) { - // if _previousAppState is null, we assume that the first call to - // AppState#change event is not actually triggered by a real change - // (https://facebook.github.io/react-native/docs/appstate#basic-usage) - if (_previousAppState === null) { - _previousAppState = state; + if (!_isAppStateAvailable) { + _isAppStateAvailable = true; return; } if (state === 'active' && _onWebBrowserCloseAndroid) { diff --git a/packages/expo-web-browser/build/WebBrowser.js.map b/packages/expo-web-browser/build/WebBrowser.js.map index 02a61dc455588..525afa7464128 100644 --- a/packages/expo-web-browser/build/WebBrowser.js.map +++ b/packages/expo-web-browser/build/WebBrowser.js.map @@ -1 +1 @@ -{"version":3,"file":"WebBrowser.js","sourceRoot":"","sources":["../src/WebBrowser.ts"],"names":[],"mappings":"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","sourcesContent":["import { UnavailabilityError } from '@unimodules/core';\nimport { AppState, Linking, Platform, AppStateStatus } from 'react-native';\n\nimport ExponentWebBrowser from './ExpoWebBrowser';\nimport {\n RedirectEvent,\n WebBrowserOpenOptions,\n WebBrowserAuthSessionResult,\n WebBrowserCustomTabsResults,\n WebBrowserResult,\n WebBrowserRedirectResult,\n WebBrowserMayInitWithUrlResult,\n WebBrowserWarmUpResult,\n WebBrowserCoolDownResult,\n WebBrowserResultType,\n} from './WebBrowser.types';\n\nexport {\n WebBrowserOpenOptions,\n WebBrowserAuthSessionResult,\n WebBrowserCustomTabsResults,\n WebBrowserResult,\n WebBrowserRedirectResult,\n WebBrowserMayInitWithUrlResult,\n WebBrowserWarmUpResult,\n WebBrowserCoolDownResult,\n WebBrowserResultType,\n};\n\nconst emptyCustomTabsPackages: WebBrowserCustomTabsResults = {\n defaultBrowserPackage: undefined,\n preferredBrowserPackage: undefined,\n browserPackages: [],\n servicePackages: [],\n};\n\nexport async function getCustomTabsSupportingBrowsersAsync(): Promise {\n if (!ExponentWebBrowser.getCustomTabsSupportingBrowsersAsync) {\n throw new UnavailabilityError('WebBrowser', 'getCustomTabsSupportingBrowsersAsync');\n }\n if (Platform.OS !== 'android') {\n return emptyCustomTabsPackages;\n } else {\n return await ExponentWebBrowser.getCustomTabsSupportingBrowsersAsync();\n }\n}\n\nexport async function warmUpAsync(browserPackage?: string): Promise {\n if (!ExponentWebBrowser.warmUpAsync) {\n throw new UnavailabilityError('WebBrowser', 'warmUpAsync');\n }\n if (Platform.OS !== 'android') {\n return {};\n } else {\n return await ExponentWebBrowser.warmUpAsync(browserPackage);\n }\n}\n\nexport async function mayInitWithUrlAsync(\n url: string,\n browserPackage?: string\n): Promise {\n if (!ExponentWebBrowser.mayInitWithUrlAsync) {\n throw new UnavailabilityError('WebBrowser', 'mayInitWithUrlAsync');\n }\n if (Platform.OS !== 'android') {\n return {};\n } else {\n return await ExponentWebBrowser.mayInitWithUrlAsync(url, browserPackage);\n }\n}\n\nexport async function coolDownAsync(browserPackage?: string): Promise {\n if (!ExponentWebBrowser.coolDownAsync) {\n throw new UnavailabilityError('WebBrowser', 'coolDownAsync');\n }\n if (Platform.OS !== 'android') {\n return {};\n } else {\n return await ExponentWebBrowser.coolDownAsync(browserPackage);\n }\n}\n\nexport async function openBrowserAsync(\n url: string,\n browserParams: WebBrowserOpenOptions = {}\n): Promise {\n if (!ExponentWebBrowser.openBrowserAsync) {\n throw new UnavailabilityError('WebBrowser', 'openBrowserAsync');\n }\n return await ExponentWebBrowser.openBrowserAsync(url, browserParams);\n}\n\nexport function dismissBrowser(): void {\n if (!ExponentWebBrowser.dismissBrowser) {\n throw new UnavailabilityError('WebBrowser', 'dismissBrowser');\n }\n ExponentWebBrowser.dismissBrowser();\n}\n\nexport async function openAuthSessionAsync(\n url: string,\n redirectUrl: string,\n browserParams: WebBrowserOpenOptions = {}\n): Promise {\n if (_authSessionIsNativelySupported()) {\n if (!ExponentWebBrowser.openAuthSessionAsync) {\n throw new UnavailabilityError('WebBrowser', 'openAuthSessionAsync');\n }\n return ExponentWebBrowser.openAuthSessionAsync(url, redirectUrl);\n } else {\n return _openAuthSessionPolyfillAsync(url, redirectUrl, browserParams);\n }\n}\n\nexport function dismissAuthSession(): void {\n if (_authSessionIsNativelySupported()) {\n if (!ExponentWebBrowser.dismissAuthSession) {\n throw new UnavailabilityError('WebBrowser', 'dismissAuthSession');\n }\n ExponentWebBrowser.dismissAuthSession();\n } else {\n if (!ExponentWebBrowser.dismissBrowser) {\n throw new UnavailabilityError('WebBrowser', 'dismissAuthSession');\n }\n ExponentWebBrowser.dismissBrowser();\n }\n}\n\n/* iOS <= 10 and Android polyfill for SFAuthenticationSession flow */\n\nfunction _authSessionIsNativelySupported(): boolean {\n if (Platform.OS === 'android') {\n return false;\n }\n\n const versionNumber = parseInt(String(Platform.Version), 10);\n return versionNumber >= 11;\n}\n\nlet _redirectHandler: ((event: RedirectEvent) => void) | null = null;\n\n/*\n * openBrowserAsync on Android doesn't wait until closed, so we need to polyfill\n * it with AppState\n */\n\n// Store the `resolve` function from a Promise to fire when the AppState\n// returns to active\nlet _onWebBrowserCloseAndroid: null | (() => void) = null;\n\n// Store previous app state to check whether the listener has ever been attached\nlet _previousAppState: null | string = AppState.currentState;\n\nfunction _onAppStateChangeAndroid(state: AppStateStatus) {\n // if _previousAppState is null, we assume that the first call to\n // AppState#change event is not actually triggered by a real change\n // (https://facebook.github.io/react-native/docs/appstate#basic-usage)\n if (_previousAppState === null) {\n _previousAppState = state;\n return;\n }\n\n if (state === 'active' && _onWebBrowserCloseAndroid) {\n _onWebBrowserCloseAndroid();\n }\n}\n\nasync function _openBrowserAndWaitAndroidAsync(\n startUrl: string,\n browserParams: WebBrowserOpenOptions = {}\n): Promise {\n const appStateChangedToActive = new Promise(resolve => {\n _onWebBrowserCloseAndroid = resolve;\n AppState.addEventListener('change', _onAppStateChangeAndroid);\n });\n\n let result: WebBrowserResult = { type: 'cancel' };\n const { type } = await openBrowserAsync(startUrl, browserParams);\n\n if (type === 'opened') {\n await appStateChangedToActive;\n result = { type: 'dismiss' };\n }\n\n AppState.removeEventListener('change', _onAppStateChangeAndroid);\n _onWebBrowserCloseAndroid = null;\n return result;\n}\n\nasync function _openAuthSessionPolyfillAsync(\n startUrl: string,\n returnUrl: string,\n browserParams: WebBrowserOpenOptions = {}\n): Promise {\n if (_redirectHandler) {\n throw new Error(\n `The WebBrowser's auth session is in an invalid state with a redirect handler set when it should not be`\n );\n }\n\n if (_onWebBrowserCloseAndroid) {\n throw new Error(`WebBrowser is already open, only one can be open at a time`);\n }\n\n try {\n if (Platform.OS === 'android') {\n return await Promise.race([\n _openBrowserAndWaitAndroidAsync(startUrl, browserParams),\n _waitForRedirectAsync(returnUrl),\n ]);\n } else {\n return await Promise.race([\n openBrowserAsync(startUrl, browserParams),\n _waitForRedirectAsync(returnUrl),\n ]);\n }\n } finally {\n // We can't dismiss the browser on Android, only call this when it's available.\n // Users on Android need to manually press the 'x' button in Chrome Custom Tabs, sadly.\n if (ExponentWebBrowser.dismissBrowser) {\n ExponentWebBrowser.dismissBrowser();\n }\n\n _stopWaitingForRedirect();\n }\n}\n\nfunction _stopWaitingForRedirect() {\n if (!_redirectHandler) {\n throw new Error(\n `The WebBrowser auth session is in an invalid state with no redirect handler when one should be set`\n );\n }\n\n Linking.removeEventListener('url', _redirectHandler);\n _redirectHandler = null;\n}\n\nfunction _waitForRedirectAsync(returnUrl: string): Promise {\n return new Promise(resolve => {\n _redirectHandler = (event: RedirectEvent) => {\n if (event.url.startsWith(returnUrl)) {\n resolve({ url: event.url, type: 'success' });\n }\n };\n\n Linking.addEventListener('url', _redirectHandler);\n });\n}\n"]} \ No newline at end of file +{"version":3,"file":"WebBrowser.js","sourceRoot":"","sources":["../src/WebBrowser.ts"],"names":[],"mappings":"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","sourcesContent":["import { UnavailabilityError } from '@unimodules/core';\nimport { AppState, Linking, Platform, AppStateStatus } from 'react-native';\n\nimport ExponentWebBrowser from './ExpoWebBrowser';\nimport {\n RedirectEvent,\n WebBrowserOpenOptions,\n WebBrowserAuthSessionResult,\n WebBrowserCustomTabsResults,\n WebBrowserResult,\n WebBrowserRedirectResult,\n WebBrowserMayInitWithUrlResult,\n WebBrowserWarmUpResult,\n WebBrowserCoolDownResult,\n WebBrowserResultType,\n} from './WebBrowser.types';\n\nexport {\n WebBrowserOpenOptions,\n WebBrowserAuthSessionResult,\n WebBrowserCustomTabsResults,\n WebBrowserResult,\n WebBrowserRedirectResult,\n WebBrowserMayInitWithUrlResult,\n WebBrowserWarmUpResult,\n WebBrowserCoolDownResult,\n WebBrowserResultType,\n};\n\nconst emptyCustomTabsPackages: WebBrowserCustomTabsResults = {\n defaultBrowserPackage: undefined,\n preferredBrowserPackage: undefined,\n browserPackages: [],\n servicePackages: [],\n};\n\nexport async function getCustomTabsSupportingBrowsersAsync(): Promise {\n if (!ExponentWebBrowser.getCustomTabsSupportingBrowsersAsync) {\n throw new UnavailabilityError('WebBrowser', 'getCustomTabsSupportingBrowsersAsync');\n }\n if (Platform.OS !== 'android') {\n return emptyCustomTabsPackages;\n } else {\n return await ExponentWebBrowser.getCustomTabsSupportingBrowsersAsync();\n }\n}\n\nexport async function warmUpAsync(browserPackage?: string): Promise {\n if (!ExponentWebBrowser.warmUpAsync) {\n throw new UnavailabilityError('WebBrowser', 'warmUpAsync');\n }\n if (Platform.OS !== 'android') {\n return {};\n } else {\n return await ExponentWebBrowser.warmUpAsync(browserPackage);\n }\n}\n\nexport async function mayInitWithUrlAsync(\n url: string,\n browserPackage?: string\n): Promise {\n if (!ExponentWebBrowser.mayInitWithUrlAsync) {\n throw new UnavailabilityError('WebBrowser', 'mayInitWithUrlAsync');\n }\n if (Platform.OS !== 'android') {\n return {};\n } else {\n return await ExponentWebBrowser.mayInitWithUrlAsync(url, browserPackage);\n }\n}\n\nexport async function coolDownAsync(browserPackage?: string): Promise {\n if (!ExponentWebBrowser.coolDownAsync) {\n throw new UnavailabilityError('WebBrowser', 'coolDownAsync');\n }\n if (Platform.OS !== 'android') {\n return {};\n } else {\n return await ExponentWebBrowser.coolDownAsync(browserPackage);\n }\n}\n\nexport async function openBrowserAsync(\n url: string,\n browserParams: WebBrowserOpenOptions = {}\n): Promise {\n if (!ExponentWebBrowser.openBrowserAsync) {\n throw new UnavailabilityError('WebBrowser', 'openBrowserAsync');\n }\n return await ExponentWebBrowser.openBrowserAsync(url, browserParams);\n}\n\nexport function dismissBrowser(): void {\n if (!ExponentWebBrowser.dismissBrowser) {\n throw new UnavailabilityError('WebBrowser', 'dismissBrowser');\n }\n ExponentWebBrowser.dismissBrowser();\n}\n\nexport async function openAuthSessionAsync(\n url: string,\n redirectUrl: string,\n browserParams: WebBrowserOpenOptions = {}\n): Promise {\n if (_authSessionIsNativelySupported()) {\n if (!ExponentWebBrowser.openAuthSessionAsync) {\n throw new UnavailabilityError('WebBrowser', 'openAuthSessionAsync');\n }\n return ExponentWebBrowser.openAuthSessionAsync(url, redirectUrl);\n } else {\n return _openAuthSessionPolyfillAsync(url, redirectUrl, browserParams);\n }\n}\n\nexport function dismissAuthSession(): void {\n if (_authSessionIsNativelySupported()) {\n if (!ExponentWebBrowser.dismissAuthSession) {\n throw new UnavailabilityError('WebBrowser', 'dismissAuthSession');\n }\n ExponentWebBrowser.dismissAuthSession();\n } else {\n if (!ExponentWebBrowser.dismissBrowser) {\n throw new UnavailabilityError('WebBrowser', 'dismissAuthSession');\n }\n ExponentWebBrowser.dismissBrowser();\n }\n}\n\n/* iOS <= 10 and Android polyfill for SFAuthenticationSession flow */\n\nfunction _authSessionIsNativelySupported(): boolean {\n if (Platform.OS === 'android') {\n return false;\n }\n\n const versionNumber = parseInt(String(Platform.Version), 10);\n return versionNumber >= 11;\n}\n\nlet _redirectHandler: ((event: RedirectEvent) => void) | null = null;\n\n/*\n * openBrowserAsync on Android doesn't wait until closed, so we need to polyfill\n * it with AppState\n */\n\n// Store the `resolve` function from a Promise to fire when the AppState\n// returns to active\nlet _onWebBrowserCloseAndroid: null | (() => void) = null;\n\n// If the initial AppState.currentState is null, we assume that the first call to\n// AppState#change event is not actually triggered by a real change,\n// is triggered instead by the bridge capturing the current state\n// (https://facebook.github.io/react-native/docs/appstate#basic-usage)\nlet _isAppStateAvailable: boolean = AppState.currentState !== null;\nfunction _onAppStateChangeAndroid(state: AppStateStatus) {\n if (!_isAppStateAvailable) {\n _isAppStateAvailable = true;\n return;\n }\n\n if (state === 'active' && _onWebBrowserCloseAndroid) {\n _onWebBrowserCloseAndroid();\n }\n}\n\nasync function _openBrowserAndWaitAndroidAsync(\n startUrl: string,\n browserParams: WebBrowserOpenOptions = {}\n): Promise {\n const appStateChangedToActive = new Promise(resolve => {\n _onWebBrowserCloseAndroid = resolve;\n AppState.addEventListener('change', _onAppStateChangeAndroid);\n });\n\n let result: WebBrowserResult = { type: 'cancel' };\n const { type } = await openBrowserAsync(startUrl, browserParams);\n\n if (type === 'opened') {\n await appStateChangedToActive;\n result = { type: 'dismiss' };\n }\n\n AppState.removeEventListener('change', _onAppStateChangeAndroid);\n _onWebBrowserCloseAndroid = null;\n return result;\n}\n\nasync function _openAuthSessionPolyfillAsync(\n startUrl: string,\n returnUrl: string,\n browserParams: WebBrowserOpenOptions = {}\n): Promise {\n if (_redirectHandler) {\n throw new Error(\n `The WebBrowser's auth session is in an invalid state with a redirect handler set when it should not be`\n );\n }\n\n if (_onWebBrowserCloseAndroid) {\n throw new Error(`WebBrowser is already open, only one can be open at a time`);\n }\n\n try {\n if (Platform.OS === 'android') {\n return await Promise.race([\n _openBrowserAndWaitAndroidAsync(startUrl, browserParams),\n _waitForRedirectAsync(returnUrl),\n ]);\n } else {\n return await Promise.race([\n openBrowserAsync(startUrl, browserParams),\n _waitForRedirectAsync(returnUrl),\n ]);\n }\n } finally {\n // We can't dismiss the browser on Android, only call this when it's available.\n // Users on Android need to manually press the 'x' button in Chrome Custom Tabs, sadly.\n if (ExponentWebBrowser.dismissBrowser) {\n ExponentWebBrowser.dismissBrowser();\n }\n\n _stopWaitingForRedirect();\n }\n}\n\nfunction _stopWaitingForRedirect() {\n if (!_redirectHandler) {\n throw new Error(\n `The WebBrowser auth session is in an invalid state with no redirect handler when one should be set`\n );\n }\n\n Linking.removeEventListener('url', _redirectHandler);\n _redirectHandler = null;\n}\n\nfunction _waitForRedirectAsync(returnUrl: string): Promise {\n return new Promise(resolve => {\n _redirectHandler = (event: RedirectEvent) => {\n if (event.url.startsWith(returnUrl)) {\n resolve({ url: event.url, type: 'success' });\n }\n };\n\n Linking.addEventListener('url', _redirectHandler);\n });\n}\n"]} \ No newline at end of file diff --git a/packages/expo-web-browser/src/WebBrowser.ts b/packages/expo-web-browser/src/WebBrowser.ts index 071e2d2b1826b..bf08deffa5671 100644 --- a/packages/expo-web-browser/src/WebBrowser.ts +++ b/packages/expo-web-browser/src/WebBrowser.ts @@ -149,15 +149,14 @@ let _redirectHandler: ((event: RedirectEvent) => void) | null = null; // returns to active let _onWebBrowserCloseAndroid: null | (() => void) = null; -// Store previous app state to check whether the listener has ever been attached -let _previousAppState: null | string = AppState.currentState; - +// If the initial AppState.currentState is null, we assume that the first call to +// AppState#change event is not actually triggered by a real change, +// is triggered instead by the bridge capturing the current state +// (https://facebook.github.io/react-native/docs/appstate#basic-usage) +let _isAppStateAvailable: boolean = AppState.currentState !== null; function _onAppStateChangeAndroid(state: AppStateStatus) { - // if _previousAppState is null, we assume that the first call to - // AppState#change event is not actually triggered by a real change - // (https://facebook.github.io/react-native/docs/appstate#basic-usage) - if (_previousAppState === null) { - _previousAppState = state; + if (!_isAppStateAvailable) { + _isAppStateAvailable = true; return; }