From dc235daf40ba4a40e7f5c28ff896fc907766b963 Mon Sep 17 00:00:00 2001 From: Hein Rutjes Date: Thu, 9 Jan 2020 09:52:33 +0100 Subject: [PATCH 001/103] [android] Fixed NDK not installed when running `setup:native` (#6685) When running `$yarn setup:native`, it may happen that the sdkmanager cannot be executed (`sdkmanager: command not found`) and the Android NDK is not installed. This happens when your bash_profile already contains the Android SDK path (ANDROID_HOME),but not the `${sdk}/tool/bin` path. Checking whether `../tools/bin` is in the path is tricky and sketchy, instead this PR therefore makes the script more resilient by using the absolute path to reference the `sdkmanager`. Fixes #6617 --- scripts/setup-react-android.sh | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/scripts/setup-react-android.sh b/scripts/setup-react-android.sh index f51156c09c667..a9c3449b8e076 100755 --- a/scripts/setup-react-android.sh +++ b/scripts/setup-react-android.sh @@ -26,7 +26,8 @@ fi source $HOME/.bash_profile # Ensure the `sdkmanager` is installed for React Android -if [ ! -f "${ANDROID_HOME}/tools/bin/sdkmanager" ]; then +sdk_manager="${ANDROID_HOME}/tools/bin/sdkmanager" +if [ ! -f "${sdk_manager}" ]; then echo "\nDownloading android sdk tools...\n" sdk_tools_url=`curl https://developer.android.google.cn/studio/ | egrep -o "https://dl.google.com/android/repository/sdk-tools-darwin-.+?\.zip"` @@ -43,19 +44,19 @@ mkdir -p $HOME/.android touch $HOME/.android/repositories.cfg # Auto accept all the Google licenses -yes | sdkmanager --licenses +yes | ${sdk_manager} --licenses sdk_manager_options='--no_https --verbose --channel=0' # To launch the emulator by shell script -sdkmanager emulator ${sdk_manager_options} +${sdk_manager} emulator ${sdk_manager_options} # Install NDK... -sdkmanager ndk-bundle ${sdk_manager_options} -sdkmanager platform-tools ${sdk_manager_options} +${sdk_manager} ndk-bundle ${sdk_manager_options} +${sdk_manager} platform-tools ${sdk_manager_options} # Install Intel HAXM (for emulators) -sdkmanager "extras;intel;Hardware_Accelerated_Execution_Manager" ${sdk_manager_options} +${sdk_manager} "extras;intel;Hardware_Accelerated_Execution_Manager" ${sdk_manager_options} # Install the version of Android required for React Native -sdkmanager "platforms;android-26" "system-images;android-26;google_apis;x86_64" "build-tools;26.0.3" ${sdk_manager_options} -sdkmanager --update ${sdk_manager_options} +${sdk_manager} "platforms;android-26" "system-images;android-26;google_apis;x86_64" "build-tools;26.0.3" ${sdk_manager_options} +${sdk_manager} --update ${sdk_manager_options} echo '✅ React Native is now setup' \ No newline at end of file From 4ec89ef834b73b1aeebc06e979bd5ed8065db271 Mon Sep 17 00:00:00 2001 From: Hamdi Gatri Date: Thu, 9 Jan 2020 15:40:20 +0100 Subject: [PATCH 002/103] [docs] Fix library name from expo-three to expo-three-ar (#6659) * Fix library name from expo-three to expo-three-ar - Change library name to expo-three-ar. - Fix links. * Change library name to expo-three-ar for v36 doc * Change library name to expo-three-ar for v35 doc * Change library name to expo-three-ar of v34 doc - change library name. - fix links * Change library name to expo-three-ar for v33 doc - Change library name. - Fix links. * Fix examples link for v36 doc * Fix examples link for v35 doc * Fix examples link for v34 doc * Fix examples link for v33 doc --- docs/pages/versions/unversioned/sdk/AR.md | 4 ++-- docs/pages/versions/v33.0.0/sdk/AR.md | 4 ++-- docs/pages/versions/v34.0.0/sdk/AR.md | 4 ++-- docs/pages/versions/v35.0.0/sdk/AR.md | 4 ++-- docs/pages/versions/v36.0.0/sdk/AR.md | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/pages/versions/unversioned/sdk/AR.md b/docs/pages/versions/unversioned/sdk/AR.md index ee2e3d685f3ee..dc481e4e7a689 100644 --- a/docs/pages/versions/unversioned/sdk/AR.md +++ b/docs/pages/versions/unversioned/sdk/AR.md @@ -7,7 +7,7 @@ import SnackEmbed from '~/components/plugins/SnackEmbed'; > ARCore is not yet supported. This library is iOS only for now. -Enables the creation of 3D Augmented Reality scenes with ARKit for iOS. This library is generally used with [expo-three](https://github.com/expo/expo-three) to generate a camera, and manage a 3D scene. +Enables the creation of 3D Augmented Reality scenes with ARKit for iOS. This library is generally used with [expo-three-ar](https://github.com/expo/expo-three-ar) to generate a camera, and manage a 3D scene. #### Platform Compatibility @@ -25,7 +25,7 @@ This API is pre-installed in [managed](../../introduction/managed-vs-bare/#manag import { AR } from 'expo'; ``` -> [Examples can be found here](https://github.com/expo/expo-three/tree/master/example/screens/AR) +> [Examples can be found here](https://github.com/expo/expo-three-ar/tree/master/example) ### Getting Started diff --git a/docs/pages/versions/v33.0.0/sdk/AR.md b/docs/pages/versions/v33.0.0/sdk/AR.md index f7d893b5573a6..8f116075af481 100644 --- a/docs/pages/versions/v33.0.0/sdk/AR.md +++ b/docs/pages/versions/v33.0.0/sdk/AR.md @@ -6,7 +6,7 @@ import SnackEmbed from '~/components/plugins/SnackEmbed'; > ARCore is not yet supported. This lib is iOS only right now. > Augmented Reality with ARKit for iOS -> This library is generally used with [expo-three](https://github.com/expo/expo-three) to generate a camera, and manage a 3D scene. +> This library is generally used with [expo-three-ar](https://github.com/expo/expo-three-ar) to generate a camera, and manage a 3D scene. ## Installation @@ -18,7 +18,7 @@ This API is pre-installed in [managed](../../introduction/managed-vs-bare/#manag import { AR } from 'expo'; ``` -> [Examples can be found here](https://github.com/expo/expo-three/tree/master/example/screens/AR) +> [Examples can be found here](https://github.com/expo/expo-three-ar/tree/master/example) ### Getting Started diff --git a/docs/pages/versions/v34.0.0/sdk/AR.md b/docs/pages/versions/v34.0.0/sdk/AR.md index bc0e1858c193c..d744e0dc03269 100644 --- a/docs/pages/versions/v34.0.0/sdk/AR.md +++ b/docs/pages/versions/v34.0.0/sdk/AR.md @@ -7,7 +7,7 @@ import SnackEmbed from '~/components/plugins/SnackEmbed'; > ARCore is not yet supported. This lib is iOS only right now. > Augmented Reality with ARKit for iOS -> This library is generally used with [expo-three](https://github.com/expo/expo-three) to generate a camera, and manage a 3D scene. +> This library is generally used with [expo-three-ar](https://github.com/expo/expo-three-ar) to generate a camera, and manage a 3D scene. #### Platform Compatibility @@ -25,7 +25,7 @@ This API is pre-installed in [managed](../../introduction/managed-vs-bare/#manag import { AR } from 'expo'; ``` -> [Examples can be found here](https://github.com/expo/expo-three/tree/master/example/screens/AR) +> [Examples can be found here](https://github.com/expo/expo-three-ar/tree/master/example) ### Getting Started diff --git a/docs/pages/versions/v35.0.0/sdk/AR.md b/docs/pages/versions/v35.0.0/sdk/AR.md index 454178a5eb457..c4ccf27f6c50a 100644 --- a/docs/pages/versions/v35.0.0/sdk/AR.md +++ b/docs/pages/versions/v35.0.0/sdk/AR.md @@ -7,7 +7,7 @@ import SnackEmbed from '~/components/plugins/SnackEmbed'; > ARCore is not yet supported. This lib is iOS only right now. > Augmented Reality with ARKit for iOS -> This library is generally used with [expo-three](https://github.com/expo/expo-three) to generate a camera, and manage a 3D scene. +> This library is generally used with [expo-three-ar](https://github.com/expo/expo-three-ar) to generate a camera, and manage a 3D scene. #### Platform Compatibility @@ -25,7 +25,7 @@ This API is pre-installed in [managed](../../introduction/managed-vs-bare/#manag import { AR } from 'expo'; ``` -> [Examples can be found here](https://github.com/expo/expo-three/tree/master/example/screens/AR) +> [Examples can be found here](https://github.com/expo/expo-three-ar/tree/master/example) ### Getting Started diff --git a/docs/pages/versions/v36.0.0/sdk/AR.md b/docs/pages/versions/v36.0.0/sdk/AR.md index ee2e3d685f3ee..dc481e4e7a689 100644 --- a/docs/pages/versions/v36.0.0/sdk/AR.md +++ b/docs/pages/versions/v36.0.0/sdk/AR.md @@ -7,7 +7,7 @@ import SnackEmbed from '~/components/plugins/SnackEmbed'; > ARCore is not yet supported. This library is iOS only for now. -Enables the creation of 3D Augmented Reality scenes with ARKit for iOS. This library is generally used with [expo-three](https://github.com/expo/expo-three) to generate a camera, and manage a 3D scene. +Enables the creation of 3D Augmented Reality scenes with ARKit for iOS. This library is generally used with [expo-three-ar](https://github.com/expo/expo-three-ar) to generate a camera, and manage a 3D scene. #### Platform Compatibility @@ -25,7 +25,7 @@ This API is pre-installed in [managed](../../introduction/managed-vs-bare/#manag import { AR } from 'expo'; ``` -> [Examples can be found here](https://github.com/expo/expo-three/tree/master/example/screens/AR) +> [Examples can be found here](https://github.com/expo/expo-three-ar/tree/master/example) ### Getting Started From 1ef3e21ef9e3686b97d4532540c0541695a3f808 Mon Sep 17 00:00:00 2001 From: Hays Stanford Date: Fri, 10 Jan 2020 08:46:26 -0600 Subject: [PATCH 003/103] [docs] removed duplicate "is" in CONTRIBUTING.md (#6728) --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e5b75f84e799b..1e412c91e996e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -24,7 +24,7 @@ Manual smoke tests are included in `apps/native-component-list`, this is a good > 💡 How does `bare-expo` relate to `test-suite`? > -> `bare-expo` is a bare workflow app that links all of the Expo SDK dependencies in the `packages/` directory in order to be able to run projects in the `apps/` directory in the bare workflow rather than the Expo client. It currently only runs `test-suite`. `test-suite` is is a regular managed workflow Expo app with some custom code to turn it into a test runner. If you run `expo start` in the `test-suite` directory you can load the project in Expo client. `bare-expo` imports the `test-suite` app root component and uses it as its own root component. +> `bare-expo` is a bare workflow app that links all of the Expo SDK dependencies in the `packages/` directory in order to be able to run projects in the `apps/` directory in the bare workflow rather than the Expo client. It currently only runs `test-suite`. `test-suite` is a regular managed workflow Expo app with some custom code to turn it into a test runner. If you run `expo start` in the `test-suite` directory you can load the project in Expo client. `bare-expo` imports the `test-suite` app root component and uses it as its own root component. ## 📦 Download and Setup From 84b824bc3bec521fbc0ce9adef899d8a9d54c3b4 Mon Sep 17 00:00:00 2001 From: Charlie Cruzan <35579283+cruzach@users.noreply.github.com> Date: Fri, 10 Jan 2020 10:40:45 -0500 Subject: [PATCH 004/103] @cruzach/error recov (#6731) * [docs] errorRecovery supported in bare * v36 --- docs/pages/versions/unversioned/bare/unimodules-full-list.md | 2 +- docs/pages/versions/v36.0.0/bare/unimodules-full-list.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/pages/versions/unversioned/bare/unimodules-full-list.md b/docs/pages/versions/unversioned/bare/unimodules-full-list.md index 05c227010d0f7..8fd936325d4b6 100644 --- a/docs/pages/versions/unversioned/bare/unimodules-full-list.md +++ b/docs/pages/versions/unversioned/bare/unimodules-full-list.md @@ -34,6 +34,7 @@ The bare workflow is our way of describing the workflow where you use some of th - [Device](../../sdk/device/) - [DeviceMotion](../../sdk/devicemotion/) - [DocumentPicker](../../sdk/document-picker/) +- [ErrorRecovery](../../sdk/error-recovery/) - [Facebook](../../sdk/facebook/) - [FaceDetector](../../sdk/facedetector/) - [FileSystem](../../sdk/filesystem/) @@ -78,7 +79,6 @@ The bare workflow is our way of describing the workflow where you use some of th - [AppLoading](../../sdk/app-loading/) - [AuthSession](../../sdk/auth-session/) - [BackgroundFetch](../../sdk/background-fetch/) -- [ErrorRecovery](../../sdk/error-recovery/) - [Linking](../../sdk/linking/) - [Notifications](../../sdk/notifications/) - [ScreenOrientation](../../sdk/screen-orientation/) diff --git a/docs/pages/versions/v36.0.0/bare/unimodules-full-list.md b/docs/pages/versions/v36.0.0/bare/unimodules-full-list.md index 05c227010d0f7..8fd936325d4b6 100644 --- a/docs/pages/versions/v36.0.0/bare/unimodules-full-list.md +++ b/docs/pages/versions/v36.0.0/bare/unimodules-full-list.md @@ -34,6 +34,7 @@ The bare workflow is our way of describing the workflow where you use some of th - [Device](../../sdk/device/) - [DeviceMotion](../../sdk/devicemotion/) - [DocumentPicker](../../sdk/document-picker/) +- [ErrorRecovery](../../sdk/error-recovery/) - [Facebook](../../sdk/facebook/) - [FaceDetector](../../sdk/facedetector/) - [FileSystem](../../sdk/filesystem/) @@ -78,7 +79,6 @@ The bare workflow is our way of describing the workflow where you use some of th - [AppLoading](../../sdk/app-loading/) - [AuthSession](../../sdk/auth-session/) - [BackgroundFetch](../../sdk/background-fetch/) -- [ErrorRecovery](../../sdk/error-recovery/) - [Linking](../../sdk/linking/) - [Notifications](../../sdk/notifications/) - [ScreenOrientation](../../sdk/screen-orientation/) From 95606075988f85ed8674e86ca72c487a0718c1d1 Mon Sep 17 00:00:00 2001 From: Charlie Cruzan <35579283+cruzach@users.noreply.github.com> Date: Fri, 10 Jan 2020 11:01:58 -0500 Subject: [PATCH 005/103] [docs] clarify FB app id directions (#6732) * [docs] clarify FB app id directions * v36 * typo * typo --- docs/pages/versions/unversioned/sdk/facebook.md | 2 +- docs/pages/versions/v36.0.0/sdk/facebook.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/pages/versions/unversioned/sdk/facebook.md b/docs/pages/versions/unversioned/sdk/facebook.md index 154ad153275db..696b9d9dbf4bb 100644 --- a/docs/pages/versions/unversioned/sdk/facebook.md +++ b/docs/pages/versions/unversioned/sdk/facebook.md @@ -31,7 +31,7 @@ Follow [Facebook's developer documentation](https://developers.facebook.com/docs - **iOS standalone app** - - Add your app's Bundle ID as a _Bundle ID_ in app's settings page pictured above. + - Add your app's Bundle ID as a _Bundle ID_ in the app settings page pictured above. If you still have the `host.exp.Exponent` ID listed there, remove it. - In your [app.json](../../workflow/configuration/), add a field `facebookScheme` with your Facebook login redirect URL scheme found [here](https://developers.facebook.com/docs/facebook-login/ios) under _4. Configure Your info.plist_. It should look like `"fb123456"`. - Also in your [app.json](../../workflow/configuration/), add your [Facebook App ID and Facebook Display Name](https://developers.facebook.com/docs/facebook-login/ios) under the `facebookAppId` and `facebookDisplayName` keys. diff --git a/docs/pages/versions/v36.0.0/sdk/facebook.md b/docs/pages/versions/v36.0.0/sdk/facebook.md index 154ad153275db..696b9d9dbf4bb 100644 --- a/docs/pages/versions/v36.0.0/sdk/facebook.md +++ b/docs/pages/versions/v36.0.0/sdk/facebook.md @@ -31,7 +31,7 @@ Follow [Facebook's developer documentation](https://developers.facebook.com/docs - **iOS standalone app** - - Add your app's Bundle ID as a _Bundle ID_ in app's settings page pictured above. + - Add your app's Bundle ID as a _Bundle ID_ in the app settings page pictured above. If you still have the `host.exp.Exponent` ID listed there, remove it. - In your [app.json](../../workflow/configuration/), add a field `facebookScheme` with your Facebook login redirect URL scheme found [here](https://developers.facebook.com/docs/facebook-login/ios) under _4. Configure Your info.plist_. It should look like `"fb123456"`. - Also in your [app.json](../../workflow/configuration/), add your [Facebook App ID and Facebook Display Name](https://developers.facebook.com/docs/facebook-login/ios) under the `facebookAppId` and `facebookDisplayName` keys. From 1683322a5c937e86b3b60cabfd83cf00f3d5e089 Mon Sep 17 00:00:00 2001 From: Evan Bacon Date: Mon, 13 Jan 2020 13:38:36 -0800 Subject: [PATCH 006/103] [docs] Update Localization (#6675) * Update localization.md * fix typos * Apply suggestions from code review Co-Authored-By: Charlie Cruzan <35579283+cruzach@users.noreply.github.com> * backdate localization docs Co-authored-by: Charlie Cruzan <35579283+cruzach@users.noreply.github.com> --- .../versions/unversioned/sdk/localization.md | 80 ++++++++++++------ .../versions/v36.0.0/sdk/localization.md | 82 +++++++++++++------ 2 files changed, 109 insertions(+), 53 deletions(-) diff --git a/docs/pages/versions/unversioned/sdk/localization.md b/docs/pages/versions/unversioned/sdk/localization.md index a6cb22f4d45fa..ff1746eefc093 100644 --- a/docs/pages/versions/unversioned/sdk/localization.md +++ b/docs/pages/versions/unversioned/sdk/localization.md @@ -20,37 +20,63 @@ For [managed](../../introduction/managed-vs-bare/#managed-workflow) apps, you'll ## Usage -```javascript -import React from 'react'; +Let's make our app support English and Japanese. + +- Install the i18n package `i18n-js` + + ```sh + yarn add i18n-js + ``` + +- Configure the languages for your app. + + ```tsx + import * as Localization from 'expo-localization'; + import i18n from 'i18n-js'; + // Set the key-value pairs for the different languages you want to support. + i18n.translations = { + en: { welcome: 'Hello' }, + ja: { welcome: 'こんにちは' }, + }; + // Set the locale once at the beginning of your app. + i18n.locale = Localization.locale; + ``` + +### API Design Tips + +- You may want to refrain from localizing text for certain things, like names. In this case you can define them _once_ in your default language and reuse them with `i18n.fallbacks = true;`. +- When a user changes the device's language, your app will reset. This means you can set the language once, and don't need to update any of your React components to account for the language changes. + +### Full Demo + +```tsx +import * as React from 'react'; import { Text } from 'react-native'; import * as Localization from 'expo-localization'; import i18n from 'i18n-js'; -const en = { - foo: 'Foo', - bar: 'Bar {{someValue}}', -}; -const fr = { - foo: 'como telle fous', - bar: 'chatouiller {{someValue}}', -}; -i18n.fallbacks = true; -i18n.translations = { fr, en }; +// Set the key-value pairs for the different languages you want to support. +i18n.translations = { + en: { welcome: 'Hello', name: 'Charlie' }, + ja: { welcome: 'こんにちは' }, +}; +// Set the locale once at the beginning of your app. i18n.locale = Localization.locale; -export default class LitView extends React.Component { - render() { - return ( - - {i18n.t('foo')} {i18n.t('bar', { someValue: Date.now() })} - - ); - } +// When a value is missing from a language it'll fallback to another language with the key present. +i18n.fallbacks = true; + +function App() { + return ( + + {i18n.t('welcome')} {i18n.t('name')} + + ); } ``` ## API -```js +```ts import * as Localization from 'expo-localization'; ``` @@ -60,7 +86,9 @@ import * as Localization from 'expo-localization'; ## Constants -This API is mostly synchronous and driven by constants. On iOS the constants will always be correct, on Android you should check if the locale has updated using `AppState` and `Localization.getLocalizationAsync()`. Initally the constants will be correct on both platforms, but on Android a user can change the language and return, more on this later. +### Behavior + +This API is mostly synchronous and driven by constants. On iOS the constants will always be correct, on Android you should check if the locale has updated using `AppState` and `Localization.getLocalizationAsync()`. Initially the constants will be correct on both platforms, but on Android a user can change the language and return, more on this later. ### `Localization.locale` @@ -76,17 +104,17 @@ List of all the native languages provided by the user settings. These are return ### `Localization.isoCurrencyCodes` -A list of all the supported ISO codes. +A list of all the supported language ISO codes. ### `Localization.timezone` -The current time zone in display format. ex: `America/Los_Angeles` +The current timezone in display format. ex: `America/Los_Angeles` -On Web `timezone` is calculated with `Intl.DateTimeFormat().resolvedOptions().timeZone`. For a better guess you could use the `moment-timezone` library but is a very large library and will add significant bloat to your bundle. +On Web `timezone` is calculated with `Intl.DateTimeFormat().resolvedOptions().timeZone`. For a better estimation you could use the `moment-timezone` package but it will add significant bloat to your website's bundle size. ### `Localization.isRTL` -This will return `true` if the current language is Right-to-Left. +Returns if the system's language is written from Right-to-Left. This can be used to build features like [bidirectional icons](https://material.io/design/usability/bidirectionality.html). ## Methods diff --git a/docs/pages/versions/v36.0.0/sdk/localization.md b/docs/pages/versions/v36.0.0/sdk/localization.md index d77713a751082..ff1746eefc093 100644 --- a/docs/pages/versions/v36.0.0/sdk/localization.md +++ b/docs/pages/versions/v36.0.0/sdk/localization.md @@ -20,37 +20,63 @@ For [managed](../../introduction/managed-vs-bare/#managed-workflow) apps, you'll ## Usage -```javascript -import React from 'react'; +Let's make our app support English and Japanese. + +- Install the i18n package `i18n-js` + + ```sh + yarn add i18n-js + ``` + +- Configure the languages for your app. + + ```tsx + import * as Localization from 'expo-localization'; + import i18n from 'i18n-js'; + // Set the key-value pairs for the different languages you want to support. + i18n.translations = { + en: { welcome: 'Hello' }, + ja: { welcome: 'こんにちは' }, + }; + // Set the locale once at the beginning of your app. + i18n.locale = Localization.locale; + ``` + +### API Design Tips + +- You may want to refrain from localizing text for certain things, like names. In this case you can define them _once_ in your default language and reuse them with `i18n.fallbacks = true;`. +- When a user changes the device's language, your app will reset. This means you can set the language once, and don't need to update any of your React components to account for the language changes. + +### Full Demo + +```tsx +import * as React from 'react'; import { Text } from 'react-native'; import * as Localization from 'expo-localization'; import i18n from 'i18n-js'; -const en = { - foo: 'Foo', - bar: 'Bar {{someValue}}', -}; -const fr = { - foo: 'como telle fous', - bar: 'chatouiller {{someValue}}', -}; -i18n.fallbacks = true; -i18n.translations = { fr, en }; +// Set the key-value pairs for the different languages you want to support. +i18n.translations = { + en: { welcome: 'Hello', name: 'Charlie' }, + ja: { welcome: 'こんにちは' }, +}; +// Set the locale once at the beginning of your app. i18n.locale = Localization.locale; -export default class LitView extends React.Component { - render() { - return ( - - {i18n.t('foo')} {i18n.t('bar', { someValue: Date.now() })} - - ); - } +// When a value is missing from a language it'll fallback to another language with the key present. +i18n.fallbacks = true; + +function App() { + return ( + + {i18n.t('welcome')} {i18n.t('name')} + + ); } ``` ## API -```js +```ts import * as Localization from 'expo-localization'; ``` @@ -60,7 +86,9 @@ import * as Localization from 'expo-localization'; ## Constants -This API is mostly synchronous and driven by constants. On iOS the constants will always be correct, on Android you should check if the locale has updated using `AppState` and `Localization.getLocalizationAsync()`. Initally the constants will be correct on both platforms, but on Android a user can change the language and return, more on this later. +### Behavior + +This API is mostly synchronous and driven by constants. On iOS the constants will always be correct, on Android you should check if the locale has updated using `AppState` and `Localization.getLocalizationAsync()`. Initially the constants will be correct on both platforms, but on Android a user can change the language and return, more on this later. ### `Localization.locale` @@ -76,17 +104,17 @@ List of all the native languages provided by the user settings. These are return ### `Localization.isoCurrencyCodes` -A list of all the supported ISO codes. +A list of all the supported language ISO codes. ### `Localization.timezone` -The current time zone in display format. ex: `America/Los_Angeles` +The current timezone in display format. ex: `America/Los_Angeles` -On Web `timezone` is calculated with `Intl.DateTimeFormat().resolvedOptions().timeZone`. For a better guess you could use the `moment-timezone` library but is a very large library and will add significant bloat to your bundle. +On Web `timezone` is calculated with `Intl.DateTimeFormat().resolvedOptions().timeZone`. For a better estimation you could use the `moment-timezone` package but it will add significant bloat to your website's bundle size. ### `Localization.isRTL` -This will return `true` if the current language is Right-to-Left. +Returns if the system's language is written from Right-to-Left. This can be used to build features like [bidirectional icons](https://material.io/design/usability/bidirectionality.html). ## Methods @@ -111,4 +139,4 @@ type NativeEvent = { // When the app returns from the background on Android... const { locale } = await Localization.getLocalizationAsync(); -``` \ No newline at end of file +``` From 86ab3a9282a9813cd9099eae73b8f18d89b420c5 Mon Sep 17 00:00:00 2001 From: Evan Bacon Date: Mon, 13 Jan 2020 16:54:37 -0800 Subject: [PATCH 007/103] Create using-preact.md (#6718) --- .../unversioned/guides/using-preact.md | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 docs/pages/versions/unversioned/guides/using-preact.md diff --git a/docs/pages/versions/unversioned/guides/using-preact.md b/docs/pages/versions/unversioned/guides/using-preact.md new file mode 100644 index 0000000000000..3789feda827b0 --- /dev/null +++ b/docs/pages/versions/unversioned/guides/using-preact.md @@ -0,0 +1,31 @@ +--- +title: Using Preact with Expo for Web +--- + +> Warning: Preact is not a first-class feature of React Native for web, if you run into any problems please open an issue at [expo-cli/issues](https://github.com/expo/expo-cli/issues). + +[Preact](https://preactjs.com/) is a 3kb alternative to React. Using Preact in a blank `react-native-web` project can lower your GZipped bundle by nearly 24kb. + +- Install Preact (requires Preact 10+): `yarn add preact-responder-event-plugin preact` +- Run `expo customize:web` and select `webpack.config.js` +- Modify the webpack config to use Preact instead of React: + + ```js + const createExpoWebpackConfigAsync = require('@expo/webpack-config'); + + module.exports = async function(env, argv) { + const config = await createExpoWebpackConfigAsync({ ...env, report: true }, argv); + + config.resolve.alias = { + ...config.resolve.alias, + // Use Preact aliases + react$: 'preact/compat', + 'react-dom$': 'preact/compat', + // Fix the responder system which react-native-web depends on + 'react-dom/unstable-native-dependencies$': 'preact-responder-event-plugin', + }; + return config; + }; + ``` + +- That's it! Running `expo build:web` will now produce a significantly smaller bundle. From a651402b5bc95c12414cbf231412097f29b99b5a Mon Sep 17 00:00:00 2001 From: Brent Vatne Date: Mon, 13 Jan 2020 17:26:37 -0800 Subject: [PATCH 008/103] [image-picker][sharing] Small fixes while working on tutorial (#6757) --- .../build/ExponentImagePicker.js.map | 2 +- .../build/ExponentImagePicker.web.d.ts | 6 ++++ .../build/ExponentImagePicker.web.js | 29 ++++++++++++++++ .../build/ExponentImagePicker.web.js.map | 2 +- .../build/ImagePicker.js.map | 2 +- .../build/ImagePicker.types.js.map | 2 +- packages/expo-image-picker/package.json | 5 ++- .../{ImagePicker => }/ExponentImagePicker.ts | 0 .../ExponentImagePicker.web.ts | 34 +++++++++++++++++++ .../src/{ImagePicker => }/ImagePicker.ts | 0 .../{ImagePicker => }/ImagePicker.types.ts | 0 .../__tests__/ExponentImagePicker-test.web.ts | 19 +++++++++++ .../expo-sharing/build/ExpoSharing.web.js | 7 ++-- .../expo-sharing/build/ExpoSharing.web.js.map | 2 +- packages/expo-sharing/package.json | 5 ++- packages/expo-sharing/src/ExpoSharing.web.ts | 8 +++-- .../src/__tests__/Sharing-test.native.ts | 10 ++++++ .../src/__tests__/Sharing-test.web.ts | 24 +++++++++++++ 18 files changed, 146 insertions(+), 11 deletions(-) rename packages/expo-image-picker/src/{ImagePicker => }/ExponentImagePicker.ts (100%) rename packages/expo-image-picker/src/{ImagePicker => }/ExponentImagePicker.web.ts (72%) rename packages/expo-image-picker/src/{ImagePicker => }/ImagePicker.ts (100%) rename packages/expo-image-picker/src/{ImagePicker => }/ImagePicker.types.ts (100%) create mode 100644 packages/expo-image-picker/src/__tests__/ExponentImagePicker-test.web.ts create mode 100644 packages/expo-sharing/src/__tests__/Sharing-test.native.ts create mode 100644 packages/expo-sharing/src/__tests__/Sharing-test.web.ts diff --git a/packages/expo-image-picker/build/ExponentImagePicker.js.map b/packages/expo-image-picker/build/ExponentImagePicker.js.map index 816af0e765ec7..d29a52a19498e 100644 --- a/packages/expo-image-picker/build/ExponentImagePicker.js.map +++ b/packages/expo-image-picker/build/ExponentImagePicker.js.map @@ -1 +1 @@ -{"version":3,"file":"ExponentImagePicker.js","sourceRoot":"","sources":["../src/ImagePicker/ExponentImagePicker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,eAAe,kBAAkB,CAAC,mBAAmB,CAAC","sourcesContent":["import { NativeModulesProxy } from '@unimodules/core';\nexport default NativeModulesProxy.ExponentImagePicker;\n"]} \ No newline at end of file +{"version":3,"file":"ExponentImagePicker.js","sourceRoot":"","sources":["../src/ExponentImagePicker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,eAAe,kBAAkB,CAAC,mBAAmB,CAAC","sourcesContent":["import { NativeModulesProxy } from '@unimodules/core';\nexport default NativeModulesProxy.ExponentImagePicker;\n"]} \ No newline at end of file diff --git a/packages/expo-image-picker/build/ExponentImagePicker.web.d.ts b/packages/expo-image-picker/build/ExponentImagePicker.web.d.ts index 497beba67536e..ba984ab60868b 100644 --- a/packages/expo-image-picker/build/ExponentImagePicker.web.d.ts +++ b/packages/expo-image-picker/build/ExponentImagePicker.web.d.ts @@ -1,7 +1,13 @@ +import * as Permissions from 'expo-permissions'; +import { PermissionResponse } from 'unimodules-permissions-interface'; import { ImagePickerResult, ImagePickerOptions } from './ImagePicker.types'; declare const _default: { readonly name: string; launchImageLibraryAsync({ mediaTypes, allowsMultipleSelection, }: ImagePickerOptions): Promise; launchCameraAsync({ mediaTypes, allowsMultipleSelection, }: ImagePickerOptions): Promise; + getCameraPermissionAsync(): Promise; + requestCameraPermissionsAsync(): Promise; + getCameraRollPermissionsAsync(): Promise; + requestCameraRollPermissionsAsync(): Promise; }; export default _default; diff --git a/packages/expo-image-picker/build/ExponentImagePicker.web.js b/packages/expo-image-picker/build/ExponentImagePicker.web.js index f0a455466efb3..932e50957cc46 100644 --- a/packages/expo-image-picker/build/ExponentImagePicker.web.js +++ b/packages/expo-image-picker/build/ExponentImagePicker.web.js @@ -1,4 +1,6 @@ import uuidv4 from 'uuid/v4'; +import * as Permissions from 'expo-permissions'; +import { PermissionStatus } from 'unimodules-permissions-interface'; import { MediaTypeOptions, } from './ImagePicker.types'; const MediaTypeInput = { [MediaTypeOptions.All]: 'video/mp4,video/quicktime,video/x-m4v,video/*,image/*', @@ -22,7 +24,34 @@ export default { capture: true, }); }, + /* + * Delegate to expo-permissions to request camera permissions + */ + async getCameraPermissionAsync() { + return Permissions.getAsync(Permissions.CAMERA); + }, + async requestCameraPermissionsAsync() { + return Permissions.askAsync(Permissions.CAMERA); + }, + /* + * Camera roll permissions don't need to be requested on web, so we always + * respond with granted. + */ + async getCameraRollPermissionsAsync() { + return permissionGrantedResponse(); + }, + async requestCameraRollPermissionsAsync() { + return permissionGrantedResponse(); + }, }; +function permissionGrantedResponse() { + return { + status: PermissionStatus.GRANTED, + expires: 'never', + granted: true, + canAskAgain: true, + }; +} function openFileBrowserAsync({ mediaTypes, capture = false, allowsMultipleSelection = false, }) { const mediaTypeFormat = MediaTypeInput[mediaTypes]; const input = document.createElement('input'); diff --git a/packages/expo-image-picker/build/ExponentImagePicker.web.js.map b/packages/expo-image-picker/build/ExponentImagePicker.web.js.map index dd45f102b633d..4d4a1d8e7f671 100644 --- a/packages/expo-image-picker/build/ExponentImagePicker.web.js.map +++ b/packages/expo-image-picker/build/ExponentImagePicker.web.js.map @@ -1 +1 @@ -{"version":3,"file":"ExponentImagePicker.web.js","sourceRoot":"","sources":["../src/ImagePicker/ExponentImagePicker.web.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,SAAS,CAAC;AAE7B,OAAO,EAEL,gBAAgB,GAGjB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,cAAc,GAAG;IACrB,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,uDAAuD;IAC/E,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,SAAS;IACpC,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,+CAA+C;CAC3E,CAAC;AAEF,eAAe;IACb,IAAI,IAAI;QACN,OAAO,qBAAqB,CAAC;IAC/B,CAAC;IACD,KAAK,CAAC,uBAAuB,CAAC,EAC5B,UAAU,GAAG,gBAAgB,CAAC,GAAG,EACjC,uBAAuB,GAAG,KAAK,GACZ;QACnB,OAAO,MAAM,oBAAoB,CAAC;YAChC,UAAU;YACV,uBAAuB;SACxB,CAAC,CAAC;IACL,CAAC;IACD,KAAK,CAAC,iBAAiB,CAAC,EACtB,UAAU,GAAG,gBAAgB,CAAC,GAAG,EACjC,uBAAuB,GAAG,KAAK,GACZ;QACnB,OAAO,MAAM,oBAAoB,CAAC;YAChC,UAAU;YACV,uBAAuB;YACvB,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;IACL,CAAC;CACF,CAAC;AAEF,SAAS,oBAAoB,CAAC,EAC5B,UAAU,EACV,OAAO,GAAG,KAAK,EACf,uBAAuB,GAAG,KAAK,GACR;IACvB,MAAM,eAAe,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;IAEnD,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAC9C,KAAK,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC;IAC7B,KAAK,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,KAAK,CAAC,YAAY,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;IAC9C,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACnC,IAAI,uBAAuB,EAAE;QAC3B,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;KAC5C;IACD,IAAI,OAAO,EAAE;QACX,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;KACzC;IACD,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IAEjC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,KAAK,CAAC,gBAAgB,CAAC,QAAQ,EAAE,GAAG,EAAE;YACpC,IAAI,KAAK,CAAC,KAAK,EAAE;gBACf,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;gBAClC,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;gBAChC,MAAM,CAAC,OAAO,GAAG,GAAG,EAAE;oBACpB,MAAM,CAAC,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAC,CAAC;gBACvF,CAAC,CAAC;gBACF,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;oBAC7B,MAAM,GAAG,GAAI,MAAc,CAAC,MAAM,CAAC;oBACnC,OAAO,CAAC;wBACN,SAAS,EAAE,KAAK;wBAChB,GAAG;wBACH,KAAK,EAAE,CAAC;wBACR,MAAM,EAAE,CAAC;qBACV,CAAC,CAAC;gBACL,CAAC,CAAC;gBACF,6CAA6C;gBAC7C,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;aAClC;iBAAM;gBACL,OAAO,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;aAC9B;YAED,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC;QACtC,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import uuidv4 from 'uuid/v4';\n\nimport {\n ImagePickerResult,\n MediaTypeOptions,\n OpenFileBrowserOptions,\n ImagePickerOptions,\n} from './ImagePicker.types';\n\nconst MediaTypeInput = {\n [MediaTypeOptions.All]: 'video/mp4,video/quicktime,video/x-m4v,video/*,image/*',\n [MediaTypeOptions.Images]: 'image/*',\n [MediaTypeOptions.Videos]: 'video/mp4,video/quicktime,video/x-m4v,video/*',\n};\n\nexport default {\n get name(): string {\n return 'ExponentImagePicker';\n },\n async launchImageLibraryAsync({\n mediaTypes = MediaTypeOptions.All,\n allowsMultipleSelection = false,\n }: ImagePickerOptions): Promise {\n return await openFileBrowserAsync({\n mediaTypes,\n allowsMultipleSelection,\n });\n },\n async launchCameraAsync({\n mediaTypes = MediaTypeOptions.All,\n allowsMultipleSelection = false,\n }: ImagePickerOptions): Promise {\n return await openFileBrowserAsync({\n mediaTypes,\n allowsMultipleSelection,\n capture: true,\n });\n },\n};\n\nfunction openFileBrowserAsync({\n mediaTypes,\n capture = false,\n allowsMultipleSelection = false,\n}: OpenFileBrowserOptions): Promise {\n const mediaTypeFormat = MediaTypeInput[mediaTypes];\n\n const input = document.createElement('input');\n input.style.display = 'none';\n input.setAttribute('type', 'file');\n input.setAttribute('accept', mediaTypeFormat);\n input.setAttribute('id', uuidv4());\n if (allowsMultipleSelection) {\n input.setAttribute('multiple', 'multiple');\n }\n if (capture) {\n input.setAttribute('capture', 'camera');\n }\n document.body.appendChild(input);\n\n return new Promise((resolve, reject) => {\n input.addEventListener('change', () => {\n if (input.files) {\n const targetFile = input.files[0];\n const reader = new FileReader();\n reader.onerror = () => {\n reject(new Error(`Failed to read the selected media because the operation failed.`));\n };\n reader.onload = ({ target }) => {\n const uri = (target as any).result;\n resolve({\n cancelled: false,\n uri,\n width: 0,\n height: 0,\n });\n };\n // Read in the image file as a binary string.\n reader.readAsDataURL(targetFile);\n } else {\n resolve({ cancelled: true });\n }\n\n document.body.removeChild(input);\n });\n\n const event = new MouseEvent('click');\n input.dispatchEvent(event);\n });\n}\n"]} \ No newline at end of file +{"version":3,"file":"ExponentImagePicker.web.js","sourceRoot":"","sources":["../src/ExponentImagePicker.web.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,SAAS,CAAC;AAC7B,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAsB,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAExF,OAAO,EAEL,gBAAgB,GAGjB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,cAAc,GAAG;IACrB,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,uDAAuD;IAC/E,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,SAAS;IACpC,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,+CAA+C;CAC3E,CAAC;AAEF,eAAe;IACb,IAAI,IAAI;QACN,OAAO,qBAAqB,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,uBAAuB,CAAC,EAC5B,UAAU,GAAG,gBAAgB,CAAC,GAAG,EACjC,uBAAuB,GAAG,KAAK,GACZ;QACnB,OAAO,MAAM,oBAAoB,CAAC;YAChC,UAAU;YACV,uBAAuB;SACxB,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,EACtB,UAAU,GAAG,gBAAgB,CAAC,GAAG,EACjC,uBAAuB,GAAG,KAAK,GACZ;QACnB,OAAO,MAAM,oBAAoB,CAAC;YAChC,UAAU;YACV,uBAAuB;YACvB,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,wBAAwB;QAC5B,OAAO,WAAW,CAAC,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAClD,CAAC;IACD,KAAK,CAAC,6BAA6B;QACjC,OAAO,WAAW,CAAC,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAClD,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,6BAA6B;QACjC,OAAO,yBAAyB,EAAE,CAAC;IACrC,CAAC;IACD,KAAK,CAAC,iCAAiC;QACrC,OAAO,yBAAyB,EAAE,CAAC;IACrC,CAAC;CACF,CAAC;AAEF,SAAS,yBAAyB;IAChC,OAAO;QACL,MAAM,EAAE,gBAAgB,CAAC,OAAO;QAChC,OAAO,EAAE,OAAO;QAChB,OAAO,EAAE,IAAI;QACb,WAAW,EAAE,IAAI;KAClB,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAAC,EAC5B,UAAU,EACV,OAAO,GAAG,KAAK,EACf,uBAAuB,GAAG,KAAK,GACR;IACvB,MAAM,eAAe,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;IAEnD,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAC9C,KAAK,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC;IAC7B,KAAK,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,KAAK,CAAC,YAAY,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;IAC9C,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACnC,IAAI,uBAAuB,EAAE;QAC3B,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;KAC5C;IACD,IAAI,OAAO,EAAE;QACX,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;KACzC;IACD,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IAEjC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,KAAK,CAAC,gBAAgB,CAAC,QAAQ,EAAE,GAAG,EAAE;YACpC,IAAI,KAAK,CAAC,KAAK,EAAE;gBACf,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;gBAClC,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;gBAChC,MAAM,CAAC,OAAO,GAAG,GAAG,EAAE;oBACpB,MAAM,CAAC,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAC,CAAC;gBACvF,CAAC,CAAC;gBACF,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;oBAC7B,MAAM,GAAG,GAAI,MAAc,CAAC,MAAM,CAAC;oBACnC,OAAO,CAAC;wBACN,SAAS,EAAE,KAAK;wBAChB,GAAG;wBACH,KAAK,EAAE,CAAC;wBACR,MAAM,EAAE,CAAC;qBACV,CAAC,CAAC;gBACL,CAAC,CAAC;gBACF,6CAA6C;gBAC7C,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;aAClC;iBAAM;gBACL,OAAO,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;aAC9B;YAED,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC;QACtC,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import uuidv4 from 'uuid/v4';\nimport * as Permissions from 'expo-permissions';\nimport { PermissionResponse, PermissionStatus } from 'unimodules-permissions-interface';\n\nimport {\n ImagePickerResult,\n MediaTypeOptions,\n OpenFileBrowserOptions,\n ImagePickerOptions,\n} from './ImagePicker.types';\n\nconst MediaTypeInput = {\n [MediaTypeOptions.All]: 'video/mp4,video/quicktime,video/x-m4v,video/*,image/*',\n [MediaTypeOptions.Images]: 'image/*',\n [MediaTypeOptions.Videos]: 'video/mp4,video/quicktime,video/x-m4v,video/*',\n};\n\nexport default {\n get name(): string {\n return 'ExponentImagePicker';\n },\n\n async launchImageLibraryAsync({\n mediaTypes = MediaTypeOptions.All,\n allowsMultipleSelection = false,\n }: ImagePickerOptions): Promise {\n return await openFileBrowserAsync({\n mediaTypes,\n allowsMultipleSelection,\n });\n },\n\n async launchCameraAsync({\n mediaTypes = MediaTypeOptions.All,\n allowsMultipleSelection = false,\n }: ImagePickerOptions): Promise {\n return await openFileBrowserAsync({\n mediaTypes,\n allowsMultipleSelection,\n capture: true,\n });\n },\n\n /*\n * Delegate to expo-permissions to request camera permissions\n */\n async getCameraPermissionAsync() {\n return Permissions.getAsync(Permissions.CAMERA);\n },\n async requestCameraPermissionsAsync() {\n return Permissions.askAsync(Permissions.CAMERA);\n },\n\n /*\n * Camera roll permissions don't need to be requested on web, so we always\n * respond with granted.\n */\n async getCameraRollPermissionsAsync(): Promise {\n return permissionGrantedResponse();\n },\n async requestCameraRollPermissionsAsync(): Promise {\n return permissionGrantedResponse();\n },\n};\n\nfunction permissionGrantedResponse(): PermissionResponse {\n return {\n status: PermissionStatus.GRANTED,\n expires: 'never',\n granted: true,\n canAskAgain: true,\n };\n}\n\nfunction openFileBrowserAsync({\n mediaTypes,\n capture = false,\n allowsMultipleSelection = false,\n}: OpenFileBrowserOptions): Promise {\n const mediaTypeFormat = MediaTypeInput[mediaTypes];\n\n const input = document.createElement('input');\n input.style.display = 'none';\n input.setAttribute('type', 'file');\n input.setAttribute('accept', mediaTypeFormat);\n input.setAttribute('id', uuidv4());\n if (allowsMultipleSelection) {\n input.setAttribute('multiple', 'multiple');\n }\n if (capture) {\n input.setAttribute('capture', 'camera');\n }\n document.body.appendChild(input);\n\n return new Promise((resolve, reject) => {\n input.addEventListener('change', () => {\n if (input.files) {\n const targetFile = input.files[0];\n const reader = new FileReader();\n reader.onerror = () => {\n reject(new Error(`Failed to read the selected media because the operation failed.`));\n };\n reader.onload = ({ target }) => {\n const uri = (target as any).result;\n resolve({\n cancelled: false,\n uri,\n width: 0,\n height: 0,\n });\n };\n // Read in the image file as a binary string.\n reader.readAsDataURL(targetFile);\n } else {\n resolve({ cancelled: true });\n }\n\n document.body.removeChild(input);\n });\n\n const event = new MouseEvent('click');\n input.dispatchEvent(event);\n });\n}\n"]} \ No newline at end of file diff --git a/packages/expo-image-picker/build/ImagePicker.js.map b/packages/expo-image-picker/build/ImagePicker.js.map index d69f4473afe32..d1b2fb4a24927 100644 --- a/packages/expo-image-picker/build/ImagePicker.js.map +++ b/packages/expo-image-picker/build/ImagePicker.js.map @@ -1 +1 @@ -{"version":3,"file":"ImagePicker.js","sourceRoot":"","sources":["../src/ImagePicker/ImagePicker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,mBAAmB,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAEL,gBAAgB,EAGhB,iBAAiB,GAClB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,CAAC,KAAK,UAAU,yBAAyB;IAC7C,OAAO,mBAAmB,CAAC,yBAAyB,EAAE,CAAC;AACzD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,6BAA6B;IACjD,OAAO,mBAAmB,CAAC,6BAA6B,EAAE,CAAC;AAC7D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,6BAA6B;IACjD,OAAO,mBAAmB,CAAC,6BAA6B,EAAE,CAAC;AAC7D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iCAAiC;IACrD,OAAO,mBAAmB,CAAC,iCAAiC,EAAE,CAAC;AACjE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,UAA8B,EAAE;IAEhC,IAAI,CAAC,mBAAmB,CAAC,uBAAuB,EAAE;QAChD,MAAM,IAAI,mBAAmB,CAAC,aAAa,EAAE,yBAAyB,CAAC,CAAC;KACzE;IACD,OAAO,MAAM,mBAAmB,CAAC,uBAAuB,CAAC,OAAO,CAAC,CAAC;AACpE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,UAA8B,EAAE;IAEhC,IAAI,CAAC,mBAAmB,CAAC,iBAAiB,EAAE;QAC1C,MAAM,IAAI,mBAAmB,CAAC,aAAa,EAAE,mBAAmB,CAAC,CAAC;KACnE;IACD,OAAO,MAAM,mBAAmB,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;AAC9D,CAAC;AAED,OAAO,EAAE,gBAAgB,EAAyC,iBAAiB,EAAE,CAAC","sourcesContent":["import { UnavailabilityError } from '@unimodules/core';\n\nimport ExponentImagePicker from './ExponentImagePicker';\nimport {\n ImagePickerResult,\n MediaTypeOptions,\n ImagePickerOptions,\n PermissionResponse,\n VideoExportPreset,\n} from './ImagePicker.types';\n\nexport async function getCameraPermissionsAsync(): Promise {\n return ExponentImagePicker.getCameraPermissionsAsync();\n}\n\nexport async function getCameraRollPermissionsAsync(): Promise {\n return ExponentImagePicker.getCameraRollPermissionsAsync();\n}\n\nexport async function requestCameraPermissionsAsync(): Promise {\n return ExponentImagePicker.requestCameraPermissionsAsync();\n}\n\nexport async function requestCameraRollPermissionsAsync(): Promise {\n return ExponentImagePicker.requestCameraRollPermissionsAsync();\n}\n\nexport async function launchImageLibraryAsync(\n options: ImagePickerOptions = {}\n): Promise {\n if (!ExponentImagePicker.launchImageLibraryAsync) {\n throw new UnavailabilityError('ImagePicker', 'launchImageLibraryAsync');\n }\n return await ExponentImagePicker.launchImageLibraryAsync(options);\n}\n\nexport async function launchCameraAsync(\n options: ImagePickerOptions = {}\n): Promise {\n if (!ExponentImagePicker.launchCameraAsync) {\n throw new UnavailabilityError('ImagePicker', 'launchCameraAsync');\n }\n return await ExponentImagePicker.launchCameraAsync(options);\n}\n\nexport { MediaTypeOptions, ImagePickerOptions, ImagePickerResult, VideoExportPreset };\n"]} \ No newline at end of file +{"version":3,"file":"ImagePicker.js","sourceRoot":"","sources":["../src/ImagePicker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,mBAAmB,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAEL,gBAAgB,EAGhB,iBAAiB,GAClB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,CAAC,KAAK,UAAU,yBAAyB;IAC7C,OAAO,mBAAmB,CAAC,yBAAyB,EAAE,CAAC;AACzD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,6BAA6B;IACjD,OAAO,mBAAmB,CAAC,6BAA6B,EAAE,CAAC;AAC7D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,6BAA6B;IACjD,OAAO,mBAAmB,CAAC,6BAA6B,EAAE,CAAC;AAC7D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iCAAiC;IACrD,OAAO,mBAAmB,CAAC,iCAAiC,EAAE,CAAC;AACjE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,UAA8B,EAAE;IAEhC,IAAI,CAAC,mBAAmB,CAAC,uBAAuB,EAAE;QAChD,MAAM,IAAI,mBAAmB,CAAC,aAAa,EAAE,yBAAyB,CAAC,CAAC;KACzE;IACD,OAAO,MAAM,mBAAmB,CAAC,uBAAuB,CAAC,OAAO,CAAC,CAAC;AACpE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,UAA8B,EAAE;IAEhC,IAAI,CAAC,mBAAmB,CAAC,iBAAiB,EAAE;QAC1C,MAAM,IAAI,mBAAmB,CAAC,aAAa,EAAE,mBAAmB,CAAC,CAAC;KACnE;IACD,OAAO,MAAM,mBAAmB,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;AAC9D,CAAC;AAED,OAAO,EAAE,gBAAgB,EAAyC,iBAAiB,EAAE,CAAC","sourcesContent":["import { UnavailabilityError } from '@unimodules/core';\n\nimport ExponentImagePicker from './ExponentImagePicker';\nimport {\n ImagePickerResult,\n MediaTypeOptions,\n ImagePickerOptions,\n PermissionResponse,\n VideoExportPreset,\n} from './ImagePicker.types';\n\nexport async function getCameraPermissionsAsync(): Promise {\n return ExponentImagePicker.getCameraPermissionsAsync();\n}\n\nexport async function getCameraRollPermissionsAsync(): Promise {\n return ExponentImagePicker.getCameraRollPermissionsAsync();\n}\n\nexport async function requestCameraPermissionsAsync(): Promise {\n return ExponentImagePicker.requestCameraPermissionsAsync();\n}\n\nexport async function requestCameraRollPermissionsAsync(): Promise {\n return ExponentImagePicker.requestCameraRollPermissionsAsync();\n}\n\nexport async function launchImageLibraryAsync(\n options: ImagePickerOptions = {}\n): Promise {\n if (!ExponentImagePicker.launchImageLibraryAsync) {\n throw new UnavailabilityError('ImagePicker', 'launchImageLibraryAsync');\n }\n return await ExponentImagePicker.launchImageLibraryAsync(options);\n}\n\nexport async function launchCameraAsync(\n options: ImagePickerOptions = {}\n): Promise {\n if (!ExponentImagePicker.launchCameraAsync) {\n throw new UnavailabilityError('ImagePicker', 'launchCameraAsync');\n }\n return await ExponentImagePicker.launchCameraAsync(options);\n}\n\nexport { MediaTypeOptions, ImagePickerOptions, ImagePickerResult, VideoExportPreset };\n"]} \ No newline at end of file diff --git a/packages/expo-image-picker/build/ImagePicker.types.js.map b/packages/expo-image-picker/build/ImagePicker.types.js.map index ddb4af689ead0..09f00b6e350d8 100644 --- a/packages/expo-image-picker/build/ImagePicker.types.js.map +++ b/packages/expo-image-picker/build/ImagePicker.types.js.map @@ -1 +1 @@ -{"version":3,"file":"ImagePicker.types.js","sourceRoot":"","sources":["../src/ImagePicker/ImagePicker.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAExF,MAAM,CAAN,IAAY,gBAIX;AAJD,WAAY,gBAAgB;IAC1B,+BAAW,CAAA;IACX,qCAAiB,CAAA;IACjB,qCAAiB,CAAA;AACnB,CAAC,EAJW,gBAAgB,KAAhB,gBAAgB,QAI3B;AAED,MAAM,CAAN,IAAY,iBAYX;AAZD,WAAY,iBAAiB;IAC3B,uEAAe,CAAA;IACf,qEAAc,CAAA;IACd,2EAAiB,CAAA;IACjB,6EAAkB,CAAA;IAClB,yEAAgB,CAAA;IAChB,yEAAgB,CAAA;IAChB,2EAAiB,CAAA;IACjB,6EAAkB,CAAA;IAClB,6EAAkB,CAAA;IAClB,6EAAkB,CAAA;IAClB,8EAAmB,CAAA;AACrB,CAAC,EAZW,iBAAiB,KAAjB,iBAAiB,QAY5B;AA8BD,OAAO,EAAsB,gBAAgB,EAAE,CAAC","sourcesContent":["import { PermissionResponse, PermissionStatus } from 'unimodules-permissions-interface';\n\nexport enum MediaTypeOptions {\n All = 'All',\n Videos = 'Videos',\n Images = 'Images',\n}\n\nexport enum VideoExportPreset {\n Passthrough = 0,\n LowQuality = 1,\n MediumQuality = 2,\n HighestQuality = 3,\n H264_640x480 = 4,\n H264_960x540 = 5,\n H264_1280x720 = 6,\n H264_1920x1080 = 7,\n H264_3840x2160 = 8,\n HEVC_1920x1080 = 9,\n HEVC_3840x2160 = 10,\n}\n\nexport type ImageInfo = {\n uri: string;\n width: number;\n height: number;\n type?: 'image' | 'video';\n exif?: { [key: string]: any };\n base64?: string;\n};\n\nexport type ImagePickerResult = { cancelled: true } | ({ cancelled: false } & ImageInfo);\n\nexport type ImagePickerOptions = {\n allowsEditing?: boolean;\n aspect?: [number, number];\n quality?: number;\n allowsMultipleSelection?: boolean;\n mediaTypes?: MediaTypeOptions;\n exif?: boolean;\n base64?: boolean;\n videoExportPreset?: VideoExportPreset;\n};\n\nexport type OpenFileBrowserOptions = {\n mediaTypes: MediaTypeOptions;\n capture?: boolean;\n allowsMultipleSelection: boolean;\n};\n\nexport { PermissionResponse, PermissionStatus };\n"]} \ No newline at end of file +{"version":3,"file":"ImagePicker.types.js","sourceRoot":"","sources":["../src/ImagePicker.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAExF,MAAM,CAAN,IAAY,gBAIX;AAJD,WAAY,gBAAgB;IAC1B,+BAAW,CAAA;IACX,qCAAiB,CAAA;IACjB,qCAAiB,CAAA;AACnB,CAAC,EAJW,gBAAgB,KAAhB,gBAAgB,QAI3B;AAED,MAAM,CAAN,IAAY,iBAYX;AAZD,WAAY,iBAAiB;IAC3B,uEAAe,CAAA;IACf,qEAAc,CAAA;IACd,2EAAiB,CAAA;IACjB,6EAAkB,CAAA;IAClB,yEAAgB,CAAA;IAChB,yEAAgB,CAAA;IAChB,2EAAiB,CAAA;IACjB,6EAAkB,CAAA;IAClB,6EAAkB,CAAA;IAClB,6EAAkB,CAAA;IAClB,8EAAmB,CAAA;AACrB,CAAC,EAZW,iBAAiB,KAAjB,iBAAiB,QAY5B;AA8BD,OAAO,EAAsB,gBAAgB,EAAE,CAAC","sourcesContent":["import { PermissionResponse, PermissionStatus } from 'unimodules-permissions-interface';\n\nexport enum MediaTypeOptions {\n All = 'All',\n Videos = 'Videos',\n Images = 'Images',\n}\n\nexport enum VideoExportPreset {\n Passthrough = 0,\n LowQuality = 1,\n MediumQuality = 2,\n HighestQuality = 3,\n H264_640x480 = 4,\n H264_960x540 = 5,\n H264_1280x720 = 6,\n H264_1920x1080 = 7,\n H264_3840x2160 = 8,\n HEVC_1920x1080 = 9,\n HEVC_3840x2160 = 10,\n}\n\nexport type ImageInfo = {\n uri: string;\n width: number;\n height: number;\n type?: 'image' | 'video';\n exif?: { [key: string]: any };\n base64?: string;\n};\n\nexport type ImagePickerResult = { cancelled: true } | ({ cancelled: false } & ImageInfo);\n\nexport type ImagePickerOptions = {\n allowsEditing?: boolean;\n aspect?: [number, number];\n quality?: number;\n allowsMultipleSelection?: boolean;\n mediaTypes?: MediaTypeOptions;\n exif?: boolean;\n base64?: boolean;\n videoExportPreset?: VideoExportPreset;\n};\n\nexport type OpenFileBrowserOptions = {\n mediaTypes: MediaTypeOptions;\n capture?: boolean;\n allowsMultipleSelection: boolean;\n};\n\nexport { PermissionResponse, PermissionStatus };\n"]} \ No newline at end of file diff --git a/packages/expo-image-picker/package.json b/packages/expo-image-picker/package.json index 3b6842123977c..b4e598a31fa85 100644 --- a/packages/expo-image-picker/package.json +++ b/packages/expo-image-picker/package.json @@ -33,11 +33,14 @@ "license": "MIT", "homepage": "https://docs.expo.io/versions/latest/sdk/imagepicker/", "jest": { - "preset": "expo-module-scripts/ios" + "preset": "expo-module-scripts" }, "unimodulePeerDependencies": { "@unimodules/core": "*" }, + "dependencies": { + "expo-permissions": "*" + }, "devDependencies": { "expo-module-scripts": "~1.1.1" }, diff --git a/packages/expo-image-picker/src/ImagePicker/ExponentImagePicker.ts b/packages/expo-image-picker/src/ExponentImagePicker.ts similarity index 100% rename from packages/expo-image-picker/src/ImagePicker/ExponentImagePicker.ts rename to packages/expo-image-picker/src/ExponentImagePicker.ts diff --git a/packages/expo-image-picker/src/ImagePicker/ExponentImagePicker.web.ts b/packages/expo-image-picker/src/ExponentImagePicker.web.ts similarity index 72% rename from packages/expo-image-picker/src/ImagePicker/ExponentImagePicker.web.ts rename to packages/expo-image-picker/src/ExponentImagePicker.web.ts index 0b5312abc7300..13e5233179cbb 100644 --- a/packages/expo-image-picker/src/ImagePicker/ExponentImagePicker.web.ts +++ b/packages/expo-image-picker/src/ExponentImagePicker.web.ts @@ -1,4 +1,6 @@ import uuidv4 from 'uuid/v4'; +import * as Permissions from 'expo-permissions'; +import { PermissionResponse, PermissionStatus } from 'unimodules-permissions-interface'; import { ImagePickerResult, @@ -17,6 +19,7 @@ export default { get name(): string { return 'ExponentImagePicker'; }, + async launchImageLibraryAsync({ mediaTypes = MediaTypeOptions.All, allowsMultipleSelection = false, @@ -26,6 +29,7 @@ export default { allowsMultipleSelection, }); }, + async launchCameraAsync({ mediaTypes = MediaTypeOptions.All, allowsMultipleSelection = false, @@ -36,8 +40,38 @@ export default { capture: true, }); }, + + /* + * Delegate to expo-permissions to request camera permissions + */ + async getCameraPermissionAsync() { + return Permissions.getAsync(Permissions.CAMERA); + }, + async requestCameraPermissionsAsync() { + return Permissions.askAsync(Permissions.CAMERA); + }, + + /* + * Camera roll permissions don't need to be requested on web, so we always + * respond with granted. + */ + async getCameraRollPermissionsAsync(): Promise { + return permissionGrantedResponse(); + }, + async requestCameraRollPermissionsAsync(): Promise { + return permissionGrantedResponse(); + }, }; +function permissionGrantedResponse(): PermissionResponse { + return { + status: PermissionStatus.GRANTED, + expires: 'never', + granted: true, + canAskAgain: true, + }; +} + function openFileBrowserAsync({ mediaTypes, capture = false, diff --git a/packages/expo-image-picker/src/ImagePicker/ImagePicker.ts b/packages/expo-image-picker/src/ImagePicker.ts similarity index 100% rename from packages/expo-image-picker/src/ImagePicker/ImagePicker.ts rename to packages/expo-image-picker/src/ImagePicker.ts diff --git a/packages/expo-image-picker/src/ImagePicker/ImagePicker.types.ts b/packages/expo-image-picker/src/ImagePicker.types.ts similarity index 100% rename from packages/expo-image-picker/src/ImagePicker/ImagePicker.types.ts rename to packages/expo-image-picker/src/ImagePicker.types.ts diff --git a/packages/expo-image-picker/src/__tests__/ExponentImagePicker-test.web.ts b/packages/expo-image-picker/src/__tests__/ExponentImagePicker-test.web.ts new file mode 100644 index 0000000000000..abc025bc32b4f --- /dev/null +++ b/packages/expo-image-picker/src/__tests__/ExponentImagePicker-test.web.ts @@ -0,0 +1,19 @@ +import ExponentImagePicker from '../ExponentImagePicker'; + +describe('ExponentImagePicker', () => { + describe('getCameraRollPermissionsAsync', () => { + it(`is always granted`, async () => { + let response = await ExponentImagePicker.getCameraRollPermissionsAsync(); + expect(response.granted).toBeTruthy(); + expect(response.status).toBe('granted'); + }); + }); + + describe('requestCameraRollPermissionsAsync', () => { + it(`is always granted`, async () => { + let response = await ExponentImagePicker.getCameraRollPermissionsAsync(); + expect(response.granted).toBeTruthy(); + expect(response.status).toBe('granted'); + }); + }); +}); diff --git a/packages/expo-sharing/build/ExpoSharing.web.js b/packages/expo-sharing/build/ExpoSharing.web.js index 8afbaee7ff3ec..5c977eeffef19 100644 --- a/packages/expo-sharing/build/ExpoSharing.web.js +++ b/packages/expo-sharing/build/ExpoSharing.web.js @@ -3,8 +3,11 @@ export default { get name() { return 'ExpoSharing'; }, - isAvailableAsync() { - return Promise.resolve(!!navigator.share); + async isAvailableAsync() { + if (typeof navigator === 'undefined') { + return false; + } + return !!navigator.share; }, async shareAsync(url, options = {}) { const sharingNavigator = navigator; diff --git a/packages/expo-sharing/build/ExpoSharing.web.js.map b/packages/expo-sharing/build/ExpoSharing.web.js.map index 2f7a8ff7b100c..c8bdb50d1dd0b 100644 --- a/packages/expo-sharing/build/ExpoSharing.web.js.map +++ b/packages/expo-sharing/build/ExpoSharing.web.js.map @@ -1 +1 @@ -{"version":3,"file":"ExpoSharing.web.js","sourceRoot":"","sources":["../src/ExpoSharing.web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAUvD,eAAe;IACb,IAAI,IAAI;QACN,OAAO,aAAa,CAAC;IACvB,CAAC;IACD,gBAAgB;QACd,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC,CAAE,SAAuB,CAAC,KAAK,CAAC,CAAC;IAC3D,CAAC;IACD,KAAK,CAAC,UAAU,CAAC,GAAW,EAAE,UAAwB,EAAE;QACtD,MAAM,gBAAgB,GAAc,SAAsB,CAAC;QAE3D,sDAAsD;QACtD,IAAI,gBAAgB,CAAC,KAAK,EAAE;YAC1B,OAAO,MAAM,gBAAgB,CAAC,KAAK,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;SAC1D;aAAM;YACL,MAAM,IAAI,mBAAmB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;SACrD;IACH,CAAC;CACF,CAAC","sourcesContent":["import { UnavailabilityError } from '@unimodules/core';\n\ntype ShareOptions = { title?: string; text?: string; url?: string };\n\ntype NavigatorShare = (options: ShareOptions) => Promise<{}>;\n\ninterface Navigator {\n share?: NavigatorShare;\n}\n\nexport default {\n get name(): string {\n return 'ExpoSharing';\n },\n isAvailableAsync(): Promise {\n return Promise.resolve(!!(navigator as Navigator).share);\n },\n async shareAsync(url: string, options: ShareOptions = {}): Promise<{}> {\n const sharingNavigator: Navigator = navigator as Navigator;\n\n // NOTE: `navigator.share` is only available via HTTPS\n if (sharingNavigator.share) {\n return await sharingNavigator.share({ ...options, url });\n } else {\n throw new UnavailabilityError('navigator', 'share');\n }\n },\n};\n"]} \ No newline at end of file +{"version":3,"file":"ExpoSharing.web.js","sourceRoot":"","sources":["../src/ExpoSharing.web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAUvD,eAAe;IACb,IAAI,IAAI;QACN,OAAO,aAAa,CAAC;IACvB,CAAC;IACD,KAAK,CAAC,gBAAgB;QACpB,IAAI,OAAO,SAAS,KAAK,WAAW,EAAE;YACpC,OAAO,KAAK,CAAC;SACd;QAEA,OAAO,CAAC,CAAE,SAAuB,CAAC,KAAK,CAAC;IAC3C,CAAC;IACD,KAAK,CAAC,UAAU,CAAC,GAAW,EAAE,UAAwB,EAAE;QACtD,MAAM,gBAAgB,GAAc,SAAsB,CAAC;QAE3D,sDAAsD;QACtD,IAAI,gBAAgB,CAAC,KAAK,EAAE;YAC1B,OAAO,MAAM,gBAAgB,CAAC,KAAK,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;SAC1D;aAAM;YACL,MAAM,IAAI,mBAAmB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;SACrD;IACH,CAAC;CACF,CAAC","sourcesContent":["import { UnavailabilityError } from '@unimodules/core';\n\ntype ShareOptions = { title?: string; text?: string; url?: string };\n\ntype NavigatorShare = (options: ShareOptions) => Promise<{}>;\n\ninterface Navigator {\n share?: NavigatorShare;\n}\n\nexport default {\n get name(): string {\n return 'ExpoSharing';\n },\n async isAvailableAsync(): Promise {\n if (typeof navigator === 'undefined') {\n return false;\n }\n\n return !!(navigator as Navigator).share;\n },\n async shareAsync(url: string, options: ShareOptions = {}): Promise<{}> {\n const sharingNavigator: Navigator = navigator as Navigator;\n\n // NOTE: `navigator.share` is only available via HTTPS\n if (sharingNavigator.share) {\n return await sharingNavigator.share({ ...options, url });\n } else {\n throw new UnavailabilityError('navigator', 'share');\n }\n },\n};\n"]} \ No newline at end of file diff --git a/packages/expo-sharing/package.json b/packages/expo-sharing/package.json index 168e262e0f473..454f656206362 100644 --- a/packages/expo-sharing/package.json +++ b/packages/expo-sharing/package.json @@ -24,6 +24,9 @@ "url": "https://github.com/expo/expo.git", "directory": "packages/expo-sharing" }, + "jest": { + "preset": "expo-module-scripts" + }, "author": "650 Industries, Inc.", "license": "MIT", "homepage": "https://github.com/expo/expo/tree/master/packages/expo-sharing", @@ -36,4 +39,4 @@ "expo-module-scripts": "~1.1.1" }, "gitHead": "ec7878b9ce54f2537721218ae0fe4017e4004806" -} \ No newline at end of file +} diff --git a/packages/expo-sharing/src/ExpoSharing.web.ts b/packages/expo-sharing/src/ExpoSharing.web.ts index 848b08c53676a..2e15334924531 100644 --- a/packages/expo-sharing/src/ExpoSharing.web.ts +++ b/packages/expo-sharing/src/ExpoSharing.web.ts @@ -12,8 +12,12 @@ export default { get name(): string { return 'ExpoSharing'; }, - isAvailableAsync(): Promise { - return Promise.resolve(!!(navigator as Navigator).share); + async isAvailableAsync(): Promise { + if (typeof navigator === 'undefined') { + return false; + } + + return !!(navigator as Navigator).share; }, async shareAsync(url: string, options: ShareOptions = {}): Promise<{}> { const sharingNavigator: Navigator = navigator as Navigator; diff --git a/packages/expo-sharing/src/__tests__/Sharing-test.native.ts b/packages/expo-sharing/src/__tests__/Sharing-test.native.ts new file mode 100644 index 0000000000000..c634c62d22573 --- /dev/null +++ b/packages/expo-sharing/src/__tests__/Sharing-test.native.ts @@ -0,0 +1,10 @@ +import * as Sharing from '../Sharing'; + +describe('Sharing', () => { + describe('isAvailableAsync', () => { + it(`is always true on native`, async () => { + let isAvailable = await Sharing.isAvailableAsync(); + expect(isAvailable).toBeTruthy(); + }); + }); +}); \ No newline at end of file diff --git a/packages/expo-sharing/src/__tests__/Sharing-test.web.ts b/packages/expo-sharing/src/__tests__/Sharing-test.web.ts new file mode 100644 index 0000000000000..cad61d6d456ed --- /dev/null +++ b/packages/expo-sharing/src/__tests__/Sharing-test.web.ts @@ -0,0 +1,24 @@ +import { mockProperty, unmockProperty } from 'jest-expo'; +import * as Sharing from '../Sharing'; + +describe('Sharing', () => { + describe('isAvailableAsync', () => { + if (typeof navigator !== 'undefined') { + describe('browser', () => { + it(`returns true if navigator.share is defined`, async () => { + mockProperty(navigator, 'share', true); + let isAvailable = await Sharing.isAvailableAsync(); + expect(isAvailable).toBeTruthy(); + unmockProperty(navigator, 'share'); + }); + }); + } else { + describe('node', () => { + it(`returns false`, async () => { + let isAvailable = await Sharing.isAvailableAsync(); + expect(isAvailable).toBeFalsy(); + }) + }); + } + }); +}); From 2276f9abac8803ef35648fd7ba7dbdcbeeaf9393 Mon Sep 17 00:00:00 2001 From: Brent Vatne Date: Mon, 13 Jan 2020 17:48:37 -0800 Subject: [PATCH 009/103] [sharing] Fix build --- packages/expo-sharing/build/ExpoSharing.web.js.map | 2 +- packages/expo-sharing/src/ExpoSharing.web.ts | 2 +- packages/expo-sharing/src/__tests__/Sharing-test.native.ts | 2 +- packages/expo-sharing/src/__tests__/Sharing-test.web.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/expo-sharing/build/ExpoSharing.web.js.map b/packages/expo-sharing/build/ExpoSharing.web.js.map index c8bdb50d1dd0b..c716d5683a77f 100644 --- a/packages/expo-sharing/build/ExpoSharing.web.js.map +++ b/packages/expo-sharing/build/ExpoSharing.web.js.map @@ -1 +1 @@ -{"version":3,"file":"ExpoSharing.web.js","sourceRoot":"","sources":["../src/ExpoSharing.web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAUvD,eAAe;IACb,IAAI,IAAI;QACN,OAAO,aAAa,CAAC;IACvB,CAAC;IACD,KAAK,CAAC,gBAAgB;QACpB,IAAI,OAAO,SAAS,KAAK,WAAW,EAAE;YACpC,OAAO,KAAK,CAAC;SACd;QAEA,OAAO,CAAC,CAAE,SAAuB,CAAC,KAAK,CAAC;IAC3C,CAAC;IACD,KAAK,CAAC,UAAU,CAAC,GAAW,EAAE,UAAwB,EAAE;QACtD,MAAM,gBAAgB,GAAc,SAAsB,CAAC;QAE3D,sDAAsD;QACtD,IAAI,gBAAgB,CAAC,KAAK,EAAE;YAC1B,OAAO,MAAM,gBAAgB,CAAC,KAAK,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;SAC1D;aAAM;YACL,MAAM,IAAI,mBAAmB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;SACrD;IACH,CAAC;CACF,CAAC","sourcesContent":["import { UnavailabilityError } from '@unimodules/core';\n\ntype ShareOptions = { title?: string; text?: string; url?: string };\n\ntype NavigatorShare = (options: ShareOptions) => Promise<{}>;\n\ninterface Navigator {\n share?: NavigatorShare;\n}\n\nexport default {\n get name(): string {\n return 'ExpoSharing';\n },\n async isAvailableAsync(): Promise {\n if (typeof navigator === 'undefined') {\n return false;\n }\n\n return !!(navigator as Navigator).share;\n },\n async shareAsync(url: string, options: ShareOptions = {}): Promise<{}> {\n const sharingNavigator: Navigator = navigator as Navigator;\n\n // NOTE: `navigator.share` is only available via HTTPS\n if (sharingNavigator.share) {\n return await sharingNavigator.share({ ...options, url });\n } else {\n throw new UnavailabilityError('navigator', 'share');\n }\n },\n};\n"]} \ No newline at end of file +{"version":3,"file":"ExpoSharing.web.js","sourceRoot":"","sources":["../src/ExpoSharing.web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAUvD,eAAe;IACb,IAAI,IAAI;QACN,OAAO,aAAa,CAAC;IACvB,CAAC;IACD,KAAK,CAAC,gBAAgB;QACpB,IAAI,OAAO,SAAS,KAAK,WAAW,EAAE;YACpC,OAAO,KAAK,CAAC;SACd;QAED,OAAO,CAAC,CAAE,SAAuB,CAAC,KAAK,CAAC;IAC1C,CAAC;IACD,KAAK,CAAC,UAAU,CAAC,GAAW,EAAE,UAAwB,EAAE;QACtD,MAAM,gBAAgB,GAAc,SAAsB,CAAC;QAE3D,sDAAsD;QACtD,IAAI,gBAAgB,CAAC,KAAK,EAAE;YAC1B,OAAO,MAAM,gBAAgB,CAAC,KAAK,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;SAC1D;aAAM;YACL,MAAM,IAAI,mBAAmB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;SACrD;IACH,CAAC;CACF,CAAC","sourcesContent":["import { UnavailabilityError } from '@unimodules/core';\n\ntype ShareOptions = { title?: string; text?: string; url?: string };\n\ntype NavigatorShare = (options: ShareOptions) => Promise<{}>;\n\ninterface Navigator {\n share?: NavigatorShare;\n}\n\nexport default {\n get name(): string {\n return 'ExpoSharing';\n },\n async isAvailableAsync(): Promise {\n if (typeof navigator === 'undefined') {\n return false;\n }\n\n return !!(navigator as Navigator).share;\n },\n async shareAsync(url: string, options: ShareOptions = {}): Promise<{}> {\n const sharingNavigator: Navigator = navigator as Navigator;\n\n // NOTE: `navigator.share` is only available via HTTPS\n if (sharingNavigator.share) {\n return await sharingNavigator.share({ ...options, url });\n } else {\n throw new UnavailabilityError('navigator', 'share');\n }\n },\n};\n"]} \ No newline at end of file diff --git a/packages/expo-sharing/src/ExpoSharing.web.ts b/packages/expo-sharing/src/ExpoSharing.web.ts index 2e15334924531..6a4d5cf9a103f 100644 --- a/packages/expo-sharing/src/ExpoSharing.web.ts +++ b/packages/expo-sharing/src/ExpoSharing.web.ts @@ -17,7 +17,7 @@ export default { return false; } - return !!(navigator as Navigator).share; + return !!(navigator as Navigator).share; }, async shareAsync(url: string, options: ShareOptions = {}): Promise<{}> { const sharingNavigator: Navigator = navigator as Navigator; diff --git a/packages/expo-sharing/src/__tests__/Sharing-test.native.ts b/packages/expo-sharing/src/__tests__/Sharing-test.native.ts index c634c62d22573..51f278ade86a0 100644 --- a/packages/expo-sharing/src/__tests__/Sharing-test.native.ts +++ b/packages/expo-sharing/src/__tests__/Sharing-test.native.ts @@ -7,4 +7,4 @@ describe('Sharing', () => { expect(isAvailable).toBeTruthy(); }); }); -}); \ No newline at end of file +}); diff --git a/packages/expo-sharing/src/__tests__/Sharing-test.web.ts b/packages/expo-sharing/src/__tests__/Sharing-test.web.ts index cad61d6d456ed..496e44e869dea 100644 --- a/packages/expo-sharing/src/__tests__/Sharing-test.web.ts +++ b/packages/expo-sharing/src/__tests__/Sharing-test.web.ts @@ -17,7 +17,7 @@ describe('Sharing', () => { it(`returns false`, async () => { let isAvailable = await Sharing.isAvailableAsync(); expect(isAvailable).toBeFalsy(); - }) + }); }); } }); From 0c403cd65dc7358ea0b4e143ff2ee4ffcf3e97b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw=20Chmiela?= Date: Tue, 14 Jan 2020 11:19:24 +0100 Subject: [PATCH 010/103] [bare] Enable singleton modules creation (#6751) This is a reapplication of https://github.com/expo/expo/pull/6575 + changes of `templates`. --- # Why I'll add singleton modules in `expo-notifications` PR and, since I'm testing the new library in `bare-expo` project, it needs to handle singleton modules well. # How If we pass `null` in place of `singletonModules` argument, when `ReactModuleRegistryProvider` calls `getSingletonModules()` they'll get created: https://github.com/expo/expo/blob/9c60cc74437760fafe100fee9cbccf204fc1baf7/packages/%40unimodules/react-native-adapter/android/src/main/java/org/unimodules/adapters/react/ReactModuleRegistryProvider.java#L58-L69 # Test Plan `bare-expo` created singleton modules and passed them to module registry, letting exported modules query them by name. --- .../app/src/main/java/dev/expo/payments/MainApplication.java | 2 +- .../app/src/main/java/com/helloworld/MainApplication.java | 2 +- .../app/src/main/java/com/helloworld/MainApplication.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/bare-expo/android/app/src/main/java/dev/expo/payments/MainApplication.java b/apps/bare-expo/android/app/src/main/java/dev/expo/payments/MainApplication.java index 811ea64463043..245dcb45750ba 100644 --- a/apps/bare-expo/android/app/src/main/java/dev/expo/payments/MainApplication.java +++ b/apps/bare-expo/android/app/src/main/java/dev/expo/payments/MainApplication.java @@ -26,7 +26,7 @@ public class MainApplication extends Application implements ReactApplication { private final ReactModuleRegistryProvider mModuleRegistryProvider = new ReactModuleRegistryProvider( new BasePackageList().getPackageList(), - Arrays.asList() + null ); private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { diff --git a/templates/expo-template-bare-minimum/android/app/src/main/java/com/helloworld/MainApplication.java b/templates/expo-template-bare-minimum/android/app/src/main/java/com/helloworld/MainApplication.java index e784f27341d18..193c4557153a8 100644 --- a/templates/expo-template-bare-minimum/android/app/src/main/java/com/helloworld/MainApplication.java +++ b/templates/expo-template-bare-minimum/android/app/src/main/java/com/helloworld/MainApplication.java @@ -25,7 +25,7 @@ public class MainApplication extends Application implements ReactApplication { private final ReactModuleRegistryProvider mModuleRegistryProvider = new ReactModuleRegistryProvider( new BasePackageList().getPackageList(), - Arrays.asList() + null ); private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { diff --git a/templates/expo-template-bare-typescript/android/app/src/main/java/com/helloworld/MainApplication.java b/templates/expo-template-bare-typescript/android/app/src/main/java/com/helloworld/MainApplication.java index e784f27341d18..193c4557153a8 100644 --- a/templates/expo-template-bare-typescript/android/app/src/main/java/com/helloworld/MainApplication.java +++ b/templates/expo-template-bare-typescript/android/app/src/main/java/com/helloworld/MainApplication.java @@ -25,7 +25,7 @@ public class MainApplication extends Application implements ReactApplication { private final ReactModuleRegistryProvider mModuleRegistryProvider = new ReactModuleRegistryProvider( new BasePackageList().getPackageList(), - Arrays.asList() + null ); private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { From 1b0aea81add22404234d8307f70100643b7b1041 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw=20Chmiela?= Date: Tue, 14 Jan 2020 12:12:30 +0100 Subject: [PATCH 011/103] [ci] Disable android_test_suite job (and test_suite_publish) (#6735) # Why https://exponent-internal.slack.com/archives/C1QNF5L3C/p1576852692010900 # How Commented out jobs from workflow. # Test Plan All CI for this PR should pass. --- .circleci/config.yml | 88 +++++++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 41 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5500296e93fc8..ddbd979cfb1d2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -358,10 +358,12 @@ workflows: - expotools - client_android - client_ios - - test_suite_publish - - android_test_suite: - requires: - - test_suite_publish + # Disabled until further notice + # See https://exponent-internal.slack.com/archives/C1QNF5L3C/p1576852692010900 + # - test_suite_publish + # - android_test_suite: + # requires: + # - test_suite_publish - client_android_approve_google_play: type: approval requires: @@ -718,29 +720,31 @@ jobs: echo "You can deploy this by updating or creating a new file in https://github.com/expo/turtle/tree/master/shellTarballs/android" echo "Then follow the deployment instructions: https://github.com/expo/turtle-deploy" - android_test_suite: - executor: android - steps: - - setup - - guard_sdk_tests - - update_submodules - - yarn_install: - working_directory: ~/expo # need jsc-android dependency in expokit-npm-package - - yarn_install: - working_directory: ~/expo/tools-public - - restore_gradle_cache - - run: - name: Build APK, upload to Device Farm, follow device logs - command: | - nix-shell android/shell.nix --pure \ - --keep AWS_ACCESS_KEY_ID \ - --keep AWS_SECRET_ACCESS_KEY \ - --keep SSL_CERT_FILE \ - --keep FASTLANE_SKIP_UPDATE_CHECK \ - --keep FASTLANE_DISABLE_COLORS \ - --keep CI \ - --run "fastlane android devicefarm" - - save_gradle_cache +# Disabled until further notice +# See https://exponent-internal.slack.com/archives/C1QNF5L3C/p1576852692010900 +# android_test_suite: +# executor: android +# steps: +# - setup +# - guard_sdk_tests +# - update_submodules +# - yarn_install: +# working_directory: ~/expo # need jsc-android dependency in expokit-npm-package +# - yarn_install: +# working_directory: ~/expo/tools-public +# - restore_gradle_cache +# - run: +# name: Build APK, upload to Device Farm, follow device logs +# command: | +# nix-shell android/shell.nix --pure \ +# --keep AWS_ACCESS_KEY_ID \ +# --keep AWS_SECRET_ACCESS_KEY \ +# --keep SSL_CERT_FILE \ +# --keep FASTLANE_SKIP_UPDATE_CHECK \ +# --keep FASTLANE_DISABLE_COLORS \ +# --keep CI \ +# --run "fastlane android devicefarm" +# - save_gradle_cache client_android: executor: android @@ -850,17 +854,19 @@ jobs: command: ./deploy.sh working_directory: docs - test_suite_publish: - executor: nix - steps: - - setup - - conditionally_halt: - # Exclude .git/, node_modules,THIRD-PARTY-LICENSES, LICENSE, docs/, guides/, template-files/, templates/, native-component-list/, bare-expo/, and every `.md` file - exclude: '^(.*)(\/(.git\/|LICENSE|THIRD-PARTY-LICENSES|node_modules|docs|guides|scripts|template-files|templates|native-component-list|bare-expo).*|\.md$)' - search_depth: 1 - - update_submodules - - decrypt_secrets_if_possible - - run: - name: Publish - working_directory: ~/expo/apps/test-suite - command: ./publish.sh +# Disabled until further notice +# See https://exponent-internal.slack.com/archives/C1QNF5L3C/p1576852692010900 +# test_suite_publish: +# executor: nix +# steps: +# - setup +# - conditionally_halt: +# # Exclude .git/, node_modules,THIRD-PARTY-LICENSES, LICENSE, docs/, guides/, template-files/, templates/, native-component-list/, bare-expo/, and every `.md` file +# exclude: '^(.*)(\/(.git\/|LICENSE|THIRD-PARTY-LICENSES|node_modules|docs|guides|scripts|template-files|templates|native-component-list|bare-expo).*|\.md$)' +# search_depth: 1 +# - update_submodules +# - decrypt_secrets_if_possible +# - run: +# name: Publish +# working_directory: ~/expo/apps/test-suite +# command: ./publish.sh From 470c2db6792b18df36efdb51a88fdf412af9b100 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw=20Chmiela?= Date: Tue, 14 Jan 2020 12:23:57 +0100 Subject: [PATCH 012/103] [@unimodules/react-native-adapter] Export ProxyNativeModule (#6759) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Why `ProxyNativeModule` type may come in handy in other type-safe unimodules which want to rely on the listener functionality. # How Exported `ProxyNativeModule`, rebuilt all the packages. # Test Plan Code compiles, so ✅ --- .../react-native-adapter/build/NativeModulesProxy.d.ts | 2 +- .../react-native-adapter/build/NativeModulesProxy.js.map | 2 +- packages/@unimodules/react-native-adapter/build/index.d.ts | 4 ++-- .../@unimodules/react-native-adapter/build/index.js.map | 2 +- .../react-native-adapter/src/NativeModulesProxy.ts | 2 +- packages/@unimodules/react-native-adapter/src/index.ts | 3 ++- packages/expo-ads-admob/build/ExpoAdsAdMob.d.ts | 6 +----- .../build/ExpoAdsAdMobInterstitialManager.d.ts | 6 +----- .../build/ExpoAdsAdMobRewardedVideoAdManager.d.ts | 6 +----- packages/expo-analytics-amplitude/build/ExpoAmplitude.d.ts | 6 +----- packages/expo-analytics-segment/build/ExponentSegment.d.ts | 6 +----- packages/expo-app-auth/build/ExpoAppAuth.d.ts | 6 +----- .../build/ExpoAppleAuthentication.d.ts | 6 +----- packages/expo-application/build/ExpoApplication.d.ts | 6 +----- packages/expo-av/build/ExpoVideoManager.d.ts | 6 +----- packages/expo-av/build/ExponentAV.d.ts | 6 +----- .../build/ExpoBarCodeScannerModule.d.ts | 6 +----- packages/expo-battery/build/ExpoBattery.d.ts | 6 +----- .../expo-bluetooth/build/ExpoBluetooth/ExpoBluetooth.d.ts | 6 +----- packages/expo-brightness/build/ExpoBrightness.d.ts | 6 +----- packages/expo-calendar/build/ExpoCalendar.d.ts | 6 +----- packages/expo-cellular/build/ExpoCellular.d.ts | 6 +----- packages/expo-constants/build/ExponentConstants.d.ts | 6 +----- packages/expo-contacts/build/ExpoContacts.d.ts | 6 +----- packages/expo-crypto/build/ExpoCrypto.d.ts | 6 +----- packages/expo-device/build/ExpoDevice.d.ts | 6 +----- packages/expo-document-picker/build/ExpoDocumentPicker.d.ts | 6 +----- packages/expo-error-recovery/build/ExpoErrorRecovery.d.ts | 6 +----- packages/expo-face-detector/build/ExpoFaceDetector.d.ts | 6 +----- packages/expo-facebook/build/ExponentFacebook.d.ts | 6 +----- packages/expo-font/build/ExpoFontLoader.d.ts | 6 +----- packages/expo-google-sign-in/build/ExpoGoogleSignIn.d.ts | 6 +----- packages/expo-haptics/build/ExpoHaptics.d.ts | 6 +----- .../expo-image-manipulator/build/ExpoImageManipulator.d.ts | 6 +----- packages/expo-image-picker/build/ExponentImagePicker.d.ts | 6 +----- .../expo-in-app-purchases/build/ExpoInAppPurchases.d.ts | 6 +----- packages/expo-intent-launcher/build/ExpoIntentLauncher.d.ts | 6 +----- packages/expo-keep-awake/build/ExpoKeepAwake.d.ts | 6 +----- .../build/ExpoLocalAuthentication.d.ts | 6 +----- packages/expo-localization/build/ExpoLocalization.d.ts | 6 +----- packages/expo-location/build/ExpoLocation.d.ts | 6 +----- packages/expo-mail-composer/build/ExpoMailComposer.d.ts | 6 +----- packages/expo-media-library/build/ExponentMediaLibrary.d.ts | 6 +----- packages/expo-network/build/ExpoNetwork.d.ts | 6 +----- packages/expo-permissions/build/ExpoPermissions.d.ts | 6 +----- packages/expo-print/build/ExponentPrint.d.ts | 6 +----- packages/expo-random/build/ExpoRandom.d.ts | 6 +----- packages/expo-secure-store/build/ExpoSecureStore.d.ts | 6 +----- packages/expo-sensors/build/ExpoBarometer.d.ts | 6 +----- packages/expo-sensors/build/ExponentAccelerometer.d.ts | 6 +----- packages/expo-sensors/build/ExponentDeviceMotion.d.ts | 6 +----- packages/expo-sensors/build/ExponentGyroscope.d.ts | 6 +----- packages/expo-sensors/build/ExponentMagnetometer.d.ts | 6 +----- .../build/ExponentMagnetometerUncalibrated.d.ts | 6 +----- packages/expo-sensors/build/ExponentPedometer.d.ts | 6 +----- packages/expo-sharing/build/ExpoSharing.d.ts | 6 +----- packages/expo-sms/build/ExpoSMS.d.ts | 6 +----- packages/expo-speech/build/ExponentSpeech.d.ts | 6 +----- packages/expo-store-review/build/ExpoStoreReview.d.ts | 6 +----- packages/expo-task-manager/build/ExpoTaskManager.d.ts | 6 +----- .../expo-video-thumbnails/build/ExpoVideoThumbnails.d.ts | 6 +----- packages/expo-web-browser/build/ExpoWebBrowser.d.ts | 6 +----- 62 files changed, 64 insertions(+), 287 deletions(-) diff --git a/packages/@unimodules/react-native-adapter/build/NativeModulesProxy.d.ts b/packages/@unimodules/react-native-adapter/build/NativeModulesProxy.d.ts index c78081a65613e..0b735457fef41 100644 --- a/packages/@unimodules/react-native-adapter/build/NativeModulesProxy.d.ts +++ b/packages/@unimodules/react-native-adapter/build/NativeModulesProxy.d.ts @@ -1,4 +1,4 @@ -declare type ProxyNativeModule = { +export declare type ProxyNativeModule = { [propertyName: string]: any; addListener: (eventName: string) => void; removeListeners: (count: number) => void; diff --git a/packages/@unimodules/react-native-adapter/build/NativeModulesProxy.js.map b/packages/@unimodules/react-native-adapter/build/NativeModulesProxy.js.map index bf5cb096584c8..fca27d6275477 100644 --- a/packages/@unimodules/react-native-adapter/build/NativeModulesProxy.js.map +++ b/packages/@unimodules/react-native-adapter/build/NativeModulesProxy.js.map @@ -1 +1 @@ -{"version":3,"file":"NativeModulesProxy.js","sourceRoot":"","sources":["../src/NativeModulesProxy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,WAAW,GAAG,aAAa,CAAC,oBAAoB,CAAC;AACvD,MAAM,mBAAmB,GAAG,kBAAkB,CAAC;AAC/C,MAAM,kBAAkB,GAAG,iBAAiB,CAAC;AAQ7C,MAAM,kBAAkB,GAAgD,EAAE,CAAC;AAE3E,IAAI,WAAW,EAAE;IACf,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE;QAChE,kBAAkB,CAAC,UAAU,CAAC,GAAG,WAAW,CAAC,mBAAmB,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QACpF,WAAW,CAAC,kBAAkB,CAAC,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE;YAC/D,kBAAkB,CAAC,UAAU,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,KAAK,EACrD,GAAG,IAAe,EACJ,EAAE;gBAChB,MAAM,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,UAAU,CAAC;gBAC3C,IAAI,cAAc,KAAK,IAAI,CAAC,MAAM,EAAE;oBAClC,MAAM,IAAI,KAAK,CACb,iBAAiB,UAAU,IAAI,UAAU,CAAC,IAAI,YAAY,cAAc,IACtE,cAAc,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WACtC,iBAAiB,IAAI,CAAC,MAAM,EAAE,CAC/B,CAAC;iBACH;gBACD,OAAO,MAAM,WAAW,CAAC,UAAU,CAAC,UAAU,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;YAC7D,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,+EAA+E;QAC/E,kFAAkF;QAClF,EAAE;QACF,wEAAwE;QACxE,gDAAgD;QAChD,kBAAkB,CAAC,UAAU,CAAC,CAAC,WAAW,GAAG,CAAC,GAAG,IAAI,EAAE,EAAE,CACvD,aAAa,CAAC,yBAAyB,CAAC,kBAAkB,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,CAAC;QAClF,kBAAkB,CAAC,UAAU,CAAC,CAAC,eAAe,GAAG,CAAC,GAAG,IAAI,EAAE,EAAE,CAC3D,aAAa,CAAC,yBAAyB,CAAC,sBAAsB,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,CAAC;IACxF,CAAC,CAAC,CAAC;CACJ;KAAM;IACL,OAAO,CAAC,IAAI,CACV,+JAA+J,CAChK,CAAC;CACH;AAED,eAAe,kBAAkB,CAAC","sourcesContent":["import { NativeModules } from 'react-native';\n\nconst NativeProxy = NativeModules.NativeUnimoduleProxy;\nconst modulesConstantsKey = 'modulesConstants';\nconst exportedMethodsKey = 'exportedMethods';\n\ntype ProxyNativeModule = {\n [propertyName: string]: any;\n addListener: (eventName: string) => void;\n removeListeners: (count: number) => void;\n};\n\nconst NativeModulesProxy: { [moduleName: string]: ProxyNativeModule } = {};\n\nif (NativeProxy) {\n Object.keys(NativeProxy[exportedMethodsKey]).forEach(moduleName => {\n NativeModulesProxy[moduleName] = NativeProxy[modulesConstantsKey][moduleName] || {};\n NativeProxy[exportedMethodsKey][moduleName].forEach(methodInfo => {\n NativeModulesProxy[moduleName][methodInfo.name] = async (\n ...args: unknown[]\n ): Promise => {\n const { key, argumentsCount } = methodInfo;\n if (argumentsCount !== args.length) {\n throw new Error(\n `Native method ${moduleName}.${methodInfo.name} expects ${argumentsCount} ${\n argumentsCount === 1 ? 'argument' : 'arguments'\n } but received ${args.length}`\n );\n }\n return await NativeProxy.callMethod(moduleName, key, args);\n };\n });\n\n // These are called by EventEmitter (which is a wrapper for NativeEventEmitter)\n // only on iOS and they use iOS-specific native module, EXReactNativeEventEmitter.\n //\n // On Android only {start,stop}Observing are called on the native module\n // and these should be exported as Expo methods.\n NativeModulesProxy[moduleName].addListener = (...args) =>\n NativeModules.UMReactNativeEventEmitter.addProxiedListener(moduleName, ...args);\n NativeModulesProxy[moduleName].removeListeners = (...args) =>\n NativeModules.UMReactNativeEventEmitter.removeProxiedListeners(moduleName, ...args);\n });\n} else {\n console.warn(\n `The \"UMNativeModulesProxy\" native module is not exported through NativeModules; verify that @unimodules/react-native-adapter's native code is linked properly`\n );\n}\n\nexport default NativeModulesProxy;\n"]} \ No newline at end of file +{"version":3,"file":"NativeModulesProxy.js","sourceRoot":"","sources":["../src/NativeModulesProxy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,WAAW,GAAG,aAAa,CAAC,oBAAoB,CAAC;AACvD,MAAM,mBAAmB,GAAG,kBAAkB,CAAC;AAC/C,MAAM,kBAAkB,GAAG,iBAAiB,CAAC;AAQ7C,MAAM,kBAAkB,GAAgD,EAAE,CAAC;AAE3E,IAAI,WAAW,EAAE;IACf,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE;QAChE,kBAAkB,CAAC,UAAU,CAAC,GAAG,WAAW,CAAC,mBAAmB,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QACpF,WAAW,CAAC,kBAAkB,CAAC,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE;YAC/D,kBAAkB,CAAC,UAAU,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,KAAK,EACrD,GAAG,IAAe,EACJ,EAAE;gBAChB,MAAM,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,UAAU,CAAC;gBAC3C,IAAI,cAAc,KAAK,IAAI,CAAC,MAAM,EAAE;oBAClC,MAAM,IAAI,KAAK,CACb,iBAAiB,UAAU,IAAI,UAAU,CAAC,IAAI,YAAY,cAAc,IACtE,cAAc,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WACtC,iBAAiB,IAAI,CAAC,MAAM,EAAE,CAC/B,CAAC;iBACH;gBACD,OAAO,MAAM,WAAW,CAAC,UAAU,CAAC,UAAU,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;YAC7D,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,+EAA+E;QAC/E,kFAAkF;QAClF,EAAE;QACF,wEAAwE;QACxE,gDAAgD;QAChD,kBAAkB,CAAC,UAAU,CAAC,CAAC,WAAW,GAAG,CAAC,GAAG,IAAI,EAAE,EAAE,CACvD,aAAa,CAAC,yBAAyB,CAAC,kBAAkB,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,CAAC;QAClF,kBAAkB,CAAC,UAAU,CAAC,CAAC,eAAe,GAAG,CAAC,GAAG,IAAI,EAAE,EAAE,CAC3D,aAAa,CAAC,yBAAyB,CAAC,sBAAsB,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,CAAC;IACxF,CAAC,CAAC,CAAC;CACJ;KAAM;IACL,OAAO,CAAC,IAAI,CACV,+JAA+J,CAChK,CAAC;CACH;AAED,eAAe,kBAAkB,CAAC","sourcesContent":["import { NativeModules } from 'react-native';\n\nconst NativeProxy = NativeModules.NativeUnimoduleProxy;\nconst modulesConstantsKey = 'modulesConstants';\nconst exportedMethodsKey = 'exportedMethods';\n\nexport type ProxyNativeModule = {\n [propertyName: string]: any;\n addListener: (eventName: string) => void;\n removeListeners: (count: number) => void;\n};\n\nconst NativeModulesProxy: { [moduleName: string]: ProxyNativeModule } = {};\n\nif (NativeProxy) {\n Object.keys(NativeProxy[exportedMethodsKey]).forEach(moduleName => {\n NativeModulesProxy[moduleName] = NativeProxy[modulesConstantsKey][moduleName] || {};\n NativeProxy[exportedMethodsKey][moduleName].forEach(methodInfo => {\n NativeModulesProxy[moduleName][methodInfo.name] = async (\n ...args: unknown[]\n ): Promise => {\n const { key, argumentsCount } = methodInfo;\n if (argumentsCount !== args.length) {\n throw new Error(\n `Native method ${moduleName}.${methodInfo.name} expects ${argumentsCount} ${\n argumentsCount === 1 ? 'argument' : 'arguments'\n } but received ${args.length}`\n );\n }\n return await NativeProxy.callMethod(moduleName, key, args);\n };\n });\n\n // These are called by EventEmitter (which is a wrapper for NativeEventEmitter)\n // only on iOS and they use iOS-specific native module, EXReactNativeEventEmitter.\n //\n // On Android only {start,stop}Observing are called on the native module\n // and these should be exported as Expo methods.\n NativeModulesProxy[moduleName].addListener = (...args) =>\n NativeModules.UMReactNativeEventEmitter.addProxiedListener(moduleName, ...args);\n NativeModulesProxy[moduleName].removeListeners = (...args) =>\n NativeModules.UMReactNativeEventEmitter.removeProxiedListeners(moduleName, ...args);\n });\n} else {\n console.warn(\n `The \"UMNativeModulesProxy\" native module is not exported through NativeModules; verify that @unimodules/react-native-adapter's native code is linked properly`\n );\n}\n\nexport default NativeModulesProxy;\n"]} \ No newline at end of file diff --git a/packages/@unimodules/react-native-adapter/build/index.d.ts b/packages/@unimodules/react-native-adapter/build/index.d.ts index d1e455e2aca8b..59815ce003fff 100644 --- a/packages/@unimodules/react-native-adapter/build/index.d.ts +++ b/packages/@unimodules/react-native-adapter/build/index.d.ts @@ -1,9 +1,9 @@ import { EventEmitter, Subscription } from './EventEmitter'; -import NativeModulesProxy from './NativeModulesProxy'; +import NativeModulesProxy, { ProxyNativeModule } from './NativeModulesProxy'; import { requireNativeViewManager } from './NativeViewManagerAdapter'; import Platform from './Platform'; import SyntheticPlatformEmitter from './SyntheticPlatformEmitter'; import { RCTDeviceEventEmitter } from './nativeEmitters'; import { CodedError } from './errors/CodedError'; import { UnavailabilityError } from './errors/UnavailabilityError'; -export { RCTDeviceEventEmitter, EventEmitter, NativeModulesProxy, Platform, Subscription, SyntheticPlatformEmitter, requireNativeViewManager, CodedError, UnavailabilityError, }; +export { RCTDeviceEventEmitter, EventEmitter, NativeModulesProxy, ProxyNativeModule, Platform, Subscription, SyntheticPlatformEmitter, requireNativeViewManager, CodedError, UnavailabilityError, }; diff --git a/packages/@unimodules/react-native-adapter/build/index.js.map b/packages/@unimodules/react-native-adapter/build/index.js.map index fc3a7cee517f3..339cfff671d28 100644 --- a/packages/@unimodules/react-native-adapter/build/index.js.map +++ b/packages/@unimodules/react-native-adapter/build/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAgB,MAAM,gBAAgB,CAAC;AAC5D,OAAO,kBAAkB,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,QAAQ,MAAM,YAAY,CAAC;AAClC,OAAO,wBAAwB,MAAM,4BAA4B,CAAC;AAElE,sFAAsF;AACtF,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAEnE,OAAO,EACL,qBAAqB,EACrB,YAAY,EACZ,kBAAkB,EAClB,QAAQ,EAER,wBAAwB,EACxB,wBAAwB;AACxB,SAAS;AACT,UAAU,EACV,mBAAmB,GACpB,CAAC","sourcesContent":["import { EventEmitter, Subscription } from './EventEmitter';\nimport NativeModulesProxy from './NativeModulesProxy';\nimport { requireNativeViewManager } from './NativeViewManagerAdapter';\nimport Platform from './Platform';\nimport SyntheticPlatformEmitter from './SyntheticPlatformEmitter';\n\n// RCTDeviceEventEmitter pending https://github.com/necolas/react-native-web/pull/1402\nimport { RCTDeviceEventEmitter } from './nativeEmitters';\n\nimport { CodedError } from './errors/CodedError';\nimport { UnavailabilityError } from './errors/UnavailabilityError';\n\nexport {\n RCTDeviceEventEmitter,\n EventEmitter,\n NativeModulesProxy,\n Platform,\n Subscription,\n SyntheticPlatformEmitter,\n requireNativeViewManager,\n // Errors\n CodedError,\n UnavailabilityError,\n};\n"]} \ No newline at end of file +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAgB,MAAM,gBAAgB,CAAC;AAC5D,OAAO,kBAAyC,MAAM,sBAAsB,CAAC;AAC7E,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,QAAQ,MAAM,YAAY,CAAC;AAClC,OAAO,wBAAwB,MAAM,4BAA4B,CAAC;AAElE,sFAAsF;AACtF,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAEnE,OAAO,EACL,qBAAqB,EACrB,YAAY,EACZ,kBAAkB,EAElB,QAAQ,EAER,wBAAwB,EACxB,wBAAwB;AACxB,SAAS;AACT,UAAU,EACV,mBAAmB,GACpB,CAAC","sourcesContent":["import { EventEmitter, Subscription } from './EventEmitter';\nimport NativeModulesProxy, { ProxyNativeModule } from './NativeModulesProxy';\nimport { requireNativeViewManager } from './NativeViewManagerAdapter';\nimport Platform from './Platform';\nimport SyntheticPlatformEmitter from './SyntheticPlatformEmitter';\n\n// RCTDeviceEventEmitter pending https://github.com/necolas/react-native-web/pull/1402\nimport { RCTDeviceEventEmitter } from './nativeEmitters';\n\nimport { CodedError } from './errors/CodedError';\nimport { UnavailabilityError } from './errors/UnavailabilityError';\n\nexport {\n RCTDeviceEventEmitter,\n EventEmitter,\n NativeModulesProxy,\n ProxyNativeModule,\n Platform,\n Subscription,\n SyntheticPlatformEmitter,\n requireNativeViewManager,\n // Errors\n CodedError,\n UnavailabilityError,\n};\n"]} \ No newline at end of file diff --git a/packages/@unimodules/react-native-adapter/src/NativeModulesProxy.ts b/packages/@unimodules/react-native-adapter/src/NativeModulesProxy.ts index 4c53cd62700ba..5d6bed468d2cd 100644 --- a/packages/@unimodules/react-native-adapter/src/NativeModulesProxy.ts +++ b/packages/@unimodules/react-native-adapter/src/NativeModulesProxy.ts @@ -4,7 +4,7 @@ const NativeProxy = NativeModules.NativeUnimoduleProxy; const modulesConstantsKey = 'modulesConstants'; const exportedMethodsKey = 'exportedMethods'; -type ProxyNativeModule = { +export type ProxyNativeModule = { [propertyName: string]: any; addListener: (eventName: string) => void; removeListeners: (count: number) => void; diff --git a/packages/@unimodules/react-native-adapter/src/index.ts b/packages/@unimodules/react-native-adapter/src/index.ts index e85782fcb9e2f..f1bbb6e935f3c 100644 --- a/packages/@unimodules/react-native-adapter/src/index.ts +++ b/packages/@unimodules/react-native-adapter/src/index.ts @@ -1,5 +1,5 @@ import { EventEmitter, Subscription } from './EventEmitter'; -import NativeModulesProxy from './NativeModulesProxy'; +import NativeModulesProxy, { ProxyNativeModule } from './NativeModulesProxy'; import { requireNativeViewManager } from './NativeViewManagerAdapter'; import Platform from './Platform'; import SyntheticPlatformEmitter from './SyntheticPlatformEmitter'; @@ -14,6 +14,7 @@ export { RCTDeviceEventEmitter, EventEmitter, NativeModulesProxy, + ProxyNativeModule, Platform, Subscription, SyntheticPlatformEmitter, diff --git a/packages/expo-ads-admob/build/ExpoAdsAdMob.d.ts b/packages/expo-ads-admob/build/ExpoAdsAdMob.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-ads-admob/build/ExpoAdsAdMob.d.ts +++ b/packages/expo-ads-admob/build/ExpoAdsAdMob.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-ads-admob/build/ExpoAdsAdMobInterstitialManager.d.ts b/packages/expo-ads-admob/build/ExpoAdsAdMobInterstitialManager.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-ads-admob/build/ExpoAdsAdMobInterstitialManager.d.ts +++ b/packages/expo-ads-admob/build/ExpoAdsAdMobInterstitialManager.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-ads-admob/build/ExpoAdsAdMobRewardedVideoAdManager.d.ts b/packages/expo-ads-admob/build/ExpoAdsAdMobRewardedVideoAdManager.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-ads-admob/build/ExpoAdsAdMobRewardedVideoAdManager.d.ts +++ b/packages/expo-ads-admob/build/ExpoAdsAdMobRewardedVideoAdManager.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-analytics-amplitude/build/ExpoAmplitude.d.ts b/packages/expo-analytics-amplitude/build/ExpoAmplitude.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-analytics-amplitude/build/ExpoAmplitude.d.ts +++ b/packages/expo-analytics-amplitude/build/ExpoAmplitude.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-analytics-segment/build/ExponentSegment.d.ts b/packages/expo-analytics-segment/build/ExponentSegment.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-analytics-segment/build/ExponentSegment.d.ts +++ b/packages/expo-analytics-segment/build/ExponentSegment.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-app-auth/build/ExpoAppAuth.d.ts b/packages/expo-app-auth/build/ExpoAppAuth.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-app-auth/build/ExpoAppAuth.d.ts +++ b/packages/expo-app-auth/build/ExpoAppAuth.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-apple-authentication/build/ExpoAppleAuthentication.d.ts b/packages/expo-apple-authentication/build/ExpoAppleAuthentication.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-apple-authentication/build/ExpoAppleAuthentication.d.ts +++ b/packages/expo-apple-authentication/build/ExpoAppleAuthentication.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-application/build/ExpoApplication.d.ts b/packages/expo-application/build/ExpoApplication.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-application/build/ExpoApplication.d.ts +++ b/packages/expo-application/build/ExpoApplication.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-av/build/ExpoVideoManager.d.ts b/packages/expo-av/build/ExpoVideoManager.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-av/build/ExpoVideoManager.d.ts +++ b/packages/expo-av/build/ExpoVideoManager.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-av/build/ExponentAV.d.ts b/packages/expo-av/build/ExponentAV.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-av/build/ExponentAV.d.ts +++ b/packages/expo-av/build/ExponentAV.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-barcode-scanner/build/ExpoBarCodeScannerModule.d.ts b/packages/expo-barcode-scanner/build/ExpoBarCodeScannerModule.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-barcode-scanner/build/ExpoBarCodeScannerModule.d.ts +++ b/packages/expo-barcode-scanner/build/ExpoBarCodeScannerModule.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-battery/build/ExpoBattery.d.ts b/packages/expo-battery/build/ExpoBattery.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-battery/build/ExpoBattery.d.ts +++ b/packages/expo-battery/build/ExpoBattery.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-bluetooth/build/ExpoBluetooth/ExpoBluetooth.d.ts b/packages/expo-bluetooth/build/ExpoBluetooth/ExpoBluetooth.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-bluetooth/build/ExpoBluetooth/ExpoBluetooth.d.ts +++ b/packages/expo-bluetooth/build/ExpoBluetooth/ExpoBluetooth.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-brightness/build/ExpoBrightness.d.ts b/packages/expo-brightness/build/ExpoBrightness.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-brightness/build/ExpoBrightness.d.ts +++ b/packages/expo-brightness/build/ExpoBrightness.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-calendar/build/ExpoCalendar.d.ts b/packages/expo-calendar/build/ExpoCalendar.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-calendar/build/ExpoCalendar.d.ts +++ b/packages/expo-calendar/build/ExpoCalendar.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-cellular/build/ExpoCellular.d.ts b/packages/expo-cellular/build/ExpoCellular.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-cellular/build/ExpoCellular.d.ts +++ b/packages/expo-cellular/build/ExpoCellular.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-constants/build/ExponentConstants.d.ts b/packages/expo-constants/build/ExponentConstants.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-constants/build/ExponentConstants.d.ts +++ b/packages/expo-constants/build/ExponentConstants.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-contacts/build/ExpoContacts.d.ts b/packages/expo-contacts/build/ExpoContacts.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-contacts/build/ExpoContacts.d.ts +++ b/packages/expo-contacts/build/ExpoContacts.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-crypto/build/ExpoCrypto.d.ts b/packages/expo-crypto/build/ExpoCrypto.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-crypto/build/ExpoCrypto.d.ts +++ b/packages/expo-crypto/build/ExpoCrypto.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-device/build/ExpoDevice.d.ts b/packages/expo-device/build/ExpoDevice.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-device/build/ExpoDevice.d.ts +++ b/packages/expo-device/build/ExpoDevice.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-document-picker/build/ExpoDocumentPicker.d.ts b/packages/expo-document-picker/build/ExpoDocumentPicker.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-document-picker/build/ExpoDocumentPicker.d.ts +++ b/packages/expo-document-picker/build/ExpoDocumentPicker.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-error-recovery/build/ExpoErrorRecovery.d.ts b/packages/expo-error-recovery/build/ExpoErrorRecovery.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-error-recovery/build/ExpoErrorRecovery.d.ts +++ b/packages/expo-error-recovery/build/ExpoErrorRecovery.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-face-detector/build/ExpoFaceDetector.d.ts b/packages/expo-face-detector/build/ExpoFaceDetector.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-face-detector/build/ExpoFaceDetector.d.ts +++ b/packages/expo-face-detector/build/ExpoFaceDetector.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-facebook/build/ExponentFacebook.d.ts b/packages/expo-facebook/build/ExponentFacebook.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-facebook/build/ExponentFacebook.d.ts +++ b/packages/expo-facebook/build/ExponentFacebook.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-font/build/ExpoFontLoader.d.ts b/packages/expo-font/build/ExpoFontLoader.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-font/build/ExpoFontLoader.d.ts +++ b/packages/expo-font/build/ExpoFontLoader.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-google-sign-in/build/ExpoGoogleSignIn.d.ts b/packages/expo-google-sign-in/build/ExpoGoogleSignIn.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-google-sign-in/build/ExpoGoogleSignIn.d.ts +++ b/packages/expo-google-sign-in/build/ExpoGoogleSignIn.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-haptics/build/ExpoHaptics.d.ts b/packages/expo-haptics/build/ExpoHaptics.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-haptics/build/ExpoHaptics.d.ts +++ b/packages/expo-haptics/build/ExpoHaptics.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-image-manipulator/build/ExpoImageManipulator.d.ts b/packages/expo-image-manipulator/build/ExpoImageManipulator.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-image-manipulator/build/ExpoImageManipulator.d.ts +++ b/packages/expo-image-manipulator/build/ExpoImageManipulator.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-image-picker/build/ExponentImagePicker.d.ts b/packages/expo-image-picker/build/ExponentImagePicker.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-image-picker/build/ExponentImagePicker.d.ts +++ b/packages/expo-image-picker/build/ExponentImagePicker.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-in-app-purchases/build/ExpoInAppPurchases.d.ts b/packages/expo-in-app-purchases/build/ExpoInAppPurchases.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-in-app-purchases/build/ExpoInAppPurchases.d.ts +++ b/packages/expo-in-app-purchases/build/ExpoInAppPurchases.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-intent-launcher/build/ExpoIntentLauncher.d.ts b/packages/expo-intent-launcher/build/ExpoIntentLauncher.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-intent-launcher/build/ExpoIntentLauncher.d.ts +++ b/packages/expo-intent-launcher/build/ExpoIntentLauncher.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-keep-awake/build/ExpoKeepAwake.d.ts b/packages/expo-keep-awake/build/ExpoKeepAwake.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-keep-awake/build/ExpoKeepAwake.d.ts +++ b/packages/expo-keep-awake/build/ExpoKeepAwake.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-local-authentication/build/ExpoLocalAuthentication.d.ts b/packages/expo-local-authentication/build/ExpoLocalAuthentication.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-local-authentication/build/ExpoLocalAuthentication.d.ts +++ b/packages/expo-local-authentication/build/ExpoLocalAuthentication.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-localization/build/ExpoLocalization.d.ts b/packages/expo-localization/build/ExpoLocalization.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-localization/build/ExpoLocalization.d.ts +++ b/packages/expo-localization/build/ExpoLocalization.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-location/build/ExpoLocation.d.ts b/packages/expo-location/build/ExpoLocation.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-location/build/ExpoLocation.d.ts +++ b/packages/expo-location/build/ExpoLocation.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-mail-composer/build/ExpoMailComposer.d.ts b/packages/expo-mail-composer/build/ExpoMailComposer.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-mail-composer/build/ExpoMailComposer.d.ts +++ b/packages/expo-mail-composer/build/ExpoMailComposer.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-media-library/build/ExponentMediaLibrary.d.ts b/packages/expo-media-library/build/ExponentMediaLibrary.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-media-library/build/ExponentMediaLibrary.d.ts +++ b/packages/expo-media-library/build/ExponentMediaLibrary.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-network/build/ExpoNetwork.d.ts b/packages/expo-network/build/ExpoNetwork.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-network/build/ExpoNetwork.d.ts +++ b/packages/expo-network/build/ExpoNetwork.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-permissions/build/ExpoPermissions.d.ts b/packages/expo-permissions/build/ExpoPermissions.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-permissions/build/ExpoPermissions.d.ts +++ b/packages/expo-permissions/build/ExpoPermissions.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-print/build/ExponentPrint.d.ts b/packages/expo-print/build/ExponentPrint.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-print/build/ExponentPrint.d.ts +++ b/packages/expo-print/build/ExponentPrint.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-random/build/ExpoRandom.d.ts b/packages/expo-random/build/ExpoRandom.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-random/build/ExpoRandom.d.ts +++ b/packages/expo-random/build/ExpoRandom.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-secure-store/build/ExpoSecureStore.d.ts b/packages/expo-secure-store/build/ExpoSecureStore.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-secure-store/build/ExpoSecureStore.d.ts +++ b/packages/expo-secure-store/build/ExpoSecureStore.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-sensors/build/ExpoBarometer.d.ts b/packages/expo-sensors/build/ExpoBarometer.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-sensors/build/ExpoBarometer.d.ts +++ b/packages/expo-sensors/build/ExpoBarometer.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-sensors/build/ExponentAccelerometer.d.ts b/packages/expo-sensors/build/ExponentAccelerometer.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-sensors/build/ExponentAccelerometer.d.ts +++ b/packages/expo-sensors/build/ExponentAccelerometer.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-sensors/build/ExponentDeviceMotion.d.ts b/packages/expo-sensors/build/ExponentDeviceMotion.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-sensors/build/ExponentDeviceMotion.d.ts +++ b/packages/expo-sensors/build/ExponentDeviceMotion.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-sensors/build/ExponentGyroscope.d.ts b/packages/expo-sensors/build/ExponentGyroscope.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-sensors/build/ExponentGyroscope.d.ts +++ b/packages/expo-sensors/build/ExponentGyroscope.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-sensors/build/ExponentMagnetometer.d.ts b/packages/expo-sensors/build/ExponentMagnetometer.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-sensors/build/ExponentMagnetometer.d.ts +++ b/packages/expo-sensors/build/ExponentMagnetometer.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-sensors/build/ExponentMagnetometerUncalibrated.d.ts b/packages/expo-sensors/build/ExponentMagnetometerUncalibrated.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-sensors/build/ExponentMagnetometerUncalibrated.d.ts +++ b/packages/expo-sensors/build/ExponentMagnetometerUncalibrated.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-sensors/build/ExponentPedometer.d.ts b/packages/expo-sensors/build/ExponentPedometer.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-sensors/build/ExponentPedometer.d.ts +++ b/packages/expo-sensors/build/ExponentPedometer.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-sharing/build/ExpoSharing.d.ts b/packages/expo-sharing/build/ExpoSharing.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-sharing/build/ExpoSharing.d.ts +++ b/packages/expo-sharing/build/ExpoSharing.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-sms/build/ExpoSMS.d.ts b/packages/expo-sms/build/ExpoSMS.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-sms/build/ExpoSMS.d.ts +++ b/packages/expo-sms/build/ExpoSMS.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-speech/build/ExponentSpeech.d.ts b/packages/expo-speech/build/ExponentSpeech.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-speech/build/ExponentSpeech.d.ts +++ b/packages/expo-speech/build/ExponentSpeech.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-store-review/build/ExpoStoreReview.d.ts b/packages/expo-store-review/build/ExpoStoreReview.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-store-review/build/ExpoStoreReview.d.ts +++ b/packages/expo-store-review/build/ExpoStoreReview.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-task-manager/build/ExpoTaskManager.d.ts b/packages/expo-task-manager/build/ExpoTaskManager.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-task-manager/build/ExpoTaskManager.d.ts +++ b/packages/expo-task-manager/build/ExpoTaskManager.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-video-thumbnails/build/ExpoVideoThumbnails.d.ts b/packages/expo-video-thumbnails/build/ExpoVideoThumbnails.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-video-thumbnails/build/ExpoVideoThumbnails.d.ts +++ b/packages/expo-video-thumbnails/build/ExpoVideoThumbnails.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; diff --git a/packages/expo-web-browser/build/ExpoWebBrowser.d.ts b/packages/expo-web-browser/build/ExpoWebBrowser.d.ts index ac6d5144a6b2b..468dfd2735cb7 100644 --- a/packages/expo-web-browser/build/ExpoWebBrowser.d.ts +++ b/packages/expo-web-browser/build/ExpoWebBrowser.d.ts @@ -1,6 +1,2 @@ -declare const _default: { - [propertyName: string]: any; - addListener: (eventName: string) => void; - removeListeners: (count: number) => void; -}; +declare const _default: import("@unimodules/core").ProxyNativeModule; export default _default; From cee2253dbcac0d382931dfdaa45260d53ad86a78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw=20Chmiela?= Date: Tue, 14 Jan 2020 12:47:22 +0100 Subject: [PATCH 013/103] [expo-notifications] Device push token fetching module (#6577) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Why To eventually deprecate ExpoKit. # How - created a new unimodule, disabling autolinking in the root projects - implemented `getDevicePushTokenAsync` method in TS, then in native (on iOS we rely on system framework, on Android we're using Firebase Cloud Messaging) - implemented listening to token changes ### Notable changes to TS implementation - I had to juggle around types a bit to achieve what I wanted — for TS to discriminate by `type: keyof Platform.OS` value what is the type of `data` field and at the same time to use `data: any` for unsupported platforms. Types are ready, but I needed to use [`@ts-ignore`](https://github.com/expo/expo/pull/6577/commits/0bd46874ad547f6a1f196adcfc15b6d98614d94f#diff-66b6995155cd1e190f53b012f5c2a857R43-R44) to get away with it. ### Notable changes to native implementation - we use singleton module for listening to token changes [android](https://github.com/expo/expo/pull/6577/commits/69ee9efd42ba725703fd3f30073564ad3574f1d6#diff-5f9ef5ef7358f7a9c8cc386d42ee934f), [ios](https://github.com/expo/expo/pull/6577/commits/0aa2b66e1342c4de084fc329866752b53b4a6a76#diff-f8332f28b28ad9a24e0af0cb435876c7) - on Android there's a service subclassing `FirebaseMessagingService` to which the singleton above subscribes [link](https://github.com/expo/expo/pull/6577/commits/69ee9efd42ba725703fd3f30073564ad3574f1d6#diff-b6817886a179022070e2417712503fa9) ### Notable changes to web implementation - eventually, I guess, developers would want to customize how their app responds to notifications — for this I added a `serviceWorkerPath` manifest field [commit](https://github.com/expo/expo/pull/6577/commits/82e54aeb892b30661e0f5059e64acba70e686f85) # Test Plan - tests in `test-suite` are passing on **all three platforms** (on web puppeteer has to be run in head…ful (?) mode, otherwise overriding permissions doesn't work, which is a [known issue](https://github.com/puppeteer/puppeteer/issues/3279)) - push notifications sent to device push tokens are received on **all three platforms** --- android/app/build.gradle | 1 + android/expoview/build.gradle | 1 + android/settings.gradle | 1 + .../payments/generated/BasePackageList.java | 1 + apps/bare-expo/app.json | 4 + apps/bare-expo/e2e/TestSuite-test.web.js | 12 +- .../ios/BareExpo.xcodeproj/project.pbxproj | 4 + .../ios/BareExpo/Bare Expo.entitlements | 8 + apps/bare-expo/ios/Podfile.lock | 7 + .../.project_cache/installation_cache.yaml | 21 +- .../Pods/.project_cache/metadata_cache.yaml | 4 + .../EXNotifications.xcodeproj/project.pbxproj | 405 +++ .../EXNotifications/EXPushTokenListener.h | 1 + .../EXNotifications/EXPushTokenManager.h | 1 + .../EXNotifications/EXPushTokenModule.h | 1 + .../EXNotifications/EXPushTokenListener.h | 1 + .../EXNotifications/EXPushTokenManager.h | 1 + .../EXNotifications/EXPushTokenModule.h | 1 + .../EXNotifications.podspec.json | 23 + apps/bare-expo/ios/Pods/Manifest.lock | 7 + .../ios/Pods/Pods.xcodeproj/project.pbxproj | 2206 +++++++++-------- .../EXNotifications/EXNotifications-dummy.m | 5 + .../EXNotifications-prefix.pch | 12 + .../EXNotifications/EXNotifications.xcconfig | 10 + .../Pods-BareExpo.debug.xcconfig | 6 +- .../Pods-BareExpo.release.xcconfig | 6 +- .../Pods-BareExpoTests.debug.xcconfig | 2 +- .../Pods-BareExpoTests.release.xcconfig | 2 +- apps/bare-expo/package.json | 1 + apps/test-suite/TestUtils.js | 9 +- apps/test-suite/package.json | 3 +- apps/test-suite/tests/NewNotifications.js | 58 + ios/Podfile | 1 + ios/Podfile.lock | 2 +- ios/Pods/Manifest.lock | 2 +- packages/expo-notifications/.eslintrc.js | 2 + packages/expo-notifications/.npmignore | 2 + packages/expo-notifications/README.md | 1 + .../expo-notifications/android/.gitignore | 269 ++ .../expo-notifications/android/build.gradle | 72 + .../android/src/main/AndroidManifest.xml | 12 + .../notifications/NotificationsPackage.java | 25 + .../tokens/FirebaseTokenListenerService.java | 69 + .../tokens/PushTokenManager.java | 86 + .../notifications/tokens/PushTokenModule.java | 99 + .../tokens/interfaces/PushTokenListener.java | 14 + .../tokens/interfaces/PushTokenManager.java | 22 + packages/expo-notifications/babel.config.js | 2 + .../build/PushTokenManager.d.ts | 6 + .../build/PushTokenManager.js | 3 + .../build/PushTokenManager.js.map | 1 + .../build/PushTokenManager.web.d.ts | 2 + .../build/PushTokenManager.web.js | 3 + .../build/PushTokenManager.web.js.map | 1 + .../build/TokenEmitter.d.ts | 6 + .../expo-notifications/build/TokenEmitter.js | 18 + .../build/TokenEmitter.js.map | 1 + .../build/getDevicePushTokenAsync.d.ts | 23 + .../build/getDevicePushTokenAsync.js | 11 + .../build/getDevicePushTokenAsync.js.map | 1 + .../build/getDevicePushTokenAsync.web.d.ts | 2 + .../build/getDevicePushTokenAsync.web.js | 79 + .../build/getDevicePushTokenAsync.web.js.map | 1 + packages/expo-notifications/build/index.d.ts | 2 + packages/expo-notifications/build/index.js | 3 + .../expo-notifications/build/index.js.map | 1 + .../ios/EXNotifications.podspec | 20 + .../ios/EXNotifications/EXPushTokenListener.h | 14 + .../ios/EXNotifications/EXPushTokenManager.h | 24 + .../ios/EXNotifications/EXPushTokenManager.m | 63 + .../ios/EXNotifications/EXPushTokenModule.h | 9 + .../ios/EXNotifications/EXPushTokenModule.m | 147 ++ packages/expo-notifications/package.json | 38 + .../src/PushTokenManager.ts | 7 + .../src/PushTokenManager.web.ts | 2 + .../expo-notifications/src/TokenEmitter.ts | 24 + .../src/getDevicePushTokenAsync.ts | 41 + .../src/getDevicePushTokenAsync.web.ts | 111 + packages/expo-notifications/src/index.ts | 2 + packages/expo-notifications/tsconfig.json | 9 + packages/expo-notifications/unimodule.json | 4 + 81 files changed, 3070 insertions(+), 1114 deletions(-) create mode 100644 apps/bare-expo/ios/BareExpo/Bare Expo.entitlements create mode 100644 apps/bare-expo/ios/Pods/EXNotifications.xcodeproj/project.pbxproj create mode 120000 apps/bare-expo/ios/Pods/Headers/Private/EXNotifications/EXPushTokenListener.h create mode 120000 apps/bare-expo/ios/Pods/Headers/Private/EXNotifications/EXPushTokenManager.h create mode 120000 apps/bare-expo/ios/Pods/Headers/Private/EXNotifications/EXPushTokenModule.h create mode 120000 apps/bare-expo/ios/Pods/Headers/Public/EXNotifications/EXPushTokenListener.h create mode 120000 apps/bare-expo/ios/Pods/Headers/Public/EXNotifications/EXPushTokenManager.h create mode 120000 apps/bare-expo/ios/Pods/Headers/Public/EXNotifications/EXPushTokenModule.h create mode 100644 apps/bare-expo/ios/Pods/Local Podspecs/EXNotifications.podspec.json create mode 100644 apps/bare-expo/ios/Pods/Target Support Files/EXNotifications/EXNotifications-dummy.m create mode 100644 apps/bare-expo/ios/Pods/Target Support Files/EXNotifications/EXNotifications-prefix.pch create mode 100644 apps/bare-expo/ios/Pods/Target Support Files/EXNotifications/EXNotifications.xcconfig create mode 100644 apps/test-suite/tests/NewNotifications.js create mode 100644 packages/expo-notifications/.eslintrc.js create mode 100644 packages/expo-notifications/.npmignore create mode 100644 packages/expo-notifications/README.md create mode 100644 packages/expo-notifications/android/.gitignore create mode 100644 packages/expo-notifications/android/build.gradle create mode 100644 packages/expo-notifications/android/src/main/AndroidManifest.xml create mode 100644 packages/expo-notifications/android/src/main/java/expo/modules/notifications/NotificationsPackage.java create mode 100644 packages/expo-notifications/android/src/main/java/expo/modules/notifications/tokens/FirebaseTokenListenerService.java create mode 100644 packages/expo-notifications/android/src/main/java/expo/modules/notifications/tokens/PushTokenManager.java create mode 100644 packages/expo-notifications/android/src/main/java/expo/modules/notifications/tokens/PushTokenModule.java create mode 100644 packages/expo-notifications/android/src/main/java/expo/modules/notifications/tokens/interfaces/PushTokenListener.java create mode 100644 packages/expo-notifications/android/src/main/java/expo/modules/notifications/tokens/interfaces/PushTokenManager.java create mode 100644 packages/expo-notifications/babel.config.js create mode 100644 packages/expo-notifications/build/PushTokenManager.d.ts create mode 100644 packages/expo-notifications/build/PushTokenManager.js create mode 100644 packages/expo-notifications/build/PushTokenManager.js.map create mode 100644 packages/expo-notifications/build/PushTokenManager.web.d.ts create mode 100644 packages/expo-notifications/build/PushTokenManager.web.js create mode 100644 packages/expo-notifications/build/PushTokenManager.web.js.map create mode 100644 packages/expo-notifications/build/TokenEmitter.d.ts create mode 100644 packages/expo-notifications/build/TokenEmitter.js create mode 100644 packages/expo-notifications/build/TokenEmitter.js.map create mode 100644 packages/expo-notifications/build/getDevicePushTokenAsync.d.ts create mode 100644 packages/expo-notifications/build/getDevicePushTokenAsync.js create mode 100644 packages/expo-notifications/build/getDevicePushTokenAsync.js.map create mode 100644 packages/expo-notifications/build/getDevicePushTokenAsync.web.d.ts create mode 100644 packages/expo-notifications/build/getDevicePushTokenAsync.web.js create mode 100644 packages/expo-notifications/build/getDevicePushTokenAsync.web.js.map create mode 100644 packages/expo-notifications/build/index.d.ts create mode 100644 packages/expo-notifications/build/index.js create mode 100644 packages/expo-notifications/build/index.js.map create mode 100644 packages/expo-notifications/ios/EXNotifications.podspec create mode 100644 packages/expo-notifications/ios/EXNotifications/EXPushTokenListener.h create mode 100644 packages/expo-notifications/ios/EXNotifications/EXPushTokenManager.h create mode 100644 packages/expo-notifications/ios/EXNotifications/EXPushTokenManager.m create mode 100644 packages/expo-notifications/ios/EXNotifications/EXPushTokenModule.h create mode 100644 packages/expo-notifications/ios/EXNotifications/EXPushTokenModule.m create mode 100644 packages/expo-notifications/package.json create mode 100644 packages/expo-notifications/src/PushTokenManager.ts create mode 100644 packages/expo-notifications/src/PushTokenManager.web.ts create mode 100644 packages/expo-notifications/src/TokenEmitter.ts create mode 100644 packages/expo-notifications/src/getDevicePushTokenAsync.ts create mode 100644 packages/expo-notifications/src/getDevicePushTokenAsync.web.ts create mode 100644 packages/expo-notifications/src/index.ts create mode 100644 packages/expo-notifications/tsconfig.json create mode 100644 packages/expo-notifications/unimodule.json diff --git a/android/app/build.gradle b/android/app/build.gradle index 6130ab25746b1..1f8cfa6c9d55d 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -236,6 +236,7 @@ dependencies { 'expo-module-template', 'expo-bluetooth', 'expo-in-app-purchases', + 'expo-notifications', 'expo-payments-stripe', 'expo-updates' ] diff --git a/android/expoview/build.gradle b/android/expoview/build.gradle index 9554238f1393e..77065fec77ffb 100644 --- a/android/expoview/build.gradle +++ b/android/expoview/build.gradle @@ -170,6 +170,7 @@ dependencies { exclude : [ 'expo-module-template', 'expo-bluetooth', + 'expo-notifications', 'expo-in-app-purchases', 'expo-updates', ] diff --git a/android/settings.gradle b/android/settings.gradle index 903c9bf055402..ae0f05182b45a 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -33,6 +33,7 @@ includeUnimodulesProjects( // FLAG_BEGIN_REMOVE__UPDATE_EXPOKIT - used during `et android-build-packages` // section below previous line comment flag contains modules that need to be built for `expokit-npm-package` 'expo-bluetooth', + 'expo-notifications', 'expo-in-app-purchases', 'expo-updates', // FLAG_END_REMOVE__UPDATE_EXPOKIT diff --git a/apps/bare-expo/android/app/src/main/java/dev/expo/payments/generated/BasePackageList.java b/apps/bare-expo/android/app/src/main/java/dev/expo/payments/generated/BasePackageList.java index 08d66bc091939..6fd14ed6f0ee7 100644 --- a/apps/bare-expo/android/app/src/main/java/dev/expo/payments/generated/BasePackageList.java +++ b/apps/bare-expo/android/app/src/main/java/dev/expo/payments/generated/BasePackageList.java @@ -39,6 +39,7 @@ public List getPackageList() { new expo.modules.mailcomposer.MailComposerPackage(), new expo.modules.medialibrary.MediaLibraryPackage(), new expo.modules.network.NetworkPackage(), + new expo.modules.notifications.NotificationsPackage(), new expo.modules.permissions.PermissionsPackage(), new expo.modules.print.PrintPackage(), new expo.modules.random.RandomPackage(), diff --git a/apps/bare-expo/app.json b/apps/bare-expo/app.json index f0622a85d3a20..7a5d48a36b9b0 100644 --- a/apps/bare-expo/app.json +++ b/apps/bare-expo/app.json @@ -15,6 +15,10 @@ "include": ["test-suite", "bare-expo"] } } + }, + "notification": { + "serviceWorkerPath": "/expo-service-worker.js", + "vapidPublicKey": "BNHvR05XkY5LH9GdN0GreLx2wZnK9IwNJGVmo3jujIkFni4of26E3U3fnt9nUrZfM7h0omdIHKM0eshkzTSFOWQ" } } } diff --git a/apps/bare-expo/e2e/TestSuite-test.web.js b/apps/bare-expo/e2e/TestSuite-test.web.js index ee6930e0d67b0..bcc41986e7bd1 100644 --- a/apps/bare-expo/e2e/TestSuite-test.web.js +++ b/apps/bare-expo/e2e/TestSuite-test.web.js @@ -1,4 +1,4 @@ -/* global page */ +/* global page, browser */ import { setDefaultOptions } from 'expect-puppeteer'; import config from '../jest-puppeteer.config'; @@ -19,9 +19,12 @@ const TESTS = [ 'Blur', 'LinearGradient', 'KeepAwake', + // Overridding permissions doesn't work in headless mode + // see https://github.com/puppeteer/puppeteer/issues/3279 + !config.launch.headless && 'expo-notifications', // 'Haptics', // 'SecureStore', -]; +].filter(t => t); // This is how long we allocate for the actual tests to be run after the test screen has mounted. const MIN_TIME = 50000; @@ -31,6 +34,11 @@ setDefaultOptions({ timeout: MIN_TIME * 1.5, }); +beforeAll(async () => { + const context = browser.defaultBrowserContext(); + await context.overridePermissions(config.url, ['notifications']); +}); + function matchID(id, ...props) { return expect(page).toMatchElement(`div[data-testid="${id}"]`, ...props); } diff --git a/apps/bare-expo/ios/BareExpo.xcodeproj/project.pbxproj b/apps/bare-expo/ios/BareExpo.xcodeproj/project.pbxproj index 8c2c4d2876e0f..964a23b768f10 100644 --- a/apps/bare-expo/ios/BareExpo.xcodeproj/project.pbxproj +++ b/apps/bare-expo/ios/BareExpo.xcodeproj/project.pbxproj @@ -41,6 +41,7 @@ 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = BareExpo/Info.plist; sourceTree = ""; }; 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = BareExpo/main.m; sourceTree = ""; }; 2D16E6891FA4F8E400B85C8A /* libReact.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libReact.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 31B7D64323A904E900CE18C0 /* Bare Expo.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = "Bare Expo.entitlements"; path = "BareExpo/Bare Expo.entitlements"; sourceTree = ""; }; 4ADC22B6EC034901305B8CDC /* Pods-BareExpo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BareExpo.debug.xcconfig"; path = "Target Support Files/Pods-BareExpo/Pods-BareExpo.debug.xcconfig"; sourceTree = ""; }; 70419E2A27811C660476A295 /* Pods-BareExpo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BareExpo.release.xcconfig"; path = "Target Support Files/Pods-BareExpo/Pods-BareExpo.release.xcconfig"; sourceTree = ""; }; 7EF74F8A2123893DE8D71406 /* Pods-BareExpoTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BareExpoTests.debug.xcconfig"; path = "Target Support Files/Pods-BareExpoTests/Pods-BareExpoTests.debug.xcconfig"; sourceTree = ""; }; @@ -92,6 +93,7 @@ 13B07FAE1A68108700A75B9A /* BareExpo */ = { isa = PBXGroup; children = ( + 31B7D64323A904E900CE18C0 /* Bare Expo.entitlements */, 008F07F21AC5B25A0029DE68 /* main.jsbundle */, 13B07FAF1A68108700A75B9A /* AppDelegate.h */, 13B07FB01A68108700A75B9A /* AppDelegate.m */, @@ -453,6 +455,7 @@ baseConfigurationReference = 4ADC22B6EC034901305B8CDC /* Pods-BareExpo.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = "BareExpo/Bare Expo.entitlements"; CURRENT_PROJECT_VERSION = 1; DEAD_CODE_STRIPPING = NO; DEVELOPMENT_TEAM = C8D8QTF339; @@ -474,6 +477,7 @@ baseConfigurationReference = 70419E2A27811C660476A295 /* Pods-BareExpo.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = "BareExpo/Bare Expo.entitlements"; CURRENT_PROJECT_VERSION = 1; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = C8D8QTF339; diff --git a/apps/bare-expo/ios/BareExpo/Bare Expo.entitlements b/apps/bare-expo/ios/BareExpo/Bare Expo.entitlements new file mode 100644 index 0000000000000..903def2af5306 --- /dev/null +++ b/apps/bare-expo/ios/BareExpo/Bare Expo.entitlements @@ -0,0 +1,8 @@ + + + + + aps-environment + development + + diff --git a/apps/bare-expo/ios/Podfile.lock b/apps/bare-expo/ios/Podfile.lock index 0d01c33e419cb..6ddd7f766a5c8 100644 --- a/apps/bare-expo/ios/Podfile.lock +++ b/apps/bare-expo/ios/Podfile.lock @@ -102,6 +102,8 @@ PODS: - UMPermissionsInterface - EXNetwork (2.0.0): - UMCore + - EXNotifications (1.0.0): + - UMCore - EXPermissions (8.0.0): - UMCore - UMPermissionsInterface @@ -426,6 +428,7 @@ DEPENDENCIES: - EXMailComposer (from `../../../packages/expo-mail-composer/ios`) - EXMediaLibrary (from `../../../packages/expo-media-library/ios`) - EXNetwork (from `../../../packages/expo-network/ios`) + - EXNotifications (from `../../../packages/expo-notifications/ios`) - EXPermissions (from `../../../packages/expo-permissions/ios`) - EXPrint (from `../../../packages/expo-print/ios`) - EXRandom (from `../../../packages/expo-random/ios`) @@ -593,6 +596,9 @@ EXTERNAL SOURCES: EXNetwork: :path: !ruby/object:Pathname path: "../../../packages/expo-network/ios" + EXNotifications: + :path: !ruby/object:Pathname + path: "../../../packages/expo-notifications/ios" EXPermissions: :path: !ruby/object:Pathname path: "../../../packages/expo-permissions/ios" @@ -756,6 +762,7 @@ SPEC CHECKSUMS: EXMailComposer: b9be58adaabb860fc8b722204ce27b33c7da5aad EXMediaLibrary: 9281707de8f95cc391d242b614f493ab781030fa EXNetwork: a52f713ced4b05a2634eb88a1f1f8678fcb8b69c + EXNotifications: d654494e84df90927cca410ebac178c61553647b EXPermissions: 9bc08859a675d291e89be9a0870155c27c16ac35 EXPrint: b20aef0e774d96e0ea6688b97d9e0c1d268b95ae EXRandom: 3a6f6dce1997a40a7fc3bb00d18eabc380c51c2e diff --git a/apps/bare-expo/ios/Pods/.project_cache/installation_cache.yaml b/apps/bare-expo/ios/Pods/.project_cache/installation_cache.yaml index 67c465e93b792..c4473d8cfab21 100644 --- a/apps/bare-expo/ios/Pods/.project_cache/installation_cache.yaml +++ b/apps/bare-expo/ios/Pods/.project_cache/installation_cache.yaml @@ -482,6 +482,19 @@ CACHE_KEYS: PROJECT_NAME: EXNetwork SPECS: - EXNetwork (2.0.0) + EXNotifications: + BUILD_SETTINGS_CHECKSUM: + EXNotifications: 42083d7be3b81dc87f399732a97ebffe + CHECKSUM: d654494e84df90927cca410ebac178c61553647b + FILES: + - "../../../../packages/expo-notifications/ios/EXNotifications/EXPushTokenListener.h" + - "../../../../packages/expo-notifications/ios/EXNotifications/EXPushTokenManager.h" + - "../../../../packages/expo-notifications/ios/EXNotifications/EXPushTokenManager.m" + - "../../../../packages/expo-notifications/ios/EXNotifications/EXPushTokenModule.h" + - "../../../../packages/expo-notifications/ios/EXNotifications/EXPushTokenModule.m" + PROJECT_NAME: EXNotifications + SPECS: + - EXNotifications (1.0.0) EXPermissions: BUILD_SETTINGS_CHECKSUM: EXPermissions: 042b0d307d74f9ba36a7183b44cd74a0 @@ -700,12 +713,12 @@ CACHE_KEYS: - GTMSessionFetcher/Full (1.3.0) Pods-BareExpo: BUILD_SETTINGS_CHECKSUM: - Debug: 9fa395d50ce617a2a71ed32b1caae8ef - Release: 9fa395d50ce617a2a71ed32b1caae8ef + Debug: 56436cf11abb9cf3f33b76749e92e0af + Release: 56436cf11abb9cf3f33b76749e92e0af Pods-BareExpoTests: BUILD_SETTINGS_CHECKSUM: - Debug: b61a68dc0ecf8315379a8243485d7899 - Release: b61a68dc0ecf8315379a8243485d7899 + Debug: 9af093871462b0148da322b01f112ded + Release: 9af093871462b0148da322b01f112ded RCTRequired: BUILD_SETTINGS_CHECKSUM: RCTRequired: 4dfdb65505e509cfb5f433fb54943666 diff --git a/apps/bare-expo/ios/Pods/.project_cache/metadata_cache.yaml b/apps/bare-expo/ios/Pods/.project_cache/metadata_cache.yaml index 2a4dfbff9a454..c4039f5672ae8 100644 --- a/apps/bare-expo/ios/Pods/.project_cache/metadata_cache.yaml +++ b/apps/bare-expo/ios/Pods/.project_cache/metadata_cache.yaml @@ -154,6 +154,10 @@ EXNetwork: LABEL: EXNetwork PROJECT_PATH: EXNetwork.xcodeproj UUID: 71F2A4AC24C8FBC0E24B6A613BB4F7BC +EXNotifications: + LABEL: EXNotifications + PROJECT_PATH: EXNotifications.xcodeproj + UUID: 6C660F81CE4F0EC96D208B20C3E8B154 EXPermissions: LABEL: EXPermissions PROJECT_PATH: EXPermissions.xcodeproj diff --git a/apps/bare-expo/ios/Pods/EXNotifications.xcodeproj/project.pbxproj b/apps/bare-expo/ios/Pods/EXNotifications.xcodeproj/project.pbxproj new file mode 100644 index 0000000000000..bf5ea2b5d3922 --- /dev/null +++ b/apps/bare-expo/ios/Pods/EXNotifications.xcodeproj/project.pbxproj @@ -0,0 +1,405 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 031E0786AE7DA5012377EEA2E4DDCA9D /* EXNotifications-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 97F761B442D5FD846C53C2082656EF00 /* EXNotifications-dummy.m */; }; + 13AA2027AA62EA38846BF6CC06D15019 /* EXPushTokenManager.h in Headers */ = {isa = PBXBuildFile; fileRef = EA3B3488E0B12AA023AC3DB7A77A65ED /* EXPushTokenManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 17BB77DD1F219711788D64C3F8EE7ED0 /* EXPushTokenListener.h in Headers */ = {isa = PBXBuildFile; fileRef = C4889B8D11F43B40986F975FE4262907 /* EXPushTokenListener.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7FD62BE25AB9D99451855741E2005DC6 /* EXPushTokenManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 733042F9597C31BCE53FD75EFF73F52E /* EXPushTokenManager.m */; }; + A6985ACD9FBE244E9C4C2D100CE1CDC2 /* EXPushTokenModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 60637594D8ABDAA802B620C019A49330 /* EXPushTokenModule.m */; }; + AB6756E5B35914AA056E4D24ED7531B4 /* EXPushTokenModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 736825122FE005F2F529ED1F4D6ACDCE /* EXPushTokenModule.h */; settings = {ATTRIBUTES = (Project, ); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 230B559F9E34EDC587CA27438564E946 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 6B4054ABD2AFCAF4186CB91DD1245387 /* UMCore.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 153171642F5C5CBC05FD3EF6B23A3F36; + remoteInfo = UMCore; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 1E0C15E3A464A48CE07C5530547F8674 /* EXNotifications.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = EXNotifications.xcconfig; sourceTree = ""; }; + 60637594D8ABDAA802B620C019A49330 /* EXPushTokenModule.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = EXPushTokenModule.m; path = EXNotifications/EXPushTokenModule.m; sourceTree = ""; }; + 686AC224CB480A164AD980F32DF0507A /* EXNotifications.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = EXNotifications.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 6B4054ABD2AFCAF4186CB91DD1245387 /* UMCore */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = UMCore; path = UMCore.xcodeproj; sourceTree = ""; }; + 733042F9597C31BCE53FD75EFF73F52E /* EXPushTokenManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = EXPushTokenManager.m; path = EXNotifications/EXPushTokenManager.m; sourceTree = ""; }; + 736825122FE005F2F529ED1F4D6ACDCE /* EXPushTokenModule.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = EXPushTokenModule.h; path = EXNotifications/EXPushTokenModule.h; sourceTree = ""; }; + 97F761B442D5FD846C53C2082656EF00 /* EXNotifications-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "EXNotifications-dummy.m"; sourceTree = ""; }; + AB4F468E1EA9333F76F8937368ACD772 /* libEXNotifications.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = libEXNotifications.a; path = libEXNotifications.a; sourceTree = BUILT_PRODUCTS_DIR; }; + C4889B8D11F43B40986F975FE4262907 /* EXPushTokenListener.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = EXPushTokenListener.h; path = EXNotifications/EXPushTokenListener.h; sourceTree = ""; }; + E246387DCE73F6475A2EEB6CA97169EE /* EXNotifications-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "EXNotifications-prefix.pch"; sourceTree = ""; }; + EA3B3488E0B12AA023AC3DB7A77A65ED /* EXPushTokenManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = EXPushTokenManager.h; path = EXNotifications/EXPushTokenManager.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 16C2569AEF74FEE07FC31E849CE8A5DD /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 11C75FA9F6E7BD19025CAA04B578E04E /* Products */ = { + isa = PBXGroup; + children = ( + AB4F468E1EA9333F76F8937368ACD772 /* libEXNotifications.a */, + ); + name = Products; + sourceTree = ""; + }; + 13F8C991E3E04DEA0BE15C158F3C5F7E = { + isa = PBXGroup; + children = ( + DE5C7B94E024D27CF89F5138081ED80B /* Dependencies */, + CF7FF0EB26DABE36657A6655A1A49E87 /* EXNotifications */, + CCE96D56F43E72270B9F3BEC1866196F /* Frameworks */, + 11C75FA9F6E7BD19025CAA04B578E04E /* Products */, + ); + sourceTree = ""; + }; + 22BDFFED547112B9D1C62B5484945963 /* Pod */ = { + isa = PBXGroup; + children = ( + 686AC224CB480A164AD980F32DF0507A /* EXNotifications.podspec */, + ); + name = Pod; + sourceTree = ""; + }; + A594F26887607F0F6E6DC63A8503C80B /* Support Files */ = { + isa = PBXGroup; + children = ( + 1E0C15E3A464A48CE07C5530547F8674 /* EXNotifications.xcconfig */, + 97F761B442D5FD846C53C2082656EF00 /* EXNotifications-dummy.m */, + E246387DCE73F6475A2EEB6CA97169EE /* EXNotifications-prefix.pch */, + ); + name = "Support Files"; + path = "../../../apps/bare-expo/ios/Pods/Target Support Files/EXNotifications"; + sourceTree = ""; + }; + CCE96D56F43E72270B9F3BEC1866196F /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; + CF7FF0EB26DABE36657A6655A1A49E87 /* EXNotifications */ = { + isa = PBXGroup; + children = ( + C4889B8D11F43B40986F975FE4262907 /* EXPushTokenListener.h */, + EA3B3488E0B12AA023AC3DB7A77A65ED /* EXPushTokenManager.h */, + 733042F9597C31BCE53FD75EFF73F52E /* EXPushTokenManager.m */, + 736825122FE005F2F529ED1F4D6ACDCE /* EXPushTokenModule.h */, + 60637594D8ABDAA802B620C019A49330 /* EXPushTokenModule.m */, + 22BDFFED547112B9D1C62B5484945963 /* Pod */, + A594F26887607F0F6E6DC63A8503C80B /* Support Files */, + ); + name = EXNotifications; + path = "../../../../packages/expo-notifications/ios"; + sourceTree = ""; + }; + DE5C7B94E024D27CF89F5138081ED80B /* Dependencies */ = { + isa = PBXGroup; + children = ( + 6B4054ABD2AFCAF4186CB91DD1245387 /* UMCore */, + ); + name = Dependencies; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 09C0CF8D1357A2747F9FD31AD960F5A7 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 17BB77DD1F219711788D64C3F8EE7ED0 /* EXPushTokenListener.h in Headers */, + 13AA2027AA62EA38846BF6CC06D15019 /* EXPushTokenManager.h in Headers */, + AB6756E5B35914AA056E4D24ED7531B4 /* EXPushTokenModule.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 6C660F81CE4F0EC96D208B20C3E8B154 /* EXNotifications */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4E4A3056D2F07C040C9A9D54FA1585DD /* Build configuration list for PBXNativeTarget "EXNotifications" */; + buildPhases = ( + 09C0CF8D1357A2747F9FD31AD960F5A7 /* Headers */, + 85E426ED953D87F859EB811194B979A0 /* Sources */, + 16C2569AEF74FEE07FC31E849CE8A5DD /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 5D6CF486F20FE4DC5BC6E1B130BD4E6E /* PBXTargetDependency */, + ); + name = EXNotifications; + productName = EXNotifications; + productReference = AB4F468E1EA9333F76F8937368ACD772 /* libEXNotifications.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 5E314CA8E40739B611EF78EB1939B691 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1100; + LastUpgradeCheck = 1100; + }; + buildConfigurationList = 990AC4F59C718B1E37447D25BED3BC0F /* Build configuration list for PBXProject "EXNotifications" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 13F8C991E3E04DEA0BE15C158F3C5F7E; + productRefGroup = 11C75FA9F6E7BD19025CAA04B578E04E /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProjectRef = 6B4054ABD2AFCAF4186CB91DD1245387 /* UMCore */; + }, + ); + projectRoot = ""; + targets = ( + 6C660F81CE4F0EC96D208B20C3E8B154 /* EXNotifications */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 85E426ED953D87F859EB811194B979A0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 031E0786AE7DA5012377EEA2E4DDCA9D /* EXNotifications-dummy.m in Sources */, + 7FD62BE25AB9D99451855741E2005DC6 /* EXPushTokenManager.m in Sources */, + A6985ACD9FBE244E9C4C2D100CE1CDC2 /* EXPushTokenModule.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 5D6CF486F20FE4DC5BC6E1B130BD4E6E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = UMCore; + targetProxy = 230B559F9E34EDC587CA27438564E946 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 06A68EB852A48A112EBAB52B72715E0F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_DEBUG=1", + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Debug; + }; + 9EF1858BF74D4AECDE897873D172CA6C /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1E0C15E3A464A48CE07C5530547F8674 /* EXNotifications.xcconfig */; + buildSettings = { + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + GCC_PREFIX_HEADER = "Target Support Files/EXNotifications/EXNotifications-prefix.pch"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PRIVATE_HEADERS_FOLDER_PATH = ""; + PRODUCT_MODULE_NAME = EXNotifications; + PRODUCT_NAME = EXNotifications; + PUBLIC_HEADERS_FOLDER_PATH = ""; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + C713B0E6DDE114F062471662491E7F99 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_RELEASE=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Release; + }; + CC1F977FA7A4B9D79A3B5AEED4E926DB /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1E0C15E3A464A48CE07C5530547F8674 /* EXNotifications.xcconfig */; + buildSettings = { + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + GCC_PREFIX_HEADER = "Target Support Files/EXNotifications/EXNotifications-prefix.pch"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PRIVATE_HEADERS_FOLDER_PATH = ""; + PRODUCT_MODULE_NAME = EXNotifications; + PRODUCT_NAME = EXNotifications; + PUBLIC_HEADERS_FOLDER_PATH = ""; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 4E4A3056D2F07C040C9A9D54FA1585DD /* Build configuration list for PBXNativeTarget "EXNotifications" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CC1F977FA7A4B9D79A3B5AEED4E926DB /* Debug */, + 9EF1858BF74D4AECDE897873D172CA6C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 990AC4F59C718B1E37447D25BED3BC0F /* Build configuration list for PBXProject "EXNotifications" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 06A68EB852A48A112EBAB52B72715E0F /* Debug */, + C713B0E6DDE114F062471662491E7F99 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 5E314CA8E40739B611EF78EB1939B691 /* Project object */; +} diff --git a/apps/bare-expo/ios/Pods/Headers/Private/EXNotifications/EXPushTokenListener.h b/apps/bare-expo/ios/Pods/Headers/Private/EXNotifications/EXPushTokenListener.h new file mode 120000 index 0000000000000..7c0c2194e3c25 --- /dev/null +++ b/apps/bare-expo/ios/Pods/Headers/Private/EXNotifications/EXPushTokenListener.h @@ -0,0 +1 @@ +../../../../../../../packages/expo-notifications/ios/EXNotifications/EXPushTokenListener.h \ No newline at end of file diff --git a/apps/bare-expo/ios/Pods/Headers/Private/EXNotifications/EXPushTokenManager.h b/apps/bare-expo/ios/Pods/Headers/Private/EXNotifications/EXPushTokenManager.h new file mode 120000 index 0000000000000..e0198dca9bd46 --- /dev/null +++ b/apps/bare-expo/ios/Pods/Headers/Private/EXNotifications/EXPushTokenManager.h @@ -0,0 +1 @@ +../../../../../../../packages/expo-notifications/ios/EXNotifications/EXPushTokenManager.h \ No newline at end of file diff --git a/apps/bare-expo/ios/Pods/Headers/Private/EXNotifications/EXPushTokenModule.h b/apps/bare-expo/ios/Pods/Headers/Private/EXNotifications/EXPushTokenModule.h new file mode 120000 index 0000000000000..f9ff266aafc13 --- /dev/null +++ b/apps/bare-expo/ios/Pods/Headers/Private/EXNotifications/EXPushTokenModule.h @@ -0,0 +1 @@ +../../../../../../../packages/expo-notifications/ios/EXNotifications/EXPushTokenModule.h \ No newline at end of file diff --git a/apps/bare-expo/ios/Pods/Headers/Public/EXNotifications/EXPushTokenListener.h b/apps/bare-expo/ios/Pods/Headers/Public/EXNotifications/EXPushTokenListener.h new file mode 120000 index 0000000000000..7c0c2194e3c25 --- /dev/null +++ b/apps/bare-expo/ios/Pods/Headers/Public/EXNotifications/EXPushTokenListener.h @@ -0,0 +1 @@ +../../../../../../../packages/expo-notifications/ios/EXNotifications/EXPushTokenListener.h \ No newline at end of file diff --git a/apps/bare-expo/ios/Pods/Headers/Public/EXNotifications/EXPushTokenManager.h b/apps/bare-expo/ios/Pods/Headers/Public/EXNotifications/EXPushTokenManager.h new file mode 120000 index 0000000000000..e0198dca9bd46 --- /dev/null +++ b/apps/bare-expo/ios/Pods/Headers/Public/EXNotifications/EXPushTokenManager.h @@ -0,0 +1 @@ +../../../../../../../packages/expo-notifications/ios/EXNotifications/EXPushTokenManager.h \ No newline at end of file diff --git a/apps/bare-expo/ios/Pods/Headers/Public/EXNotifications/EXPushTokenModule.h b/apps/bare-expo/ios/Pods/Headers/Public/EXNotifications/EXPushTokenModule.h new file mode 120000 index 0000000000000..f9ff266aafc13 --- /dev/null +++ b/apps/bare-expo/ios/Pods/Headers/Public/EXNotifications/EXPushTokenModule.h @@ -0,0 +1 @@ +../../../../../../../packages/expo-notifications/ios/EXNotifications/EXPushTokenModule.h \ No newline at end of file diff --git a/apps/bare-expo/ios/Pods/Local Podspecs/EXNotifications.podspec.json b/apps/bare-expo/ios/Pods/Local Podspecs/EXNotifications.podspec.json new file mode 100644 index 0000000000000..5d8e9b07c1eb3 --- /dev/null +++ b/apps/bare-expo/ios/Pods/Local Podspecs/EXNotifications.podspec.json @@ -0,0 +1,23 @@ +{ + "name": "EXNotifications", + "version": "1.0.0", + "summary": "Notifications module", + "description": "Notifications module", + "license": "MIT", + "authors": "650 Industries, Inc.", + "homepage": "https://github.com/expo/expo/tree/master/packages/expo-notifications", + "platforms": { + "ios": "10.0" + }, + "source": { + "git": "https://github.com/expo/expo.git" + }, + "source_files": "EXNotifications/**/*.{h,m}", + "preserve_paths": "EXNotifications/**/*.{h,m}", + "requires_arc": true, + "dependencies": { + "UMCore": [ + + ] + } +} diff --git a/apps/bare-expo/ios/Pods/Manifest.lock b/apps/bare-expo/ios/Pods/Manifest.lock index 0d01c33e419cb..6ddd7f766a5c8 100644 --- a/apps/bare-expo/ios/Pods/Manifest.lock +++ b/apps/bare-expo/ios/Pods/Manifest.lock @@ -102,6 +102,8 @@ PODS: - UMPermissionsInterface - EXNetwork (2.0.0): - UMCore + - EXNotifications (1.0.0): + - UMCore - EXPermissions (8.0.0): - UMCore - UMPermissionsInterface @@ -426,6 +428,7 @@ DEPENDENCIES: - EXMailComposer (from `../../../packages/expo-mail-composer/ios`) - EXMediaLibrary (from `../../../packages/expo-media-library/ios`) - EXNetwork (from `../../../packages/expo-network/ios`) + - EXNotifications (from `../../../packages/expo-notifications/ios`) - EXPermissions (from `../../../packages/expo-permissions/ios`) - EXPrint (from `../../../packages/expo-print/ios`) - EXRandom (from `../../../packages/expo-random/ios`) @@ -593,6 +596,9 @@ EXTERNAL SOURCES: EXNetwork: :path: !ruby/object:Pathname path: "../../../packages/expo-network/ios" + EXNotifications: + :path: !ruby/object:Pathname + path: "../../../packages/expo-notifications/ios" EXPermissions: :path: !ruby/object:Pathname path: "../../../packages/expo-permissions/ios" @@ -756,6 +762,7 @@ SPEC CHECKSUMS: EXMailComposer: b9be58adaabb860fc8b722204ce27b33c7da5aad EXMediaLibrary: 9281707de8f95cc391d242b614f493ab781030fa EXNetwork: a52f713ced4b05a2634eb88a1f1f8678fcb8b69c + EXNotifications: d654494e84df90927cca410ebac178c61553647b EXPermissions: 9bc08859a675d291e89be9a0870155c27c16ac35 EXPrint: b20aef0e774d96e0ea6688b97d9e0c1d268b95ae EXRandom: 3a6f6dce1997a40a7fc3bb00d18eabc380c51c2e diff --git a/apps/bare-expo/ios/Pods/Pods.xcodeproj/project.pbxproj b/apps/bare-expo/ios/Pods/Pods.xcodeproj/project.pbxproj index 0e6e0c3508918..ced8244b1413c 100644 --- a/apps/bare-expo/ios/Pods/Pods.xcodeproj/project.pbxproj +++ b/apps/bare-expo/ios/Pods/Pods.xcodeproj/project.pbxproj @@ -7,771 +7,779 @@ objects = { /* Begin PBXBuildFile section */ - 27B74A7EF0716B4AF7ECCB2F8E04A0B3 /* Pods-BareExpo-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = D090CDB16B158897ECDA29AE3E2FDBF6 /* Pods-BareExpo-dummy.m */; }; E89FBD11BA5BD749E1F14E71BC829335 /* Pods-BareExpoTests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 8465E2FC705BE47B5397BF4A39C8AC18 /* Pods-BareExpoTests-dummy.m */; }; + F2F714CCB8A26BEEAF45A7BC332B8802 /* Pods-BareExpo-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = D090CDB16B158897ECDA29AE3E2FDBF6 /* Pods-BareExpo-dummy.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 01523E2DE8178E06D1C82D6E3664203C /* PBXContainerItemProxy */ = { + 0465DF8591EAA0DA3C033AC54D14FF18 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 0143F693E54C76D9CEC9B89D39EA738C /* React-jsinspector.xcodeproj */; + containerPortal = FA3F1AFA57847B7DE0AAEDF4186FC4BF /* React-jsi.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 1AC0EAF3E808B6AA276E43B30A5B20AA; - remoteInfo = "React-jsinspector"; + remoteGlobalIDString = D0DB82AB65D33935072718EA2468992F; + remoteInfo = "React-jsi"; }; - 0353DEE60CB234F82C58A10CDC031E88 /* PBXContainerItemProxy */ = { + 06963D9ACFF76386269904DEB96637B5 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = A1A9EF9126D232C7848495ED0D34FC82 /* UMFileSystemInterface.xcodeproj */; + containerPortal = 0F4A4147605A8FA472874292E84CA8AA /* EXSMS.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 1C326487F8F888A9111422C7014319AC; - remoteInfo = UMFileSystemInterface; + remoteGlobalIDString = 1309E054CB75DA99E029D5D2C8C2210E; + remoteInfo = EXSMS; }; - 04D4A9C49B1150F6E441E4B21B87FE46 /* PBXContainerItemProxy */ = { + 071C80A0F327B444E7A3951CDF5D81F4 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 093F33B91AB6CCF24EC5B44C2168D6B7 /* RNReanimated.xcodeproj */; + containerPortal = 83741058F1FBE8278A49685754C1020B /* React-RCTSettings.xcodeproj */; proxyType = 1; - remoteGlobalIDString = E9E22639328ACC061EB56756AD5B4F57; - remoteInfo = RNReanimated; + remoteGlobalIDString = 02DD1E05F06C403A8300ABEFC2C29A3D; + remoteInfo = "React-RCTSettings"; }; - 05B0119097CB972CC8342F1A43F98833 /* PBXContainerItemProxy */ = { + 0B8C5F00B0B111D1DB9CAAE8560EF8DA /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = A14282E7B246C428EDC564624DBDD9BF /* UMBarCodeScannerInterface.xcodeproj */; + containerPortal = DD26F4B8BC160D314045C1E9FF99E1C0 /* UMFileSystemInterface.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 971E60E1AF9163E7E08105622FC91C16; - remoteInfo = UMBarCodeScannerInterface; + remoteGlobalIDString = 1C326487F8F888A9111422C7014319AC; + remoteInfo = UMFileSystemInterface; }; - 07AE4300B905F05CED560E1C5437466E /* PBXContainerItemProxy */ = { + 0DC15D8582D6A9B17EA3D24BF2A5F567 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 04AF6CFC908ABC897934A123721DCDC8 /* React-RCTImage.xcodeproj */; + containerPortal = F1BA3A37FBB21699CAA6831FD7EA7A4B /* EXBarCodeScanner.xcodeproj */; proxyType = 1; - remoteGlobalIDString = C78CA5C5EDDCCF5EC637E0FC8BB4C96E; - remoteInfo = "React-RCTImage"; + remoteGlobalIDString = E6D544E86F973F511B82FE486E5E25CD; + remoteInfo = EXBarCodeScanner; }; - 0D95C376406A62ADA46606B0D3771DE2 /* PBXContainerItemProxy */ = { + 1090EB79679288E70162A4CE7209B308 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 66E0036061F06985A735F972DA873D82 /* EXCalendar.xcodeproj */; + containerPortal = 6E562C149ACFF3572AF76219136BAE6F /* EXCellular.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 0F2988851D689F1E41CFC89C31422758; - remoteInfo = EXCalendar; + remoteGlobalIDString = 0F0F7D35F4DD6BA6A33589D3CB5759F3; + remoteInfo = EXCellular; }; - 0DE728E47B2336653C2DCDC120B4DBEF /* PBXContainerItemProxy */ = { + 15EBFE0C5D680BC678D2BAEE2AA7EB17 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = ED50116F92CAB9F1E06FE905363CE060 /* EXPermissions.xcodeproj */; + containerPortal = 1874C56666647F9C71C26C490DCD0921 /* AppAuth.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 488F0C19AB92FC4B503EB55CC688FCF5; - remoteInfo = EXPermissions; + remoteGlobalIDString = 4EFA7E4CE531453CF475A9A4322A84F8; + remoteInfo = AppAuth; }; - 0E638FE83654AAA0102A8CC346914D53 /* PBXContainerItemProxy */ = { + 17C369DA24A77B5DFF1F57381D6566B6 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = A528590EDEA69FCB74BFA09B141B4DBF /* EXGL.xcodeproj */; + containerPortal = 3F7A24830AA6A74FD093D740F10D7773 /* EXKeepAwake.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 78CC35D6F49ACC0F72F0095F78EFDCE7; - remoteInfo = EXGL; + remoteGlobalIDString = E593B1631324E147D59AE9990EDA53A2; + remoteInfo = EXKeepAwake; }; - 0FAD10CD5AEBC9229D69C5193AA1996D /* PBXContainerItemProxy */ = { + 1818CAC700E350A246DD8A1AD3C332F3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 228AECF796357BD0C17A0250B493CF46 /* RNGestureHandler.xcodeproj */; + containerPortal = A32518B2BC57B6ACB06728AD31C6FED7 /* React-jsinspector.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 0356CDCA5DB6D4F4B4F5991088D05580; - remoteInfo = RNGestureHandler; + remoteGlobalIDString = 1AC0EAF3E808B6AA276E43B30A5B20AA; + remoteInfo = "React-jsinspector"; }; - 10F882494F1E53F051D53F1647C0F700 /* PBXContainerItemProxy */ = { + 1A08C035C5D4A09AC05CCB509F8F6D9F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 9946A17BD11A68F7A944498FD73C8413 /* ZXingObjC.xcodeproj */; + containerPortal = 1682454010CE1DE95AE1F2B800003AE8 /* EXSpeech.xcodeproj */; proxyType = 1; - remoteGlobalIDString = F1A98E99C5291C55C29C32D889990685; - remoteInfo = ZXingObjC; + remoteGlobalIDString = AC043527FC46D59E5210AD9D49B847FC; + remoteInfo = EXSpeech; }; - 138B551B7760FEF12E9588FB05659D94 /* PBXContainerItemProxy */ = { + 1C05065DBB3562956F366E93DDEBF6E4 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 559D179071A592B620836CC4F14A9F63 /* EXBlur.xcodeproj */; + containerPortal = 539904AF85D455EEA0BC80314430F767 /* React-RCTLinking.xcodeproj */; proxyType = 1; - remoteGlobalIDString = D08BCCD5DE12C8EFB6429B9126525E9F; - remoteInfo = EXBlur; + remoteGlobalIDString = FF1621D1C3F9AF33EDD2BF51FEDEB3D8; + remoteInfo = "React-RCTLinking"; }; - 179551060FF9EA6024A9C9F7CEF0B4BA /* PBXContainerItemProxy */ = { + 22549EA770513D61589580CBFFB1E807 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = FC694360F93EB50AF01BD9AD3DDF6F63 /* React-RCTLinking.xcodeproj */; + containerPortal = 24D571065DC8E7D78DE3D281B7F9665E /* EXImagePicker.xcodeproj */; proxyType = 1; - remoteGlobalIDString = FF1621D1C3F9AF33EDD2BF51FEDEB3D8; - remoteInfo = "React-RCTLinking"; + remoteGlobalIDString = 9ACF1D2895E366F44F904503F65171CD; + remoteInfo = EXImagePicker; }; - 1CD7699E779B7207306C3A18AE7958E9 /* PBXContainerItemProxy */ = { + 227262230BCEBE33778709618CB70E9B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 5F89074EFF9BBFF30A654696E06822C7 /* EXImageManipulator.xcodeproj */; + containerPortal = D295C7698687650B201A4E18B1A6CE87 /* React.xcodeproj */; proxyType = 1; - remoteGlobalIDString = C3AA7C99B7CAD2FC22B8AA8928D7DF6F; - remoteInfo = EXImageManipulator; + remoteGlobalIDString = 94DA87F24FB4B93E5D08FE961D5E5A3E; + remoteInfo = React; }; - 1E3E312EFD96A12407172E96E9390F77 /* PBXContainerItemProxy */ = { + 22F148F91BD9CC2DB52F7F801629B509 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = EF2B74AE23B4D085A4D41634852D9E79 /* EXSecureStore.xcodeproj */; + containerPortal = 20C29A1EAED431974F1F9ADE24297AD8 /* RNGestureHandler.xcodeproj */; proxyType = 1; - remoteGlobalIDString = C4DBAA5ED98E7A037D09674FF42AF66F; - remoteInfo = EXSecureStore; + remoteGlobalIDString = 0356CDCA5DB6D4F4B4F5991088D05580; + remoteInfo = RNGestureHandler; }; - 2310E33AFE5DCF99B3982C7E4D4D7BDD /* PBXContainerItemProxy */ = { + 238E361F058A96459D5F16A251E0920F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 89B3742C40E8B4801826442347325BBF /* EXLocalization.xcodeproj */; + containerPortal = 6FCCE9A29FCD2F955BD249B2E8FE64D6 /* React-RCTVibration.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 55C7C51CE4B49B971674C896CB1DC301; - remoteInfo = EXLocalization; + remoteGlobalIDString = 502D208480A94D02F62BB739D7512657; + remoteInfo = "React-RCTVibration"; }; - 275C89C48B89E482C6C0A093E8672536 /* PBXContainerItemProxy */ = { + 270D963B83EE8B8579C8857BFCD46219 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 0F87C4C729C750646FF9170E107841D0 /* EXConstants.xcodeproj */; + containerPortal = B399F6209661F0C9597B9B02C293119F /* EXPermissions.xcodeproj */; proxyType = 1; - remoteGlobalIDString = F3E96ACB94E2361FA9D83BE599DEC427; - remoteInfo = EXConstants; + remoteGlobalIDString = 488F0C19AB92FC4B503EB55CC688FCF5; + remoteInfo = EXPermissions; }; - 284686AE181AFB3CF7D3966FEBB9063D /* PBXContainerItemProxy */ = { + 2886FB9B4B7F2B85BCE556DBA40F64E1 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 2AFEBA4AE1BF044913C3A1F0ABCD7BEF /* React-RCTVibration.xcodeproj */; + containerPortal = A0F40A7EF94F9CDB1C9EC3706EF31977 /* EXFileSystem.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 502D208480A94D02F62BB739D7512657; - remoteInfo = "React-RCTVibration"; + remoteGlobalIDString = 5232535845650ADAE59870B722468D8A; + remoteInfo = EXFileSystem; }; - 2F6A828F617177C24C91AFE67336840B /* PBXContainerItemProxy */ = { + 299C7D8FCEEE584A590BCFE9CBC14FBF /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 58F5BF4DBAF85B453DD79DA82B862E0A /* EXHaptics.xcodeproj */; + containerPortal = 1291D1E0EF26BE30E64DFE7E772780FF /* EXSharing.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 458E4E0DEA9D752CC28F1A42E4B306AC; - remoteInfo = EXHaptics; + remoteGlobalIDString = 1458926EF4B0A3DF1C40B5639E7358B1; + remoteInfo = EXSharing; }; - 326C844A787822153322EEB5212C6F27 /* PBXContainerItemProxy */ = { + 29A2F824BAAC6D5862899640DB847035 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = D5E45FC61A6D2D7E3F46F8A281EA7F64 /* UMReactNativeAdapter.xcodeproj */; + containerPortal = AC64B72943BF5A964B4BEA5D03352E8A /* React-Core.xcodeproj */; proxyType = 1; - remoteGlobalIDString = E0F5743D6C158230DA447A63190DF2E9; - remoteInfo = UMReactNativeAdapter; + remoteGlobalIDString = 5DA1A74647F652AE8E4DE074AFC4C6B7; + remoteInfo = "React-Core"; }; - 35855868F9E27821A58D859456185065 /* PBXContainerItemProxy */ = { + 2C46490A97F4F656FDE29AFC58990241 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 7C6CEDFBCA521989947F5B019C76054A /* React-RCTActionSheet.xcodeproj */; + containerPortal = 69B62F0A6A5AE0185AB31AF2B50E6C73 /* EXContacts.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 2B622CBAFD85AC413ED6306FD8B71B00; - remoteInfo = "React-RCTActionSheet"; + remoteGlobalIDString = B22EE26A55A92797A576C80A1202EFFD; + remoteInfo = EXContacts; }; - 39B15604EA16A09A49DA569249C7AA83 /* PBXContainerItemProxy */ = { + 2D3F02A4EF58120647F70AD3648877C9 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = B1BC6698202B367C7B3129780457D544 /* EXGL_CPP.xcodeproj */; + containerPortal = E3D4951BFB897802566871A47737F1EE /* EXCrypto.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 4C66693C554B15E2593FB1F665F8BA01; - remoteInfo = EXGL_CPP; + remoteGlobalIDString = 7313EAFC3221A55173D00B5135657D25; + remoteInfo = EXCrypto; }; - 3B6AAB8218C95833AC4ECBF0FCFC644F /* PBXContainerItemProxy */ = { + 2D6B7FE0D400077A830A889D5F2E3BF6 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = EC64490903CB102FA5D88F9FD8D4873B /* DoubleConversion.xcodeproj */; + containerPortal = 3AC85EC6EA5A15DE1A14AC44693B3FAF /* EXLocalization.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 725D0E8C1060F8939288E8C91236BA4F; - remoteInfo = DoubleConversion; + remoteGlobalIDString = 55C7C51CE4B49B971674C896CB1DC301; + remoteInfo = EXLocalization; }; - 3C1A537234950AB8ECD1F34B075F0F28 /* PBXContainerItemProxy */ = { + 30088EFDAAB1E9DE2384E33382C74BDE /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 6FF66503720CEADA5339CA295727D2E6 /* EXBattery.xcodeproj */; + containerPortal = 790A2E685AC19C611733CE7F67102977 /* UMPermissionsInterface.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 5941E7B2BA388644B9A594045D22DE1D; - remoteInfo = EXBattery; + remoteGlobalIDString = 12FF61416C5E794E9DEAC78D381D9726; + remoteInfo = UMPermissionsInterface; }; - 3E4F5A1B13CBDC95AFB48D68224FBDEA /* PBXContainerItemProxy */ = { + 32EB6A244E8E2B57AA237ACBA3AFE442 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = EC8B540ED755EDCB2AE686784D3AF479 /* EXApplication.xcodeproj */; + containerPortal = 154D415A4BF5B57E8E22F022EE88A1A2 /* Yoga.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 2C391225329DE46C6566ED1ADF52F10D; - remoteInfo = EXApplication; + remoteGlobalIDString = 8DB658880A3F558549A84D99BCFADCBC; + remoteInfo = Yoga; }; - 415E5BEBE0E75178ADED5451DEB88B6F /* PBXContainerItemProxy */ = { + 33EA9FDC3E1504E6D2321C306A5A70A2 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 8DD091FE677FB13DC171D90C021CA7DE /* GTMAppAuth.xcodeproj */; + containerPortal = 81D1A93D40939D17C69ACA87E0F091B9 /* Amplitude-iOS.xcodeproj */; proxyType = 1; - remoteGlobalIDString = AFFE62B58843E7D325544E4D760E8920; - remoteInfo = GTMAppAuth; + remoteGlobalIDString = E9F5188151EE37F157A617BBBC3DB105; + remoteInfo = "Amplitude-iOS"; }; - 431AF7D2922ED0E18BFF9D7C0FA1633D /* PBXContainerItemProxy */ = { + 3877B90A6B5F0B1026CCF6519797BC8B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 4B81D9E849F7B0FF699CF47FC7F2EC7B /* React-Core.xcodeproj */; + containerPortal = 99EC51DA27D3AF613938A01C65921965 /* UMCore.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 5DA1A74647F652AE8E4DE074AFC4C6B7; - remoteInfo = "React-Core"; + remoteGlobalIDString = 153171642F5C5CBC05FD3EF6B23A3F36; + remoteInfo = UMCore; }; - 4D5B404E23A828F7AA99BBBA54EFDA9B /* PBXContainerItemProxy */ = { + 395309C6928642091FF420CF2575E3AF /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 06A760ACB1990444FA093A6D7A8AC2EB /* boost-for-react-native.xcodeproj */; + containerPortal = 5C904EB0F8D09A9D6A2CA1D9E5FB1A5E /* FBReactNativeSpec.xcodeproj */; proxyType = 1; - remoteGlobalIDString = AA4CE39926C0C12D02F874C1C48A5710; - remoteInfo = "boost-for-react-native"; + remoteGlobalIDString = 5CDFFFDA1BEA16A0D3629FE9F761022A; + remoteInfo = FBReactNativeSpec; }; - 4FE18B2D19C547E0FF873FCE071D4A0D /* PBXContainerItemProxy */ = { + 3A3442214292971BCE3FB68A3F07763B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = B2F742EBD46D881CC735F4D4A4260119 /* Folly.xcodeproj */; + containerPortal = 1CEBDBC09F655F237DA82B43D4E56D1A /* EXConstants.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = F3E96ACB94E2361FA9D83BE599DEC427; + remoteInfo = EXConstants; + }; + 436B61B79E4477585A4EDB1DDA6D1502 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 3BA6FCAA80CA6709FC129B2F8F1455D9 /* Folly.xcodeproj */; proxyType = 1; remoteGlobalIDString = 14BB2B7275726942E762F076FA966088; remoteInfo = Folly; }; - 54275ED60E349E7388A578FD6CAC77C9 /* PBXContainerItemProxy */ = { + 458E74C7A2B3BCEB0678B44712A07B95 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 0CCA7AB54711A1C565D9146E86AF6FE5 /* EXSegment.xcodeproj */; + containerPortal = 38C1D46D658188871C901CE039368D2B /* GoogleSignIn.xcodeproj */; proxyType = 1; - remoteGlobalIDString = D65C18BEC619DFEA9C73805518539F66; - remoteInfo = EXSegment; + remoteGlobalIDString = 70D52585A9FA4EEA343010638ADABC11; + remoteInfo = GoogleSignIn; }; - 5C9524D6AB93120FF7D58A9461D45112 /* PBXContainerItemProxy */ = { + 496ADDE86A2DCEA1811894FEDE15246A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 6F2506A46EAB2A974A4A198BF26B5D11 /* UMCore.xcodeproj */; + containerPortal = A31EA7E16D8F9F37E83632B7A9BD49BD /* UMFontInterface.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 153171642F5C5CBC05FD3EF6B23A3F36; - remoteInfo = UMCore; + remoteGlobalIDString = 7F4112A673122B6D50845D9BC1D9AFDB; + remoteInfo = UMFontInterface; }; - 603B6A8FFFCAC287D8B39746D674B792 /* PBXContainerItemProxy */ = { + 4ADB525BF5F77FDD2CEEF68E2C4F36C3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 00D632F97A746F8FBEE5FD654C95A5D4 /* EXBrightness.xcodeproj */; + containerPortal = 9FBF69DFB7386F17655AA92E47A91B88 /* EXLocalAuthentication.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 4AA3EE5BEEB58B2975A12819B1C58D97; - remoteInfo = EXBrightness; + remoteGlobalIDString = 8D12244750972C21D688A2875A0E77F4; + remoteInfo = EXLocalAuthentication; }; - 64A6C9CE2FB3DF3B12C572FCB9448BD0 /* PBXContainerItemProxy */ = { + 56D4B2E5F7422F637672FED6B1CF986F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 86F0EA4A0FCDB3FC734AE64574A90EBC /* react-native-safe-area-context.xcodeproj */; + containerPortal = D0A15388E6A79D84E72CB78529279E0C /* React-CoreModules.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 6FF729CB9CEA59FDDF1BA16AEB2B98D6; - remoteInfo = "react-native-safe-area-context"; + remoteGlobalIDString = 42F070932EC272C376353459CE0FA76E; + remoteInfo = "React-CoreModules"; }; - 65CCF35240ECB03F58B9E1E002B5E477 /* PBXContainerItemProxy */ = { + 56F4DE4682B3525F826E75C5B6982250 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 7572990AACADFEEFE5EF8AF3A2415FD0 /* FBReactNativeSpec.xcodeproj */; + containerPortal = C307D52AB4940565B4FE24E5B2BA7277 /* EXMediaLibrary.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 5CDFFFDA1BEA16A0D3629FE9F761022A; - remoteInfo = FBReactNativeSpec; + remoteGlobalIDString = 422CF65902B3ABF0E6A47527F9209CC8; + remoteInfo = EXMediaLibrary; }; - 67D78E6479226F565CE530FAD81A8B39 /* PBXContainerItemProxy */ = { + 586B05268C91474689F61A15ED902913 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 6790273ACF64FACB6F6C790F7465109B /* Amplitude-iOS.xcodeproj */; + containerPortal = 837FB515358617F85BDF99978EE71115 /* glog.xcodeproj */; proxyType = 1; - remoteGlobalIDString = E9F5188151EE37F157A617BBBC3DB105; - remoteInfo = "Amplitude-iOS"; + remoteGlobalIDString = 86F597DC3D8F3D7A34EC5A5C413F7255; + remoteInfo = glog; }; - 6D82ECC6C79E6BD8C4D55A0CF63A4D21 /* PBXContainerItemProxy */ = { + 5886A4134F2FA5B8753778E853BA19BA /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = D7D345E8C3BC6E50CBED042829BBF090 /* EXSensors.xcodeproj */; + containerPortal = D88FC63D8F76640F60314E4A5077FD31 /* EXAppAuth.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 5F5B88A2576A073FBDD91B02A10308F1; - remoteInfo = EXSensors; + remoteGlobalIDString = 5FB7695B45E2F2A9171D3B6C97B3A1A2; + remoteInfo = EXAppAuth; }; - 70227CF8F6B2D08A40EC88165F2BAEE8 /* PBXContainerItemProxy */ = { + 5986255D885BB7F771FE7C2C0E2BD5E3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + containerPortal = 37D51A279F61ACA707D2DDB2B4775260 /* react-native-safe-area-context.xcodeproj */; proxyType = 1; - remoteGlobalIDString = C616BB9F650D110E835D02A3250F302E; - remoteInfo = "Pods-BareExpo"; + remoteGlobalIDString = 6FF729CB9CEA59FDDF1BA16AEB2B98D6; + remoteInfo = "react-native-safe-area-context"; }; - 72CCD3670C80EA569EAE6696701FE495 /* PBXContainerItemProxy */ = { + 5A4A2A9AC0BEE1DF43937DF2E89B2C90 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = C4691EC6027337FE88F7B6C142C79DA9 /* EXLinearGradient.xcodeproj */; + containerPortal = 602F1AC40936205BAA0B2DB343047BC2 /* FBLazyVector.xcodeproj */; proxyType = 1; - remoteGlobalIDString = AF5113FDFEF2ECEBDD58149C34DD4634; - remoteInfo = EXLinearGradient; + remoteGlobalIDString = 4B95F1280DBD545D036916608691C3EF; + remoteInfo = FBLazyVector; }; - 747EAA46A036A88E6C075D7CAC73D253 /* PBXContainerItemProxy */ = { + 5B3A54C1CC98D54A8BF01EC39A0CCE9A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 3A6F2FEF94FB5051D0E15E0E75E061CE /* EXCellular.xcodeproj */; + containerPortal = 847FD5ED7B8C4325822B875EFAC72828 /* RCTTypeSafety.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 0F0F7D35F4DD6BA6A33589D3CB5759F3; - remoteInfo = EXCellular; + remoteGlobalIDString = 9C3601DE72183D42B9DC3FF333D35CF7; + remoteInfo = RCTTypeSafety; }; - 748CA12AEE04BEF5A766A071E198A2F3 /* PBXContainerItemProxy */ = { + 5C939B02FA3137B5DF8CDE1F7841A5EA /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 9B3C09E1B51BE5C72B1178721DFB4736 /* EXSQLite.xcodeproj */; + containerPortal = B79AA8F0753060DE025621A58BF10081 /* EXSecureStore.xcodeproj */; proxyType = 1; - remoteGlobalIDString = B8358C45B103287E90F710967785DD34; - remoteInfo = EXSQLite; + remoteGlobalIDString = C4DBAA5ED98E7A037D09674FF42AF66F; + remoteInfo = EXSecureStore; }; - 7EF30E0E4FFCDBEEAF279262F6874A60 /* PBXContainerItemProxy */ = { + 5E64C90BB3D6B2D2266FA06EF57FEDE3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 621E66BDF9658FBAEB7835F073CC1D58 /* EXAV.xcodeproj */; + containerPortal = D78B6B55B6F370CFD13934B2CC9B6119 /* EXDocumentPicker.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 657B3E0E8F77DB91FA182432EC404FBF; - remoteInfo = EXAV; + remoteGlobalIDString = 40300EFA08DDB78C6AFF84A0F118E9CD; + remoteInfo = EXDocumentPicker; }; - 7FC8F2D1B333FC5EADC4FBA1AB7EBFB5 /* PBXContainerItemProxy */ = { + 6FD2484E117822D91CEF929D743CB84F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 50C4358AD398837056C0C6E564E5FB45 /* RCTRequired.xcodeproj */; + containerPortal = 6FE9E6378CCA409045A0D6F7725BD635 /* React-RCTImage.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 7B4E6DC12B1D694845842E9A06C59213; - remoteInfo = RCTRequired; + remoteGlobalIDString = C78CA5C5EDDCCF5EC637E0FC8BB4C96E; + remoteInfo = "React-RCTImage"; }; - 834482237C0D29D3B0A986E0108F44E8 /* PBXContainerItemProxy */ = { + 70227CF8F6B2D08A40EC88165F2BAEE8 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 469C509D4699E1DC0DF43F06F3A21FD4 /* EXMailComposer.xcodeproj */; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 2E02530F5AAAD2AC2A43FE2B8AC3E99C; - remoteInfo = EXMailComposer; + remoteGlobalIDString = C616BB9F650D110E835D02A3250F302E; + remoteInfo = "Pods-BareExpo"; }; - 838268DE1B4CA8F37523351A20B732E7 /* PBXContainerItemProxy */ = { + 70734B1E9EA0F936F6E3A313F90C657C /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = AF0568DC623CE5D3D2E159457E57B21F /* EXMediaLibrary.xcodeproj */; + containerPortal = 2FA4EA22672E5A6B552140467F83F0D5 /* UMImageLoaderInterface.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 422CF65902B3ABF0E6A47527F9209CC8; - remoteInfo = EXMediaLibrary; + remoteGlobalIDString = A734124238F83C1FEE81C0FEDC5CDC5C; + remoteInfo = UMImageLoaderInterface; }; - 84CBD0CEF3538AC641BB40C36876BD81 /* PBXContainerItemProxy */ = { + 754D4A6FA047092156B7BFE15CF5CE82 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = C099422E2DC2875E807A665C97BCC571 /* FBLazyVector.xcodeproj */; + containerPortal = BFC20E8D25AC617CEF09AEE4F3B6447C /* EXUpdates.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 4B95F1280DBD545D036916608691C3EF; - remoteInfo = FBLazyVector; + remoteGlobalIDString = 076FF2640FFF3466FB36FD12A629113A; + remoteInfo = EXUpdates; }; - 865D575A281702845E263A55EB18538C /* PBXContainerItemProxy */ = { + 7582E2C1BD5F25FFE26C1115879B20E1 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = A3F4A301606C753818F89B954CBABFFA /* React-CoreModules.xcodeproj */; + containerPortal = C82A773803E9590719BF9B2ADBDC8853 /* RNReanimated.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 42F070932EC272C376353459CE0FA76E; - remoteInfo = "React-CoreModules"; + remoteGlobalIDString = E9E22639328ACC061EB56756AD5B4F57; + remoteInfo = RNReanimated; }; - 8A898395EFE24E3518D6ACE4807A4410 /* PBXContainerItemProxy */ = { + 762C229920508A7C1071A62F613FE744 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 3561DE58B3DAAE4AA0D0BC1C630862FA /* Analytics.xcodeproj */; + containerPortal = 39600D89716D9EF152089FCE92F9611F /* React-RCTText.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 428EE321470913F61A7C253ACF3B4D53; - remoteInfo = Analytics; + remoteGlobalIDString = F0809BF90AC70C40646AB597C21CC420; + remoteInfo = "React-RCTText"; }; - 8B6BE6262BA49516FE8E6F4D75224DD0 /* PBXContainerItemProxy */ = { + 7811002A80AC1E7EAF4C8894ABE73D57 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = D1D370A1C813FC6C49069D6F265F56E3 /* EXErrorRecovery.xcodeproj */; + containerPortal = 2DFD1D139E40516EB3C8592132C16563 /* React-RCTBlob.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 49603BA4A7FB1CFC9ACD589B8CE05EA2; - remoteInfo = EXErrorRecovery; + remoteGlobalIDString = D8D59AAB809693DB02967107370F4619; + remoteInfo = "React-RCTBlob"; }; - 8E0663814249A4ADFF8E7A4A5345A03A /* PBXContainerItemProxy */ = { + 78B92CED29A733A14982F6CF0A7DFEFC /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1CA025FC93211998774902CC4663DD61 /* EXSharing.xcodeproj */; + containerPortal = 0E7C660C1D1A671A1C2C6E0A386E4F98 /* EXGoogleSignIn.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 1458926EF4B0A3DF1C40B5639E7358B1; - remoteInfo = EXSharing; + remoteGlobalIDString = 1EBA7C3FD4A2348A1EFF618E12286F06; + remoteInfo = EXGoogleSignIn; }; - 9AF5A7B953E92F6D2EFF76EFFDE4DE59 /* PBXContainerItemProxy */ = { + 7A966DD2F28C59FB519D21A29DAC0C3E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1EC4C5F6778FD0728D36B94A40185D7A /* EXFileSystem.xcodeproj */; + containerPortal = 0DCFBB69843FF7B3B3F4DBFA9395897F /* EXRandom.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 5232535845650ADAE59870B722468D8A; - remoteInfo = EXFileSystem; + remoteGlobalIDString = 00EB4A6BB9778AFFF7F587D732973596; + remoteInfo = EXRandom; }; - 9B46D48EFD5EF68D89130936A94F0CD3 /* PBXContainerItemProxy */ = { + 8339A31787E72B0335048723E34B17A0 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 8C472FA03A74CA155968F8B7216E490A /* EXSpeech.xcodeproj */; + containerPortal = 67E8A05962A87D9D3E97F466C0588F3E /* EXBattery.xcodeproj */; proxyType = 1; - remoteGlobalIDString = AC043527FC46D59E5210AD9D49B847FC; - remoteInfo = EXSpeech; + remoteGlobalIDString = 5941E7B2BA388644B9A594045D22DE1D; + remoteInfo = EXBattery; }; - 9B902F5A4F54D64F86DDBD98FFC44F69 /* PBXContainerItemProxy */ = { + 88E8AAB58D90D69B73E53CB1039AD148 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 5C7101C48EADF48A3F01ADAD195A0608 /* EXStoreReview.xcodeproj */; + containerPortal = C48CFC9D9BAC60B4713D773CBCC18138 /* React-RCTActionSheet.xcodeproj */; proxyType = 1; - remoteGlobalIDString = F2C74458D282DA74DB95F8A7FE6A5207; - remoteInfo = EXStoreReview; + remoteGlobalIDString = 2B622CBAFD85AC413ED6306FD8B71B00; + remoteInfo = "React-RCTActionSheet"; }; - 9BDC84B84E26F07933C0332937E97893 /* PBXContainerItemProxy */ = { + 89C1B83344DFB9F8757ED973FEFD75D8 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 59558382C9C14CEDEC8ECC99462044AC /* EXSMS.xcodeproj */; + containerPortal = D918720DA8177424E16B7D398B1E42BA /* React-RCTNetwork.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 1309E054CB75DA99E029D5D2C8C2210E; - remoteInfo = EXSMS; + remoteGlobalIDString = B42CC4F102742853C37E7C4841756DBE; + remoteInfo = "React-RCTNetwork"; }; - 9C3E3E2A9F7E24D3111FB14B5EE4B00D /* PBXContainerItemProxy */ = { + 9412205B3F0255BC6427D1FE79F93D4D /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 384191FF16B8310DB2CA32CE12714F26 /* EXAppAuth.xcodeproj */; + containerPortal = 2D820764336141EB6A64FB5E39379B84 /* EXSQLite.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 5FB7695B45E2F2A9171D3B6C97B3A1A2; - remoteInfo = EXAppAuth; + remoteGlobalIDString = B8358C45B103287E90F710967785DD34; + remoteInfo = EXSQLite; }; - A2F13C125416EB21F8FAEE2465DAC2AB /* PBXContainerItemProxy */ = { + 9A6F2C6B72B62171B236644CDFA5E17C /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = A9333E5CD08216B9D4D56A43F8AFFB5B /* EXDevice.xcodeproj */; + containerPortal = AF9B03AFD3122203FA523C331045B557 /* EXErrorRecovery.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 61CE878EC16A63D023F23DA6C1B824B9; - remoteInfo = EXDevice; + remoteGlobalIDString = 49603BA4A7FB1CFC9ACD589B8CE05EA2; + remoteInfo = EXErrorRecovery; }; - A4861781D8FFCA47636C2B2572BBA817 /* PBXContainerItemProxy */ = { + 9B3387B09458A77915E4FECED561E332 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 10773CD4E5B8A755D9E0D42FC649AEB4 /* UMFontInterface.xcodeproj */; + containerPortal = E35074979A21EA433E91AFF284E3AC50 /* EXSensors.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 7F4112A673122B6D50845D9BC1D9AFDB; - remoteInfo = UMFontInterface; + remoteGlobalIDString = 5F5B88A2576A073FBDD91B02A10308F1; + remoteInfo = EXSensors; }; - A58BD843AD668DFD173903AEB86893D7 /* PBXContainerItemProxy */ = { + 9D76DE94DE8A9BBDB566D04BDBAD1044 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 6FA7CD78D631158BDBE6D2A9C4FC19FB /* AppAuth.xcodeproj */; + containerPortal = F5378BC6DC876907C7D4762A994635E1 /* UMSensorsInterface.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 4EFA7E4CE531453CF475A9A4322A84F8; - remoteInfo = AppAuth; + remoteGlobalIDString = 1FDCE556B997E87DAB0DA2727CC69285; + remoteInfo = UMSensorsInterface; }; - A75B4DE316B3C94CC37B4A662123569C /* PBXContainerItemProxy */ = { + 9E57EB6A3151AA92814D09FFBB8D1788 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = E3C83D9BB0BF020DE9E3EA402FF40418 /* EXDocumentPicker.xcodeproj */; + containerPortal = 42DD6321E59344D440B1F51FE3CF79E7 /* ReactCommon.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 40300EFA08DDB78C6AFF84A0F118E9CD; - remoteInfo = EXDocumentPicker; + remoteGlobalIDString = 2610D146B211EB79FECF83D4FA5AB36D; + remoteInfo = ReactCommon; }; - A8B0AE310D7DFFEE773B7F31A8FC8DC7 /* PBXContainerItemProxy */ = { + 9EAC0AFB4D6D6D4B4E2D72A086562D4B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = B16FF31EB7B2D5E60E6685477B72EBC5 /* EXFont.xcodeproj */; + containerPortal = 486D05376E4B939AAAA46292A4C1EDC5 /* React-RCTAnimation.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 0A4A001679E384FB337FF08C5D081399; - remoteInfo = EXFont; + remoteGlobalIDString = 8FD0C9BFE0E509D0066C67C06EE170B5; + remoteInfo = "React-RCTAnimation"; }; - A8F91F7C4377813388AE4D2DDB3F6CA4 /* PBXContainerItemProxy */ = { + A0702A3F3987D834E5CB524D7582BC42 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = D58517F1F49DD7F710C941D73B419B5C /* EXAppLoaderProvider.xcodeproj */; + containerPortal = 2B3EF7E45E25388E46088AEF724044E2 /* EXGL_CPP.xcodeproj */; proxyType = 1; - remoteGlobalIDString = BCF55F45F804FC2D6BC57983597F3174; - remoteInfo = EXAppLoaderProvider; + remoteGlobalIDString = 4C66693C554B15E2593FB1F665F8BA01; + remoteInfo = EXGL_CPP; }; - AD6B10B33B18CA4A347E896D47BF322A /* PBXContainerItemProxy */ = { + A1E5C22EA8DDC7C8B2374E152A49DDF8 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = AFBF976B0EF04C9912E08179B68D2308 /* EXBarCodeScanner.xcodeproj */; + containerPortal = 211D8213F75598D838AA142334A75A03 /* RCTRequired.xcodeproj */; proxyType = 1; - remoteGlobalIDString = E6D544E86F973F511B82FE486E5E25CD; - remoteInfo = EXBarCodeScanner; + remoteGlobalIDString = 7B4E6DC12B1D694845842E9A06C59213; + remoteInfo = RCTRequired; }; - B060D0AFB1E0CC3F9EFAB39BBB472BDE /* PBXContainerItemProxy */ = { + A45DAF1200969FEA0AAE45BA94FBE32D /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = A90F97E439A7BC54338B0DC132FB389F /* EXLocalAuthentication.xcodeproj */; + containerPortal = 72E97573157DD427D06035896E61A932 /* GTMAppAuth.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 8D12244750972C21D688A2875A0E77F4; - remoteInfo = EXLocalAuthentication; + remoteGlobalIDString = AFFE62B58843E7D325544E4D760E8920; + remoteInfo = GTMAppAuth; }; - B142D18C098B8F928A3B28E83EE06A70 /* PBXContainerItemProxy */ = { + A7F2BAC3294F187AAFAFAC16F66D2F77 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 081775E5E1E22CD733CEC31DEC05391D /* EXImagePicker.xcodeproj */; + containerPortal = B79E739FDB18023D4C8E4264D5CE84D3 /* EXGL.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 9ACF1D2895E366F44F904503F65171CD; - remoteInfo = EXImagePicker; + remoteGlobalIDString = 78CC35D6F49ACC0F72F0095F78EFDCE7; + remoteInfo = EXGL; }; - B302FD2BB02B0AAD96BDC1C6DB19E566 /* PBXContainerItemProxy */ = { + AAFC45B81AD9B7003B656D494849C5BC /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = D06CF6E8B5CE7D5A760E443475289B14 /* UMImageLoaderInterface.xcodeproj */; + containerPortal = 4915DBB1FD2CAFEC6F31A56C0C6957F2 /* GTMSessionFetcher.xcodeproj */; proxyType = 1; - remoteGlobalIDString = A734124238F83C1FEE81C0FEDC5CDC5C; - remoteInfo = UMImageLoaderInterface; + remoteGlobalIDString = BD7A8A3BC22FD28DCB40568BE43D7C70; + remoteInfo = GTMSessionFetcher; }; - B3B22FDA90847B607B6AB701065D65BE /* PBXContainerItemProxy */ = { + AE5C3FC5B1E65980DAD50948DCF5C6D4 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 24C2C1248498064540A1A0795384B075 /* UMConstantsInterface.xcodeproj */; + containerPortal = 4F6D317BD66107DED81B141CC7C9862B /* EXCalendar.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 46F82E84687582F366B907E2BD5F1EA2; - remoteInfo = UMConstantsInterface; + remoteGlobalIDString = 0F2988851D689F1E41CFC89C31422758; + remoteInfo = EXCalendar; }; - B3DFA936118F40EC72787C517C5197ED /* PBXContainerItemProxy */ = { + B0AF012459FB8FBA764ECFBCAF75AEFF /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 93A314050AEE5C54490FF76731532B5D /* React-RCTAnimation.xcodeproj */; + containerPortal = 4A75B063423ACC708261B1E2E6A5AF72 /* EXBluetooth.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 8FD0C9BFE0E509D0066C67C06EE170B5; - remoteInfo = "React-RCTAnimation"; + remoteGlobalIDString = 85E4ABA3FE5052C9FD39179D7166A9C1; + remoteInfo = EXBluetooth; }; - B4151C4687EFC1E5E85C4622E62BABAA /* PBXContainerItemProxy */ = { + B22CA872137DE382F4D19A1808237607 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = BAD136761E20C0CF271C8994F81BE4E8 /* UMCameraInterface.xcodeproj */; + containerPortal = 74FEDEFE688494CAE07748B5D758B147 /* EXBlur.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 86372E925D4E10D72894E239CC18BCD9; - remoteInfo = UMCameraInterface; + remoteGlobalIDString = D08BCCD5DE12C8EFB6429B9126525E9F; + remoteInfo = EXBlur; }; - B621C005B2348C73A36A9F050EF3AAEC /* PBXContainerItemProxy */ = { + B43AF8ADB4ABED542A191F0C92CDA58E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 9F278CA3578A1C7C742F5C39E58E8626 /* EXRandom.xcodeproj */; + containerPortal = 7C365CF21BA55DFDF477C4C9CE32DCA1 /* EXPrint.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 00EB4A6BB9778AFFF7F587D732973596; - remoteInfo = EXRandom; + remoteGlobalIDString = FEAB4A1E3F5EAA6EBAE612E8CBDD2612; + remoteInfo = EXPrint; }; - BA9CC7508F551A390E71FA7366A4BB7B /* PBXContainerItemProxy */ = { + B616A6DBE11835E3828477A080007882 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1FBDB8F24C5539045D8AE87F927FB3EE /* EXWebBrowser.xcodeproj */; + containerPortal = ACDF0A1622DDFFECE9C4DD356D1BA970 /* EXDevice.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 026359A12CA511AF12897ED05A83462C; - remoteInfo = EXWebBrowser; + remoteGlobalIDString = 61CE878EC16A63D023F23DA6C1B824B9; + remoteInfo = EXDevice; }; - BAD1DF73985CE89817BFA6C0543F3D03 /* PBXContainerItemProxy */ = { + B8313E58D931E0DF5AAF44180C29A885 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 3E8F53A4E4A9F6D8E7270A1D59C0414A /* EXCrypto.xcodeproj */; + containerPortal = 283EB81A8B2631DC912F91F2E743D805 /* UMCameraInterface.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 7313EAFC3221A55173D00B5135657D25; - remoteInfo = EXCrypto; + remoteGlobalIDString = 86372E925D4E10D72894E239CC18BCD9; + remoteInfo = UMCameraInterface; }; - BC28539A09791D00B0BBE33A1BFCC04F /* PBXContainerItemProxy */ = { + BC67C44FE17DD6A19F9E8B7CA1B8C21C /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = BB09D5AC4BEBC2617D9D95C54475FA09 /* React.xcodeproj */; + containerPortal = 951A59FA6D6F13FE2BC2DC148092885D /* EXLinearGradient.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 94DA87F24FB4B93E5D08FE961D5E5A3E; - remoteInfo = React; + remoteGlobalIDString = AF5113FDFEF2ECEBDD58149C34DD4634; + remoteInfo = EXLinearGradient; }; - BC8167D94C315BAC5226405FC6608AA7 /* PBXContainerItemProxy */ = { + BCF48DD07D2F4C863C70A03EA55F39F7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 21907930CDED304581AE9F8EF737DFC3 /* glog.xcodeproj */; + containerPortal = D1A3C1892F717A0516FC6E06862425AD /* React-cxxreact.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 86F597DC3D8F3D7A34EC5A5C413F7255; - remoteInfo = glog; + remoteGlobalIDString = BD509719D4F0C3D8910F2BED0B6AB5F3; + remoteInfo = "React-cxxreact"; }; - BF01986E6376555F8A81956D27CEE244 /* PBXContainerItemProxy */ = { + BE305DBB61F72B252077F23B9000886B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 73E1515109725296D25100C06DA91793 /* RCTTypeSafety.xcodeproj */; + containerPortal = A5F35E9471A25BAFEB3AB53EDB2E48BD /* UMBarCodeScannerInterface.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 9C3601DE72183D42B9DC3FF333D35CF7; - remoteInfo = RCTTypeSafety; + remoteGlobalIDString = 971E60E1AF9163E7E08105622FC91C16; + remoteInfo = UMBarCodeScannerInterface; }; - C0D1C19DEA5D365061FF4508B4800EF2 /* PBXContainerItemProxy */ = { + BF42B9CC2019D0F91470CE826F220F28 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = F6C89811BEB495795C6F1B805FCF9133 /* GTMSessionFetcher.xcodeproj */; + containerPortal = 5ED0F47567E19D563562378CB541F063 /* React-jsiexecutor.xcodeproj */; proxyType = 1; - remoteGlobalIDString = BD7A8A3BC22FD28DCB40568BE43D7C70; - remoteInfo = GTMSessionFetcher; + remoteGlobalIDString = 7F7693C84AD2D676CE4E5741F508C198; + remoteInfo = "React-jsiexecutor"; }; - C58FA3752529C35AD98AF55942791482 /* PBXContainerItemProxy */ = { + C44BFA7EDE6D662FB3341FE30CCE61A1 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = B95E106A906DA6BC3B1AE32B1476EC96 /* React-RCTText.xcodeproj */; + containerPortal = 85183E225D7A7272819751A43B77122A /* ZXingObjC.xcodeproj */; proxyType = 1; - remoteGlobalIDString = F0809BF90AC70C40646AB597C21CC420; - remoteInfo = "React-RCTText"; + remoteGlobalIDString = F1A98E99C5291C55C29C32D889990685; + remoteInfo = ZXingObjC; }; - C6775EA6E67262174AE3F8EB9BC04527 /* PBXContainerItemProxy */ = { + C4D1D3FD3BAD1607F4A843AEA84F1910 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 53B70B73EBA72F4DB54EFB1201B958D9 /* React-RCTBlob.xcodeproj */; + containerPortal = 4830F218FE12E25D199C4BF46791F52C /* EXBrightness.xcodeproj */; proxyType = 1; - remoteGlobalIDString = D8D59AAB809693DB02967107370F4619; - remoteInfo = "React-RCTBlob"; + remoteGlobalIDString = 4AA3EE5BEEB58B2975A12819B1C58D97; + remoteInfo = EXBrightness; }; - C793E8E284B01FE1C42765785C913284 /* PBXContainerItemProxy */ = { + CAF99F2177FE1B7C7F23798B15E0A5A7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = C2EA603A6A2597676F274428E05872B9 /* React-jsiexecutor.xcodeproj */; + containerPortal = 31ED0F047A312EAA2BE054E15BB3DA57 /* EXFont.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 7F7693C84AD2D676CE4E5741F508C198; - remoteInfo = "React-jsiexecutor"; + remoteGlobalIDString = 0A4A001679E384FB337FF08C5D081399; + remoteInfo = EXFont; }; - C7B8E4638B3FEEE41A30B79BCD5A66A2 /* PBXContainerItemProxy */ = { + CB6007B65E78188B3DBC7B7B0B53EE7C /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 11A32ED6BFC7435B83A74B68227CF672 /* ReactCommon.xcodeproj */; + containerPortal = 22B7962C5AC6F553566BDB321CDCBED7 /* Analytics.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 2610D146B211EB79FECF83D4FA5AB36D; - remoteInfo = ReactCommon; + remoteGlobalIDString = 428EE321470913F61A7C253ACF3B4D53; + remoteInfo = Analytics; }; - D1E465D8EE4E1BB41A4F686819B41C3F /* PBXContainerItemProxy */ = { + CC0A1C43A4C49CE5036AF9D65AE0A094 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 5C0692C4DCE5A6E01C6809F60A6FBB6E /* React-cxxreact.xcodeproj */; + containerPortal = 19518053F4B0ADB5DD067DBC654DCDC8 /* EXHaptics.xcodeproj */; proxyType = 1; - remoteGlobalIDString = BD509719D4F0C3D8910F2BED0B6AB5F3; - remoteInfo = "React-cxxreact"; + remoteGlobalIDString = 458E4E0DEA9D752CC28F1A42E4B306AC; + remoteInfo = EXHaptics; }; - D7FFDD3F5095036FF7AF5F5D29EFB1BE /* PBXContainerItemProxy */ = { + D043C6D69D8E8DBE9A2A6B5904D80A4B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 966D82943A84614F0D90E09EED82FC4A /* EXAmplitude.xcodeproj */; + containerPortal = D9159EDE5B081372F59C922A6F771D88 /* EXWebBrowser.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 700BA3D76A8C4362E721FECC92A96DFB; - remoteInfo = EXAmplitude; + remoteGlobalIDString = 026359A12CA511AF12897ED05A83462C; + remoteInfo = EXWebBrowser; }; - DC0A99BF800318FF2591A3C3BF67AA2A /* PBXContainerItemProxy */ = { + D264A1CBF2E9FEA332EC92EB30758B6A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 068283BA3523101E0BA7F90CEB90A6A1 /* Yoga.xcodeproj */; + containerPortal = 84BC96E6F93CA7ACABFB696BC390AAE4 /* DoubleConversion.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 8DB658880A3F558549A84D99BCFADCBC; - remoteInfo = Yoga; + remoteGlobalIDString = 725D0E8C1060F8939288E8C91236BA4F; + remoteInfo = DoubleConversion; }; - DDFE0FA34D9552D9D2E63BB7DDC37FB3 /* PBXContainerItemProxy */ = { + D27C7DF1BFAE9F9C2D7274FCF3D08D5F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 7673391655AE15ABB96812EE718E18B3 /* EXBluetooth.xcodeproj */; + containerPortal = 9CEAF6033593566F9D90D312481E1561 /* EXSegment.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 85E4ABA3FE5052C9FD39179D7166A9C1; - remoteInfo = EXBluetooth; + remoteGlobalIDString = D65C18BEC619DFEA9C73805518539F66; + remoteInfo = EXSegment; }; - DF4AEE3244EB84A881866AE1F00F702A /* PBXContainerItemProxy */ = { + D84005DE0A7FC1C2180D6DC48F158195 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 01CFA74EFC65BCFDF41AE2DB0615EED8 /* React-jsi.xcodeproj */; + containerPortal = FBDB34F0ECB442D367E68748ADA3820F /* EXImageManipulator.xcodeproj */; proxyType = 1; - remoteGlobalIDString = D0DB82AB65D33935072718EA2468992F; - remoteInfo = "React-jsi"; + remoteGlobalIDString = C3AA7C99B7CAD2FC22B8AA8928D7DF6F; + remoteInfo = EXImageManipulator; }; - E22601FB7D527CB7700F5EF31658A6BD /* PBXContainerItemProxy */ = { + DCF29BC56D0890AC4130BF00F0C9D8DD /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 6F0ED87952B752BF2F6950D2DAB51472 /* EXContacts.xcodeproj */; + containerPortal = 766836226A2B4B63203538724CCB4F1C /* EXAmplitude.xcodeproj */; proxyType = 1; - remoteGlobalIDString = B22EE26A55A92797A576C80A1202EFFD; - remoteInfo = EXContacts; + remoteGlobalIDString = 700BA3D76A8C4362E721FECC92A96DFB; + remoteInfo = EXAmplitude; }; - E49E09ABFFD95C08AE12CE1C82C5B1C2 /* PBXContainerItemProxy */ = { + DF962C651115BD29A1B59BB3CB77A30D /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 4B8658D487323D6EEE125B5F57F06468 /* UMSensorsInterface.xcodeproj */; + containerPortal = 5370504E9C2AB0A5A79DCDA80512DF63 /* EXNotifications.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 1FDCE556B997E87DAB0DA2727CC69285; - remoteInfo = UMSensorsInterface; + remoteGlobalIDString = 6C660F81CE4F0EC96D208B20C3E8B154; + remoteInfo = EXNotifications; }; - E6029B48C29AAF21C67710BD18B592A9 /* PBXContainerItemProxy */ = { + E4F13EAE7D0B938A6C9D9ADE3128ED84 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 9F3B324040A71A156CE8681CBF0610AA /* EXUpdates.xcodeproj */; + containerPortal = CF1C7256B0751DFBBBC3C32DA058F9B2 /* EXAV.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 076FF2640FFF3466FB36FD12A629113A; - remoteInfo = EXUpdates; + remoteGlobalIDString = 657B3E0E8F77DB91FA182432EC404FBF; + remoteInfo = EXAV; }; - EB26241BADD0FC63FCBA5916C92149FB /* PBXContainerItemProxy */ = { + E51836B09C2FC93BC074CCA4B3AD62CC /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 9530BB032E863145DD427DBC06A82F68 /* EXGoogleSignIn.xcodeproj */; + containerPortal = 4A8C2D314E95B84D433DB3EC5D0248A8 /* EXMailComposer.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 1EBA7C3FD4A2348A1EFF618E12286F06; - remoteInfo = EXGoogleSignIn; + remoteGlobalIDString = 2E02530F5AAAD2AC2A43FE2B8AC3E99C; + remoteInfo = EXMailComposer; }; - EC0BE966E103A871BD282F4BEAD88408 /* PBXContainerItemProxy */ = { + E80BDFD8FD707172EE3568836C8E214F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = E17942621B3C5C442DAEF9E85EE80964 /* GoogleSignIn.xcodeproj */; + containerPortal = EBA46FF6FE79918F2108E6350176703C /* EXApplication.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 70D52585A9FA4EEA343010638ADABC11; - remoteInfo = GoogleSignIn; + remoteGlobalIDString = 2C391225329DE46C6566ED1ADF52F10D; + remoteInfo = EXApplication; }; - ECE72C945FEE79C19347B366A6114888 /* PBXContainerItemProxy */ = { + ED027510CF7496DCB9D74BD29EBBE262 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 4971CAC7D488A21F083090F5DF77441A /* EXPrint.xcodeproj */; + containerPortal = A0472A19A0663233A80B3D04DF83139C /* EXAppLoaderProvider.xcodeproj */; proxyType = 1; - remoteGlobalIDString = FEAB4A1E3F5EAA6EBAE612E8CBDD2612; - remoteInfo = EXPrint; + remoteGlobalIDString = BCF55F45F804FC2D6BC57983597F3174; + remoteInfo = EXAppLoaderProvider; }; - EDE74689F85B5DC963E8E16C1B164F4E /* PBXContainerItemProxy */ = { + EF8186F7500A8E201AC45D09194C7997 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 63CC2109E824718DD6CF3ECF2951714F /* EXNetwork.xcodeproj */; + containerPortal = 8BB89C73D41B6306783F6127102D17EE /* UMConstantsInterface.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 71F2A4AC24C8FBC0E24B6A613BB4F7BC; - remoteInfo = EXNetwork; + remoteGlobalIDString = 46F82E84687582F366B907E2BD5F1EA2; + remoteInfo = UMConstantsInterface; }; - F5B574F9DB6077B85805505D38AC81FA /* PBXContainerItemProxy */ = { + EFCF51AE8DE666A1A23D98409FEEA1AA /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = F93842B2AFB5431663D17D6C8B0DAD27 /* UMPermissionsInterface.xcodeproj */; + containerPortal = E6C81641E33F90B0058BD7F47E6F95F4 /* boost-for-react-native.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 12FF61416C5E794E9DEAC78D381D9726; - remoteInfo = UMPermissionsInterface; + remoteGlobalIDString = AA4CE39926C0C12D02F874C1C48A5710; + remoteInfo = "boost-for-react-native"; }; - F6613DD846BED619D89CA5871B5D76BE /* PBXContainerItemProxy */ = { + F610086B8A99E86BD49AC94781366EDE /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = A82D7F91B76D88E3B3001116B85C6F8F /* EXKeepAwake.xcodeproj */; + containerPortal = 5E612F91AF7A9DFF650E744D5DDDE6BB /* EXNetwork.xcodeproj */; proxyType = 1; - remoteGlobalIDString = E593B1631324E147D59AE9990EDA53A2; - remoteInfo = EXKeepAwake; + remoteGlobalIDString = 71F2A4AC24C8FBC0E24B6A613BB4F7BC; + remoteInfo = EXNetwork; }; - F7CA9DF8CB84759BCCD92D51371A60EE /* PBXContainerItemProxy */ = { + FCCD606F996CBBAAF838FA6301625D42 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = C3F1268A122894A50E585D0D43F60664 /* React-RCTNetwork.xcodeproj */; + containerPortal = 20EFB8787523F1F8E82C44E6D2318625 /* UMReactNativeAdapter.xcodeproj */; proxyType = 1; - remoteGlobalIDString = B42CC4F102742853C37E7C4841756DBE; - remoteInfo = "React-RCTNetwork"; + remoteGlobalIDString = E0F5743D6C158230DA447A63190DF2E9; + remoteInfo = UMReactNativeAdapter; }; - F891AEC19213E84B0E931017A9DD68A3 /* PBXContainerItemProxy */ = { + FF9E7C648C79FC370E36E22D87203385 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 00E9EF1B95C123998456AA100CE87025 /* React-RCTSettings.xcodeproj */; + containerPortal = 76D754AC0977B5323E742EEECB40AED4 /* EXStoreReview.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 02DD1E05F06C403A8300ABEFC2C29A3D; - remoteInfo = "React-RCTSettings"; + remoteGlobalIDString = F2C74458D282DA74DB95F8A7FE6A5207; + remoteInfo = EXStoreReview; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 00D632F97A746F8FBEE5FD654C95A5D4 /* EXBrightness */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXBrightness; path = EXBrightness.xcodeproj; sourceTree = ""; }; - 00E9EF1B95C123998456AA100CE87025 /* React-RCTSettings */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "React-RCTSettings"; path = "React-RCTSettings.xcodeproj"; sourceTree = ""; }; - 0143F693E54C76D9CEC9B89D39EA738C /* React-jsinspector */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "React-jsinspector"; path = "React-jsinspector.xcodeproj"; sourceTree = ""; }; - 01CFA74EFC65BCFDF41AE2DB0615EED8 /* React-jsi */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "React-jsi"; path = "React-jsi.xcodeproj"; sourceTree = ""; }; - 04AF6CFC908ABC897934A123721DCDC8 /* React-RCTImage */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "React-RCTImage"; path = "React-RCTImage.xcodeproj"; sourceTree = ""; }; - 068283BA3523101E0BA7F90CEB90A6A1 /* Yoga */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Yoga; path = Yoga.xcodeproj; sourceTree = ""; }; - 06A760ACB1990444FA093A6D7A8AC2EB /* boost-for-react-native */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "boost-for-react-native"; path = "boost-for-react-native.xcodeproj"; sourceTree = ""; }; - 081775E5E1E22CD733CEC31DEC05391D /* EXImagePicker */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXImagePicker; path = EXImagePicker.xcodeproj; sourceTree = ""; }; - 093F33B91AB6CCF24EC5B44C2168D6B7 /* RNReanimated */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RNReanimated; path = RNReanimated.xcodeproj; sourceTree = ""; }; 0B584D0632E15581F96D24B9C3B042D7 /* Pods-BareExpoTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-BareExpoTests.release.xcconfig"; sourceTree = ""; }; - 0CCA7AB54711A1C565D9146E86AF6FE5 /* EXSegment */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXSegment; path = EXSegment.xcodeproj; sourceTree = ""; }; - 0F87C4C729C750646FF9170E107841D0 /* EXConstants */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXConstants; path = EXConstants.xcodeproj; sourceTree = ""; }; - 10773CD4E5B8A755D9E0D42FC649AEB4 /* UMFontInterface */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = UMFontInterface; path = UMFontInterface.xcodeproj; sourceTree = ""; }; - 11A32ED6BFC7435B83A74B68227CF672 /* ReactCommon */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ReactCommon; path = ReactCommon.xcodeproj; sourceTree = ""; }; - 1CA025FC93211998774902CC4663DD61 /* EXSharing */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXSharing; path = EXSharing.xcodeproj; sourceTree = ""; }; - 1EC4C5F6778FD0728D36B94A40185D7A /* EXFileSystem */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXFileSystem; path = EXFileSystem.xcodeproj; sourceTree = ""; }; - 1FBDB8F24C5539045D8AE87F927FB3EE /* EXWebBrowser */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXWebBrowser; path = EXWebBrowser.xcodeproj; sourceTree = ""; }; - 21907930CDED304581AE9F8EF737DFC3 /* glog */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = glog; path = glog.xcodeproj; sourceTree = ""; }; - 228AECF796357BD0C17A0250B493CF46 /* RNGestureHandler */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RNGestureHandler; path = RNGestureHandler.xcodeproj; sourceTree = ""; }; - 24C2C1248498064540A1A0795384B075 /* UMConstantsInterface */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = UMConstantsInterface; path = UMConstantsInterface.xcodeproj; sourceTree = ""; }; - 2AFEBA4AE1BF044913C3A1F0ABCD7BEF /* React-RCTVibration */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "React-RCTVibration"; path = "React-RCTVibration.xcodeproj"; sourceTree = ""; }; - 3561DE58B3DAAE4AA0D0BC1C630862FA /* Analytics */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Analytics; path = Analytics.xcodeproj; sourceTree = ""; }; - 384191FF16B8310DB2CA32CE12714F26 /* EXAppAuth */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXAppAuth; path = EXAppAuth.xcodeproj; sourceTree = ""; }; - 3A6F2FEF94FB5051D0E15E0E75E061CE /* EXCellular */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXCellular; path = EXCellular.xcodeproj; sourceTree = ""; }; - 3E8F53A4E4A9F6D8E7270A1D59C0414A /* EXCrypto */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXCrypto; path = EXCrypto.xcodeproj; sourceTree = ""; }; - 469C509D4699E1DC0DF43F06F3A21FD4 /* EXMailComposer */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXMailComposer; path = EXMailComposer.xcodeproj; sourceTree = ""; }; - 4971CAC7D488A21F083090F5DF77441A /* EXPrint */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXPrint; path = EXPrint.xcodeproj; sourceTree = ""; }; - 4B81D9E849F7B0FF699CF47FC7F2EC7B /* React-Core */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "React-Core"; path = "React-Core.xcodeproj"; sourceTree = ""; }; - 4B8658D487323D6EEE125B5F57F06468 /* UMSensorsInterface */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = UMSensorsInterface; path = UMSensorsInterface.xcodeproj; sourceTree = ""; }; - 50C4358AD398837056C0C6E564E5FB45 /* RCTRequired */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTRequired; path = RCTRequired.xcodeproj; sourceTree = ""; }; - 53B70B73EBA72F4DB54EFB1201B958D9 /* React-RCTBlob */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "React-RCTBlob"; path = "React-RCTBlob.xcodeproj"; sourceTree = ""; }; - 559D179071A592B620836CC4F14A9F63 /* EXBlur */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXBlur; path = EXBlur.xcodeproj; sourceTree = ""; }; - 58F5BF4DBAF85B453DD79DA82B862E0A /* EXHaptics */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXHaptics; path = EXHaptics.xcodeproj; sourceTree = ""; }; - 59558382C9C14CEDEC8ECC99462044AC /* EXSMS */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXSMS; path = EXSMS.xcodeproj; sourceTree = ""; }; - 5C0692C4DCE5A6E01C6809F60A6FBB6E /* React-cxxreact */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "React-cxxreact"; path = "React-cxxreact.xcodeproj"; sourceTree = ""; }; - 5C7101C48EADF48A3F01ADAD195A0608 /* EXStoreReview */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXStoreReview; path = EXStoreReview.xcodeproj; sourceTree = ""; }; - 5F89074EFF9BBFF30A654696E06822C7 /* EXImageManipulator */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXImageManipulator; path = EXImageManipulator.xcodeproj; sourceTree = ""; }; - 621E66BDF9658FBAEB7835F073CC1D58 /* EXAV */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXAV; path = EXAV.xcodeproj; sourceTree = ""; }; - 63CC2109E824718DD6CF3ECF2951714F /* EXNetwork */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXNetwork; path = EXNetwork.xcodeproj; sourceTree = ""; }; - 66E0036061F06985A735F972DA873D82 /* EXCalendar */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXCalendar; path = EXCalendar.xcodeproj; sourceTree = ""; }; - 6790273ACF64FACB6F6C790F7465109B /* Amplitude-iOS */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "Amplitude-iOS"; path = "Amplitude-iOS.xcodeproj"; sourceTree = ""; }; + 0DCFBB69843FF7B3B3F4DBFA9395897F /* EXRandom */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXRandom; path = EXRandom.xcodeproj; sourceTree = ""; }; + 0E7C660C1D1A671A1C2C6E0A386E4F98 /* EXGoogleSignIn */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXGoogleSignIn; path = EXGoogleSignIn.xcodeproj; sourceTree = ""; }; + 0F4A4147605A8FA472874292E84CA8AA /* EXSMS */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXSMS; path = EXSMS.xcodeproj; sourceTree = ""; }; + 1291D1E0EF26BE30E64DFE7E772780FF /* EXSharing */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXSharing; path = EXSharing.xcodeproj; sourceTree = ""; }; + 154D415A4BF5B57E8E22F022EE88A1A2 /* Yoga */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Yoga; path = Yoga.xcodeproj; sourceTree = ""; }; + 1682454010CE1DE95AE1F2B800003AE8 /* EXSpeech */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXSpeech; path = EXSpeech.xcodeproj; sourceTree = ""; }; + 1874C56666647F9C71C26C490DCD0921 /* AppAuth */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = AppAuth; path = AppAuth.xcodeproj; sourceTree = ""; }; + 19518053F4B0ADB5DD067DBC654DCDC8 /* EXHaptics */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXHaptics; path = EXHaptics.xcodeproj; sourceTree = ""; }; + 1CEBDBC09F655F237DA82B43D4E56D1A /* EXConstants */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXConstants; path = EXConstants.xcodeproj; sourceTree = ""; }; + 20C29A1EAED431974F1F9ADE24297AD8 /* RNGestureHandler */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RNGestureHandler; path = RNGestureHandler.xcodeproj; sourceTree = ""; }; + 20EFB8787523F1F8E82C44E6D2318625 /* UMReactNativeAdapter */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = UMReactNativeAdapter; path = UMReactNativeAdapter.xcodeproj; sourceTree = ""; }; + 211D8213F75598D838AA142334A75A03 /* RCTRequired */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTRequired; path = RCTRequired.xcodeproj; sourceTree = ""; }; + 22B7962C5AC6F553566BDB321CDCBED7 /* Analytics */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Analytics; path = Analytics.xcodeproj; sourceTree = ""; }; + 24D571065DC8E7D78DE3D281B7F9665E /* EXImagePicker */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXImagePicker; path = EXImagePicker.xcodeproj; sourceTree = ""; }; + 283EB81A8B2631DC912F91F2E743D805 /* UMCameraInterface */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = UMCameraInterface; path = UMCameraInterface.xcodeproj; sourceTree = ""; }; + 2B3EF7E45E25388E46088AEF724044E2 /* EXGL_CPP */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXGL_CPP; path = EXGL_CPP.xcodeproj; sourceTree = ""; }; + 2D820764336141EB6A64FB5E39379B84 /* EXSQLite */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXSQLite; path = EXSQLite.xcodeproj; sourceTree = ""; }; + 2DFD1D139E40516EB3C8592132C16563 /* React-RCTBlob */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "React-RCTBlob"; path = "React-RCTBlob.xcodeproj"; sourceTree = ""; }; + 2FA4EA22672E5A6B552140467F83F0D5 /* UMImageLoaderInterface */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = UMImageLoaderInterface; path = UMImageLoaderInterface.xcodeproj; sourceTree = ""; }; + 31ED0F047A312EAA2BE054E15BB3DA57 /* EXFont */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXFont; path = EXFont.xcodeproj; sourceTree = ""; }; + 37D51A279F61ACA707D2DDB2B4775260 /* react-native-safe-area-context */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "react-native-safe-area-context"; path = "react-native-safe-area-context.xcodeproj"; sourceTree = ""; }; + 38C1D46D658188871C901CE039368D2B /* GoogleSignIn */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GoogleSignIn; path = GoogleSignIn.xcodeproj; sourceTree = ""; }; + 39600D89716D9EF152089FCE92F9611F /* React-RCTText */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "React-RCTText"; path = "React-RCTText.xcodeproj"; sourceTree = ""; }; + 3AC85EC6EA5A15DE1A14AC44693B3FAF /* EXLocalization */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXLocalization; path = EXLocalization.xcodeproj; sourceTree = ""; }; + 3BA6FCAA80CA6709FC129B2F8F1455D9 /* Folly */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Folly; path = Folly.xcodeproj; sourceTree = ""; }; + 3F7A24830AA6A74FD093D740F10D7773 /* EXKeepAwake */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXKeepAwake; path = EXKeepAwake.xcodeproj; sourceTree = ""; }; + 42DD6321E59344D440B1F51FE3CF79E7 /* ReactCommon */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ReactCommon; path = ReactCommon.xcodeproj; sourceTree = ""; }; + 4830F218FE12E25D199C4BF46791F52C /* EXBrightness */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXBrightness; path = EXBrightness.xcodeproj; sourceTree = ""; }; + 486D05376E4B939AAAA46292A4C1EDC5 /* React-RCTAnimation */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "React-RCTAnimation"; path = "React-RCTAnimation.xcodeproj"; sourceTree = ""; }; + 4915DBB1FD2CAFEC6F31A56C0C6957F2 /* GTMSessionFetcher */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GTMSessionFetcher; path = GTMSessionFetcher.xcodeproj; sourceTree = ""; }; + 4A75B063423ACC708261B1E2E6A5AF72 /* EXBluetooth */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXBluetooth; path = EXBluetooth.xcodeproj; sourceTree = ""; }; + 4A8C2D314E95B84D433DB3EC5D0248A8 /* EXMailComposer */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXMailComposer; path = EXMailComposer.xcodeproj; sourceTree = ""; }; + 4F6D317BD66107DED81B141CC7C9862B /* EXCalendar */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXCalendar; path = EXCalendar.xcodeproj; sourceTree = ""; }; + 5370504E9C2AB0A5A79DCDA80512DF63 /* EXNotifications */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXNotifications; path = EXNotifications.xcodeproj; sourceTree = ""; }; + 539904AF85D455EEA0BC80314430F767 /* React-RCTLinking */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "React-RCTLinking"; path = "React-RCTLinking.xcodeproj"; sourceTree = ""; }; + 5C904EB0F8D09A9D6A2CA1D9E5FB1A5E /* FBReactNativeSpec */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = FBReactNativeSpec; path = FBReactNativeSpec.xcodeproj; sourceTree = ""; }; + 5E612F91AF7A9DFF650E744D5DDDE6BB /* EXNetwork */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXNetwork; path = EXNetwork.xcodeproj; sourceTree = ""; }; + 5ED0F47567E19D563562378CB541F063 /* React-jsiexecutor */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "React-jsiexecutor"; path = "React-jsiexecutor.xcodeproj"; sourceTree = ""; }; + 602F1AC40936205BAA0B2DB343047BC2 /* FBLazyVector */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = FBLazyVector; path = FBLazyVector.xcodeproj; sourceTree = ""; }; + 67E8A05962A87D9D3E97F466C0588F3E /* EXBattery */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXBattery; path = EXBattery.xcodeproj; sourceTree = ""; }; + 69B62F0A6A5AE0185AB31AF2B50E6C73 /* EXContacts */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXContacts; path = EXContacts.xcodeproj; sourceTree = ""; }; 6D02C945BC67559AFEB7B446AD8A35E6 /* Pods-BareExpo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-BareExpo.debug.xcconfig"; sourceTree = ""; }; - 6F0ED87952B752BF2F6950D2DAB51472 /* EXContacts */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXContacts; path = EXContacts.xcodeproj; sourceTree = ""; }; - 6F2506A46EAB2A974A4A198BF26B5D11 /* UMCore */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = UMCore; path = UMCore.xcodeproj; sourceTree = ""; }; - 6FA7CD78D631158BDBE6D2A9C4FC19FB /* AppAuth */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = AppAuth; path = AppAuth.xcodeproj; sourceTree = ""; }; - 6FF66503720CEADA5339CA295727D2E6 /* EXBattery */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXBattery; path = EXBattery.xcodeproj; sourceTree = ""; }; - 73E1515109725296D25100C06DA91793 /* RCTTypeSafety */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTTypeSafety; path = RCTTypeSafety.xcodeproj; sourceTree = ""; }; - 7572990AACADFEEFE5EF8AF3A2415FD0 /* FBReactNativeSpec */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = FBReactNativeSpec; path = FBReactNativeSpec.xcodeproj; sourceTree = ""; }; - 7673391655AE15ABB96812EE718E18B3 /* EXBluetooth */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXBluetooth; path = EXBluetooth.xcodeproj; sourceTree = ""; }; + 6E562C149ACFF3572AF76219136BAE6F /* EXCellular */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXCellular; path = EXCellular.xcodeproj; sourceTree = ""; }; + 6FCCE9A29FCD2F955BD249B2E8FE64D6 /* React-RCTVibration */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "React-RCTVibration"; path = "React-RCTVibration.xcodeproj"; sourceTree = ""; }; + 6FE9E6378CCA409045A0D6F7725BD635 /* React-RCTImage */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "React-RCTImage"; path = "React-RCTImage.xcodeproj"; sourceTree = ""; }; + 72E97573157DD427D06035896E61A932 /* GTMAppAuth */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GTMAppAuth; path = GTMAppAuth.xcodeproj; sourceTree = ""; }; + 74FEDEFE688494CAE07748B5D758B147 /* EXBlur */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXBlur; path = EXBlur.xcodeproj; sourceTree = ""; }; + 766836226A2B4B63203538724CCB4F1C /* EXAmplitude */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXAmplitude; path = EXAmplitude.xcodeproj; sourceTree = ""; }; + 76D754AC0977B5323E742EEECB40AED4 /* EXStoreReview */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXStoreReview; path = EXStoreReview.xcodeproj; sourceTree = ""; }; + 790A2E685AC19C611733CE7F67102977 /* UMPermissionsInterface */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = UMPermissionsInterface; path = UMPermissionsInterface.xcodeproj; sourceTree = ""; }; 7BA510FA2B18C840471D62EB836D6A34 /* Pods-BareExpoTests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-BareExpoTests-acknowledgements.markdown"; sourceTree = ""; }; - 7C6CEDFBCA521989947F5B019C76054A /* React-RCTActionSheet */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "React-RCTActionSheet"; path = "React-RCTActionSheet.xcodeproj"; sourceTree = ""; }; + 7C365CF21BA55DFDF477C4C9CE32DCA1 /* EXPrint */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXPrint; path = EXPrint.xcodeproj; sourceTree = ""; }; + 81D1A93D40939D17C69ACA87E0F091B9 /* Amplitude-iOS */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "Amplitude-iOS"; path = "Amplitude-iOS.xcodeproj"; sourceTree = ""; }; + 83741058F1FBE8278A49685754C1020B /* React-RCTSettings */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "React-RCTSettings"; path = "React-RCTSettings.xcodeproj"; sourceTree = ""; }; + 837FB515358617F85BDF99978EE71115 /* glog */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = glog; path = glog.xcodeproj; sourceTree = ""; }; 8465E2FC705BE47B5397BF4A39C8AC18 /* Pods-BareExpoTests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-BareExpoTests-dummy.m"; sourceTree = ""; }; - 86F0EA4A0FCDB3FC734AE64574A90EBC /* react-native-safe-area-context */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "react-native-safe-area-context"; path = "react-native-safe-area-context.xcodeproj"; sourceTree = ""; }; + 847FD5ED7B8C4325822B875EFAC72828 /* RCTTypeSafety */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTTypeSafety; path = RCTTypeSafety.xcodeproj; sourceTree = ""; }; + 84BC96E6F93CA7ACABFB696BC390AAE4 /* DoubleConversion */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = DoubleConversion; path = DoubleConversion.xcodeproj; sourceTree = ""; }; + 85183E225D7A7272819751A43B77122A /* ZXingObjC */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ZXingObjC; path = ZXingObjC.xcodeproj; sourceTree = ""; }; 878E77864652C9881F9C85C3BC4CA6E7 /* libPods-BareExpoTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = "libPods-BareExpoTests.a"; path = "libPods-BareExpoTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 89B3742C40E8B4801826442347325BBF /* EXLocalization */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXLocalization; path = EXLocalization.xcodeproj; sourceTree = ""; }; - 8C472FA03A74CA155968F8B7216E490A /* EXSpeech */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXSpeech; path = EXSpeech.xcodeproj; sourceTree = ""; }; - 8DD091FE677FB13DC171D90C021CA7DE /* GTMAppAuth */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GTMAppAuth; path = GTMAppAuth.xcodeproj; sourceTree = ""; }; - 93A314050AEE5C54490FF76731532B5D /* React-RCTAnimation */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "React-RCTAnimation"; path = "React-RCTAnimation.xcodeproj"; sourceTree = ""; }; - 9530BB032E863145DD427DBC06A82F68 /* EXGoogleSignIn */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXGoogleSignIn; path = EXGoogleSignIn.xcodeproj; sourceTree = ""; }; - 966D82943A84614F0D90E09EED82FC4A /* EXAmplitude */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXAmplitude; path = EXAmplitude.xcodeproj; sourceTree = ""; }; - 9946A17BD11A68F7A944498FD73C8413 /* ZXingObjC */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ZXingObjC; path = ZXingObjC.xcodeproj; sourceTree = ""; }; - 9B3C09E1B51BE5C72B1178721DFB4736 /* EXSQLite */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXSQLite; path = EXSQLite.xcodeproj; sourceTree = ""; }; + 8BB89C73D41B6306783F6127102D17EE /* UMConstantsInterface */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = UMConstantsInterface; path = UMConstantsInterface.xcodeproj; sourceTree = ""; }; + 951A59FA6D6F13FE2BC2DC148092885D /* EXLinearGradient */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXLinearGradient; path = EXLinearGradient.xcodeproj; sourceTree = ""; }; + 99EC51DA27D3AF613938A01C65921965 /* UMCore */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = UMCore; path = UMCore.xcodeproj; sourceTree = ""; }; + 9CEAF6033593566F9D90D312481E1561 /* EXSegment */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXSegment; path = EXSegment.xcodeproj; sourceTree = ""; }; 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 9F278CA3578A1C7C742F5C39E58E8626 /* EXRandom */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXRandom; path = EXRandom.xcodeproj; sourceTree = ""; }; - 9F3B324040A71A156CE8681CBF0610AA /* EXUpdates */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXUpdates; path = EXUpdates.xcodeproj; sourceTree = ""; }; 9F3EED7C7CC54C74129840B0C037651C /* Pods-BareExpo-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-BareExpo-acknowledgements.markdown"; sourceTree = ""; }; - A14282E7B246C428EDC564624DBDD9BF /* UMBarCodeScannerInterface */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = UMBarCodeScannerInterface; path = UMBarCodeScannerInterface.xcodeproj; sourceTree = ""; }; - A1A9EF9126D232C7848495ED0D34FC82 /* UMFileSystemInterface */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = UMFileSystemInterface; path = UMFileSystemInterface.xcodeproj; sourceTree = ""; }; - A3F4A301606C753818F89B954CBABFFA /* React-CoreModules */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "React-CoreModules"; path = "React-CoreModules.xcodeproj"; sourceTree = ""; }; - A528590EDEA69FCB74BFA09B141B4DBF /* EXGL */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXGL; path = EXGL.xcodeproj; sourceTree = ""; }; - A82D7F91B76D88E3B3001116B85C6F8F /* EXKeepAwake */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXKeepAwake; path = EXKeepAwake.xcodeproj; sourceTree = ""; }; - A90F97E439A7BC54338B0DC132FB389F /* EXLocalAuthentication */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXLocalAuthentication; path = EXLocalAuthentication.xcodeproj; sourceTree = ""; }; - A9333E5CD08216B9D4D56A43F8AFFB5B /* EXDevice */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXDevice; path = EXDevice.xcodeproj; sourceTree = ""; }; - AF0568DC623CE5D3D2E159457E57B21F /* EXMediaLibrary */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXMediaLibrary; path = EXMediaLibrary.xcodeproj; sourceTree = ""; }; - AFBF976B0EF04C9912E08179B68D2308 /* EXBarCodeScanner */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXBarCodeScanner; path = EXBarCodeScanner.xcodeproj; sourceTree = ""; }; - B16FF31EB7B2D5E60E6685477B72EBC5 /* EXFont */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXFont; path = EXFont.xcodeproj; sourceTree = ""; }; - B1BC6698202B367C7B3129780457D544 /* EXGL_CPP */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXGL_CPP; path = EXGL_CPP.xcodeproj; sourceTree = ""; }; - B2F742EBD46D881CC735F4D4A4260119 /* Folly */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Folly; path = Folly.xcodeproj; sourceTree = ""; }; + 9FBF69DFB7386F17655AA92E47A91B88 /* EXLocalAuthentication */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXLocalAuthentication; path = EXLocalAuthentication.xcodeproj; sourceTree = ""; }; + A0472A19A0663233A80B3D04DF83139C /* EXAppLoaderProvider */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXAppLoaderProvider; path = EXAppLoaderProvider.xcodeproj; sourceTree = ""; }; + A0F40A7EF94F9CDB1C9EC3706EF31977 /* EXFileSystem */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXFileSystem; path = EXFileSystem.xcodeproj; sourceTree = ""; }; + A31EA7E16D8F9F37E83632B7A9BD49BD /* UMFontInterface */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = UMFontInterface; path = UMFontInterface.xcodeproj; sourceTree = ""; }; + A32518B2BC57B6ACB06728AD31C6FED7 /* React-jsinspector */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "React-jsinspector"; path = "React-jsinspector.xcodeproj"; sourceTree = ""; }; + A5F35E9471A25BAFEB3AB53EDB2E48BD /* UMBarCodeScannerInterface */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = UMBarCodeScannerInterface; path = UMBarCodeScannerInterface.xcodeproj; sourceTree = ""; }; + AC64B72943BF5A964B4BEA5D03352E8A /* React-Core */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "React-Core"; path = "React-Core.xcodeproj"; sourceTree = ""; }; + ACDF0A1622DDFFECE9C4DD356D1BA970 /* EXDevice */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXDevice; path = EXDevice.xcodeproj; sourceTree = ""; }; + AF9B03AFD3122203FA523C331045B557 /* EXErrorRecovery */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXErrorRecovery; path = EXErrorRecovery.xcodeproj; sourceTree = ""; }; + B399F6209661F0C9597B9B02C293119F /* EXPermissions */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXPermissions; path = EXPermissions.xcodeproj; sourceTree = ""; }; B54740B002D716FDD124C76801E0EAB3 /* Pods-BareExpoTests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-BareExpoTests-acknowledgements.plist"; sourceTree = ""; }; + B79AA8F0753060DE025621A58BF10081 /* EXSecureStore */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXSecureStore; path = EXSecureStore.xcodeproj; sourceTree = ""; }; + B79E739FDB18023D4C8E4264D5CE84D3 /* EXGL */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXGL; path = EXGL.xcodeproj; sourceTree = ""; }; B9129F18779266F08BA65232D729B5FC /* Pods-BareExpo-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-BareExpo-resources.sh"; sourceTree = ""; }; - B95E106A906DA6BC3B1AE32B1476EC96 /* React-RCTText */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "React-RCTText"; path = "React-RCTText.xcodeproj"; sourceTree = ""; }; - BAD136761E20C0CF271C8994F81BE4E8 /* UMCameraInterface */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = UMCameraInterface; path = UMCameraInterface.xcodeproj; sourceTree = ""; }; - BB09D5AC4BEBC2617D9D95C54475FA09 /* React */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React; path = React.xcodeproj; sourceTree = ""; }; - C099422E2DC2875E807A665C97BCC571 /* FBLazyVector */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = FBLazyVector; path = FBLazyVector.xcodeproj; sourceTree = ""; }; - C2EA603A6A2597676F274428E05872B9 /* React-jsiexecutor */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "React-jsiexecutor"; path = "React-jsiexecutor.xcodeproj"; sourceTree = ""; }; - C3F1268A122894A50E585D0D43F60664 /* React-RCTNetwork */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "React-RCTNetwork"; path = "React-RCTNetwork.xcodeproj"; sourceTree = ""; }; + BFC20E8D25AC617CEF09AEE4F3B6447C /* EXUpdates */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXUpdates; path = EXUpdates.xcodeproj; sourceTree = ""; }; + C307D52AB4940565B4FE24E5B2BA7277 /* EXMediaLibrary */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXMediaLibrary; path = EXMediaLibrary.xcodeproj; sourceTree = ""; }; C42944AE78D3C85AE9277FE320D54C35 /* Pods-BareExpo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-BareExpo.release.xcconfig"; sourceTree = ""; }; - C4691EC6027337FE88F7B6C142C79DA9 /* EXLinearGradient */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXLinearGradient; path = EXLinearGradient.xcodeproj; sourceTree = ""; }; + C48CFC9D9BAC60B4713D773CBCC18138 /* React-RCTActionSheet */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "React-RCTActionSheet"; path = "React-RCTActionSheet.xcodeproj"; sourceTree = ""; }; C4A8AD09B0987CCC643BCC6FFC68B2AE /* Pods-BareExpoTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-BareExpoTests.debug.xcconfig"; sourceTree = ""; }; - D06CF6E8B5CE7D5A760E443475289B14 /* UMImageLoaderInterface */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = UMImageLoaderInterface; path = UMImageLoaderInterface.xcodeproj; sourceTree = ""; }; + C82A773803E9590719BF9B2ADBDC8853 /* RNReanimated */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RNReanimated; path = RNReanimated.xcodeproj; sourceTree = ""; }; + CF1C7256B0751DFBBBC3C32DA058F9B2 /* EXAV */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXAV; path = EXAV.xcodeproj; sourceTree = ""; }; D090CDB16B158897ECDA29AE3E2FDBF6 /* Pods-BareExpo-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-BareExpo-dummy.m"; sourceTree = ""; }; + D0A15388E6A79D84E72CB78529279E0C /* React-CoreModules */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "React-CoreModules"; path = "React-CoreModules.xcodeproj"; sourceTree = ""; }; D1014EA3C6789E7FAA1DC562E34C204D /* libPods-BareExpo.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = "libPods-BareExpo.a"; path = "libPods-BareExpo.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - D1D370A1C813FC6C49069D6F265F56E3 /* EXErrorRecovery */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXErrorRecovery; path = EXErrorRecovery.xcodeproj; sourceTree = ""; }; + D1A3C1892F717A0516FC6E06862425AD /* React-cxxreact */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "React-cxxreact"; path = "React-cxxreact.xcodeproj"; sourceTree = ""; }; + D295C7698687650B201A4E18B1A6CE87 /* React */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React; path = React.xcodeproj; sourceTree = ""; }; D48CF9AF6779F366D43DAFA00F78BE5E /* Pods-BareExpo-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-BareExpo-acknowledgements.plist"; sourceTree = ""; }; - D58517F1F49DD7F710C941D73B419B5C /* EXAppLoaderProvider */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXAppLoaderProvider; path = EXAppLoaderProvider.xcodeproj; sourceTree = ""; }; - D5E45FC61A6D2D7E3F46F8A281EA7F64 /* UMReactNativeAdapter */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = UMReactNativeAdapter; path = UMReactNativeAdapter.xcodeproj; sourceTree = ""; }; - D7D345E8C3BC6E50CBED042829BBF090 /* EXSensors */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXSensors; path = EXSensors.xcodeproj; sourceTree = ""; }; - E17942621B3C5C442DAEF9E85EE80964 /* GoogleSignIn */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GoogleSignIn; path = GoogleSignIn.xcodeproj; sourceTree = ""; }; - E3C83D9BB0BF020DE9E3EA402FF40418 /* EXDocumentPicker */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXDocumentPicker; path = EXDocumentPicker.xcodeproj; sourceTree = ""; }; - EC64490903CB102FA5D88F9FD8D4873B /* DoubleConversion */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = DoubleConversion; path = DoubleConversion.xcodeproj; sourceTree = ""; }; - EC8B540ED755EDCB2AE686784D3AF479 /* EXApplication */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXApplication; path = EXApplication.xcodeproj; sourceTree = ""; }; - ED50116F92CAB9F1E06FE905363CE060 /* EXPermissions */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXPermissions; path = EXPermissions.xcodeproj; sourceTree = ""; }; - EF2B74AE23B4D085A4D41634852D9E79 /* EXSecureStore */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXSecureStore; path = EXSecureStore.xcodeproj; sourceTree = ""; }; - F6C89811BEB495795C6F1B805FCF9133 /* GTMSessionFetcher */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GTMSessionFetcher; path = GTMSessionFetcher.xcodeproj; sourceTree = ""; }; - F93842B2AFB5431663D17D6C8B0DAD27 /* UMPermissionsInterface */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = UMPermissionsInterface; path = UMPermissionsInterface.xcodeproj; sourceTree = ""; }; - FC694360F93EB50AF01BD9AD3DDF6F63 /* React-RCTLinking */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "React-RCTLinking"; path = "React-RCTLinking.xcodeproj"; sourceTree = ""; }; + D78B6B55B6F370CFD13934B2CC9B6119 /* EXDocumentPicker */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXDocumentPicker; path = EXDocumentPicker.xcodeproj; sourceTree = ""; }; + D88FC63D8F76640F60314E4A5077FD31 /* EXAppAuth */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXAppAuth; path = EXAppAuth.xcodeproj; sourceTree = ""; }; + D9159EDE5B081372F59C922A6F771D88 /* EXWebBrowser */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXWebBrowser; path = EXWebBrowser.xcodeproj; sourceTree = ""; }; + D918720DA8177424E16B7D398B1E42BA /* React-RCTNetwork */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "React-RCTNetwork"; path = "React-RCTNetwork.xcodeproj"; sourceTree = ""; }; + DD26F4B8BC160D314045C1E9FF99E1C0 /* UMFileSystemInterface */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = UMFileSystemInterface; path = UMFileSystemInterface.xcodeproj; sourceTree = ""; }; + E35074979A21EA433E91AFF284E3AC50 /* EXSensors */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXSensors; path = EXSensors.xcodeproj; sourceTree = ""; }; + E3D4951BFB897802566871A47737F1EE /* EXCrypto */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXCrypto; path = EXCrypto.xcodeproj; sourceTree = ""; }; + E6C81641E33F90B0058BD7F47E6F95F4 /* boost-for-react-native */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "boost-for-react-native"; path = "boost-for-react-native.xcodeproj"; sourceTree = ""; }; + EBA46FF6FE79918F2108E6350176703C /* EXApplication */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXApplication; path = EXApplication.xcodeproj; sourceTree = ""; }; + F1BA3A37FBB21699CAA6831FD7EA7A4B /* EXBarCodeScanner */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXBarCodeScanner; path = EXBarCodeScanner.xcodeproj; sourceTree = ""; }; + F5378BC6DC876907C7D4762A994635E1 /* UMSensorsInterface */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = UMSensorsInterface; path = UMSensorsInterface.xcodeproj; sourceTree = ""; }; + FA3F1AFA57847B7DE0AAEDF4186FC4BF /* React-jsi */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "React-jsi"; path = "React-jsi.xcodeproj"; sourceTree = ""; }; + FBDB34F0ECB442D367E68748ADA3820F /* EXImageManipulator */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EXImageManipulator; path = EXImageManipulator.xcodeproj; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -782,7 +790,7 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - DB7DC0C1E6C2D56F295B8748F348E613 /* Frameworks */ = { + EA79F5789FD7E159BC6D17FAB7102A55 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( @@ -792,27 +800,6 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 3F99B2263C0408AD869FFB149189BBD1 /* Pods */ = { - isa = PBXGroup; - children = ( - 6790273ACF64FACB6F6C790F7465109B /* Amplitude-iOS */, - 3561DE58B3DAAE4AA0D0BC1C630862FA /* Analytics */, - 6FA7CD78D631158BDBE6D2A9C4FC19FB /* AppAuth */, - 06A760ACB1990444FA093A6D7A8AC2EB /* boost-for-react-native */, - EC64490903CB102FA5D88F9FD8D4873B /* DoubleConversion */, - B2F742EBD46D881CC735F4D4A4260119 /* Folly */, - 21907930CDED304581AE9F8EF737DFC3 /* glog */, - E17942621B3C5C442DAEF9E85EE80964 /* GoogleSignIn */, - 8DD091FE677FB13DC171D90C021CA7DE /* GTMAppAuth */, - F6C89811BEB495795C6F1B805FCF9133 /* GTMSessionFetcher */, - 86F0EA4A0FCDB3FC734AE64574A90EBC /* react-native-safe-area-context */, - 228AECF796357BD0C17A0250B493CF46 /* RNGestureHandler */, - 093F33B91AB6CCF24EC5B44C2168D6B7 /* RNReanimated */, - 9946A17BD11A68F7A944498FD73C8413 /* ZXingObjC */, - ); - name = Pods; - sourceTree = ""; - }; 47A0FFA7A01C9BA895E5664886E9B952 /* Targets Support Files */ = { isa = PBXGroup; children = ( @@ -836,18 +823,125 @@ path = "Target Support Files/Pods-BareExpo"; sourceTree = ""; }; + 765BFFF755F3BFE5DF6F3E415809E0E2 /* Development Pods */ = { + isa = PBXGroup; + children = ( + 766836226A2B4B63203538724CCB4F1C /* EXAmplitude */, + D88FC63D8F76640F60314E4A5077FD31 /* EXAppAuth */, + EBA46FF6FE79918F2108E6350176703C /* EXApplication */, + A0472A19A0663233A80B3D04DF83139C /* EXAppLoaderProvider */, + CF1C7256B0751DFBBBC3C32DA058F9B2 /* EXAV */, + F1BA3A37FBB21699CAA6831FD7EA7A4B /* EXBarCodeScanner */, + 67E8A05962A87D9D3E97F466C0588F3E /* EXBattery */, + 4A75B063423ACC708261B1E2E6A5AF72 /* EXBluetooth */, + 74FEDEFE688494CAE07748B5D758B147 /* EXBlur */, + 4830F218FE12E25D199C4BF46791F52C /* EXBrightness */, + 4F6D317BD66107DED81B141CC7C9862B /* EXCalendar */, + 6E562C149ACFF3572AF76219136BAE6F /* EXCellular */, + 1CEBDBC09F655F237DA82B43D4E56D1A /* EXConstants */, + 69B62F0A6A5AE0185AB31AF2B50E6C73 /* EXContacts */, + E3D4951BFB897802566871A47737F1EE /* EXCrypto */, + ACDF0A1622DDFFECE9C4DD356D1BA970 /* EXDevice */, + D78B6B55B6F370CFD13934B2CC9B6119 /* EXDocumentPicker */, + AF9B03AFD3122203FA523C331045B557 /* EXErrorRecovery */, + A0F40A7EF94F9CDB1C9EC3706EF31977 /* EXFileSystem */, + 31ED0F047A312EAA2BE054E15BB3DA57 /* EXFont */, + B79E739FDB18023D4C8E4264D5CE84D3 /* EXGL */, + 2B3EF7E45E25388E46088AEF724044E2 /* EXGL_CPP */, + 0E7C660C1D1A671A1C2C6E0A386E4F98 /* EXGoogleSignIn */, + 19518053F4B0ADB5DD067DBC654DCDC8 /* EXHaptics */, + FBDB34F0ECB442D367E68748ADA3820F /* EXImageManipulator */, + 24D571065DC8E7D78DE3D281B7F9665E /* EXImagePicker */, + 3F7A24830AA6A74FD093D740F10D7773 /* EXKeepAwake */, + 951A59FA6D6F13FE2BC2DC148092885D /* EXLinearGradient */, + 9FBF69DFB7386F17655AA92E47A91B88 /* EXLocalAuthentication */, + 3AC85EC6EA5A15DE1A14AC44693B3FAF /* EXLocalization */, + 4A8C2D314E95B84D433DB3EC5D0248A8 /* EXMailComposer */, + C307D52AB4940565B4FE24E5B2BA7277 /* EXMediaLibrary */, + 5E612F91AF7A9DFF650E744D5DDDE6BB /* EXNetwork */, + 5370504E9C2AB0A5A79DCDA80512DF63 /* EXNotifications */, + B399F6209661F0C9597B9B02C293119F /* EXPermissions */, + 7C365CF21BA55DFDF477C4C9CE32DCA1 /* EXPrint */, + 0DCFBB69843FF7B3B3F4DBFA9395897F /* EXRandom */, + B79AA8F0753060DE025621A58BF10081 /* EXSecureStore */, + 9CEAF6033593566F9D90D312481E1561 /* EXSegment */, + E35074979A21EA433E91AFF284E3AC50 /* EXSensors */, + 1291D1E0EF26BE30E64DFE7E772780FF /* EXSharing */, + 0F4A4147605A8FA472874292E84CA8AA /* EXSMS */, + 1682454010CE1DE95AE1F2B800003AE8 /* EXSpeech */, + 2D820764336141EB6A64FB5E39379B84 /* EXSQLite */, + 76D754AC0977B5323E742EEECB40AED4 /* EXStoreReview */, + BFC20E8D25AC617CEF09AEE4F3B6447C /* EXUpdates */, + D9159EDE5B081372F59C922A6F771D88 /* EXWebBrowser */, + 602F1AC40936205BAA0B2DB343047BC2 /* FBLazyVector */, + 5C904EB0F8D09A9D6A2CA1D9E5FB1A5E /* FBReactNativeSpec */, + 211D8213F75598D838AA142334A75A03 /* RCTRequired */, + 847FD5ED7B8C4325822B875EFAC72828 /* RCTTypeSafety */, + D295C7698687650B201A4E18B1A6CE87 /* React */, + AC64B72943BF5A964B4BEA5D03352E8A /* React-Core */, + D0A15388E6A79D84E72CB78529279E0C /* React-CoreModules */, + D1A3C1892F717A0516FC6E06862425AD /* React-cxxreact */, + FA3F1AFA57847B7DE0AAEDF4186FC4BF /* React-jsi */, + 5ED0F47567E19D563562378CB541F063 /* React-jsiexecutor */, + A32518B2BC57B6ACB06728AD31C6FED7 /* React-jsinspector */, + C48CFC9D9BAC60B4713D773CBCC18138 /* React-RCTActionSheet */, + 486D05376E4B939AAAA46292A4C1EDC5 /* React-RCTAnimation */, + 2DFD1D139E40516EB3C8592132C16563 /* React-RCTBlob */, + 6FE9E6378CCA409045A0D6F7725BD635 /* React-RCTImage */, + 539904AF85D455EEA0BC80314430F767 /* React-RCTLinking */, + D918720DA8177424E16B7D398B1E42BA /* React-RCTNetwork */, + 83741058F1FBE8278A49685754C1020B /* React-RCTSettings */, + 39600D89716D9EF152089FCE92F9611F /* React-RCTText */, + 6FCCE9A29FCD2F955BD249B2E8FE64D6 /* React-RCTVibration */, + 42DD6321E59344D440B1F51FE3CF79E7 /* ReactCommon */, + A5F35E9471A25BAFEB3AB53EDB2E48BD /* UMBarCodeScannerInterface */, + 283EB81A8B2631DC912F91F2E743D805 /* UMCameraInterface */, + 8BB89C73D41B6306783F6127102D17EE /* UMConstantsInterface */, + 99EC51DA27D3AF613938A01C65921965 /* UMCore */, + DD26F4B8BC160D314045C1E9FF99E1C0 /* UMFileSystemInterface */, + A31EA7E16D8F9F37E83632B7A9BD49BD /* UMFontInterface */, + 2FA4EA22672E5A6B552140467F83F0D5 /* UMImageLoaderInterface */, + 790A2E685AC19C611733CE7F67102977 /* UMPermissionsInterface */, + 20EFB8787523F1F8E82C44E6D2318625 /* UMReactNativeAdapter */, + F5378BC6DC876907C7D4762A994635E1 /* UMSensorsInterface */, + 154D415A4BF5B57E8E22F022EE88A1A2 /* Yoga */, + ); + name = "Development Pods"; + sourceTree = ""; + }; CF1408CF629C7361332E53B88F7BD30C = { isa = PBXGroup; children = ( 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, - F390F7E91E479D81DED26468230696EB /* Development Pods */, + 765BFFF755F3BFE5DF6F3E415809E0E2 /* Development Pods */, D89477F20FB1DE18A04690586D7808C4 /* Frameworks */, - 3F99B2263C0408AD869FFB149189BBD1 /* Pods */, + CF4891EF1B4F2322C4C03D1D33013C8F /* Pods */, E71A1A9A54AF9481ED09CD84DBFA729C /* Products */, 47A0FFA7A01C9BA895E5664886E9B952 /* Targets Support Files */, ); sourceTree = ""; }; + CF4891EF1B4F2322C4C03D1D33013C8F /* Pods */ = { + isa = PBXGroup; + children = ( + 81D1A93D40939D17C69ACA87E0F091B9 /* Amplitude-iOS */, + 22B7962C5AC6F553566BDB321CDCBED7 /* Analytics */, + 1874C56666647F9C71C26C490DCD0921 /* AppAuth */, + E6C81641E33F90B0058BD7F47E6F95F4 /* boost-for-react-native */, + 84BC96E6F93CA7ACABFB696BC390AAE4 /* DoubleConversion */, + 3BA6FCAA80CA6709FC129B2F8F1455D9 /* Folly */, + 837FB515358617F85BDF99978EE71115 /* glog */, + 38C1D46D658188871C901CE039368D2B /* GoogleSignIn */, + 72E97573157DD427D06035896E61A932 /* GTMAppAuth */, + 4915DBB1FD2CAFEC6F31A56C0C6957F2 /* GTMSessionFetcher */, + 37D51A279F61ACA707D2DDB2B4775260 /* react-native-safe-area-context */, + 20C29A1EAED431974F1F9ADE24297AD8 /* RNGestureHandler */, + C82A773803E9590719BF9B2ADBDC8853 /* RNReanimated */, + 85183E225D7A7272819751A43B77122A /* ZXingObjC */, + ); + name = Pods; + sourceTree = ""; + }; D89477F20FB1DE18A04690586D7808C4 /* Frameworks */ = { isa = PBXGroup; children = ( @@ -877,102 +971,17 @@ path = "Target Support Files/Pods-BareExpoTests"; sourceTree = ""; }; - F390F7E91E479D81DED26468230696EB /* Development Pods */ = { - isa = PBXGroup; - children = ( - 966D82943A84614F0D90E09EED82FC4A /* EXAmplitude */, - 384191FF16B8310DB2CA32CE12714F26 /* EXAppAuth */, - EC8B540ED755EDCB2AE686784D3AF479 /* EXApplication */, - D58517F1F49DD7F710C941D73B419B5C /* EXAppLoaderProvider */, - 621E66BDF9658FBAEB7835F073CC1D58 /* EXAV */, - AFBF976B0EF04C9912E08179B68D2308 /* EXBarCodeScanner */, - 6FF66503720CEADA5339CA295727D2E6 /* EXBattery */, - 7673391655AE15ABB96812EE718E18B3 /* EXBluetooth */, - 559D179071A592B620836CC4F14A9F63 /* EXBlur */, - 00D632F97A746F8FBEE5FD654C95A5D4 /* EXBrightness */, - 66E0036061F06985A735F972DA873D82 /* EXCalendar */, - 3A6F2FEF94FB5051D0E15E0E75E061CE /* EXCellular */, - 0F87C4C729C750646FF9170E107841D0 /* EXConstants */, - 6F0ED87952B752BF2F6950D2DAB51472 /* EXContacts */, - 3E8F53A4E4A9F6D8E7270A1D59C0414A /* EXCrypto */, - A9333E5CD08216B9D4D56A43F8AFFB5B /* EXDevice */, - E3C83D9BB0BF020DE9E3EA402FF40418 /* EXDocumentPicker */, - D1D370A1C813FC6C49069D6F265F56E3 /* EXErrorRecovery */, - 1EC4C5F6778FD0728D36B94A40185D7A /* EXFileSystem */, - B16FF31EB7B2D5E60E6685477B72EBC5 /* EXFont */, - A528590EDEA69FCB74BFA09B141B4DBF /* EXGL */, - B1BC6698202B367C7B3129780457D544 /* EXGL_CPP */, - 9530BB032E863145DD427DBC06A82F68 /* EXGoogleSignIn */, - 58F5BF4DBAF85B453DD79DA82B862E0A /* EXHaptics */, - 5F89074EFF9BBFF30A654696E06822C7 /* EXImageManipulator */, - 081775E5E1E22CD733CEC31DEC05391D /* EXImagePicker */, - A82D7F91B76D88E3B3001116B85C6F8F /* EXKeepAwake */, - C4691EC6027337FE88F7B6C142C79DA9 /* EXLinearGradient */, - A90F97E439A7BC54338B0DC132FB389F /* EXLocalAuthentication */, - 89B3742C40E8B4801826442347325BBF /* EXLocalization */, - 469C509D4699E1DC0DF43F06F3A21FD4 /* EXMailComposer */, - AF0568DC623CE5D3D2E159457E57B21F /* EXMediaLibrary */, - 63CC2109E824718DD6CF3ECF2951714F /* EXNetwork */, - ED50116F92CAB9F1E06FE905363CE060 /* EXPermissions */, - 4971CAC7D488A21F083090F5DF77441A /* EXPrint */, - 9F278CA3578A1C7C742F5C39E58E8626 /* EXRandom */, - EF2B74AE23B4D085A4D41634852D9E79 /* EXSecureStore */, - 0CCA7AB54711A1C565D9146E86AF6FE5 /* EXSegment */, - D7D345E8C3BC6E50CBED042829BBF090 /* EXSensors */, - 1CA025FC93211998774902CC4663DD61 /* EXSharing */, - 59558382C9C14CEDEC8ECC99462044AC /* EXSMS */, - 8C472FA03A74CA155968F8B7216E490A /* EXSpeech */, - 9B3C09E1B51BE5C72B1178721DFB4736 /* EXSQLite */, - 5C7101C48EADF48A3F01ADAD195A0608 /* EXStoreReview */, - 9F3B324040A71A156CE8681CBF0610AA /* EXUpdates */, - 1FBDB8F24C5539045D8AE87F927FB3EE /* EXWebBrowser */, - C099422E2DC2875E807A665C97BCC571 /* FBLazyVector */, - 7572990AACADFEEFE5EF8AF3A2415FD0 /* FBReactNativeSpec */, - 50C4358AD398837056C0C6E564E5FB45 /* RCTRequired */, - 73E1515109725296D25100C06DA91793 /* RCTTypeSafety */, - BB09D5AC4BEBC2617D9D95C54475FA09 /* React */, - 4B81D9E849F7B0FF699CF47FC7F2EC7B /* React-Core */, - A3F4A301606C753818F89B954CBABFFA /* React-CoreModules */, - 5C0692C4DCE5A6E01C6809F60A6FBB6E /* React-cxxreact */, - 01CFA74EFC65BCFDF41AE2DB0615EED8 /* React-jsi */, - C2EA603A6A2597676F274428E05872B9 /* React-jsiexecutor */, - 0143F693E54C76D9CEC9B89D39EA738C /* React-jsinspector */, - 7C6CEDFBCA521989947F5B019C76054A /* React-RCTActionSheet */, - 93A314050AEE5C54490FF76731532B5D /* React-RCTAnimation */, - 53B70B73EBA72F4DB54EFB1201B958D9 /* React-RCTBlob */, - 04AF6CFC908ABC897934A123721DCDC8 /* React-RCTImage */, - FC694360F93EB50AF01BD9AD3DDF6F63 /* React-RCTLinking */, - C3F1268A122894A50E585D0D43F60664 /* React-RCTNetwork */, - 00E9EF1B95C123998456AA100CE87025 /* React-RCTSettings */, - B95E106A906DA6BC3B1AE32B1476EC96 /* React-RCTText */, - 2AFEBA4AE1BF044913C3A1F0ABCD7BEF /* React-RCTVibration */, - 11A32ED6BFC7435B83A74B68227CF672 /* ReactCommon */, - A14282E7B246C428EDC564624DBDD9BF /* UMBarCodeScannerInterface */, - BAD136761E20C0CF271C8994F81BE4E8 /* UMCameraInterface */, - 24C2C1248498064540A1A0795384B075 /* UMConstantsInterface */, - 6F2506A46EAB2A974A4A198BF26B5D11 /* UMCore */, - A1A9EF9126D232C7848495ED0D34FC82 /* UMFileSystemInterface */, - 10773CD4E5B8A755D9E0D42FC649AEB4 /* UMFontInterface */, - D06CF6E8B5CE7D5A760E443475289B14 /* UMImageLoaderInterface */, - F93842B2AFB5431663D17D6C8B0DAD27 /* UMPermissionsInterface */, - D5E45FC61A6D2D7E3F46F8A281EA7F64 /* UMReactNativeAdapter */, - 4B8658D487323D6EEE125B5F57F06468 /* UMSensorsInterface */, - 068283BA3523101E0BA7F90CEB90A6A1 /* Yoga */, - ); - name = "Development Pods"; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 8ED90DC5716F75FECF5D5B4BD8C3C21E /* Headers */ = { + 1CBFA6108973A78F755F58805BCCC094 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - FA3600A7F5008DE2BE1E3B6AA43CAA1C /* Headers */ = { + 8ED90DC5716F75FECF5D5B4BD8C3C21E /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( @@ -1002,107 +1011,108 @@ }; C616BB9F650D110E835D02A3250F302E /* Pods-BareExpo */ = { isa = PBXNativeTarget; - buildConfigurationList = 19B0920102FB081C56D8699A0F9D676E /* Build configuration list for PBXNativeTarget "Pods-BareExpo" */; + buildConfigurationList = A832C04A5E806A099A7BB7DE00106985 /* Build configuration list for PBXNativeTarget "Pods-BareExpo" */; buildPhases = ( - FA3600A7F5008DE2BE1E3B6AA43CAA1C /* Headers */, - 0B99572B5B1932951237131C16FBB9C7 /* Sources */, - DB7DC0C1E6C2D56F295B8748F348E613 /* Frameworks */, + 1CBFA6108973A78F755F58805BCCC094 /* Headers */, + 2B5408C2A80FFB629A3932BF9BCC394E /* Sources */, + EA79F5789FD7E159BC6D17FAB7102A55 /* Frameworks */, ); buildRules = ( ); dependencies = ( - 91D2A06942280D2149E8D2FECE2139DA /* PBXTargetDependency */, - 68583D60CD1D2FCEE73CF16A926196A3 /* PBXTargetDependency */, - CB74FAEC6179ED8E6DA650BC436B0217 /* PBXTargetDependency */, - 5CC4BF5204B9D14211D9845D3CCE8B3A /* PBXTargetDependency */, - 49ED00B0339E6859EE2CF1B4112EBA9C /* PBXTargetDependency */, - 216CEB250607CD8D1847439AA9943219 /* PBXTargetDependency */, - EB510BB4F1A396F8FBC810E5DE644C4A /* PBXTargetDependency */, - 3B41B5F91EC84A9F522A725288F03622 /* PBXTargetDependency */, - E69875FB639872DAE546EF4B38A99FFC /* PBXTargetDependency */, - 0B3198B72438B14E12C3547AEFF35817 /* PBXTargetDependency */, - 5E5513B0C5190451B739B75885958F81 /* PBXTargetDependency */, - 3C1825C8E667A847B094BC84710EB57D /* PBXTargetDependency */, - 7ED59F0C6BB5C3C97A81252A98FDD60D /* PBXTargetDependency */, - CFEB7B078D667D898DCC8EEEF1FC5C82 /* PBXTargetDependency */, - 835E57D62A25653590E6A4879FE2E498 /* PBXTargetDependency */, - 0C6704A85B88110C459780D3DC0D42AE /* PBXTargetDependency */, - CC0B2B3947F5D1DB5CCBEC92CDE90B59 /* PBXTargetDependency */, - 57D398309C4C6FD51F9130573985A66F /* PBXTargetDependency */, - 3ECE96F17B686C020335F76E3191E00C /* PBXTargetDependency */, - 45148C8779E18C0083EC9DE6AF0CD38E /* PBXTargetDependency */, - 5310F632D43BB2D1B1B6F890ED3F0885 /* PBXTargetDependency */, - D13E8EC0261A514C204BE1AF5FCE1A71 /* PBXTargetDependency */, - 6B4B82E9706935B9950B575B6C1B42B3 /* PBXTargetDependency */, - EAFDA9B9134F1DF606BD4C18A97A874A /* PBXTargetDependency */, - 94930F6A17DE516441EAB3E4B56FDE83 /* PBXTargetDependency */, - 7AEE79031110CDCCD4AC9582EE18DBF1 /* PBXTargetDependency */, - AF61AC42B51AAD8083082E9E97A532D6 /* PBXTargetDependency */, - 24B0592F7CE999C10F5252F040275E53 /* PBXTargetDependency */, - D95A8BE51BA7A624286CB26082A825D7 /* PBXTargetDependency */, - 919D9299543E75927B76412AF77C67EB /* PBXTargetDependency */, - 76648E6385C38D92D9919DD8BEFB72FA /* PBXTargetDependency */, - 91231C8705F62ADF08EF987BC7F7F23A /* PBXTargetDependency */, - 76FC85DADC17FF90C5FDD5EBC9DB22F8 /* PBXTargetDependency */, - 162A14750937C65A2A4729155712F26E /* PBXTargetDependency */, - 62DBCD1EAB8D4CDB7E9A7CC0D50DBF17 /* PBXTargetDependency */, - C7AE23F84AE918C528379534C668DCE0 /* PBXTargetDependency */, - 26D2DAA1BEB626B4F3074DA792E9E049 /* PBXTargetDependency */, - BF03A3699E84F70F58A4C068CE723367 /* PBXTargetDependency */, - 8D73DF6AB515BDCAAA2E924F15FD7543 /* PBXTargetDependency */, - 88ABB33EF0314C0E1DE20E898CE4A48A /* PBXTargetDependency */, - 4B0B0B6F3B87CDE371502EF81AF50391 /* PBXTargetDependency */, - BC84B0B805D0DF23F0B5D1160056B9A8 /* PBXTargetDependency */, - 69FD5C53F5ECA3ED4DEC576EC605C19A /* PBXTargetDependency */, - B74039FCB994BF9585D0D4215D0875C8 /* PBXTargetDependency */, - FC734C17AB4E1E840D10ADA1901A3113 /* PBXTargetDependency */, - 424DBC0AAC3F2A89B819DB3A1BE2BD7E /* PBXTargetDependency */, - 86A336B574906E89C02F69D66AC2808D /* PBXTargetDependency */, - 85BB7A1710A8F651EDD241F7D71D9490 /* PBXTargetDependency */, - 9C1FA1598D376386D6CD15F13B05F844 /* PBXTargetDependency */, - A72A154D15AD1504DEE8CE49645A6D8E /* PBXTargetDependency */, - 254CD38753A6118FF2B524C09C120314 /* PBXTargetDependency */, - 412783A91C9AF4D6972DFA2F62A8C1A1 /* PBXTargetDependency */, - B48E006DA8F8AAD53D57E6AFE04AFD17 /* PBXTargetDependency */, - 983CF6E21DB008E9A79C819012FBC053 /* PBXTargetDependency */, - 06E7A26C669DC0234C327B2516735C98 /* PBXTargetDependency */, - C3DC6DBE2445FFE60812CAC637B5864A /* PBXTargetDependency */, - 067EEBB3B5DDD40A466FBB4557C0F507 /* PBXTargetDependency */, - C2ECFA6910CED7EFD2A5A498D869E980 /* PBXTargetDependency */, - 8B21978C9FB81332E24D4A9F14A03B76 /* PBXTargetDependency */, - 4C1B6D1DAD6D319DF2CD230DBC3D0A5C /* PBXTargetDependency */, - 856A79330ECD4101A00DA78356547395 /* PBXTargetDependency */, - 47096324E65A4400F049734DD6E59F2B /* PBXTargetDependency */, - 46F8894ECF5069E01E4352102610933F /* PBXTargetDependency */, - 37D3D1A9C752C5DCC821B584FF3A1207 /* PBXTargetDependency */, - FB8B0A16B9643FB2D121C43BE8B77BCE /* PBXTargetDependency */, - 53034382723F052DDE13043CAE339AD1 /* PBXTargetDependency */, - 4C7C9F601F826720D3382337E1A187B8 /* PBXTargetDependency */, - F67EDF6A0F61A98853459D1B6B6F30CB /* PBXTargetDependency */, - 535FEE6DEE208FC493B372D9576C8AC2 /* PBXTargetDependency */, - AB63AA75C19598CA9C832401B5B9B047 /* PBXTargetDependency */, - BEC0646C92263C5E750B29FD6901140F /* PBXTargetDependency */, - C3C71EE9BA9918D7266A6FFBE2175E03 /* PBXTargetDependency */, - 87B2B4711BCBD138FCB4F284EA4C8BC6 /* PBXTargetDependency */, - 0E3EDD0C0CAB8AC18DE1EB33B5A1A82E /* PBXTargetDependency */, - 4F80E27CCDD9788CB333ACE8F8A59297 /* PBXTargetDependency */, - ADB4BFD566AFDD1299060706572125FE /* PBXTargetDependency */, - 6DA363B8D5958C02C2899867D87A3604 /* PBXTargetDependency */, - 3D13AD9A803C789A67D93CB50870AE39 /* PBXTargetDependency */, - 8761BD1357846AC44DF8B0AD3BC395E4 /* PBXTargetDependency */, - EFDD1908CE86282341ED19473B7AE71C /* PBXTargetDependency */, - 4F9388F4DEB1B74534B3754E88705B26 /* PBXTargetDependency */, - 66C28A13D97C9C346092B072029BA58F /* PBXTargetDependency */, - 52B54ADE77A4B8F029D40C7F6EC7D27B /* PBXTargetDependency */, - 282F7AE82F5459CBCAF3B846755E8ADD /* PBXTargetDependency */, - F0DEEDCF04A5A943D216CA78725B1A59 /* PBXTargetDependency */, - DC62D20C43EFDA514ADDD1CA3E5A3612 /* PBXTargetDependency */, - FFF415525CCA9E6451D7DC64BF8E9558 /* PBXTargetDependency */, - 6213BDDA0827311C7C0F66457FF159F6 /* PBXTargetDependency */, - 9F74AAB317F546683493B1AA32B41061 /* PBXTargetDependency */, - CB54F2A88C91D4157C8371E3352C28DB /* PBXTargetDependency */, - 26CB9F470F7056BE615723902FE526BA /* PBXTargetDependency */, - A9CF24640E6BAC3911BFD39EC8991A9B /* PBXTargetDependency */, + 38AC68B3FC23B2F0783BA90C8E8426A6 /* PBXTargetDependency */, + D1C4ACAFAA72572F8F61F24DA1BBB93D /* PBXTargetDependency */, + 929A5F7FDCDD25EEBCB3E07A03C103CE /* PBXTargetDependency */, + 6B2F38A52325C62E2E89240590C61640 /* PBXTargetDependency */, + AA83F07E10C8CA91A174A07FCA4D8A6E /* PBXTargetDependency */, + 0BB959489706C32955C028ED3E946475 /* PBXTargetDependency */, + 97AD5E1C8C6461A410568E27E8298EE4 /* PBXTargetDependency */, + 98155535013FAB952B26FD59EA592733 /* PBXTargetDependency */, + 9A7EE76FE7B8451A3ABBEC321F37522A /* PBXTargetDependency */, + EA540322798F361FD75AB353A1C9E425 /* PBXTargetDependency */, + E1C4A34F07DB6233F3BF2D2194A30469 /* PBXTargetDependency */, + 529586BDD1A1BC5077323A1A95E70047 /* PBXTargetDependency */, + F011689EA3A1147252210457C97FA573 /* PBXTargetDependency */, + 7D284C4B2E5DB73EE5067247B058C3CB /* PBXTargetDependency */, + 1CC9860D756C501FBBDAD340ACD45301 /* PBXTargetDependency */, + E95C2A53C42B0C4B2A3DD8ED22515054 /* PBXTargetDependency */, + CC4024177BE3EF3FE61A9A3B3C018F1E /* PBXTargetDependency */, + C46368AB770EF37967821926E021655B /* PBXTargetDependency */, + B9F37584BD5F5DF521EEAF7DA2550C50 /* PBXTargetDependency */, + 94545BA4E14CACC60668DBF5F7A7FB41 /* PBXTargetDependency */, + F906514B0D6BCE2CBA379DD64D057DCA /* PBXTargetDependency */, + 7647F7896697657A08CB008CF8A1907E /* PBXTargetDependency */, + 1D21B4C455565DD8A6BED621DE7852F4 /* PBXTargetDependency */, + C73F214F338AF6934EC8B8210F1E4518 /* PBXTargetDependency */, + D9D6522A7F9C1E1C6F2DD5914631FAA9 /* PBXTargetDependency */, + 978A0C95E2F96A89F932C532B6F90256 /* PBXTargetDependency */, + 0FD68F4C7B38830F185FF274592003CC /* PBXTargetDependency */, + F37D811CFA93B6AE8DED6C44168D5F40 /* PBXTargetDependency */, + 84CC68EC049927C17EDEC11A282DB112 /* PBXTargetDependency */, + E50E2CACBAD5824E8F506F867D29E7F9 /* PBXTargetDependency */, + 3474A83F853C1621D4A60C85FB3B5555 /* PBXTargetDependency */, + F4D8474538222F1E4389329EA94E9A58 /* PBXTargetDependency */, + D2B61A644452D29E76D78C61565A3682 /* PBXTargetDependency */, + 30FA6F8FEFB0B4CF0650B24C14A071BE /* PBXTargetDependency */, + 15DBA299E33DACCA73D322741CD10812 /* PBXTargetDependency */, + 7C7133F5DE20EAE4D0A7861E6297321B /* PBXTargetDependency */, + 214598C7CB40021BF5A857C6899DBC29 /* PBXTargetDependency */, + 65E138FF098B57693C6289FC8C4FB9BA /* PBXTargetDependency */, + 3F0A7DF614313C493013438828985700 /* PBXTargetDependency */, + 8AD5472941BC778BC00CE66106DE52BE /* PBXTargetDependency */, + B53F9B180CF395A111802CF7D02CAAEF /* PBXTargetDependency */, + 0C11EB1F53B1C1874325CDEFC8F0CE37 /* PBXTargetDependency */, + BE769D0B980A5DB4845F947D415BA555 /* PBXTargetDependency */, + 08ADE63BAC33643606FD43457B45E5AF /* PBXTargetDependency */, + CC8E5348F1E30D61CA0DCA945DD4F365 /* PBXTargetDependency */, + 2EDB4B27A23329ACB4E760E9B4F61516 /* PBXTargetDependency */, + C387DF4A58B28C4DA207FB0AD9E42348 /* PBXTargetDependency */, + EF8F66AA6D6C124FA84615C4FC2FE394 /* PBXTargetDependency */, + F66B89EB7E24031640FD65D48062E982 /* PBXTargetDependency */, + 439838C4889B2AC4B55C3EBD64C0D1D6 /* PBXTargetDependency */, + 2AD5C55817C25E13E7BDA9C4625EBAC9 /* PBXTargetDependency */, + 29485F9ADE7BEC342392EAFC37CEB122 /* PBXTargetDependency */, + A7CCF6BB887BB5FA23764FFAA0F8C15F /* PBXTargetDependency */, + FEA444976F0D70F22B23ABC76FB5ABCF /* PBXTargetDependency */, + CA003B374ECABE4FCC0797795E0D7A24 /* PBXTargetDependency */, + FAB2907B370386C8A8D74F88C0AC18CD /* PBXTargetDependency */, + 469C038162F5AB1A532A73582DF196DF /* PBXTargetDependency */, + 63F7DF6FD6F44A626F748AC7E74C8310 /* PBXTargetDependency */, + A5D29CA2E6979DE225FF023B09BAB672 /* PBXTargetDependency */, + 41346F8DADB81886E3845AE9D8BFFD5C /* PBXTargetDependency */, + D1BF93DBD12BD38D63F3C1834F35A85D /* PBXTargetDependency */, + D4AE12762722C68043841E0A82895AB1 /* PBXTargetDependency */, + 6A29C5D7AE3EEA2B80C70D4B284EC068 /* PBXTargetDependency */, + 839B3A3DB5D6EC00BF184CDFE1BC89CB /* PBXTargetDependency */, + 150BF162EFB5B752D10D91E63C0792C3 /* PBXTargetDependency */, + 2E5716BCB8093BF6EC9D011E331AE1BA /* PBXTargetDependency */, + 3A2107C795E6C2F491520ECC5B9FDDDC /* PBXTargetDependency */, + D8B65332F6F04283C4A524E41A644C7E /* PBXTargetDependency */, + F4B4B447B2FCD3B2D60B4FAEBC041A1A /* PBXTargetDependency */, + BE534E2808AAB9F13F983B27B7A9294C /* PBXTargetDependency */, + 335EDC9B2B75B9E606F6B609C6CF3DF2 /* PBXTargetDependency */, + 14308070B74D3F97AE842E84369D5F7E /* PBXTargetDependency */, + E8551290A5DA862706D76E9756856FAF /* PBXTargetDependency */, + 402F4143BE5D6B40C7649098BDE34D42 /* PBXTargetDependency */, + CB630A8A25286F4E88724177E5CA654A /* PBXTargetDependency */, + EDDEA0F9453E294ED1F1FA31E51F40F6 /* PBXTargetDependency */, + BFC95FCE89B2927EF2E1EDD9629A6B85 /* PBXTargetDependency */, + 64D73D2C44ADEFA6EA63B9F52985BD4B /* PBXTargetDependency */, + A3FBC5EB5E34437E8B39D57FA12EDDD7 /* PBXTargetDependency */, + 54D849C80B8ED34AB176E1A25AB7F3F5 /* PBXTargetDependency */, + D8085D697FDF15F9ACD35A8F667C1335 /* PBXTargetDependency */, + 3A05B4CC399D864775EF6991303E9DB6 /* PBXTargetDependency */, + 001B7F5232F9201BBE63BBB72E3A2811 /* PBXTargetDependency */, + C996CD5E48EBD344EBD3F9B7EBFF161E /* PBXTargetDependency */, + 76495F4A164E644E0B9375BC4450908A /* PBXTargetDependency */, + C848DF48C5C46DCEE964DB9F7110C0CA /* PBXTargetDependency */, + 4967CB1496D4EDB15B54699271507559 /* PBXTargetDependency */, + 811B6D1BDCD74FBF733001D3D5F6DE7E /* PBXTargetDependency */, + 5812922982B864443AB44DF437ADD3C6 /* PBXTargetDependency */, + 770F0514FB5D96E957F38260390B16C3 /* PBXTargetDependency */, + A1E081118605689BEEB1687205A58BD5 /* PBXTargetDependency */, + F1F886C878767FC61B02C70AFED07CAE /* PBXTargetDependency */, + 0BA494B2300DAFF1DD2703CA6A4E7A33 /* PBXTargetDependency */, ); name = "Pods-BareExpo"; productName = "Pods-BareExpo"; @@ -1131,280 +1141,283 @@ projectDirPath = ""; projectReferences = ( { - ProjectRef = 6790273ACF64FACB6F6C790F7465109B /* Amplitude-iOS */; + ProjectRef = 5370504E9C2AB0A5A79DCDA80512DF63 /* EXNotifications */; + }, + { + ProjectRef = 1874C56666647F9C71C26C490DCD0921 /* AppAuth */; }, { - ProjectRef = 3561DE58B3DAAE4AA0D0BC1C630862FA /* Analytics */; + ProjectRef = CF1C7256B0751DFBBBC3C32DA058F9B2 /* EXAV */; }, { - ProjectRef = 6FA7CD78D631158BDBE6D2A9C4FC19FB /* AppAuth */; + ProjectRef = 24D571065DC8E7D78DE3D281B7F9665E /* EXImagePicker */; }, { - ProjectRef = EC64490903CB102FA5D88F9FD8D4873B /* DoubleConversion */; + ProjectRef = 790A2E685AC19C611733CE7F67102977 /* UMPermissionsInterface */; }, { - ProjectRef = 621E66BDF9658FBAEB7835F073CC1D58 /* EXAV */; + ProjectRef = 81D1A93D40939D17C69ACA87E0F091B9 /* Amplitude-iOS */; }, { - ProjectRef = 966D82943A84614F0D90E09EED82FC4A /* EXAmplitude */; + ProjectRef = 22B7962C5AC6F553566BDB321CDCBED7 /* Analytics */; }, { - ProjectRef = 384191FF16B8310DB2CA32CE12714F26 /* EXAppAuth */; + ProjectRef = 84BC96E6F93CA7ACABFB696BC390AAE4 /* DoubleConversion */; }, { - ProjectRef = D58517F1F49DD7F710C941D73B419B5C /* EXAppLoaderProvider */; + ProjectRef = 766836226A2B4B63203538724CCB4F1C /* EXAmplitude */; }, { - ProjectRef = EC8B540ED755EDCB2AE686784D3AF479 /* EXApplication */; + ProjectRef = D88FC63D8F76640F60314E4A5077FD31 /* EXAppAuth */; }, { - ProjectRef = AFBF976B0EF04C9912E08179B68D2308 /* EXBarCodeScanner */; + ProjectRef = A0472A19A0663233A80B3D04DF83139C /* EXAppLoaderProvider */; }, { - ProjectRef = 6FF66503720CEADA5339CA295727D2E6 /* EXBattery */; + ProjectRef = EBA46FF6FE79918F2108E6350176703C /* EXApplication */; }, { - ProjectRef = 7673391655AE15ABB96812EE718E18B3 /* EXBluetooth */; + ProjectRef = F1BA3A37FBB21699CAA6831FD7EA7A4B /* EXBarCodeScanner */; }, { - ProjectRef = 559D179071A592B620836CC4F14A9F63 /* EXBlur */; + ProjectRef = 67E8A05962A87D9D3E97F466C0588F3E /* EXBattery */; }, { - ProjectRef = 00D632F97A746F8FBEE5FD654C95A5D4 /* EXBrightness */; + ProjectRef = 4A75B063423ACC708261B1E2E6A5AF72 /* EXBluetooth */; }, { - ProjectRef = 66E0036061F06985A735F972DA873D82 /* EXCalendar */; + ProjectRef = 74FEDEFE688494CAE07748B5D758B147 /* EXBlur */; }, { - ProjectRef = 3A6F2FEF94FB5051D0E15E0E75E061CE /* EXCellular */; + ProjectRef = 4830F218FE12E25D199C4BF46791F52C /* EXBrightness */; }, { - ProjectRef = 0F87C4C729C750646FF9170E107841D0 /* EXConstants */; + ProjectRef = 4F6D317BD66107DED81B141CC7C9862B /* EXCalendar */; }, { - ProjectRef = 6F0ED87952B752BF2F6950D2DAB51472 /* EXContacts */; + ProjectRef = 6E562C149ACFF3572AF76219136BAE6F /* EXCellular */; }, { - ProjectRef = 3E8F53A4E4A9F6D8E7270A1D59C0414A /* EXCrypto */; + ProjectRef = 1CEBDBC09F655F237DA82B43D4E56D1A /* EXConstants */; }, { - ProjectRef = A9333E5CD08216B9D4D56A43F8AFFB5B /* EXDevice */; + ProjectRef = 69B62F0A6A5AE0185AB31AF2B50E6C73 /* EXContacts */; }, { - ProjectRef = E3C83D9BB0BF020DE9E3EA402FF40418 /* EXDocumentPicker */; + ProjectRef = E3D4951BFB897802566871A47737F1EE /* EXCrypto */; }, { - ProjectRef = D1D370A1C813FC6C49069D6F265F56E3 /* EXErrorRecovery */; + ProjectRef = ACDF0A1622DDFFECE9C4DD356D1BA970 /* EXDevice */; }, { - ProjectRef = 1EC4C5F6778FD0728D36B94A40185D7A /* EXFileSystem */; + ProjectRef = D78B6B55B6F370CFD13934B2CC9B6119 /* EXDocumentPicker */; }, { - ProjectRef = B16FF31EB7B2D5E60E6685477B72EBC5 /* EXFont */; + ProjectRef = AF9B03AFD3122203FA523C331045B557 /* EXErrorRecovery */; }, { - ProjectRef = A528590EDEA69FCB74BFA09B141B4DBF /* EXGL */; + ProjectRef = A0F40A7EF94F9CDB1C9EC3706EF31977 /* EXFileSystem */; }, { - ProjectRef = B1BC6698202B367C7B3129780457D544 /* EXGL_CPP */; + ProjectRef = 31ED0F047A312EAA2BE054E15BB3DA57 /* EXFont */; }, { - ProjectRef = 9530BB032E863145DD427DBC06A82F68 /* EXGoogleSignIn */; + ProjectRef = B79E739FDB18023D4C8E4264D5CE84D3 /* EXGL */; }, { - ProjectRef = 58F5BF4DBAF85B453DD79DA82B862E0A /* EXHaptics */; + ProjectRef = 2B3EF7E45E25388E46088AEF724044E2 /* EXGL_CPP */; }, { - ProjectRef = 5F89074EFF9BBFF30A654696E06822C7 /* EXImageManipulator */; + ProjectRef = 0E7C660C1D1A671A1C2C6E0A386E4F98 /* EXGoogleSignIn */; }, { - ProjectRef = 081775E5E1E22CD733CEC31DEC05391D /* EXImagePicker */; + ProjectRef = 19518053F4B0ADB5DD067DBC654DCDC8 /* EXHaptics */; }, { - ProjectRef = A82D7F91B76D88E3B3001116B85C6F8F /* EXKeepAwake */; + ProjectRef = FBDB34F0ECB442D367E68748ADA3820F /* EXImageManipulator */; }, { - ProjectRef = C4691EC6027337FE88F7B6C142C79DA9 /* EXLinearGradient */; + ProjectRef = 3F7A24830AA6A74FD093D740F10D7773 /* EXKeepAwake */; }, { - ProjectRef = A90F97E439A7BC54338B0DC132FB389F /* EXLocalAuthentication */; + ProjectRef = 951A59FA6D6F13FE2BC2DC148092885D /* EXLinearGradient */; }, { - ProjectRef = 89B3742C40E8B4801826442347325BBF /* EXLocalization */; + ProjectRef = 9FBF69DFB7386F17655AA92E47A91B88 /* EXLocalAuthentication */; }, { - ProjectRef = 469C509D4699E1DC0DF43F06F3A21FD4 /* EXMailComposer */; + ProjectRef = 3AC85EC6EA5A15DE1A14AC44693B3FAF /* EXLocalization */; }, { - ProjectRef = AF0568DC623CE5D3D2E159457E57B21F /* EXMediaLibrary */; + ProjectRef = 4A8C2D314E95B84D433DB3EC5D0248A8 /* EXMailComposer */; }, { - ProjectRef = 63CC2109E824718DD6CF3ECF2951714F /* EXNetwork */; + ProjectRef = C307D52AB4940565B4FE24E5B2BA7277 /* EXMediaLibrary */; }, { - ProjectRef = ED50116F92CAB9F1E06FE905363CE060 /* EXPermissions */; + ProjectRef = 5E612F91AF7A9DFF650E744D5DDDE6BB /* EXNetwork */; }, { - ProjectRef = 4971CAC7D488A21F083090F5DF77441A /* EXPrint */; + ProjectRef = B399F6209661F0C9597B9B02C293119F /* EXPermissions */; }, { - ProjectRef = 9F278CA3578A1C7C742F5C39E58E8626 /* EXRandom */; + ProjectRef = 7C365CF21BA55DFDF477C4C9CE32DCA1 /* EXPrint */; }, { - ProjectRef = 59558382C9C14CEDEC8ECC99462044AC /* EXSMS */; + ProjectRef = 0DCFBB69843FF7B3B3F4DBFA9395897F /* EXRandom */; }, { - ProjectRef = 9B3C09E1B51BE5C72B1178721DFB4736 /* EXSQLite */; + ProjectRef = 0F4A4147605A8FA472874292E84CA8AA /* EXSMS */; }, { - ProjectRef = EF2B74AE23B4D085A4D41634852D9E79 /* EXSecureStore */; + ProjectRef = 2D820764336141EB6A64FB5E39379B84 /* EXSQLite */; }, { - ProjectRef = 0CCA7AB54711A1C565D9146E86AF6FE5 /* EXSegment */; + ProjectRef = B79AA8F0753060DE025621A58BF10081 /* EXSecureStore */; }, { - ProjectRef = D7D345E8C3BC6E50CBED042829BBF090 /* EXSensors */; + ProjectRef = 9CEAF6033593566F9D90D312481E1561 /* EXSegment */; }, { - ProjectRef = 1CA025FC93211998774902CC4663DD61 /* EXSharing */; + ProjectRef = E35074979A21EA433E91AFF284E3AC50 /* EXSensors */; }, { - ProjectRef = 8C472FA03A74CA155968F8B7216E490A /* EXSpeech */; + ProjectRef = 1291D1E0EF26BE30E64DFE7E772780FF /* EXSharing */; }, { - ProjectRef = 5C7101C48EADF48A3F01ADAD195A0608 /* EXStoreReview */; + ProjectRef = 1682454010CE1DE95AE1F2B800003AE8 /* EXSpeech */; }, { - ProjectRef = 9F3B324040A71A156CE8681CBF0610AA /* EXUpdates */; + ProjectRef = 76D754AC0977B5323E742EEECB40AED4 /* EXStoreReview */; }, { - ProjectRef = 1FBDB8F24C5539045D8AE87F927FB3EE /* EXWebBrowser */; + ProjectRef = BFC20E8D25AC617CEF09AEE4F3B6447C /* EXUpdates */; }, { - ProjectRef = C099422E2DC2875E807A665C97BCC571 /* FBLazyVector */; + ProjectRef = D9159EDE5B081372F59C922A6F771D88 /* EXWebBrowser */; }, { - ProjectRef = 7572990AACADFEEFE5EF8AF3A2415FD0 /* FBReactNativeSpec */; + ProjectRef = 602F1AC40936205BAA0B2DB343047BC2 /* FBLazyVector */; }, { - ProjectRef = B2F742EBD46D881CC735F4D4A4260119 /* Folly */; + ProjectRef = 5C904EB0F8D09A9D6A2CA1D9E5FB1A5E /* FBReactNativeSpec */; }, { - ProjectRef = 8DD091FE677FB13DC171D90C021CA7DE /* GTMAppAuth */; + ProjectRef = 3BA6FCAA80CA6709FC129B2F8F1455D9 /* Folly */; }, { - ProjectRef = F6C89811BEB495795C6F1B805FCF9133 /* GTMSessionFetcher */; + ProjectRef = 72E97573157DD427D06035896E61A932 /* GTMAppAuth */; }, { - ProjectRef = E17942621B3C5C442DAEF9E85EE80964 /* GoogleSignIn */; + ProjectRef = 4915DBB1FD2CAFEC6F31A56C0C6957F2 /* GTMSessionFetcher */; }, { - ProjectRef = 50C4358AD398837056C0C6E564E5FB45 /* RCTRequired */; + ProjectRef = 38C1D46D658188871C901CE039368D2B /* GoogleSignIn */; }, { - ProjectRef = 73E1515109725296D25100C06DA91793 /* RCTTypeSafety */; + ProjectRef = 211D8213F75598D838AA142334A75A03 /* RCTRequired */; }, { - ProjectRef = 228AECF796357BD0C17A0250B493CF46 /* RNGestureHandler */; + ProjectRef = 847FD5ED7B8C4325822B875EFAC72828 /* RCTTypeSafety */; }, { - ProjectRef = 093F33B91AB6CCF24EC5B44C2168D6B7 /* RNReanimated */; + ProjectRef = 20C29A1EAED431974F1F9ADE24297AD8 /* RNGestureHandler */; }, { - ProjectRef = BB09D5AC4BEBC2617D9D95C54475FA09 /* React */; + ProjectRef = C82A773803E9590719BF9B2ADBDC8853 /* RNReanimated */; }, { - ProjectRef = 4B81D9E849F7B0FF699CF47FC7F2EC7B /* React-Core */; + ProjectRef = D295C7698687650B201A4E18B1A6CE87 /* React */; }, { - ProjectRef = A3F4A301606C753818F89B954CBABFFA /* React-CoreModules */; + ProjectRef = AC64B72943BF5A964B4BEA5D03352E8A /* React-Core */; }, { - ProjectRef = 7C6CEDFBCA521989947F5B019C76054A /* React-RCTActionSheet */; + ProjectRef = D0A15388E6A79D84E72CB78529279E0C /* React-CoreModules */; }, { - ProjectRef = 93A314050AEE5C54490FF76731532B5D /* React-RCTAnimation */; + ProjectRef = C48CFC9D9BAC60B4713D773CBCC18138 /* React-RCTActionSheet */; }, { - ProjectRef = 53B70B73EBA72F4DB54EFB1201B958D9 /* React-RCTBlob */; + ProjectRef = 486D05376E4B939AAAA46292A4C1EDC5 /* React-RCTAnimation */; }, { - ProjectRef = 04AF6CFC908ABC897934A123721DCDC8 /* React-RCTImage */; + ProjectRef = 2DFD1D139E40516EB3C8592132C16563 /* React-RCTBlob */; }, { - ProjectRef = FC694360F93EB50AF01BD9AD3DDF6F63 /* React-RCTLinking */; + ProjectRef = 6FE9E6378CCA409045A0D6F7725BD635 /* React-RCTImage */; }, { - ProjectRef = C3F1268A122894A50E585D0D43F60664 /* React-RCTNetwork */; + ProjectRef = 539904AF85D455EEA0BC80314430F767 /* React-RCTLinking */; }, { - ProjectRef = 00E9EF1B95C123998456AA100CE87025 /* React-RCTSettings */; + ProjectRef = D918720DA8177424E16B7D398B1E42BA /* React-RCTNetwork */; }, { - ProjectRef = B95E106A906DA6BC3B1AE32B1476EC96 /* React-RCTText */; + ProjectRef = 83741058F1FBE8278A49685754C1020B /* React-RCTSettings */; }, { - ProjectRef = 2AFEBA4AE1BF044913C3A1F0ABCD7BEF /* React-RCTVibration */; + ProjectRef = 39600D89716D9EF152089FCE92F9611F /* React-RCTText */; }, { - ProjectRef = 5C0692C4DCE5A6E01C6809F60A6FBB6E /* React-cxxreact */; + ProjectRef = 6FCCE9A29FCD2F955BD249B2E8FE64D6 /* React-RCTVibration */; }, { - ProjectRef = 01CFA74EFC65BCFDF41AE2DB0615EED8 /* React-jsi */; + ProjectRef = D1A3C1892F717A0516FC6E06862425AD /* React-cxxreact */; }, { - ProjectRef = C2EA603A6A2597676F274428E05872B9 /* React-jsiexecutor */; + ProjectRef = FA3F1AFA57847B7DE0AAEDF4186FC4BF /* React-jsi */; }, { - ProjectRef = 0143F693E54C76D9CEC9B89D39EA738C /* React-jsinspector */; + ProjectRef = 5ED0F47567E19D563562378CB541F063 /* React-jsiexecutor */; }, { - ProjectRef = 11A32ED6BFC7435B83A74B68227CF672 /* ReactCommon */; + ProjectRef = A32518B2BC57B6ACB06728AD31C6FED7 /* React-jsinspector */; }, { - ProjectRef = A14282E7B246C428EDC564624DBDD9BF /* UMBarCodeScannerInterface */; + ProjectRef = 42DD6321E59344D440B1F51FE3CF79E7 /* ReactCommon */; }, { - ProjectRef = BAD136761E20C0CF271C8994F81BE4E8 /* UMCameraInterface */; + ProjectRef = A5F35E9471A25BAFEB3AB53EDB2E48BD /* UMBarCodeScannerInterface */; }, { - ProjectRef = 24C2C1248498064540A1A0795384B075 /* UMConstantsInterface */; + ProjectRef = 283EB81A8B2631DC912F91F2E743D805 /* UMCameraInterface */; }, { - ProjectRef = 6F2506A46EAB2A974A4A198BF26B5D11 /* UMCore */; + ProjectRef = 8BB89C73D41B6306783F6127102D17EE /* UMConstantsInterface */; }, { - ProjectRef = A1A9EF9126D232C7848495ED0D34FC82 /* UMFileSystemInterface */; + ProjectRef = 99EC51DA27D3AF613938A01C65921965 /* UMCore */; }, { - ProjectRef = 10773CD4E5B8A755D9E0D42FC649AEB4 /* UMFontInterface */; + ProjectRef = DD26F4B8BC160D314045C1E9FF99E1C0 /* UMFileSystemInterface */; }, { - ProjectRef = D06CF6E8B5CE7D5A760E443475289B14 /* UMImageLoaderInterface */; + ProjectRef = A31EA7E16D8F9F37E83632B7A9BD49BD /* UMFontInterface */; }, { - ProjectRef = F93842B2AFB5431663D17D6C8B0DAD27 /* UMPermissionsInterface */; + ProjectRef = 2FA4EA22672E5A6B552140467F83F0D5 /* UMImageLoaderInterface */; }, { - ProjectRef = D5E45FC61A6D2D7E3F46F8A281EA7F64 /* UMReactNativeAdapter */; + ProjectRef = 20EFB8787523F1F8E82C44E6D2318625 /* UMReactNativeAdapter */; }, { - ProjectRef = 4B8658D487323D6EEE125B5F57F06468 /* UMSensorsInterface */; + ProjectRef = F5378BC6DC876907C7D4762A994635E1 /* UMSensorsInterface */; }, { - ProjectRef = 068283BA3523101E0BA7F90CEB90A6A1 /* Yoga */; + ProjectRef = 154D415A4BF5B57E8E22F022EE88A1A2 /* Yoga */; }, { - ProjectRef = 9946A17BD11A68F7A944498FD73C8413 /* ZXingObjC */; + ProjectRef = 85183E225D7A7272819751A43B77122A /* ZXingObjC */; }, { - ProjectRef = 06A760ACB1990444FA093A6D7A8AC2EB /* boost-for-react-native */; + ProjectRef = E6C81641E33F90B0058BD7F47E6F95F4 /* boost-for-react-native */; }, { - ProjectRef = 21907930CDED304581AE9F8EF737DFC3 /* glog */; + ProjectRef = 837FB515358617F85BDF99978EE71115 /* glog */; }, { - ProjectRef = 86F0EA4A0FCDB3FC734AE64574A90EBC /* react-native-safe-area-context */; + ProjectRef = 37D51A279F61ACA707D2DDB2B4775260 /* react-native-safe-area-context */; }, ); projectRoot = ""; @@ -1416,11 +1429,11 @@ /* End PBXProject section */ /* Begin PBXSourcesBuildPhase section */ - 0B99572B5B1932951237131C16FBB9C7 /* Sources */ = { + 2B5408C2A80FFB629A3932BF9BCC394E /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 27B74A7EF0716B4AF7ECCB2F8E04A0B3 /* Pods-BareExpo-dummy.m in Sources */, + F2F714CCB8A26BEEAF45A7BC332B8802 /* Pods-BareExpo-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1435,498 +1448,480 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 067EEBB3B5DDD40A466FBB4557C0F507 /* PBXTargetDependency */ = { + 001B7F5232F9201BBE63BBB72E3A2811 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = RCTRequired; - targetProxy = 7FC8F2D1B333FC5EADC4FBA1AB7EBFB5 /* PBXContainerItemProxy */; + name = UMFileSystemInterface; + targetProxy = 0B8C5F00B0B111D1DB9CAAE8560EF8DA /* PBXContainerItemProxy */; }; - 06E7A26C669DC0234C327B2516735C98 /* PBXTargetDependency */ = { + 08ADE63BAC33643606FD43457B45E5AF /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = GTMSessionFetcher; - targetProxy = C0D1C19DEA5D365061FF4508B4800EF2 /* PBXContainerItemProxy */; + name = EXSecureStore; + targetProxy = 5C939B02FA3137B5DF8CDE1F7841A5EA /* PBXContainerItemProxy */; }; - 0B3198B72438B14E12C3547AEFF35817 /* PBXTargetDependency */ = { + 0BA494B2300DAFF1DD2703CA6A4E7A33 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXBarCodeScanner; - targetProxy = AD6B10B33B18CA4A347E896D47BF322A /* PBXContainerItemProxy */; + name = "react-native-safe-area-context"; + targetProxy = 5986255D885BB7F771FE7C2C0E2BD5E3 /* PBXContainerItemProxy */; }; - 0C6704A85B88110C459780D3DC0D42AE /* PBXTargetDependency */ = { + 0BB959489706C32955C028ED3E946475 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXCellular; - targetProxy = 747EAA46A036A88E6C075D7CAC73D253 /* PBXContainerItemProxy */; + name = EXAmplitude; + targetProxy = DCF29BC56D0890AC4130BF00F0C9D8DD /* PBXContainerItemProxy */; }; - 0E3EDD0C0CAB8AC18DE1EB33B5A1A82E /* PBXTargetDependency */ = { + 0C11EB1F53B1C1874325CDEFC8F0CE37 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = "React-jsi"; - targetProxy = DF4AEE3244EB84A881866AE1F00F702A /* PBXContainerItemProxy */; + name = EXSMS; + targetProxy = 06963D9ACFF76386269904DEB96637B5 /* PBXContainerItemProxy */; }; - 162A14750937C65A2A4729155712F26E /* PBXTargetDependency */ = { + 0FD68F4C7B38830F185FF274592003CC /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXLocalization; - targetProxy = 2310E33AFE5DCF99B3982C7E4D4D7BDD /* PBXContainerItemProxy */; + name = EXGoogleSignIn; + targetProxy = 78B92CED29A733A14982F6CF0A7DFEFC /* PBXContainerItemProxy */; }; - 216CEB250607CD8D1847439AA9943219 /* PBXTargetDependency */ = { + 14308070B74D3F97AE842E84369D5F7E /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXAmplitude; - targetProxy = D7FFDD3F5095036FF7AF5F5D29EFB1BE /* PBXContainerItemProxy */; + name = "React-RCTText"; + targetProxy = 762C229920508A7C1071A62F613FE744 /* PBXContainerItemProxy */; }; - 24B0592F7CE999C10F5252F040275E53 /* PBXTargetDependency */ = { + 150BF162EFB5B752D10D91E63C0792C3 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXHaptics; - targetProxy = 2F6A828F617177C24C91AFE67336840B /* PBXContainerItemProxy */; + name = "React-RCTActionSheet"; + targetProxy = 88E8AAB58D90D69B73E53CB1039AD148 /* PBXContainerItemProxy */; }; - 254CD38753A6118FF2B524C09C120314 /* PBXTargetDependency */ = { + 15DBA299E33DACCA73D322741CD10812 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = FBLazyVector; - targetProxy = 84CBD0CEF3538AC641BB40C36876BD81 /* PBXContainerItemProxy */; + name = EXMailComposer; + targetProxy = E51836B09C2FC93BC074CCA4B3AD62CC /* PBXContainerItemProxy */; }; - 26CB9F470F7056BE615723902FE526BA /* PBXTargetDependency */ = { + 1CC9860D756C501FBBDAD340ACD45301 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = glog; - targetProxy = BC8167D94C315BAC5226405FC6608AA7 /* PBXContainerItemProxy */; + name = EXCalendar; + targetProxy = AE5C3FC5B1E65980DAD50948DCF5C6D4 /* PBXContainerItemProxy */; }; - 26D2DAA1BEB626B4F3074DA792E9E049 /* PBXTargetDependency */ = { + 1D21B4C455565DD8A6BED621DE7852F4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = EXFileSystem; + targetProxy = 2886FB9B4B7F2B85BCE556DBA40F64E1 /* PBXContainerItemProxy */; + }; + 214598C7CB40021BF5A857C6899DBC29 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = EXNetwork; - targetProxy = EDE74689F85B5DC963E8E16C1B164F4E /* PBXContainerItemProxy */; + targetProxy = F610086B8A99E86BD49AC94781366EDE /* PBXContainerItemProxy */; }; - 282F7AE82F5459CBCAF3B846755E8ADD /* PBXTargetDependency */ = { + 29485F9ADE7BEC342392EAFC37CEB122 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = UMImageLoaderInterface; - targetProxy = B302FD2BB02B0AAD96BDC1C6DB19E566 /* PBXContainerItemProxy */; + name = FBLazyVector; + targetProxy = 5A4A2A9AC0BEE1DF43937DF2E89B2C90 /* PBXContainerItemProxy */; + }; + 2AD5C55817C25E13E7BDA9C4625EBAC9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = EXWebBrowser; + targetProxy = D043C6D69D8E8DBE9A2A6B5904D80A4B /* PBXContainerItemProxy */; }; - 37D3D1A9C752C5DCC821B584FF3A1207 /* PBXTargetDependency */ = { + 2E5716BCB8093BF6EC9D011E331AE1BA /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = "React-RCTActionSheet"; - targetProxy = 35855868F9E27821A58D859456185065 /* PBXContainerItemProxy */; + name = "React-RCTAnimation"; + targetProxy = 9EAC0AFB4D6D6D4B4E2D72A086562D4B /* PBXContainerItemProxy */; }; - 3B41B5F91EC84A9F522A725288F03622 /* PBXTargetDependency */ = { + 2EDB4B27A23329ACB4E760E9B4F61516 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXAppLoaderProvider; - targetProxy = A8F91F7C4377813388AE4D2DDB3F6CA4 /* PBXContainerItemProxy */; + name = EXSensors; + targetProxy = 9B3387B09458A77915E4FECED561E332 /* PBXContainerItemProxy */; }; - 3C1825C8E667A847B094BC84710EB57D /* PBXTargetDependency */ = { + 30FA6F8FEFB0B4CF0650B24C14A071BE /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXBluetooth; - targetProxy = DDFE0FA34D9552D9D2E63BB7DDC37FB3 /* PBXContainerItemProxy */; + name = EXLocalization; + targetProxy = 2D6B7FE0D400077A830A889D5F2E3BF6 /* PBXContainerItemProxy */; }; - 3D13AD9A803C789A67D93CB50870AE39 /* PBXTargetDependency */ = { + 335EDC9B2B75B9E606F6B609C6CF3DF2 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = UMBarCodeScannerInterface; - targetProxy = 05B0119097CB972CC8342F1A43F98833 /* PBXContainerItemProxy */; + name = "React-RCTSettings"; + targetProxy = 071C80A0F327B444E7A3951CDF5D81F4 /* PBXContainerItemProxy */; }; - 3ECE96F17B686C020335F76E3191E00C /* PBXTargetDependency */ = { + 3474A83F853C1621D4A60C85FB3B5555 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXCrypto; - targetProxy = BAD1DF73985CE89817BFA6C0543F3D03 /* PBXContainerItemProxy */; + name = EXKeepAwake; + targetProxy = 17C369DA24A77B5DFF1F57381D6566B6 /* PBXContainerItemProxy */; }; - 412783A91C9AF4D6972DFA2F62A8C1A1 /* PBXTargetDependency */ = { + 38AC68B3FC23B2F0783BA90C8E8426A6 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = FBReactNativeSpec; - targetProxy = 65CCF35240ECB03F58B9E1E002B5E477 /* PBXContainerItemProxy */; + name = "Amplitude-iOS"; + targetProxy = 33EA9FDC3E1504E6D2321C306A5A70A2 /* PBXContainerItemProxy */; }; - 424DBC0AAC3F2A89B819DB3A1BE2BD7E /* PBXTargetDependency */ = { + 3A05B4CC399D864775EF6991303E9DB6 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXSharing; - targetProxy = 8E0663814249A4ADFF8E7A4A5345A03A /* PBXContainerItemProxy */; + name = UMCore; + targetProxy = 3877B90A6B5F0B1026CCF6519797BC8B /* PBXContainerItemProxy */; }; - 45148C8779E18C0083EC9DE6AF0CD38E /* PBXTargetDependency */ = { + 3A2107C795E6C2F491520ECC5B9FDDDC /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXDevice; - targetProxy = A2F13C125416EB21F8FAEE2465DAC2AB /* PBXContainerItemProxy */; + name = "React-RCTBlob"; + targetProxy = 7811002A80AC1E7EAF4C8894ABE73D57 /* PBXContainerItemProxy */; }; - 46F8894ECF5069E01E4352102610933F /* PBXTargetDependency */ = { + 3F0A7DF614313C493013438828985700 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = "React-CoreModules"; - targetProxy = 865D575A281702845E263A55EB18538C /* PBXContainerItemProxy */; + name = EXPermissions; + targetProxy = 270D963B83EE8B8579C8857BFCD46219 /* PBXContainerItemProxy */; }; - 47096324E65A4400F049734DD6E59F2B /* PBXTargetDependency */ = { + 402F4143BE5D6B40C7649098BDE34D42 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = "React-Core"; - targetProxy = 431AF7D2922ED0E18BFF9D7C0FA1633D /* PBXContainerItemProxy */; + name = "React-cxxreact"; + targetProxy = BCF48DD07D2F4C863C70A03EA55F39F7 /* PBXContainerItemProxy */; }; - 49ED00B0339E6859EE2CF1B4112EBA9C /* PBXTargetDependency */ = { + 41346F8DADB81886E3845AE9D8BFFD5C /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXAV; - targetProxy = 7EF30E0E4FFCDBEEAF279262F6874A60 /* PBXContainerItemProxy */; + name = RNGestureHandler; + targetProxy = 22F148F91BD9CC2DB52F7F801629B509 /* PBXContainerItemProxy */; }; - 4B0B0B6F3B87CDE371502EF81AF50391 /* PBXTargetDependency */ = { + 439838C4889B2AC4B55C3EBD64C0D1D6 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXSMS; - targetProxy = 9BDC84B84E26F07933C0332937E97893 /* PBXContainerItemProxy */; + name = EXUpdates; + targetProxy = 754D4A6FA047092156B7BFE15CF5CE82 /* PBXContainerItemProxy */; }; - 4C1B6D1DAD6D319DF2CD230DBC3D0A5C /* PBXTargetDependency */ = { + 469C038162F5AB1A532A73582DF196DF /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = RNReanimated; - targetProxy = 04D4A9C49B1150F6E441E4B21B87FE46 /* PBXContainerItemProxy */; + name = GoogleSignIn; + targetProxy = 458E74C7A2B3BCEB0678B44712A07B95 /* PBXContainerItemProxy */; }; - 4C7C9F601F826720D3382337E1A187B8 /* PBXTargetDependency */ = { + 4967CB1496D4EDB15B54699271507559 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = "React-RCTImage"; - targetProxy = 07AE4300B905F05CED560E1C5437466E /* PBXContainerItemProxy */; + name = UMReactNativeAdapter; + targetProxy = FCCD606F996CBBAAF838FA6301625D42 /* PBXContainerItemProxy */; }; - 4F80E27CCDD9788CB333ACE8F8A59297 /* PBXTargetDependency */ = { + 529586BDD1A1BC5077323A1A95E70047 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = "React-jsiexecutor"; - targetProxy = C793E8E284B01FE1C42765785C913284 /* PBXContainerItemProxy */; + name = EXBluetooth; + targetProxy = B0AF012459FB8FBA764ECFBCAF75AEFF /* PBXContainerItemProxy */; }; - 4F9388F4DEB1B74534B3754E88705B26 /* PBXTargetDependency */ = { + 54D849C80B8ED34AB176E1A25AB7F3F5 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = UMCore; - targetProxy = 5C9524D6AB93120FF7D58A9461D45112 /* PBXContainerItemProxy */; + name = UMCameraInterface; + targetProxy = B8313E58D931E0DF5AAF44180C29A885 /* PBXContainerItemProxy */; }; - 52B54ADE77A4B8F029D40C7F6EC7D27B /* PBXTargetDependency */ = { + 5812922982B864443AB44DF437ADD3C6 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = UMFontInterface; - targetProxy = A4861781D8FFCA47636C2B2572BBA817 /* PBXContainerItemProxy */; + name = Yoga; + targetProxy = 32EB6A244E8E2B57AA237ACBA3AFE442 /* PBXContainerItemProxy */; }; - 53034382723F052DDE13043CAE339AD1 /* PBXTargetDependency */ = { + 63F7DF6FD6F44A626F748AC7E74C8310 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = "React-RCTBlob"; - targetProxy = C6775EA6E67262174AE3F8EB9BC04527 /* PBXContainerItemProxy */; + name = RCTRequired; + targetProxy = A1E5C22EA8DDC7C8B2374E152A49DDF8 /* PBXContainerItemProxy */; }; - 5310F632D43BB2D1B1B6F890ED3F0885 /* PBXTargetDependency */ = { + 64D73D2C44ADEFA6EA63B9F52985BD4B /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXDocumentPicker; - targetProxy = A75B4DE316B3C94CC37B4A662123569C /* PBXContainerItemProxy */; + name = ReactCommon; + targetProxy = 9E57EB6A3151AA92814D09FFBB8D1788 /* PBXContainerItemProxy */; }; - 535FEE6DEE208FC493B372D9576C8AC2 /* PBXTargetDependency */ = { + 65E138FF098B57693C6289FC8C4FB9BA /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = "React-RCTNetwork"; - targetProxy = F7CA9DF8CB84759BCCD92D51371A60EE /* PBXContainerItemProxy */; + name = EXNotifications; + targetProxy = DF962C651115BD29A1B59BB3CB77A30D /* PBXContainerItemProxy */; }; - 57D398309C4C6FD51F9130573985A66F /* PBXTargetDependency */ = { + 6A29C5D7AE3EEA2B80C70D4B284EC068 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXContacts; - targetProxy = E22601FB7D527CB7700F5EF31658A6BD /* PBXContainerItemProxy */; + name = "React-Core"; + targetProxy = 29A2F824BAAC6D5862899640DB847035 /* PBXContainerItemProxy */; }; - 5CC4BF5204B9D14211D9845D3CCE8B3A /* PBXTargetDependency */ = { + 6B2F38A52325C62E2E89240590C61640 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = DoubleConversion; - targetProxy = 3B6AAB8218C95833AC4ECBF0FCFC644F /* PBXContainerItemProxy */; - }; - 5E5513B0C5190451B739B75885958F81 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = EXBattery; - targetProxy = 3C1A537234950AB8ECD1F34B075F0F28 /* PBXContainerItemProxy */; + targetProxy = D264A1CBF2E9FEA332EC92EB30758B6A /* PBXContainerItemProxy */; }; - 6213BDDA0827311C7C0F66457FF159F6 /* PBXTargetDependency */ = { + 7647F7896697657A08CB008CF8A1907E /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = Yoga; - targetProxy = DC0A99BF800318FF2591A3C3BF67AA2A /* PBXContainerItemProxy */; + name = EXErrorRecovery; + targetProxy = 9A6F2C6B72B62171B236644CDFA5E17C /* PBXContainerItemProxy */; }; - 62DBCD1EAB8D4CDB7E9A7CC0D50DBF17 /* PBXTargetDependency */ = { + 76495F4A164E644E0B9375BC4450908A /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXMailComposer; - targetProxy = 834482237C0D29D3B0A986E0108F44E8 /* PBXContainerItemProxy */; + name = UMImageLoaderInterface; + targetProxy = 70734B1E9EA0F936F6E3A313F90C657C /* PBXContainerItemProxy */; }; - 66C28A13D97C9C346092B072029BA58F /* PBXTargetDependency */ = { + 770F0514FB5D96E957F38260390B16C3 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = UMFileSystemInterface; - targetProxy = 0353DEE60CB234F82C58A10CDC031E88 /* PBXContainerItemProxy */; + name = ZXingObjC; + targetProxy = C44BFA7EDE6D662FB3341FE30CCE61A1 /* PBXContainerItemProxy */; }; - 68583D60CD1D2FCEE73CF16A926196A3 /* PBXTargetDependency */ = { + 7C7133F5DE20EAE4D0A7861E6297321B /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = Analytics; - targetProxy = 8A898395EFE24E3518D6ACE4807A4410 /* PBXContainerItemProxy */; + name = EXMediaLibrary; + targetProxy = 56F4DE4682B3525F826E75C5B6982250 /* PBXContainerItemProxy */; }; - 69FD5C53F5ECA3ED4DEC576EC605C19A /* PBXTargetDependency */ = { + 7D284C4B2E5DB73EE5067247B058C3CB /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXSecureStore; - targetProxy = 1E3E312EFD96A12407172E96E9390F77 /* PBXContainerItemProxy */; + name = EXBrightness; + targetProxy = C4D1D3FD3BAD1607F4A843AEA84F1910 /* PBXContainerItemProxy */; }; - 6B4B82E9706935B9950B575B6C1B42B3 /* PBXTargetDependency */ = { + 811B6D1BDCD74FBF733001D3D5F6DE7E /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXFileSystem; - targetProxy = 9AF5A7B953E92F6D2EFF76EFFDE4DE59 /* PBXContainerItemProxy */; + name = UMSensorsInterface; + targetProxy = 9D76DE94DE8A9BBDB566D04BDBAD1044 /* PBXContainerItemProxy */; }; - 6DA363B8D5958C02C2899867D87A3604 /* PBXTargetDependency */ = { + 839B3A3DB5D6EC00BF184CDFE1BC89CB /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = ReactCommon; - targetProxy = C7B8E4638B3FEEE41A30B79BCD5A66A2 /* PBXContainerItemProxy */; + name = "React-CoreModules"; + targetProxy = 56D4B2E5F7422F637672FED6B1CF986F /* PBXContainerItemProxy */; }; - 76648E6385C38D92D9919DD8BEFB72FA /* PBXTargetDependency */ = { + 84CC68EC049927C17EDEC11A282DB112 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXKeepAwake; - targetProxy = F6613DD846BED619D89CA5871B5D76BE /* PBXContainerItemProxy */; + name = EXImageManipulator; + targetProxy = D84005DE0A7FC1C2180D6DC48F158195 /* PBXContainerItemProxy */; }; - 76FC85DADC17FF90C5FDD5EBC9DB22F8 /* PBXTargetDependency */ = { + 8AD5472941BC778BC00CE66106DE52BE /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXLocalAuthentication; - targetProxy = B060D0AFB1E0CC3F9EFAB39BBB472BDE /* PBXContainerItemProxy */; + name = EXPrint; + targetProxy = B43AF8ADB4ABED542A191F0C92CDA58E /* PBXContainerItemProxy */; }; - 7AEE79031110CDCCD4AC9582EE18DBF1 /* PBXTargetDependency */ = { + 929A5F7FDCDD25EEBCB3E07A03C103CE /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXGL_CPP; - targetProxy = 39B15604EA16A09A49DA569249C7AA83 /* PBXContainerItemProxy */; + name = AppAuth; + targetProxy = 15EBFE0C5D680BC678D2BAEE2AA7EB17 /* PBXContainerItemProxy */; }; - 7ED59F0C6BB5C3C97A81252A98FDD60D /* PBXTargetDependency */ = { + 94545BA4E14CACC60668DBF5F7A7FB41 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXBlur; - targetProxy = 138B551B7760FEF12E9588FB05659D94 /* PBXContainerItemProxy */; + name = EXDevice; + targetProxy = B616A6DBE11835E3828477A080007882 /* PBXContainerItemProxy */; }; - 835E57D62A25653590E6A4879FE2E498 /* PBXTargetDependency */ = { + 978A0C95E2F96A89F932C532B6F90256 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXCalendar; - targetProxy = 0D95C376406A62ADA46606B0D3771DE2 /* PBXContainerItemProxy */; + name = EXGL_CPP; + targetProxy = A0702A3F3987D834E5CB524D7582BC42 /* PBXContainerItemProxy */; }; - 856A79330ECD4101A00DA78356547395 /* PBXTargetDependency */ = { + 97AD5E1C8C6461A410568E27E8298EE4 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = React; - targetProxy = BC28539A09791D00B0BBE33A1BFCC04F /* PBXContainerItemProxy */; + name = EXAppAuth; + targetProxy = 5886A4134F2FA5B8753778E853BA19BA /* PBXContainerItemProxy */; }; - 85BB7A1710A8F651EDD241F7D71D9490 /* PBXTargetDependency */ = { + 98155535013FAB952B26FD59EA592733 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXStoreReview; - targetProxy = 9B902F5A4F54D64F86DDBD98FFC44F69 /* PBXContainerItemProxy */; + name = EXAppLoaderProvider; + targetProxy = ED027510CF7496DCB9D74BD29EBBE262 /* PBXContainerItemProxy */; }; - 86A336B574906E89C02F69D66AC2808D /* PBXTargetDependency */ = { + 9A7EE76FE7B8451A3ABBEC321F37522A /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXSpeech; - targetProxy = 9B46D48EFD5EF68D89130936A94F0CD3 /* PBXContainerItemProxy */; + name = EXApplication; + targetProxy = E80BDFD8FD707172EE3568836C8E214F /* PBXContainerItemProxy */; }; - 8761BD1357846AC44DF8B0AD3BC395E4 /* PBXTargetDependency */ = { + A1E081118605689BEEB1687205A58BD5 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = UMCameraInterface; - targetProxy = B4151C4687EFC1E5E85C4622E62BABAA /* PBXContainerItemProxy */; + name = "boost-for-react-native"; + targetProxy = EFCF51AE8DE666A1A23D98409FEEA1AA /* PBXContainerItemProxy */; }; - 87B2B4711BCBD138FCB4F284EA4C8BC6 /* PBXTargetDependency */ = { + A3FBC5EB5E34437E8B39D57FA12EDDD7 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = "React-cxxreact"; - targetProxy = D1E465D8EE4E1BB41A4F686819B41C3F /* PBXContainerItemProxy */; + name = UMBarCodeScannerInterface; + targetProxy = BE305DBB61F72B252077F23B9000886B /* PBXContainerItemProxy */; }; - 88ABB33EF0314C0E1DE20E898CE4A48A /* PBXTargetDependency */ = { + A5D29CA2E6979DE225FF023B09BAB672 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXRandom; - targetProxy = B621C005B2348C73A36A9F050EF3AAEC /* PBXContainerItemProxy */; + name = RCTTypeSafety; + targetProxy = 5B3A54C1CC98D54A8BF01EC39A0CCE9A /* PBXContainerItemProxy */; }; - 8B21978C9FB81332E24D4A9F14A03B76 /* PBXTargetDependency */ = { + A7CCF6BB887BB5FA23764FFAA0F8C15F /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = RNGestureHandler; - targetProxy = 0FAD10CD5AEBC9229D69C5193AA1996D /* PBXContainerItemProxy */; + name = FBReactNativeSpec; + targetProxy = 395309C6928642091FF420CF2575E3AF /* PBXContainerItemProxy */; }; - 8D73DF6AB515BDCAAA2E924F15FD7543 /* PBXTargetDependency */ = { + AA83F07E10C8CA91A174A07FCA4D8A6E /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXPrint; - targetProxy = ECE72C945FEE79C19347B366A6114888 /* PBXContainerItemProxy */; + name = EXAV; + targetProxy = E4F13EAE7D0B938A6C9D9ADE3128ED84 /* PBXContainerItemProxy */; }; - 91231C8705F62ADF08EF987BC7F7F23A /* PBXTargetDependency */ = { + B53F9B180CF395A111802CF7D02CAAEF /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXLinearGradient; - targetProxy = 72CCD3670C80EA569EAE6696701FE495 /* PBXContainerItemProxy */; + name = EXRandom; + targetProxy = 7A966DD2F28C59FB519D21A29DAC0C3E /* PBXContainerItemProxy */; }; - 919D9299543E75927B76412AF77C67EB /* PBXTargetDependency */ = { + B9F37584BD5F5DF521EEAF7DA2550C50 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXImagePicker; - targetProxy = B142D18C098B8F928A3B28E83EE06A70 /* PBXContainerItemProxy */; + name = EXCrypto; + targetProxy = 2D3F02A4EF58120647F70AD3648877C9 /* PBXContainerItemProxy */; }; - 91D2A06942280D2149E8D2FECE2139DA /* PBXTargetDependency */ = { + BE534E2808AAB9F13F983B27B7A9294C /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = "Amplitude-iOS"; - targetProxy = 67D78E6479226F565CE530FAD81A8B39 /* PBXContainerItemProxy */; + name = "React-RCTNetwork"; + targetProxy = 89C1B83344DFB9F8757ED973FEFD75D8 /* PBXContainerItemProxy */; }; - 94930F6A17DE516441EAB3E4B56FDE83 /* PBXTargetDependency */ = { + BE769D0B980A5DB4845F947D415BA555 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXGL; - targetProxy = 0E638FE83654AAA0102A8CC346914D53 /* PBXContainerItemProxy */; + name = EXSQLite; + targetProxy = 9412205B3F0255BC6427D1FE79F93D4D /* PBXContainerItemProxy */; }; - 983CF6E21DB008E9A79C819012FBC053 /* PBXTargetDependency */ = { + BFC95FCE89B2927EF2E1EDD9629A6B85 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = GTMAppAuth; - targetProxy = 415E5BEBE0E75178ADED5451DEB88B6F /* PBXContainerItemProxy */; + name = "React-jsinspector"; + targetProxy = 1818CAC700E350A246DD8A1AD3C332F3 /* PBXContainerItemProxy */; }; - 9C1FA1598D376386D6CD15F13B05F844 /* PBXTargetDependency */ = { + C387DF4A58B28C4DA207FB0AD9E42348 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXUpdates; - targetProxy = E6029B48C29AAF21C67710BD18B592A9 /* PBXContainerItemProxy */; + name = EXSharing; + targetProxy = 299C7D8FCEEE584A590BCFE9CBC14FBF /* PBXContainerItemProxy */; }; - 9F74AAB317F546683493B1AA32B41061 /* PBXTargetDependency */ = { + C46368AB770EF37967821926E021655B /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = ZXingObjC; - targetProxy = 10F882494F1E53F051D53F1647C0F700 /* PBXContainerItemProxy */; + name = EXContacts; + targetProxy = 2C46490A97F4F656FDE29AFC58990241 /* PBXContainerItemProxy */; }; - A72A154D15AD1504DEE8CE49645A6D8E /* PBXTargetDependency */ = { + C73F214F338AF6934EC8B8210F1E4518 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXWebBrowser; - targetProxy = BA9CC7508F551A390E71FA7366A4BB7B /* PBXContainerItemProxy */; + name = EXFont; + targetProxy = CAF99F2177FE1B7C7F23798B15E0A5A7 /* PBXContainerItemProxy */; }; - A9CF24640E6BAC3911BFD39EC8991A9B /* PBXTargetDependency */ = { + C848DF48C5C46DCEE964DB9F7110C0CA /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = "react-native-safe-area-context"; - targetProxy = 64A6C9CE2FB3DF3B12C572FCB9448BD0 /* PBXContainerItemProxy */; + name = UMPermissionsInterface; + targetProxy = 30088EFDAAB1E9DE2384E33382C74BDE /* PBXContainerItemProxy */; }; - AB63AA75C19598CA9C832401B5B9B047 /* PBXTargetDependency */ = { + C996CD5E48EBD344EBD3F9B7EBFF161E /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = "React-RCTSettings"; - targetProxy = F891AEC19213E84B0E931017A9DD68A3 /* PBXContainerItemProxy */; + name = UMFontInterface; + targetProxy = 496ADDE86A2DCEA1811894FEDE15246A /* PBXContainerItemProxy */; }; - ADB4BFD566AFDD1299060706572125FE /* PBXTargetDependency */ = { + CA003B374ECABE4FCC0797795E0D7A24 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = "React-jsinspector"; - targetProxy = 01523E2DE8178E06D1C82D6E3664203C /* PBXContainerItemProxy */; + name = GTMAppAuth; + targetProxy = A45DAF1200969FEA0AAE45BA94FBE32D /* PBXContainerItemProxy */; }; - AF61AC42B51AAD8083082E9E97A532D6 /* PBXTargetDependency */ = { + CB630A8A25286F4E88724177E5CA654A /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXGoogleSignIn; - targetProxy = EB26241BADD0FC63FCBA5916C92149FB /* PBXContainerItemProxy */; + name = "React-jsi"; + targetProxy = 0465DF8591EAA0DA3C033AC54D14FF18 /* PBXContainerItemProxy */; }; - B48E006DA8F8AAD53D57E6AFE04AFD17 /* PBXTargetDependency */ = { + CC4024177BE3EF3FE61A9A3B3C018F1E /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = Folly; - targetProxy = 4FE18B2D19C547E0FF873FCE071D4A0D /* PBXContainerItemProxy */; + name = EXConstants; + targetProxy = 3A3442214292971BCE3FB68A3F07763B /* PBXContainerItemProxy */; }; - B74039FCB994BF9585D0D4215D0875C8 /* PBXTargetDependency */ = { + CC8E5348F1E30D61CA0DCA945DD4F365 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = EXSegment; - targetProxy = 54275ED60E349E7388A578FD6CAC77C9 /* PBXContainerItemProxy */; + targetProxy = D27C7DF1BFAE9F9C2D7274FCF3D08D5F /* PBXContainerItemProxy */; }; - BC84B0B805D0DF23F0B5D1160056B9A8 /* PBXTargetDependency */ = { + D1BF93DBD12BD38D63F3C1834F35A85D /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXSQLite; - targetProxy = 748CA12AEE04BEF5A766A071E198A2F3 /* PBXContainerItemProxy */; + name = RNReanimated; + targetProxy = 7582E2C1BD5F25FFE26C1115879B20E1 /* PBXContainerItemProxy */; }; - BEC0646C92263C5E750B29FD6901140F /* PBXTargetDependency */ = { + D1C4ACAFAA72572F8F61F24DA1BBB93D /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = "React-RCTText"; - targetProxy = C58FA3752529C35AD98AF55942791482 /* PBXContainerItemProxy */; + name = Analytics; + targetProxy = CB6007B65E78188B3DBC7B7B0B53EE7C /* PBXContainerItemProxy */; }; - BF03A3699E84F70F58A4C068CE723367 /* PBXTargetDependency */ = { + D2B61A644452D29E76D78C61565A3682 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXPermissions; - targetProxy = 0DE728E47B2336653C2DCDC120B4DBEF /* PBXContainerItemProxy */; + name = EXLocalAuthentication; + targetProxy = 4ADB525BF5F77FDD2CEEF68E2C4F36C3 /* PBXContainerItemProxy */; }; - C2ECFA6910CED7EFD2A5A498D869E980 /* PBXTargetDependency */ = { + D4AE12762722C68043841E0A82895AB1 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = RCTTypeSafety; - targetProxy = BF01986E6376555F8A81956D27CEE244 /* PBXContainerItemProxy */; + name = React; + targetProxy = 227262230BCEBE33778709618CB70E9B /* PBXContainerItemProxy */; }; - C3C71EE9BA9918D7266A6FFBE2175E03 /* PBXTargetDependency */ = { + D8085D697FDF15F9ACD35A8F667C1335 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = "React-RCTVibration"; - targetProxy = 284686AE181AFB3CF7D3966FEBB9063D /* PBXContainerItemProxy */; + name = UMConstantsInterface; + targetProxy = EF8186F7500A8E201AC45D09194C7997 /* PBXContainerItemProxy */; }; - C3DC6DBE2445FFE60812CAC637B5864A /* PBXTargetDependency */ = { + D8B65332F6F04283C4A524E41A644C7E /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = GoogleSignIn; - targetProxy = EC0BE966E103A871BD282F4BEAD88408 /* PBXContainerItemProxy */; + name = "React-RCTImage"; + targetProxy = 6FD2484E117822D91CEF929D743CB84F /* PBXContainerItemProxy */; }; - C7AE23F84AE918C528379534C668DCE0 /* PBXTargetDependency */ = { + D99886342357C6B0C1EC9E10BD60A6CA /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXMediaLibrary; - targetProxy = 838268DE1B4CA8F37523351A20B732E7 /* PBXContainerItemProxy */; + name = "Pods-BareExpo"; + target = C616BB9F650D110E835D02A3250F302E /* Pods-BareExpo */; + targetProxy = 70227CF8F6B2D08A40EC88165F2BAEE8 /* PBXContainerItemProxy */; }; - CB54F2A88C91D4157C8371E3352C28DB /* PBXTargetDependency */ = { + D9D6522A7F9C1E1C6F2DD5914631FAA9 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = "boost-for-react-native"; - targetProxy = 4D5B404E23A828F7AA99BBBA54EFDA9B /* PBXContainerItemProxy */; + name = EXGL; + targetProxy = A7F2BAC3294F187AAFAFAC16F66D2F77 /* PBXContainerItemProxy */; }; - CB74FAEC6179ED8E6DA650BC436B0217 /* PBXTargetDependency */ = { + E1C4A34F07DB6233F3BF2D2194A30469 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = AppAuth; - targetProxy = A58BD843AD668DFD173903AEB86893D7 /* PBXContainerItemProxy */; + name = EXBattery; + targetProxy = 8339A31787E72B0335048723E34B17A0 /* PBXContainerItemProxy */; }; - CC0B2B3947F5D1DB5CCBEC92CDE90B59 /* PBXTargetDependency */ = { + E50E2CACBAD5824E8F506F867D29E7F9 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXConstants; - targetProxy = 275C89C48B89E482C6C0A093E8672536 /* PBXContainerItemProxy */; + name = EXImagePicker; + targetProxy = 22549EA770513D61589580CBFFB1E807 /* PBXContainerItemProxy */; }; - CFEB7B078D667D898DCC8EEEF1FC5C82 /* PBXTargetDependency */ = { + E8551290A5DA862706D76E9756856FAF /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXBrightness; - targetProxy = 603B6A8FFFCAC287D8B39746D674B792 /* PBXContainerItemProxy */; + name = "React-RCTVibration"; + targetProxy = 238E361F058A96459D5F16A251E0920F /* PBXContainerItemProxy */; }; - D13E8EC0261A514C204BE1AF5FCE1A71 /* PBXTargetDependency */ = { + E95C2A53C42B0C4B2A3DD8ED22515054 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXErrorRecovery; - targetProxy = 8B6BE6262BA49516FE8E6F4D75224DD0 /* PBXContainerItemProxy */; + name = EXCellular; + targetProxy = 1090EB79679288E70162A4CE7209B308 /* PBXContainerItemProxy */; }; - D95A8BE51BA7A624286CB26082A825D7 /* PBXTargetDependency */ = { + EA540322798F361FD75AB353A1C9E425 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXImageManipulator; - targetProxy = 1CD7699E779B7207306C3A18AE7958E9 /* PBXContainerItemProxy */; + name = EXBarCodeScanner; + targetProxy = 0DC15D8582D6A9B17EA3D24BF2A5F567 /* PBXContainerItemProxy */; }; - D99886342357C6B0C1EC9E10BD60A6CA /* PBXTargetDependency */ = { + EDDEA0F9453E294ED1F1FA31E51F40F6 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = "Pods-BareExpo"; - target = C616BB9F650D110E835D02A3250F302E /* Pods-BareExpo */; - targetProxy = 70227CF8F6B2D08A40EC88165F2BAEE8 /* PBXContainerItemProxy */; + name = "React-jsiexecutor"; + targetProxy = BF42B9CC2019D0F91470CE826F220F28 /* PBXContainerItemProxy */; }; - DC62D20C43EFDA514ADDD1CA3E5A3612 /* PBXTargetDependency */ = { + EF8F66AA6D6C124FA84615C4FC2FE394 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = UMReactNativeAdapter; - targetProxy = 326C844A787822153322EEB5212C6F27 /* PBXContainerItemProxy */; + name = EXSpeech; + targetProxy = 1A08C035C5D4A09AC05CCB509F8F6D9F /* PBXContainerItemProxy */; }; - E69875FB639872DAE546EF4B38A99FFC /* PBXTargetDependency */ = { + F011689EA3A1147252210457C97FA573 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXApplication; - targetProxy = 3E4F5A1B13CBDC95AFB48D68224FBDEA /* PBXContainerItemProxy */; + name = EXBlur; + targetProxy = B22CA872137DE382F4D19A1808237607 /* PBXContainerItemProxy */; }; - EAFDA9B9134F1DF606BD4C18A97A874A /* PBXTargetDependency */ = { + F1F886C878767FC61B02C70AFED07CAE /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXFont; - targetProxy = A8B0AE310D7DFFEE773B7F31A8FC8DC7 /* PBXContainerItemProxy */; + name = glog; + targetProxy = 586B05268C91474689F61A15ED902913 /* PBXContainerItemProxy */; }; - EB510BB4F1A396F8FBC810E5DE644C4A /* PBXTargetDependency */ = { + F37D811CFA93B6AE8DED6C44168D5F40 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXAppAuth; - targetProxy = 9C3E3E2A9F7E24D3111FB14B5EE4B00D /* PBXContainerItemProxy */; + name = EXHaptics; + targetProxy = CC0A1C43A4C49CE5036AF9D65AE0A094 /* PBXContainerItemProxy */; }; - EFDD1908CE86282341ED19473B7AE71C /* PBXTargetDependency */ = { + F4B4B447B2FCD3B2D60B4FAEBC041A1A /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = UMConstantsInterface; - targetProxy = B3B22FDA90847B607B6AB701065D65BE /* PBXContainerItemProxy */; + name = "React-RCTLinking"; + targetProxy = 1C05065DBB3562956F366E93DDEBF6E4 /* PBXContainerItemProxy */; }; - F0DEEDCF04A5A943D216CA78725B1A59 /* PBXTargetDependency */ = { + F4D8474538222F1E4389329EA94E9A58 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = UMPermissionsInterface; - targetProxy = F5B574F9DB6077B85805505D38AC81FA /* PBXContainerItemProxy */; + name = EXLinearGradient; + targetProxy = BC67C44FE17DD6A19F9E8B7CA1B8C21C /* PBXContainerItemProxy */; }; - F67EDF6A0F61A98853459D1B6B6F30CB /* PBXTargetDependency */ = { + F66B89EB7E24031640FD65D48062E982 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = "React-RCTLinking"; - targetProxy = 179551060FF9EA6024A9C9F7CEF0B4BA /* PBXContainerItemProxy */; + name = EXStoreReview; + targetProxy = FF9E7C648C79FC370E36E22D87203385 /* PBXContainerItemProxy */; }; - FB8B0A16B9643FB2D121C43BE8B77BCE /* PBXTargetDependency */ = { + F906514B0D6BCE2CBA379DD64D057DCA /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = "React-RCTAnimation"; - targetProxy = B3DFA936118F40EC72787C517C5197ED /* PBXContainerItemProxy */; + name = EXDocumentPicker; + targetProxy = 5E64C90BB3D6B2D2266FA06EF57FEDE3 /* PBXContainerItemProxy */; }; - FC734C17AB4E1E840D10ADA1901A3113 /* PBXTargetDependency */ = { + FAB2907B370386C8A8D74F88C0AC18CD /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = EXSensors; - targetProxy = 6D82ECC6C79E6BD8C4D55A0CF63A4D21 /* PBXContainerItemProxy */; + name = GTMSessionFetcher; + targetProxy = AAFC45B81AD9B7003B656D494849C5BC /* PBXContainerItemProxy */; }; - FFF415525CCA9E6451D7DC64BF8E9558 /* PBXTargetDependency */ = { + FEA444976F0D70F22B23ABC76FB5ABCF /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = UMSensorsInterface; - targetProxy = E49E09ABFFD95C08AE12CE1C82C5B1C2 /* PBXContainerItemProxy */; + name = Folly; + targetProxy = 436B61B79E4477585A4EDB1DDA6D1502 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 186C5EE56BC105165FB5B73F0A23654C /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = C42944AE78D3C85AE9277FE320D54C35 /* Pods-BareExpo.release.xcconfig */; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CLANG_ENABLE_OBJC_WEAK = NO; - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - MACH_O_TYPE = staticlib; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; 196DFA3E4A09A28224918543529A1885 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1991,6 +1986,29 @@ }; name = Debug; }; + 34C6D7723CE1A4F8E9221BA053103146 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = C42944AE78D3C85AE9277FE320D54C35 /* Pods-BareExpo.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + MACH_O_TYPE = staticlib; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; 6252BAC8F776E655D51C48A49BF6EFB2 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 0B584D0632E15581F96D24B9C3B042D7 /* Pods-BareExpoTests.release.xcconfig */; @@ -2014,6 +2032,28 @@ }; name = Release; }; + ABF374522C8F86ACD391A735DEFDAE88 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 6D02C945BC67559AFEB7B446AD8A35E6 /* Pods-BareExpo.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + MACH_O_TYPE = staticlib; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; B01D14FDC83DCF9D4BE53066BEA96D05 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { @@ -2096,45 +2136,23 @@ }; name = Debug; }; - F68AA0ABC81AD6B6A5764E8A14B679A8 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 6D02C945BC67559AFEB7B446AD8A35E6 /* Pods-BareExpo.debug.xcconfig */; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CLANG_ENABLE_OBJC_WEAK = NO; - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - MACH_O_TYPE = staticlib; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 19B0920102FB081C56D8699A0F9D676E /* Build configuration list for PBXNativeTarget "Pods-BareExpo" */ = { + 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { isa = XCConfigurationList; buildConfigurations = ( - F68AA0ABC81AD6B6A5764E8A14B679A8 /* Debug */, - 186C5EE56BC105165FB5B73F0A23654C /* Release */, + 196DFA3E4A09A28224918543529A1885 /* Debug */, + B01D14FDC83DCF9D4BE53066BEA96D05 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { + A832C04A5E806A099A7BB7DE00106985 /* Build configuration list for PBXNativeTarget "Pods-BareExpo" */ = { isa = XCConfigurationList; buildConfigurations = ( - 196DFA3E4A09A28224918543529A1885 /* Debug */, - B01D14FDC83DCF9D4BE53066BEA96D05 /* Release */, + ABF374522C8F86ACD391A735DEFDAE88 /* Debug */, + 34C6D7723CE1A4F8E9221BA053103146 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/apps/bare-expo/ios/Pods/Target Support Files/EXNotifications/EXNotifications-dummy.m b/apps/bare-expo/ios/Pods/Target Support Files/EXNotifications/EXNotifications-dummy.m new file mode 100644 index 0000000000000..08241e6161207 --- /dev/null +++ b/apps/bare-expo/ios/Pods/Target Support Files/EXNotifications/EXNotifications-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_EXNotifications : NSObject +@end +@implementation PodsDummy_EXNotifications +@end diff --git a/apps/bare-expo/ios/Pods/Target Support Files/EXNotifications/EXNotifications-prefix.pch b/apps/bare-expo/ios/Pods/Target Support Files/EXNotifications/EXNotifications-prefix.pch new file mode 100644 index 0000000000000..beb2a2441835a --- /dev/null +++ b/apps/bare-expo/ios/Pods/Target Support Files/EXNotifications/EXNotifications-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/apps/bare-expo/ios/Pods/Target Support Files/EXNotifications/EXNotifications.xcconfig b/apps/bare-expo/ios/Pods/Target Support Files/EXNotifications/EXNotifications.xcconfig new file mode 100644 index 0000000000000..ccffcfd1675ec --- /dev/null +++ b/apps/bare-expo/ios/Pods/Target Support Files/EXNotifications/EXNotifications.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/EXNotifications +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/EXNotifications" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/EXNotifications" "${PODS_ROOT}/Headers/Public/UMCore" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/../../../../packages/expo-notifications/ios +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/apps/bare-expo/ios/Pods/Target Support Files/Pods-BareExpo/Pods-BareExpo.debug.xcconfig b/apps/bare-expo/ios/Pods/Target Support Files/Pods-BareExpo/Pods-BareExpo.debug.xcconfig index 323d5db107207..e22d98e458a6f 100644 --- a/apps/bare-expo/ios/Pods/Target Support Files/Pods-BareExpo/Pods-BareExpo.debug.xcconfig +++ b/apps/bare-expo/ios/Pods/Target Support Files/Pods-BareExpo/Pods-BareExpo.debug.xcconfig @@ -1,9 +1,9 @@ FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/GoogleSignIn/Frameworks" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 ZXINGOBJC_USE_SUBSPECS ZXINGOBJC_USE_SUBSPECS ZXINGOBJC_ONED ZXINGOBJC_USE_SUBSPECS ZXINGOBJC_PDF417 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Amplitude-iOS" "${PODS_ROOT}/Headers/Public/Analytics" "${PODS_ROOT}/Headers/Public/AppAuth" "${PODS_ROOT}/Headers/Public/DoubleConversion" "${PODS_ROOT}/Headers/Public/EXAV" "${PODS_ROOT}/Headers/Public/EXAmplitude" "${PODS_ROOT}/Headers/Public/EXAppAuth" "${PODS_ROOT}/Headers/Public/EXAppLoaderProvider" "${PODS_ROOT}/Headers/Public/EXApplication" "${PODS_ROOT}/Headers/Public/EXBarCodeScanner" "${PODS_ROOT}/Headers/Public/EXBattery" "${PODS_ROOT}/Headers/Public/EXBluetooth" "${PODS_ROOT}/Headers/Public/EXBlur" "${PODS_ROOT}/Headers/Public/EXBrightness" "${PODS_ROOT}/Headers/Public/EXCalendar" "${PODS_ROOT}/Headers/Public/EXCellular" "${PODS_ROOT}/Headers/Public/EXConstants" "${PODS_ROOT}/Headers/Public/EXContacts" "${PODS_ROOT}/Headers/Public/EXCrypto" "${PODS_ROOT}/Headers/Public/EXDevice" "${PODS_ROOT}/Headers/Public/EXDocumentPicker" "${PODS_ROOT}/Headers/Public/EXErrorRecovery" "${PODS_ROOT}/Headers/Public/EXFileSystem" "${PODS_ROOT}/Headers/Public/EXFont" "${PODS_ROOT}/Headers/Public/EXGL" "${PODS_ROOT}/Headers/Public/EXGL_CPP" "${PODS_ROOT}/Headers/Public/EXGoogleSignIn" "${PODS_ROOT}/Headers/Public/EXHaptics" "${PODS_ROOT}/Headers/Public/EXImageManipulator" "${PODS_ROOT}/Headers/Public/EXImagePicker" "${PODS_ROOT}/Headers/Public/EXKeepAwake" "${PODS_ROOT}/Headers/Public/EXLinearGradient" "${PODS_ROOT}/Headers/Public/EXLocalAuthentication" "${PODS_ROOT}/Headers/Public/EXLocalization" "${PODS_ROOT}/Headers/Public/EXMailComposer" "${PODS_ROOT}/Headers/Public/EXMediaLibrary" "${PODS_ROOT}/Headers/Public/EXNetwork" "${PODS_ROOT}/Headers/Public/EXPermissions" "${PODS_ROOT}/Headers/Public/EXPrint" "${PODS_ROOT}/Headers/Public/EXRandom" "${PODS_ROOT}/Headers/Public/EXSMS" "${PODS_ROOT}/Headers/Public/EXSQLite" "${PODS_ROOT}/Headers/Public/EXSecureStore" "${PODS_ROOT}/Headers/Public/EXSegment" "${PODS_ROOT}/Headers/Public/EXSensors" "${PODS_ROOT}/Headers/Public/EXSharing" "${PODS_ROOT}/Headers/Public/EXSpeech" "${PODS_ROOT}/Headers/Public/EXStoreReview" "${PODS_ROOT}/Headers/Public/EXUpdates" "${PODS_ROOT}/Headers/Public/EXWebBrowser" "${PODS_ROOT}/Headers/Public/FBLazyVector" "${PODS_ROOT}/Headers/Public/FBReactNativeSpec" "${PODS_ROOT}/Headers/Public/GTMAppAuth" "${PODS_ROOT}/Headers/Public/GTMSessionFetcher" "${PODS_ROOT}/Headers/Public/RCTRequired" "${PODS_ROOT}/Headers/Public/RCTTypeSafety" "${PODS_ROOT}/Headers/Public/RNGestureHandler" "${PODS_ROOT}/Headers/Public/RNReanimated" "${PODS_ROOT}/Headers/Public/React-Core" "${PODS_ROOT}/Headers/Public/React-RCTBlob" "${PODS_ROOT}/Headers/Public/React-RCTText" "${PODS_ROOT}/Headers/Public/React-cxxreact" "${PODS_ROOT}/Headers/Public/React-jsi" "${PODS_ROOT}/Headers/Public/React-jsiexecutor" "${PODS_ROOT}/Headers/Public/React-jsinspector" "${PODS_ROOT}/Headers/Public/ReactCommon" "${PODS_ROOT}/Headers/Public/UMBarCodeScannerInterface" "${PODS_ROOT}/Headers/Public/UMCameraInterface" "${PODS_ROOT}/Headers/Public/UMConstantsInterface" "${PODS_ROOT}/Headers/Public/UMCore" "${PODS_ROOT}/Headers/Public/UMFileSystemInterface" "${PODS_ROOT}/Headers/Public/UMFontInterface" "${PODS_ROOT}/Headers/Public/UMImageLoaderInterface" "${PODS_ROOT}/Headers/Public/UMPermissionsInterface" "${PODS_ROOT}/Headers/Public/UMReactNativeAdapter" "${PODS_ROOT}/Headers/Public/UMSensorsInterface" "${PODS_ROOT}/Headers/Public/Yoga" "${PODS_ROOT}/Headers/Public/ZXingObjC" "${PODS_ROOT}/Headers/Public/glog" "${PODS_ROOT}/Headers/Public/react-native-safe-area-context" "$(PODS_ROOT)/Headers/Private/React-Core" -LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Amplitude-iOS" "${PODS_CONFIGURATION_BUILD_DIR}/Analytics" "${PODS_CONFIGURATION_BUILD_DIR}/AppAuth" "${PODS_CONFIGURATION_BUILD_DIR}/DoubleConversion" "${PODS_CONFIGURATION_BUILD_DIR}/EXAV" "${PODS_CONFIGURATION_BUILD_DIR}/EXAmplitude" "${PODS_CONFIGURATION_BUILD_DIR}/EXAppAuth" "${PODS_CONFIGURATION_BUILD_DIR}/EXAppLoaderProvider" "${PODS_CONFIGURATION_BUILD_DIR}/EXApplication" "${PODS_CONFIGURATION_BUILD_DIR}/EXBarCodeScanner" "${PODS_CONFIGURATION_BUILD_DIR}/EXBattery" "${PODS_CONFIGURATION_BUILD_DIR}/EXBluetooth" "${PODS_CONFIGURATION_BUILD_DIR}/EXBlur" "${PODS_CONFIGURATION_BUILD_DIR}/EXBrightness" "${PODS_CONFIGURATION_BUILD_DIR}/EXCalendar" "${PODS_CONFIGURATION_BUILD_DIR}/EXCellular" "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants" "${PODS_CONFIGURATION_BUILD_DIR}/EXContacts" "${PODS_CONFIGURATION_BUILD_DIR}/EXCrypto" "${PODS_CONFIGURATION_BUILD_DIR}/EXDevice" "${PODS_CONFIGURATION_BUILD_DIR}/EXDocumentPicker" "${PODS_CONFIGURATION_BUILD_DIR}/EXErrorRecovery" "${PODS_CONFIGURATION_BUILD_DIR}/EXFileSystem" "${PODS_CONFIGURATION_BUILD_DIR}/EXFont" "${PODS_CONFIGURATION_BUILD_DIR}/EXGL" "${PODS_CONFIGURATION_BUILD_DIR}/EXGL_CPP" "${PODS_CONFIGURATION_BUILD_DIR}/EXGoogleSignIn" "${PODS_CONFIGURATION_BUILD_DIR}/EXHaptics" "${PODS_CONFIGURATION_BUILD_DIR}/EXImageManipulator" "${PODS_CONFIGURATION_BUILD_DIR}/EXImagePicker" "${PODS_CONFIGURATION_BUILD_DIR}/EXKeepAwake" "${PODS_CONFIGURATION_BUILD_DIR}/EXLinearGradient" "${PODS_CONFIGURATION_BUILD_DIR}/EXLocalAuthentication" "${PODS_CONFIGURATION_BUILD_DIR}/EXLocalization" "${PODS_CONFIGURATION_BUILD_DIR}/EXMailComposer" "${PODS_CONFIGURATION_BUILD_DIR}/EXMediaLibrary" "${PODS_CONFIGURATION_BUILD_DIR}/EXNetwork" "${PODS_CONFIGURATION_BUILD_DIR}/EXPermissions" "${PODS_CONFIGURATION_BUILD_DIR}/EXPrint" "${PODS_CONFIGURATION_BUILD_DIR}/EXRandom" "${PODS_CONFIGURATION_BUILD_DIR}/EXSMS" "${PODS_CONFIGURATION_BUILD_DIR}/EXSQLite" "${PODS_CONFIGURATION_BUILD_DIR}/EXSecureStore" "${PODS_CONFIGURATION_BUILD_DIR}/EXSegment" "${PODS_CONFIGURATION_BUILD_DIR}/EXSensors" "${PODS_CONFIGURATION_BUILD_DIR}/EXSharing" "${PODS_CONFIGURATION_BUILD_DIR}/EXSpeech" "${PODS_CONFIGURATION_BUILD_DIR}/EXStoreReview" "${PODS_CONFIGURATION_BUILD_DIR}/EXUpdates" "${PODS_CONFIGURATION_BUILD_DIR}/EXWebBrowser" "${PODS_CONFIGURATION_BUILD_DIR}/FBReactNativeSpec" "${PODS_CONFIGURATION_BUILD_DIR}/Folly" "${PODS_CONFIGURATION_BUILD_DIR}/GTMAppAuth" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" "${PODS_CONFIGURATION_BUILD_DIR}/RCTTypeSafety" "${PODS_CONFIGURATION_BUILD_DIR}/RNGestureHandler" "${PODS_CONFIGURATION_BUILD_DIR}/RNReanimated" "${PODS_CONFIGURATION_BUILD_DIR}/React-Core" "${PODS_CONFIGURATION_BUILD_DIR}/React-CoreModules" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTActionSheet" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTAnimation" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTBlob" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTImage" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTLinking" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTNetwork" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTSettings" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTText" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTVibration" "${PODS_CONFIGURATION_BUILD_DIR}/React-cxxreact" "${PODS_CONFIGURATION_BUILD_DIR}/React-jsi" "${PODS_CONFIGURATION_BUILD_DIR}/React-jsiexecutor" "${PODS_CONFIGURATION_BUILD_DIR}/React-jsinspector" "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon" "${PODS_CONFIGURATION_BUILD_DIR}/UMCore" "${PODS_CONFIGURATION_BUILD_DIR}/UMPermissionsInterface" "${PODS_CONFIGURATION_BUILD_DIR}/UMReactNativeAdapter" "${PODS_CONFIGURATION_BUILD_DIR}/Yoga" "${PODS_CONFIGURATION_BUILD_DIR}/ZXingObjC" "${PODS_CONFIGURATION_BUILD_DIR}/glog" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-safe-area-context" +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Amplitude-iOS" "${PODS_ROOT}/Headers/Public/Analytics" "${PODS_ROOT}/Headers/Public/AppAuth" "${PODS_ROOT}/Headers/Public/DoubleConversion" "${PODS_ROOT}/Headers/Public/EXAV" "${PODS_ROOT}/Headers/Public/EXAmplitude" "${PODS_ROOT}/Headers/Public/EXAppAuth" "${PODS_ROOT}/Headers/Public/EXAppLoaderProvider" "${PODS_ROOT}/Headers/Public/EXApplication" "${PODS_ROOT}/Headers/Public/EXBarCodeScanner" "${PODS_ROOT}/Headers/Public/EXBattery" "${PODS_ROOT}/Headers/Public/EXBluetooth" "${PODS_ROOT}/Headers/Public/EXBlur" "${PODS_ROOT}/Headers/Public/EXBrightness" "${PODS_ROOT}/Headers/Public/EXCalendar" "${PODS_ROOT}/Headers/Public/EXCellular" "${PODS_ROOT}/Headers/Public/EXConstants" "${PODS_ROOT}/Headers/Public/EXContacts" "${PODS_ROOT}/Headers/Public/EXCrypto" "${PODS_ROOT}/Headers/Public/EXDevice" "${PODS_ROOT}/Headers/Public/EXDocumentPicker" "${PODS_ROOT}/Headers/Public/EXErrorRecovery" "${PODS_ROOT}/Headers/Public/EXFileSystem" "${PODS_ROOT}/Headers/Public/EXFont" "${PODS_ROOT}/Headers/Public/EXGL" "${PODS_ROOT}/Headers/Public/EXGL_CPP" "${PODS_ROOT}/Headers/Public/EXGoogleSignIn" "${PODS_ROOT}/Headers/Public/EXHaptics" "${PODS_ROOT}/Headers/Public/EXImageManipulator" "${PODS_ROOT}/Headers/Public/EXImagePicker" "${PODS_ROOT}/Headers/Public/EXKeepAwake" "${PODS_ROOT}/Headers/Public/EXLinearGradient" "${PODS_ROOT}/Headers/Public/EXLocalAuthentication" "${PODS_ROOT}/Headers/Public/EXLocalization" "${PODS_ROOT}/Headers/Public/EXMailComposer" "${PODS_ROOT}/Headers/Public/EXMediaLibrary" "${PODS_ROOT}/Headers/Public/EXNetwork" "${PODS_ROOT}/Headers/Public/EXNotifications" "${PODS_ROOT}/Headers/Public/EXPermissions" "${PODS_ROOT}/Headers/Public/EXPrint" "${PODS_ROOT}/Headers/Public/EXRandom" "${PODS_ROOT}/Headers/Public/EXSMS" "${PODS_ROOT}/Headers/Public/EXSQLite" "${PODS_ROOT}/Headers/Public/EXSecureStore" "${PODS_ROOT}/Headers/Public/EXSegment" "${PODS_ROOT}/Headers/Public/EXSensors" "${PODS_ROOT}/Headers/Public/EXSharing" "${PODS_ROOT}/Headers/Public/EXSpeech" "${PODS_ROOT}/Headers/Public/EXStoreReview" "${PODS_ROOT}/Headers/Public/EXUpdates" "${PODS_ROOT}/Headers/Public/EXWebBrowser" "${PODS_ROOT}/Headers/Public/FBLazyVector" "${PODS_ROOT}/Headers/Public/FBReactNativeSpec" "${PODS_ROOT}/Headers/Public/GTMAppAuth" "${PODS_ROOT}/Headers/Public/GTMSessionFetcher" "${PODS_ROOT}/Headers/Public/RCTRequired" "${PODS_ROOT}/Headers/Public/RCTTypeSafety" "${PODS_ROOT}/Headers/Public/RNGestureHandler" "${PODS_ROOT}/Headers/Public/RNReanimated" "${PODS_ROOT}/Headers/Public/React-Core" "${PODS_ROOT}/Headers/Public/React-RCTBlob" "${PODS_ROOT}/Headers/Public/React-RCTText" "${PODS_ROOT}/Headers/Public/React-cxxreact" "${PODS_ROOT}/Headers/Public/React-jsi" "${PODS_ROOT}/Headers/Public/React-jsiexecutor" "${PODS_ROOT}/Headers/Public/React-jsinspector" "${PODS_ROOT}/Headers/Public/ReactCommon" "${PODS_ROOT}/Headers/Public/UMBarCodeScannerInterface" "${PODS_ROOT}/Headers/Public/UMCameraInterface" "${PODS_ROOT}/Headers/Public/UMConstantsInterface" "${PODS_ROOT}/Headers/Public/UMCore" "${PODS_ROOT}/Headers/Public/UMFileSystemInterface" "${PODS_ROOT}/Headers/Public/UMFontInterface" "${PODS_ROOT}/Headers/Public/UMImageLoaderInterface" "${PODS_ROOT}/Headers/Public/UMPermissionsInterface" "${PODS_ROOT}/Headers/Public/UMReactNativeAdapter" "${PODS_ROOT}/Headers/Public/UMSensorsInterface" "${PODS_ROOT}/Headers/Public/Yoga" "${PODS_ROOT}/Headers/Public/ZXingObjC" "${PODS_ROOT}/Headers/Public/glog" "${PODS_ROOT}/Headers/Public/react-native-safe-area-context" "$(PODS_ROOT)/Headers/Private/React-Core" +LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Amplitude-iOS" "${PODS_CONFIGURATION_BUILD_DIR}/Analytics" "${PODS_CONFIGURATION_BUILD_DIR}/AppAuth" "${PODS_CONFIGURATION_BUILD_DIR}/DoubleConversion" "${PODS_CONFIGURATION_BUILD_DIR}/EXAV" "${PODS_CONFIGURATION_BUILD_DIR}/EXAmplitude" "${PODS_CONFIGURATION_BUILD_DIR}/EXAppAuth" "${PODS_CONFIGURATION_BUILD_DIR}/EXAppLoaderProvider" "${PODS_CONFIGURATION_BUILD_DIR}/EXApplication" "${PODS_CONFIGURATION_BUILD_DIR}/EXBarCodeScanner" "${PODS_CONFIGURATION_BUILD_DIR}/EXBattery" "${PODS_CONFIGURATION_BUILD_DIR}/EXBluetooth" "${PODS_CONFIGURATION_BUILD_DIR}/EXBlur" "${PODS_CONFIGURATION_BUILD_DIR}/EXBrightness" "${PODS_CONFIGURATION_BUILD_DIR}/EXCalendar" "${PODS_CONFIGURATION_BUILD_DIR}/EXCellular" "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants" "${PODS_CONFIGURATION_BUILD_DIR}/EXContacts" "${PODS_CONFIGURATION_BUILD_DIR}/EXCrypto" "${PODS_CONFIGURATION_BUILD_DIR}/EXDevice" "${PODS_CONFIGURATION_BUILD_DIR}/EXDocumentPicker" "${PODS_CONFIGURATION_BUILD_DIR}/EXErrorRecovery" "${PODS_CONFIGURATION_BUILD_DIR}/EXFileSystem" "${PODS_CONFIGURATION_BUILD_DIR}/EXFont" "${PODS_CONFIGURATION_BUILD_DIR}/EXGL" "${PODS_CONFIGURATION_BUILD_DIR}/EXGL_CPP" "${PODS_CONFIGURATION_BUILD_DIR}/EXGoogleSignIn" "${PODS_CONFIGURATION_BUILD_DIR}/EXHaptics" "${PODS_CONFIGURATION_BUILD_DIR}/EXImageManipulator" "${PODS_CONFIGURATION_BUILD_DIR}/EXImagePicker" "${PODS_CONFIGURATION_BUILD_DIR}/EXKeepAwake" "${PODS_CONFIGURATION_BUILD_DIR}/EXLinearGradient" "${PODS_CONFIGURATION_BUILD_DIR}/EXLocalAuthentication" "${PODS_CONFIGURATION_BUILD_DIR}/EXLocalization" "${PODS_CONFIGURATION_BUILD_DIR}/EXMailComposer" "${PODS_CONFIGURATION_BUILD_DIR}/EXMediaLibrary" "${PODS_CONFIGURATION_BUILD_DIR}/EXNetwork" "${PODS_CONFIGURATION_BUILD_DIR}/EXNotifications" "${PODS_CONFIGURATION_BUILD_DIR}/EXPermissions" "${PODS_CONFIGURATION_BUILD_DIR}/EXPrint" "${PODS_CONFIGURATION_BUILD_DIR}/EXRandom" "${PODS_CONFIGURATION_BUILD_DIR}/EXSMS" "${PODS_CONFIGURATION_BUILD_DIR}/EXSQLite" "${PODS_CONFIGURATION_BUILD_DIR}/EXSecureStore" "${PODS_CONFIGURATION_BUILD_DIR}/EXSegment" "${PODS_CONFIGURATION_BUILD_DIR}/EXSensors" "${PODS_CONFIGURATION_BUILD_DIR}/EXSharing" "${PODS_CONFIGURATION_BUILD_DIR}/EXSpeech" "${PODS_CONFIGURATION_BUILD_DIR}/EXStoreReview" "${PODS_CONFIGURATION_BUILD_DIR}/EXUpdates" "${PODS_CONFIGURATION_BUILD_DIR}/EXWebBrowser" "${PODS_CONFIGURATION_BUILD_DIR}/FBReactNativeSpec" "${PODS_CONFIGURATION_BUILD_DIR}/Folly" "${PODS_CONFIGURATION_BUILD_DIR}/GTMAppAuth" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" "${PODS_CONFIGURATION_BUILD_DIR}/RCTTypeSafety" "${PODS_CONFIGURATION_BUILD_DIR}/RNGestureHandler" "${PODS_CONFIGURATION_BUILD_DIR}/RNReanimated" "${PODS_CONFIGURATION_BUILD_DIR}/React-Core" "${PODS_CONFIGURATION_BUILD_DIR}/React-CoreModules" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTActionSheet" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTAnimation" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTBlob" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTImage" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTLinking" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTNetwork" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTSettings" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTText" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTVibration" "${PODS_CONFIGURATION_BUILD_DIR}/React-cxxreact" "${PODS_CONFIGURATION_BUILD_DIR}/React-jsi" "${PODS_CONFIGURATION_BUILD_DIR}/React-jsiexecutor" "${PODS_CONFIGURATION_BUILD_DIR}/React-jsinspector" "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon" "${PODS_CONFIGURATION_BUILD_DIR}/UMCore" "${PODS_CONFIGURATION_BUILD_DIR}/UMPermissionsInterface" "${PODS_CONFIGURATION_BUILD_DIR}/UMReactNativeAdapter" "${PODS_CONFIGURATION_BUILD_DIR}/Yoga" "${PODS_CONFIGURATION_BUILD_DIR}/ZXingObjC" "${PODS_CONFIGURATION_BUILD_DIR}/glog" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-safe-area-context" OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/Amplitude-iOS" -isystem "${PODS_ROOT}/Headers/Public/Analytics" -isystem "${PODS_ROOT}/Headers/Public/AppAuth" -isystem "${PODS_ROOT}/Headers/Public/DoubleConversion" -isystem "${PODS_ROOT}/Headers/Public/FBLazyVector" -isystem "${PODS_ROOT}/Headers/Public/FBReactNativeSpec" -isystem "${PODS_ROOT}/Headers/Public/RCTRequired" -isystem "${PODS_ROOT}/Headers/Public/RCTTypeSafety" -isystem "${PODS_ROOT}/Headers/Public/React-Core" -isystem "${PODS_ROOT}/Headers/Public/React-cxxreact" -isystem "${PODS_ROOT}/Headers/Public/React-jsi" -isystem "${PODS_ROOT}/Headers/Public/React-jsiexecutor" -isystem "${PODS_ROOT}/Headers/Public/React-jsinspector" -isystem "${PODS_ROOT}/Headers/Public/ReactCommon" -isystem "${PODS_ROOT}/Headers/Public/Yoga" -isystem "${PODS_ROOT}/Headers/Public/glog" -isystem "${PODS_ROOT}/Headers/Public/GTMAppAuth" -isystem "${PODS_ROOT}/Headers/Public/GTMSessionFetcher" -isystem "${PODS_ROOT}/Headers/Public/RNGestureHandler" -isystem "${PODS_ROOT}/Headers/Public/React-RCTBlob" -isystem "${PODS_ROOT}/Headers/Public/React-RCTText" -isystem "${PODS_ROOT}/Headers/Public/RNReanimated" -isystem "${PODS_ROOT}/Headers/Public/ZXingObjC" -isystem "${PODS_ROOT}/Headers/Public/react-native-safe-area-context" -iframework "${PODS_ROOT}/GoogleSignIn/Frameworks" -OTHER_LDFLAGS = $(inherited) -ObjC -l"Amplitude-iOS" -l"Analytics" -l"AppAuth" -l"DoubleConversion" -l"EXAV" -l"EXAmplitude" -l"EXAppAuth" -l"EXAppLoaderProvider" -l"EXApplication" -l"EXBarCodeScanner" -l"EXBattery" -l"EXBluetooth" -l"EXBlur" -l"EXBrightness" -l"EXCalendar" -l"EXCellular" -l"EXConstants" -l"EXContacts" -l"EXCrypto" -l"EXDevice" -l"EXDocumentPicker" -l"EXErrorRecovery" -l"EXFileSystem" -l"EXFont" -l"EXGL" -l"EXGL_CPP" -l"EXGoogleSignIn" -l"EXHaptics" -l"EXImageManipulator" -l"EXImagePicker" -l"EXKeepAwake" -l"EXLinearGradient" -l"EXLocalAuthentication" -l"EXLocalization" -l"EXMailComposer" -l"EXMediaLibrary" -l"EXNetwork" -l"EXPermissions" -l"EXPrint" -l"EXRandom" -l"EXSMS" -l"EXSQLite" -l"EXSecureStore" -l"EXSegment" -l"EXSensors" -l"EXSharing" -l"EXSpeech" -l"EXStoreReview" -l"EXUpdates" -l"EXWebBrowser" -l"FBReactNativeSpec" -l"Folly" -l"GTMAppAuth" -l"GTMSessionFetcher" -l"RCTTypeSafety" -l"RNGestureHandler" -l"RNReanimated" -l"React-Core" -l"React-CoreModules" -l"React-RCTActionSheet" -l"React-RCTAnimation" -l"React-RCTBlob" -l"React-RCTImage" -l"React-RCTLinking" -l"React-RCTNetwork" -l"React-RCTSettings" -l"React-RCTText" -l"React-RCTVibration" -l"React-cxxreact" -l"React-jsi" -l"React-jsiexecutor" -l"React-jsinspector" -l"ReactCommon" -l"UMCore" -l"UMPermissionsInterface" -l"UMReactNativeAdapter" -l"Yoga" -l"ZXingObjC" -l"glog" -l"react-native-safe-area-context" -l"sqlite3.0" -l"stdc++" -framework "AVFoundation" -framework "CoreGraphics" -framework "CoreMedia" -framework "CoreTelephony" -framework "CoreText" -framework "CoreVideo" -framework "Foundation" -framework "GoogleSignIn" -framework "ImageIO" -framework "JavaScriptCore" -framework "LocalAuthentication" -framework "QuartzCore" -framework "SafariServices" -framework "Security" -framework "StoreKit" -framework "SystemConfiguration" -framework "UIKit" -weak_framework "AuthenticationServices" +OTHER_LDFLAGS = $(inherited) -ObjC -l"Amplitude-iOS" -l"Analytics" -l"AppAuth" -l"DoubleConversion" -l"EXAV" -l"EXAmplitude" -l"EXAppAuth" -l"EXAppLoaderProvider" -l"EXApplication" -l"EXBarCodeScanner" -l"EXBattery" -l"EXBluetooth" -l"EXBlur" -l"EXBrightness" -l"EXCalendar" -l"EXCellular" -l"EXConstants" -l"EXContacts" -l"EXCrypto" -l"EXDevice" -l"EXDocumentPicker" -l"EXErrorRecovery" -l"EXFileSystem" -l"EXFont" -l"EXGL" -l"EXGL_CPP" -l"EXGoogleSignIn" -l"EXHaptics" -l"EXImageManipulator" -l"EXImagePicker" -l"EXKeepAwake" -l"EXLinearGradient" -l"EXLocalAuthentication" -l"EXLocalization" -l"EXMailComposer" -l"EXMediaLibrary" -l"EXNetwork" -l"EXNotifications" -l"EXPermissions" -l"EXPrint" -l"EXRandom" -l"EXSMS" -l"EXSQLite" -l"EXSecureStore" -l"EXSegment" -l"EXSensors" -l"EXSharing" -l"EXSpeech" -l"EXStoreReview" -l"EXUpdates" -l"EXWebBrowser" -l"FBReactNativeSpec" -l"Folly" -l"GTMAppAuth" -l"GTMSessionFetcher" -l"RCTTypeSafety" -l"RNGestureHandler" -l"RNReanimated" -l"React-Core" -l"React-CoreModules" -l"React-RCTActionSheet" -l"React-RCTAnimation" -l"React-RCTBlob" -l"React-RCTImage" -l"React-RCTLinking" -l"React-RCTNetwork" -l"React-RCTSettings" -l"React-RCTText" -l"React-RCTVibration" -l"React-cxxreact" -l"React-jsi" -l"React-jsiexecutor" -l"React-jsinspector" -l"ReactCommon" -l"UMCore" -l"UMPermissionsInterface" -l"UMReactNativeAdapter" -l"Yoga" -l"ZXingObjC" -l"glog" -l"react-native-safe-area-context" -l"sqlite3.0" -l"stdc++" -framework "AVFoundation" -framework "CoreGraphics" -framework "CoreMedia" -framework "CoreTelephony" -framework "CoreText" -framework "CoreVideo" -framework "Foundation" -framework "GoogleSignIn" -framework "ImageIO" -framework "JavaScriptCore" -framework "LocalAuthentication" -framework "QuartzCore" -framework "SafariServices" -framework "Security" -framework "StoreKit" -framework "SystemConfiguration" -framework "UIKit" -weak_framework "AuthenticationServices" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. diff --git a/apps/bare-expo/ios/Pods/Target Support Files/Pods-BareExpo/Pods-BareExpo.release.xcconfig b/apps/bare-expo/ios/Pods/Target Support Files/Pods-BareExpo/Pods-BareExpo.release.xcconfig index 323d5db107207..e22d98e458a6f 100644 --- a/apps/bare-expo/ios/Pods/Target Support Files/Pods-BareExpo/Pods-BareExpo.release.xcconfig +++ b/apps/bare-expo/ios/Pods/Target Support Files/Pods-BareExpo/Pods-BareExpo.release.xcconfig @@ -1,9 +1,9 @@ FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/GoogleSignIn/Frameworks" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 ZXINGOBJC_USE_SUBSPECS ZXINGOBJC_USE_SUBSPECS ZXINGOBJC_ONED ZXINGOBJC_USE_SUBSPECS ZXINGOBJC_PDF417 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Amplitude-iOS" "${PODS_ROOT}/Headers/Public/Analytics" "${PODS_ROOT}/Headers/Public/AppAuth" "${PODS_ROOT}/Headers/Public/DoubleConversion" "${PODS_ROOT}/Headers/Public/EXAV" "${PODS_ROOT}/Headers/Public/EXAmplitude" "${PODS_ROOT}/Headers/Public/EXAppAuth" "${PODS_ROOT}/Headers/Public/EXAppLoaderProvider" "${PODS_ROOT}/Headers/Public/EXApplication" "${PODS_ROOT}/Headers/Public/EXBarCodeScanner" "${PODS_ROOT}/Headers/Public/EXBattery" "${PODS_ROOT}/Headers/Public/EXBluetooth" "${PODS_ROOT}/Headers/Public/EXBlur" "${PODS_ROOT}/Headers/Public/EXBrightness" "${PODS_ROOT}/Headers/Public/EXCalendar" "${PODS_ROOT}/Headers/Public/EXCellular" "${PODS_ROOT}/Headers/Public/EXConstants" "${PODS_ROOT}/Headers/Public/EXContacts" "${PODS_ROOT}/Headers/Public/EXCrypto" "${PODS_ROOT}/Headers/Public/EXDevice" "${PODS_ROOT}/Headers/Public/EXDocumentPicker" "${PODS_ROOT}/Headers/Public/EXErrorRecovery" "${PODS_ROOT}/Headers/Public/EXFileSystem" "${PODS_ROOT}/Headers/Public/EXFont" "${PODS_ROOT}/Headers/Public/EXGL" "${PODS_ROOT}/Headers/Public/EXGL_CPP" "${PODS_ROOT}/Headers/Public/EXGoogleSignIn" "${PODS_ROOT}/Headers/Public/EXHaptics" "${PODS_ROOT}/Headers/Public/EXImageManipulator" "${PODS_ROOT}/Headers/Public/EXImagePicker" "${PODS_ROOT}/Headers/Public/EXKeepAwake" "${PODS_ROOT}/Headers/Public/EXLinearGradient" "${PODS_ROOT}/Headers/Public/EXLocalAuthentication" "${PODS_ROOT}/Headers/Public/EXLocalization" "${PODS_ROOT}/Headers/Public/EXMailComposer" "${PODS_ROOT}/Headers/Public/EXMediaLibrary" "${PODS_ROOT}/Headers/Public/EXNetwork" "${PODS_ROOT}/Headers/Public/EXPermissions" "${PODS_ROOT}/Headers/Public/EXPrint" "${PODS_ROOT}/Headers/Public/EXRandom" "${PODS_ROOT}/Headers/Public/EXSMS" "${PODS_ROOT}/Headers/Public/EXSQLite" "${PODS_ROOT}/Headers/Public/EXSecureStore" "${PODS_ROOT}/Headers/Public/EXSegment" "${PODS_ROOT}/Headers/Public/EXSensors" "${PODS_ROOT}/Headers/Public/EXSharing" "${PODS_ROOT}/Headers/Public/EXSpeech" "${PODS_ROOT}/Headers/Public/EXStoreReview" "${PODS_ROOT}/Headers/Public/EXUpdates" "${PODS_ROOT}/Headers/Public/EXWebBrowser" "${PODS_ROOT}/Headers/Public/FBLazyVector" "${PODS_ROOT}/Headers/Public/FBReactNativeSpec" "${PODS_ROOT}/Headers/Public/GTMAppAuth" "${PODS_ROOT}/Headers/Public/GTMSessionFetcher" "${PODS_ROOT}/Headers/Public/RCTRequired" "${PODS_ROOT}/Headers/Public/RCTTypeSafety" "${PODS_ROOT}/Headers/Public/RNGestureHandler" "${PODS_ROOT}/Headers/Public/RNReanimated" "${PODS_ROOT}/Headers/Public/React-Core" "${PODS_ROOT}/Headers/Public/React-RCTBlob" "${PODS_ROOT}/Headers/Public/React-RCTText" "${PODS_ROOT}/Headers/Public/React-cxxreact" "${PODS_ROOT}/Headers/Public/React-jsi" "${PODS_ROOT}/Headers/Public/React-jsiexecutor" "${PODS_ROOT}/Headers/Public/React-jsinspector" "${PODS_ROOT}/Headers/Public/ReactCommon" "${PODS_ROOT}/Headers/Public/UMBarCodeScannerInterface" "${PODS_ROOT}/Headers/Public/UMCameraInterface" "${PODS_ROOT}/Headers/Public/UMConstantsInterface" "${PODS_ROOT}/Headers/Public/UMCore" "${PODS_ROOT}/Headers/Public/UMFileSystemInterface" "${PODS_ROOT}/Headers/Public/UMFontInterface" "${PODS_ROOT}/Headers/Public/UMImageLoaderInterface" "${PODS_ROOT}/Headers/Public/UMPermissionsInterface" "${PODS_ROOT}/Headers/Public/UMReactNativeAdapter" "${PODS_ROOT}/Headers/Public/UMSensorsInterface" "${PODS_ROOT}/Headers/Public/Yoga" "${PODS_ROOT}/Headers/Public/ZXingObjC" "${PODS_ROOT}/Headers/Public/glog" "${PODS_ROOT}/Headers/Public/react-native-safe-area-context" "$(PODS_ROOT)/Headers/Private/React-Core" -LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Amplitude-iOS" "${PODS_CONFIGURATION_BUILD_DIR}/Analytics" "${PODS_CONFIGURATION_BUILD_DIR}/AppAuth" "${PODS_CONFIGURATION_BUILD_DIR}/DoubleConversion" "${PODS_CONFIGURATION_BUILD_DIR}/EXAV" "${PODS_CONFIGURATION_BUILD_DIR}/EXAmplitude" "${PODS_CONFIGURATION_BUILD_DIR}/EXAppAuth" "${PODS_CONFIGURATION_BUILD_DIR}/EXAppLoaderProvider" "${PODS_CONFIGURATION_BUILD_DIR}/EXApplication" "${PODS_CONFIGURATION_BUILD_DIR}/EXBarCodeScanner" "${PODS_CONFIGURATION_BUILD_DIR}/EXBattery" "${PODS_CONFIGURATION_BUILD_DIR}/EXBluetooth" "${PODS_CONFIGURATION_BUILD_DIR}/EXBlur" "${PODS_CONFIGURATION_BUILD_DIR}/EXBrightness" "${PODS_CONFIGURATION_BUILD_DIR}/EXCalendar" "${PODS_CONFIGURATION_BUILD_DIR}/EXCellular" "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants" "${PODS_CONFIGURATION_BUILD_DIR}/EXContacts" "${PODS_CONFIGURATION_BUILD_DIR}/EXCrypto" "${PODS_CONFIGURATION_BUILD_DIR}/EXDevice" "${PODS_CONFIGURATION_BUILD_DIR}/EXDocumentPicker" "${PODS_CONFIGURATION_BUILD_DIR}/EXErrorRecovery" "${PODS_CONFIGURATION_BUILD_DIR}/EXFileSystem" "${PODS_CONFIGURATION_BUILD_DIR}/EXFont" "${PODS_CONFIGURATION_BUILD_DIR}/EXGL" "${PODS_CONFIGURATION_BUILD_DIR}/EXGL_CPP" "${PODS_CONFIGURATION_BUILD_DIR}/EXGoogleSignIn" "${PODS_CONFIGURATION_BUILD_DIR}/EXHaptics" "${PODS_CONFIGURATION_BUILD_DIR}/EXImageManipulator" "${PODS_CONFIGURATION_BUILD_DIR}/EXImagePicker" "${PODS_CONFIGURATION_BUILD_DIR}/EXKeepAwake" "${PODS_CONFIGURATION_BUILD_DIR}/EXLinearGradient" "${PODS_CONFIGURATION_BUILD_DIR}/EXLocalAuthentication" "${PODS_CONFIGURATION_BUILD_DIR}/EXLocalization" "${PODS_CONFIGURATION_BUILD_DIR}/EXMailComposer" "${PODS_CONFIGURATION_BUILD_DIR}/EXMediaLibrary" "${PODS_CONFIGURATION_BUILD_DIR}/EXNetwork" "${PODS_CONFIGURATION_BUILD_DIR}/EXPermissions" "${PODS_CONFIGURATION_BUILD_DIR}/EXPrint" "${PODS_CONFIGURATION_BUILD_DIR}/EXRandom" "${PODS_CONFIGURATION_BUILD_DIR}/EXSMS" "${PODS_CONFIGURATION_BUILD_DIR}/EXSQLite" "${PODS_CONFIGURATION_BUILD_DIR}/EXSecureStore" "${PODS_CONFIGURATION_BUILD_DIR}/EXSegment" "${PODS_CONFIGURATION_BUILD_DIR}/EXSensors" "${PODS_CONFIGURATION_BUILD_DIR}/EXSharing" "${PODS_CONFIGURATION_BUILD_DIR}/EXSpeech" "${PODS_CONFIGURATION_BUILD_DIR}/EXStoreReview" "${PODS_CONFIGURATION_BUILD_DIR}/EXUpdates" "${PODS_CONFIGURATION_BUILD_DIR}/EXWebBrowser" "${PODS_CONFIGURATION_BUILD_DIR}/FBReactNativeSpec" "${PODS_CONFIGURATION_BUILD_DIR}/Folly" "${PODS_CONFIGURATION_BUILD_DIR}/GTMAppAuth" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" "${PODS_CONFIGURATION_BUILD_DIR}/RCTTypeSafety" "${PODS_CONFIGURATION_BUILD_DIR}/RNGestureHandler" "${PODS_CONFIGURATION_BUILD_DIR}/RNReanimated" "${PODS_CONFIGURATION_BUILD_DIR}/React-Core" "${PODS_CONFIGURATION_BUILD_DIR}/React-CoreModules" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTActionSheet" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTAnimation" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTBlob" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTImage" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTLinking" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTNetwork" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTSettings" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTText" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTVibration" "${PODS_CONFIGURATION_BUILD_DIR}/React-cxxreact" "${PODS_CONFIGURATION_BUILD_DIR}/React-jsi" "${PODS_CONFIGURATION_BUILD_DIR}/React-jsiexecutor" "${PODS_CONFIGURATION_BUILD_DIR}/React-jsinspector" "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon" "${PODS_CONFIGURATION_BUILD_DIR}/UMCore" "${PODS_CONFIGURATION_BUILD_DIR}/UMPermissionsInterface" "${PODS_CONFIGURATION_BUILD_DIR}/UMReactNativeAdapter" "${PODS_CONFIGURATION_BUILD_DIR}/Yoga" "${PODS_CONFIGURATION_BUILD_DIR}/ZXingObjC" "${PODS_CONFIGURATION_BUILD_DIR}/glog" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-safe-area-context" +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Amplitude-iOS" "${PODS_ROOT}/Headers/Public/Analytics" "${PODS_ROOT}/Headers/Public/AppAuth" "${PODS_ROOT}/Headers/Public/DoubleConversion" "${PODS_ROOT}/Headers/Public/EXAV" "${PODS_ROOT}/Headers/Public/EXAmplitude" "${PODS_ROOT}/Headers/Public/EXAppAuth" "${PODS_ROOT}/Headers/Public/EXAppLoaderProvider" "${PODS_ROOT}/Headers/Public/EXApplication" "${PODS_ROOT}/Headers/Public/EXBarCodeScanner" "${PODS_ROOT}/Headers/Public/EXBattery" "${PODS_ROOT}/Headers/Public/EXBluetooth" "${PODS_ROOT}/Headers/Public/EXBlur" "${PODS_ROOT}/Headers/Public/EXBrightness" "${PODS_ROOT}/Headers/Public/EXCalendar" "${PODS_ROOT}/Headers/Public/EXCellular" "${PODS_ROOT}/Headers/Public/EXConstants" "${PODS_ROOT}/Headers/Public/EXContacts" "${PODS_ROOT}/Headers/Public/EXCrypto" "${PODS_ROOT}/Headers/Public/EXDevice" "${PODS_ROOT}/Headers/Public/EXDocumentPicker" "${PODS_ROOT}/Headers/Public/EXErrorRecovery" "${PODS_ROOT}/Headers/Public/EXFileSystem" "${PODS_ROOT}/Headers/Public/EXFont" "${PODS_ROOT}/Headers/Public/EXGL" "${PODS_ROOT}/Headers/Public/EXGL_CPP" "${PODS_ROOT}/Headers/Public/EXGoogleSignIn" "${PODS_ROOT}/Headers/Public/EXHaptics" "${PODS_ROOT}/Headers/Public/EXImageManipulator" "${PODS_ROOT}/Headers/Public/EXImagePicker" "${PODS_ROOT}/Headers/Public/EXKeepAwake" "${PODS_ROOT}/Headers/Public/EXLinearGradient" "${PODS_ROOT}/Headers/Public/EXLocalAuthentication" "${PODS_ROOT}/Headers/Public/EXLocalization" "${PODS_ROOT}/Headers/Public/EXMailComposer" "${PODS_ROOT}/Headers/Public/EXMediaLibrary" "${PODS_ROOT}/Headers/Public/EXNetwork" "${PODS_ROOT}/Headers/Public/EXNotifications" "${PODS_ROOT}/Headers/Public/EXPermissions" "${PODS_ROOT}/Headers/Public/EXPrint" "${PODS_ROOT}/Headers/Public/EXRandom" "${PODS_ROOT}/Headers/Public/EXSMS" "${PODS_ROOT}/Headers/Public/EXSQLite" "${PODS_ROOT}/Headers/Public/EXSecureStore" "${PODS_ROOT}/Headers/Public/EXSegment" "${PODS_ROOT}/Headers/Public/EXSensors" "${PODS_ROOT}/Headers/Public/EXSharing" "${PODS_ROOT}/Headers/Public/EXSpeech" "${PODS_ROOT}/Headers/Public/EXStoreReview" "${PODS_ROOT}/Headers/Public/EXUpdates" "${PODS_ROOT}/Headers/Public/EXWebBrowser" "${PODS_ROOT}/Headers/Public/FBLazyVector" "${PODS_ROOT}/Headers/Public/FBReactNativeSpec" "${PODS_ROOT}/Headers/Public/GTMAppAuth" "${PODS_ROOT}/Headers/Public/GTMSessionFetcher" "${PODS_ROOT}/Headers/Public/RCTRequired" "${PODS_ROOT}/Headers/Public/RCTTypeSafety" "${PODS_ROOT}/Headers/Public/RNGestureHandler" "${PODS_ROOT}/Headers/Public/RNReanimated" "${PODS_ROOT}/Headers/Public/React-Core" "${PODS_ROOT}/Headers/Public/React-RCTBlob" "${PODS_ROOT}/Headers/Public/React-RCTText" "${PODS_ROOT}/Headers/Public/React-cxxreact" "${PODS_ROOT}/Headers/Public/React-jsi" "${PODS_ROOT}/Headers/Public/React-jsiexecutor" "${PODS_ROOT}/Headers/Public/React-jsinspector" "${PODS_ROOT}/Headers/Public/ReactCommon" "${PODS_ROOT}/Headers/Public/UMBarCodeScannerInterface" "${PODS_ROOT}/Headers/Public/UMCameraInterface" "${PODS_ROOT}/Headers/Public/UMConstantsInterface" "${PODS_ROOT}/Headers/Public/UMCore" "${PODS_ROOT}/Headers/Public/UMFileSystemInterface" "${PODS_ROOT}/Headers/Public/UMFontInterface" "${PODS_ROOT}/Headers/Public/UMImageLoaderInterface" "${PODS_ROOT}/Headers/Public/UMPermissionsInterface" "${PODS_ROOT}/Headers/Public/UMReactNativeAdapter" "${PODS_ROOT}/Headers/Public/UMSensorsInterface" "${PODS_ROOT}/Headers/Public/Yoga" "${PODS_ROOT}/Headers/Public/ZXingObjC" "${PODS_ROOT}/Headers/Public/glog" "${PODS_ROOT}/Headers/Public/react-native-safe-area-context" "$(PODS_ROOT)/Headers/Private/React-Core" +LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Amplitude-iOS" "${PODS_CONFIGURATION_BUILD_DIR}/Analytics" "${PODS_CONFIGURATION_BUILD_DIR}/AppAuth" "${PODS_CONFIGURATION_BUILD_DIR}/DoubleConversion" "${PODS_CONFIGURATION_BUILD_DIR}/EXAV" "${PODS_CONFIGURATION_BUILD_DIR}/EXAmplitude" "${PODS_CONFIGURATION_BUILD_DIR}/EXAppAuth" "${PODS_CONFIGURATION_BUILD_DIR}/EXAppLoaderProvider" "${PODS_CONFIGURATION_BUILD_DIR}/EXApplication" "${PODS_CONFIGURATION_BUILD_DIR}/EXBarCodeScanner" "${PODS_CONFIGURATION_BUILD_DIR}/EXBattery" "${PODS_CONFIGURATION_BUILD_DIR}/EXBluetooth" "${PODS_CONFIGURATION_BUILD_DIR}/EXBlur" "${PODS_CONFIGURATION_BUILD_DIR}/EXBrightness" "${PODS_CONFIGURATION_BUILD_DIR}/EXCalendar" "${PODS_CONFIGURATION_BUILD_DIR}/EXCellular" "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants" "${PODS_CONFIGURATION_BUILD_DIR}/EXContacts" "${PODS_CONFIGURATION_BUILD_DIR}/EXCrypto" "${PODS_CONFIGURATION_BUILD_DIR}/EXDevice" "${PODS_CONFIGURATION_BUILD_DIR}/EXDocumentPicker" "${PODS_CONFIGURATION_BUILD_DIR}/EXErrorRecovery" "${PODS_CONFIGURATION_BUILD_DIR}/EXFileSystem" "${PODS_CONFIGURATION_BUILD_DIR}/EXFont" "${PODS_CONFIGURATION_BUILD_DIR}/EXGL" "${PODS_CONFIGURATION_BUILD_DIR}/EXGL_CPP" "${PODS_CONFIGURATION_BUILD_DIR}/EXGoogleSignIn" "${PODS_CONFIGURATION_BUILD_DIR}/EXHaptics" "${PODS_CONFIGURATION_BUILD_DIR}/EXImageManipulator" "${PODS_CONFIGURATION_BUILD_DIR}/EXImagePicker" "${PODS_CONFIGURATION_BUILD_DIR}/EXKeepAwake" "${PODS_CONFIGURATION_BUILD_DIR}/EXLinearGradient" "${PODS_CONFIGURATION_BUILD_DIR}/EXLocalAuthentication" "${PODS_CONFIGURATION_BUILD_DIR}/EXLocalization" "${PODS_CONFIGURATION_BUILD_DIR}/EXMailComposer" "${PODS_CONFIGURATION_BUILD_DIR}/EXMediaLibrary" "${PODS_CONFIGURATION_BUILD_DIR}/EXNetwork" "${PODS_CONFIGURATION_BUILD_DIR}/EXNotifications" "${PODS_CONFIGURATION_BUILD_DIR}/EXPermissions" "${PODS_CONFIGURATION_BUILD_DIR}/EXPrint" "${PODS_CONFIGURATION_BUILD_DIR}/EXRandom" "${PODS_CONFIGURATION_BUILD_DIR}/EXSMS" "${PODS_CONFIGURATION_BUILD_DIR}/EXSQLite" "${PODS_CONFIGURATION_BUILD_DIR}/EXSecureStore" "${PODS_CONFIGURATION_BUILD_DIR}/EXSegment" "${PODS_CONFIGURATION_BUILD_DIR}/EXSensors" "${PODS_CONFIGURATION_BUILD_DIR}/EXSharing" "${PODS_CONFIGURATION_BUILD_DIR}/EXSpeech" "${PODS_CONFIGURATION_BUILD_DIR}/EXStoreReview" "${PODS_CONFIGURATION_BUILD_DIR}/EXUpdates" "${PODS_CONFIGURATION_BUILD_DIR}/EXWebBrowser" "${PODS_CONFIGURATION_BUILD_DIR}/FBReactNativeSpec" "${PODS_CONFIGURATION_BUILD_DIR}/Folly" "${PODS_CONFIGURATION_BUILD_DIR}/GTMAppAuth" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" "${PODS_CONFIGURATION_BUILD_DIR}/RCTTypeSafety" "${PODS_CONFIGURATION_BUILD_DIR}/RNGestureHandler" "${PODS_CONFIGURATION_BUILD_DIR}/RNReanimated" "${PODS_CONFIGURATION_BUILD_DIR}/React-Core" "${PODS_CONFIGURATION_BUILD_DIR}/React-CoreModules" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTActionSheet" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTAnimation" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTBlob" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTImage" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTLinking" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTNetwork" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTSettings" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTText" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTVibration" "${PODS_CONFIGURATION_BUILD_DIR}/React-cxxreact" "${PODS_CONFIGURATION_BUILD_DIR}/React-jsi" "${PODS_CONFIGURATION_BUILD_DIR}/React-jsiexecutor" "${PODS_CONFIGURATION_BUILD_DIR}/React-jsinspector" "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon" "${PODS_CONFIGURATION_BUILD_DIR}/UMCore" "${PODS_CONFIGURATION_BUILD_DIR}/UMPermissionsInterface" "${PODS_CONFIGURATION_BUILD_DIR}/UMReactNativeAdapter" "${PODS_CONFIGURATION_BUILD_DIR}/Yoga" "${PODS_CONFIGURATION_BUILD_DIR}/ZXingObjC" "${PODS_CONFIGURATION_BUILD_DIR}/glog" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-safe-area-context" OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/Amplitude-iOS" -isystem "${PODS_ROOT}/Headers/Public/Analytics" -isystem "${PODS_ROOT}/Headers/Public/AppAuth" -isystem "${PODS_ROOT}/Headers/Public/DoubleConversion" -isystem "${PODS_ROOT}/Headers/Public/FBLazyVector" -isystem "${PODS_ROOT}/Headers/Public/FBReactNativeSpec" -isystem "${PODS_ROOT}/Headers/Public/RCTRequired" -isystem "${PODS_ROOT}/Headers/Public/RCTTypeSafety" -isystem "${PODS_ROOT}/Headers/Public/React-Core" -isystem "${PODS_ROOT}/Headers/Public/React-cxxreact" -isystem "${PODS_ROOT}/Headers/Public/React-jsi" -isystem "${PODS_ROOT}/Headers/Public/React-jsiexecutor" -isystem "${PODS_ROOT}/Headers/Public/React-jsinspector" -isystem "${PODS_ROOT}/Headers/Public/ReactCommon" -isystem "${PODS_ROOT}/Headers/Public/Yoga" -isystem "${PODS_ROOT}/Headers/Public/glog" -isystem "${PODS_ROOT}/Headers/Public/GTMAppAuth" -isystem "${PODS_ROOT}/Headers/Public/GTMSessionFetcher" -isystem "${PODS_ROOT}/Headers/Public/RNGestureHandler" -isystem "${PODS_ROOT}/Headers/Public/React-RCTBlob" -isystem "${PODS_ROOT}/Headers/Public/React-RCTText" -isystem "${PODS_ROOT}/Headers/Public/RNReanimated" -isystem "${PODS_ROOT}/Headers/Public/ZXingObjC" -isystem "${PODS_ROOT}/Headers/Public/react-native-safe-area-context" -iframework "${PODS_ROOT}/GoogleSignIn/Frameworks" -OTHER_LDFLAGS = $(inherited) -ObjC -l"Amplitude-iOS" -l"Analytics" -l"AppAuth" -l"DoubleConversion" -l"EXAV" -l"EXAmplitude" -l"EXAppAuth" -l"EXAppLoaderProvider" -l"EXApplication" -l"EXBarCodeScanner" -l"EXBattery" -l"EXBluetooth" -l"EXBlur" -l"EXBrightness" -l"EXCalendar" -l"EXCellular" -l"EXConstants" -l"EXContacts" -l"EXCrypto" -l"EXDevice" -l"EXDocumentPicker" -l"EXErrorRecovery" -l"EXFileSystem" -l"EXFont" -l"EXGL" -l"EXGL_CPP" -l"EXGoogleSignIn" -l"EXHaptics" -l"EXImageManipulator" -l"EXImagePicker" -l"EXKeepAwake" -l"EXLinearGradient" -l"EXLocalAuthentication" -l"EXLocalization" -l"EXMailComposer" -l"EXMediaLibrary" -l"EXNetwork" -l"EXPermissions" -l"EXPrint" -l"EXRandom" -l"EXSMS" -l"EXSQLite" -l"EXSecureStore" -l"EXSegment" -l"EXSensors" -l"EXSharing" -l"EXSpeech" -l"EXStoreReview" -l"EXUpdates" -l"EXWebBrowser" -l"FBReactNativeSpec" -l"Folly" -l"GTMAppAuth" -l"GTMSessionFetcher" -l"RCTTypeSafety" -l"RNGestureHandler" -l"RNReanimated" -l"React-Core" -l"React-CoreModules" -l"React-RCTActionSheet" -l"React-RCTAnimation" -l"React-RCTBlob" -l"React-RCTImage" -l"React-RCTLinking" -l"React-RCTNetwork" -l"React-RCTSettings" -l"React-RCTText" -l"React-RCTVibration" -l"React-cxxreact" -l"React-jsi" -l"React-jsiexecutor" -l"React-jsinspector" -l"ReactCommon" -l"UMCore" -l"UMPermissionsInterface" -l"UMReactNativeAdapter" -l"Yoga" -l"ZXingObjC" -l"glog" -l"react-native-safe-area-context" -l"sqlite3.0" -l"stdc++" -framework "AVFoundation" -framework "CoreGraphics" -framework "CoreMedia" -framework "CoreTelephony" -framework "CoreText" -framework "CoreVideo" -framework "Foundation" -framework "GoogleSignIn" -framework "ImageIO" -framework "JavaScriptCore" -framework "LocalAuthentication" -framework "QuartzCore" -framework "SafariServices" -framework "Security" -framework "StoreKit" -framework "SystemConfiguration" -framework "UIKit" -weak_framework "AuthenticationServices" +OTHER_LDFLAGS = $(inherited) -ObjC -l"Amplitude-iOS" -l"Analytics" -l"AppAuth" -l"DoubleConversion" -l"EXAV" -l"EXAmplitude" -l"EXAppAuth" -l"EXAppLoaderProvider" -l"EXApplication" -l"EXBarCodeScanner" -l"EXBattery" -l"EXBluetooth" -l"EXBlur" -l"EXBrightness" -l"EXCalendar" -l"EXCellular" -l"EXConstants" -l"EXContacts" -l"EXCrypto" -l"EXDevice" -l"EXDocumentPicker" -l"EXErrorRecovery" -l"EXFileSystem" -l"EXFont" -l"EXGL" -l"EXGL_CPP" -l"EXGoogleSignIn" -l"EXHaptics" -l"EXImageManipulator" -l"EXImagePicker" -l"EXKeepAwake" -l"EXLinearGradient" -l"EXLocalAuthentication" -l"EXLocalization" -l"EXMailComposer" -l"EXMediaLibrary" -l"EXNetwork" -l"EXNotifications" -l"EXPermissions" -l"EXPrint" -l"EXRandom" -l"EXSMS" -l"EXSQLite" -l"EXSecureStore" -l"EXSegment" -l"EXSensors" -l"EXSharing" -l"EXSpeech" -l"EXStoreReview" -l"EXUpdates" -l"EXWebBrowser" -l"FBReactNativeSpec" -l"Folly" -l"GTMAppAuth" -l"GTMSessionFetcher" -l"RCTTypeSafety" -l"RNGestureHandler" -l"RNReanimated" -l"React-Core" -l"React-CoreModules" -l"React-RCTActionSheet" -l"React-RCTAnimation" -l"React-RCTBlob" -l"React-RCTImage" -l"React-RCTLinking" -l"React-RCTNetwork" -l"React-RCTSettings" -l"React-RCTText" -l"React-RCTVibration" -l"React-cxxreact" -l"React-jsi" -l"React-jsiexecutor" -l"React-jsinspector" -l"ReactCommon" -l"UMCore" -l"UMPermissionsInterface" -l"UMReactNativeAdapter" -l"Yoga" -l"ZXingObjC" -l"glog" -l"react-native-safe-area-context" -l"sqlite3.0" -l"stdc++" -framework "AVFoundation" -framework "CoreGraphics" -framework "CoreMedia" -framework "CoreTelephony" -framework "CoreText" -framework "CoreVideo" -framework "Foundation" -framework "GoogleSignIn" -framework "ImageIO" -framework "JavaScriptCore" -framework "LocalAuthentication" -framework "QuartzCore" -framework "SafariServices" -framework "Security" -framework "StoreKit" -framework "SystemConfiguration" -framework "UIKit" -weak_framework "AuthenticationServices" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. diff --git a/apps/bare-expo/ios/Pods/Target Support Files/Pods-BareExpoTests/Pods-BareExpoTests.debug.xcconfig b/apps/bare-expo/ios/Pods/Target Support Files/Pods-BareExpoTests/Pods-BareExpoTests.debug.xcconfig index 72fa95c67ecc7..1f48d1cd49dde 100644 --- a/apps/bare-expo/ios/Pods/Target Support Files/Pods-BareExpoTests/Pods-BareExpoTests.debug.xcconfig +++ b/apps/bare-expo/ios/Pods/Target Support Files/Pods-BareExpoTests/Pods-BareExpoTests.debug.xcconfig @@ -1,6 +1,6 @@ FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/GoogleSignIn/Frameworks" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 ZXINGOBJC_USE_SUBSPECS ZXINGOBJC_USE_SUBSPECS ZXINGOBJC_ONED ZXINGOBJC_USE_SUBSPECS ZXINGOBJC_PDF417 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Amplitude-iOS" "${PODS_ROOT}/Headers/Public/Analytics" "${PODS_ROOT}/Headers/Public/AppAuth" "${PODS_ROOT}/Headers/Public/DoubleConversion" "${PODS_ROOT}/Headers/Public/EXAV" "${PODS_ROOT}/Headers/Public/EXAmplitude" "${PODS_ROOT}/Headers/Public/EXAppAuth" "${PODS_ROOT}/Headers/Public/EXAppLoaderProvider" "${PODS_ROOT}/Headers/Public/EXApplication" "${PODS_ROOT}/Headers/Public/EXBarCodeScanner" "${PODS_ROOT}/Headers/Public/EXBattery" "${PODS_ROOT}/Headers/Public/EXBluetooth" "${PODS_ROOT}/Headers/Public/EXBlur" "${PODS_ROOT}/Headers/Public/EXBrightness" "${PODS_ROOT}/Headers/Public/EXCalendar" "${PODS_ROOT}/Headers/Public/EXCellular" "${PODS_ROOT}/Headers/Public/EXConstants" "${PODS_ROOT}/Headers/Public/EXContacts" "${PODS_ROOT}/Headers/Public/EXCrypto" "${PODS_ROOT}/Headers/Public/EXDevice" "${PODS_ROOT}/Headers/Public/EXDocumentPicker" "${PODS_ROOT}/Headers/Public/EXErrorRecovery" "${PODS_ROOT}/Headers/Public/EXFileSystem" "${PODS_ROOT}/Headers/Public/EXFont" "${PODS_ROOT}/Headers/Public/EXGL" "${PODS_ROOT}/Headers/Public/EXGL_CPP" "${PODS_ROOT}/Headers/Public/EXGoogleSignIn" "${PODS_ROOT}/Headers/Public/EXHaptics" "${PODS_ROOT}/Headers/Public/EXImageManipulator" "${PODS_ROOT}/Headers/Public/EXImagePicker" "${PODS_ROOT}/Headers/Public/EXKeepAwake" "${PODS_ROOT}/Headers/Public/EXLinearGradient" "${PODS_ROOT}/Headers/Public/EXLocalAuthentication" "${PODS_ROOT}/Headers/Public/EXLocalization" "${PODS_ROOT}/Headers/Public/EXMailComposer" "${PODS_ROOT}/Headers/Public/EXMediaLibrary" "${PODS_ROOT}/Headers/Public/EXNetwork" "${PODS_ROOT}/Headers/Public/EXPermissions" "${PODS_ROOT}/Headers/Public/EXPrint" "${PODS_ROOT}/Headers/Public/EXRandom" "${PODS_ROOT}/Headers/Public/EXSMS" "${PODS_ROOT}/Headers/Public/EXSQLite" "${PODS_ROOT}/Headers/Public/EXSecureStore" "${PODS_ROOT}/Headers/Public/EXSegment" "${PODS_ROOT}/Headers/Public/EXSensors" "${PODS_ROOT}/Headers/Public/EXSharing" "${PODS_ROOT}/Headers/Public/EXSpeech" "${PODS_ROOT}/Headers/Public/EXStoreReview" "${PODS_ROOT}/Headers/Public/EXUpdates" "${PODS_ROOT}/Headers/Public/EXWebBrowser" "${PODS_ROOT}/Headers/Public/FBLazyVector" "${PODS_ROOT}/Headers/Public/FBReactNativeSpec" "${PODS_ROOT}/Headers/Public/GTMAppAuth" "${PODS_ROOT}/Headers/Public/GTMSessionFetcher" "${PODS_ROOT}/Headers/Public/RCTRequired" "${PODS_ROOT}/Headers/Public/RCTTypeSafety" "${PODS_ROOT}/Headers/Public/RNGestureHandler" "${PODS_ROOT}/Headers/Public/RNReanimated" "${PODS_ROOT}/Headers/Public/React-Core" "${PODS_ROOT}/Headers/Public/React-RCTBlob" "${PODS_ROOT}/Headers/Public/React-RCTText" "${PODS_ROOT}/Headers/Public/React-cxxreact" "${PODS_ROOT}/Headers/Public/React-jsi" "${PODS_ROOT}/Headers/Public/React-jsiexecutor" "${PODS_ROOT}/Headers/Public/React-jsinspector" "${PODS_ROOT}/Headers/Public/ReactCommon" "${PODS_ROOT}/Headers/Public/UMBarCodeScannerInterface" "${PODS_ROOT}/Headers/Public/UMCameraInterface" "${PODS_ROOT}/Headers/Public/UMConstantsInterface" "${PODS_ROOT}/Headers/Public/UMCore" "${PODS_ROOT}/Headers/Public/UMFileSystemInterface" "${PODS_ROOT}/Headers/Public/UMFontInterface" "${PODS_ROOT}/Headers/Public/UMImageLoaderInterface" "${PODS_ROOT}/Headers/Public/UMPermissionsInterface" "${PODS_ROOT}/Headers/Public/UMReactNativeAdapter" "${PODS_ROOT}/Headers/Public/UMSensorsInterface" "${PODS_ROOT}/Headers/Public/Yoga" "${PODS_ROOT}/Headers/Public/ZXingObjC" "${PODS_ROOT}/Headers/Public/glog" "${PODS_ROOT}/Headers/Public/react-native-safe-area-context" "$(PODS_ROOT)/Headers/Private/React-Core" +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Amplitude-iOS" "${PODS_ROOT}/Headers/Public/Analytics" "${PODS_ROOT}/Headers/Public/AppAuth" "${PODS_ROOT}/Headers/Public/DoubleConversion" "${PODS_ROOT}/Headers/Public/EXAV" "${PODS_ROOT}/Headers/Public/EXAmplitude" "${PODS_ROOT}/Headers/Public/EXAppAuth" "${PODS_ROOT}/Headers/Public/EXAppLoaderProvider" "${PODS_ROOT}/Headers/Public/EXApplication" "${PODS_ROOT}/Headers/Public/EXBarCodeScanner" "${PODS_ROOT}/Headers/Public/EXBattery" "${PODS_ROOT}/Headers/Public/EXBluetooth" "${PODS_ROOT}/Headers/Public/EXBlur" "${PODS_ROOT}/Headers/Public/EXBrightness" "${PODS_ROOT}/Headers/Public/EXCalendar" "${PODS_ROOT}/Headers/Public/EXCellular" "${PODS_ROOT}/Headers/Public/EXConstants" "${PODS_ROOT}/Headers/Public/EXContacts" "${PODS_ROOT}/Headers/Public/EXCrypto" "${PODS_ROOT}/Headers/Public/EXDevice" "${PODS_ROOT}/Headers/Public/EXDocumentPicker" "${PODS_ROOT}/Headers/Public/EXErrorRecovery" "${PODS_ROOT}/Headers/Public/EXFileSystem" "${PODS_ROOT}/Headers/Public/EXFont" "${PODS_ROOT}/Headers/Public/EXGL" "${PODS_ROOT}/Headers/Public/EXGL_CPP" "${PODS_ROOT}/Headers/Public/EXGoogleSignIn" "${PODS_ROOT}/Headers/Public/EXHaptics" "${PODS_ROOT}/Headers/Public/EXImageManipulator" "${PODS_ROOT}/Headers/Public/EXImagePicker" "${PODS_ROOT}/Headers/Public/EXKeepAwake" "${PODS_ROOT}/Headers/Public/EXLinearGradient" "${PODS_ROOT}/Headers/Public/EXLocalAuthentication" "${PODS_ROOT}/Headers/Public/EXLocalization" "${PODS_ROOT}/Headers/Public/EXMailComposer" "${PODS_ROOT}/Headers/Public/EXMediaLibrary" "${PODS_ROOT}/Headers/Public/EXNetwork" "${PODS_ROOT}/Headers/Public/EXNotifications" "${PODS_ROOT}/Headers/Public/EXPermissions" "${PODS_ROOT}/Headers/Public/EXPrint" "${PODS_ROOT}/Headers/Public/EXRandom" "${PODS_ROOT}/Headers/Public/EXSMS" "${PODS_ROOT}/Headers/Public/EXSQLite" "${PODS_ROOT}/Headers/Public/EXSecureStore" "${PODS_ROOT}/Headers/Public/EXSegment" "${PODS_ROOT}/Headers/Public/EXSensors" "${PODS_ROOT}/Headers/Public/EXSharing" "${PODS_ROOT}/Headers/Public/EXSpeech" "${PODS_ROOT}/Headers/Public/EXStoreReview" "${PODS_ROOT}/Headers/Public/EXUpdates" "${PODS_ROOT}/Headers/Public/EXWebBrowser" "${PODS_ROOT}/Headers/Public/FBLazyVector" "${PODS_ROOT}/Headers/Public/FBReactNativeSpec" "${PODS_ROOT}/Headers/Public/GTMAppAuth" "${PODS_ROOT}/Headers/Public/GTMSessionFetcher" "${PODS_ROOT}/Headers/Public/RCTRequired" "${PODS_ROOT}/Headers/Public/RCTTypeSafety" "${PODS_ROOT}/Headers/Public/RNGestureHandler" "${PODS_ROOT}/Headers/Public/RNReanimated" "${PODS_ROOT}/Headers/Public/React-Core" "${PODS_ROOT}/Headers/Public/React-RCTBlob" "${PODS_ROOT}/Headers/Public/React-RCTText" "${PODS_ROOT}/Headers/Public/React-cxxreact" "${PODS_ROOT}/Headers/Public/React-jsi" "${PODS_ROOT}/Headers/Public/React-jsiexecutor" "${PODS_ROOT}/Headers/Public/React-jsinspector" "${PODS_ROOT}/Headers/Public/ReactCommon" "${PODS_ROOT}/Headers/Public/UMBarCodeScannerInterface" "${PODS_ROOT}/Headers/Public/UMCameraInterface" "${PODS_ROOT}/Headers/Public/UMConstantsInterface" "${PODS_ROOT}/Headers/Public/UMCore" "${PODS_ROOT}/Headers/Public/UMFileSystemInterface" "${PODS_ROOT}/Headers/Public/UMFontInterface" "${PODS_ROOT}/Headers/Public/UMImageLoaderInterface" "${PODS_ROOT}/Headers/Public/UMPermissionsInterface" "${PODS_ROOT}/Headers/Public/UMReactNativeAdapter" "${PODS_ROOT}/Headers/Public/UMSensorsInterface" "${PODS_ROOT}/Headers/Public/Yoga" "${PODS_ROOT}/Headers/Public/ZXingObjC" "${PODS_ROOT}/Headers/Public/glog" "${PODS_ROOT}/Headers/Public/react-native-safe-area-context" "$(PODS_ROOT)/Headers/Private/React-Core" OTHER_LDFLAGS = $(inherited) -ObjC -l"sqlite3.0" -l"stdc++" -framework "AVFoundation" -framework "CoreGraphics" -framework "CoreMedia" -framework "CoreTelephony" -framework "CoreText" -framework "CoreVideo" -framework "Foundation" -framework "ImageIO" -framework "JavaScriptCore" -framework "LocalAuthentication" -framework "QuartzCore" -framework "SafariServices" -framework "Security" -framework "StoreKit" -framework "SystemConfiguration" -framework "UIKit" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) diff --git a/apps/bare-expo/ios/Pods/Target Support Files/Pods-BareExpoTests/Pods-BareExpoTests.release.xcconfig b/apps/bare-expo/ios/Pods/Target Support Files/Pods-BareExpoTests/Pods-BareExpoTests.release.xcconfig index 72fa95c67ecc7..1f48d1cd49dde 100644 --- a/apps/bare-expo/ios/Pods/Target Support Files/Pods-BareExpoTests/Pods-BareExpoTests.release.xcconfig +++ b/apps/bare-expo/ios/Pods/Target Support Files/Pods-BareExpoTests/Pods-BareExpoTests.release.xcconfig @@ -1,6 +1,6 @@ FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/GoogleSignIn/Frameworks" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 ZXINGOBJC_USE_SUBSPECS ZXINGOBJC_USE_SUBSPECS ZXINGOBJC_ONED ZXINGOBJC_USE_SUBSPECS ZXINGOBJC_PDF417 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Amplitude-iOS" "${PODS_ROOT}/Headers/Public/Analytics" "${PODS_ROOT}/Headers/Public/AppAuth" "${PODS_ROOT}/Headers/Public/DoubleConversion" "${PODS_ROOT}/Headers/Public/EXAV" "${PODS_ROOT}/Headers/Public/EXAmplitude" "${PODS_ROOT}/Headers/Public/EXAppAuth" "${PODS_ROOT}/Headers/Public/EXAppLoaderProvider" "${PODS_ROOT}/Headers/Public/EXApplication" "${PODS_ROOT}/Headers/Public/EXBarCodeScanner" "${PODS_ROOT}/Headers/Public/EXBattery" "${PODS_ROOT}/Headers/Public/EXBluetooth" "${PODS_ROOT}/Headers/Public/EXBlur" "${PODS_ROOT}/Headers/Public/EXBrightness" "${PODS_ROOT}/Headers/Public/EXCalendar" "${PODS_ROOT}/Headers/Public/EXCellular" "${PODS_ROOT}/Headers/Public/EXConstants" "${PODS_ROOT}/Headers/Public/EXContacts" "${PODS_ROOT}/Headers/Public/EXCrypto" "${PODS_ROOT}/Headers/Public/EXDevice" "${PODS_ROOT}/Headers/Public/EXDocumentPicker" "${PODS_ROOT}/Headers/Public/EXErrorRecovery" "${PODS_ROOT}/Headers/Public/EXFileSystem" "${PODS_ROOT}/Headers/Public/EXFont" "${PODS_ROOT}/Headers/Public/EXGL" "${PODS_ROOT}/Headers/Public/EXGL_CPP" "${PODS_ROOT}/Headers/Public/EXGoogleSignIn" "${PODS_ROOT}/Headers/Public/EXHaptics" "${PODS_ROOT}/Headers/Public/EXImageManipulator" "${PODS_ROOT}/Headers/Public/EXImagePicker" "${PODS_ROOT}/Headers/Public/EXKeepAwake" "${PODS_ROOT}/Headers/Public/EXLinearGradient" "${PODS_ROOT}/Headers/Public/EXLocalAuthentication" "${PODS_ROOT}/Headers/Public/EXLocalization" "${PODS_ROOT}/Headers/Public/EXMailComposer" "${PODS_ROOT}/Headers/Public/EXMediaLibrary" "${PODS_ROOT}/Headers/Public/EXNetwork" "${PODS_ROOT}/Headers/Public/EXPermissions" "${PODS_ROOT}/Headers/Public/EXPrint" "${PODS_ROOT}/Headers/Public/EXRandom" "${PODS_ROOT}/Headers/Public/EXSMS" "${PODS_ROOT}/Headers/Public/EXSQLite" "${PODS_ROOT}/Headers/Public/EXSecureStore" "${PODS_ROOT}/Headers/Public/EXSegment" "${PODS_ROOT}/Headers/Public/EXSensors" "${PODS_ROOT}/Headers/Public/EXSharing" "${PODS_ROOT}/Headers/Public/EXSpeech" "${PODS_ROOT}/Headers/Public/EXStoreReview" "${PODS_ROOT}/Headers/Public/EXUpdates" "${PODS_ROOT}/Headers/Public/EXWebBrowser" "${PODS_ROOT}/Headers/Public/FBLazyVector" "${PODS_ROOT}/Headers/Public/FBReactNativeSpec" "${PODS_ROOT}/Headers/Public/GTMAppAuth" "${PODS_ROOT}/Headers/Public/GTMSessionFetcher" "${PODS_ROOT}/Headers/Public/RCTRequired" "${PODS_ROOT}/Headers/Public/RCTTypeSafety" "${PODS_ROOT}/Headers/Public/RNGestureHandler" "${PODS_ROOT}/Headers/Public/RNReanimated" "${PODS_ROOT}/Headers/Public/React-Core" "${PODS_ROOT}/Headers/Public/React-RCTBlob" "${PODS_ROOT}/Headers/Public/React-RCTText" "${PODS_ROOT}/Headers/Public/React-cxxreact" "${PODS_ROOT}/Headers/Public/React-jsi" "${PODS_ROOT}/Headers/Public/React-jsiexecutor" "${PODS_ROOT}/Headers/Public/React-jsinspector" "${PODS_ROOT}/Headers/Public/ReactCommon" "${PODS_ROOT}/Headers/Public/UMBarCodeScannerInterface" "${PODS_ROOT}/Headers/Public/UMCameraInterface" "${PODS_ROOT}/Headers/Public/UMConstantsInterface" "${PODS_ROOT}/Headers/Public/UMCore" "${PODS_ROOT}/Headers/Public/UMFileSystemInterface" "${PODS_ROOT}/Headers/Public/UMFontInterface" "${PODS_ROOT}/Headers/Public/UMImageLoaderInterface" "${PODS_ROOT}/Headers/Public/UMPermissionsInterface" "${PODS_ROOT}/Headers/Public/UMReactNativeAdapter" "${PODS_ROOT}/Headers/Public/UMSensorsInterface" "${PODS_ROOT}/Headers/Public/Yoga" "${PODS_ROOT}/Headers/Public/ZXingObjC" "${PODS_ROOT}/Headers/Public/glog" "${PODS_ROOT}/Headers/Public/react-native-safe-area-context" "$(PODS_ROOT)/Headers/Private/React-Core" +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Amplitude-iOS" "${PODS_ROOT}/Headers/Public/Analytics" "${PODS_ROOT}/Headers/Public/AppAuth" "${PODS_ROOT}/Headers/Public/DoubleConversion" "${PODS_ROOT}/Headers/Public/EXAV" "${PODS_ROOT}/Headers/Public/EXAmplitude" "${PODS_ROOT}/Headers/Public/EXAppAuth" "${PODS_ROOT}/Headers/Public/EXAppLoaderProvider" "${PODS_ROOT}/Headers/Public/EXApplication" "${PODS_ROOT}/Headers/Public/EXBarCodeScanner" "${PODS_ROOT}/Headers/Public/EXBattery" "${PODS_ROOT}/Headers/Public/EXBluetooth" "${PODS_ROOT}/Headers/Public/EXBlur" "${PODS_ROOT}/Headers/Public/EXBrightness" "${PODS_ROOT}/Headers/Public/EXCalendar" "${PODS_ROOT}/Headers/Public/EXCellular" "${PODS_ROOT}/Headers/Public/EXConstants" "${PODS_ROOT}/Headers/Public/EXContacts" "${PODS_ROOT}/Headers/Public/EXCrypto" "${PODS_ROOT}/Headers/Public/EXDevice" "${PODS_ROOT}/Headers/Public/EXDocumentPicker" "${PODS_ROOT}/Headers/Public/EXErrorRecovery" "${PODS_ROOT}/Headers/Public/EXFileSystem" "${PODS_ROOT}/Headers/Public/EXFont" "${PODS_ROOT}/Headers/Public/EXGL" "${PODS_ROOT}/Headers/Public/EXGL_CPP" "${PODS_ROOT}/Headers/Public/EXGoogleSignIn" "${PODS_ROOT}/Headers/Public/EXHaptics" "${PODS_ROOT}/Headers/Public/EXImageManipulator" "${PODS_ROOT}/Headers/Public/EXImagePicker" "${PODS_ROOT}/Headers/Public/EXKeepAwake" "${PODS_ROOT}/Headers/Public/EXLinearGradient" "${PODS_ROOT}/Headers/Public/EXLocalAuthentication" "${PODS_ROOT}/Headers/Public/EXLocalization" "${PODS_ROOT}/Headers/Public/EXMailComposer" "${PODS_ROOT}/Headers/Public/EXMediaLibrary" "${PODS_ROOT}/Headers/Public/EXNetwork" "${PODS_ROOT}/Headers/Public/EXNotifications" "${PODS_ROOT}/Headers/Public/EXPermissions" "${PODS_ROOT}/Headers/Public/EXPrint" "${PODS_ROOT}/Headers/Public/EXRandom" "${PODS_ROOT}/Headers/Public/EXSMS" "${PODS_ROOT}/Headers/Public/EXSQLite" "${PODS_ROOT}/Headers/Public/EXSecureStore" "${PODS_ROOT}/Headers/Public/EXSegment" "${PODS_ROOT}/Headers/Public/EXSensors" "${PODS_ROOT}/Headers/Public/EXSharing" "${PODS_ROOT}/Headers/Public/EXSpeech" "${PODS_ROOT}/Headers/Public/EXStoreReview" "${PODS_ROOT}/Headers/Public/EXUpdates" "${PODS_ROOT}/Headers/Public/EXWebBrowser" "${PODS_ROOT}/Headers/Public/FBLazyVector" "${PODS_ROOT}/Headers/Public/FBReactNativeSpec" "${PODS_ROOT}/Headers/Public/GTMAppAuth" "${PODS_ROOT}/Headers/Public/GTMSessionFetcher" "${PODS_ROOT}/Headers/Public/RCTRequired" "${PODS_ROOT}/Headers/Public/RCTTypeSafety" "${PODS_ROOT}/Headers/Public/RNGestureHandler" "${PODS_ROOT}/Headers/Public/RNReanimated" "${PODS_ROOT}/Headers/Public/React-Core" "${PODS_ROOT}/Headers/Public/React-RCTBlob" "${PODS_ROOT}/Headers/Public/React-RCTText" "${PODS_ROOT}/Headers/Public/React-cxxreact" "${PODS_ROOT}/Headers/Public/React-jsi" "${PODS_ROOT}/Headers/Public/React-jsiexecutor" "${PODS_ROOT}/Headers/Public/React-jsinspector" "${PODS_ROOT}/Headers/Public/ReactCommon" "${PODS_ROOT}/Headers/Public/UMBarCodeScannerInterface" "${PODS_ROOT}/Headers/Public/UMCameraInterface" "${PODS_ROOT}/Headers/Public/UMConstantsInterface" "${PODS_ROOT}/Headers/Public/UMCore" "${PODS_ROOT}/Headers/Public/UMFileSystemInterface" "${PODS_ROOT}/Headers/Public/UMFontInterface" "${PODS_ROOT}/Headers/Public/UMImageLoaderInterface" "${PODS_ROOT}/Headers/Public/UMPermissionsInterface" "${PODS_ROOT}/Headers/Public/UMReactNativeAdapter" "${PODS_ROOT}/Headers/Public/UMSensorsInterface" "${PODS_ROOT}/Headers/Public/Yoga" "${PODS_ROOT}/Headers/Public/ZXingObjC" "${PODS_ROOT}/Headers/Public/glog" "${PODS_ROOT}/Headers/Public/react-native-safe-area-context" "$(PODS_ROOT)/Headers/Private/React-Core" OTHER_LDFLAGS = $(inherited) -ObjC -l"sqlite3.0" -l"stdc++" -framework "AVFoundation" -framework "CoreGraphics" -framework "CoreMedia" -framework "CoreTelephony" -framework "CoreText" -framework "CoreVideo" -framework "Foundation" -framework "ImageIO" -framework "JavaScriptCore" -framework "LocalAuthentication" -framework "QuartzCore" -framework "SafariServices" -framework "Security" -framework "StoreKit" -framework "SystemConfiguration" -framework "UIKit" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) diff --git a/apps/bare-expo/package.json b/apps/bare-expo/package.json index 0f86c4418d1d6..fc46916e4f1da 100644 --- a/apps/bare-expo/package.json +++ b/apps/bare-expo/package.json @@ -84,6 +84,7 @@ "@babel/runtime": "^7.5.5", "@react-navigation/web": "2.0.0-alpha.0", "expo": "~36.0.0", + "expo-notifications": "~1.0.0", "expo-yarn-workspaces": "^1.2.1", "react": "16.9.0", "react-dom": "16.9.0", diff --git a/apps/test-suite/TestUtils.js b/apps/test-suite/TestUtils.js index f2908f4c28713..d0fed84b1963c 100644 --- a/apps/test-suite/TestUtils.js +++ b/apps/test-suite/TestUtils.js @@ -64,7 +64,8 @@ export function getTestModules() { require('./tests/Localization'), require('./tests/SecureStore'), require('./tests/SMS'), - require('./tests/StoreReview') + require('./tests/StoreReview'), + require('./tests/NewNotifications') ); return modules; } @@ -73,7 +74,8 @@ export function getTestModules() { modules.push( require('./tests/Contacts'), // require('./tests/SVG'), - require('./tests/Localization') + require('./tests/Localization'), + optionalRequire(() => require('./tests/NewNotifications')) ); if (browserSupportsWebGL()) { @@ -102,7 +104,8 @@ export function getTestModules() { optionalRequire(() => require('./tests/Payments')), optionalRequire(() => require('./tests/AdMobInterstitial')), optionalRequire(() => require('./tests/AdMobRewarded')), - optionalRequire(() => require('./tests/FBBannerAd')) + optionalRequire(() => require('./tests/FBBannerAd')), + optionalRequire(() => require('./tests/NewNotifications')) ); if (!isDeviceFarm()) { diff --git a/apps/test-suite/package.json b/apps/test-suite/package.json index 867387170c4b4..62955a098fc94 100644 --- a/apps/test-suite/package.json +++ b/apps/test-suite/package.json @@ -36,6 +36,7 @@ "expo-location": "~8.0.0", "expo-media-library": "~8.0.0", "expo-network": "~2.0.0", + "expo-notifications": "~1.0.0", "expo-permissions": "~8.0.0", "expo-random": "~8.0.0", "expo-secure-store": "~8.0.0", @@ -66,4 +67,4 @@ "not ie <= 11", "not op_mini all" ] -} \ No newline at end of file +} diff --git a/apps/test-suite/tests/NewNotifications.js b/apps/test-suite/tests/NewNotifications.js new file mode 100644 index 0000000000000..0c4353b3a9abb --- /dev/null +++ b/apps/test-suite/tests/NewNotifications.js @@ -0,0 +1,58 @@ +'use strict'; + +import { Platform } from '@unimodules/core'; +import * as Notifications from 'expo-notifications'; + +import * as TestUtils from '../TestUtils'; +import { waitFor } from './helpers'; + +export const name = 'expo-notifications'; + +export async function test(t) { + const shouldSkipTestsRequiringPermissions = await TestUtils.shouldSkipTestsRequiringPermissionsAsync(); + const describeWithPermissions = shouldSkipTestsRequiringPermissions ? t.xdescribe : t.describe; + + describeWithPermissions('expo-notifications', () => { + t.describe('getDevicePushTokenAsync', () => { + let subscription = null; + let tokenFromEvent = null; + let tokenFromMethodCall = null; + + t.beforeAll(() => { + subscription = Notifications.addTokenListener(newEvent => { + tokenFromEvent = newEvent; + }); + }); + + t.afterAll(() => { + if (subscription) { + subscription.remove(); + subscription = null; + } + }); + + if (Platform.OS === 'android' || Platform.OS === 'ios') { + t.it('resolves with a string', async () => { + const devicePushToken = await Notifications.getDevicePushTokenAsync(); + t.expect(typeof devicePushToken.data).toBe('string'); + tokenFromMethodCall = devicePushToken; + }); + } + + if (Platform.OS === 'web') { + t.it('resolves with an object', async () => { + const devicePushToken = await Notifications.getDevicePushTokenAsync(); + t.expect(typeof devicePushToken.data).toBe('object'); + tokenFromMethodCall = devicePushToken; + }); + } + + t.it('emits an event with token (or not, if getDevicePushTokenAsync failed)', async () => { + // It would be better to do `if (!tokenFromMethodCall) { pending(); } else { ... }` + // but `t.pending()` still doesn't work. + await waitFor(500); + t.expect(tokenFromEvent).toEqual(tokenFromMethodCall); + }); + }); + }); +} diff --git a/ios/Podfile b/ios/Podfile index 6d3cad557a227..74a2782cb61a3 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -26,6 +26,7 @@ target 'Exponent' do 'expo-module-template', 'expo-bluetooth', 'expo-in-app-purchases', + 'expo-notifications', 'expo-payments-stripe', 'expo-updates', ], diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 8100a06dec459..4252ef976db37 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -3630,6 +3630,6 @@ SPEC CHECKSUMS: yogaABI35_0_0: ba82ada0c3a58619049128d51d6de437638fe1a1 ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb -PODFILE CHECKSUM: 37a9208bd80b8a86a3898fd1e0c3062bd08fe8f3 +PODFILE CHECKSUM: 3a66eabee75c5532809ccfc3eca4e6b72c440b0b COCOAPODS: 1.8.4 diff --git a/ios/Pods/Manifest.lock b/ios/Pods/Manifest.lock index 8100a06dec459..4252ef976db37 100644 --- a/ios/Pods/Manifest.lock +++ b/ios/Pods/Manifest.lock @@ -3630,6 +3630,6 @@ SPEC CHECKSUMS: yogaABI35_0_0: ba82ada0c3a58619049128d51d6de437638fe1a1 ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb -PODFILE CHECKSUM: 37a9208bd80b8a86a3898fd1e0c3062bd08fe8f3 +PODFILE CHECKSUM: 3a66eabee75c5532809ccfc3eca4e6b72c440b0b COCOAPODS: 1.8.4 diff --git a/packages/expo-notifications/.eslintrc.js b/packages/expo-notifications/.eslintrc.js new file mode 100644 index 0000000000000..2720197860feb --- /dev/null +++ b/packages/expo-notifications/.eslintrc.js @@ -0,0 +1,2 @@ +// @generated by expo-module-scripts +module.exports = require('expo-module-scripts/eslintrc.base.js'); diff --git a/packages/expo-notifications/.npmignore b/packages/expo-notifications/.npmignore new file mode 100644 index 0000000000000..35d6f21144a89 --- /dev/null +++ b/packages/expo-notifications/.npmignore @@ -0,0 +1,2 @@ +# @generated by expo-module-scripts +babel.config.js diff --git a/packages/expo-notifications/README.md b/packages/expo-notifications/README.md new file mode 100644 index 0000000000000..b93b80f76c64e --- /dev/null +++ b/packages/expo-notifications/README.md @@ -0,0 +1 @@ +# expo-notifications diff --git a/packages/expo-notifications/android/.gitignore b/packages/expo-notifications/android/.gitignore new file mode 100644 index 0000000000000..099ccc86a0da7 --- /dev/null +++ b/packages/expo-notifications/android/.gitignore @@ -0,0 +1,269 @@ + +# Created by https://www.gitignore.io/api/java,maven,gradle,android,intellij,androidstudio + +### Android ### +# Built application files +*.apk +*.ap_ + +# Files for the ART/Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ +out/ + +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log + +# Android Studio Navigation editor temp files +.navigation/ + +# Android Studio captures folder +captures/ + +# Intellij +*.iml +.idea/workspace.xml +.idea/tasks.xml +.idea/gradle.xml +.idea/dictionaries +.idea/libraries + +# External native build folder generated in Android Studio 2.2 and later +.externalNativeBuild + +# Freeline +freeline.py +freeline/ +freeline_project_description.json + +### Android Patch ### +gen-external-apklibs + +### AndroidStudio ### +# Covers files to be ignored for android development using Android Studio. + +# Built application files + +# Files for the ART/Dalvik VM + +# Java class files + +# Generated files + +# Gradle files +.gradle + +# Signing files +.signing/ + +# Local configuration file (sdk path, etc) + +# Proguard folder generated by Eclipse + +# Log Files + +# Android Studio +/*/build/ +/*/local.properties +/*/out +/*/*/build +/*/*/production +*.ipr +*~ +*.swp + +# Android Patch + +# External native build folder generated in Android Studio 2.2 and later + +# NDK +obj/ + +# IntelliJ IDEA +*.iws +/out/ + +# User-specific configurations +.idea/libraries/ +.idea/.name +.idea/compiler.xml +.idea/copyright/profiles_settings.xml +.idea/encodings.xml +.idea/misc.xml +.idea/modules.xml +.idea/scopes/scope_settings.xml +.idea/vcs.xml +.idea/jsLibraryMappings.xml +.idea/datasources.xml +.idea/dataSources.ids +.idea/sqlDataSources.xml +.idea/dynamic.xml +.idea/uiDesigner.xml + +# OS-specific files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# Legacy Eclipse project files +.classpath +.project +.cproject +.settings/ + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.war +*.ear + +# virtual machine crash logs (Reference: http://www.java.com/en/download/help/error_hotspot.xml) +hs_err_pid* + +## Plugin-specific files: + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Mongo Explorer plugin +.idea/mongoSettings.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +### AndroidStudio Patch ### + +!/gradle/wrapper/gradle-wrapper.jar + +### Intellij ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff: +.idea/**/workspace.xml +.idea/**/tasks.xml + +# Sensitive or high-churn files: +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.xml +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml + +# Gradle: +.idea/**/gradle.xml +.idea/**/libraries + +# CMake +cmake-build-debug/ + +# Mongo Explorer plugin: +.idea/**/mongoSettings.xml + +## File-based project format: + +## Plugin-specific files: + +# IntelliJ + +# mpeltonen/sbt-idea plugin + +# JIRA plugin + +# Cursive Clojure plugin +.idea/replstate.xml + +# Ruby plugin and RubyMine +/.rakeTasks + +# Crashlytics plugin (for Android Studio and IntelliJ) + +### Intellij Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +.idea/sonarlint + +### Java ### +# Compiled class file + +# Log file + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) + +# Package Files # +*.jar +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml + +### Maven ### +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties + +# Avoid ignoring Maven wrapper jar file (.jar files are usually ignored) +!/.mvn/wrapper/maven-wrapper.jar + +### Gradle ### +**/build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Cache of project +.gradletasknamecache + +# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 +# gradle/wrapper/gradle-wrapper.properties + + +# End of https://www.gitignore.io/api/java,maven,gradle,android,intellij,androidstudio diff --git a/packages/expo-notifications/android/build.gradle b/packages/expo-notifications/android/build.gradle new file mode 100644 index 0000000000000..a5616ceb75066 --- /dev/null +++ b/packages/expo-notifications/android/build.gradle @@ -0,0 +1,72 @@ +buildscript { + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.5.1' + } +} + +apply plugin: 'com.android.library' +apply plugin: 'maven' + +group = 'host.exp.exponent' +version = '1.0.0' + +def safeExtGet(prop, fallback) { + rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback +} + +// Upload android library to maven with javadoc and android sources +configurations { + deployerJars +} + +// Creating sources with comments +task androidSourcesJar(type: Jar) { + classifier = 'sources' + from android.sourceSets.main.java.srcDirs +} + +// Put the androidSources and javadoc to the artifacts +artifacts { + archives androidSourcesJar +} + +uploadArchives { + repositories { + mavenDeployer { + configuration = configurations.deployerJars + repository(url: mavenLocal().url) + } + } +} + +android { + compileSdkVersion safeExtGet("compileSdkVersion", 28) + + defaultConfig { + minSdkVersion safeExtGet("minSdkVersion", 21) + targetSdkVersion safeExtGet("targetSdkVersion", 28) + versionCode 1 + versionName '1.0.0' + } + lintOptions { + abortOnError false + } +} + +if (new File(rootProject.projectDir.parentFile, 'package.json').exists()) { + apply from: project(":unimodules-core").file("../unimodules-core.gradle") +} else { + throw new GradleException( + '\'unimodules-core.gradle\' was not found in the usual Flutter or React Native dependency locations. ' + + 'This package can only be used in such projects. Are you sure you\'ve installed the dependencies properly?') +} + +dependencies { + unimodule 'unimodules-core' + api 'com.google.firebase:firebase-messaging:20.1.0' +} diff --git a/packages/expo-notifications/android/src/main/AndroidManifest.xml b/packages/expo-notifications/android/src/main/AndroidManifest.xml new file mode 100644 index 0000000000000..f3c35c3ad930e --- /dev/null +++ b/packages/expo-notifications/android/src/main/AndroidManifest.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/packages/expo-notifications/android/src/main/java/expo/modules/notifications/NotificationsPackage.java b/packages/expo-notifications/android/src/main/java/expo/modules/notifications/NotificationsPackage.java new file mode 100644 index 0000000000000..585510d802c49 --- /dev/null +++ b/packages/expo-notifications/android/src/main/java/expo/modules/notifications/NotificationsPackage.java @@ -0,0 +1,25 @@ +package expo.modules.notifications; + +import android.content.Context; + +import org.unimodules.core.BasePackage; +import org.unimodules.core.ExportedModule; +import org.unimodules.core.interfaces.SingletonModule; + +import java.util.Collections; +import java.util.List; + +import expo.modules.notifications.tokens.PushTokenManager; +import expo.modules.notifications.tokens.PushTokenModule; + +public class NotificationsPackage extends BasePackage { + @Override + public List createExportedModules(Context context) { + return Collections.singletonList((ExportedModule) new PushTokenModule(context)); + } + + @Override + public List createSingletonModules(Context context) { + return Collections.singletonList((SingletonModule) new PushTokenManager()); + } +} diff --git a/packages/expo-notifications/android/src/main/java/expo/modules/notifications/tokens/FirebaseTokenListenerService.java b/packages/expo-notifications/android/src/main/java/expo/modules/notifications/tokens/FirebaseTokenListenerService.java new file mode 100644 index 0000000000000..c515330e7d9e5 --- /dev/null +++ b/packages/expo-notifications/android/src/main/java/expo/modules/notifications/tokens/FirebaseTokenListenerService.java @@ -0,0 +1,69 @@ +package expo.modules.notifications.tokens; + +import com.google.firebase.messaging.FirebaseMessagingService; + +import java.lang.ref.WeakReference; +import java.util.WeakHashMap; + +import androidx.annotation.NonNull; + +/** + * Subclass of FirebaseMessagingService responsible for dispatching new tokens. + */ +public class FirebaseTokenListenerService extends FirebaseMessagingService { + // Unfortunately we cannot save state between instances of a service other way + // than by static properties. Fortunately, using weak references we can + // be somehow sure instances of PushTokenListeners won't be leaked by this component. + + /** + * We store this value to be able to inform new listeners of last known token. + */ + private static String sLastToken = null; + + /** + * A weak map of listeners -> reference. Used to check quickly whether given listener + * is already registered and to iterate over when notifying of new token. + */ + private static WeakHashMap> sListenersReferences = new WeakHashMap<>(); + + /** + * Used only by {@link PushTokenManager} instances. If you look for a place to register + * your listener, use {@link PushTokenManager} singleton module. + *

+ * Purposefully the argument is expected to be a {@link PushTokenManager} and just a listener. + *

+ * This class doesn't hold strong references to listeners, so you need to own your listeners. + * + * @param listener A listener instance to be informed of new push device tokens. + */ + static void addListener(PushTokenManager listener) { + // Checks whether this listener has already been registered + if (!sListenersReferences.containsKey(listener)) { + WeakReference listenerReference = new WeakReference<>(listener); + sListenersReferences.put(listener, listenerReference); + // Since it's a new listener and we know of a last valid token, let's let them know. + if (sLastToken != null) { + listener.onNewToken(sLastToken); + } + } + } + + /** + * Called on new token, dispatches it to {@link FirebaseTokenListenerService#sListenersReferences}. + * + * @param token New device push token. + */ + @Override + public void onNewToken(@NonNull String token) { + super.onNewToken(token); + + for (WeakReference listenerReference : sListenersReferences.values()) { + PushTokenManager listener = listenerReference.get(); + if (listener != null) { + listener.onNewToken(token); + } + } + + sLastToken = token; + } +} diff --git a/packages/expo-notifications/android/src/main/java/expo/modules/notifications/tokens/PushTokenManager.java b/packages/expo-notifications/android/src/main/java/expo/modules/notifications/tokens/PushTokenManager.java new file mode 100644 index 0000000000000..00e2257d5c072 --- /dev/null +++ b/packages/expo-notifications/android/src/main/java/expo/modules/notifications/tokens/PushTokenManager.java @@ -0,0 +1,86 @@ +package expo.modules.notifications.tokens; + +import org.unimodules.core.interfaces.SingletonModule; + +import java.lang.ref.WeakReference; +import java.util.Collection; +import java.util.HashSet; +import java.util.WeakHashMap; + +import expo.modules.notifications.tokens.interfaces.PushTokenListener; + +public class PushTokenManager implements SingletonModule, expo.modules.notifications.tokens.interfaces.PushTokenManager { + private static final String SINGLETON_NAME = "PushTokenManager"; + + /** + * We store this value to be able to inform new listeners of last known token. + */ + private String mLastToken; + + /** + * A weak map of listeners -> reference. Used to check quickly whether given listener + * is already registered and to iterate over on new token. + */ + private WeakHashMap> mListenerReferenceMap; + + public PushTokenManager() { + mListenerReferenceMap = new WeakHashMap<>(); + + // Registers this singleton instance in static FirebaseTokenListenerService listeners collection. + // Since it doesn't hold strong reference to the object this should be safe. + FirebaseTokenListenerService.addListener(this); + } + + @Override + public String getName() { + return SINGLETON_NAME; + } + + /** + * Registers a {@link PushTokenListener} by adding a {@link WeakReference} to + * the {@link PushTokenManager#mListenerReferenceMap} map. + * + * @param listener Listener to be notified of new device push tokens. + */ + @Override + public void addListener(PushTokenListener listener) { + // Check if the listener is already registered + if (!mListenerReferenceMap.containsKey(listener)) { + WeakReference listenerReference = new WeakReference<>(listener); + mListenerReferenceMap.put(listener, listenerReference); + // Since it's a new listener and we know of a last valid value, let's let them know. + if (mLastToken != null) { + listener.onNewToken(mLastToken); + } + } + } + + /** + * Unregisters a {@link PushTokenListener} by removing the {@link WeakReference} to the listener + * from the {@link PushTokenManager#mListenerReferenceMap} map. + * + * @param listener Listener previously registered with {@link PushTokenManager#addListener(PushTokenListener)}. + */ + @Override + public void removeListener(PushTokenListener listener) { + mListenerReferenceMap.remove(listener); + } + + /** + * Used by {@link FirebaseTokenListenerService} to notify of new tokens. + * Calls {@link PushTokenListener#onNewToken(String)} on all values + * of {@link PushTokenManager#mListenerReferenceMap}. + * + * @param token New device push token. + */ + void onNewToken(String token) { + for (WeakReference listenerReference : mListenerReferenceMap.values()) { + PushTokenListener listener = listenerReference.get(); + if (listener != null) { + listener.onNewToken(token); + } + } + + mLastToken = token; + } +} diff --git a/packages/expo-notifications/android/src/main/java/expo/modules/notifications/tokens/PushTokenModule.java b/packages/expo-notifications/android/src/main/java/expo/modules/notifications/tokens/PushTokenModule.java new file mode 100644 index 0000000000000..10d39d5b5ac6a --- /dev/null +++ b/packages/expo-notifications/android/src/main/java/expo/modules/notifications/tokens/PushTokenModule.java @@ -0,0 +1,99 @@ +package expo.modules.notifications.tokens; + +import android.content.Context; +import android.os.Bundle; + +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.Task; +import com.google.firebase.iid.FirebaseInstanceId; +import com.google.firebase.iid.InstanceIdResult; + +import org.unimodules.core.ExportedModule; +import org.unimodules.core.ModuleRegistry; +import org.unimodules.core.Promise; +import org.unimodules.core.interfaces.ExpoMethod; +import org.unimodules.core.interfaces.services.EventEmitter; + +import androidx.annotation.NonNull; +import expo.modules.notifications.tokens.interfaces.PushTokenListener; +import expo.modules.notifications.tokens.interfaces.PushTokenManager; + +public class PushTokenModule extends ExportedModule implements PushTokenListener { + private final static String EXPORTED_NAME = "ExpoPushTokenManager"; + + private final static String NEW_TOKEN_EVENT_NAME = "onDevicePushToken"; + private final static String NEW_TOKEN_EVENT_TOKEN_KEY = "devicePushToken"; + + private final static String REGISTRATION_FAIL_CODE = "E_REGISTRATION_FAILED"; + + private PushTokenManager mPushTokenManager; + private EventEmitter mEventEmitter; + + public PushTokenModule(Context context) { + super(context); + } + + @Override + public String getName() { + return EXPORTED_NAME; + } + + + @Override + public void onCreate(ModuleRegistry moduleRegistry) { + // Register the module as a listener in PushTokenManager singleton module. + // Deregistration happens in onDestroy callback. + mPushTokenManager = moduleRegistry.getSingletonModule("PushTokenManager", PushTokenManager.class); + mPushTokenManager.addListener(this); + + mEventEmitter = moduleRegistry.getModule(EventEmitter.class); + } + + @Override + public void onDestroy() { + mPushTokenManager.removeListener(this); + } + + /** + * Fetches Firebase push token and resolves the promise. + * + * @param promise Promise to be resolved with the token. + */ + @ExpoMethod + public void getDevicePushTokenAsync(final Promise promise) { + FirebaseInstanceId.getInstance().getInstanceId() + .addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if (!task.isSuccessful() || task.getResult() == null) { + if (task.getException() == null) { + promise.reject(REGISTRATION_FAIL_CODE, "Fetching the token failed."); + } else { + promise.reject(REGISTRATION_FAIL_CODE, "Fetching the token failed: " + task.getException().getMessage(), task.getException()); + } + return; + } + + String token = task.getResult().getToken(); + + promise.resolve(token); + onNewToken(token); + } + }); + } + + /** + * Callback called when {@link PushTokenManager} gets notified of a new token. + * Emits a {@link PushTokenModule#NEW_TOKEN_EVENT_NAME} event. + * + * @param token New push token. + */ + @Override + public void onNewToken(String token) { + if (mEventEmitter != null) { + Bundle eventBody = new Bundle(); + eventBody.putString(NEW_TOKEN_EVENT_TOKEN_KEY, token); + mEventEmitter.emit(NEW_TOKEN_EVENT_NAME, eventBody); + } + } +} diff --git a/packages/expo-notifications/android/src/main/java/expo/modules/notifications/tokens/interfaces/PushTokenListener.java b/packages/expo-notifications/android/src/main/java/expo/modules/notifications/tokens/interfaces/PushTokenListener.java new file mode 100644 index 0000000000000..6fadc2fb3afdf --- /dev/null +++ b/packages/expo-notifications/android/src/main/java/expo/modules/notifications/tokens/interfaces/PushTokenListener.java @@ -0,0 +1,14 @@ +package expo.modules.notifications.tokens.interfaces; + +/** + * Interface used to register in {@link PushTokenManager} + * and be notified of new device push tokens. + */ +public interface PushTokenListener { + /** + * Callback called when new push token is generated. + * + * @param token New push token + */ + void onNewToken(String token); +} diff --git a/packages/expo-notifications/android/src/main/java/expo/modules/notifications/tokens/interfaces/PushTokenManager.java b/packages/expo-notifications/android/src/main/java/expo/modules/notifications/tokens/interfaces/PushTokenManager.java new file mode 100644 index 0000000000000..c39987f0c5645 --- /dev/null +++ b/packages/expo-notifications/android/src/main/java/expo/modules/notifications/tokens/interfaces/PushTokenManager.java @@ -0,0 +1,22 @@ +package expo.modules.notifications.tokens.interfaces; + +/** + * Interface of a singleton module responsible + * for dispatching new push token information to listeners. + */ +public interface PushTokenManager { + /** + * Registers a {@link PushTokenListener}. + * + * @param listener Listener to be notified of new device push tokens. + */ + void addListener(PushTokenListener listener); + + /** + * Unregisters a {@link PushTokenListener}. + * + * @param listener Listener previously registered + * with {@link PushTokenManager#addListener(PushTokenListener)}. + */ + void removeListener(PushTokenListener listener); +} diff --git a/packages/expo-notifications/babel.config.js b/packages/expo-notifications/babel.config.js new file mode 100644 index 0000000000000..68c7d3192262e --- /dev/null +++ b/packages/expo-notifications/babel.config.js @@ -0,0 +1,2 @@ +// @generated by expo-module-scripts +module.exports = require('expo-module-scripts/babel.config.base'); diff --git a/packages/expo-notifications/build/PushTokenManager.d.ts b/packages/expo-notifications/build/PushTokenManager.d.ts new file mode 100644 index 0000000000000..a3fa8fa236837 --- /dev/null +++ b/packages/expo-notifications/build/PushTokenManager.d.ts @@ -0,0 +1,6 @@ +import { ProxyNativeModule } from '@unimodules/core'; +export interface PushTokenManagerModule extends ProxyNativeModule { + getDevicePushTokenAsync: () => Promise; +} +declare const _default: PushTokenManagerModule; +export default _default; diff --git a/packages/expo-notifications/build/PushTokenManager.js b/packages/expo-notifications/build/PushTokenManager.js new file mode 100644 index 0000000000000..0a483ffd90809 --- /dev/null +++ b/packages/expo-notifications/build/PushTokenManager.js @@ -0,0 +1,3 @@ +import { NativeModulesProxy } from '@unimodules/core'; +export default NativeModulesProxy.ExpoPushTokenManager; +//# sourceMappingURL=PushTokenManager.js.map \ No newline at end of file diff --git a/packages/expo-notifications/build/PushTokenManager.js.map b/packages/expo-notifications/build/PushTokenManager.js.map new file mode 100644 index 0000000000000..a6448c1db57c6 --- /dev/null +++ b/packages/expo-notifications/build/PushTokenManager.js.map @@ -0,0 +1 @@ +{"version":3,"file":"PushTokenManager.js","sourceRoot":"","sources":["../src/PushTokenManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAqB,MAAM,kBAAkB,CAAC;AAMzE,eAAgB,kBAAkB,CAAC,oBAAsD,CAAC","sourcesContent":["import { NativeModulesProxy, ProxyNativeModule } from '@unimodules/core';\n\nexport interface PushTokenManagerModule extends ProxyNativeModule {\n getDevicePushTokenAsync: () => Promise;\n}\n\nexport default (NativeModulesProxy.ExpoPushTokenManager as any) as PushTokenManagerModule;\n"]} \ No newline at end of file diff --git a/packages/expo-notifications/build/PushTokenManager.web.d.ts b/packages/expo-notifications/build/PushTokenManager.web.d.ts new file mode 100644 index 0000000000000..d87c48512f1ad --- /dev/null +++ b/packages/expo-notifications/build/PushTokenManager.web.d.ts @@ -0,0 +1,2 @@ +declare const _default: {}; +export default _default; diff --git a/packages/expo-notifications/build/PushTokenManager.web.js b/packages/expo-notifications/build/PushTokenManager.web.js new file mode 100644 index 0000000000000..7f3bc873d8e03 --- /dev/null +++ b/packages/expo-notifications/build/PushTokenManager.web.js @@ -0,0 +1,3 @@ +// mock +export default {}; +//# sourceMappingURL=PushTokenManager.web.js.map \ No newline at end of file diff --git a/packages/expo-notifications/build/PushTokenManager.web.js.map b/packages/expo-notifications/build/PushTokenManager.web.js.map new file mode 100644 index 0000000000000..96255ad408f63 --- /dev/null +++ b/packages/expo-notifications/build/PushTokenManager.web.js.map @@ -0,0 +1 @@ +{"version":3,"file":"PushTokenManager.web.js","sourceRoot":"","sources":["../src/PushTokenManager.web.ts"],"names":[],"mappings":"AAAA,OAAO;AACP,eAAe,EAAE,CAAC","sourcesContent":["// mock\nexport default {};\n"]} \ No newline at end of file diff --git a/packages/expo-notifications/build/TokenEmitter.d.ts b/packages/expo-notifications/build/TokenEmitter.d.ts new file mode 100644 index 0000000000000..cf71b2a43cecf --- /dev/null +++ b/packages/expo-notifications/build/TokenEmitter.d.ts @@ -0,0 +1,6 @@ +import { Subscription } from '@unimodules/core'; +import { DevicePushToken } from './getDevicePushTokenAsync'; +export declare type TokenListener = (token: DevicePushToken) => void; +export declare function addTokenListener(listener: TokenListener): Subscription; +export declare function removeTokenSubscription(subscription: Subscription): void; +export declare function removeAllTokenListeners(): void; diff --git a/packages/expo-notifications/build/TokenEmitter.js b/packages/expo-notifications/build/TokenEmitter.js new file mode 100644 index 0000000000000..6765d45a7967e --- /dev/null +++ b/packages/expo-notifications/build/TokenEmitter.js @@ -0,0 +1,18 @@ +import { EventEmitter, Platform } from '@unimodules/core'; +import PushTokenManager from './PushTokenManager'; +// Web uses SyntheticEventEmitter +const tokenEmitter = new EventEmitter(PushTokenManager); +const newTokenEventName = 'onDevicePushToken'; +export function addTokenListener(listener) { + const wrappingListener = ({ devicePushToken }) => + // @ts-ignore: TS can't decide what Platform.OS is. + listener({ data: devicePushToken, type: Platform.OS }); + return tokenEmitter.addListener(newTokenEventName, wrappingListener); +} +export function removeTokenSubscription(subscription) { + tokenEmitter.removeSubscription(subscription); +} +export function removeAllTokenListeners() { + tokenEmitter.removeAllListeners(newTokenEventName); +} +//# sourceMappingURL=TokenEmitter.js.map \ No newline at end of file diff --git a/packages/expo-notifications/build/TokenEmitter.js.map b/packages/expo-notifications/build/TokenEmitter.js.map new file mode 100644 index 0000000000000..8b812c8579290 --- /dev/null +++ b/packages/expo-notifications/build/TokenEmitter.js.map @@ -0,0 +1 @@ +{"version":3,"file":"TokenEmitter.js","sourceRoot":"","sources":["../src/TokenEmitter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAgB,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAExE,OAAO,gBAAgB,MAAM,oBAAoB,CAAC;AAIlD,iCAAiC;AACjC,MAAM,YAAY,GAAG,IAAI,YAAY,CAAC,gBAAgB,CAAC,CAAC;AACxD,MAAM,iBAAiB,GAAG,mBAAmB,CAAC;AAE9C,MAAM,UAAU,gBAAgB,CAAC,QAAuB;IACtD,MAAM,gBAAgB,GAAG,CAAC,EAAE,eAAe,EAAE,EAAE,EAAE;IAC/C,mDAAmD;IACnD,QAAQ,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC;IACzD,OAAO,YAAY,CAAC,WAAW,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,YAA0B;IAChE,YAAY,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,uBAAuB;IACrC,YAAY,CAAC,kBAAkB,CAAC,iBAAiB,CAAC,CAAC;AACrD,CAAC","sourcesContent":["import { EventEmitter, Subscription, Platform } from '@unimodules/core';\nimport { DevicePushToken } from './getDevicePushTokenAsync';\nimport PushTokenManager from './PushTokenManager';\n\nexport type TokenListener = (token: DevicePushToken) => void;\n\n// Web uses SyntheticEventEmitter\nconst tokenEmitter = new EventEmitter(PushTokenManager);\nconst newTokenEventName = 'onDevicePushToken';\n\nexport function addTokenListener(listener: TokenListener): Subscription {\n const wrappingListener = ({ devicePushToken }) =>\n // @ts-ignore: TS can't decide what Platform.OS is.\n listener({ data: devicePushToken, type: Platform.OS });\n return tokenEmitter.addListener(newTokenEventName, wrappingListener);\n}\n\nexport function removeTokenSubscription(subscription: Subscription) {\n tokenEmitter.removeSubscription(subscription);\n}\n\nexport function removeAllTokenListeners() {\n tokenEmitter.removeAllListeners(newTokenEventName);\n}\n"]} \ No newline at end of file diff --git a/packages/expo-notifications/build/getDevicePushTokenAsync.d.ts b/packages/expo-notifications/build/getDevicePushTokenAsync.d.ts new file mode 100644 index 0000000000000..2b3ee4a87bc57 --- /dev/null +++ b/packages/expo-notifications/build/getDevicePushTokenAsync.d.ts @@ -0,0 +1,23 @@ +import { Platform } from '@unimodules/core'; +export interface NativeDevicePushToken { + type: 'ios' | 'android'; + data: string; +} +export interface WebDevicePushToken { + type: 'web'; + data: { + endpoint: string; + keys: { + p256dh: string; + auth: string; + }; + }; +} +declare type ExplicitlySupportedDevicePushToken = NativeDevicePushToken | WebDevicePushToken; +declare type ImplicitlySupportedDevicePushToken = { + type: Exclude; + data: any; +}; +export declare type DevicePushToken = ExplicitlySupportedDevicePushToken | ImplicitlySupportedDevicePushToken; +export default function getDevicePushTokenAsync(): Promise; +export {}; diff --git a/packages/expo-notifications/build/getDevicePushTokenAsync.js b/packages/expo-notifications/build/getDevicePushTokenAsync.js new file mode 100644 index 0000000000000..49256a69e41b4 --- /dev/null +++ b/packages/expo-notifications/build/getDevicePushTokenAsync.js @@ -0,0 +1,11 @@ +import { UnavailabilityError, Platform } from '@unimodules/core'; +import PushTokenManager from './PushTokenManager'; +export default async function getDevicePushTokenAsync() { + if (!PushTokenManager.getDevicePushTokenAsync) { + throw new UnavailabilityError('ExpoNotifications', 'getDevicePushTokenAsync'); + } + const devicePushToken = await PushTokenManager.getDevicePushTokenAsync(); + // @ts-ignore: TS thinks Platform.OS could be anything and can't decide what type is it + return { type: Platform.OS, data: devicePushToken }; +} +//# sourceMappingURL=getDevicePushTokenAsync.js.map \ No newline at end of file diff --git a/packages/expo-notifications/build/getDevicePushTokenAsync.js.map b/packages/expo-notifications/build/getDevicePushTokenAsync.js.map new file mode 100644 index 0000000000000..516e35708d176 --- /dev/null +++ b/packages/expo-notifications/build/getDevicePushTokenAsync.js.map @@ -0,0 +1 @@ +{"version":3,"file":"getDevicePushTokenAsync.js","sourceRoot":"","sources":["../src/getDevicePushTokenAsync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEjE,OAAO,gBAAgB,MAAM,oBAAoB,CAAC;AA6BlD,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,uBAAuB;IACnD,IAAI,CAAC,gBAAgB,CAAC,uBAAuB,EAAE;QAC7C,MAAM,IAAI,mBAAmB,CAAC,mBAAmB,EAAE,yBAAyB,CAAC,CAAC;KAC/E;IAED,MAAM,eAAe,GAAG,MAAM,gBAAgB,CAAC,uBAAuB,EAAE,CAAC;IAEzE,uFAAuF;IACvF,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC;AACtD,CAAC","sourcesContent":["import { UnavailabilityError, Platform } from '@unimodules/core';\n\nimport PushTokenManager from './PushTokenManager';\n\nexport interface NativeDevicePushToken {\n type: 'ios' | 'android';\n data: string;\n}\n\nexport interface WebDevicePushToken {\n type: 'web';\n data: {\n endpoint: string;\n keys: {\n p256dh: string;\n auth: string;\n };\n };\n}\n\ntype ExplicitlySupportedDevicePushToken = NativeDevicePushToken | WebDevicePushToken;\n\ntype ImplicitlySupportedDevicePushToken = {\n type: Exclude;\n data: any;\n};\n\nexport type DevicePushToken =\n | ExplicitlySupportedDevicePushToken\n | ImplicitlySupportedDevicePushToken;\n\nexport default async function getDevicePushTokenAsync(): Promise {\n if (!PushTokenManager.getDevicePushTokenAsync) {\n throw new UnavailabilityError('ExpoNotifications', 'getDevicePushTokenAsync');\n }\n\n const devicePushToken = await PushTokenManager.getDevicePushTokenAsync();\n\n // @ts-ignore: TS thinks Platform.OS could be anything and can't decide what type is it\n return { type: Platform.OS, data: devicePushToken };\n}\n"]} \ No newline at end of file diff --git a/packages/expo-notifications/build/getDevicePushTokenAsync.web.d.ts b/packages/expo-notifications/build/getDevicePushTokenAsync.web.d.ts new file mode 100644 index 0000000000000..c6cac11a1a5e5 --- /dev/null +++ b/packages/expo-notifications/build/getDevicePushTokenAsync.web.d.ts @@ -0,0 +1,2 @@ +import { DevicePushToken } from './getDevicePushTokenAsync'; +export default function getDevicePushTokenAsync(): Promise; diff --git a/packages/expo-notifications/build/getDevicePushTokenAsync.web.js b/packages/expo-notifications/build/getDevicePushTokenAsync.web.js new file mode 100644 index 0000000000000..d2fb49ac698d0 --- /dev/null +++ b/packages/expo-notifications/build/getDevicePushTokenAsync.web.js @@ -0,0 +1,79 @@ +import { CodedError, Platform, SyntheticPlatformEmitter } from '@unimodules/core'; +import Constants from 'expo-constants'; +export default async function getDevicePushTokenAsync() { + const data = await _subscribeUserToPushAsync(); + SyntheticPlatformEmitter.emit('onDevicePushToken', { devicePushToken: data }); + return { type: Platform.OS, data }; +} +function guardPermission() { + if (!('Notification' in window)) { + throw new Error('The Notification API is not available on this device.'); + } + if (!navigator.serviceWorker) { + throw new Error('Notifications cannot be used because the service worker API is not supported on this device. This might also happen because your web page does not support HTTPS.'); + } + if (Notification.permission !== 'granted') { + throw new Error('Cannot use Notifications without permissions. Please request permissions with `expo-permissions`'); + } +} +async function _subscribeUserToPushAsync() { + if (!Constants.manifest.notification || !Constants.manifest.notification.vapidPublicKey) { + throw new CodedError('E_NOTIFICATIONS_PUSH_WEB_MISSING_CONFIG', 'You must provide `notification.vapidPublicKey` in `app.json` to use push notifications on web. Learn more: https://docs.expo.io/versions/latest/guides/using-vapid/.'); + } + if (!Constants.manifest.notification || !Constants.manifest.notification.serviceWorkerPath) { + throw new CodedError('E_NOTIFICATIONS_PUSH_WEB_MISSING_CONFIG', 'You must provide `notification.serviceWorkerPath` in `app.json` to use push notifications on web. Please provide path to the service worker that will handle notifications.'); + } + guardPermission(); + let registration = null; + try { + registration = await navigator.serviceWorker.register(Constants.manifest.notification.serviceWorkerPath); + } + catch (error) { + throw new Error(`Notifications might not be working because the service worker (${Constants.manifest.notification.serviceWorkerPath}) couldn't be registered: ${error}`); + } + await navigator.serviceWorker.ready; + if (!registration.active) { + throw new Error('Notifications might not be working because the service worker API is not active.'); + } + const subscribeOptions = { + userVisibleOnly: true, + applicationServerKey: _urlBase64ToUint8Array(Constants.manifest.notification.vapidPublicKey), + }; + let pushSubscription = null; + try { + pushSubscription = await registration.pushManager.subscribe(subscribeOptions); + } + catch (error) { + throw new CodedError('E_NOTIFICATIONS_PUSH_WEB_TOKEN_REGISTRATION_FAILED', 'The device was unable to register for remote notifications with the browser endpoint. (' + + error + + ')'); + } + const pushSubscriptionJson = pushSubscription.toJSON(); + const subscriptionObject = { + endpoint: pushSubscriptionJson.endpoint, + keys: { + p256dh: pushSubscriptionJson.keys.p256dh, + auth: pushSubscriptionJson.keys.auth, + }, + }; + // Store notification icon string in service worker. + // This message is received by `/expo-service-worker.js`. + // We wrap it with `fromExpoWebClient` to make sure other message + // will not override content such as `notificationIcon`. + // https://stackoverflow.com/a/35729334/2603230 + let notificationIcon = (Constants.manifest.notification || {}).icon; + await registration.active.postMessage(JSON.stringify({ fromExpoWebClient: { notificationIcon } })); + return subscriptionObject; +} +// https://github.com/web-push-libs/web-push#using-vapid-key-for-applicationserverkey +function _urlBase64ToUint8Array(base64String) { + const padding = '='.repeat((4 - (base64String.length % 4)) % 4); + const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/'); + const rawData = window.atob(base64); + const outputArray = new Uint8Array(rawData.length); + for (let i = 0; i < rawData.length; ++i) { + outputArray[i] = rawData.charCodeAt(i); + } + return outputArray; +} +//# sourceMappingURL=getDevicePushTokenAsync.web.js.map \ No newline at end of file diff --git a/packages/expo-notifications/build/getDevicePushTokenAsync.web.js.map b/packages/expo-notifications/build/getDevicePushTokenAsync.web.js.map new file mode 100644 index 0000000000000..f9f7ca0e7ef53 --- /dev/null +++ b/packages/expo-notifications/build/getDevicePushTokenAsync.web.js.map @@ -0,0 +1 @@ +{"version":3,"file":"getDevicePushTokenAsync.web.js","sourceRoot":"","sources":["../src/getDevicePushTokenAsync.web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAClF,OAAO,SAAS,MAAM,gBAAgB,CAAC;AAIvC,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,uBAAuB;IACnD,MAAM,IAAI,GAAG,MAAM,yBAAyB,EAAE,CAAC;IAC/C,wBAAwB,CAAC,IAAI,CAAC,mBAAmB,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9E,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC;AACrC,CAAC;AAED,SAAS,eAAe;IACtB,IAAI,CAAC,CAAC,cAAc,IAAI,MAAM,CAAC,EAAE;QAC/B,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;KAC1E;IACD,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE;QAC5B,MAAM,IAAI,KAAK,CACb,mKAAmK,CACpK,CAAC;KACH;IACD,IAAI,YAAY,CAAC,UAAU,KAAK,SAAS,EAAE;QACzC,MAAM,IAAI,KAAK,CACb,kGAAkG,CACnG,CAAC;KACH;AACH,CAAC;AAED,KAAK,UAAU,yBAAyB;IACtC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,YAAY,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,cAAc,EAAE;QACvF,MAAM,IAAI,UAAU,CAClB,yCAAyC,EACzC,sKAAsK,CACvK,CAAC;KACH;IACD,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,YAAY,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,iBAAiB,EAAE;QAC1F,MAAM,IAAI,UAAU,CAClB,yCAAyC,EACzC,6KAA6K,CAC9K,CAAC;KACH;IACD,eAAe,EAAE,CAAC;IAElB,IAAI,YAAY,GAAqC,IAAI,CAAC;IAC1D,IAAI;QACF,YAAY,GAAG,MAAM,SAAS,CAAC,aAAa,CAAC,QAAQ,CACnD,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,iBAAiB,CAClD,CAAC;KACH;IAAC,OAAO,KAAK,EAAE;QACd,MAAM,IAAI,KAAK,CACb,kEAAkE,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,iBAAiB,6BAA6B,KAAK,EAAE,CACxJ,CAAC;KACH;IACD,MAAM,SAAS,CAAC,aAAa,CAAC,KAAK,CAAC;IAEpC,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE;QACxB,MAAM,IAAI,KAAK,CACb,kFAAkF,CACnF,CAAC;KACH;IAED,MAAM,gBAAgB,GAAG;QACvB,eAAe,EAAE,IAAI;QACrB,oBAAoB,EAAE,sBAAsB,CAAC,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC;KAC7F,CAAC;IACF,IAAI,gBAAgB,GAA4B,IAAI,CAAC;IACrD,IAAI;QACF,gBAAgB,GAAG,MAAM,YAAY,CAAC,WAAW,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;KAC/E;IAAC,OAAO,KAAK,EAAE;QACd,MAAM,IAAI,UAAU,CAClB,oDAAoD,EACpD,yFAAyF;YACvF,KAAK;YACL,GAAG,CACN,CAAC;KACH;IACD,MAAM,oBAAoB,GAAG,gBAAgB,CAAC,MAAM,EAAE,CAAC;IAEvD,MAAM,kBAAkB,GAAG;QACzB,QAAQ,EAAE,oBAAoB,CAAC,QAAQ;QACvC,IAAI,EAAE;YACJ,MAAM,EAAE,oBAAoB,CAAC,IAAK,CAAC,MAAM;YACzC,IAAI,EAAE,oBAAoB,CAAC,IAAK,CAAC,IAAI;SACtC;KACF,CAAC;IAEF,oDAAoD;IACpD,yDAAyD;IACzD,iEAAiE;IACjE,wDAAwD;IACxD,+CAA+C;IAC/C,IAAI,gBAAgB,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;IACpE,MAAM,YAAY,CAAC,MAAM,CAAC,WAAW,CACnC,IAAI,CAAC,SAAS,CAAC,EAAE,iBAAiB,EAAE,EAAE,gBAAgB,EAAE,EAAE,CAAC,CAC5D,CAAC;IAEF,OAAO,kBAAkB,CAAC;AAC5B,CAAC;AAED,qFAAqF;AACrF,SAAS,sBAAsB,CAAC,YAAoB;IAClD,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAChE,MAAM,MAAM,GAAG,CAAC,YAAY,GAAG,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAE9E,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,WAAW,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAEnD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE;QACvC,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;KACxC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC","sourcesContent":["import { CodedError, Platform, SyntheticPlatformEmitter } from '@unimodules/core';\nimport Constants from 'expo-constants';\n\nimport { DevicePushToken } from './getDevicePushTokenAsync';\n\nexport default async function getDevicePushTokenAsync(): Promise {\n const data = await _subscribeUserToPushAsync();\n SyntheticPlatformEmitter.emit('onDevicePushToken', { devicePushToken: data });\n return { type: Platform.OS, data };\n}\n\nfunction guardPermission() {\n if (!('Notification' in window)) {\n throw new Error('The Notification API is not available on this device.');\n }\n if (!navigator.serviceWorker) {\n throw new Error(\n 'Notifications cannot be used because the service worker API is not supported on this device. This might also happen because your web page does not support HTTPS.'\n );\n }\n if (Notification.permission !== 'granted') {\n throw new Error(\n 'Cannot use Notifications without permissions. Please request permissions with `expo-permissions`'\n );\n }\n}\n\nasync function _subscribeUserToPushAsync(): Promise {\n if (!Constants.manifest.notification || !Constants.manifest.notification.vapidPublicKey) {\n throw new CodedError(\n 'E_NOTIFICATIONS_PUSH_WEB_MISSING_CONFIG',\n 'You must provide `notification.vapidPublicKey` in `app.json` to use push notifications on web. Learn more: https://docs.expo.io/versions/latest/guides/using-vapid/.'\n );\n }\n if (!Constants.manifest.notification || !Constants.manifest.notification.serviceWorkerPath) {\n throw new CodedError(\n 'E_NOTIFICATIONS_PUSH_WEB_MISSING_CONFIG',\n 'You must provide `notification.serviceWorkerPath` in `app.json` to use push notifications on web. Please provide path to the service worker that will handle notifications.'\n );\n }\n guardPermission();\n\n let registration: ServiceWorkerRegistration | null = null;\n try {\n registration = await navigator.serviceWorker.register(\n Constants.manifest.notification.serviceWorkerPath\n );\n } catch (error) {\n throw new Error(\n `Notifications might not be working because the service worker (${Constants.manifest.notification.serviceWorkerPath}) couldn't be registered: ${error}`\n );\n }\n await navigator.serviceWorker.ready;\n\n if (!registration.active) {\n throw new Error(\n 'Notifications might not be working because the service worker API is not active.'\n );\n }\n\n const subscribeOptions = {\n userVisibleOnly: true,\n applicationServerKey: _urlBase64ToUint8Array(Constants.manifest.notification.vapidPublicKey),\n };\n let pushSubscription: PushSubscription | null = null;\n try {\n pushSubscription = await registration.pushManager.subscribe(subscribeOptions);\n } catch (error) {\n throw new CodedError(\n 'E_NOTIFICATIONS_PUSH_WEB_TOKEN_REGISTRATION_FAILED',\n 'The device was unable to register for remote notifications with the browser endpoint. (' +\n error +\n ')'\n );\n }\n const pushSubscriptionJson = pushSubscription.toJSON();\n\n const subscriptionObject = {\n endpoint: pushSubscriptionJson.endpoint,\n keys: {\n p256dh: pushSubscriptionJson.keys!.p256dh,\n auth: pushSubscriptionJson.keys!.auth,\n },\n };\n\n // Store notification icon string in service worker.\n // This message is received by `/expo-service-worker.js`.\n // We wrap it with `fromExpoWebClient` to make sure other message\n // will not override content such as `notificationIcon`.\n // https://stackoverflow.com/a/35729334/2603230\n let notificationIcon = (Constants.manifest.notification || {}).icon;\n await registration.active.postMessage(\n JSON.stringify({ fromExpoWebClient: { notificationIcon } })\n );\n\n return subscriptionObject;\n}\n\n// https://github.com/web-push-libs/web-push#using-vapid-key-for-applicationserverkey\nfunction _urlBase64ToUint8Array(base64String: string): Uint8Array {\n const padding = '='.repeat((4 - (base64String.length % 4)) % 4);\n const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');\n\n const rawData = window.atob(base64);\n const outputArray = new Uint8Array(rawData.length);\n\n for (let i = 0; i < rawData.length; ++i) {\n outputArray[i] = rawData.charCodeAt(i);\n }\n return outputArray;\n}\n"]} \ No newline at end of file diff --git a/packages/expo-notifications/build/index.d.ts b/packages/expo-notifications/build/index.d.ts new file mode 100644 index 0000000000000..444e33c073245 --- /dev/null +++ b/packages/expo-notifications/build/index.d.ts @@ -0,0 +1,2 @@ +export { default as getDevicePushTokenAsync } from './getDevicePushTokenAsync'; +export * from './TokenEmitter'; diff --git a/packages/expo-notifications/build/index.js b/packages/expo-notifications/build/index.js new file mode 100644 index 0000000000000..6e1fb39ed66ee --- /dev/null +++ b/packages/expo-notifications/build/index.js @@ -0,0 +1,3 @@ +export { default as getDevicePushTokenAsync } from './getDevicePushTokenAsync'; +export * from './TokenEmitter'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/packages/expo-notifications/build/index.js.map b/packages/expo-notifications/build/index.js.map new file mode 100644 index 0000000000000..a5530676d5593 --- /dev/null +++ b/packages/expo-notifications/build/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAC/E,cAAc,gBAAgB,CAAC","sourcesContent":["export { default as getDevicePushTokenAsync } from './getDevicePushTokenAsync';\nexport * from './TokenEmitter';\n"]} \ No newline at end of file diff --git a/packages/expo-notifications/ios/EXNotifications.podspec b/packages/expo-notifications/ios/EXNotifications.podspec new file mode 100644 index 0000000000000..ac429d2fc94e4 --- /dev/null +++ b/packages/expo-notifications/ios/EXNotifications.podspec @@ -0,0 +1,20 @@ +require 'json' + +package = JSON.parse(File.read(File.join(__dir__, '..', 'package.json'))) + +Pod::Spec.new do |s| + s.name = 'EXNotifications' + s.version = package['version'] + s.summary = package['description'] + s.description = package['description'] + s.license = package['license'] + s.author = package['author'] + s.homepage = package['homepage'] + s.platform = :ios, '10.0' + s.source = { git: 'https://github.com/expo/expo.git' } + s.source_files = 'EXNotifications/**/*.{h,m}' + s.preserve_paths = 'EXNotifications/**/*.{h,m}' + s.requires_arc = true + + s.dependency 'UMCore' +end diff --git a/packages/expo-notifications/ios/EXNotifications/EXPushTokenListener.h b/packages/expo-notifications/ios/EXNotifications/EXPushTokenListener.h new file mode 100644 index 0000000000000..a5102aadc2191 --- /dev/null +++ b/packages/expo-notifications/ios/EXNotifications/EXPushTokenListener.h @@ -0,0 +1,14 @@ +// Copyright 2018-present 650 Industries. All rights reserved. + +#import + +NS_ASSUME_NONNULL_BEGIN + +@protocol EXPushTokenListener + +- (void)onDidRegisterWithDeviceToken:(NSData *)token; +- (void)onDidFailToRegisterWithError:(NSError *)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/expo-notifications/ios/EXNotifications/EXPushTokenManager.h b/packages/expo-notifications/ios/EXNotifications/EXPushTokenManager.h new file mode 100644 index 0000000000000..1e8c966d1f916 --- /dev/null +++ b/packages/expo-notifications/ios/EXNotifications/EXPushTokenManager.h @@ -0,0 +1,24 @@ +// Copyright 2018-present 650 Industries. All rights reserved. + +#import +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@protocol EXPushTokenManager + +- (void)addListener:(id)listener; +- (void)removeListener:(id)listener; + +@end + +@interface EXPushTokenManager : UMSingletonModule + +- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken; +- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/expo-notifications/ios/EXNotifications/EXPushTokenManager.m b/packages/expo-notifications/ios/EXNotifications/EXPushTokenManager.m new file mode 100644 index 0000000000000..a2c424a47dd9f --- /dev/null +++ b/packages/expo-notifications/ios/EXNotifications/EXPushTokenManager.m @@ -0,0 +1,63 @@ +// Copyright 2018-present 650 Industries. All rights reserved. + +#import +#import + +@interface EXPushTokenManager () + +@property (nonatomic, strong) NSPointerArray *listeners; + +@end + +@implementation EXPushTokenManager + +UM_REGISTER_SINGLETON_MODULE(PushTokenManager); + +- (instancetype)init +{ + if (self = [super init]) { + _listeners = [NSPointerArray weakObjectsPointerArray]; + } + return self; +} + +# pragma mark - UIApplicationDelegate + +- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken +{ + for (int i = 0; i < _listeners.count; i++) { + id pointer = [_listeners pointerAtIndex:i]; + [pointer onDidRegisterWithDeviceToken:deviceToken]; + } +} + +- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error +{ + for (int i = 0; i < _listeners.count; i++) { + id pointer = [_listeners pointerAtIndex:i]; + [pointer onDidFailToRegisterWithError:error]; + } +} + +# pragma mark - Listeners + +- (void)addListener:(id)listener +{ + [_listeners addPointer:(__bridge void * _Nullable)(listener)]; +} + +- (void)removeListener:(id)listener +{ + for (int i = 0; i < _listeners.count; i++) { + id pointer = [_listeners pointerAtIndex:i]; + if (pointer == (__bridge void * _Nullable)(listener) || !pointer) { + [_listeners removePointerAtIndex:i]; + i--; + } + } + // compact doesn't work, that's why we need the `|| !pointer` above + // http://www.openradar.me/15396578 + [_listeners compact]; +} + +@end diff --git a/packages/expo-notifications/ios/EXNotifications/EXPushTokenModule.h b/packages/expo-notifications/ios/EXNotifications/EXPushTokenModule.h new file mode 100644 index 0000000000000..5ddb5d21ae085 --- /dev/null +++ b/packages/expo-notifications/ios/EXNotifications/EXPushTokenModule.h @@ -0,0 +1,9 @@ +// Copyright 2018-present 650 Industries. All rights reserved. + +#import +#import +#import +#import + +@interface EXPushTokenModule : UMExportedModule +@end diff --git a/packages/expo-notifications/ios/EXNotifications/EXPushTokenModule.m b/packages/expo-notifications/ios/EXNotifications/EXPushTokenModule.m new file mode 100644 index 0000000000000..ef7ca013f8e7e --- /dev/null +++ b/packages/expo-notifications/ios/EXNotifications/EXPushTokenModule.m @@ -0,0 +1,147 @@ +// Copyright 2018-present 650 Industries. All rights reserved. + +#import +#import + +#import + +static const NSString *onDevicePushTokenEventName = @"onDevicePushToken"; + +@interface EXPushTokenModule () + +@property (nonatomic, weak) id pushTokenManager; + +@property (nonatomic, assign) BOOL isListening; +@property (nonatomic, assign) BOOL isBeingObserved; +@property (nonatomic, assign) BOOL isSettlingPromise; + +@property (nonatomic, weak) id eventEmitter; + +@property (nonatomic, strong) UMPromiseResolveBlock getDevicePushTokenResolver; +@property (nonatomic, strong) UMPromiseRejectBlock getDevicePushTokenRejecter; + +@end + +@implementation EXPushTokenModule + +UM_EXPORT_MODULE(ExpoPushTokenManager); + +# pragma mark - Exported methods + +UM_EXPORT_METHOD_AS(getDevicePushTokenAsync, + getDevicePushTokenResolving:(UMPromiseResolveBlock)resolve rejecting:(UMPromiseRejectBlock)reject) +{ + if (_getDevicePushTokenRejecter) { + reject(@"E_AWAIT_PROMISE", @"Another async call to this method is in progress. Await the first Promise.", nil); + return; + } + + _getDevicePushTokenResolver = resolve; + _getDevicePushTokenRejecter = reject; + [self setIsSettlingPromise:YES]; + + dispatch_async(dispatch_get_main_queue(), ^{ + [[UIApplication sharedApplication] registerForRemoteNotifications]; + }); +} + +# pragma mark - UMModuleRegistryConsumer + +- (void)setModuleRegistry:(UMModuleRegistry *)moduleRegistry +{ + _eventEmitter = [moduleRegistry getModuleImplementingProtocol:@protocol(UMEventEmitterService)]; + _pushTokenManager = [moduleRegistry getSingletonModuleForName:@"PushTokenManager"]; +} + +# pragma mark - UMEventEmitter + +- (NSArray *)supportedEvents +{ + return @[(NSString *)onDevicePushTokenEventName]; +} + +- (void)startObserving +{ + [self setIsBeingObserved:YES]; +} + +- (void)stopObserving +{ + [self setIsBeingObserved:NO]; +} + +- (BOOL)shouldListen +{ + return _isBeingObserved || _isSettlingPromise; +} + +- (void)updateListeningState +{ + if ([self shouldListen] && !_isListening) { + [_pushTokenManager addListener:self]; + _isListening = YES; + } else if (![self shouldListen] && _isListening) { + [_pushTokenManager removeListener:self]; + _isListening = NO; + } +} + +# pragma mark - EXPushTokenListener + +- (void)onDidRegisterWithDeviceToken:(NSData *)devicePushToken +{ + NSMutableString *stringToken = [NSMutableString string]; + const char *bytes = [devicePushToken bytes]; + for (int i = 0; i < [devicePushToken length]; i++) { + [stringToken appendFormat:@"%02.2hhx", bytes[i]]; + } + + if (_getDevicePushTokenResolver) { + _getDevicePushTokenResolver(stringToken); + [self onGetDevicePushTokenPromiseSettled]; + } + + if (_isBeingObserved) { + [_eventEmitter sendEventWithName:(NSString *)onDevicePushTokenEventName + body:@{ @"devicePushToken": stringToken }]; + } +} + +- (void)onDidFailToRegisterWithError:(NSError *)error +{ + if (_getDevicePushTokenRejecter) { + NSString *message = @"Notification registration failed: "; + + // A common error, localizedDescription may not be helpful. + if (error.code == 3000 && [NSCocoaErrorDomain isEqualToString:error.domain]) { + message = [message stringByAppendingString:@"\"Push Notifications\" capability hasn't been added to the app in current environment: "]; + } + + message = [message stringByAppendingFormat:@"%@", error.localizedDescription]; + _getDevicePushTokenRejecter(@"E_REGISTRATION_FAILED", message, error); + [self onGetDevicePushTokenPromiseSettled]; + } +} + +- (void)onGetDevicePushTokenPromiseSettled +{ + _getDevicePushTokenResolver = nil; + _getDevicePushTokenRejecter = nil; + [self setIsSettlingPromise:NO]; +} + +# pragma mark - Internal state + +- (void)setIsBeingObserved:(BOOL)isBeingObserved +{ + _isBeingObserved = isBeingObserved; + [self updateListeningState]; +} + +- (void)setIsSettlingPromise:(BOOL)isSettlingPromise +{ + _isSettlingPromise = isSettlingPromise; + [self updateListeningState]; +} + +@end diff --git a/packages/expo-notifications/package.json b/packages/expo-notifications/package.json new file mode 100644 index 0000000000000..b60d2eb09c53d --- /dev/null +++ b/packages/expo-notifications/package.json @@ -0,0 +1,38 @@ +{ + "name": "expo-notifications", + "version": "1.0.0", + "description": "Notifications module", + "main": "build/index.js", + "types": "build/index.d.ts", + "scripts": { + "build": "expo-module build", + "clean": "expo-module clean", + "lint": "expo-module lint", + "test": "expo-module test", + "prepare": "expo-module prepare", + "prepublishOnly": "expo-module prepublishOnly", + "expo-module": "expo-module" + }, + "keywords": [ + "react-native", + "expo", + "notifications", + "expo-notifications" + ], + "repository": { + "type": "git", + "url": "https://github.com/expo/expo.git", + "directory": "packages/expo-notifications" + }, + "bugs": { + "url": "https://github.com/expo/expo/issues" + }, + "author": "650 Industries, Inc.", + "license": "MIT", + "homepage": "https://github.com/expo/expo/tree/master/packages/expo-notifications", + "peerDependencies": { + "@unimodules/core": "~5.0.0", + "expo-constants": "~8.0.0" + }, + "gitHead": "ec7878b9ce54f2537721218ae0fe4017e4004806" +} diff --git a/packages/expo-notifications/src/PushTokenManager.ts b/packages/expo-notifications/src/PushTokenManager.ts new file mode 100644 index 0000000000000..4130bb9003796 --- /dev/null +++ b/packages/expo-notifications/src/PushTokenManager.ts @@ -0,0 +1,7 @@ +import { NativeModulesProxy, ProxyNativeModule } from '@unimodules/core'; + +export interface PushTokenManagerModule extends ProxyNativeModule { + getDevicePushTokenAsync: () => Promise; +} + +export default (NativeModulesProxy.ExpoPushTokenManager as any) as PushTokenManagerModule; diff --git a/packages/expo-notifications/src/PushTokenManager.web.ts b/packages/expo-notifications/src/PushTokenManager.web.ts new file mode 100644 index 0000000000000..82f90c737146b --- /dev/null +++ b/packages/expo-notifications/src/PushTokenManager.web.ts @@ -0,0 +1,2 @@ +// mock +export default {}; diff --git a/packages/expo-notifications/src/TokenEmitter.ts b/packages/expo-notifications/src/TokenEmitter.ts new file mode 100644 index 0000000000000..7a2aeb9a6f5fa --- /dev/null +++ b/packages/expo-notifications/src/TokenEmitter.ts @@ -0,0 +1,24 @@ +import { EventEmitter, Subscription, Platform } from '@unimodules/core'; +import { DevicePushToken } from './getDevicePushTokenAsync'; +import PushTokenManager from './PushTokenManager'; + +export type TokenListener = (token: DevicePushToken) => void; + +// Web uses SyntheticEventEmitter +const tokenEmitter = new EventEmitter(PushTokenManager); +const newTokenEventName = 'onDevicePushToken'; + +export function addTokenListener(listener: TokenListener): Subscription { + const wrappingListener = ({ devicePushToken }) => + // @ts-ignore: TS can't decide what Platform.OS is. + listener({ data: devicePushToken, type: Platform.OS }); + return tokenEmitter.addListener(newTokenEventName, wrappingListener); +} + +export function removeTokenSubscription(subscription: Subscription) { + tokenEmitter.removeSubscription(subscription); +} + +export function removeAllTokenListeners() { + tokenEmitter.removeAllListeners(newTokenEventName); +} diff --git a/packages/expo-notifications/src/getDevicePushTokenAsync.ts b/packages/expo-notifications/src/getDevicePushTokenAsync.ts new file mode 100644 index 0000000000000..6418c0a944ec7 --- /dev/null +++ b/packages/expo-notifications/src/getDevicePushTokenAsync.ts @@ -0,0 +1,41 @@ +import { UnavailabilityError, Platform } from '@unimodules/core'; + +import PushTokenManager from './PushTokenManager'; + +export interface NativeDevicePushToken { + type: 'ios' | 'android'; + data: string; +} + +export interface WebDevicePushToken { + type: 'web'; + data: { + endpoint: string; + keys: { + p256dh: string; + auth: string; + }; + }; +} + +type ExplicitlySupportedDevicePushToken = NativeDevicePushToken | WebDevicePushToken; + +type ImplicitlySupportedDevicePushToken = { + type: Exclude; + data: any; +}; + +export type DevicePushToken = + | ExplicitlySupportedDevicePushToken + | ImplicitlySupportedDevicePushToken; + +export default async function getDevicePushTokenAsync(): Promise { + if (!PushTokenManager.getDevicePushTokenAsync) { + throw new UnavailabilityError('ExpoNotifications', 'getDevicePushTokenAsync'); + } + + const devicePushToken = await PushTokenManager.getDevicePushTokenAsync(); + + // @ts-ignore: TS thinks Platform.OS could be anything and can't decide what type is it + return { type: Platform.OS, data: devicePushToken }; +} diff --git a/packages/expo-notifications/src/getDevicePushTokenAsync.web.ts b/packages/expo-notifications/src/getDevicePushTokenAsync.web.ts new file mode 100644 index 0000000000000..b5014531adf8b --- /dev/null +++ b/packages/expo-notifications/src/getDevicePushTokenAsync.web.ts @@ -0,0 +1,111 @@ +import { CodedError, Platform, SyntheticPlatformEmitter } from '@unimodules/core'; +import Constants from 'expo-constants'; + +import { DevicePushToken } from './getDevicePushTokenAsync'; + +export default async function getDevicePushTokenAsync(): Promise { + const data = await _subscribeUserToPushAsync(); + SyntheticPlatformEmitter.emit('onDevicePushToken', { devicePushToken: data }); + return { type: Platform.OS, data }; +} + +function guardPermission() { + if (!('Notification' in window)) { + throw new Error('The Notification API is not available on this device.'); + } + if (!navigator.serviceWorker) { + throw new Error( + 'Notifications cannot be used because the service worker API is not supported on this device. This might also happen because your web page does not support HTTPS.' + ); + } + if (Notification.permission !== 'granted') { + throw new Error( + 'Cannot use Notifications without permissions. Please request permissions with `expo-permissions`' + ); + } +} + +async function _subscribeUserToPushAsync(): Promise { + if (!Constants.manifest.notification || !Constants.manifest.notification.vapidPublicKey) { + throw new CodedError( + 'E_NOTIFICATIONS_PUSH_WEB_MISSING_CONFIG', + 'You must provide `notification.vapidPublicKey` in `app.json` to use push notifications on web. Learn more: https://docs.expo.io/versions/latest/guides/using-vapid/.' + ); + } + if (!Constants.manifest.notification || !Constants.manifest.notification.serviceWorkerPath) { + throw new CodedError( + 'E_NOTIFICATIONS_PUSH_WEB_MISSING_CONFIG', + 'You must provide `notification.serviceWorkerPath` in `app.json` to use push notifications on web. Please provide path to the service worker that will handle notifications.' + ); + } + guardPermission(); + + let registration: ServiceWorkerRegistration | null = null; + try { + registration = await navigator.serviceWorker.register( + Constants.manifest.notification.serviceWorkerPath + ); + } catch (error) { + throw new Error( + `Notifications might not be working because the service worker (${Constants.manifest.notification.serviceWorkerPath}) couldn't be registered: ${error}` + ); + } + await navigator.serviceWorker.ready; + + if (!registration.active) { + throw new Error( + 'Notifications might not be working because the service worker API is not active.' + ); + } + + const subscribeOptions = { + userVisibleOnly: true, + applicationServerKey: _urlBase64ToUint8Array(Constants.manifest.notification.vapidPublicKey), + }; + let pushSubscription: PushSubscription | null = null; + try { + pushSubscription = await registration.pushManager.subscribe(subscribeOptions); + } catch (error) { + throw new CodedError( + 'E_NOTIFICATIONS_PUSH_WEB_TOKEN_REGISTRATION_FAILED', + 'The device was unable to register for remote notifications with the browser endpoint. (' + + error + + ')' + ); + } + const pushSubscriptionJson = pushSubscription.toJSON(); + + const subscriptionObject = { + endpoint: pushSubscriptionJson.endpoint, + keys: { + p256dh: pushSubscriptionJson.keys!.p256dh, + auth: pushSubscriptionJson.keys!.auth, + }, + }; + + // Store notification icon string in service worker. + // This message is received by `/expo-service-worker.js`. + // We wrap it with `fromExpoWebClient` to make sure other message + // will not override content such as `notificationIcon`. + // https://stackoverflow.com/a/35729334/2603230 + let notificationIcon = (Constants.manifest.notification || {}).icon; + await registration.active.postMessage( + JSON.stringify({ fromExpoWebClient: { notificationIcon } }) + ); + + return subscriptionObject; +} + +// https://github.com/web-push-libs/web-push#using-vapid-key-for-applicationserverkey +function _urlBase64ToUint8Array(base64String: string): Uint8Array { + const padding = '='.repeat((4 - (base64String.length % 4)) % 4); + const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/'); + + const rawData = window.atob(base64); + const outputArray = new Uint8Array(rawData.length); + + for (let i = 0; i < rawData.length; ++i) { + outputArray[i] = rawData.charCodeAt(i); + } + return outputArray; +} diff --git a/packages/expo-notifications/src/index.ts b/packages/expo-notifications/src/index.ts new file mode 100644 index 0000000000000..444e33c073245 --- /dev/null +++ b/packages/expo-notifications/src/index.ts @@ -0,0 +1,2 @@ +export { default as getDevicePushTokenAsync } from './getDevicePushTokenAsync'; +export * from './TokenEmitter'; diff --git a/packages/expo-notifications/tsconfig.json b/packages/expo-notifications/tsconfig.json new file mode 100644 index 0000000000000..a24ec0ff2f600 --- /dev/null +++ b/packages/expo-notifications/tsconfig.json @@ -0,0 +1,9 @@ +// @generated by expo-module-scripts +{ + "extends": "expo-module-scripts/tsconfig.base", + "compilerOptions": { + "outDir": "./build" + }, + "include": ["./src"], + "exclude": ["**/__mocks__/*", "**/__tests__/*"] +} diff --git a/packages/expo-notifications/unimodule.json b/packages/expo-notifications/unimodule.json new file mode 100644 index 0000000000000..363fc92f99c13 --- /dev/null +++ b/packages/expo-notifications/unimodule.json @@ -0,0 +1,4 @@ +{ + "name": "expo-notifications", + "platforms": ["ios", "android"] +} From 360eba3b723d7d147b531f55628e0aa5d5060c39 Mon Sep 17 00:00:00 2001 From: Juwan Wheatley Date: Tue, 14 Jan 2020 10:38:53 -0800 Subject: [PATCH 014/103] [templates] make typescript templates strict by default (#6755) --- templates/expo-template-bare-typescript/tsconfig.json | 3 ++- templates/expo-template-blank-typescript/tsconfig.json | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/templates/expo-template-bare-typescript/tsconfig.json b/templates/expo-template-bare-typescript/tsconfig.json index 2ee1a98f42ca8..3c78a191dbc99 100644 --- a/templates/expo-template-bare-typescript/tsconfig.json +++ b/templates/expo-template-bare-typescript/tsconfig.json @@ -6,6 +6,7 @@ "moduleResolution": "node", "noEmit": true, "skipLibCheck": true, - "resolveJsonModule": true + "resolveJsonModule": true, + "strict": true } } diff --git a/templates/expo-template-blank-typescript/tsconfig.json b/templates/expo-template-blank-typescript/tsconfig.json index 2ee1a98f42ca8..3c78a191dbc99 100644 --- a/templates/expo-template-blank-typescript/tsconfig.json +++ b/templates/expo-template-blank-typescript/tsconfig.json @@ -6,6 +6,7 @@ "moduleResolution": "node", "noEmit": true, "skipLibCheck": true, - "resolveJsonModule": true + "resolveJsonModule": true, + "strict": true } } From e1ea07eeb296a638a8817b02831eecdb3de67961 Mon Sep 17 00:00:00 2001 From: Charlie Cruzan <35579283+cruzach@users.noreply.github.com> Date: Tue, 14 Jan 2020 16:14:01 -0500 Subject: [PATCH 015/103] [docs] improvements to push notification guide (#6766) --- .../unversioned/guides/push-notifications.md | 482 ++++++++---------- .../versions/unversioned/sdk/notifications.md | 16 +- .../pages/versions/unversioned/sdk/sharing.md | 2 +- .../v36.0.0/guides/push-notifications.md | 482 ++++++++---------- .../versions/v36.0.0/sdk/notifications.md | 16 +- docs/pages/versions/v36.0.0/sdk/sharing.md | 2 +- docs/static/images/saving-token.png | Bin 56194 -> 58287 bytes docs/static/images/sending-notification.png | Bin 133261 -> 129462 bytes 8 files changed, 430 insertions(+), 570 deletions(-) diff --git a/docs/pages/versions/unversioned/guides/push-notifications.md b/docs/pages/versions/unversioned/guides/push-notifications.md index 0883f0d46e0fe..ffc0d2fa8953b 100644 --- a/docs/pages/versions/unversioned/guides/push-notifications.md +++ b/docs/pages/versions/unversioned/guides/push-notifications.md @@ -2,19 +2,23 @@ title: Push Notifications --- -Push Notifications are an important feature to, as _"growth hackers"_ would say, retain and re-engage users and monetize on their attention, or something. From my point of view it's just super handy to know when a relevant event happens in an app so I can jump back into it and read more. Let's look at how to do this with Expo. Spoiler alert: it's almost too easy. +Push Notifications are an important feature, no matter what kind of app you're building. Not only is it nice to let users know about something that may interest them, be it a new album being released, a sale or other limited-time-only deal, or that one of their friends sent them a message, but push notifications are proven to help boost user interaction and create a better overall user experience. -> **Note:** -> -> iOS and Android simulators cannot receive push notifications. To test them out you will need to use a real-life device. Additionally, when calling Permissions.askAsync on the simulator, it will resolve immediately with "undetermined" as the status, regardless of whether you choose to allow or not. -> -> For Expo for Web, unless you're using localhost, your web page has to support HTTPS in order for push notifications to work. +Whether you just want to be able to let users know when a relevant event happens, or you're trying to optimize customer engagement and retention, Expo makes implementing push notifications almost too easy. All the hassle with native device information and communicating with APNS (Apple Push Notification Service) or FCM (Firebase Cloud Messaging) is taken care of behind the scenes, so that you can treat iOS and Android notifications the same, saving you time on the front-end, and back-end! + +There are three main steps to setting up push notifications: -There are three main steps to wiring up push notifications: sending a user's Expo Push Token to your server, calling Expo's Push API with the token when you want to send a notification, and responding to receiving and/or selecting the notification in your app (for example to jump to a particular screen that the notification refers to). This has all been put together for you to try out in [this example snack](https://snack.expo.io/@charliecruzan/pushnotifications34?platform=ios)! +- getting a user's Expo Push Token +- calling Expo's Push API with the token when you want to send a notification +- responding to receiving the notification in your app (maybe upon opening, you want to jump to a particular screen that the notification refers to) -## 1. Save the user's Expo Push Token on your server +> Reading the full guide is important, but to take a quick look at this in action, check out [this example snack](https://snack.expo.io/@charliecruzan/pushnotifications36?platform=ios)! -In order to send a push notification to somebody, we need to know about their device. Sure, we know our user's account information, but Apple, Google, and Expo do not understand what devices correspond to "Brent" in your proprietary user account system. Expo takes care of identifying your device with Apple and Google through the Expo push token, which is unique each time an app is installed on a device. All we need to do is send this token to your server so you can associate it with the user account and use it in the future for sending push notifications. +## Set Up + +### 1. Getting the user's Push Token + +In order to send a push notification, Expo needs to know which device to send it to. Expo takes care of identifying your device with Apple and Google through the Expo push token, which is uniquely generated each time an app is installed on a device. Once you have this token, save it in association with that user account on your server. This token is what you'll provide to Expo's push notification service. Halfway done with the setup! ![Diagram explaining saving tokens](/static/images/saving-token.png) @@ -25,26 +29,19 @@ import * as Permissions from 'expo-permissions'; const PUSH_ENDPOINT = 'https://your-server.com/users/push-token'; export default async function registerForPushNotificationsAsync() { - const { status: existingStatus } = await Permissions.getAsync( - Permissions.NOTIFICATIONS - ); - let finalStatus = existingStatus; - - // only ask if permissions have not already been determined, because + const { status } = await Permissions.askAsync(Permissions.NOTIFICATIONS); + // only asks if permissions have not already been determined, because // iOS won't necessarily prompt the user a second time. - if (existingStatus !== 'granted') { - // Android remote notification permissions are granted during the app - // install, so this will only ask on iOS - const { status } = await Permissions.askAsync(Permissions.NOTIFICATIONS); - finalStatus = status; - } + // On Android, permissions are granted on app installation, so + // `askAsync` will never prompt the user // Stop here if the user did not grant permissions - if (finalStatus !== 'granted') { + if (status !== 'granted') { + alert('No notification permissions!'); return; } - // Get the token that uniquely identifies this device + // Get the token that identifies this device let token = await Notifications.getExpoPushTokenAsync(); // POST the token to your backend server from where you can retrieve it to send push notifications. @@ -66,20 +63,22 @@ export default async function registerForPushNotificationsAsync() { } ``` -## 2. Call Expo's Push API with the user's token +### 2. Call Expo's Push API with the user's token to send the Notification + +> If you're just getting started and want to focus on the front-end for now, you can skip this step and just use [Expo's push notification tool](https://expo.io/notifications) to send notifications with the click of a button. -Push notifications have to come from somewhere, and that somewhere is your server, probably (you could write a command line tool to send them if you wanted, it's all the same). When you're ready to send a push notification, grab the Expo push token off of the user record and send it over to the Expo API using a plain old HTTPS POST request. We've taken care of wrapping that for you in a few languages: +Push notifications have to come from somewhere, and that somewhere is probably your server (you could write a command line tool to send them if you wanted, or send them straight from your app, it's all the same). When you're ready to send a push notification, take the Expo push token from your user record and send it to the Expo API using a plain old HTTPS POST request. We've taken care of wrapping that for you in a few languages: ![Diagram explaining sending a push from your server to device](/static/images/sending-notification.png) -- [expo-server-sdk-node](https://github.com/expo/expo-server-sdk-node) for Node.js. Maintained by the Expo team. -- [expo-server-sdk-python](https://github.com/expo/expo-server-sdk-python) for Python. Maintained by community developers. -- [expo-server-sdk-ruby](https://github.com/expo/expo-server-sdk-ruby) for Ruby. Maintained by community developers. -- [expo-server-sdk-rust](https://github.com/expo/expo-server-sdk-rust) for Rust. Maintained by community developers. -- [ExpoNotificationsBundle](https://github.com/solvecrew/ExpoNotificationsBundle) for Symfony. Maintained by SolveCrew. -- [exponent-server-sdk-php](https://github.com/Alymosul/exponent-server-sdk-php) for PHP. Maintained by community developers. -- [exponent-server-sdk-golang](https://github.com/oliveroneill/exponent-server-sdk-golang) for Golang. Maintained by community developers. -- [exponent-server-sdk-elixir](https://github.com/rdrop/exponent-server-sdk-elixir) for Elixir. Maintained by community developers. +- [expo-server-sdk-node](https://github.com/expo/expo-server-sdk-node) for Node.js. Maintained by the Expo team. +- [expo-server-sdk-python](https://github.com/expo/expo-server-sdk-python) for Python. Maintained by community developers. +- [expo-server-sdk-ruby](https://github.com/expo/expo-server-sdk-ruby) for Ruby. Maintained by community developers. +- [expo-server-sdk-rust](https://github.com/expo/expo-server-sdk-rust) for Rust. Maintained by community developers. +- [ExpoNotificationsBundle](https://github.com/solvecrew/ExpoNotificationsBundle) for Symfony. Maintained by SolveCrew. +- [exponent-server-sdk-php](https://github.com/Alymosul/exponent-server-sdk-php) for PHP. Maintained by community developers. +- [exponent-server-sdk-golang](https://github.com/oliveroneill/exponent-server-sdk-golang) for Golang. Maintained by community developers. +- [exponent-server-sdk-elixir](https://github.com/rdrop/exponent-server-sdk-elixir) for Elixir. Maintained by community developers. Check out the source if you would like to implement it in another language. @@ -87,25 +86,16 @@ Check out the source if you would like to implement it in another language. > > For Android, you'll also need to upload your Firebase Cloud Messaging server key to Expo so that Expo can send notifications to your app. **This step is necessary** unless you are not creating your own APK and using just the Expo client app from Google Play. Follow the guide on [Using FCM for Push Notifications](../../guides/using-fcm) to learn how to create a Firebase project, get your FCM server key, and upload the key to Expo. -The [Expo push notification tool](https://expo.io/notifications) is also useful for testing push notifications during development. It lets you easily send test notifications to your device. - -## 3. Handle receiving and/or selecting the notification - -For Android, this step is entirely optional -- if your notifications are purely informational and you have no desire to handle them when they are received or selected, you're already done. Notifications will appear in the system notification tray as you've come to expect, and tapping them will open/foreground the app. +### 3. Handle receiving the notification in your app -For iOS, if you do not set `notification.iosDisplayInForeground` (in your `app.json`) or `_displayInForeground` (in your push message) to `true`, you would be wise to handle push notifications that are received while the app is foregrounded, because otherwise the user will never see them. Notifications that arrive while the app is foregrounded on iOS do not show up in the system notification list. A common solution is to just show the notification manually. For example, if you get a message on Messenger for iOS, have the app foregrounded, but do not have that conversation open, you will see the notification slide down from the top of the screen with a custom notification UI. +You can now successfully send a notification to your app! If all you wanted was purely informational notifications, then you can stop here. But Expo provides the capabilities to do much more: maybe you want to update the UI based on the notification, or maybe navigate to a particular screen if a notification was selected. -Thankfully, handling push notifications is straightforward with Expo, all you need to do is add a listener using the `Notifications` API. +Like most things with Expo, handling received notifications is simple and straightforward across all platforms. All you need to do is add a listener using the [`Notifications` API](../../sdk/notifications). ```javascript import React from 'react'; -import { - Notifications, -} from 'expo'; -import { - Text, - View, -} from 'react-native'; +import { Notifications } from 'expo'; +import { Text, View } from 'react-native'; // This refers to the function defined earlier in this guide import registerForPushNotificationsAsync from './registerForPushNotificationsAsync'; @@ -126,13 +116,14 @@ export default class AppContainer extends React.Component { this._notificationSubscription = Notifications.addListener(this._handleNotification); } - _handleNotification = (notification) => { - this.setState({notification: notification}); + _handleNotification = notification => { + // do whatever you want to do with the notification + this.setState({ notification: notification }); }; render() { return ( - + Origin: {this.state.notification.origin} Data: {JSON.stringify(this.state.notification.data)} @@ -141,25 +132,30 @@ export default class AppContainer extends React.Component { } ``` -### Determining `origin` of the notification +> **Important Note**: On iOS, if you do not set `notification.iosDisplayInForeground` (in your `app.json`) or `_displayInForeground` (in your push message) to `true`, you would be wise to handle push notifications that are received while the app is foregrounded, otherwise the user will never see them. You can handle this specific case in your listener by checking if the `origin` of the notification is `received`. Notifications that arrive while the app is foregrounded on iOS do not show up in the system notification list. + +Event listeners added using `Notifications.addListener` will receive an object when a notification is received ([docs](../../sdk/notifications/#notification)). The `origin` of the object will vary based on the app's state at the time the notification was received and the user's subsequent action. The table below summarizes the different possibilities and what the `origin` will be in each case. + +| Push was received when... | `origin` will be... | +| -------------------------------------------------------------------- | :-----------------------------------: | +| App is open and foregrounded | `'received'` | +| App is open and backgrounded, then notification is not selected | no notification is passed to listener | +| App is open and backgrounded, then notification is selected | `'selected'` | +| App was not open, and then opened by selecting the push notification | `'selected'` | +| App was not open, and then opened by tapping the home screen icon | no notification is passed to listener | -Event listeners added using `Notifications.addListener` will receive an object when a notification is received ([docs](../../sdk/notifications/#eventsubscription)). The `origin` of the object will vary based on the app's state at the time the notification was received and the user's subsequent action. The table below summarizes the different possibilities and what the `origin` will be in each case. + -| Push was received when... | `origin` will be... | -| ------------------------------------------------|:-----------------:| -| App is open and foregrounded | `'received'` | -| App is open and backgrounded, then notification not selected | n/a, no notification is passed to listener | -| App is open and backgrounded, then notification is selected | `'selected'` | -| App was not open, and then opened by selecting the push notification | `'selected'` | -| App was not open, and then opened by tapping the home screen icon | n/a, no notification is passed to listener | +## Testing -## HTTP/2 API +iOS and Android simulators cannot receive push notifications, so you will need to test using a physical device. Additionally, when calling `Permissions.askAsync` on the simulator, it will resolve immediately with `undetermined` as the status, regardless of whether you choose to allow or not. -Although there are server-side SDKs in several languages to help you send push notifications, you may want to directly send requests to our HTTP/2 API. +The [Expo push notification tool](https://expo.io/notifications) is also useful for testing push notifications during development. It lets you easily send test notifications to your device, without having to use your CLI or write out a test server. -### Sending notifications +## Sending notifications from your server -Send a POST request to `https://exp.host/--/api/v2/push/send` with the following HTTP headers: +Although there are server-side SDKs in several languages to help you send push notifications, you may want to directly send requests to our HTTP/2 API (this API currently does not require any authentication). All you need to do is send a POST request to `https://exp.host/--/api/v2/push/send` with the following HTTP headers: ``` host: exp.host @@ -168,11 +164,7 @@ accept-encoding: gzip, deflate content-type: application/json ``` -The Expo server also optionally accepts gzip-compressed request bodies. This can greatly reduce the amount of upload bandwidth needed to send large numbers of notifications. The [Node SDK](https://github.com/expo/expo-server-sdk-node) automatically gzips requests for you. - -This API currently does not require any authentication. - -This is a "hello world" request using cURL (replace the placeholder push token with your own): +This is a "hello world" push notification using cURL that you can send using your CLI (replace the placeholder push token with your own): ```bash curl -H "Content-Type: application/json" -X POST "https://exp.host/--/api/v2/push/send" -d '{ @@ -182,52 +174,80 @@ curl -H "Content-Type: application/json" -X POST "https://exp.host/--/api/v2/pus }' ``` -The HTTP request body must be JSON. It may either be a single message object or an array of up to 100 messages. **We recommend using an array when you want to send multiple messages to efficiently minimize the number of requests you need to make to Expo servers.** This is an example request body that sends four messages: +The request body must be JSON. It may either be a single [message object](#message-request-format) (example above) or an array of up to 100 message objects, as long as they are all for the same project (show below). **We recommend using an array when you want to send multiple messages to efficiently minimize the number of requests you need to make to Expo servers.** Here's an example request body that sends four messages: ```json -[{ - "to": "ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]", - "sound": "default", - "body": "Hello world!" -}, { - "to": "ExponentPushToken[yyyyyyyyyyyyyyyyyyyyyy]", - "badge": 1, - "body": "You've got mail" -}, { - "to": [ - "ExponentPushToken[zzzzzzzzzzzzzzzzzzzzzz]", - "ExponentPushToken[aaaaaaaaaaaaaaaaaaaaaa]" - ], - "body": "Breaking news!" -}] +[ + { + "to": "ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]", + "sound": "default", + "body": "Hello world!" + }, + { + "to": "ExponentPushToken[yyyyyyyyyyyyyyyyyyyyyy]", + "badge": 1, + "body": "You've got mail" + }, + { + "to": [ + "ExponentPushToken[zzzzzzzzzzzzzzzzzzzzzz]", + "ExponentPushToken[aaaaaaaaaaaaaaaaaaaaaa]" + ], + "body": "Breaking news!" + } +] ``` -Upon success, the HTTP response will be a JSON object whose `data` field is an array of **push tickets**, each of which corresponds to the message at its respective index in the request. Continuing the above example, this is what a successful response body looks like: +The Expo server also optionally accepts gzip-compressed request bodies. This can greatly reduce the amount of upload bandwidth needed to send large numbers of notifications. The [Node Expo Server SDK](https://github.com/expo/expo-server-sdk-node) automatically gzips requests for you, and automatically throttles your requests to smooth out the load, so we highly recommend it! + +### Push tickets + +The requests above will respond with a JSON object with two optional fields, `data` and `errors`. `data` will contain an array of [**push tickets**](#push-ticket-format) in the same order in which the messages were sent (or one push ticket object, if you send a single message to a single recipient). Each ticket includes a `status` field that indicates whether Expo successfully received the notification and, if successful, an `id` field that can be used to later retrieve a push receipt. + +> **Note**: a status of `ok` along with a receipt ID means that the message was received by Expo's servers, **not** that it was received by the user (for that you will need to check the [push receipt](#push-receipts)). + +Continuing the above example, this is what a successful response body looks like: ```json { "data": [ - {"status": "ok", "id": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"}, - {"status": "ok", "id": "YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY"}, - {"status": "ok", "id": "ZZZZZZZZ-ZZZZ-ZZZZ-ZZZZ-ZZZZZZZZZZZZ"}, - {"status": "ok", "id": "AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA"} + { "status": "ok", "id": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" }, + { "status": "ok", "id": "YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY" }, + { "status": "ok", "id": "ZZZZZZZZ-ZZZZ-ZZZZ-ZZZZ-ZZZZZZZZZZZZ" }, + { "status": "ok", "id": "AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA" } ] } ``` -If you send a single message that isn't wrapped in an array to a single recipient, the `data` field will be the push ticket also not wrapped in an array. +If there were errors with individual messages, but not the entire request, the bad messages' corresponding push tickets will have a status of `error`, and fields that describe the error, like this: -#### Push tickets +```json +{ + "data": [ + { + "status": "error", + "message": "\\\"ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]\\\" is not a registered push notification recipient", + "details": { + "error": "DeviceNotRegistered" + } + }, + { + "status": "ok", + "id": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" + } + ] +} +``` -Each push ticket indicates whether Expo successfully received the notification and, when successful, a receipt ID to later retrieve a push receipt. When there is an error receiving a message, the ticket's status will be "error" and the ticket will contain information about the error and might not contain a receipt ID. More information about the response format is documented below. +If the entire request failed, the HTTP status code will be 4xx or 5xx and the `errors` field will be an array of error objects (usually just one). Otherwise, the HTTP status code will be 200 and your messages will be on their way to the iOS and Android push notification services! -> **Note:** Even if a ticket says "ok", it doesn't guarantee that the notification will be delivered nor that the device has received the message; "ok" in a push ticket means that Expo successfully received the message and enqueued it to be delivered to the Android or iOS push notification service. +### Push receipts -#### Push receipts +After receiving a batch of notifications, Expo enqueues each notification to be delivered to the iOS and Android push notification services (APNs and FCM, respectively). Most notifications are typically delivered within a few seconds. Sometimes it may take longer to deliver notifications, particularly if the iOS or Android push notification services are taking longer than usual to receive and deliver notifications, or if Expo's cloud infrastructure is under high load. -After receiving a batch of notifications, Expo enqueues each notification to be delivered to the iOS and Android push notification services (APNs and FCM, respectively). Most notifications are typically delivered within a few seconds. Sometimes it may take longer to deliver notifications, particularly if the iOS or Android push notification services are taking longer than usual to receive and deliver notifications, or if Expo's cloud infrastructure is under high load. Once Expo delivers a notification to the iOS or Android push notification service, Expo creates a **push receipt** that indicates whether the iOS or Android push notification service successfully received the notification. If there was an error delivering the notification, perhaps due to faulty credentials or service downtime, the push receipt will contain information about the error. +Once Expo delivers a notification to the iOS or Android push notification service, Expo creates a [**push receipt**](#push-receipt-response-format) that indicates whether the iOS or Android push notification service successfully received the notification. If there was an error delivering the notification, perhaps due to faulty credentials or service downtime, the push receipt will contain more information regarding that error. -To fetch the push receipts, send a POST request to `https://exp.host/--/api/v2/push/getReceipts`. The request body must be a JSON object with a field name "ids" that is an array of receipt ID strings: +To fetch the push receipts, send a POST request to `https://exp.host/--/api/v2/push/getReceipts`. The [request body](#push-receipt-request-format) must be a JSON object with a field name `ids` that is an array of ticket ID strings: ```bash curl -H "Content-Type: application/json" -X POST "https://exp.host/--/api/v2/push/getReceipts" -d '{ @@ -235,7 +255,7 @@ curl -H "Content-Type: application/json" -X POST "https://exp.host/--/api/v2/pus }' ``` -The response body contains a mapping from receipt IDs to receipts: +The [response body](#push-receipt-response-format) for push receipts is very similar to that of push tickets; it is a JSON object with two optional fields, `data` and `errors`. `data` contains a mapping of receipt IDs to receipts. Receipts include a `status` field, and two optional `message` and `details` fields (in the case where `"status": "error"`). If there is no push receipt for a requested receipt ID, the mapping won't contain that ID. This is what a successful response to the above request looks like: ```json { @@ -246,219 +266,119 @@ The response body contains a mapping from receipt IDs to receipts: } ``` -**You must check each push receipt, which may contain information about errors you need to resolve.** For example, if a device is no longer eligible to receive notifications, Apple's documentation asks that you stop sending notifications to that device. The push receipts will contain information about these errors. +**You must check each push receipt, since they may contain information about errors you need to resolve.** For example, if a device is no longer eligible to receive notifications, Apple's documentation asks that you stop sending notifications to that device. The push receipts will contain information about these errors. -> **Note:** Even if a receipt says "ok", it doesn't guarantee that the device has received the message; "ok" in a push receipt means that the Android or iOS push notification service successfully received the notification. If the recipient device is turned off, for example, the iOS or Android push notification service will try to deliver the message but the device won't necessarily receive it. +> **Note:** Even if a receipt's `status` says `ok`, this doesn't guarantee that the device has received the message; "ok" in a push receipt means that the Android or iOS push notification service successfully received the notification. If the recipient device is turned off, for example, the iOS or Android push notification service will try to deliver the message but the device won't necessarily receive it. -### Message format +If the entire request failed, the HTTP status code will be 4xx or 5xx and the `errors` field will be an array of error objects (usually just one). Otherwise, the HTTP status code will be 200 and your messages will be on their way to your users' devices! -Each message must be a JSON object with the given fields: +## Errors -```javascript -type PushMessage = { - /** - * An Expo push token or an array of Expo push tokens specifying the recipient(s) - * of this message. - */ - to: string | string[], - - /** - * A JSON object delivered to your app. It may be up to about 4KiB; the total - * notification payload sent to Apple and Google must be at most 4KiB or else - * you will get a "Message Too Big" error. - */ - data?: Object, - - /** - * The title to display in the notification. Devices often display this in - * bold above the notification body. Only the title might be displayed on - * devices with smaller screens like Apple Watch. - */ - title?: string, - - /** - * The message to display in the notification - */ - body?: string, - - /** - * Time to Live: the number of seconds for which the message may be kept - * around for redelivery if it hasn't been delivered yet. Defaults to - * `undefined` in order to use the respective defaults of each provider. - * These are 0 for iOS/APNs and 2419200 (4 weeks) for Android/FCM and web - * push notifications. - * - * On Android, we make a best effort to deliver messages with zero TTL - * immediately and do not throttle them. - * - * However, note that setting TTL to a low value (e.g. zero) can prevent - * normal-priority notifications from ever reaching Android devices that are - * in doze mode. In order to guarantee that a notification will be delivered, - * TTL must be long enough for the device to wake from doze mode. - * - * This field takes precedence over `expiration` when both are specified. - */ - ttl?: number, - - /** - * A timestamp since the UNIX epoch specifying when the message expires. This - * has the same effect as the `ttl` field and is just an absolute timestamp - * instead of a relative time. - */ - expiration?: number, - - /** - * The delivery priority of the message. Specify "default" or omit this field - * to use the default priority on each platform, which is "normal" on Android - * and "high" on iOS. - * - * On Android, normal-priority messages won't open network connections on - * sleeping devices and their delivery may be delayed to conserve the battery. - * High-priority messages are delivered immediately if possible and may wake - * sleeping devices to open network connections, consuming energy. - * - * On iOS, normal-priority messages are sent at a time that takes into account - * power considerations for the device, and may be grouped and delivered in - * bursts. They are throttled and may not be delivered by Apple. High-priority - * messages are sent immediately. Normal priority corresponds to APNs priority - * level 5 and high priority to 10. - */ - priority?: 'default' | 'normal' | 'high', - - // iOS-specific fields - - /** - * The subtitle to display in the notification below the title - */ - subtitle?: string, - - /** - * A sound to play when the recipient receives this notification. Specify - * "default" to play the device's default notification sound, or omit this - * field to play no sound. - * - * Note that on apps that target Android 8.0+ (if using `expo build`, built - * in June 2018 or later), this setting will have no effect on Android. - * Instead, use `channelId` and a channel with the desired setting. - */ - sound?: 'default' | null, - - /** - * Number to display in the badge on the app icon. Specify zero to clear the - * badge. - */ - badge?: number, - - // Android-specific fields - - /** - * ID of the Notification Channel through which to display this notification - * on Android devices. If an ID is specified but the corresponding channel - * does not exist on the device (i.e. has not yet been created by your app), - * the notification will not be displayed to the user. - * - * If left null, a "Default" channel will be used, and Expo will create the - * channel on the device if it does not yet exist. However, use caution, as - * the "Default" channel is user-facing and you may not be able to fully - * delete it. - */ - channelId?: string, -} -``` +Expo provides details regarding any errors that occur during this entire process. We'll cover some of the most common errors below so that you can implement logic to handle them automatically on your server. If, for whatever reason, Expo couldn't deliver the message to the Android or iOS push notification service, the push receipt's details may also include service-specific information. This is useful mostly for debugging and reporting possible bugs to Expo. -### Response format +### Individual errors -The response is a JSON object with two optional fields, `data` and `errors`. If there is an error with the entire request, the HTTP status code will be 4xx or 5xx and `errors` will be an array of error objects (usually just one): +Inside both push tickets and push receipts, look for a `details` object with an `error` field. If present, it may be one of the following values, and you should handle these errors like so: -```json -{ - "errors": [{ - "code": "INTERNAL_SERVER_ERROR", - "message": "An unknown error occurred." - }] -} -``` - -If there are errors that affect individual messages but not the entire request, the HTTP status code will be 200, the `errors` field will be empty, and the `data` field will contain push tickets that describe the errors: +- `DeviceNotRegistered`: the device cannot receive push notifications anymore and you should stop sending messages to the corresponding Expo push token. -```json -{ - "data": [{ - "status": "error", - "message": "\\\"ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]\\\" is not a registered push notification recipient", - "details": { - "error": "DeviceNotRegistered" - } - }, { - "status": "ok", - "id": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" - }] -} -``` +- `MessageTooBig`: the total notification payload was too large. On Android and iOS the total payload must be at most 4096 bytes. -> **Note:** You should check the ticket for each notification to determine if there was a problem delivering it to Expo. In particular, **do not assume a 200 HTTP status code means your notifications were sent successfully**; the granularity of push notification errors is finer than that of HTTP statuses. +- `MessageRateExceeded`: you are sending messages too frequently to the given device. Implement exponential backoff and slowly retry sending messages. -The HTTP status code will be 200 also if all of the messages were successfully delivered to Expo and enqueued to be delivered to the iOS and Android push notification services. +- `InvalidCredentials`: your push notification credentials for your standalone app are invalid (ex: you may have revoked them). Run `expo build:ios -c` to regenerate new push notification credentials for iOS. -Successful push receipts, and some types of failed ones, will contain an "id" field with the ID of a receipt to fetch later. +### Request errors -### Receipt request format +If there's an error with the entire request for either push tickets or push receipts, the `errors` object may be one of the following values, and you should handle these errors like so: -Each receipt request must contain a field named "ids" that is an array of receipt IDs: +- `PUSH_TOO_MANY_EXPERIENCE_IDS`: you are trying to send push notifications to different Expo experiences, for example `@username/projectAAA` and `@username/projectBBB`. Check the `details` field for a mapping of experience names to their associated push tokens from the request, and remove any from another experience. -```javascript -{ - "ids": string[] -} -``` +## FAQ -### Receipt response format +- **Does Expo store the contents of push notifications?** Expo does not store the contents of push notifications any longer than it takes to deliver the notifications to the push notification services operated by Apple, Google, etc... Push notifications are stored only in memory and in message queues and **not** stored in databases. -The response format for push receipts is similar to that of push tickets; it is a JSON object with two optional fields, `data` and `errors`. If there is an error with the entire request, the HTTP status code will be 4xx or 5xx and `errors` will be an array of error objects. +- **Does Expo read or share the contents of push notifications?** Expo does not read or share the contents of push notifications and our services keep push notifications only as long as needed to deliver them to push notification services run by Apple and Google. If the Expo team is actively debugging the push notifications service, we may see notification contents (ex: at a breakpoint) but Expo cannot see push notification contents otherwise. -If there are errors that affected individual notifications but not the entire request, the HTTP status code will be 200, the `errors` field will be empty, and the `data` field will be a JSON object whose keys are receipt IDs and values are corresponding push receipts. If there is no push receipt for a requested receipt ID, the mapping won't contain that ID. This is an example response: +- **How does Expo encrypt connections to push notification services, like Apple's and Google's?** Expo's connections to Apple and Google are encrypted and use HTTPS. -```json -{ - "data": { - "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX": { - "status": "error", - "message": "The Apple Push Notification service failed to send the notification", - "details": { - "error": "DeviceNotRegistered" - } - }, - "YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY": { - "status": "ok" - } - } -} -``` +- **What browsers does Expo for Web's push notifications support?** It works on all browsers that support Push API such as Chrome and Firefox. Check the full list here: https://caniuse.com/#feat=push-api. -> **Note:** You should check each receipt to determine if there was an issue delivering the notification to the Android or iOS push notification service. In particular, **do not assume a 200 HTTP status code means your notifications were sent successfully**; the granularity of push notification errors is finer than that of HTTP statuses. +- **How do I handle expired push notification credentials?** When your push notification credentials have expired, run `expo credentials:manager -p ios` which will provide a list of actions to choose from. Select the removal of your expired credentials and then select "Add new Push Notifications Key". -The HTTP status code will be 200 also if all of the messages were successfully delivered to the Android and iOS push notification services. +## Formats -**Important:** in particular, look for an `details` object with an `error` field inside both push tickets and push receipts. If present, it may be one of these values: `DeviceNotRegistered`, `MessageTooBig`, `MessageRateExceeded`, and `InvalidCredentials`. You should handle these errors like so: +### Message request format -- `DeviceNotRegistered`: the device cannot receive push notifications anymore and you should stop sending messages to the corresponding Expo push token. +Each message must be a JSON object with the given fields (only the `to` field is required): -- `MessageTooBig`: the total notification payload was too large. On Android and iOS the total payload must be at most 4096 bytes. +| Field | Platform? | Type | Description | +| ------------ | ------------- | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `to` | iOS & Android | `string | string[]` | An Expo push token or an array of Expo push tokens specifying the recipient(s) of this message. | +| `data` | iOS & Android | `Object` | A JSON object delivered to your app. It may be up to about 4KiB; the total notification payload sent to Apple and Google must be at most 4KiB or else you will get a "Message Too Big" error. | +| `title` | iOS & Android | `string` | The title to display in the notification. Often displayed above the notification body | +| `body` | iOS & Android | `string` | The message to display in the notification. | +| `ttl` | iOS & Android | `number` | Time to Live: the number of seconds for which the message may be kept around for redelivery if it hasn't been delivered yet. Defaults to `undefined` in order to use the respective defaults of each provider (0 for iOS/APNs and 2419200 (4 weeks) for Android/FCM). | +| `expiration` | iOS & Android | `number` | Timestamp since the UNIX epoch specifying when the message expires. Same effect as `ttl` (`ttl` takes precedence over `expiration`). | +| `priority` | iOS & Android | `'default' | 'normal' | 'high'` | The delivery priority of the message. Specify "default" or omit this field to use the default priority on each platform ("normal" on Android and "high" on iOS). | +| `subtitle` | iOS Only | `string` | The subtitle to display in the notification below the title. | +| `sound` | iOS Only | `'default' | null` | Play a sound when the recipient receives this notification. Specify `"default"` to play the device's default notification sound, or omit this field to play no sound. | +| `badge` | iOS Only | `number` | Number to display in the badge on the app icon. Specify zero to clear the badge. | +| `channelId` | Android Only | `string` | ID of the Notification Channel through which to display this notification. If an ID is specified but the corresponding channel does not exist on the device (i.e. has not yet been created by your app), the notification will not be displayed to the user. | -- `MessageRateExceeded`: you are sending messages too frequently to the given device. Implement exponential backoff and slowly retry sending messages. +**Note on `ttl`**: On Android, we make a best effort to deliver messages with zero TTL immediately and do not throttle them. However, setting TTL to a low value (e.g. zero) can prevent normal-priority notifications from ever reaching Android devices that are in doze mode. In order to guarantee that a notification will be delivered, TTL must be long enough for the device to wake from doze mode. This field takes precedence over `expiration` when both are specified. -- `InvalidCredentials`: your push notification credentials for your standalone app are invalid (ex: you may have revoked them). Run `expo build:ios -c` to regenerate new push notification credentials for iOS. +**Note on `priority`**: On Android, normal-priority messages won't open network connections on sleeping devices and their delivery may be delayed to conserve the battery. High-priority messages are delivered immediately if possible and may wake sleeping devices to open network connections, consuming energy. On iOS, normal-priority messages are sent at a time that takes into account power considerations for the device, and may be grouped and delivered in bursts. They are throttled and may not be delivered by Apple. High-priority messages are sent immediately. Normal priority corresponds to APNs priority level 5 and high priority to 10. -If Expo couldn't deliver the message to the Android or iOS push notification service, the receipt's details may also include service-specific information. This is useful mostly for debugging and reporting possible bugs to Expo. +**Note on `channelId`**: If left null, a "Default" channel will be used, and Expo will create the channel on the device if it does not yet exist. However, use caution, as the "Default" channel is user-facing and you may not be able to fully delete it. -# FAQ +### Push ticket format -- **Does Expo store the contents of push notifications?** Expo does not store the contents of push notifications any longer than it takes to deliver the notifications to the push notification services operated by Apple, Google, etc... Push notifications are stored only in memory and in message queues and **not** stored in databases. +```javascript +{ + "data": [ + { + "status": "error" | "ok", + "id": string, // this is the Receipt ID + // if status === "error" + "message": string, + "details": JSON + }, + ... + ], + // only populated if there was an error with the entire request + "errors": [{ + "code": number, + "message": string + }] +} +``` -- **Does Expo read or share the contents of push notifications?** Expo does not read or share the contents of push notifications and our services keep push notifications only as long as needed to deliver them to push notification services run by Apple and Google. If the Expo team is actively debugging the push notifications service, we may see notification contents (ex: at a breakpoint) but Expo cannot see push notification contents otherwise. +### Push receipt request format -- **How does Expo encrypt connections to push notification services, like Apple's and Google's?** Expo's connections to Apple and Google are encrypted and use HTTPS. +```javascript +{ + "ids": string[] +} +``` -- **What browsers does Expo for Web's push notifications support?** It works on all browsers that support Push API such as Chrome and Firefox. Check the full list here: https://caniuse.com/#feat=push-api. +### Push receipt response format -- **How do I handle expired push notification credentials?** When your push notification credentials have expired, run `expo credentials:manager -p ios` which will provide a list of actions to choose from. Select the removal of your expired credentials and then select "Add new Push Notifications Key". +```javascript +{ + "data": { + Receipt ID: { + "status": "error" | "ok", + // if status === "error" + "message": string, + "details": JSON + }, + ... + }, + // only populated if there was an error with the entire request + "errors": [{ + "code": string, + "message": string + }] +} +``` diff --git a/docs/pages/versions/unversioned/sdk/notifications.md b/docs/pages/versions/unversioned/sdk/notifications.md index 4bd1410f57735..e7dea8216eb5a 100644 --- a/docs/pages/versions/unversioned/sdk/notifications.md +++ b/docs/pages/versions/unversioned/sdk/notifications.md @@ -59,6 +59,16 @@ An object that is passed into each event listener when a notification is receive - **data (_object_)** -- Any data that has been attached with the notification. - **remote (_boolean_)** -- `true` if the notification is a push notification, `false` if it is a local notification. +The `origin` will vary based on the app's state at the time the notification was received and the user's subsequent action. The table below summarizes the different possibilities and what the `origin` will be in each case. + +| Push was received when... | `origin` will be... | +| -------------------------------------------------------------------- | :-----------------------------------: | +| App is open and foregrounded | `'received'` | +| App is open and backgrounded, then notification is not selected | no notification is passed to listener | +| App is open and backgrounded, then notification is selected | `'selected'` | +| App was not open, and then opened by selecting the push notification | `'selected'` | +| App was not open, and then opened by tapping the home screen icon | no notification is passed to listener | + ## Notifications ### `Notifications.getExpoPushTokenAsync()` @@ -246,6 +256,6 @@ A Promise that resolves to an object with the following fields: ## Error Codes -| Code | Description | -| -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| E_NOTIFICATIONS_TOKEN_REGISTRATION_FAILED | The device was unable to register for remote notifications with Expo. | | +| Code | Description | +| ----------------------------------------- | --------------------------------------------------------------------- | +| E_NOTIFICATIONS_TOKEN_REGISTRATION_FAILED | The device was unable to register for remote notifications with Expo. | | diff --git a/docs/pages/versions/unversioned/sdk/sharing.md b/docs/pages/versions/unversioned/sdk/sharing.md index e4fe14c242f2a..9ba313ceb48a3 100644 --- a/docs/pages/versions/unversioned/sdk/sharing.md +++ b/docs/pages/versions/unversioned/sdk/sharing.md @@ -5,7 +5,7 @@ sourceCodeUrl: 'https://github.com/expo/expo/tree/sdk-36/packages/expo-sharing' import Video from '../../../../components/plugins/Video' -**`expo-sharing`** allows sharing files. +**`expo-sharing`** allows you to share files directly with other compatible applications.

c=K{DwA9bJX7^?NF;QLtR{gG zBe3O=F?GcieEL`0vNO`8k+mN=hWTJikra4u96vICRmZRWIu&OFMs8i$*$`=%aO89{ zbMp4MY6ZG*O2qPq2g&Tx1L^M8@!}-~jQVKbBW1C6@!>R2r3Dfx9zf6FLomOE`cT(T z1OyU7X))oaAvo9~;X<>K$*?iKv?l?50Tk*p9^XVsyIu;5@vOgb3Veb)tTpps8R0^% z5_jvB?8BCtI#G=I&~8*JtRyDyg1#HwR!TUmfQpf4<+cAIUPf9z z1I=P{ro~5vqmeF&CoEadeX9SoQu(tcz#1Qwz$HmeIg~_R zX3cY)^27i))}-BX=1`SiVQFe$UM`13ttPDgO020f5O}DJ_1_5!|)IlR0w+eGg&4*OF0_x1E zF5dxhH|Uny*Gq7I99_G8ykO+3`gBy@-ypO4sy=9&eHMde&h5*bBd};odZjN|%_ly! zzsmKS@(74j`JTq{pH%e?9~&HIlo~7KhgbTO`@U(w!3Zcg?Jpr66Q#Rt+m!OA8#ma|W*gX61(bN-K>dX&rJxGJ%>#c*nanDQYyEqI4pisl`>g7|AsU|{W&1%0V zP|f->CK(ofm#?;Q^IdUZUwd#O{Z5yafnhvR*UO0eiVKa(ky?x_P2aOO(I^ARrK`hP zMFvsngwBqfGNcpeNDbC9hF7BdXB{$hu0YioBjFL9s~kQKX2sy*J%>O!{iC9Ut0$&? zag@&;K{tV0NWpSL_`WknREP-1b*bE1r6pz0E#YRVW*O;7LWs4ob;>1fF~TWQio?9z zd`MkZ*%bz9rm;^Kp8@;FNndbwDzA&|c)SG4T`hCYU*w-JVXB_73FtmZ9q0J@Lh*36 zai02~*n?O0N4v@RY~2j&vFgm*lAI*dA08{5q#0AbWx^M%*#R737=e%yXkL6LUZ)0o z=xr*(UR==Pz_Tmgh>lM(rmsQqxsQJ18fSubs|OuPIoRes?i+$iw5_;vJTbD%??u?p zW36!6Xj9o!JR4o5O9#&xstigUfm9geLD_?{2CA;&j%*B0@7NJHe3g$X^fPBV#Y0qi z0zM;bR7z}+%hLyGgdZ2|?vUxRG0D{As9j&&B%|>9&G==WpZRDV3gnA5=bA?OOLvWk zgM9Lc0g{}Iy=os5AHR5)!4m8X6&;6!!Cn9T_DX=ucZrc^fRW&%i@=%awW!5uVTo{t zG>AM62YLtz^JdpJpBDPhjy1sLA{Pu*G&H>x>T%icYpB|)13=xTwSW?B) zPHD#_K+0#5Tk()dx0oIg@*Ap@szRR z(d7VMm~4D1g*VPH)Wn+ii6Xsp_n!6&hAZ}yxXv;{DH(E)@>=kMsdeMsyA3I-?Me5! zgh+@)(aSheZx!c&7~55hWAQPXTx^YB?_?$h<;?E5WL8E;w)w|g2ZF(<$ zrW56g8W;v^0K=jw*(BjYZR+~S`Vw@J*DXS)1ZR=s)z&kIPr2G+Z!J)3_DPbPj&>i* z>&Waf37+k`iHBc2zpJsThsHczPaOI*QIE`T1^O zt5N=^mAh;KXy~xk=_R!NyFD;#x)fBp{-($dTn;yUrhD0H(xO{=rA*;0$1SP;B-yum zd;9h2Wa*suh5esfycmr;2vD{$8cuT%kr`i&dpe<#Rt-byCo*QnGCR zG!=&C{bq7q)ve5@Az!mF0Zq1!zN+!XP;Ew=#->QSfw$F`Y#9%G`LQlQ>t3I4m18f> zTNI=x5ARMF2qD#1DRZYIJ) zwOK>BZ(}c|?1i1)xy8E>Mhg3MCN>pTbjv{0r|bc`Fv1M6^&`;%V+M;kW$WYy^a{Lc zR)=C6$Bf~|MSu*UNHAfe1G`RMoewd)fD4;QN>MDYg3XTn5vOL=nA&84rqS@@BoDo> zF4s+Uy%eP`I~p@5hV?~tP8Mn428dltxy3rhpGVuws%~9I&m6yIK|*cgJDdDY9GmKsh#51s#G zj566NnX(e9sgtiwqZC5>^Kuw;+GX?!d2GIxCSPDeU7D-58K4io*i|q0Zs{!PAwZp^ zwF>hXwV-WJ?vd&2p*z1t%?$_D6+Fz)*WghMI$UxpIn2VVQN@t>q-m&QWK5uhg1+7+ z&X2@fX4g%(@8`)PVBBHXDcu+9`oJIVz|_^dv91-s<31Q|lR+s^klVRr(~YYbdYTr zm8a;!{YYJ=(&Uvj9?|XvaxLFw;EC-&Ugmg6M!hi@l_rO1GBXUAN_m)c?JES8R9b|J z>_#yM2T9>CX%gm7A>Ov@0o`y=BIs~7Us47NTlqU6#dLpF(cpTvadkl&-kSca-eO6~ zYOp9|q|7LYWE}U}y$k1L@#=KOH8wRX-WDl$z(g4*z>xxE(;_4t0K;()yh!v%KN+~l zlksmL1f8*!@VX_FpHu<(5Q^K5r5>MqQzU94azOIx2pY)d{l3?K{(QTEx~MXmCrbdb z^iNee3-XtrWpaFz8Etm6+nO%b@xhv4ql)7J=Uf#o8cP73_*-Hg7{XHbHyGVyA)C?Y z!X&!wb1s61eRQJtU|<_X0U!DJ9Pca2U*iP^&fE}5(i2D6k+8Pk z#w4>Y)vmq2!n*SSsR&dPsB1-YLc!VMuiF9a1$5CV5ao>TTW-Q5X@ze}ID<|rg~}bc z)FDHv31V-b!7D%*Y5%2#3hwBSP|5a*=fawV!?naeH@bZ>OVsA_>|h*l$|csy4dDcw z!`l@6TzORfYh3PUAlRZK^C#`z0tv-g{QG25G6>FF^K)?ie1IS0(DnO8APq1Vze0t- zp$Np@rlQt3)W=i5;2ULerp#&UHBhp6hO{$XkG<^hqq0}qtUeJwk5nT~Z+LQAK@lBq zE}2S@ST#FF@fo51K>Y(brzkm$2{YQEI+ z3VyGXU|Q=D!M`sb6X~}>DDiwh6IJgB8%@u-%~&0+Zw08sUOYnTLB(G2IB8s;Hjh;v z1qo<6zGeklBze)rD=qUcZxqcK9gxEBdUG4PbX*ujysT)Ka>c%pf?z_T)h|vZQ)8(l z9rb^y-~C}Z4A@AdJkAx%K+>XtjqkD@nG^J1&(t^=c{sClx3q^C52moWj&rY1;z*L3 zppZH%Md}piNBpOMxjB*-R~cywqlDRg*h(+N2g(m+fwJzuDw%H4iS*W6tocPr^Lu&A zq#zV&M7;c5ZKg;9w9s45Ix*_Lm)2VYAQA0s@ej^)iVVpndxwuj1=9=!?9h1lq{4wT z6EB$^+bSA_+EL3J!tper9IR$QvuCHg`3gl2pXipz*zR8=rz8Rq8IKnZD$&@Rrxfi0 zU>NJ&H{5mB8!B*pCbVOk7Wr-;GZ5anCYn)ln;xz}kwsZ(Hb@`VmcU#5@xqL>CU8p_ zb=?<}$a6yRO4wbSX>aS7sVtF*sPz6-9uzu9v%i`AOg}AoLE|;K|BcgONi0p!E`wRO zVI=vXjwvV>Rj1=VLMN8mEx_KL{(648XP3k0zkY@WvrZ{cR>O}EWVKw!g(u^KQOb*6 zlNlPE^)Fe84$Jau8dHQrABz3~v4#)b+xKV&Lo;)FWEJ>?9JX&-s=Ym+Y*2PM89oV@ zb;S@Un4av+d`ANP`_+k5qv|df+XIQ!@Teuf~|~=tWO~@44@? zaz+Xn?h@_fqULjY@Yo{fHP!xr(*5(kN~h-`%pnXR z;_xj66*|xu>63B0maQu^<-%((gMT$z(dU2s3Mx=@77x~Xp|&GzY;P64uib^EqHh#V zEpDCt?%%*EDI)OC8A;+Eanhq>efG@GvWX7t%Xs%L6u=k%LaP1YKJSMMZJ}=#H)$&( zg<}Ctj7RqbrRt~S5{pqOpC9l<(MFC{>j15e|JuOdi?s{24>t!9dAvzJ?e;xA?XcbX zmYMKa<<)W6@eo6xIZg@B$%Lvlgt)D?R7Y0T+WR99Xjb{dvBEEe7~!Mp{}~vO4)P0@ z7Ev75@YoJ3XSDtTf^f0}IC2Lk2^kIS09WlvAh!B*?EZ71Brg=}Tda(Coi90@5kmg7 zQ<6er8>n|^*IJsasUxG}Hl!{->$Ea`&MR9nJ4t@826{kU-RgKVn9?kt_TX#h9}?dOV|$F>B3mh5C$43ds!bszqTZt{27w`=OO?d zZsv$Vf}Y!&ybV?wGY!v0ku4dAM0280OUvuJ?AegrU}Bg{W)+GRoeV=PoF2uoY3zCZ z!$q)vtv5!TCnG3t6SWrxZA=aYR?n8x8t)GIc?P4Ga8%TVmw&aT8CrNBZ!QeyyW5X| z$!3>Y=KlBKf^Jpl{+K7I(Nz4rb+U>TX^%2@pOUjUIbY@ zb*BI%E8slu;j*1K1iFTV$lF3c@!nj{@|uIx?%yX6K8L@SF#$N_>Dzn=#eOIv|1NtJ z)u8+6*v|KhcD;qFg`UPQp@=_L+b=(70E`k{!gUc5)ZeP@ZU)*kK^+r&w(v2P5=Ov7 zpVbGPjz7L@pZrBX^v50s4UhuHMf16Rf{fp5I`;aa&1Ph=1G7XrOalaz<>h``I4}xV zr>4vAcK`81AAvL^DEr|q!$I`6XG3<@YtclMJLc5s5?_;{0iqYj992_qeAiMXJfDHq zm_MKQ_eDS;h(Z}qHTYfUYb+94&MuFBfvw;uwIdVYa*qq8!xC`=;1LPH`iZmk0N8tduX$i5NzW{Q7yJeruBG0Xp!H?n({%!5xTmHX348B^O zNt^Ls_6F}E;{-D|%1LDz`>&M%UkvKt-73S+GXEL?@NfY&a1Nw89A&S+|ByegtKewt zyHV=@G=*R5EjI=nRBB?vr~mB);187q-YwCr`R`!zKi>>!7(gF_jo293|9q$t@UC%p zcG5p=;rCxHs6kL{L!Eu{kHzr&ug36@`2l_@oDAY$FDVjWd=?})|3pduHUo+W;9ads z^Su8#iql}RNX>*7^8e3=(t;J6w&prD8e-3$M pn#5UenmF%&yX0`8+X1~dfc-lLGpMZf8@e~4ow6}0Iq4Ko1b8r#z6s7q+LJ0i%;W8%;)x!|L$<_@B3Fnh1?BED?7cU1_6Hj&r7ur9Q{4ObaNG@p+N({ z5&!x6vs2esmj5p0;PUszz+2>e_zNdD2N&mmCI>$%@^Dp1_4O+YaOsBy#JEL%kNh9k z9`5L2Fz3VS|Fs+HKll3kGI+CMXd;~dk(?Nsayz3=8OO#ta86-du4&PHKC`*{(PfcJ zkoM9u)SISR0_RL2v{k2{s}J6 z(?-tkw9dCG8tU_<+%kkT$L>$nMzL&*n#LU`@`_Iv9C2WAnQ-7bMCCPJ>F9(Fy;Whz zP(~8QP(y};1!zLWm&b`k$klOSalvso0Y0?;&;VAr{oX)&q$!Sr5^pBV`CoyhttN^R=9KWSts%8 zULi|}6b$;HPedYvQdIlpj&%+V6&%gr7ldb8kAQpXcwH_MWnY`Ox^mZ-l9|)+_M-PY z6_3)6R@|-e9|lsvF(cq`zhFlS50k9#ciq(1_+ZPgigM7vmElLm(q)tG!}S#7Vej8~ z1G;l_E8i<)o}^U2#ahFJE#xjurw(g~_`PvF*iQHK$?g3YOY@q+Xu(lS9bq-80Ky&} z3dzmw3*3P8M{&?04byzihb3j6`Mc_DzC4A6M}mZl)2lOMz>)FWl@k1TKSLcxp-T)u z&Lks&Af1_tARF_Tq#PpOxxr8>QrO)jRVYswL#^fv(3{fruI}@V^IVz>(&Ewr;;f`8 z5Bu0rhno@QG8ej+P2YH*3pn#kWe2IR>)=tHP90hNpffdBQNskMK1ytjqn3(#uXu=S ztS(|R%A{B0U@*Nv)5X8io{pQPAr?;jW>jl3gE86=L0ST#oI!$REcB^hOHT~hdu`xr zdAhNFxpGbps@rakS@sA{SucxG#GQX#iKoDZ|hqh&T-dr5ES$sX7 z7HZ%}bt-|H1U5J~43cB>tbrd#c_i2>0iBS1bDQn4#A<+a3Qk(oR!YS z>8dG0W0j-ql?@Y5<}HC0R5536mPZ=IJZ~yhGPpa&iw#o8=jhZmQ@x&Lj%K$MfD(Ur zNl@cLRWBG-KA0yaCTeALcU8r$X%w2t0IjX3j2RRT3Y|>js;O)AaNfzS!KipUeH8=M zb#mnNxMtWD^BQwz3OsJpPg#$RReE16!HrReJvMc0It1;4E?H!rg3k^@5&K*U@2>@& zAY}1&3&i%w#Hs3B=B`)P#60RtIH}Deu{<01Ty~qee;qA%%JHCO1~>rmChq6hWZ{}f zT_J<72w3Od*I{xLsH(DPZdkXkW}y)*561$&)Sw8^=m1`%yoDOa1w*I?(=_*ST=2`< z%T+}DZ493=box@LHd(WCmgP7f?N)8pyrSd!8!RbitTM67gFS`1G)|_)gl% zTO8jT3s#W;Y(%ca8N1)l1=!FL%ove|!K4>hbQXVm$Q$H<(@ zi#%;_loITGT4S7VE=Q}q)P%ClcXuNt!(z2lThAW!I3lqXxVzqWv`Tl=ItXJM7bHAt zENvCoyI4W@LL+VXtvLQDm9#h^Q6%Ym1btRMs;z$T8GlT%G}DqgI*uFY zVt-bK^-a6L|C!a#3ukg!uJ%Oaz00I%y2P>Ywvo z+w8X1*47?|!ro!6AAQd;_r$K$YdkKt^Z%%ecM^=LXc>1Y29*?2i9W+241!!TVGd)Sb{+i4DAmS$K(u{^g{i~D#h_7!GyXU^Bt)1PD ziigdN5*)2ubh*-vA5Mw%KTaSb5#||^7OZ)1E2-JL``ei^v#{Oisvr3U1x3Zh&jV$# z9mSNLha{3e=kb81KReuYq9`1c@IlVDn;oV+CZjF+PQagBI+d6%fsld>8=q^5ST*3kCt z7nnG=p@+gFV`0D{F;C+@!3kf~lb4~9rJiGt{_O+LXkhOy$mdAOR^r1b%J~g}IpAU` z^Q|x(3bA=q-9c8Q-QZ$dT|;Rx-EW%%RZfCR7uT5A-vTM=6D0g7f+kd7MQHwO4m2Px zz)2m&ftK8A__Z{REW;C_-v&)H7yttx#5zS{jC#MWySJDZnJM*aO80c78aqek`XqY1 zQ?Z*skrB+O{@1Pnn!yZID(h0>bzVrjU&|E}7)Z2h^b!ajv}qo1Q4XH_i7YO!&ziFL zug~x8mI4vAbabY!`^Tho;ja5q@X9;mqRpd_=U@B{-wz+VQ_Sr24gGMvy~^wOC#KKi zem(csjU?i%=3gJEsS$PQE&r@!zuuqL1Z=-7nn6)c=4!(dJ5dw99M!Nd)@%J1l7kt| z_n@f~2x!pO8OKHwPSI;S;zNZm84h6-&eE{ahEhLy;3kwhzf}llE&cJZkEj$c-o}cd z5t2~)UVJKoG|%!m%vz77BdO?m4eT*Fb26x;+f`T&RCnCU&3_6bx6}}60zUo@&fo<2 zG_akK_cv1m)0npf!0m+l@~baZ!nx$Q8w>&4zn%}PyvYCU-)Q1eVDjp)gm0W?99wSf z=IY(5ZN^yis$PFCI^QkQtC@bT8YXLaK0U2#dqkzL@&wKrK2#6T_Jzg^k6`6id^KKUlIEHH&FSboT$QW&MJ;yWQ)VM-~5l+{zM%rI2~MYA_6|%KmPRrA^z9v8!xzI z9YgVU_&*Whzt=IB0Vmd)9F&ykzYb)NAN+|A|GsCIqRMwN?Oac+3^^`T|J?+A96G5SldG&OXkeue&F7WG3|AP@3rIoI8sAZ=s&UKUoRxF0Q#>X54PiKMtx~N zx0UF#24sqFGu(tDt%g2#UV3$=AqMvyl+!uA36ZaCK1BX+ce$ephqhCveYn21%zt5zn zwGi<86Ef1EhsB-i8_k<_p0U@`(@T8=xfWz_+Mn~7DNYl1@zFGR{yWh8ft|nKBVxe_ zwA}E;L{_iHuIx*?XO_H`He@8fu&^?W^3B&$q@tlenZkbwk>Zh>`&*GlW?$|cZ9~5) zQZh1t$DQ}h4rFG(6`m)3B0L?}|MbS|I7*po^Scsfqj5&lR=(>OSLOe`_(Q@>XX=Xg z@{{HRo)IE{Eh7_BWY|7`cF(66ojoy z09^aO7!MRf%Cd}m3=83n^1NRZ)@U97uPF5m7xXfMaB15=><*KOSuSP#?YRF*sQw9X z;2}&s1WVC|MtcRS-mCihMsg#7e6rep=4yNNFM|57n74rk_lWz79l^}c?JaYyxnFeo zeYEWP=leOApMQe-e`KBM2-?GjUiy~GLjXjVHpT{Zu`H}LUk{AXsLkMMXFGc3^Mk*j ziGl~&O#xTnAd{d5i;sGh1fEgzue|w(01ces1RRNumejL9frCfFD4nXXs`;5;RyHL6 ztKRq8y&yl|M%YlEEL%3ZJRFa4Iuw)4ZhO2aN+4X(gYvjNsy_D_ez0r} zRnakdyzd2tg?);OiiLG`Q%UT4mYmHOS(@6~=Zz~(lcr$a1h^mdGR~lLHd5i5an2(f z=>G3RtycoI&_f~5kjfuY=CssKWlUwa)3D#{-pAcDx!4x8yA(#r!K8S4dTP>m*p!J> z()NETm^fW#GV$#}?s?a{vewqL)uNjDa*uhh9tJRB2WVxZPz=mI1$>sRf1#^8y{B(u zFstQsyy#i~h+RTJE-ju`ZaPykXj=0#)EVawg9&~wJR|d z*ZVCC{bJWUIN5=CowE{;y>_c60)Hre-MMdAj$jRR3WUDiDeKXdk&zLQQH~V9-Bhi% z_(9lk(2gEd>b&1{-fd~W56%HNMS5*~3M(uw=6D=yDyv6t|F50>1EN+Rj>*eQ56xDs zBMckBhL>&qmW%ONV34Ev!c?!+I6(A#*5y+qJeELfjKDIq^mePDq0r9L$N{!SN5VKccZsezesyOStbS8J(`)1Zm8ZzpOSmVH)w zKmEXoKp*!8UVmGO6?d>5FDx@?aG&~~$QqOxpxON?jKW4KiLDHTxbQIsa zX>e|)M{svzYtDfY=1)F^{_FBxpGhPUr?n2{#UPXhN;Fb^Whf?v5&`FP9vQo{broj6 zC?2%+GI?V9xu?%l)$Gg}O;}PG#m5C&r0(DkuJmKfg0MC{O=@$G`HxsmseVLa3hRuu6qt?K*jWf5*H8sr&{d7#{nj zTU(7oOG{YD&G7sqaUoCXH-PFnQW?Lg$;ZxdYa5%0u#?}JZitNW%yoKyZ(rHlNwiV+L*Dx56+rQjKS>$q&+`T_(Zwn9>flf^C@05>j8=mr(siYM52iHUOoST@ zj0B8=wB$>SLOQ5hJX_~Cr~~ccMUFxO270vl4hCEhK%+m%UlJ>J#gyX^ZSTpL^e4>Y z(*$I;>_JS&{UerOxk(K=4Gt=veT?Y-uP8ak5I0}lGV@bY9YN?3l`Tr!Q!wQv3r3t3 zl8q*{=y~iCH8wixYPTqttC~U4pP++)9v*}x#Dqdo(scG=Y;3H`Hi+x+5Qqh4*M6oF zJxPfo;bF*u{JLn^-}6Hwf%h3Ea^^La7?>nUQH~M6yTG|QzCFKvmHUTo#tC>)z&~>u zuk)0__Mpx2&8*!Vx@E$1j?5J6um2wZpf4Cr>IW2g8x;Jh(tx|;jNMK=)yk3Q!t9ka zsox4pnr(m_NqTx)8?TcgIVsmidbT zN~o`NYaHfCw{p(9{OUa)Z*FZSKWO+WLBIzUiawWJ2i%}G-deSryV#!$kFB(H3-)O0`QApIX zloUlWd>ETplkgf#OIzz{bJbPG%~DsOkMp#MKbk!*&?-WML%#kUb=A}m@+YpH%&K$8 zVZKH0(bsQl#>O6go$8B3w-F-!hvoq{>l)^7YU&#HcFSA^1|5jX@gLHZgJPwj66fva zr7E;$aum}c?A5KYjPp=c#puKnr;_H?hcVJi%8D;jpMqWwPN=5xz`HJBu9~q+C&en0>HGb zNdLgFw?W}gF0(>`agnt(n=6Mt3Hh-9#FwLY{<8{4C*9VNDLjGw#$&tHZ}Cf2CLN(T zFi)@NM_)XweiRFnqVV0FU8S=_{wo0!Q5D6>amT$aeeFAp$0L4l9QsdN4hUHD?jxrr z3x3928|@C*s{Y7TC4<`*X%@USu}IOH_Whwt%_tRRL5=;{xd*U1rM!1KS3c+a zO6lLzIC>{>G^L!5rQY!$=w>bFpG^2UJ%#Q~d=47%M{B@6KFhg@m-E6RvJHuxt?mcB zABU}AkC<+E3{jt!c(38PqDB#~<5dywzE6Yqspfypeia7_O)NOC_^*CbF(R;Ndx}Jn zw&0KBtM@{+pYKduoqca8d`FeZ>u`Fu1k^*92uXW~7Y}*n@59k4(#LWNfEO)Yc2f&F zy;!l?Wm|INv#a)+|Jn;x7{coFw^Eb!@BYS-6Vw25C4)vM?kpbIjsafU*Dvj>x@!PS ziw;>m1@>h*AHN|M_or{tzF%^wo3>cEZfN;&?QG)@dX^B?%y|O| z7I)tbIJjmi^*CcgRP?CvSA5>H1EHZ$SPgFUSV?wFWl~z6DU8aXxSFve${`ohSs#9)%O5s!ikn`-`|)T~lf>)$x$5@0x`u`V*W}j)L)++?RQtu3 z(oxcL7fruT3)g%-2LPTWHYNgncmF#)i z+^O{=GzJRv`wqMAu05J3Pafyb)eU~vzHdq#E3!j{o7SzWf@jUs8F$aAAp=WpRlj}! z@Ab^g6#HT*T=lo=%pXcf35=>(Me@C(j`Jb~d3j~<*dl{#eJLYB^RKlDw!e8S_)ctX z>zPJ9AT}(4MHp7jiGj-5IYa}6-+G^^hO$v&_Gy+mTH~)BP)YdrGsMbBHb&-XBChKq zV$6TgM_(M%pVIw_J?;&JjtzgBFGnDt)v;c@9rHCmYug?7Y~?R znO3x&31#qL)Ol2lTPQW%Z&g!fH}%9DL~TXY)nu@;Jo<@_|j1ZdutveD*O*% zKk)M`2<(mD8@Q*CyN#-o=rwXGo9rs5^IQcEBh-o z-x-%w50TE_wv2O`#%S8ze@^5tJdAnLIcI(3?p9D#8C>?V@+|RIFNKvFLL+S(YzMq) zFXGhYY`i_2srEWvtG?T~Pq9ibqm2=0pX{#*Je6^CbHmXueay_PfF^gzryDKzSFC3g zAdL2oZTe5*EXr8wlE;d>NBNcw6*haSDy4-w;9d9yFQNx7Ee;f796}D*q6f%@}$P3LO5dQw85= zt(ms&siJo>E>(_k3OTz0em~qRwke~FRo?-zxu!pitw%OqX{3h6)WBXVpSTO(>g!3p zvCkvEr!3YnrT>-wDaYZK0+$;EGV^8=*ruk+seJ5FM_`1+N+N<1L9D54KEBz?lTGts zFK_-fA)M{}hp}D714VS{%Kwz`uixJYhM{=;SygP-zzj1zFBm3+{s!&9CYqPS7{dkDY(c>Rc5#h3e2ZClw?t>&j()6Q?#;@e z094FN&N`XPB=Dh}qjS#hz5{94tKZ(~A~M2oAO)ju^5OR$nnN1O{fO>ABv4$*gRr*K zhH8I%J^-vmhDg+nC2Mk^w@c;wOO91Th!cyS;pEdmiFff)#W&!>GHeefGYQNZN#VMk zh`82H)LJDrt!)kj$due|=`pfm(O@~e^}fA)z4`h5S#|2iN>zdsg5(NR2_~);56LaMx zI3)PjBXMifzo-*!DZF3d&xRqx!V?kyQ`N=^h(S1-;I3SOxc#%(6@P#tcFwC+R-$_I20#U(+D?F1gM5Lt8(}ov0O9n9?oBY?6RF!@#L9MI)RzL|G%Xmz00N zW0x|Rt91Ez@bdpYxqxLF3Cl+`F1Z3uPaBf_&$}F0qx#^GBuHmNa?Fnq$V4U#Q;~PZKVxPO4))wjks$ zKpO3)KEM66`AoGv`ot%W67_6Z3%i8s?D3#Hv#EMFTj*|EGE+{t1zWaUtb_ef1wUNc zleO>PzaM0sf-MZ~wtdOmvfn4t3D;UoI*=adMNDEYswn%(QWIG~^ykx#DwAH@o*44G zO9wQwZ1LnLT7N_raHjzB3ipk`{)ejHhawSxE0M!gq`zl_7&#d%zmzK3D$&`B7L=LM zmYCxfh>DK!Va%KGQR>tAQ1X2^*%Z!xUk{H%v@*Jx5VLR>=M1UzPn|X*QVJ9i#ODh@ zOOZ|m1Dn6jfzj(;dTL|qkIQ(fA|{kR2LaR=rQe#5zO!}&riL6J4*=qhVC4)8eFHRV zD&@G#)dHhi8~HKPYe=Payy*2#MYYf6Q5-CyGpr=p1eJ|oKST9Z{U|UL0|IfJuLRE71?A?w zZ(C2YW5u2f|CA-xVOk0uZm?_0=&6NO`r6S0_F%oXz` z{S8Y__h<6!-nx;{+XwQ346J)PHUpQrX>Q{>?%gC-mCgziB{6?oCq7ZYTuWett>K60 zzb*rxAOKC(%BCTyny1~E5rw$e_G$c!#K(nY7c^Xi)msJ5)G5}ItxUU}A;Iq9)yzaE z>F(ztPPp6^1b03=BU_h z?(s?f{XTlHU2Q|JuDz!7`RcM9L-?9_J;$c8(#Iys>b03h#XZSpEg#MLpd^)&bPDVz zZKrDk84KOPha&*;I2lMoVb8>K-xfj2XimZ!6l_d5VnvRix0eF|)=D-I)Ap{6`pF^1 zbr342Gm&8 z0=Bcf9#fyQohj;KczZ$df-#zzfZAyiwyb@t%{sb0Nn zUenpMEwvU>JIrmlT84;M`EJF4SnrRT8N(Wfw8Jb+Uyb`@vl#AK9b%$D6hdME;%PTk zPCsfk6#EN73ya9m)1={!_}ai@&Z0oO1nXEnhJ+vc#n2N=w#QDN+UA07xg58K&&U=o zWE(EXphWvE_kO8v=q?@KR}VU{u}?QRV~*?A)6pFSqu>jo?ypMj%S(KIu}Z#!!pj6p z;+yvC8N-N2=UBkUp)T0{09cvbHB*)PhDJ1 z86lsqmbI5J12@uJo8hJtB^)jhB-u#BP;_F5v06#dPVqKtPjxms zS?}$tyCQF)_?DKA7pen?Z?ksGQ2a5X|=KmZ}uVANRp0HG*_ zh^@v+?W|DVdqOeeb;Y}ZMFC$^>Vt4qpY|Bxz1q=yK9{vV9Avl}9Ku_+!7?^aknap+ zYIV0UIi&1@M~DKYJ@Z_6x00*a+~BJF34%Jp1llwg@~i~3jk`e8=@aHMY%v}Fnp{h5 z`ki6(Qw;Ty+OSdFWOjnRBQIn!fmHo~qkMY-YAbt}?1f z-Fp-c{fuO?GWK15umJ%@>hVg~g%hseaUYNHY{llt7v%BUFE};9UL8?q$P}K&-PZ$d zFaIQ25kV3?E$Lm{oIigz2!R(PB7xRo0*9?dG-+GD5h}x4|G}Ml=~M#Q?X0)q6;o>4 zT8|Q(s5grcLp>nNDXm}6!BP&Ll=v>@vr|d$-E|n4aR>M9bZ& zlS(0R7R=i`Be*z2w=qrk4orRoTeP(Z&!FT0>kcsvYIP{IT{ZXa8^i0%U+=>fb5Nvr z7=Q2#h~U*y9SstV6G8b?05mr!XW&M#490FPKXCcOXy>C#fA6UBUwScA1|;Nd#29OmnGnc>Gm`BJ5vWo z4qMJt+m^D=2}~zBl3Jv?W0ifMj-WEd$hR&%%qF!1j*=$q7T{x?EAI9z7AHlMPW0Hi zanYBbrFg`2-I}w;bRGAu^zIfTU~H97_7Kn}bRnfEmy#Oes;22U>^gzP3r5Za_tbi} zddJ4Y?$Sw1%I)wRXuJ?-aA-e5lqdCC2tCRkeU7q)U1urP9fEIX;9_6_a>*Y4EKjK& zl_vvW*724$f>=M{&U8tnn8h5U_ho73VxsOh1Uv(m4Wa<}!(3rRTM|>B#p=K~$%B_{ z0>e7Bu3yB*{2YvY^>>$-_fIke~yF}QdU zV9f&2iSc}v_H#)U3~1_BA_vasfwI_NGCJ8s(@)wBAp$=L3n?6h^N}wD2_umZLbS3m z7L01Uqq)R<=8;4$%gLQuVcSBoDw45xOH%x>(UF#g4}#OQU&m+6=JG}wZCO2{95(v2 zqCU$dq{Lj`$MfC^GZ^kW$j*}%iceZ$L`9yvT0G!28?|60!r2^ii^FJu7m&|h{yGUo$DEA1M6_Hfx=G1 zsf@i;p6KN`?AdZwik5-)o}{qox131QlnC#{i@;|3S~^$;)YrXuryxUTVe|G-;2EqI zOfA)cV;~|+R7eS90D%(RI{ zV`)W5y*X`s>yL=+EJnzJT5{Io-a;#v0(uPX}Ng?@K( zKS=8J@sCWWOY7AK!GV3}6rPI#2l)6EyXKZK>1*>KVIwOcdef+*cDV9Urc>4LD4`Vi z!Cq5&3)vr$JOwfS228U%tSzdJ`xX%ua?Mg@dJ!pxdW_fi7kI#CKSd$V z{KR2~ngnM?&WUUr^2c-{mL*$SpGH_Lw z-z2@3Cm<)5JNnRj*=awYP$KYrErE52HO6TFk6)@|1iKH;``lze>W+p{0{{M@;OTb| zL zwOz#1L^)4)w;kRP9)-9$99?1aX-%s@H4$8BPhD%sDyTvf2vO+}Bl8c`kxFp<^Iq#| zXTLZB!F_|Aw~_10F3SR^rSFU-(|5B-&H;jDLAB*Tk)4Zs$Yc+qx5)UIu)XK!)DAGI z3i4E>Jc;ar+oM6rZTu3!4UwV}5jh>zpmsp=9p=#N%oLZ#5%{>dsV084kxiwABOE-5 zug}PAeK7Z%0pp#}A6cu%D`MJ++{S_Mc8?m1H`n^juBEv*E)p9-iC=dFmpJH>KBJ>5LiJ2UZrASio;?|7=MwUu3|Bp_ z<7K1Md1=YQW~vYpUV5$#0H@kIoL4-j3)(#^G<6ks%OZJ7JE(zr?!N+ub%4!&XG}Iy zPm{8-xxj2)hB~HRC_0`smuEEXJad9h zsg^ENSu>d;<(cF1Ta&?8&ikIvo&9w5TO#!K0XdW(b{-;?TRFgb}X<@6} z^s(Pf$@r+SevLi;9?pu%%Ev202?`#CL<`|Qs=mV*mMqE7TR@P#ltcF zNgrd75}h#cQTJ7ES$W#5s)v2xlu2Rg>EpPICJ8fON!}xHlk(YOyc7jz6HA-Pa-b9)eC%Og1|41|y2fxE2v9m&Cs2U34}1g0da5 zb+7M&JFMByB;2!`WfBT_S{Df!F)5!=uNN__upBfHno@z?!okoGux8#oty9(XrdXH; z>6rvuDOJ%cqjxzQ62JkS#Vb{`d-ui1N|o|ddjOJe7hnrvH4cbZXoc>2sdg6_i(fW% z`Q^6rUf9K%{F=5csp9lIj9hxtm%vS9L+zl30!ND8j;=-fPp`=!30UNHm6cn60FpPsIaH!_F9(L~tT#O^w}BPT35T*?yg^Q% zC3JTXYlpl!8A&+oxqAi7;yoX=GC|x|;;8EcJ0R??!K`ndgBJGqw$Dn;j7Z-JcI?{i zu&O-qWpU}-H?i=8i0 z+4{^hg#ZM}*ydh=;j}=mgDWsSLM4b|zq`&UVS2)iq%W66rex)7HWgs2gU^9Owd`&e z=KT%qL)ZnAy3LdH?#c#pnI#u#Nyt*gL0POX+X>mV6$PZ=bA4^6ZEiDd40ZnJ3R9(` z0^h$`7Wg0;ZnnT)wk6n#G>8dz19N{E3p`FgN%P*TYhz6Pa>vY zSB#s*^NDwV@glQAAoAf+(rLT)xVFCnws9ELRue%{F%_&RTQ zuSTlHKUU}N-gPca`2B>KTy(f2L=BT9*jeLny(J`$lU%lDH_$Ow`)Ovf^YyVgI-nJM zj-OwgoP$r;%oeP}L^G?7(=cABgICCPaq|c-V1Uw8CzlxaL~0zhkm%z4B{XD*6#A(z zXh0N>dRfIoEc>S62J|X;0wA-GHb!21=HSj!4yc~54|?V zEI;AGh$0<>10O2yCkdN?$XG6xssb+efz*D!%1&h2l34pP>cY`#`(XrYF?6h5SXIGm zImM^EH{p4q28G|n64kQ4`;>*rjwlJxD6cBm<=$99EVTa7B~VjV#P2(Jc9ERT#KS+9 zV;9m8P3`pF0sC$jcpJ2aDhui~Ta$O-x+n389$79(!3HtxDVCeBSkD-WmIguF zo~3p1W>AWy`h=F^m=2MOyRZp33rn=FETBj3_p`B!f&5n^J~!lLj|?AVn4q((qF?BT z-+9AA$OsA?#BGQ#B4u-$+lsCJYZxMNJM%O6Wm?2|0Jgt(yCQR4=y4EG-+oJNzjZty zzF@i3ntZ`eu#aupRqMQh!JXhz>uiF1n5XK?V(`AL3KMn(WZ&%ZNWXp)0O`y!YGXAV z=~^)w!Uf(gr`I)Tbsp_pa*ULbYJtyak$xrEu9~R7q8@t&^Q~atKuQEhmmt*En z?xLstFxk-cRf0JTUPQd z(HRNFv<=)eXH4m1*iX|0bM#P30j_7At)!p%Kl6WtR7!6rtP`IABEO8jN!pawW5@PW~7-!w*M?4!9EDqGX~t zbO!okyL9C*g1vEQNvfk}&)NEWQQECUbl%>}t_T<_NW8r2{tm;BGmYnH38oK{7?LPa z%P{K~cM-*OC#o$_dXzx??vMgBGpW8PXO-HL&M}F&*8HHdBgeR_vd(SeU(WTBx}z3` zC?r0NOC0d<(s;#6zIT}Szyrw_Nbmdlu}9e|vDHAjJ@h?i)5!}mjZSsq46vxvR*qp3 zbp~lW@RHhqI(y*Q;e=fHY5&cB{lM%u;+|r^jKrbD&_)Vbx$>x-+Q86EyC{|XJ(fFl zW|wRA52PZ3W~Xbtv+ofGT6#uS7E8#^9(rfR>G#i%)>DA!YCGGi+a4ZPJ7b-2-#zP; zuV*nfewFE9vNRoF+^-z&{NzHtf5bwc&D6hfG&Gs>*p-(=N4%;(ebUNKM3X*OR!B0p z!nT}>`WHPq;nk;7weQs@NqBZ6m*vMN$^L*SrbF_s$Wgt)PbAi&f|@OM5RUy|=el~) zYP`&0Xa~#-b|QwIWx-|;C|}jd-LK!@WKfBfLd-usMvwenyVwo40`}`vv|OgPphlW^ z7Oh@7F_);S^^C5RwXAyY@O!aQR_ja}`Ca~UFX*X|EHuF#h`gj-RWrtyL7&gYX?12p z6g#gQsKTR6VZD9vHL|p|1)WXLdLS$9F53<9^a7|MGBYSuU8qemF^T_<1&iQ87>qsb z6fI!5HOzVIY*b5OCJ7Y;DY-x;^ji(i{vcodquTdT(R`IXD$(1W1E@V0ev*Bej#s~K z6Ebehkv#~dO`212pc}D7Sttvzm6Dx{S5XT9MP*8sw_-WeFD^pF(Pk3a z-Fdzgz74je5~NQb;fvf|>_49=2DVO;G;*)o+%)zTw9S~uk5y*0A)D?*T)9>Caf{l+ zdj+L)&(T6x>sH;fK76sK&-_xNK7$r1J(~*Yq!~S|Q*gswx;v02*YG2JE0VabAe01C z`?Rbz)&bU@{2Ix(f>=eD!byxG7Tw~^TW^EbFUGW`S4^<`@?vX`7k8?-4p<}gK4?Sk z$V#glB#Lxb^ogBV7V*VHUj@;X>muO*{lba>WXBBF{efvlY?Q%(CLvdbA4mAEpoMB` z)ECmCJjwt=w3Kp8avq)FJd^n_M z-9#d2^?I`J5*hqn)$nngQa(vRh*4e#8WlX@HV^NFF-$gEUkkgm zlvOVTf2y{=<)sy2+O;y`U_3?JEn@*`daC>U< zDZGvkoz`y$F9)~6t~}=?7qmZgqQrjGr*?Cuzwj8Q2c_mha(G~~JF>(t=aOdkJex)< ze7b9EW+@AS1PB)cI=Yth)8*d9Es4;y+HVZ=@O!Z4X%eII>?wCm2ab3isDy3$C7kK` zw4Db!U!3NwcX4{8^+~r%A!{E*FGXm~7j1%mwSlb;IJ5K{;)3D=!~DlWm#YbwHC3yZ z0$B4)sJ4XLedGbq#nuOgGmtpg_}j(X-8$^r>O;UW)%a7dOK3Us8yb?8-vFc5u+qO449+|K@lATSo`yNhzU8 zOy#%4cx>uwKt1V8$@ zpn@?*hUl&5ZGW-k!SfgNrppVtVpz&X zmKs=`i+!`rk=bYHRX9Yh&#kgh7YY#e>3mth;tWFqx&mPWn}F5N4+Kw?N(Fv}i|!%# za46hHO2jGPXO@hX-``z_HA6CUBQW#a8X97GVIz&vCX@|!mN^po^5fq$3r~at+)Sn4 zrpqmqaA=lW*a@c_!O}QE;EU_-XSBNH(qc}F3+&wNrFLy|aG&7OQ48sDkes|$3|+ra zDaQ{dLx^)^KdUxV3dCF!no17~*|glAp)Zh^?YsIAv$nIyzSR+vSDy zS9XVQ5VlsrfWAPS*yHBD+n*ze=`rGZ&o_&U%*avS?R$UXWlwSZ48QPN9FZupL)+n* zv;6IArF`7oYT+~TcOcnLCR{jOH02I#9;TR3-<^!8BHN;i4M6cxFg}`P5FHv{u$d1V<)y;9On+2xXU|42VrddlvYd`r~zAy|+Ntd)BSh*&UgOV$sM99sQgo~v?W z!wd)*DO@!ZuL@mSczxT>v%Q!?6y$WK)w=k)I82$cqAAGf$8tIwq51q`ujngi%k8dX z7!fzXS^A=Ww|ZtLl+2;@!IQfWh@K-TMd?&nl5A?V93_?@9CC^!uD@VA8$k{HsPSJ< z;_l&q9oHUAdC!I6980cL^{P&%ob2uu-iMvbIK;;n*OCX5^RIiKEnOjtSay4#Z4KXB zNFhHjKkS(KlB6_I&EMlG+v^DU%zGU!KDk+2xXm1j{R)*>N8pO@#!l-ZLFe-+Ib>bm zzw1`C^|Sp9KiibU=QC6F%v3mO)m?;eL8HHpd3xtiZ|=0X-vBVQ+_yH>@Zfm6Ztk9fJrZDf(3i+S}0m2f)TX2#^ocH9N zB>y(-X5IrhU>`ZK=a$h|neWh~XFNMGuC2YP$t^>^h&4w~&wf{*!|vz$u4D@izl`tE4Ntt+0A!vozE$EtrRi$)Iu1+@5EMnP16h?| zDzBWU%Ipw@#g1r&+oJT)_-8P!&H9bpq1z=bVn8Q_gc@}a0%F46)SeQ>NV}oWVOJZ= zDp+SW`>I54N)Wdk=Mu$JWzKVFC-B)&``Q4HiCn1HF2hl8MpVY3 zp%e2^kIMjHUJs;~3y&tzdPSL9**g#6>tgvn)5G6R1OJ0YKf!dVA#H#dj&KIQpEjRf z12FG)`DjJR!ctvEL|E`JQpTnsGnOpjU4ab-S$E23frFs~*IJPb;2ylzh?g2oj80AlHox0b zAn3{Xsn0l=BOm{-+vUo;u3F~ zTc0*!{7JH%)zR#JZd+h)U=h75?pJ%;k|EN1*K@lc@-FWe$Lm3dQt_W_P27hw>9&|` z=eBf#v-BljcJGw@VLYVw_Z=j;>S#B4gOl0VsWz|EQgzl&Za~+9(^sIQ z1zuQF>X{tG>Sh^yh7wjRf!k~tl^BABYa7y<(WQmr^!;Okq;%P2`=f1tc&rT<*aRz8 zbRrInapPXw_C(;?ANuZ%Nbko&o*S~=7@SnQ_mTE%-K=Risgc{;q<^XhA(CKnZZi9& zk(gdb-hI4qE1}G;AZ~#6x#?NOyO4mmsBd3nJ1f{q1ub&;8!- z`_H%5(Y4v@th28@*VHxho0$Om`|BIR<~E*@DnX|V-Hi^?NL6((t`aDRmmOc#ci5-Z|H$)sF!HXl;7ak6S>41SN(>y%z(Szx z_=XB>D!j5X#NQj2YNR04wT-$db%Ew=g!uwTZb@WjZC6+S+XuD~BuNoF=A zt!p-_4FuYF%mPVE?vJ>b&>%dHimcluq=+AaK=`CL6V;ebdjv(S$9QHazK*L=0I0yI#2pGhFAHBPh&r8M2gR#q)r620v-%?~+v(+}_V5SWp@^+IU4|CJyA4M<;+IPx4V-6%f0yO+jbV33pS@#qBKtL&Lk#nR(GIC=qI;rQ_UK`9{p~-{=&wS4Grd%m zp1UcPRtKJ6YIfZj%6&#;;XFDb+Xfcc5%JYdnY%XwY!3Gmc9-owk=bOtMXj3=kNqUh zY?q;rh%fLOB-PV$e>Q%{C}_Dnc)bM&DF-^wScjQU4M2az6UrM3KTyRBPA5-6eeYcHv8SotE<|W#`ahC2H?WN%`>sicZ^z9moy4?uO?+of1&>O zyn%z}ZI;#a#m{8;4ZVh=ES79mG4z@Qp)2Mq(17>+)#&{YD*wVna<{2c=aXA=O^Lf- z!AHgAC(vTxrj*5c_Y*`mn{|!PRcfjG_W8KoLv%XE9Cm~asK+vb`=Abfx4N-9n`_*_ zpzZTMQC?u&1NG-$MHyib8aC$r#oGNJx|@qK@pRAAGgf6cc$*o|N3z{YvFx1Jn?ab2 zE1mXZBa(M3!`~JJKXEU9nfOs}aIz)pzcW}YC^-vMzQrr0dI=^2&>)JI@Yq_qXa38S zwixiVpGE!oTAX6{@mc+X_|ul|`02C^V^3ir{pF=XrAFr( zbK{?4OaT-nTHe@9q1;}ysPQ-Is^{cK~c?AT6K$b%ZWrg^zVKcXB zTbCZMjbS*x>7i>ut9GZ9+-OSE#U=mc>QBort7neWZW!%nB`=yf>(<^sP3n}>xse?h zLm$MJQrQN=KUO%+?!&Je{BUBCJzRkv(iL-2i!d!PN?V65iCu$ItI{YJT1rKDHrSsZXh8Lfs0lGI zavAiIDnk*(D?K?@XEC1xa)2yH5lnO`xicT8VhhYr`ML&lu(ev z%&aV{WRI@A+Pi9fo-U&nFFz>_Vm*m;eM-%BUyMsQJSNkzOlm~sa{5VrR|S79;JMD~ ze*DAc;K_TRO1Hjp>B!5cQJ?K?d?%>GEJEFLU;S5+l?D{`V@aNEpA1k3g>SR)vmwd8 zZDQM;@q!tsD9CB?ojx!eR4^~rJ)dJvi%Pd4rR7Zo8m+-HAZ3MP%lXlsCAL5)u3BUV zy-0>AFv#S8YrpW#gBADLM;3A(3+pfwbbsMGfvW}6UP8aQp+sV*RcSeidOF$fG;6_t7+;P3p`u%J`TDWb}5L7{wBTouJFxPpTB?KE0+!S zTDKox$g5&M)99#y$N{1&Zw$W)g@V2cTNly8go(?(|4M62S|f$R3)I2AjP|Rg9gLp} zd;HaxML7{1kJ+(%xh9izi|$}B+V=>7KI1tNHf#5N*V^0t^cfLr$qLh}ckv{=rirTu zwJcQv)@7ZI79kI(otIa0{uAzxBG`wNLZD`3!ut^rvw|5Vq6Wz*vZXHArXYO)9B~MS z>~~$9G5o9PO|Kl9&Z(c)%A0mY>MO1G5jFU>YS7ZMw-T=x-;iwwaY8C}J4I}K=Z-Kp zU=-FistX;kgFud)tTP>Wk9;+WNwMCSHe+h3(FR%5?R+;H6Je+dYyb3XDH3xAjS7Tsj<}-4VN6sAXb6N_=|+Qo5)zCTQ4yF` zRJAoRjWX7L@Gj5guwY+@w0(@()(dDI^p^u6Z5Qd|By90^M*LGCje`eH#k&bbxN{*O z7if{ZD)|T+X~1Ls$?AR)Iqm-Fw|(e9_HI2Gg|V@9R&s%JSh3l#vti}2!6+Z~+Lmga z&otWSs}n0%Yx`&fnOzeydYYv})rx%tx4I60H$7wdxZG-6{)1civnp^ywJ8S>LZTW< zQ#|4~FKZ2u=caB|do(3u$M)>`R7>__3@jV64I_~Xa)fK3zokNt=d+djOj&)cdb&5g zQNDhA*b>M~%0ft}r4eVYTd;O2$doWg_@U@6R`0&c86wTg8H8||DHE`oh_{elUoV)( zp!!3e(s$kOFo$Rn4%B!6HRcDPtq5kcT2>61y%@FXfu)`q|46z}ed7K;=yBw$un9kP zcxog%C;QEuCv;=VM&*!Jnr{)f@;Cx}3_9flO`+DM9RTURp+j!f*e*A{e3y+AzA@@? z({buRO(xeB!%UWDB_E`av$|ASQ=B)A#}4`Q(ljc|#O+O#lz~!*`%iaJ<#1bz>k*E( z)1rpA^(M{RJEnSu=yZ$Ys%7K1olQ&htL9&uJj-q6)HC&W`i7eJ;k;*l*i}^^r^&kC zzIqsVzgSgDYar>Jy=$^t-ueqX?V1gdjLEp401FAtjs9$LRDzEZc1t*tQ-p{Sr{=k^ za1N83R?cvriNG^PA`k|YiScQc-oo&9NBxMXa4s4Y6tZ|A3Y0S&93yUg(2wmaKMCk$ z%Hm9SolxUG4-DES+eIv>=&do)jcNR0=v=6BRGxRc?AeG%v`Rt`u6yZobuIZD`>Zx! z7>QoJ^Qc+ae7*(GDx3;p)H*Z6Vl7E98||?A#JXY@%8G@&B>`$c3Ln1cdW#_NbboGl z^kx*(DDGnQ`2BnraP(hz+jUNI2e{SvEB^6rYWQMmRQ_Oy=# z+yl=lt6haoo{b~7IdqCw4}bVXGItlVDDmiO7nOk=b46As)#BiO_TBhZjJ_$jU7=s6 zjBhG7})fNyr1I7*ewyC};`k!1i@+f&uLOW20A1s4GlM?>0z zh2$d;f`azrDpt%StYF0;#1O{d!VtsY1S;fwr_dM@rO13ZBBNZitT(DeDcTXC&>uF- z{7d|#Awk$M1W@y2pplLI77ID#E+zdnmmhMub7VT=K&DKonts_?5pG^ zC;M83u8!-J?$%Hj?iEL|pTrNxPY>P8C+7~E|D=0uU5=e(`t-v zq~|8PsT5a(+i#Xgs;iuhO*DZ*Vh)jqc@5ja5Ma^0XO$kV7i3v}3!wI9;mUtp27UGe3_Az` z2NQBj1%PE3)->O@C&CIKqv^dgkyT@)tWoKi@$2i$`bcedEu7P19>9ZDtLNAYEAoLn ziOwezzzEnmNjU!42;-a=<>5W3>FoUw_G9mRhsuw0hvbjK_wC9+ByB`q7(^*)!Nr&G z4d$na>(~b;_l>W{SI5Ai5h=#>G-&(HLKUIXHJ3vn>Is=#ZDLEjNciU`FY}~_v+(`{ z>=4C<_3qBeEZvULO4g!Q>S1Ybn;ov^p@mhNrk7u@=|MbbtHTOhda@D|_CSF^2;^1dKJ zQT8o8v8hwG-o~4<5vX`g#!$G|JsbF@lK9feleaWK5UO3NXItqu$k_(4f-tXYlX-x? z9Q`jIqfNC%lb<0)tXm$6*kUrO##4vW5sQ%>OXqgs0(`dcrj$~PV-V$0B7SW-> zS-0_F1+*&L<+#G3yO&JZl0?jBSKxEB_oB(@5Y2|sQ7GO5MAO^7_5U?*wB)-V}J;6jWT%K#`n)vmePvoc)# zGQYlZ@ikPzKQ+nqHFXyf>^#||Dvweps7f}nS@a&aBCcj^3S|{GayGkvn8{!O z&lmN@1N3(_SHcjHF4995VTWn(c?z!Ul*y3gv6&&idGK)i0^mBV9of^6I;{T)Nvvo%#d{%rpBvNJ;2M$n zBTc^Q%mcss-TSo8?Mp-yKKni4<(3Gcj;x`^AKj&+n}?t6Di|lU?-*8hp}9lU^Q$uP15^_oOClrZkqy=dvfaKz!pf9BIFdsyDxnz{aRD<}4Iuy>>c z9Mh|q)+E|5IEi4-)Q;r-`sr~!fI(&1kAp~S#mL7`?%9!43$Gx!YlE_VL!S&+`}rh) zK#SY5U2_mb+JJ%#T>Ri+*y*4L$7oXlB~77YMGTLKdv-PG;Rnd>NWb>|2iiV@Dl_g? zS5@76ysfVLS)m8jlCd}E&D{@nMzJWeW8W?TjGB#{0`Z;s{mE@F`g;t$qAjO2Z?-No ze!B=^R-hZm>&Ul_F}oZ-AJdv_XUW7I`r#GoUyEIR&(G3rOXJ(e(QUXQjnSOO`e{3q z%FcFWxV0sgR*nx66O^VMRjSNeToog+y^To7#9Jvf6Hr-wCf((IeVKz#07RU$jMAUN#3(aPaUciFN$36jHW_?5 z>Pj(2$CpZ7Jg9xF?I4$@E1+lDBoa(HDGbUhrBG8XW20U_gn*pb7pY983g9H<((+N; z_`**;&~PeyL^H6!{k2+)GA`uWxfLfF$WqDpKOQma@@8-h8J3#^pwid z;N!>4>e#7POxlBx-ArhHWm7M-MYQ1XU~sbKt`BEqZ9iIr3tHFom*W$tvvZNE~1jeyxvW|`I zSB_n0Y@c)|PIM6w1PuuI7|79NE=pUaKgb?O?cZTN3p%EDoy%q1lVyeJoZx!69? zc!EbDajViYlJLSBpK=O>&?2K1mC?0+f1bSzq*QE+GG@U&o4=w%K1>|8dt;jBgDUjf zxkB-^L<@%az8_e(L>pm>6p#|{f)xZsgd2BMp` z{KZW@Jlj1M)|=J27X+&-Yv0Zv)Vc9nAM~Rp^+o}Zo$FeAU8&Yp(4LHA%}TVqCg8B` zF+jbW5V)EWyJ~zo6}l~xyQBh~6j*>(6Hq#6>9PK}m=MUp1-`z6&>GkUpC!zsH8Bw5 zp(HEBtTh>VYd(fj!aW=~YwF#~BH=esG!4-T-Hf{1v(z%Lg$4L|BZ*2{-vFL19!x4j zbw`~-PpF&Y8w!vraup2%ry1RtniqSQyw83M0uGW!z+Wr)tiB~5t1MtXb-x)Mu>y%#Si&8Ng3Vzz4S?MEUgXTRVG zFX8%8lJ{KC-{9%1!LU!`hy$Gw_Z;jWSB2_aV`Y<^0p#J*!}a>QeXJR$cAKk}$Asc` ze2P5h2isJpafDvu7ij~*_}i3=N-K(Z;r6Dad?QGW$zY_5@rO<^4$v zwe1~i^d0CB>06$z^h|$2C6=Aea$!@{;nM!mPE_d;^wt#?H$LCfTIIO7eD_@-Te0g&s=DiGy z%9h4>X{Yket-0c$kGa16q2!+)z&MPMiRS{3lgwIG5^RnS6RYRk@mg2~qJn!l0W(PW zkq~mob??EEHwsn6<;CRD1lo|IWACfx{20&?e!bmdow>G~!ZTczYPM`w5lI0AV0-grKQ_p0^5=zB!xc{c;1347xMEupAnYaC zf-6mth=u2~>#^o$km8YbE*sPIko5#9F-0!Hph1+G^j-g+;;^D}5*#TIrobuzo#SXU zK9;#0Le2LNeR;PMx-v4awUcx=1i`&r-s7qy0iy#**HP9D-8~qoNRsWjo0e(ddmf74 zl6WCGK(4$8F4ffo(lnnM3(R3^c}Ljd6(}Ocfa+&+ARt)m0~pbUf*+%0>g5LjxPWEL zE>@5cuIDI%yCNxrB1SM5!F z;M9lTJ8EIRLw(dJjm4>h-pp0Esae4j3szBft4}aCMNJv=TNB1U*zj@X2 zO_boLXBD07#6*0K@lj-1uiVtzC13Do^IM05p-Ae>)(^wx*Q=B&ZKKZ31NyRKhYQ;I z2UDZ{bq7@4>4nG|O+)83F@%CkyQD7iET2ABW7=?lz`22`5SSHpv-Wb_jMalY&kcxj zEBl7qB`=#QtFRE9>bc3azPA{Swc{nun|WhFkx@yPT=v3YQO>7g5-@C-Q|l}8W^81` zgC;;@O!rCNZ>|iJuwU@W+I}!<;DF)2yV31D0kCiym;g$?{o$&)8?_N}((`Ma)Dn;> z0IA;r2?A@N-sdncCAygTl*cp_=X`ep*+kOR)D!_nc1Z&&e)0ovy=gv&)YaV289mt$ z@f>o5#Gk70k6h(An0`Q*dkGf+3l_5zeiMnbKV{xuOD=1>Y;s=~Ama6CiXwV%8FKW+ zKKspQw+sP>(HEpfF5)5QgU&{GO?K{=pf~(VMBY(PwQcuf3=!sI=^_6VB;ojZf%@8u z+Sba(;l097_<(r;VaWqAE@)dmd357i=*t(@rs$4}A=vnq{3Bgn-v_U+OmR$;=x z=uSE`sQc*MAYGZFisy?T8;Xi(w9KX)W*Q5MeGW@cFI|ZROS50pe9JQ2dvaCsaZRx)MIPdEPhZcX_Oef!n|O;|4O=g4)j&x1gb&oKLAn&+frDSX~q%kXYhz4**z*3nhD z6ivp?QLv|Im;0+!1T4>8R6w!Fu~r%FKgA>9I|39_Urh$Rb=?=6!gDqB^@${dr2U8x zzd2HGe%^Z%OU<)3;x{+*>?rSn_iC$jH=VEit?DUvliH%wcF66i2Tdc0{qR@d0U+}Q zxH0S+mYVn9pYNcmSu!=WWhAraFW2jFbjp+HF-ov|OJPMrBRTFK;XD1+U(!1_@1cM# z(`B?z>9g7worfNzjE?#t3p9sp{|+CarQdT)0PhkNh^%+!7B~GS3NZgb3W6IHKS=86 z(jHThTPx88407mNr!;ENGIXpk@8$(gElIWQ1>w(1?`n(W$eBW?O!XB4I#o1nRD)6L zkd%gh^@{sPg0BI^aUrOBN%s$E6_Du~JVc|Q+J5%9Ikkkag2AP{X-S=&cdu0&Bhg52aM8w8_UeAzzbcXHtkosVJg+WZg zti@#O4{h)2w`*ytuAtkrv~ydl-PPkNnEN)TlP* z0*^lS+D+ei>4GLrOLv>(L>B6~F!-~b1tAgX^rYkqA?*tT0{%(oyaNU&eF{k~Bea^> z%&Y=SU`$_!e>%zN!`4r+jW|#w_SNFqbnD2 zZ|f3rH2j(ZzK-6Yp~2>rm!!Kn4nvzOfs6zO%Y{y*dU>OL5E2Q=;xpcyLbMY6I``RE ztwuTljB0>O0f$8n`Rl_(yV?Ew5{ulAjj~3rlZCI$x-h?T5C-|YX6iJJHW&$(Ckf{9 z*~!pINr|7P#%y0BI)=`qzYT#q_H4ZMCaIhpSF>wLu>@VD505iND8Wfr$@DwD^3TZ7 zcTU2}r2}$5G_9!!R%f@3+>-81yxTz^R(W}$W$kVd| zUd7+5!-t1)Z!j-xtQTF{bjvjn#$fHs!t14?Dk_hi&Sf@~-J%S(!G#vX9YDVR=!<~a z02j4q$T^H%p}nGEMM3;MTtSe1Khw{L)wMX1+{BV_AZko@l}_z?9%MN$$Z^E4{PJ%3 zdL(04p)k@I=SK3MonkRSR35;uR?6C@`9&2!w&yic*8`RlCaOw!EE`ssTOtF#Ievny zd7-&Gw%TE3cr9oz2jGyF{j4`3J-uRfs7UDbHt4=scWxmQa6xfWKx?{&O~`WJsZXE{Ou9{e`u1N7eqQ|E|^M;rxB7ct>uu=3T; z2Zcjy!eDh$qLLEwy+a^qy9D~T$&Vm7t){ymINp|JjH@Qh&E|>1qTs%mqoNAMr?=2* zvnEbAC>*RU7~p!CyO3@4s%B!o=>!qJYTxu_Ok3fA;nz-r0du1-jBEI0W;xEWr^8v<0YJrGK55D=sK$Ne*jB1Y} zUaJvhFpc>}Sgr{y*H2f9{^U5z*XIMip}9_syuFH~>iAMklJ6TqmpShWN(~6zx>5cx zBEAC*ok?Uf?c{0vFK!Ul#@vgySpDeoMz0u?0(H%dp$lWV81Q4v?6ZTwh#$wvF11k2|Jc;rZ{FH9;@K{xC9C|oBRM>B9UaY z8do@;S5a9>u*n)e2Kz~w3M=fDx+rL1ia~&tysal2dR!i@p>ZtWP~Uks5-m+lm)%*i z&ips~(}_aiu!f)HPCfr4t$taE#0MiIWtkIovV#$w>TYdeZ=xFZoFlIyv$k@HjNF&z zghDYf;QP*E$#GKiawpt-w?)r~xLiwP;39oFFr&iUjb~qvgItJM5n}o+)lGDWh|E4$ zK|3FPcp+{4TP658i2?85;yFi5_vih&{G#sAMjn>0$FIt~c&F5gJ!!?nF&WHv-b&?*fVcj6BA7K}QcbKQqsnntrTuW8_-W?-S4n5OX zsgt{g`ul>QQ*rW#1b2a`3{&bqx{nSM%3Ei7XH);>jLvH+5)u+mjpaIIJS6`g5;#z< zebv{otd13B-ds6#$ON9KsJBDrL62M;JNdOW@E`&0ZE2C3x7bYnUVh$;oZka~1lj8? zmEIX2%tXB+_$6M_Mgo{Qp{!Y1T*I=U-$sF2lDwSA{#8?@_EPze0#(>Za-9PBT7pl!`0=nRyc5?R220o*H%5IX9-yANhi1(wkp0zE<9idzh>CWg5Q_vFyeXYV%b za+|pZ=kGs+K+{{b8ElLiff`Xg-t?4;pd-{abVN&irCEqP@)vmpr9~Le=${~W@r*WZ zfi0d%m(lcU*%}u`9M!?WCPC`0`bhG_VV$E&0I^`Lq6OESm4+pr0vlMl10Ug5fB>)U zl@hl>6n}Ipg>Qni!NNR^9iPiEhtL5YCR~V&(C(QryLDB~rESA;rFCDCO*p$PO@&nxk8>TAhS-GAVY8#%66yAFkJqk4+?mQGQbOBfuM z#LZv79i?h_AKfa_;WfR5N&Bo;4NLHk{RNxgdxYmgQsWMm#F)Q1Jy!Sy_JUWAIv){X zp=u0Hkd!FG>s(*BT*OBtY)~h=Ikbs*qJT27sIUG738*pE?ksGnkiu% zUnp9a#$PU4xB85~_jJE|Wf$i6dn3nUgl}nWZla>8DF1S)Hq^52^7C>ctzB4Lk}X#Q z35cj5?QYy!?za*tM?Da1|T&yaWdcXk^wcK4;`&b_e6bA+NScu2T}UKp}Q z&7j2sE^>bl42}keNaW93+2lq)^;`Pr@l4_;6dL2u1l^lBm#LMAakM-0JrRcL>3j7UE3)w^zX+fVgu{hx!~Y^_D5l2L#6gKo4f8; z$;sHx*kikq5YwEH#;8DxBidf1$)RKUQB!DBUBQD8cW;csk}b9%#8Dqqrwa`uF3j6C z$Vr#Um+wFDc^3hn5b%N!9V%GTmzI@f$gvme!#=%s zWBuZiQaFp~A9+^vrIZX45>8k8ePc&D2fNRI@-~;hz~Z}8$tycz9PIGmCmaKU5LvPs3$L48I_1qa` z1T7%B!JEh2h&QjyA3Yn1^q|X(uj+bSb7aEmI9oO|y++gCkgs1!(n&Dk`iCmKfEkfJ zikmk2a{~l|;-TSK{Lve1GkcZ8^wW$KNy>E&L44~#-@*1puon*ub1-?RnOmO&^Te?D zIxH*#A{|+B+8(Y`gW!gd3X~3d6_%D_9<%L6se|XC*IkLRKiokt^0lQ16$YpOR4yW^ za*wR1zX7W)YDt1Uo&ojeM%22(LP4Aj{(rU(1ejDvNYYvzIP^HNKUT+?N?Bc-;&W1x zS5pY{kDA4Hg>|utyU@;p9V5{gAuk1SNIPV=%~c4$9_I#MPajJPJ%)|d93L_9+CHz+ zxjR1?8$w)@b*+7sQoDY%3&`m_q>21vx-T&8dV5pOZDEqswoX(HOdpu&Pl7>x$=HEe z8ZWhWBcgZPnVtrg+puUKpI1+x+7qQnq903@TrNg9HS}ppJAHiy=(}~ z)3&2T-h{G81>I_1V(V2fRkdQ=i#cDnrpm#dTnP(*%Jn%ETNa~Fj_8r>RHqQLn;I%_ zFkCU^j<#Our|AqadR^)Hvo838Flv6I>}K;-0fj+jKuwztT*Z_{5|{tua!obDU)ewe zWW)T7oEPQKrgKBp6Iq*`i)7aP0Ku##dkaJKke?PAAi4j9x40v8B_%WPIzFX$^W0PJ zg~)hgp?0F2+2285*1$9~g?5$Yo0?l3pRO4wL%JlaHHoz(%G(f@vjnkr`sL+99i{>* zr3?$Uxw;E0Gm;$*Bl@&7H4KUZy1$quoK@o(V z=`EW(ogWNdcRxdA{X_dS41o4D=<)skV+)q@Tn+21qlBe&>+c66C2wIn7+vAW<{;=G zHxtoFS|&fM&-tdn2r&55iiH%3)a)r==7}0=zYG!3H#R24I8pNTfb8uHM77Zx*D*~m z_0*Eh1F6TqulZQWB8-km5elotWI{@j?#GBg|GqN)j~r%bsWOf{gmhr@~rqOiOYgl_Db*cPVhyM0=(<4yYhw;G)t) zBtmvY$b|`EA~u}-7!;p;Q{XzNHsUa=_F%?&8d{o)t$iiQO>zWb4w*1H934jKVv&{_ z>}JB`zdmP@f(+f?th8K#@1hUl94#iI= z+rnjQO*Xt%i3xfA51061(e`9pQ$Ipjz51hK+5MH3aNzp8DR_A zfMip$K7c!TeH)aHRFaM6*up|(TxPKen_D19wOM#*l^({xhd;t1V)@z_+Gzs0PvW9! zs*lFnl88xu0e8oBg%=&Q8+~2}*SKwI*?j1$B>uoZM{9uW<|2UN)fSLM^Z#Qy6Ckd< zd5m@P1-jZ5>h{xe`Q6~+dc~0$FGH`D(Lfi{)3VsCY6w%yXg-U(nO;G(uw56zBO@gy z)1{S0hLJTFR0pkbK{+|10b$SRF@zEPzQGF!UVI6}*0siZo&SN$=7x2YsmT_GRc*!> zTUvSY>T(J}p7R))bL?RD6}eu^HSCP-i!cKUJUmLA*Yb;kL_Moln9^YbID3fi8v5_rC@rT4xHFM*R4HYgOE z&jDRCO0ygxZaPKb+#1p$Vhss|amILWNRL_?o1TGK>n`^G@{=zY)BlwoDbhKeK&kA*k@UN;t2b*HHO&`e$vQUf# zFX+C2&W4IGd~0b8E?}J>LNPnIR^+HMtHzb)hJu47NgP5Lv$YtaP7Huk0O%LDvr!6T z=0}p!g#5AJJMtTQFR%-&*C7{km{2)6FWui+XB^!qryb6Pb$My+ZBR(3HU}9vZH2yM z2KtN%29;o*1@sta;nQQ7sf+i#E-yi^>=j38?=z(geYPnWN|X*;NrkAzgeBTyauXI* zV!uJ^ZA@-N077wGQP|gCI(E^#!K>tLz?{OrA!VJ{SRju^>O8U~|t6 zZ1`Yyu*6!d5ojoWhNz4fq>3dz*r9|=gqMqmbF_J(p=`Po2s?t~K2SD_YpKGGfvQc| ztcUx;KXkJ=YQc(H2hJog42y7h22&dKo@So*ez`LNTRU7^hb9QpL*KVZ#h}fI=DOJB%m*5fmXuAJ-wb z4ZPEmbZ|U2FIVqLE3qeH|B*50-S0K6_g83@z(RZ8>a6x#XjzyL=6-x7VgB<4a=%j% zU!lw4VV7MxnSa78;Fo6kdzJGQ2shE)NR2@LHh{l8j$i-x{3I8~G<_%VCOU=nJtPi> zEI5W34+`87gs`m$#)D3Pyub!InkqdK(eXhgc`@oG9W@xd_7M1RbQZ0u&gXXRxlGWt z$5<@#dvSlXCGaPe3~@37+x_|1 zk`lSWqW+HdZ*vOT9!l=q2^{>YI}l z-=BVMEq~6G5Ghs`kjNk*@UosFBfJ8;t|c}f@g7(S#}zT)RGWnk>rsAl(*IT^>;#q_ zy-%hq+S>*=0l1WUFa&Qmc>cJ@e^-GY0**=bhZx95uPK`5bEOqL!7N}9~@=+Tdf z$E8uzitWI>YRPuFE2-bdr@wq_E(O^4MZp=CoU$@{&*QswL$>??JjtSbz(eJ`2nXFY zgammT2sa3m2BIV~1l0f~NnbD6KQY3pT2cLX`*An{YDheI1Y4|RFm)&=GwSm-NJ`c= zAz~jMhDk&ALW#l}Se-&SA&?egkkdTuguGHiDw>h}FN@N70W2N5z^6AlVTx&aBD z6Qr@Z?Qakf?4)-!6m(Wj1R{mvYU8o1ZR}0qUG>r>o#e*6S4(En)u7*<`4i&)%WQPk z;NQDFMOkf0YhxZNc4!eH%t#MjTcB%(_=M77YZYcNJ1!@=m?+|QeZ^3n*sSj~n6qDp z1%5ry->n8;2)_k>sg3uH~qA|04u94h{{*^K_58XSVm?2axgFi_h~83EB&o>r{dw!p z8M&R6^GTwk-2}{YY>@DC<=i_I*SMjd)F)?h%%eq7MCQfe1m4#NwSsg*%u$a~#6(40 z92_GJ-)GH-KBm>ZyK%O%v^_91PyQPq0n^jZNqocS7I`kK5B(yg4COfs0u=WYwkgKk zSSeDn(8l1u^x$6(8&veA@;1S_!_M>hd+*;DKu8$wi6S=s0tYD(24EoS(^Sjn39MH* zun-a`k31DTAr==78F0o&c17E!7{(n90xiS{`kT77H7x(X{{Jq9u z{ppavdX9r4o%0-Q9m9sjsbs)6VChUw)**lg<08p`k4jiEVUqE{s$i4{Ho6mhFL6-F z{o(<$k^h_&JL)<3hG0%;F9`bYFaP_38tgX92+$D9{8!-q`4(ot6I_aj1tcz_tUuWD zc*t{r4bd}LfE1|z|40EM_p_$NUx(qcTcIQ3wv7ew17mBQ-i7t`F7Kef5AQKF$cvfg z%V)pRxA>S!A(zaQw4a{-e$EW@zhX!3mkYc$D~=bn&f9O%Bxi;~PptxHC;d>E0mhav zgoK1&QH!&g@C=>9^h3T7+WawLp#N!s3t%fH9n8j9ItvRW>|1XvuvwOtm&Y9gP1&D2 z`fPOF9k|_x(T>3b=v3_nkJAPGeuMui@SI3QN2N%%_buOZ0T_|QE2oD`=j9j>BM!@q zSupqG!K~8w)43*y`t7RI@Cnz)FTX9szvV3u$T0krI@xEa9x((426r^Qf8fDCTtH_9 zLgflTE5-X0?{y+?Q%lJIE&P{|Ct?CjWq!fpO*nS6+P+hteG_@G++1C3TNFj^r~Ceb zs`YM?U#bS4OX1&p`cK4pI|A56HqhGBcJ`x;yY0HcZa(AMrq6b{VG?I`mre)V4BLOn zO-BJ{=sjc9xw$*H`q6J1)ufi3$z+mHK!E(r0cZ`&(lk=^@Am><8{LBgC`F&T>g!eC zpR67yf8PVi+Gv$$dC6vZZH3LSrGNRItGXsX!H69R@lH#-Il4_8O+J6~0m4uSjsX69elAvD66+f$LUbpurBLMz3q zs>Mnv0hN^?pJe0R9t1TFb(uF@%ch0Hq&{kO>6(S+|1X;*(KE2G7 zg(Bd%;oC72Qat2g(p&rAwf7i-Q-+MKl-0x7GU3ONhYPj&KO^%b{=GPJ@E^*eV40ul z->)tu5X3ZH@A7$gIq94)ZUiXC{5kCQ-%;^Dv0ie&v*&;y1AVQKuiNOxikD_)R1)2% z>He=h!UgZqj?A=^n8LFHOIq-s$dN9lnmw8FEtXWut*c{WuC8HBt~5%6pYcXIg7gAUE6o-KEXMk z>Ij9o1FSj)nDjB;m-P&Qw8b1OHOesoEn2a;>^mb0tTsnTZ{CVBfo_^UKLBU$T@s`js!^M)x8ch}>3D_4;-)Z20-{ zL~B0)IC1Xh?eo=!>y?k-$wk9$lc}s?Ty{%|UrldhH)ZIwB6al>;_ zUQ)kY2*epzrZag?NAQ1%Z#*UNqHNI8BjPZ_Mk31!q$IRol$$AI(2 z;amdH#)8diY!DgLO+yg*f4GnT=wuvfzpOWj5?1t4^tez=&xLDF3W@Fc1B0_fRaFx* z8RIAUfzrE!FM@0W=;p}Kw|z6ugkHejoD8*W_#=PhhbARhpoR8!@bJxC(9N%}pH1-i zm1pIF@vGcNxgK|;T=y|B`-~R%1yrHo`z11=R^LT&m~-*W@zCMbSW!TBoBl#fip+IN z^fmYTIO^>_^eo)UkgM+Z2G^DGf?0uRo0-(ry$2(>l&btg*YBOQn`OCOWul5%)Mt3Z zY9mR=5*C;D`FuFLzw!+bh>@(2Otb{s@XFDvru7Oi#D(c-7-SX`GY%jb!N4HoOI=kF z-%v?$8~#2n-ykN*+IdTX&5<2hIUfp6)d2}&lZF~u(__Sx}MK|*F3!6 zlDX8iNVF`s)iV48Yrttte zRc_C$tz~J#_YIh*=+giV3raH0*zA@#_)T!X15<(&$8O=WEs^i6e+Fk6K+vXr05Hl; zH{Z@b{iw$Io$~ggu2E5{cq|^4I2w92t}UPSdTz~xB<7BjW_fV-K7CSbWp*2ci+7GS z75avHFz?RS6T5)DGws#cba0TrSJnqT!S!kxNhT;r3PjTDatreG6|aHnpc{HR@`5@s z|L*H_OyrCB$)*j8Ugf|S^`v+nMr5kjY;&@p(~D(DIYkw>s;A?Gaorn!T{J) z1X9t~G+zZipk%>7yB1^;^Z|fOa|wK)IRlE-5u-&0<0^tSxw~(olB7tvP=ny%#nnIkRt`6%5vU8qG{{bRWd5RDK= z?W$czeKK5CGQvoqxXwwcWU40fW)rO853Tm#oZ7ui=uvk-$mi$ca5%yz!F~Gc$E)L8 z-&9jPb#dn8@f6Zh63^c0ifEerKC$F zq#L9|K#-CUkXE`wxY`DXG`t-?x@wXjEF4g2ow^fr0_n&@3-REx-+dGYyp4KpNGe9Li7ZLf)$aT;Jwjb?ZFAeIq-yXV{Vf8s7-SVI{Qk0228wm%^y zC4fW5A^~n+v7s#TDXBBjwD)8@`=0A7-+e*EME^eo&!+{ssiOF+&XP|vuA>MMU2{W- zof57A4tLQ=+WUfYY)q@Xucg1}gpn$4dDA+?1n}sGX1BBi2MQ~G7&TU``XOA)w8{1b z9a+;&i163O&6OD`YKfLv*30)qR#Eh?#9aWSlUgMe>+PROj0=7r$qdViE{aL+=4v5X zTa0is6A;#z6Sy;lqScU9cj}13WH8dD+xljF;ZR^Vf*;b4d;TsJs^AxtT1|)bU?WoOlRXTt0G(_ih9G38 zWZtwEJsrek8vGp#&+-Fm%a=zy8iMj3efgR)Ci75eHfCDDCUZvlAbpA1+$)*$un;1( zPx>7nlN&V8RRk@{P}f(QC~a+c*98)TNF=W-|JY)Qg{uk9U>cQ5F-NhRYIXl$DPdGR zm!S%-6?LrGrq$@#is|rB0>;?YaYBytODYkqC~d3ozFfJjW}egrUeFg7veTCQ{jJ<= zeY*5dL-S+qxf!md6LAleS(}h%O#p{F7EvY24B!<0dtVe-ZPY|KruVW^Bas9t{ih1B^msGH66a={%FmcSEWLtM~n|6R8h$#w=eRI@9(EXSJ8=_OTd?})S zn^otQu3s2xA7;nLp;He=+&kHM(yrK&842CKs19LsOMNB^vRd-Fj0i<5MVpt!m=xlE zwXaST6(%prxw3*^5xC1m3#&>A1{T7GE&64S;lm~ZHyrT_LME)4>R61hqVaX_h%g!a zvR(q!*d*p;^>yrPzs&weAbtbO-q-VRZ)|oB=PE@rJs?saP<{&;0$1}U`3(&Xqd97P zzMEPNtKwP7$^Wl)hoky|v%p5tvqk9pu^to0LMD>^I$#$Tf_<%CPowTyY!YYvIvD3K zJwJRqY#e}(DUz0~K;^Q^d)5Y=cZw|{pjG$AqR_3mMF|eSw-{TP7W=(if{Al8rXFnJ zidtk*cv2hWQ72H7&lOvl4>2Um7N}cJb0%U_sgT-bG!a1Wxr^ZHpoyP>un77;vJuXC zV{Hg*YdX;v$dFqnC&LILWxEBRXZ%->h6aO&5v3c!=6F1a0stsF59nCz7`UL3lS3ip z5Z(Xleh83YWP+EAVI2-@df_1zs(~Rem5OOyx#Y$j`rMXZH=7*e(OrWtQ_8!UR#Er! zNMz}J{V$Jb#*9DfRkED!te~>IR(q*26&<-rY8Aj&zhfzC-)Kp%>hn&11P4aMpaSg- zYf=)avh>~qsM(IlR(t(Ew&t$===|TXyyFKQmSt-)sA*@IoALqW3OVau0ePhT|6UOM z^9yPh{ek>nEvB#p&(=S!>QI?o(rauYXgB(?_DewB}f9f*U%7 zDmboe6?GmwE2&*+bym2gKuC0;`{=pFQ0;{;WKT+{%F--QXL8u(`_wh9`|vfa6ivkI zpXjH8mDraxn|W?cb!G1`ewzJ>bu-f>_`kIx_o<`-X#z`Vwex?)F6jD~JY=AbxYJ}- z9`-FZEZoc=n9Hb(RSUI{>Dee>t=V0!UuFYsJ}Tmd_F}TXHPn8{@6u zPkrtoo-75X#wEWfQ{m0lv_L$~!c=ScTtxHRUs{OWNvsk^)y)v5evhFs6V(3k!$W5~ z50>h`rC|H{+_Sy)a+3QGf5;aWrmO4UnoaPJUlzn9h<{Wmui5^*~C0s0P!-{GCAT*Pjnx%TaClZq zckcus{H1Kio3eFj@v=PLp@dCZ_J%P_L<^mpa{k3yc!1%*b(?u!w@Vy?&c`HXP42+v zB-PmznNQrMnyNZ}8>Y{=N*l7?mxFTZQcddky~OlXvAb`J11@eHi;-MkuT}Eu+-2qK zf~r)e79)mf_S|f?6_L(tk!RHkH8q$_l;2IBm$s}>4}N5#a0%$z@l%NYrFU<@`v*v_ z3=W89Fh@Ryu0!j84!ZE`h+4QAUe;Jr-kPQ^sE=u~LMtm>`cK%bkT(DQRHx^kN^-}3 z)WDgR02+#V$ym`Bj9eejQ(dokI`g837(VwxKCfXirWekN_KGTcH>YV^G6R3HTjO{R zcWn{gna@oi5BKD)Yyc|kJi2mCZ%`oYe$Jza#lAdEUp)7%#KrTuk1S-~5w#Bl(aXKt zOSCZ(p%}b2BFzqM$;CuBuiox;A%L^Cht^lSzca}Rq4B4D`@vUH()MmrbxH~!V;goL zIkPNuBh?IgmaIvwF3kJ8GgNg0X;DqcSTj%vwR-k^I1LMxF`? z5{`|cT)?NDpnn75!hcAv`&hWS;l2HbgaJ#fv33u-5d1r+7$G?VQoqK$(wRolH4WfR z)lux@cKAp3_7sZ8UKt8jkPmmkSxgb4MQFyEf6ZsHW5<~J<@#+z&%1{c9(BGFUX>1jgV$Xnw3H$RY(sEo6x13U#2l@P=KLkrsoa6s6) z2h)4`pQ!8%2Pw`=1_-q3h?FXGh3%5E)*4uY(!SK&h;n2O>SrUyi}j{X^Ek+x-!SbR z4E&;pG>0cSUl^plM=%|zVkSk^Q&c?=wC10e0? z$i6umw~Fu!WY1I^7}~?1^lPCU$x}g$EO@MgKl;Q51)8qSilt$=&qhNojL5DTtPG8qx8$Y7Hx8{I!C;6FCjm z70CGCUUz@q>yK~7U|#|MN5Iir!zP!DmIP0FHcKD=hBmGkY#fpz3hr@#Y~yD)XnFW4 zRO`!4!E)ojlBR@-!I+%`|40o@-ZG4kU?6j%hOX3>iYTJmMum7%(z_sr?4^<%XnyH) zUUbOE63vWYI~H2E+QWr?0V&N%!5=(8*lXU_#JLLeWnU8nxZ^KEnB-ZRvRK0G$MM7_ zDQIk|WiRPkEB-i=^!!IW=!HMehESaz{=+vv2YJg~Sy2)j|8|W7q*3;`^JnZcZLYx? zBE#X)sO#g8`Y9TP6#|2*>QwLWcxGiTlaj!_@4W_flcha1CC~e#fYtOCGHLG%12BC$ zy?5#E&bi%zm1*2_#0|?$pZ)0jlFXr=v9GSjP%d2a!Ld6`nIFnyW4|6PyMW= z&Vw=Dg0@#~@*jTwL-M&Yk45~*`5znb!xUK7S*!m~k2A3zuxFnjL^--Ox zss-Ug!57rcMxjqYa$doJV;G(a1JjtOVC>X66&hyl=cIAXU~I`i+gLinzn*+9UX+Du zoei%NkME;B3h%X)8N)UZlpzR6-|+mq@bWCY8e4FC)5K92Aph3qKQ4ZB<-Y~|0gv?e z+f1Ux>(tcDt)H7ZEEzjzF5UUIE7kyV>bkhV>WM&W1(bS~Gti#dbjaqM_MzwsGa)KR z<*0sxV0(BOA#4%Z9r_F8|Mq zwWGXqPf839pfGleA{M1qRlKocmoA~kR^O|pT~^8@*Gzi0E)x>>E+Vg)lz+L`S4TOo zy`Qlm`gK*F=x#Bx6JZ#hgmT?vV4+P>ORPsti4kKS$Az{U=5?REWv6jb1=n>3} zT?hfy{}C!a2G8gZK_;x#f1EowZ1MvK&`yhAWa85Z?YBu+Smak*UDMY;o6=LD5y+BI z(SOrA%1DGGz^aXGMxQ1p-OJ8?!o0c=7NPNBy-yVlldk^dQFf3=`L4uIJf|pk)b|

bhUX!X_w+z9?4i@h>pC;NGj*PY2HM?mc-1& z^*VtrAh?a+v(b*$O{w(`c8HL?U%4os{b+z>YhLNW?DwcJa?nHB^dFuqJpRm3zl-t> z1RsRc!D8~CdV{&ps(8#A@jQptf-asq)U%yC` z{DbHtSHDgYvz2R>b(*X5v4sm~F?3r`z0fAN;x^=SwzxJml3BJVjxpOy3zSQdB|xR( zTN})!0bekA?yK51>x*FPDY>vU=3oI@JoxGM#4t6Y{o8CV#de)+?FgriTv+CB?juo| z?1ei=)K2Q!7dCkCnmNt9X*r&$7?@~tWz9WahO>eM%|`z|GSDX%J6A0e{s??Pzytq` z9Ev=9^>2mg-WzZn1D4#3U`SprXk;ln!gs*L3r2k!fsPyY_h-F>&yk7Het9oSD=RBV zZCx{S5hq^E${`u5=G^XItcnK`N0G(pgi7RUS?5i7d>qrXip{zwK36%~bp#we98?rY zGs`D^2Y2mH*tA>8V}>YEQolcW@ReBwO1ba}aa25dEMNcvdqED;&Z z3hi0iX)nz9ME>&4Vc*Ft=8|Y$re~Pa8EJm>qF}|>6DhY#H^m+{SQ?+~;8SFbH3?*5 z{3d{STv-k%B%b^`Er`J*>~*ih4_xqpk>na^e;W(tc7GjtzZu>%E}Oxp9Lc*wpk8aK zu5$}ITYLkVCVMb4ec*2O>9L7FUb{lihe^Bf9jhm`%}etq$%T&E-sBgw)yYGPTY@s@ zvW{clvhEtS0AjFcBFZiuyj0 zxCaL7k+_u9a`LJvUy1X7WoGhonYk0?{Sw@A@l-H}W|j8apU-pXiFJQJqFjS{AM`TZ zFmNFO(lXJtpnL`jbl|sm|1I=ypA%vTtc+u)@OG`2Ei84GabdR`K}L`qk#&i&L0}$E zWca~^(nci0s^3Ai6=1akNw9 zj(gM57o)Np#s8MOMJ8!VDJ0!REVt<{Udp~d=OwR)eLnXr@Ro!`eVV&!VudBgOUm z!Km(K9aAzG4$5qbCQW|Gg=1@=M|{YGy1){ZSUV*OWo9BH(U+Tlw^X+;? ztg7PszgZ$9K@?_q_WVf_Zi`n^2`?3+^k>Vo@kHNjQIV5vS4_cMWq_J3f;rl@^)Vi102;nO~j6LGx!PliOy~XI_U#C1`aVZC@SPJfpKftNc}+ z1qF`U6a!oPP4o9^m^wQ&EGj0UX%aq>=BDVDlea5h2?>!#IWNkc2E*r;%!`*lovkWEIq6~2KawOXn+ffhR7?MDFK-M$RxmAB8a;uK`iK8Y>R z08<`<{ju4`^FXu8>1d&gJFj&e-6p#AVX;+wN(}45r-j>k$<*xe3Y0G>f;pPk{aqnA zh(@h-eii_)YX<0nt`3IVvOqz@K)pM!`&r;2>2UeaZ1r#)!l)(asv<>5WhngOY3EGS zEf^lK)3I>Sk*?l)4~>9otUz$ey+zV;{k@$wp9&OUe~(3lkx537xJ`wc-X*UszQR91 zZpfxb6MK>p-Y)ch)kHpqW|ARKRJ=2>7KHi@Uchi^ zelHJ4!9|f%WjBQ4PHxu*TtbEso%*F0HLL&+T7^8QnEOy!yyx;C*~Ng*UN(MV*O|wv zHLo`5GpRReXHMr_O zN5lHgVgfg!I7Ab7YCrh7*ZlFjG*@p`o~^})zrNVEX?<{V1-Ud(y#zdzZ08QqBxzBO z3f`6QgGmDRV01Q(yY9u-nRiSl(FT~aTAd*X0aJX`?}Mo#+32Mcnf7onEN>=~TD}>P zTeoq$SP5H7$=|QL!ot9DH{C6t)baxKYAaTJ=E z8x#$os?TKH5 zp8^@%;%hN3-~IXAuiJYfvJXK&-|5-Nga4a8cMuafyLMLsB|@|$31mw z^MAC^y-U5{;c1oP-t4judUg=z_IbSD6=F@+b8mZ@-seXL!%stQ+m;4r(9!OPSSn!I z1%%wSz+U|ko@;Wg7Vc^@qkgta)>UT0tZnxLNAyU*Fojwd8=I`VrCsJXja8L}&A^$ibQ>tOo?Z^=PK z*BWf-i$>Au%Sd=O1M#elcsG>%^?C*pH&<7I8HOv zL5O(~fz029|5xw*XQd~D^AT~*gKZp}R0>s+RdOzkZ0+kVf)H~%S<>U?ksieWe^VRc@RvNiOQqJ#0!A2YpuJZjF%oSO&z zeX^eJclkyMmRavlmAt_WX!m0Z1hly{JT}{?7vl&bsFuBgZ~V|jx8YmNU^LP%AqMeACNGj%)gP$48kkZIqi}{OYSCKC6n8@3eAl=edrIZU#ePZ7L zH^r$UJ-exJzJ`tXen_27CRJ98LD@YhQ0~vlrXF|AmvP~X2mAHe3Z@^V z1Q%pl4KgZ(kOz8`u0!tfmX%0v|5wdYKC1~R-O0C2>DCV%$Fzx~>%9zHCvJCb2RTz!JL!!`S@uOn~wa~Q6m;QtOO9dFK{m~RN*=hUr z%D79Vn78&5O?)X6KZy2zNxnct^N+Ly0uIfOViOKDw^x#`2kjipw~l(bB@+_c1JiSH z`IIbq%|GXBIgcpK&!#4P$eI<hzSB4Yka=8GDY z25DO96`m#jE1;(t|Dcp_@*jjV^$g)~O>I`^9{q6|+#G#WydryV`T|J(Qg*l*ha{nm z2LDqoW1;v>?HfIYS%DW7Z%u6415o2HU2KekI6c8)cScLM))h!zdX{EDz@k@2#|vuI zzLV4WCUBsr&g9Dtf8eBXEf*GSGR1)yQQYD;2=ONOdPKF3jBiZTVsgCLJt;J~I@h~^ zCc(gM-`BKk+%~BRuy|l7b)VUwg&v%n47!3Tb&oh!jZ?q0d3L5I70x^01>*lQOPg;q zOBbZ=iWi`uZY8gV1NspY zbcGhUoxab3FSu6^Z3>Hvt8+Y=anG8@Gi?n;W&9s64&0sfcxa7Yb8EzEmBy)=PUw7(1!T6q`!{=vBv4 zZy~ptPV-ge+6=#x#Kwd^+MYhGrs4_Ep90H~Wyt z5A)aqU4}LZUz6U-dbSY{{ZJ1A8PWeYIuhsuIyMlz47SYq;Ir(0{T+u*!F*(B1xQN zdj~RIax}~+w&eitl)_MYARqUPDlDy-o^hI6w*Wp^p1Ya}kGFNH(=Av_KeVkAxV!?ymYPJXuT2LSx*ZRjckho}&bAdzMQJVwi=L~(5bdqc|4|B#3 zQW}D)P$Vp3Tjh3G%Rd)26cL1&d46H}DRVxH#Ee~{ilsQ`8J?07^K&f%td3X{BCf-e zkByCA?$YAX6bb(ir~=q@kS?BPV>SbjdU=`PEBxVGr=@~YQ_XqpAD0{_C^l~*=0~&U z8HlcH%-nCqEtEt9WXj4DC!^9Sdq*?Kr*DZk0?#B~+-Z}qO+{Z+7RwntJwDX(!?_!_ zRky=Mz7r=H5X4zgu~8+)4tuc(!V4EGq5aQFE>}WHhDT z;SQSnCEPYT&cAL@NirnnuKXg8`{pPMbG(p3ry}KVla#W3f0Yzus}T;eF@skUh3p%N z@=8w=rW_Rsc(Vfz+|kEc$DHsGI?tVMRs1lUd1-w{tUwxyq;sVeUEUE?M4kPaf$-J; z8W{0s1$&G@v^|^2`4vf(iLOIkc6yCv$W2$FrZFqBklV(0=&dKwx8*WFHx8Y9+9m1v zb-7PAar+iqRfZ-5h^j+LUoo=ym$WOILHyfxN>QR8TY{M48J^K{92egplI?Jm!FV=T z#9^@gEagVI=5ELj+PXW1?@6M42ay?jP{P;`+P&Ho6fmh*<@H+A%BFtX8x?x;sJqvF zx}6os{LG-NN{tF5ISbs?=pP$eP%9^dM1g|4X4(Viy1uG;H`uPB9++9O&jHJbd|TZ| zh+88<)=4H(p9taJPwSNk8-%hZy(vOp8<3@}l--j1W#S1z- zBp0T((*(Y}AkT;zFr8J)rN}KcbL-ZfLY%x|Lebb@{zpF|JoAxf1OtP?0*z#Wh#q?y zwSVc=TizcsuI)WETQ4n|>*@gI{C1ItymJ)ppsOL=b;s>h{(S2^?l+8gn7Rl1j(dF@ zDL9AjOQIIneJ!=wCvOz=@NA@mU&xKz1OYdQ&~8>Qil>LwC+26{Q*|L%$hU_5U&WTW zLn5rXAvkmcy@FTl(3!dx8c@KT)m#y>V;f4q20JJz_yiptY<;?G1=1uwsVt9RSLg<^ z0`1tpfNN*Kq*f13zKMa65drL8Smb!$zGi=E_@wtfrP6~D8CHL#I4k-}wHx8yr)`b& zMXC?fZmthTG_>`s4$96Dz*k%DCz~0A358=es~D*Nfeml5R3_CjaudZ{@==9&nf@zL zMNGjkq}1_ktG-7sK%&A*H)NxPoy%1<(bdCNhHXzw5tQ15E+R*>k$Q@L7V@ zP>~HyN@u@0s7!_JdHw$E@ekGBApdbEaYmM?sd!9xKWz z{YL)m#`I1#w`dz5&}K@oCbNq2#(di;@UrM#^}GWF=mu1e)v3z&s$v;3Jo4d=%`bTz zN=f!?Y_j27wx*S@(^ZR7xEinO1^igY8@zA28W|cc=G3d28)Utj-O@ZD8v&61u*eZy zhTx;+YKfJ*V`u!loz=(g-?IaM9xvq2aa>hn;ce4R{YdfAus0Q8=z=X*Tb2{kh1E{K z@?!wXHf+$jA2_wLpdOW6>*Dp*-&SRhPkJ~LkLgGpukR2$is&>`RQTZ^_mV8O9qP)Z z(IDj*`jGTg=H6GdvU5zD=U;R=6-N0{M7r-os%K;&r6gIB2NB;D^(n8OzVDzx)51*p zmqNG@ngEn3NqpnCL!f=)VO!-7~p0Pd5e)`E^902Q&G887d!9?0TO}f*_Hudwy6FKBUfx^wAPq?_>pk2cu~&BOd=Y^XH`}E+pkLg z>KsZAAT)Q&T_Y4Vc=Yse`S_%Zz(yeoiGRz>UVp-ilsjS+UTZ6E)u+G0^#2MR={K-b z{~*Q3yYR!#DyRLHtT6r%_X_&4sc#fGcU*MO*3`y*ufR{^_Tvqzr0Pf8o;(fpoI5=k zo5C4oOsG|FERAcsB%zY6F5jPzJMv`-&3Bl8F?n+H`PryFJExPo-LWk#E?`NJEtXs}^a`@*Lv9q)-RoNK-jmT4bV~$-sf;?GP+}^v_=m(@7#BZ{4103|W zidB6)yBg_V{do^;iQlD;7m6&$YZMh1DNr<5oQc*dEFrueNDoowFtG>2FdHM8A97~^ zS|4Y5EzfVrlbI;_uDCk|=VNL^tTI<#|N95o!D$^swDqLVvqU^L2~S=-uDGoB66^U^ zy*8V*maAs0E`sm4x%*%)r`}IFlTB&zb)z*2*2o+Din_HUm>^WElLO_swF z%s&@YrSMj&7|R#2`_L0JmTlH#GZ5*1F}Sf^ot3;BnhN#Y?&a6IpTC^OJ(v7}grt`O zP$x=voL8RGpHZ?!(So2c8Yg&accRrSrMjCPSwJqxboZ|-)>i)LB82F%k_$gBu+kdIN;7PXaR>(I;?Q*t`aMXQ~)XqH> z-}pJ@=L&7(aNN;sykF4E8hDiTY37UM!u-<;tlNRnQNN_Tj9UZc^K%hR4?3T5I&Z@f zu;)y39^x&TtI+rJ*d$tw29xhn6mPEYo*5>VmK%dV@~u`N-(q_Rbp>`aoF%j2eEWXN zrsWkCN$m`$&6W$~jp55ZiU@&|PPNTN73-J6iMBtFj6h?=AJ4P3ZYG?^4o-&)RHJCZ zZ3GMz+U{2*U%LL<%?Eppcd*{v7ZVz|Rb(CO2x+qj=|{>;$nxNU991mk&*T#w?13ob61$S>Cpa8?Z{!B$pyyy3~X*&Ca zgZ__(l683xcA9Yp~k ziT!@kE)=)7Ecapc;n;a%e0;s%NnAT!#tFKew3~k(2u=o`f~6N)rndU5zeIO#u?pQP zknzc_f{wUaEs=#k=i2&WP$|Ky-TYVai~!F)k;+YGc;{!r%j6gtPtf@2+R#KkT3)9S zbd0OgaAYQ#GsA$a@BhFS^3j# zd6n~tjylMEg%Cf3n!@Scb-f^GMy2}*Ng57=%Ou^4>#^mS!*4l7a0UO?&;cyvK#q9W zAvK$eLz|q76WjCXINGy6Kxc1NiAIMYE~4gT$*m%ibfm^uop(03u)O!3ZCEDtmw;87 zeBS}WFJH%tBuWA&#b{?#2D37`<#iU9DS4Kwdm?qMN{SNYiwe(mN&OUe%n5H!D6ws#TqfG1 zur`oPVoDSGxZ=Fx;ktZNEXt8WO_atzpCuTLn>;i664&nVB;ZoCNHRo132Q zp&Z$jDgfqZsYU+xqFOG(R;L}Pjw-|gQh1(g1kiFir#^uHrm?B1h}T6z*!A?sxTMAb z1@@%?&XJL9eP4d(9UBWy$o-K7aq5(6l69;`Hk`arU2=kjBfR0g>pNfD!5?PnP2a)R zz>%mQOvzzJ_x%WT%$sB}yWj?DgO-FzEf+MJ0E#_GVD#atYU!s<6%2y2qoUT0d$i|U zZP+^}o+s{chhS&l1s@(KFQ_gEa=|@M?ozeFTWuUTAR6zpP6b{$H)@H>(&c5VYz&)b zh2?SE(iomE1zKd*Q8hlbzIVFY{{{Og$gAISc6Dlfv?#2g57L0MZR2&D-qcd3ObhVL z^!3!@LB|b=wryDWG`uR!i}|a~%7d-3X2;(+)ytFp3_bCA?~UM@_|eDs&8 z&#Z;T?2e~?w;EZ?lUI9Ef9u_l$$;5kVpNdT!9t$1xjCZdzH7A8tSl`Zemt3)`kPuzKrTqG zMLUB-2C$DuxQPvyGn%E3%BtElCoa7ozHr%(zu`3Q6MEbf8UP0uS)W@J zE&G0&{V9=bKs&o^5;@bGRbC zy)|!FQ0yV>1MLR4Vq~1L$AE#EsLmLNpxyPog8ZWRWG%Ks0n?-az2Maj)pqDt6G>6! zq?+2@a?Vi;hh%HLJ;U4TjU7atq@>y+o*cI`6ud(&{?jPOEqzI9DWwkgHUlB_8###z6wg<8#M6-EX4oKhI3YUQ) zE}H*;?r&}aE4rNn6LVJEIRi}0<@HK)ZU&$`X{9R#U`4Oq;?c0(-U)m6?cKX~#P*{o zOcbsMnyU;#x8qS;_^meq9ygt2wcPs$2S)=mRIc@|qOeq-K{h6MgL$~e`QT+*F7~Oo zMSY}l_jP^At!dMdzw3mOHVuzZWqagWXA6F{qfof#2aExqnUW>Q)~ANO{mt!?T%ce; z^j7>gOjyYvea-$W@?czWd%@U*S!vdynLFOV4*$Pe$_!Q;3!e!-8&-tvXIC`00(0Se0w0MNw0-Li;?0-_nIR;F1z9WlMWPqP3NTw2;$OGoY=ksMH2L~zpH6Ft z_Fh=&m0E8>{oHv5axJbGbzav3(Tab#^@V{xNlrX)vJwm{52ZRlFIug4=zm{xq>?mU@b+7@i&)J zG(W#0h5h0HW3}MIgskO0BEkD1pIY_1Fgv)FuvqX&U-+bOnhd0^-W$6Dpx9^o?L&*- z4G2N$GlOu_w-?L-ld`8a56>gWagrFyt{~z>Yw#SI^)~c@59^s*Bjjfftv{bN8#n)4h5d; zWS^a(YwRUO_npZRzAak@`aQxTya9F_)R7fr%TJ6*pd zUhmMkVj<}H{0?HwvEwK^O3&B9$ZFg$<#j)!-ctasZJ1}6T^2KA(&F7wi1~6AyB|CAZoiL(RqW#$-r1`KOZvrdRhdk+v=j6Ii02JBqI%rh&4`>iOs^BX7KV0 zv%d!*)*P-o3C+%Ue;7R;<^0IMkC?~7YJUaY9puH=V#~>OWDOlo<4FtliFhZ^yB+`W za_`Q3D3z;N_mVp@Y<0IwyAKE@8f{u(lDC{Qgg%`Q7;bGCn)H*52FPXywudWPbnpoK)pbwG z^HbPX6OTlXvyPtb=slO!La?Lz_Lc6JbpbqH=V@@n>2l^)$i8wucFNA7D65<>Kppq@ z8F_;Y{>{2;H4y`7vdn?*U@zkD8RpmIdcm?K(}wF?xj*}QSvAQS@njEa^;`sG$Uz!# z0=4T*gcP=nG$`2nCL2t|a1J_dwd=*v+$w0q?9sVgnEW33%U3T=woc$tYpUaJfp6P{ zv97Pl>^r24hed(C<#UwI5eFs;aIyQKvHh_{Uj}Io4eJUF;X0_oF&-G%ae@w%FBm=4 z!r7Tg5!|&k@+oB`mv8Pdp6)8@I`){XOc+Kn7x~zPkQSdF|CRSHca6~T-AoG|%JbdP6ZuI$mTJRAZZ8|6cLIP4lQP)Se7@|D z_^}N4a5SzbYi84X(s+x1Du5y_N_%kTwnwF+NTeH?v>)^9g!g-<$M%Zq<)80K#2*}D zJr0+0x2{a;`bM)Bm}Gx*L9UaSzzK!h@Ixz$x(AMx?+|@R6AF>$Wu49XfkBP<-LL84 z$&Mt*<2+An{wczh0uf*z`R(c1y81^GlI1LGQ|rv-5*(zjqMwPj28-S{B+iX`UVxHf z#YAvFS8IJs?a~*4lkfsQ*46%){pa7h2bdfLT1frIZoJLJZU@Zg+pX1Zbgjzl z%%r`&U81XbE$9-)@`*ui$!b1Ge5dGV;s+4DLM*2HR=T*%0tk8O#W5w%lkYNRWgxx% zYw{lMuy^!@rABZi&(!QbDTTwg3>1Q=tGmlanJ+*jtx((HM{nPj38x#+b=*WZ!VSU= zEYa`HZwW8~QUn;k zA(_`rL22%Iz>DqzOgLn;XY;W3SjJ7a&bqE#8%ab>%;x^QI&ao)^@pPsuLpFsgwQvn zr=GE3hbo|%7-MrV@yg@P-AL!bR+uUY9TrQA)011n zLBNsy{d(NiJq_p9hsG)R@BC}hrg2`CL{l+( zDB$&*zN%L;#-0XInBSH*;Rwijf0~fTeikJi>A89raYmT*-;X?b#7RQu z@6u)?xb6zW4m-%S^Z~S-j+gGWiyF1Vf6aFGiO40Jn3g;U#bLslqQU*Ui95it|gsKaUXBr>csZ`j%_?JUetBKeBf| zOG8#;vK0mm*ruk1L;*6#&On<+}e+qE58}E z9Q({rY5NhRO@68NFjh%N<@pg*e!A|sSpnY(p|*XMqf;(_U4#0ur+!dk8Ve`g-Z-Gu zh}OM0{5MIw{$8BkE%XFCvsvki$e85j!Tx>XOa74^3D z$#`Oqu^FFCAlDQ2r+>}dMbD?dh|EMD{1Nef;7u1%~qlo%2u zlfMo1@HFE++^}0c|FB&f#NE%0JC526?_O<0zefQ4iQKG5__{S*Fq8orf)mjAkxAl5Q8R z{{H275@s>VCz81`$AsC``1NN|@lnuw*`2k+X|Ha-QOQ4fOy{(POzR0Mt&I4IZ<*J)ATE$i(0#g ziJ8MOYwg2_|WX6TIL4MAuJmyBGZ=Jv~M$tsB5*=3| zexTE8DI2Sf7JgWg3hl5aH8R5iBzIx#QcJkqecnK0ZQ$qU{2mNQ8x ziV{Unl?|2=~l+1ns#a~VuPoW7qg0R?z^>Bi8f0Sb0JGFmmlX(ula-9u@Ha@-bs#20{_KNGU$V-gN>&3u)wMZo@z!9my z+EqQ3cAC9gS443BROh_Y?nE}7A!Gx{FHW+k&zM^!8d)*{taEy=aNxLK>)Bc&y+MQf zmL|iY|0pS|9Q#X3kt@YtNl_}4LP{17R-aZs#Tz|R9c`{BQB_|v)<{b2jzzjEvCiiF zA@lfgdA0dO;K=R7xxB?{`R?G@q4DmbK>K>x!5ZXa(ZAZp;#d;m9rhzo&I!6(G9*!# zifYjX`|+~?szz8;HmK*f?n+W(+bJf{_^6!dRKD-OmcP$xU!8VhF8W~#nv&hk^?u?i z1)W@M(AP&oF*7@lT=qCE7it{t%0B#}z=h@5jnbZu{kg6;b?v+Ad!x2wUa9GX7v}9t z(5(?AqSndE%lT7|w?I>XrR((ffljS%8cz~1ZaNt|~b1r5Z@)-6AZzl~y zi9`tS*i`WMfrGHEQH@v;!_LCNPy3H)D04=HHd;N6FNTYtce|!Ai!#cH;E1q!S+$hQ zxK`@&N~kuTj`x`vMrAmah!x6leL5F5E}DTb&5!knFvGYTp2pVl)znJ&t)E7mmX`@} zM{6-GL><{P+ys_6G^Ei4X2X#0xSx^`ggd%`5wkD1?v8Txd0JSo*BegDy`=6#E$100 zH>Kv!a@0VQjt0;W=`O7G2Gx*!vlFEB*l%JcK<_*-k<)dBdpe)dS+D7Kzqm)D9@Lg{ zD(g-$l9{;|ky*GaqN|ut+F~Qo2iswj&luoWo5+w=lYhdj?Rhjka&S68pUpU%0bY5n zLQb@9s{XwG7jL1d$`_vhK+1tX8`P98E;qxvs zd%vJ@RttH?tNm>_k8irxto@|lw0VoG8=U6FpGvAMgk}(?W7y!Ig(wENYN_`|5Y?x2 z6~OlYf9<_>RFrG`HcW#w0#Xu6gS5cVAR=3kP*6amTe=zQrV*t?x&}l+q&tT0?iz+} z=^Sa^VQ=txzx}NBt?zr^e}Am`W0nqF_jSf`#&ynh#IvTtTLjYY&HrK>pYsf56{anx zqikge*ePc)%2aQ=U()Yff7D`zjR|1bRx*X4;y&Mb(#(JAvBa5H!NJggE_yXbblFh1 z8^|*uOC(|3FMbfZ=kodQ(|NTlE99Iv-G{kwTrBZzWLjOU<#l-gajhNA(eOy~3-)kv za+*NileQ`6d9`3RX(oA)P%OlOq9fu|@a!XKVLl~Gqa_Y(|oINq*t8e@WzK-sGF2|BmhO6Zdk7~Pws2J-Zjoe zl9q;`q!@^9ZEvz*CqNp-Df~>3x8YgEW-TViv9^n>FWhVRUcw41t|C2G?UC_B>~~Ar z9{mL`P{ax~2nXyyaZY^!{j6hr)Uq%TD;9MnjZs&?J#8T(8HQwlv-rx~>^S3tl&5l{ zFJAuJ=ow`huS++|W1!%|3k z>n%%fZ%oLeedHAKX_`2z5wlH6?M~g<`CE%lB-!=4m`JModNx0aRKE>!>iBFRSkhQS z7i^O70u#w(h{p(|F|-Bl<-o>BSxaG|7HV4^MZ#@P;jjW3@{E1Oag@3j&T~cC1Z;Ng zn`5%Hh*2}d#HwT^ZhbPryj`C)qN#6j!cg1R%Z-dv4IPd2*i5GuG%4WCv&aRLYAAT4 z(Vt>`b&&cRG?Ld{cYI6;57wa^S#?z}UC^k(<@^clKnGy?Z3P&f(-9t$2iO5NZHxDy zMRNP6G`6MK-WTIJ9$$-fF`mvXkTzhi5xd9_3@Rz}U{g{56c=OnwAmL(a%UFd@DzK- zABGzKAZc_afHkVLlH1jw5WwQyH~MzZ$bFd}A9VEq$49(p6~74*Xn1ZtXM?|ur4`Q5 zc0F0q0DM+XK0sZ;*Y(MOEBaG~O5>WjVN}JXM>?grx-hA4qN`|Bsy|1{og6l~85bdN zK_PBa$M1!l{6(^-3VAJ%LU`+*DT;3__+r!TQn>ot6Fa+aZ+;?q87qm=a1Gz#)Kc3*J@@?h03yRjS|ImtiL>lrhYN-}jXh2n%FNYi z2yOX^U9gh$+ycB(sihueRk^~9%|BveqxsWTf}4ol*Y>*IMcQ(k@jGzm+~L$&`>Bny z!LhUO>Y21>vm8XmIfEAO-y(5_B1GD5;bg=6uXzgZ%VIrTD`UM02^?a{zx>5#Qs*Is zfO!Pb>hlRL*X16eBvBGpCF!yvl13wA?nAo;ywrR+A-er{iN+K8f*#g09=Axm9iQ^O zvDjZqYWHbfsz%IKgSdBRdJ& zin7=2&)mXj$1TpRm5+Dk){9di5U1npC#xdoe)RXfJ&UUymAiB}dN&+u)@rqk^UU`RReYUrvQ#(B>jdd5$_;aPY{ zE@p>a)3B;@`p#8i%TGu-O3V?{8eOqVf%;*q?^h_}lHbp!H0q-;yl7c`&01kdfhC&X zeu5{50~kJT2)DeaToQ9o$XQ54=q*fVv0R{=BMV-RQL{SwYVoWVtwoy{Xm~JAaD;<3 zpUv%^sm6WGi+1%$dLA|O$EPF#lFkpl5mTf6yp5CW*9_CwB-4#JYc5fKTz`@DR{c^M zpZE=NqgFYZqe%G#d21gzbd(bdDKhfb+E}Fkggo07Li7T#cb{pU814IEWjKiwNAthy zy8B6%Aie(_VKPQE*RA*6Tg!<2I(M3Lc-TPn^wLld8AeVUUYK};JQT>Q9-6G>6nS^h z?$~k5jwoL|Ju0f(ja;M2e_tVWl~*y*|2w6)Z~O9*!b}jWPF|%$RBzH4+JPhRp=}cA zDBg3cGy}C%hl`nrQ_2LEqJ&80vnNqFDwS9>KM!_R?b;{_i~4(4NK(@PWJZap_2FSs zBWp}d+$=1-^^ekajd7n%}C+^-w?{uTIo-Th19G2L+9E-FgPgzhctz0S~s8fF8XQ#IDBA6)w5Cv8edBI5_f z*7aOeoL%6)%?0qiFIhpq4#x9Fy9v_Y`c8RxD`=V{%uwths6OYKSw zw@m8n=*egv;cp3^RH4R|3Sm9Jmm}Z*_AnCP^b%Nt3rki7)6Uk$?-a`ET6CdwXR>za z$KBB2Y)^Lul~o^FsZs0NTI98Tph)>u`NFoVA7QGHpB&3m>7QLJm}qtWA*g+thJpc* zwXiijRR3~kT&FjMRKRN3627&Rt(*i(A2n5in2N_c?zh}&&UBa_?cQA5BQ1CA_x4z9 zd49eyW;;x>sacGI4PJ21JY0^@vxOXYb(gzft2EFz>$M(xQA2s|y|6Butu;!Y_PCf5 zNZ_ct-oOYqYQ$zN8Zia`ORS<3Hef6@U&iA?GuYYbXkl-%`O5oU2W6b1_KYt0Ye~DV z)TD(M4pv}`lzt4!o%83PrasfqM(mV_Y)Jt2W1feo%p^!c=4(!7M^!%q-fCezD$ntPZMy7bd zi$*>dd1^C-!j2MV#HN(RS%lN1U)7e$s!D*6yOe;hsF+*sFoIUnLUt*Uu0&x$YvAD_ z|I%u-oy0Ru(p=ktRl)V(Pcyf&wZl04Fxtcwf`3DD?dwOPPu#5MCjPUXQ8Q?Gvmlyi z+yM-{57t3@DclKGUC~XJC_Ni^P7{Ex%=-4%6wdDb(CJ|1iOUSyJ)BR+9omJoO~VSw z<~CcELD}5m+d}InLocOr$BEJ2j4Yn0{#{gD*Af0W_*@*2=bDD<`i_H zaS>(of)(6B-`-nIIr1T#Z`uG5ZFkC-Nb}v7#Ng9~fqRtad{iX)6n<^qc|6yXxkx*W z=qhJ)L8(|i)}pizOE$)(PFIYT)xqU3peI*xs7CrUSp#FWz_ycX}s_t72mv2 zV)1!2XTB3+rv&w}}ALMP416b&B{Nl|4zY2O1uORdbL z<@L1>@i3%2Y^pYRu<*7p)bpK`o;D8zcF*EE_*{dICh0&$U=d6H-mN?)aTriOd(WE< z_$hOz7!)k>9J5E9rp0{$+UMkct_q4w$vXR2e*ZR{>Ish6nz{-S+|^h3E^yb}YKc2^ zu^jPTqB7>2z?y)0G$ym5onNlj4%Dov`n!IR9@V>#sF_j9RvXq6S%1RBC!bX1SGh-# zg0}*YMth(t(=Hr9wRXPZ@_N9~_3Prx$ZhOqUtr||M^}%1)tY?`&!M`r-)6#A%FCjH zD}LBUe8a#eylm(LhMUV@M08oFE!ESA$CW2r67QmA>cZ|ivE^`c2Jm(LbOVOOVc408Y ztyied1qaHvF1wrYaV_+F_Ecbz!3L_warXH6UMZbI*BF|3_da8cRvbW}r#QpEB$|OK z*XGbft$35BaNwA;KEos?zwth43=W)zRf6z>U>3~}aNc;i)Cc$<cen#&>onm^F=#i^s_3{c&|1j8f7JoE!$4TWt>@bG@N-rTV${;w!@laRByPTUwbl zOV_jJeYv)ev)cpbBm4>1BAP{QK+3&UwA$TEJ_zq{1;Z^#N!~2N>mZnB3mS2CzasiD zxPiE8)uknRrv*h@kI^9_w}cb^y?O-u@EB*RG**iN$!mTSh*}?{rBJqN;b}d*{RgH< z5$Isec@S>D0CA%ZDq~0O$36$;SaL&V9?*#6>>&49@D=bos;uns>R{AJ} z2$R&~W7u}8?%B$3;fc7qizr&pjP6_#y?M$S{e@Gv1w-DVWNoH6)&$NLVJx0kB4wR| zy~fYwHE#6}AOR@!in;^s*7ZTCZYA5i^6j9VDbtD%Osw(M_M+acNy5!ZQeOe`;w2T< zTBdd|r5K^}1jXf!qtJkq`R{sc(#wIqh|b4n;(To}QT)(YyuI3Cc6r zmB<}7&I2%-GHOIImPqZlMWPWo%kuu;FJa0iw~s=9{U}7PVH`Ii8I?t;djw%@V*QBk zYBhg;3Z?)UUj&~f*oMBC*Vh_TR!?k1M?v&@DH+s9 z3&A61!_+F@8fBGW;^EK|IW=8s&~p3-wvp=TufODzXhggp&#o~Zh)S=D1J{D5~o zfVCsK8>Z*>7Qf&U^iG3^KKS)5RP)YYkO3`}JLCh$w|?q|Cej`oZWp^I*sgt7v-jZ) ze|tjf9DO@J=hv*1opxyG1wRAY>cv2a?isuwuY^FGa58I0$H-Q@q~)zP*yB!huH6F6 zGLNav!R=B`#kN4A$|mmOLKsrft~X(%6EBP|PG`j+tM5SAV_Fe|fh+3d$+a<$9~VyT}6VV<~m9+>NJw{L4qie~rz5q^ zQ>wjjGMJNT8MV03Z3h{7O^+BX6a`QgToDe z%NdbAq+tqa0cWNK#u?S(E%J|^jK%(-dG_16IX#8FVF{Jski4s=+CAaEV0zIX|NO6D z#NoTf2+is~Cx!rqs1@!wVytT@2YcCc&vsETll4yPbNywveDPz`wX0vFnz(ikdgF*; zOoU6M!I#X{-px*$7C<&j059V&68kN0pf=0*p^GcbF5OA@Cj7v|R=8-?c_5rp5-8ae zp^G+VNbc!bu${hHM9TVFkyinI1;l#FOv)P}=;7V0D+ajN2xIUhCK6NP9;(@W@VrmE z+L?xRi5H6Qsz*qqia~7f{8eR^?KRgv17iZB=Rt$5Y*GD$108R8$GDz^1gm>q}-Oj$x(g($!n*y^cU0Iw^uH``rTQ~|C)*XJK&hi(o1Ma6-TgTZpVou+h5%u0( zqGFA{j3#rw9B*i_#4Y7_TRoew@b8w&+e}K6n~po-=OZ#hWIB zNPoB{KuvC&21qQtB1f9*2NqO3LYNv-!iaN{ zs@7+sxF2tHWs$#$;~PYb=`(ef7ireS=IX`{v23QjR|90Cn(55F9uIB6>}$rk<8{gf zN?&3#kmn6-duXp&Urk~lgx_IYUj615L0EGl#syQyss5_ugE5AkB@TTZE=k*5fLmdg>d_|M~-Pa;T1jhbV_v2cBWXgm!gt+ z&7_C50zk%HG^QU8!QPcUG0nvJG?PKOuC7J1paSE!bvr#+>aVs@=?qc&KVoS)B4TXg zHh6gZUc1G1S^UPdAc^AXEdUp;+NKfH5hi zyzbIe_Vu-57)jT8^Rz9ggoh;-S^fyptJ+xh*YQ=M7@EOU>%pF5etVWOM%Qwgh?d6)lEeXfsm9NP!RO09Ay(l2ahr*+)9ks8<~$& zN+GDVZczMZu+MCrOjaDgGTaz;vb0uB^zIjq-rV6th1dxnW#mINUHTpzhwzOc%yuzY z{Al{ckIXQR4{ea=bZ6ns9vL-Wxg9;9yka_E#x3RkZn1n5;#qf)_R?L&{d?jo?XmBY zMzK2ISzvA>vR&(+`zfoR+TN;;@>+GK?8YDdQ5}Fo7L9^V>0O7p=?I~u%f}YnN3alq z^y2y9w%R}(TAwva_(XI`Q`ncvcc_r{Y?Dnc=HjJO|+*lTrBimPC>{O#Y+CQ0>+hH$= z>R(OrkeK0EHX#QabY{3$RWJhe!c|4f^KggU$s5 z=c=M?HE#KK#*PxvxEKJ-3{Kqfmvb}R%=(K=^>xPt`I1IOo|?V%k&C=-Vyar9F@h>h zuvq0QbNMxXM6Y&LJu-SAD{jRPXF-`~b8wvle^S)K?Q(W@8{woTe7ViRR`M|=-6O6! zdv*K6BjQE_@Y$UWbL_IgOhPlD5Hesk(22%1L+1{N(|_~k6=Ml7DmKgc?Mg%4Kn_N9 z*6oE04P=QF3U1a&H+JU}FXJaK`H7k%M*$8SgsdR1));>cqlD8R`Vqz`Iym&L$YAck zX#(oB1VeeqZ%a^p&pT`%`0CCDt8YOf6=iCAZHXmVG=8(s+o|T)(^Xn4;C*!WbV>jH z)hI{h+6f+XLVPAS_>d-Jrw+UO-u+;9(0&bJT0fR0gny8w0`XSo>iNcYe#MvR-mzXj zVrg?Li_&aTth~HBnszU{yN%&NL0Bzx)SDf955xx5Z1YH|k?pp~vN2aJ6+QoywfCj@ zGY>4^TNEQY351G@;O^Dcz<}!)XM~WZnq`R&Usi9v_SAdDl^3Nm;mYvxGXi*J37jy6 zcjLh4nM5#NBU%NyufCUxQ#rp`<+7lR!M!}4otbAZ6QsexXurb6*=qWA; zgSDC|%R^a9SGSz8A;oJ`w?kyDuGN<%T?fhHRMk0CyrOWXLhoIY_m&^-ee7?xWqa9= zysXr=UQ6~%S!wxX!Boklq*uSQ(08xIQ2}0*VGoZptM>9O#DKrbgsjSapg1+;%a#;i z6?U=Dqhn+VoJL&~@JLznY_65Jotk=VDB*1idxOJLKn^39`#ba%1Rg<~D@msC_F0dx zizcpdEhOQO%Gq3_KVt1ST?ueG=I%iy>gApJS2!7LH*haSH>yP1>Lr~}d|H$V7SHZB zdn{Gx?k-mA1R;NQ^5&6=hmHYdQ{JMu>e%-^E{MbQvn+j8- zx_+G>U@@aYeAoM>h#C~-sC01P;F|l(iBW+VjlPI;Ezn^=A6iIiP?^j>Qe8L8h^Fl( z7BF7LNY{3Vh*U}*veMvz7>z&Dv%;fzR4OR!GyxQ|mQRj(1?N&g$+7klAA^f~p$@*Z zAh#A>*x}EkBcjPo1r@?{>o*9EHe;7~2tSTpV@u;>KmCH_o8_ABx0vfuXfc1 z3hq_VuHVq2k!~;~uJC=wXInRYk)O2H8U_WnLNt_5-&yz_Sllme)#xp@e8XL&A#7D% zf3i@qxknKJSGBCQp7frOJo#L)h=>ugwEbD}EL0-Ws{Lu@K_j{VUz;kfexYPsv0-fI zodZ~n_%e98n}W+#$(g<3vv!7OT-T=?OqIFD)X2a{s@qVgj@FnBWG>R*M_9#S-rw8B zlj6#X4CmDoKWL1}NJb@$zKHXFCjhp~ZvLX;AcMOTr}Gu~>0t|(yIUXUc?5RWL5 zosJY#d0)ERoeBTgT4Du9OqZiVA9?SESHPWfia3q>+{Mn{YHYGOY3fB3$f7F=1&AqC zd$3Hrv$GEP28`2fW>% zfs4wcZ#lF5-D_LFip(HhgZFr}tm^GHoXedzBt2-0A3SxVT%uavDB;?0ornPTbGd-I zT12PbRlxMwyivLJ#v6F0MNVzywxGv(AUfh1Yaf9DZx&ffNZaaax91D02=zwGAvvkO zhdf4-8lAbnKW_-Askk$Ca-4QfvN57P1pZF1Zw?U(25+0kxHt_kF2~F-2a3b&&CDmG zb=Hi+%;hvnE4>F^%ahBrd%2dC0SCM*lbwsKTPLf+lR>?p1H*1^ zs6nfe%W&DJtq|4<_=73aCb%?`QFROXrK*bBgFZM(C}nAEEFe^H^?T={h3@=8Uma-F z=Ty|vN8;?a^Tb#!jrHZi2_hA0Q@*O}-dbqFh#$_-Ki@o!sJJQ})19nr-mY7uzW=Ct z@=fkrYfGED(V3IJ>GFk**&^Wd6tCQSHZpKEhzSaA^(@wWl1$UztY7HQ2YGSN`Qq-f zdX~5mEnJON5nvo;HVEv=;QwI+{DBhQ>m1Qa#yI>oa)+aM!FtkZTZ@!N6Lf9vF?PPv zQRXuK(opN59s}MXpB(A!B#Doo7&9E_f;PqKG_r=r*Iw0HZdzBQ6w2Xc!2|Amv2Ohs zSZ?kOrG^Vla`T9BB71Nz==U(Fs5dq*(OQ5tVQc!b`XXYLuBdH{ezGeka{_z2 zx>NGd*A=$qI%TSoH)~5nwAms;Ltv75)-p6wg2ocLo@{B8&n+ziAGr&VlSYkjlPDfN zDoIiR4;^p@WW~g>=iC-uMheK&CBD|Y#@mtt_s)RtGoJ=hSFB@FfoJi-XA@bUJxJZ# z%?`h&%SvQA5qzKDVHW9MjTi9ns|6p4Cka?qOZhI9YuiY3IS~(t=G+T0;m&ZvwS0h3;8x{W8;jqpx{gY9xcvh`L zCu1XHL5$LFig(%`1Vz7^fn|z(=ZxkTS&w&p2`HzYrZa3XvbVK8m$1}+ppq+48{H|Y z@$42L{*4bGl~MX0^|$O|v_IPH@@k+F0t%M4+@18y}4g zOnh*YV|>w0svM;x$=or##aB7T*uWQ1!Z%i5JX?2`aa6w4B~tD-_=L#m@VC{} zkun(VPEB*Ts}o$H-?}I@NXVmGsoQ$_BeRR$IGtGaPT?q@&wL}6vV`zU)7l(EA&m>(?Ly2cPbeVE&()1XZ-c zZSXgOHI%9O7Y^geHoop2_492)z5w+sWrdlV;;1IgxHu2GuTBgs-Pz$(p<+hQa(0^H zgZ(AO4TM|zbtlZUb(`~p-IJXGzM@85&!e>3jop{p-lOldokyK4ttlHm-;)sf;K;Rp z9*Vz~$%eJayEj-M-e{OsPgF$H!FL&wL5ujpDhxl$S%KwJZN=Y>K0Dp|l~pmJvFbhR zz42wIWcDIO1!jvtxcg*~pdt^v%O~RMFVQ{R7iDNDmy{#kr3E`Gv<`g(^iixC3VG|N z0@%~Y*u@{PU@-gHeAr+D57-}7$};MIx^SoG+d(@dBO7q;s*IYs^#kJT+^mJa1Lrn3 z<3$CP{2KSVBA0Ts`L)!9YASN>8F9Bi;R79*EI0u(xU$A8(J}J-E8Y4>DrHui$u5WE z&xpVuS4NB<_!@_={tMkGOn4W|& zk=L30*z~le)T}dpuur1b@&*rVxZk!!+g8&YP`o!68|y0ruic2uYYmUg6NBbiqUhDG z54zslyyM79kvVj%+q1G!gl|T3L~@Li*|saE+Oaz#2i6qMzdO!cYSLdvfi4#@+z^{4 z55_lF&HmOG^`}+lhYYTPnpjl-=`Nv|xqMg!@ixMpg@qkIWMly}-HqQ} zIQtTpQ%w5RB*4AQUOP;0#!tZHhZ|pXDIW@oxzx}!`f;<(buw<2prYb$yZN}&qTQ7z zI)W`?D+fHQ5yU_ZiW4D|0I$1qz6rRb3Kem#L9Yl*c3_2w*6pBjpzBDKTPs#r&pMDL z39Ei8;WK}uF^&S*2#eTk2-n~U953BvGs+d68bV_(4VEBb4oE#dBo$IVFibcpw#0uN zpbch|cYVooM7sGqpI=0v&M+R&>|WNr#6r@k$%ST*s}UTRN+px7^pM-OuYS#S0XV~% zws#v83=I)n+&3u>7PYZYTzU$=*1SvPZPe$1_qqg|w?96`sTTl%my-1r@b-`D|y zM}1tu98RD!v7!e)uxx$An$HPbM1f`VQ**71&x&DmrTjsgGN3?dL)ocv~M9O^kcgTnvrhbWg_@UD! zTZy)-6OIDrVV+LK)4!e({PbI-jnNDeP1&E*4CeH*J)}0?UTQDONIhHmu}UfFvMGE- zYK3PMecwA=mIel<435nd!q430%QXleBlH>ndxhtK!C?2n zd_8HOY%1NmIHDYz&Z-4@Wnc|6%PtS>bKF_w0L}&Au~SqVv2C4ja9Ptm!lU$5GG8%U z<*oYAUZy*8TJG<&eYESo8pXPDKofxrIgP8}Za=Gb!Fc zy>0ujzG|_#j$nuQcXsE$Fa(H+(J`$y#HiLl&GX^D=&rlJHlfWb!J?q~1o3U@G+^S) zkgS#TOipJqJ+kw&!9rzCi*)e#JeLCJlDhHh!m<&pgMCCaD?HL67$*fo5+Uy3>n(}0Im-`w=)c1Ni?ghQn_><)0jzYw&>jD^Fav~K5qJjz|~B_ zd*hZ$nl7NCgoP3r1;4-a!-&@hjfj|uC-LJCv(H|p`y+Hl#r$pfUCT2cxRCcV*S@p~ z{Xw#n9_jKbda{yz(0lBw#6wJOdDVwnWGfWQkyzkjOlAlW4V>j;cYM7V44q;YUVUfH zt}PM_Qnslii|fe${$i~S+K{BD6=Sl?6f2`$?%uz_nSn6j=d*aNl@^m4* z*rnx+?C>{`YSA!HVj1S`rsLL%eExjsAK(i^0-u~V2@IKG|D8%z?3k&?j*c*F2Ur0l zq05=%Co|C$H_p~{?QFb?4`gp6Z6yXJq;e}ZXX_K>%GzUX7E)Aj-mS8^d<4HJRG}OC z#V&ICXcwiw#!)GSN#(L~1KdrF@_b)2#`93UCqJK}y@w+~rhO`Kp5RN3VWC3RZ_JdD z(DfJDRQ{+i>xV@^>V9-ovPpS%vh0{WHG|-barOQjdAcYRjWNFEFhh~qpanLS_svUI z=*TYPjHJUs;xeM4V8&tx=;sphD0k71jQ>aJ(tJp?f7#<)wVC&`-DvHYO_b%zA(Y2_ zYNbnU@#NJ%kcpg4C^0L8XGvY!0AUfB)UR*lkDTjcLC%aU*PLP|i}_R3j8~U3i(v3k zR{pRxxBG;Rjg?zpU+**4&2*!|Yh1b!nBsG!A1glB@Pd%~wq>&1Ckv*foN$=(@sTT+ z5J5CaW4Rjf3d$BBFFl9yKcvyQ5$kQa3m{i!Af`uni@bR4_=w+^tU-U*PmGTPow8H{ zQ+P-@j0HpD*%0TxxJlAY_IER4ay?~oLaIu27;sdF|n(%>Vt_gXz)!{i z10leuEtK!;PlG@5xix#CYjaB4cz-~_o%=C?fDgx48q1$#HSyJ)k)8hByQJ_>m*<#x zZ6@ysZifqQaF7A5>XNFmkFcnn2Yhn#}XS#PnClV6fbvg)kS!ITQlvF{P!Mz;3EH; zdMkfQ{pa6P9tE{$+tB`cfBW~Hj{KB`YjO>KJXqZ4_d_{gUNTn0St=D*m$3e~jxn1- zR9WB03jZVSfBG*E?Z%Mu23e|)<{U#IC!y0vslU~CFn$i~bLLkzT`oC7uG_C~(vSFW z&(Hn{>ErV>Lim30M~lSV>Isax3)?Hxt7BJSRg8w)Wp=&bseW&m@FZ~7ELDo+YK`NF zxk+knWdk5#q*4_P$VGk)<6&+wBAAG_xWMz5A|gYcKJO!|hdSv@;HP`AEbp!H%~);Q zJeCrZ+r#5OKB|s~)b~%5@7(1n?csD~S>yR-X1kL}wj5dshn8w6ln22p2-mwN3s?+c zEZJp)Zy;};fNtg4mc`@%Z$>vg1^NChUN)3#6Dq_B}^rX(%JJdQYh@AA+80soJW zs0v)0eZu#Vr+?)8pEqgc*DeX)$bsFYApi7LZ@R0!*Kx}<_7&+(HgzlDzca{5B)C7b zE+{Z%y~zjutV)13q~w$iU0rr delta 73915 zcmeFZWmJ@H_Xi5Y&<)Zxv`Ck9gMgF*(lNBsB3(Bf(%mT?(v5T@0us_CAR#H8XVB+) z-uS;C&ZqO~xMsO#v4*+#-q+s0{o8R-{|h-H1|^yf4gQ^~tR&pWFXY=bUGQ5!02fNA zgSuv$Se(B(&k(8%ID{^GfFU&827?6)-J757+WKtX?Aubq_BFZa^wN)0?@_CYPp-Fw z9-N1t=lV=JAS7{$czBYMDAcGMED<~cg)VnLrpvJ=L{hh5|Mo8pC-q7i=!c>McyB9$kzsDx}0+#o8N7y| z<`Xs4Nm?VZWd4hg2iX+yx3>3`W=vZ@j0U6-r|^QI5%9YtWvgF)>vky(XDqZd^Xou$ zA24`@LV&|nQd(-F44ROKn64ZUA)sO;z{!N?;F);i!M<$(AEd>`98+STqw@suDlveX z4~1ORQOw|bJ#9*v#o`8aa0&it%i_htA%rpBRe_3atu|L@wXW7AQk^Jo_ z;vfWkpAcV(qsd}5o1w9erWC>2ph67fR@M5_p$t9|3p`$}{0Yt3ju2xnKBY>B(pS8_g&`bWhz1zRt2K~vj>S!}yY z-f1+?c#>I`DoRR*)|RTQ{#cqWI@zb8FFE(Fab-PDqb*b*LW3pU&Dd?>g24P)DInIi zIK!w(HOz_{4TnnZFCO6@Z&2;H&FR1?poyAZ{OznkMa0bRnZqf0pK3ex6E4`N9$w;X zcs_O*S|-r#^Pr$0J>kICJ#K?oDAR&<>T}S{NoY(%1G!50gQlvCaOe?gDnhKK>HPWL zPcID}&e8=gfmmUw2j>Q0aZKm)1}*uceY*0?zC>yv6zI-Ho_riw^4U`*dU%TW#ItXs z{)AujEAU~k)vQ_4Ea|@X6sL0m6}<2vEC1bv_fhym)I9{A9<|RKdi*IyqJVJgwB~4L zjEPwlu@PjNXHQwncSd7qf*3o0YZ@(%;TxwSAOmoegZ+@C&hUJEIQ2*DN&Y!})Q)?Q zr^#mxs~7xnro+dvwG3{qhcOR zqO@1P4cmsNRr@+d@9jpyQz|aQQO=}MbVA}EhV~L{S)gm>zdW83+#1cPndA|i9TPD@ zVl0@>h>XLs(u1$&&QXV)$T>^;*w}P8!KnQ~9SAxKv}tPiRS*C5!n@0QG4zkJjzov` z>&MI=ITV1DE!X{rsC_uokN6!vqzG?NNNOf&9!mW>076hY8{V&Roco6?vb z?oGVXBWYK~--6&sLEqoKY*~%EliS(dHM?zg`ntGC5%+dFc&RV)YtN~$zag1r$;d-tgvqLza z*}lkRc#sSuxIudQCeP8yX|NBIEU&Q8f`6*&CkN`JVlsqp`_!i$59znLVR)$t z!r_7v_`KqRMsP~p-|;?u`uyFyn%cTLc?%0h#0Y8wPmbP46e!Y%LVipD9S)bnn>j3* zaB2fbbH)c3s*-~P4l7mVlXQ%P3m7uVmb{V(Nj^Bz#wR5W%T}}~i=O0QN2p@Yu>3X} z%m)(TGNm{+;Ej=xmT)+33O{{XG^p-SeU#PKCVFjJA3VEA%EERC-(6kJh0jqbEfjze zBE6EP;7jw2O`jDwOLz#9XEAVh7a8~$eXcv9jO%+1OL)Tk9Hx2cZ-;Oa&9s* zo22Fne}^<8xRn6D3<;V7Km0-~bnUwghBEIqkdrHefkJ}A=3q1@chCKn^ATrkjFIr4 zvlRnf&^Ai5a%C@>u%7d2evFqw#y*aa1;kXhqkK^J2sHKSzm)=bt)a$$hf z_Y3tGGgN8~AenGZrzW@R2MIVlL9VZTqQX%RNk#24TaV_fj_>*+zJC46bu*+bB?;>5_Q4t5| zR_!_%OTHu0l4=It&kKn$(+pUo{tXFqaO|t|^|riW;pJ4GkQV3t`0ikAg)}z*XXT#2 zYt2XA?B<`-nSK$mM01}~+Z~Zu46x`MME)(eLkwI`*!|6TlyURjM*EFIll^RUGCyT> z2LyFtaGTDbuGjj{sSKh*-+bi$BCMt?xJ@TuzvA#+=pY8+=L-JU>M#;_A#jF|Q7uF5+E|IQWA&v>qD ztHIY9LTitWPrAE8B=BIdA@}0*v)>l9w+1Ee!=ZybD;-dK&_jqTCtttHB4IE-Ir}O| zi$Fvzc0uH7=}Qp{PVQG zBmXa#`un|HD2(33S61PmMkgV>g~vk^FF=LmX`Z+BvPm)a@Q-Ao@!;PRGZ~ps{}s~z z@%u1x1rzkmnswCwd@?=g5vOWbpCnyUj2-+V)D#ABT-u4AS;{2%x3F&(e-0BYFCZfD ze+caZ=2G&Zc~%fwBl16=8;|m$M-G(?JtherCM23^DohJSd<&01Pm*TBg^7jtl#u3c zHUC}e0Unq}DGXoE{^xU5X<$OqTeC?2Rv#_;4NM0vrS!c&Pm<1)hKcojMl0lhD*XS> z)W6mL{|){B8~Wc|+xPz~j|N~K-J4tkQ^=k7FE;FIL<5Os}xs6~-1T@a~7XTgB}EiOK;RSe!UqUtu<#W1gNK z4unzUF>!>fvGZ*w^xB?%Bt6o9QK`RD z>O)!s!LT75ZqmB^*kw3r7`W>PW>$oBuak#w=UU&y-Q3<^89I#9Ck+_hk1Wdt>R53+ zu%`cfmv+TJEB5jfYwfsF)@`74!=JJ1_kUNFX8)m=anWh|k+rBqoKgG^laNhtelYuhwZA#HcL0TjkRA#r)?{ zJP^lNn8Xr(LqMIiUF+GLk3Jg{Q_LribFAdxP${|>FQRKZrm;n%=emQrvkYQm{60mW;XKtu|IcyexAFFn2MbG_AP2k?T6c6RQw-J#C0B$4tn3u61tRk zgFkmRW_B?vhG$wfg-!k~kYO3e_XI`@Vhl3N{_B)~=Vm|-8UXtqV(QAW#QzlfPwIwz zdhnnmMyvmsu8FB(VfGA#rSuPR_;+1k@8#HGnQePxaPD6Y`EPvSS%~-%$`mkc`72!f z&6{EttxAY+X=Wy6r|L&cOw6xybEJJgzJ3Wn#W%e=*>>0(qb@Ej9nSw)Q}N$U!NCBd z2*hzoUR#X%+S*J>2JXesloy`w-@nhx&KAGAx-#vLq&VIwt$41hJ3q!u*^9?*@g+Wt zy-mx&Z37^9PyE4^Vut6x!xbYDb{3tn#-g-vRcp8B%Y5(%U45vG>5w0p9v{`!)d%8K zL{rq_o12@<+P%}%GAu0qu%mzJ3dO+7Rte{H9iMnRRN2wt80)kADGwQ^$CiCT{HK(jhZ2S?3v4>I0|mXpM?LsoXJ_9W8GJ_Je*1@= z{@YQ@L6{#{+|Y2WZbr$+kM&qm9dh*X2?>J{e8AFUGCte*Bt!4n68_8eIJ3c6`ucXu zsgh(%Tx{lO0%ncm*IaMcq?@*K!`6eyY@-ctcQiFd&64!Zr>T*#$U~Ss)U&K|4Tc~7Uf zqM~7x%&wJszQHbOLPbm;;vkKzNTuE8+4OV1K_xXU&Fp-Ck>Pd66O*I0-fElqr`uaw zI9mGB!6hY6e7Q$Q()e_1iP&$R3bLR7w=4L7tE1ppIjav+O`W2kgK+3b7ax5Pku0Jzsud_cKvB?kavNSd9$G;Rxqw4Y89N67qM6YMylkHL zbM*9RV^TDka2$GlVPclAzRt0JC zg1_)2vFTfOfeM@ylQ|^5h@9)av9nW|*%f%V31|sw5c&r86c=V%`t|QjmFCyfa2H?% zgkl31-PH~o&vge)zvju;_dHo!_BvnWsBk$9ZC=sr7CJd0sf-;&B+`R^5nJ{+5TP3R z)4lpz;|IHnCq5v5J`qDw3nF6%d+VW}p6hC0we>8Q5J4G3wdK^4PJpXOE0$MO`1WKX zk?M^-DH=M)dVh845j-Kmq1)Ssj@of4jtCZ&sI^TWI%Tq|pPA0?&JK%;r#`>(dKB$T z(f^TK!`WcQ{xB?Np%eW2a3br@aqKqm0M&CP9X~g~5Eo1!t*dZ>My(@!I;mC<&$e3~6~lmi^th zU!VLD`(A*gVJs;8qB$~wNKJmF@!fDD>yeDof=?h4!hZvNw74x!wh1u0(5U>=3=M4l zC7sD4{cR9ym7qE&ec+~6!2d~y&;ZmiJd*(Unyb(Fjc0RK`2_`iqQO`cT*%oe2Z*|K z|EIc><9kSe3`18z(%JR(8q;OkCJH%N1uL*5kY8NT&pgLkSE}And4PjL!@VrcJWc?d&RU_LlGVs<^rOvr%e!_=dmT z-5nq&B&GcMMK1AdmAnS=JhFL%+b55sX++p!MXUJu-9P^$X|xB7Osp^QDyT$VUzv9L zA#N7~VRdp+UY|~w)c!Q-d@=CHmJM#cEvZ4AGDIBmYE&W}Pvq1zD{9Y9-tRw8vX$Wt zi_MiRR;T}<_bPlRmL^5DfJ%heQ1$T!qSpY8svPYUhM~kiY*PwW)tSgOCjY}&p_8aZ z_TwL#-+n+NxSne^16;zq=dMkGG;f`jjiUD?5hVt-rBg=OqF#vRUN4KLiRf`S--jtS zChHlna5JB(89@3I&IT7s@I=^Rc4%Ic)J_tg?taGl3&q4iFk9k@8$J5l*~AI)UPwq{ zvYOgiMOj<^j6F|lUiaTLn4Manmz`_Lm-zuiout0f^L+%J|5o~xG+7=`OM4~0`PJCi z^Rw=?+$P=kQ+K)5jp7VRj|N(IYz3-H6qJje#N(Gz+dh(i!^z5BeW(omd!)qy^EQ)< zwO^Ber5^|*N)ZHpnb1SMRZI69ed%t?`r-!)bEokVZka3fg)uv(Nl&1%-sc`2z1bI> z6C1R@)&B^SytHV%^p_%!<8I+g7qS*KGfmx!R;N5QbM;3LtjJsDC4fXY^ zDQv_t(N{y$l{sG`=ll!#KS=q|^ljN&l>Q^eAk5t3*FjF>s>g{um@ldKA7 ze|3=cuV;}k!W8^IFbnxxL2(C=mqX(xS?~7tSCp^dzkh00-d4RQFn{y%#p{o(FP=s- zDOQI3wDN?QLxN`&E_&86v6B7PyhKD)OVzXt1oIL}<{F|#p2UR#1&?;|%CCqC>iM9& z|H2?Se3&o20S#LIg9$n&)EFBp#4O1bSv%+0sSMcuae0Le~t=>?pS%K zKgbz3|LKkq%Yzu8j>F$Q<~OPqZK_L))$-BxZF=S~7(&4B1BK97Sp7sVJzoeu8!|ym zJn{m7oS&8;2E8ZMn&KH_m5k`HW_LuBJ$YZ4;|aa&{@|;lD1dppJ$|>Z9c7$@*Xtr zA;{izm1X^%oghrUwyzMUx1P{N?Z1f`iJxPR$+PNN^{Y89l3;k78 zo=rY&XM-Or3s?P9=OJ!nK{F|}3gD!uvhyE+=BS1NbU2IQ^xxAYIu1Brn~{v;cx75` z%|cL+j%njIjW;Rkje#pR@%XWC>DY#o2HE(80@7=?a``P>PgCpHTk#u~F;%5ax+afJ z^9Z<@|Ee5)`9UY4xX1y)|C|B|BwGVOmu+$12=vc5o?BIZbFiO~3njn{LD>JWJag1v zqJEJ=M;L){tI0u%7POn_R3S6^J>mleS9`TML*k=>00&V6MAycLUj9R!TZ^Af|73+_|?^O8(_cSEH%2Gy&e(qt8&5AJ^s;cUb=`ACTHJCZH z|7t%#0AEfySacA#ZV8+HB?B=pNKh*{ze{&V%Gg6KiIin4dtsCeRVbe($i>^2Kh0!K z8WW$@FG21q37wfZfugLe`a_fKH1FBKHok|MBvW26SYotEw=kQ>Idp5M%rfCCtL)MC z&jgJrwq}o4pT~@o9T3E*>7N)sVvZ^SazQETPq?be4cZvg~f9(_huVfGv(eX($W-drGtqW48aE(kaCgW5?&E zkzYUc2GXZVuG%m|BXGeKC;b>-Ke+{|jK;EF&F3c4@9wsk&abNqSgFPXAvr(b(&EfT zek>|wRBI!qXOw$Y6VW`=jUu<%jb~t;4@`MHG;oRNYyY9}W18gclktlkRVPXv4I1tz zEvEHoq`ykT)_ZnTQ`EFs2ujRf40D*?`~k87lLuaPv35KO!_exejvT3A)5T_|2lmax zI)y8TbBJ_4E(=iAskrbhb-q{36xP1GUB1^}^1ilVVq;5$m8jeUBJOFXw^W}ft2Xp# zeYR;2cpZn&o>6?-^*TUaT%8U&c!Hel=gTfu*CQh%Pp0j*7KTPdcCx_7dpR>XbH9y~WcQ3_aKrO@)9uKY|7U)8hju!J>O z#GM<8U#K#w>dY{z4Zq(ANVOHP@r+5=P@ruMHzZunq7|AdDE&DDknVDH4HkBp!OdSa;a`s z0Ay#+QIT`G)yEY*(Pj6mq4vSxNQo73s|IV^?U+7WUV)HQF5?zodtBDnjXNyVWdeQf zwBaL>6emh`XtQ$#UlfEm2&4;>in78RcAH1A2iQbh6iK$Hw&@VB?i;X=)?^$#8!J+- z4zqNuPfN0M9-9Tfmuzvgm@=vxDtZz_58x|o=+%L=g>w`cN~Zp)64uFJ`R~$M#!VE4 zRv(n1uzi%{F)8dpzP6(XZ!dxG;oPP_zGQF#cQ?tk8^cLy;zxUSfG&e#GESWH*{p?v zwzhU3I9&aTYQl&zTAT|c_|-SJQ~}5wN$|_lU9|aJDA4%bvePJfd}Bh= zYv)k)dkt@qu!#oI@OeY1CE;;1+o$Hzd^JZ2Lf`zLEEcZ#yYHSh8WDtC*8J06DAZ5h zgs{D*aiaKCU7RB|P0kvpV16=09~b6S5~}0h!9ttni-`#S^`{yRcZ0cO-wmrc989Ba zhC^6`XXx(s8o<}^7?&YJ6+K$*@I^2W#ASy@_#QP6UCP>D>kZqe zpSO)8;Woc`JTGbQx*j9Do??-Si*e|c%x9PBxvgLr8;DMH_1F#OslY~3`%OOP7u?Is zQ9xAj`Z%eb1=fsf%BCtpS5tau8J;hBRFvtrOds#fRMD~^7;OZL-Q@Isur@Qxzq#la z!`kh}xR#C-}GGu3zX6nUrP#pIgf+wb$Fh9pz5WT zN<|SL@U#CmGxIu}+Fe3!NN&v6Q_UjkJ+a8w&|*4bk2L!nsbhOn8{C(R5~3Kh{-3=? zWz-|f7N^<-OJg0+aL66ybx;V3rV~@02w5{@myIuH*={3Tf%Dfblf|y!{#>doT_#3# zf?b}>*PGivsdoROqrNeW(K(DsF=Dv&ziCoGjSu|7dHcPW+x_kNMyl1v7+4nvrQmJr z-PLZj_pQ6a^}b6xnT{Mp%u^k5&s3OB^CQD0Q(Lg3u=hOy^LpCyO~Jz3eu^CbFHP@$ z3=skC7c#yG%33;}XEj-vEsn>7jKSC5$kTXQZ^59UMVDopY2>Vn9!8d?+}th;g+`g> zw$pOE*$yhdA%P$1CZ#FlqMkEf5WSAz73$kgr*$2+^OI7yK=-7j8s*iERJU8Q$L#mV z>w%w0)nZzxJ1u8*!Jw~mc*0a?z z&_J+4x|)i})P76Ow?s))e9q>4sZ;7 zwzIm56#Cv+dIf8DRHT3l=pkm#O7$>XjeD$@5gPh&haiXsNrOc|gT#>N3TYS-3pWgev<<*t!>e(DC=v8r4=X)>pwHBdG4rXRkva1-?zp5Hdi3T@pMWv z?Nv}z`+BUx`jjSYq0ubM`)YekwWsi%kR!;TqvQ4ytQ}mF-g!cy7}52fKLri*cj;$F z$QOgEQeX#4%9I!0@N%b;DKQ@@F6ENx;5>|l_Taie^!d) z^?ieym5a}QPih8y>i(6HNMRYN$+@>r3)r1+UjKD}K;h;k`$3Rp0<|v%12K@xLb7S$ z?X2+Si8gnBE8X!x#-MFw`3YV}eB^8R?r)I<;+gI{Of{bmY5Gi}M9jTeY@0R`UvvP6 zmz;a+b5<2~#SE|pzh_^e2viUwQTG$fmrTGI%k5jNETVXq13s1TxCqmayHUGW!CB-> zS9HzTI6?N_-Fv!@876L2ZF-Oaqai%cN^#RPo;R`KRAQq3T36DV6bXrJ6mq+8tpf$2 z7`bj_RaT;6OK0;Ek4C<+h(jmj?E$~>E1B1WYmYD>Sh0veXJoz0&_qjGp5!N=B|#wl z^HecCZe>yU-vv;07F;=M%{{4^4K~?ay@HEMk8FoHh0Xp9yYQl?Xk|K6jTI?U0_SvECIIY~{zC-j1 zWNeI;O0_iT1qq+i1-Sd{+;pg^AIbdY$|(TvX`BOZ-u&d;%`?AgRv zoYf8DX3Uu+l7$X&ME+I#RmVT{;ZM5OB^xRm=dY3Pbd|;SRib7WF+C1q-fiBGaQ^DG zaP`uR!>qLx-Q{n(iZ5n>_WU3THTg`tG>lYuoj-A@gQA*+R@D!XQa@>iNS?R z-aMheLB(0Q;nF^QlTuIU)9A-xHWY8F9~K%+6#$!meJP0Ous}+;FJQ(y`rI|;j@`Qdd?0lqb!fAs-^YVlzPtkr`jarJ=7_$>@0qI*vMFUy=sX@%?ZRD@7*F_lA%P{BEP(;9!*`yA>pq7(Ey{89?^oq1E<#V)wkkv#hA znq{$#x2%p3Rw>^JVTL>B%f5t>Sf(kUaL_l1&rIi3mFWo!_Ar)vVWF;4B>MV?LY24{ z!&#=5DXv_(5$Jb>&C@PP+Lv;P=A%~0YUH9bGS8!!nG>0nQ&||5$QaYGp6+tz0FT1g zR}F0Oe7Z+E!NR7rE1g0Q7NoSs&R>KLbcQlqmfrXyU!-#TmT^=)spsp@#hhd@_&D@aHi z4hJEN7BtZm)`4-;tYm`~d;lIX*+Wqqu`6tBA>ehReSC8b7^%rzO(M8^`ZT^&RcF=A zbkOwtnjLkNJ)Ofa;IT7rn)IHycNL-BBeNH-y17-0bP{;x>9g|kl?GjeB^Q|(A?tK4 z+UdLTGKITK3F@KmoE0UlayvTx3M!sC7f7z@4d4|%gvh5>R#tJD04)nS&RUY0k`6=( zb*V7e4#>7#ZN*ox^xj}LMAdwGba|xV*hrlwfO)>)@JU$ui5B$2gSd+z5!`3_G(SHd zRRwz@g5whk2t{K+eqDjys8d4bOg`mqKk=&JfLQ5z<^1+(_&1cB$FjY$dsliU4pyMn zyW22auAeiZ1U?`QfM1eQi}+dCS%!PLCY5c%kA9-zg}3xv+V>jIz_jtob{(|^A|7Wb z0k2SAU)*-yA{wzyNZPxPhS&WmPGPHFdly_v!YXsSd%LktE%z0z)t6RZr?pG5To3rUZT3~@~Xjh z(Gmg7(n(6?Tol(YZB%rtlAxAbPm)9lYP{!&03$pr^F|m4iK@d+ACi!efJ(N#zyEYN zqR#3YfVOY5V92B*qPkmWKp-jTv@iEA>0@{f&9BU9%3{rNVp=PVB3wx_KC%6JTo?6o zd-6NNmY$fa`zIw+3$whoFUPt}L=YDnx>u|v!<`oj@g=Vv^OFtSE}<=DLUWXgzet+Y z&eh}~S{+Xi&VTepkma|vd9Rb2jr`%XZh$Gu+z(y1IcH+8l#TosyD;rmhd(?m1M}DLA2081&yB>L5|W*QYaGMwB+jnSb}8(~ zyz1V+YhQo4{nS+jy(GO9?1&@YEwD2wg6|Gd*fIrT#80X`uL#QVWe(Dbr+pjEsM_6$8f83r505gAcGLyO2_**AGQB2Mh&Pw-bCnH^7Q zv_+QJ^f3)SQqea<;1dM%HXOV7L<}HMKH58Wy#PaB!uN-Iqw2#BHv*hx>dnCsy-;ly zmU3=lAG*!(>&GZxC$l!mZZTGJT8q0`Slb{Vh1_XJ{wB%ANvF$KLmy8U@uw)i^t7=3 z7d@>pW<-&|E3z^Ki(8VX3OJpqpREtks$n9$gkPjy@`3CGU-kHSx{B7v}5}eBR%( zIHha_EE3gsEFWEy&9ArdIS+@WSxo^!9yQ2@qzU;uGiu9{G8NW-_p~LBPO-a$Dry!v zi^nG|!RrSfMGfxuO9ID7`hN0lNzGV@-EJp0UihKlwXir$akuC6cZzT;pU{4@!YP@5s)xmFe;_Sm!&3Os9%ezD|1F1L$$!L zCCSfOh)cFo_T7^Zt?7;wi`-6XPYWnq6RaNnr35z)qM3np1&|#ZLy&_rEZvT7?g%dz zmk6~rzp(+qbEggJUeHI|QIBs3QlL48Gu>^M%wK75x&YYjOmpCXM_5bR7WDp`zPm% zK>uNL^&w57sR4lrByWMYEHlaO!GcF*DW6LaltqBIQMNOc5<5FPKl!ZgZZ4fGl&5~+ z!#d=?H#CQrDxNf}sEdW{#>8?EM34*RHIs0ljy4^DN^Yx@mKY}`;*ZPeX@Wxt5u8+y zpXsiO>YvttjPve$F#k;XOqs~8!>=t9jK8i~dOqZv=&a3Cr*n6H$~bH&QrnrR$f^;8 zumLBQ6(9=Pm;TjJXPT{EFsu)dj0(`ecmD|fr5Qqn(+=@7Le&VNLPgHL zLYOTnmHDLhjS2g}I-cM<)wDs!SRCbPjwH~Fc$4mq+qKD^oa(!5fsv8%!sz+4$?ena zgYs?s#}x=~Lm;ABUOK=Q2qZQdL+DxGy6h)KO#bLQiH<=)=(te!zLY68=Y=kE?8Qk@ zb(MCK-eTD|hrx9RCbljaG94d#cnQ#iG{h8Eo~S|O=$g+tyuj@duG^q-d_ShLE?}h} zG0|Ag;$eXDFhengkwH4z?h9}5;l=D^TcM%n6I@K2mLPQu_QmGYPQq!zP!>-2VO~sy zvYlTulRK)HpPOpdJ9)3yvox#|Q<_hvneNteX@^SxEpr)dDI{s_3lX+pGa9e!6d1s_J|V#g*uUGc^g>{!0yo5(&*6aa`031-3I0Ryrt?AM3~5iWJ|2b zsrO|dw*MJ;!>*LV=I^&y{C$_*#VD`LNEcy|p2rB8*3Q>r4lCWDxlO`&>8zKpzl4o{u)@TlQ3 zz1Z{{CQX*qC&PS{vBnuSdzAOayWtgpy+x1S1DoP#1|JfVE9|eax`rx$@W+=?Glen?t@9D@#W7geYw3n)F4V1YqtVE)@g=+L*53(u2_$(~dwM+Gx0dJ_w?~tS zE+NYrwV^%I_`*o)#^_R88aNV}Xe+R=#Huzt$sVW~6XZkCg}}mP4@g9Jd;%+AXqomb z2lEHn1NG2OPz|{2)?1kLub0wKP z`=(77JqH8tF@e;?f&%pnh995rb=~$qiK(H7J@sm2iZu(ni&88VWj?(+&9R;iK)XC? z>K|MLW|)x4=0}Pd^#V?J-YsoPjT|2Wskg@#!<)mq^SgNpR5QPCv_Pm(U~Di9?c$k4 z2LuP9-_-n)m}6~^uOJ2*jk=4D!GN!0vjwe@Kn%Ay=h;;)b~-*=)kyP(JC}Ug+l|!q znt;}Xo%!NrwNM|&JS*zX@$3n%5|@;pq#ZX7F87Uts>TO4){S4tn7Of4L;xtypyO?; zhy`uFqMr#AyN9s>(K@f`1d>GQTP`(QJY2s2N{kU%eSp8NK%I86?p<;JU67A26P>*~ z20&Da(Ipa8Y;DgU?!hH0zV0)jU6zM13|Z)}-0b)i_A28F)$)koF!^`C0IG<0$gbG8 zKKLsSnW6G@4Bsf|1M2~>s~%~y`c}}{nZoM}7-JIgU~3**EW@GB6-A9g+E&0Lk*C&i z@cZt$g1k|T;>RZm6H#RB-=~f&T2hBZufBMn`oDbqEnWCk^Xc}i*g*aQ2l~UfL7WiB zM_zQvxI3K6Up{%A@t2ja?;4CqTNB_rQkdUz-1eWuN#{sqAbkRI)#UbPRT-_+G4{th zZTZ_Gu5eHNjV5skY+m(IwH#MfJ+-0R5~qr{P^u@_c}r)(vGq)cj_YwkJDF@p7VP$C z?iV6qVIk{ViR9j}GaLq*uE0HAO4e+(r`Wr-pXVa?JH9>Bavc*o9C-(8tq$K@{u&`g zQG?;3^>W*yry(6sf+ETRgu{OMiAEhM38_#K} z;Jvb+xz-n{I(0eC(-6y?f?9gsCtEd9Dh- zd(=?TrsRD&ZP4^)8zZGaP5CqPb>(OP!Nc}L#}@7(fJH!U+@a05l z$aiIRIlyFgxX13(_4=nP=gWig)8kDEFSU;d`eYCj7Hew$v*6XIcu~u*)kGE|$sowr z_1i=hxRzeHWDA^aHkR^ZcUpK{#;%W1*!TF|x@Ttw30~iS}xWa2tTTD7&x4mM4>u^utmww*hnnFH(Z_e zFVY?Zo^F(XwvfX`9%f2QyrbLPY?Hwm(pjobUoR1z=9+Hh(pqaTi^9J-?b`{z3rgp8 z@w-X7>T0w-ay(7oeAPUOaQ%)fO75*h4zQ5D?MhbEQsrc6df}NlQ9I)X%R*J+aESys z46v&JpAUS_8R6QAkKhrcLnxBnK}QH~oQRN|m7HzldH40B49w%THgnyCp39;R4gt#| z^2exz-_P}{c@KKlAYETS3%J0yL;E zT3(NUUv}e${_Kq(_uqOnkB!^RBw~YhTgjH7Tfq*3XwBAjUzJIrEFnKTdBT^>2HX9u z&zmODl4qO?M&CC>v00Me!%4N!_>)07#eGCM`#NO41grIQlO}4Fv$5|q2%;{nrE|OF zdalP8AM-`EF(#M=Ry&@#UIJZi@766U_Tqo=Q6^gI+pL!+vB#HNqUo1TC>boeOMevd zYA#z`grr&NO3FI+J)eKV8bmAboaEB};E-GnvW(i11SgHbf6|j?uZS+c4#1H^m$2cx z(JAe3LK{{d6HzsvG#p}Ir>z(3N2ty(ZD^o&u4r=;LiNZ9k8Jt$F@bUUdOJitfvg~S z9(7ZEnUiucaF}EQV>-Ty(lM>$t(S`vL`?Fqg?xH@_igdzO$0YDOCu6I*8CRHv^%PQ z7e+6dfGq2?OLAsRBwFUWvQQeVt$w zl0zroH_C?*tA!ye-T-X-JDv5O%n-XQ7-HH1LKyyNjDCc0?$D|>c2O<-g%#9Db(j{o zi#c4ShqA@)&A3`hPbO7=&Q6w6rPB0pDbLohopZv&D{{(h#;duD!~w z{F?PC3a8_R>pHHw5=C24kNQ@R?3dn6?iK3WQZru6=L4~`0Ix$S8rl8DiTP#5rjW-H zShskcm4NHe=aDe!e0QdX5%yaXBo38$*l61V6)Nu2Nwbt{BJLwWh4elYMCrIXiBCwv zu^7A@9-u*-+V&|&Dsy&`?tsE({6^Wq-l^G80VDiq-nu=pz5>}O{TkCrU@?2{K$pV1 z*^k+{z5PN2;AQa*x5sA7FgpXalRlXRO|W)CsL_a zD`!xGx|EiM0$0e-G>NsSMzfsY8~K|Arz@rjB4m8W(BtopmYbox1Uo-#w7#V3Q8Q{J z$wl1hix4_$X?A==V*xlaz+EI7-M-Pj+X_cr;C+1*z!GN_0)>cy`PP*-v!C*_+E#~m zP~9CO*Bo}?HIKtHPd^O#5-Eh7wRrY@#V+H-VoEF81O;`wyh3VaqbTc^O9QY%@DraK zt{dL;8qR#Ww!1&G+b-piP^uKyX|T;;(XF?Z1E~~TC1nqX)A+uGEen{aSJsTHqpbLr z5~%%o5H#i;1I6eLuB;^qH(X`tBdA_x3p;NESK0L`3vQpmHk#wes{9mhlpUyLXs;L~} zpJL9$zWc%{Yc22&^z$)lv=1r~tf2J4hDVSE_;(c7mqA^KNboqE9Iiey@VK<&wQ+2> zzWT+b(X9pE9FsDB%1yu8-(O_(ctd!$GHc@Pt3IV-AMA|uN!GZ%?ewmwdt6eL>e#Z;J2<=p zcv(jwl+%^0D{&YYj~joKUoJX~^Ge^hTzH~*oVD3cv)tgOTq)x?XbD~IdDup6=!U~= zINGiH&>*jwY6&}TS6Fz-8fd@D?bl{XG(0ClBEewG8i-fA#aBJ6t2pm+b+~>e5ZRHNi-jgP4J^7rQ z(J;b+1HP%DE3XJHJJo#8J3qJMuvZ@H$*=3_HEwBFcJwi;Z*HZIlVI2O!_M0Q)>8F> zM$d6|CnWcDPm9Y<7P0Rqj&{qLBGq?$4Q8K8ZqlAwbM$++Z6aRvtyA3{QQ?bfT?s#| z_?r^J^Zy8F@|Kki#&j^+!N8?`DNf0+9Z=ks}yKb9gnb0-rPx$l3N4f`ni*@i=;U$DUrleuWIdt`5iE>+Rc*&raCu zDV8(z7D-P#jC)Uz*jH9+c`vl7pC-_W`$pWmvN_-KeC-d`UG!b>HM7OFpq@cC)an(F z-kF$sJ?9vhs-Mw(^F|@KOl0nf-8Yw^!p*4x#5e`hSRJb#JwP+g>w3cjuo%s>nU-uc zJSreDCM`(oK@K5+`R24roZp4-8{{J9Z(Uk9X<@s;1eVGI8}Z4*b+D@{HI+@U_45r_ zkJDIj4vLit+_??c!?yWbl45V2F$+Fge|gtOVlnex6xOyG-L$Q?qvP0lX!2jtLy=YK zeHv7gSkh?%4mJytdmuKXW@QD)G?|ce%o{It#5&!xRoZ)XZ0cvLJ|#yRNSmAAoIGuKZ$1cg}4u*Cm}Z zv#}|yb!j=jiAKRWY(X#XU}57Jk@&zWBirfa>lFCu^xIRMWug#r#Ljw66LkO9abBys zId(?7Y}Ffc6X@PdaY(JYR&;0#IcD5EPgT~#i18Cq#yMBXtRoRlki+BW1o%4Rw8#;JGC7z)U%NNkSuq{H^$DNo(`DIyPIm71bbdxkY3I# zSf=FMamS*PH12xPZgm1o&XfYZaPWzr#uLW2~*r|9d)o)j>VxiD)w z!gs$}a$mh>-1O^<(6v6kBCcdemho416F(G|3H1I-B16Els`Yq?`S^I4eYjurtO_jf zPHZPPj1AB8p%g)SprBAu#St!$Yjzhhwi+)%@9~DhwHD5*%tB}KX$4k6tt zp@MWbNJ@8ybYHrqyS{_|-}n92VzIcyJ%>3nv-iyG=l4iP-~>g7ZUO#e$?h3K0#v7Z z2sHd=nHfS7U*=F&5Z|!H^oL40Eq}hPF1>9cd0zN&(&hG(>m0AFX2GmYC$_#08HjpWohJG}o}E-mWpNgM|?!T4wZw zTreTT4BMaWs?EQ#|FpKw%az^xr#{ufyK*Y~VCO*D=>g*#*F~354{pZ&>HjWu1@Vv9 ze1DSVXA421HE%_VH1KLrpFcSwq?$hUO2|<3E(TEc~`xvdfFoU7$h9S zWH&-A+7=^5&pnOpcgTm!l9t-rTJ(59pDfATPZXcDU#>geFgQ&tbsA~^s*%Y3+OiEP ziasl*?t?wmdr)2>J*e83TPM@+UDG%VIr=QN7kl=NI$9z(^7-fX!OQjt?$P4+7otVa zX>=M26Nt$tOA`TNA5O)W18Pjxj}tn`z(SPtrcs0$)fXw=J=vmpDhf-dG7cGzU}5T| z+90o2$FkY^L}%GZj1K8TnIs}Zr-X0y{eIS8%uY~5pK-)Vfu@dTig}{&G`LOc4xRMp zP!p7zh!z7r@B~&%(!A_xizmV<+GSUZ{KBu|+prAs3V?iUnRQ?oEA*cCkDk5lpN3Ow z3TvTB4(!Wn_eSCBDy^EB7ojqt7dPzMF@f%{Win6{Wh8v(aH~VB+Sq6H_3YY=6g-)j zVYZFAixU%#ebBxz*Czf%d4Uun|Qry?#KZ&ML{ieGaU!I)MSED5f_qo1vYl}o24RGx873!!?+P-89r z7E8KBOf5Ntari#He3Zw7V5U2^c0jjwcq{OfA(81}fm{*y@Ih=5#h3;S9}%%d+K%^# zW?u#?%S83-p;FpC4wc3JCw;bsjEI6+I5HF6TdEaJbrWa5-4&mQ28N)hPk|DQeNcMq z_0yKVZOwsGg7JK@KYwZ_C!&`;4O6W&3mu{gT>Ll2TPuP%@rB3&MC<78f`Kigbv;LR zZ{4N9v9SHpa4A)q0GKNsc!_dff73M%O6A2whjQ?cczpeB1Fwb^^; z3jua9=%mGt&G+Rg2HLEeL+o)YNHB-t)_R1Dpwvkue3PMMfjg9t+C(D;q}((Jv!r`F z4A(C2PWLE{oOC9#s=4k0$T#VAMo}cc?vWEUM!c;#Gs8UR@{?{ng_vS;)HVIJvod_Vusd_srVifddTJe$*?OsZ}Ext^YsR9=9a2`TjY8`q3`>P zmq;m~;M{$6}`(EwCP-K%$^Iq#!#SjX>&=w>Mvb6(e{aK6dH)sT_V|6S0XL}D$`-_*39 z7tXkT+{@72>zWdNYzVHH1Hl@r02bzNrQ#_$7l1YSy+E!`yMcbfp8jRk2(HExg9sK79-_9L)6UwC7@*Y(A3hb}&N&X-^d`lvPe~*uT-!n8d zG?K#P3f!ggthKs?UU_B55t|UfIBKYnky%qae+f6eq(>cPe9<|+$s=PESWu;!>bxUT zb!`7#xFJ(*Lo>cFBaBE*fbJI_BQ(l?LV-pedWafF8@G;!^6651MBLz@f%iy+`~#i7 z*X{T3?4Jm92wRviq_MOllU*jY18w2n%0cnr0RV!A*Ay*w@9tlF6vW~EG#@t&d#8b- zFdbS&PR&WVUTAn%z;+hl+{}&POAefTUrIU~7ApumvB<5|x+l^gsQeN1e~w=504e}y1UZ*XY0?7a&QBM8yGqQ zn^M118m5y7;>FagfTaORngAlX(64N@VlEhNJ0?D4jX1b{UVJ(fA6K>VM;r#)2p)_N zeseSDD@|`NjMpOzF2ZP)Bl4y=NJ>Q>kJ;!rkkWX#szfNkJRrms$r#m9#~=&%urOU? zM|qkdsO9di-M%>%T7*4n=P~LehpR!z4|gYC+ftsRGqMF8#vuy4+pnltZt5qyivA-0 z{XUQ8axTPM6z9f*x{h_I#3+{RS6o7gt%ng%nJiQ#xuKDmk4#@;YuzFe!lIbOh@gfb z%EkGPKF$zpt#zDmKC`yDkw^`wU{Nh+!@dgzoI-|J2^r3J2oCY!p{;mqG%YLe8ib`y z*9GFH@=s_8q%k3)xCyR745+L;4Wa&?_F@?&7VwB>G!^>5-5J*y)LVbL4HqRRSG*?_ zH%8<ne>zWuNydfuf~5tu(0`aYRF6Q+ox8#r}R=^Y>Ym z4I+9g@PsPae`~*DKf-mOqmiN^hCwdbBt#o#x|p;VMTz)z#>+Bgf+C?vR$_%Y=v%{a zH!^K@pLbO`8(#Lq0n!46el&x}wUKx{c=l_?x4y9@fT~eH#%&6EXp*e~XpfvI5mEncDhtY6@K;9dnh4Yj*x=fKh0oV6-Hj17hv4WE37s z9odF~NDVy5z7Od{P9FB`rwyfYCl`6sx**rrza&OCfwxOZ0N-3xkosx`)8q{2Hu%b! znz}IsEMq)1sy)z@^AA*_23J^q>q>+{?#)D_9yCQMV6p0`S~YHjHdyFNsG^wt>dBDs ziDJZ}3sx?$)4pw(;Yuopa3$`S0J*X!;&I0z`EjUHVRSH@o$r&Vyw9J7TaVf{`C5G~ zN!3HrU2pF8hbZ1wpgmrf=D_FU6$Nge+Zo5>B9)shBby_v5Hq!f-+4n>o@GQkCtsAP zw|}4AJ6H5VBh2WR`0p~^e|#ff2^1fjjD)_YqmNYs5H9bod$9Si3J13&NT_xQuiC{C zA5Sp4@i>fgcr%U})VuCF;$=h=B`B`%O{tUB26#%-BzA;5PcQJ`y zqBFR$$HJNBYNwvujH0DSlZI(KMI^p7e_SMrUl%|%6H0}E{S6nx6502|RGCbcePi^OxpgiA{o=<@0rVm+F))HqxT!oLhlu@M;Kl%|;*a#j-ne zFCO56xpo;;LXixIK>L!0 z>cYUgC`gDI(=rc%#M@ptStC;7d2fQFp!!$ehzn?$xKl%VP%G~gk?#iwpKPz~7a26pCbvjlhF5<( zWPs)edLc|gl7{f9ZyO1z#YP-x{SmKF2|@|OTA2gADB+u}dIMBmPuhCdnO>pn7=I6Xobk1YeRW z3~Wf(Z1ld@Yt+vuhf?87Z{J~Iq|EvukRARoXb$A4ad1#h9??-0cCn`V*7=5H$BJMv zX3{A5^IB2rx`_U6+E6AfeVx{gs-*|D-#pO8lKdP-D9W+Z(irYtM%#Axy*GBxu7u5M zsJV{Lm8I+&t5Ht_e{6McSXVeJ3GRioX>W_ z*Rxo0K{Qyp?$RIYQk!@)CdGv7^P_WnazmH3r@W%bLtBR^oJZ}N8IC>LIk<-}*BL6V zpp~MUyFmN0h4B8lSo}w>&*SP2Gx3_Uxhm9$)jo&*4VeKb8r(A_H&R#aziuEW+=Q-v zao{37Qx*L_1@t>;5_Vc8dq4s3*j0a_OL?a{xH8`_sb{!hy~j zueQNHkHS}DoeFY5^%~P@=?(Qgf^4!Mdw`irsLjB;7OOAJ{w|+ z`>a+p8NliGXC8i+I{zMfnwe06rXSqB?g5T5Urheu)7_l-Q)E^7PM%n~cz`*25LMUo zGy9BSQ-fAlA(1@$M+6^Ey}aF$Rj1D-PKy~QQG8p}s%T_d8AKZ7h(Q9~mr{bN+Bsk< zY5K#DglXhh9NY)QT$5=L#|xD7Uh%<)p6X_f!F3ge>Z(q&_-HMnx9i=W1o#yYLx6$$ za6B#e#NYCG6H(N@7O|Oo%h;gqDPNT{J&e z`|p>5W>Xy2YK2u%0kbG%WBMIWy|P66i?k8q=$a@81&jRtz=Q+LK}^d}<|Vg%Lu%=? zJnu4D2}V50pFZ|ftxef9B0VNYc>q)FUOP99jfb8B;R|mDiNFNSr$*$A@E=sePO^+9 zYU{ma2lr0gb9|mOG)f2EajkGa1p`jOxNrZh9Ny;@YnGr}8^=Q)af;YPd6 zR7(K-ZNaLfj_1k8hj&xEX|| zPxcg(VWKGc(PfH!{tUPDO2iedgSS^jPEXLf14Uu6+y zl)+=&YQuEaKTAdEB>5)851;=0(AZtSWtr+Yb-iD+GF!bzWwq6t!TPF`;=WywBWK{l=z4?P& zP_17Nh?yn;D>3ZRTAKabpqom62q!{>?eju!wYJlXiw742nEHeoE3`J=#mnbMTg^{-&++&L_!zoz@V!yPp>tUK9P7Qt5AEqf4iEBH_V?xkSO6R(&i{tdZ*iC|He1PJS^LUra+bjd?-*<>W(;9i5xz zB#zqWcShLAX88W$83FN5n_-TZ{B;r+0dZm#wZ!^Hgp5TPQ@_ey?OB++73m7e&d{*4 zZvED)sLm0R&{)_JKy{%RQX#BxZiL2pCs=l0I?BZrM;y`@Rko6>=xu52rr@w`{XwKA z2Y#K=%353R#SO34l;_tubTrpVH7h3>t7&R7X&U;Rr6E1nGVxA(``$>#VYj#jr?E8+ ziIo#dIv zt5r>eqp%4w(((l53V=Y%+Xe%jyolo#6>isTue*_<)qQ)e9v4wkP zFJ-kUF=N>L#_}0)&zGIfyMno;vNyAWRxa;8y&iAfxb)q=A{bRQt{I;22U|6{NR$iS|c8CQYxeP#vkEMtZKQ~pbBz)_W&SDAP~OU zt26^?M5Ef)&9CKB#TMMPnkqN^_G~aUKDJnBbmv1<6!k~^&y(^y$KPYp+cBivk`5+C8oSr6|>m{aIb$6DMpHCPRE=UG6nSYv*K z+CDX@)iT7ma-l{Dym`OsA`M_Oz`gbB3&U0wR!wJs^`n!kRrpm7m1Tt<`gt3C6xTk3 z1~3z%*zX}livK+9#$&NwT945(vhel!RjhEn{c^MolcavaWIP)3rS%6T>J?t*FXDM( z7yrn3`}o;%nce^ghT}me^S(`$A3G-c%P_C89HmF_*9RM$mz6$P1dr#Bl%G*iYe7=x zE*p8;%H_{7EXrhUC*R*M82_POuwvlAR>}($hkNTK zOm9*kpMkno02Dl{?D9jsH$O`ZL^VpX?H0>Q+`2r?+Ib_;lp}fWw)GQkFmRMPxLDBk zEEvf((x^xQ!QTa*^_iaiBn|}2gcqH{H$xbum6x8=2_>rR_L&P5E}Ej}b8e;;r8TRpcxDF!T)<8g-I7i*n3_!K73a%QODf z@hgu{8LKU{XbFOL6KBJp7KP=|F5wj0oqGvzm;A`ncnQDi^rf=iW_s^6@)6m44LG$R zx_z2btAX>MKhg@)N=MIh)JJNcuNPse8XzMk(Q3WVxF*@a>8sCq!K*5^2Qj=p`p`;D zfJ6~LTc<6;-kMS>Yq47PY0HHXPlMu4f?bH@xyel1Z$|61?+L@}j#q&j4#yVah${<; zz?}3oK84&TAKova3%Jk16fu9Jb;xMiW~-;Yk;ur&=typ#l|fs{> zLm@pOqFzj?M*+GSj*2A9FLB@5PHG{c z{Bj98lwi)Okl0aZJYvk4q8qlL}_zyGFx?_VoaJn74-RRhH*EVN3Rw_KpsXhUBY1H-TsMnLkI{_AW zSvTiu@O@rKaBYaQKUpA6k!IpiWVfQ#8l=||w@uB;U+mwC2Vm)7`2e!tUD=rnQst@j zgm=nLs(dr7@$Ag1u-S|}UQo%M8>*6k6yx%k>(Qi$sbb=v?pg4h+;kSE{GIeYe%R7v z{TZklns}SP_gaoGMXb4eED{!ZcnZ~%H| z4N+icAR)J+-iXg_2t03J-EE1?T#Yjty1WeVy@y0Wj*2|l#4pD4C9Y$aub!_Jt{EHk zHSAa_O}w#$y%4)@MDNh%S9Of~TGbQET3vlcW-Ys7pTua2KVoxIcawEA%5%|Zkdh)w zE73$Lo?WpQW_Q1(t;pHt>gr#(Df=4MNGw^es{SI2#Y-_qwO~;g`G}Ds^s}r$%Uq%Z zkjHDt#=C}-K)5iiV4+P(NePGq6qtMnZ&k5 zEW{FN5ho)iudZ@VY>x_Z;Vc3|mi@?XdI)in^@CbfMe^DyXKLanL)V1&yQ5C=KB@>H8Jvc*=h;j( zeF5*|`c!bTQ`|a9Ta7+9nj`M0GmMQ9R*Ec1?k@EOTp#zcay5i5pO~NgF8G1*ADj8> zQ@k7XPhWXwF#Z=!29g>&{7Nw!vV*^h=7d3Y6f)onqgdYNB%PtKa^g@5nl2s_uCr+Z zki?<9Ti{_Y1wC2sUHpTJTkdD)>Y*k(Q-+U}+Gg=eGDt>vNox4`sHkeBoy~!LNQtAk zfy~bYx0q{ToPL=Bv}pl*G`iD?;_^MWfX8D#9>!Y!7jePQUl8Ho%KsiWyXd8v>JRvQPG`99v$165l@39PT1#b z3&Q=il0532jq5UV7r5H`W$LcL>NW@r0;e+H9thpfP`*aiw_z9uWJGUs2QAr~GDK0# zoGQtlb=0b(y9C-oVuWZUe{Bg3q28sHM4^gw2w0juNypZU3nQ_}95?NmrFaqeTNS=a zvTow7|5W+69E)dBOXH({KI+ksMU|Y%oj0Ep*KnTs8F~&A^Dl*`!1>>C;yqm>_iOWC zPCe*Ksr-lcOapT9(+D$jMI43_|5nMT>EipD7;lZFZ}hZulpVljaD}G`2dvX)%EeSG z5gDCa^b#@r1k&*m^3)#x(K8>}aO5f|*|w&*&pshH-9^>F)85e+_g) z2sYS_n8{G=zt`Uh#pzKJ!f0MlHyf0KTca7Q7)s<`m@Q#k#vN#&;vouN4kfZnGGCVO zO4w4`@M`N+N5K75d|N-;ka9c;z-F{9vt*;LFi-j=*D_$r7BU)MLEnZ@Wt5ev+@phX zytY_jn`HG`;!AyoNZt*=IaCG5=F!fGdGTkBGdH-e9Z<`0YrVq1#vH=^iS1E48&zd1 zLaz)rHcHEnwU-^g|1*YJTx`QHY)YDXe?_*R5WBI)A?>MBZBmoD-qh_=z;eF*3jV8r z`Dxd;0MTPt>Q~l3c$Y>{GKAV3W4F-4_S33pP7?G~4%EJ|2cs$U7rfXpUP|{_FJcKa zn}n^r7KOElf5D?53@vDRUp-BLZ>=0bLLgc?vibuO9BB6#Kg1DU(E$ApwEt1+;0c(8 z5H91%l(9Z;(P1D0T`L9e3J0{~7WnbKu%HUPAn<%(6n?YwclPVzdk|<%P99;Ih4W|b z^*tYv$xiN8Av|o` zWb3q_ee33Uu2EuER^?#&zU+t7nSH78F6x_K{%6H^D`Ml7KoWwqe;V#PZXfwL2@J%l zgrca+4X`Oq?kva?VwC;L=FGM*J?xa98JF@Njiff~0_FYEV&;--G9y?xAJd{H#o^2h zP^Vyiz43Lsv|Co#?)+)F9H#s1(UcxoxLHa|$Nt$LzHwUy8r8P`it4`kx8H0$SYK3zsh%<^=fywuaRFkmc+S(m^8^o$D8J)t*T!CiiWmOa*v%}C z5XNv+!^4wA-CyrZCoxE${}vLhGhJ;MMBKs|a>@ZE_!Pf1*j3IwtX=GxZ{=qkleyR&Wjf7im=ikHjj#Zj?ZJI+!h19qAH7}9r=jQq|gRRu11!QOgtU z2N%TPN4*%ltg-XM`vKB_STNue4uSI&N(#B<%j{yIxMRrX#r@W4&iS5Wp`u$OY*nBlNN8V0?_Ief?%J~0@n05Kj4#ZPX>;p;O5~@1=a+W>l#cH zy?B;^Oy4uFMtBNyM~iRxvE9KdWw5Iy1W~bI*p}l_Xk?BctIc{tgRw4JpJkyU610}w zi?}||QpNot&2~eZzI6r&7^XFV@QLPLdK2ls0-Ma6%0~=~Rfwh9O*W2Q`(Mg8GKfAB zHabYnnfuShVuS~cX5M!^Ppx_i*>|uD(@P)vfcd3eB3AiQ#(N-%i`%U4NyL0h={hC} z`-@e_^SzlM;BJ!ldbca;fMUY1Yf`qlEf{5Zu*B^Os}+RP6RTABzMy23q7qZ1898tZzCx49mx2o z%YRS&USQmYL7TDi&Y0OA}y_Jc8zM)HK_d(x6{HE%kk9k5i=&t>9ERzTEObXn8g?}H6 zu8OJM^Wts#4-|{9(N(1VO3_1mfKLQvP=1M5lhLhuF6Q8rWUiR1Gzi4fjVirGq16iTACZ7s1aI%kVBNe$g7AF1Gq5v=;L zu{X~LmsNF(m7g!vp2#nduZygr0KM>11!k($F3?M-7yGw-$uOZgcO?A8MT4s{~O7kDDZ;+|2*gk2XDQC&V+K_erSOutqDV$RQSwDbbCg= zd<}xGa`z?5K&9nP=WW%LL8W2y`=MlQZz-9VfC1{+ABK>aJ%&mbr|#9R)5J{;yEqcQ zz1YO5gV><&)gPR@aAtmHDqra4eJOag(19O~;6&W=3a12>s8g?&mbU#=PioyLaG0j% z`WodWy|k_S7lk6So!uy_<(=yuEm7jyj?(mr!yj7=U7~`KXD_WfZ7-|@uv|XxsN+9f z=>;fp4UpWV>nL>xlyFkDJ^t;9=i6Z@z=v8);j;Re}rN)5V97Xkc)lj(M>cVr+L z{=Bti6Bp;DG{)28_j}Xj$YO6tLJ$#g_*nslRsv>z&Ts)?GM65Nf8CNw%1=3x>LgD< z?ceJk;&94gphEeZMCgcj11wqGBfXIwZxYu8KN{=SF}epEl7hC~y%EkPKx7 zYpOViZK`nfN@1NYQzC9?lp?mv|NKtKwRcX4+_W%Qe6J|5wJ5>S87T{(L^X2pPiTo% zp6kxRB%BK$gin`QW`CmlQ#N+T%X&^dgUocfIct1Y;m=P>tFh}zJqjsWJ9fmoh9?+p zLbLrWN$pR!Dc5xfItAFCY*LU|kO?xz*wsS%wQN0@W$jRvJtUB~7&QBJ!{WUt?U>36 zV@3N+(tM>TCUO%MNwwI3G0U62FA_dk)o$-rI3?dc4(A4tk5)~Ba(Xz^9>(9vyFCv& zA8Z?|V9|RUl&jgK-{~p(|CiZ_B*3LWM9xQ@R{q82g*domg3BuMAx!H-bU7pn!ltjZ z(M1D{ONDUVy2kA?Xf zO}meq90m>33864ehdl*9<|xT#+jb-PO;lf&kf&ijFLc&B=qkLc~n>(+8lu#Nt_qr660OEc8zAyeDkZ7s7yNPK6*6o|6P1*25GBf zYi2mL^3j13o?t5&>Cj3rQao8W;O$eqj2OduaFhPs+%AHwS-N4z@;rpsT8odqjl~58 zp1;|ipcgE}Gkq;}NZQ`Z57JlJYQLbHNS@--a^kVAsX?ZN5P>rcA6X$2s=dH}+5As1 z(y7f3hh+W_wV4-R{0VXf7p$X2Hf4Gfp^G*l0v6=M=`A(D>(cUyK9&|n?$HDyV9o{F zH*Ap0N|sCld=bm zJT?Zl#&To!UHs`dj4X_Yu^0)qm=WxCVCoe7eXz(DD%Q(Aqbq`B^Pu0=HgliowD9Bn z*BM9T=ut8`G4M@D|Ggm^CqZB;;@?pVHdPlAR8jdm?_ji^OpmCtf6E63Ex`Z_>^-p- zX@q?SxLm|!b1fkHquEofzK@#aK5Vd4Ezs;G1sZ^Dp+=n>*Ak{yr0mt*bNyf64g~x9 z!m5BH@xRyfsqmFTr}3l!*+`-!b}=o;_6RuqVKg(0z#>!-@#1d zj9*LQ<@+nWHw5lnw5u%R&pr+>n~Jo4WCA|@BoLnX8y!&z!03o7>a6_FtRU?@{^4i2 zLrj54B}g=X7XioL770yj!Bh^)S9w zMbH>W$dma$6U8+0$J-(oRagGMC+J7l9#i@;U3;%1RMJIT7HrHikoM_h@Tg>QB|{el z_*;?4{Z@WbF#h)_EYQIbq$3$7_+QhFD4{_SWq#a_C;?RFq)H~BK~uH2>0*ONH8qN8 z;IuQbT$wQkHoMKU%#hynzk+fSLKuFb{w>_J$p3U5ICN(>gx#sqnzs&R=}ZK?#~t|s zAP%}hgscAMRzU1uJ4DloGs$+BoBoeI>fiMkG8(i}#d;;|`FT?dKtRxNeQ{tY{{8U~ z`0+zE87}ejllM~S|97ESaa26Fv!HCVeJXRjUn{2_W!m6Ciu&PC=PTAFyaJJk;= z4$RJWCMv9^N)~4HLw-h;|8QIMI0har0LtG6<+31#hJY9RVLa%GB|I@iCTEb#R$B*R zQKNRrrU<$WcIE7=+Q^)J=+|BsJK5VRk{ka-G$7jytmkI3p&w$%i>h(u?A}Gyf z7}U_v=mWt>Y@jOQ+rSSIUDpf#Ptm$xTThUv`HjB40`EHa76jeCh>u{emyZ_MNXi*s zf8^*=KU@OcIZmy}Bt4+h*GQJH0OsTDT6euuxV~`UTl0vbW!ucR-~0ENe#L<^!Y_PV z7QRMhVBvb8lO*vNuiw&o{qVV^HvBqNA?-WidF=V01zj9|7#yjXZ$l)6 zOOn@mnuZg$Jgo(m{PBJF=+6nf8ve=ybo=^;WE$^`=W{!*$*&&uJumG!85ZLJ;Z3gn zWX}=V_ys{n`2CX+0w!5-w`E{^A~`S%D`#;HuRDsI$!otVaj$Y%RB1;|{%>aBey;{64ggN$Lt)_hij1}y`x{g(nOp>!a4 zii#y~ECmA;+Q zK?Fd8(&@ocbF6$BAJTb%7APQ2O9As(g{3AR%$*Fp*W|=(I`nppX9?ru<4L|xyTkZ6 z?G}Z3a+c*u!N|7=!Dr+4zO>h5^VA1t*#XT>{seW!Wd70XqP#rjf`b4%pIu!9xh~K? zj1iU6IhJHoUw5^|f~Ame$$N}~X)IR-7~aL?gI!$jmiEU!l_C>JZb7rge;K$Ll!w1n zWm>Ww4NLMPT(tvkz9)lO^#`?2-ERoI4Pb{BePN?-&h1ee|AxXgr>^N`{vO6M?F!Q{ zhiMSFY6>ER-n@Gk|Bmn!Qw~!!v8t+SauI~slW(WPd9^egb&;QI2mfjD2M|wAVX$^? z+S8Q#0T0qH|6$?T)=d}i)RxUi#i%&*P}7kEV#UD1B|RkbzoFj?;uopvM05SzCLB( zRorm;`?Z1T)T6RWNihES%PMvPVXFWrox+6xCj8~U(fglJgZ6R)m#{#aZ3Uf;tI4wN z%|nn%{%-L^M#x_E={0=6TUk2ec~*;)0u!rGt0>XKsmghWF~tZkAM@@Xk1}j>1@9nux5JwUVN_o+R^*08H_df0suTi0+{&NN$(MN-6-n{?e(dAoi*Dv@0V(d|mK_s+3 zOu8jFn)4h_{|J=kN|w}ZkoB@Ri~mH46o=#(-mZ|C&HnrlV7Nr>wa3Ln`&SV0sI+ki zym~}x-w8&$!lZ!~cL%|ai>3<^r`X%w=6kEk7zCTNJEtK5xoDw3{5-YPz^%j8%&;%x z($$dL8Ys`O9OcE!4p6s1R~UUIgH&wxF6%2}L@8+Mw~CB-qkrI;2n7fsw-2DTfKBrE zqGbFwcz6T%1eiU{A9dryqX*Z9x}S16p^8o))hK}&aJQ}UXi#_zs=|9{%`{5%Sf=F( zN1xb3X^dtFH%^XX0KM}i0B{J(fDTzW%G38hzPD)Q=(y0%Upi$xv{4;}%II5hm1G_N_NwnK+qoK}JK z9lfWyZx9|9$3%8=517C-|Wupamn8(^bF$^Go z|FUut9g41UN%6Gtz~_Jm73Fvuu_N;(49-eH^5e*QqM@xYCp&A9z{BlHF~I+-ED}AR zPIQWm6!*UrqdpppQTp9KL~8utnj&jlQyehAW&b^^bH;#&sLP|JbAYA-V)yM>P)O^& zBO)*o)eJgY)~UUNq=zE4lx}mH#~oVTfxK;K^VSW=?shn*;&R?$BT<<%9J;I(uaOES zq;c9UEq~3%h;;^Om85s`bNs3==-RF!?7TH1xk8*+mGCZtT$yF%6hd!5z{rmhZZq_C zLTSlF41?cGc&E*5dJ3`oh{|iPTwy%2AGn<*JHL+vk*BV6pWEho4AMj7srglB9SOqa z$c+R-nD&hP*Gvu_W18&i5=nmj0iPyu*q8X5O)Pu{dCH@@q4QR+zq6qKZ`zi1`s_1d zeli9>L-#U&tssMwPrm709KvXBw*85P4b|>ak1;Yuyd{Msw1@dinSZ)n5>N}OH!&+O z48J(Us1NXW8NkV-4W@#nr9o4xO-Z7>G9B)}_h}swMyWtZMhKzFOkxXc>d!_pCfc@K zJy-$PadBUU;B)d>qd|;A#jw!_Qeiuuv(7f?Mcuja!))TW>zJo4JxN4?#2Ug687smJ zjYF(5K9mfiSYd8N-oFkH?9;-Tr3HjG|N0A zi^DF}xQqX|Jzt0)lfGS#)2&gO6@+GjHV^-X(ivCg^K5ybzwl?8GM{juRN&uy|J7GG z3V2Sqg`T14vo=f)#cG= z3>Nz7G~J(-_Jc{8EsilHnNwEms#k^BlC~6U2=(EYkV+aKq+4k5D4H=!-B5M~#iKeZ zVX-Cwc;~dA6JC`+CK8n^igl^_0&BIoZ~n~1^P zGgFw&c84) z^%w?rrzYtOceQKN;+23py<*K2BY)X}&8S_{t*( zqCoDSeJzt7_&Rn?%F7)Ligt~whIUIaX!0R`^Yq0 zYXZzo)Pz>(Ug$CZ{?D;+!R=$R59>-^VpGL?(L4Wg;}k`34^0_m=nom;q2bZ(tQK8! zN5VI0Cb@Td#-B=Cg&xN!GbIA&`2C64!&_hQp1yNU{f=7(G#%+7Lzh*e-@Q4o3?=>X zJU`BRd1z4Iu(q@=d!dQrFroW8Jlt-I*?IAp?!It4@M)j6>Br9x#qy&=yirQSW{vpp z+LG=0DZE_Aqb~plzP0Q(<)DP1OHn$`mCAlj)f$me`e{5uWvo3JcqWu&jZotc&#FR1 zHX?=@M0xB1D9trv<9Pc`=gH;o#3oam(3^wirD&1Prstu=665l-{{DiUw9$A~T-q0N zmo>mm&BDsh!=vk}##Af25Y7Ll9{SiB=d>57y=pFY2=A^7W9~aXf6T8ot-f5xP{tka zjQ=;Z;^88_AiJdv$Kl>!fKoZfwysO#{ zI$KfM7vwk}-+@9t94fa3m&7GT&EzKkkJx?k{0Y4Qo3tB`uoFDKBS^yNlIz=u~ z$_7)eWDJHFX8%>B{8*~{D4CDZyO+&%Ggm7-;h{gQ+ddKQ0sdps;cQWTlOGOzz=yxT zpL+Ih4eZJR9y0A2G+8&2B3yDKg&-LeE1`LG${OVL-*M@@j(OZsNl}37XFH7GiyVIh z%4a-<*3uSH^$P&@-w=J5m6>jj0no{!@13ST!y{xkXvu_5Q5pfJ>2a@#KlI&gV`MgAD6e=A@HUvK zD|D3)I4d;leRL3Ja!aFx)P|z@OChgQvBdFByCVYKmHn1>bo!if>jFC)Bmok=$DKo6DOtl>zvhV86#vW#jb14|@Y`)u%$1 z479XP8#&Zb4?cqN1bp;%%73}Xr6T3 zz-7Zq2LXSxDlU!ye=2ON)dkEMt8dq1fZI$F9`F0#=#i?Zjug4!!^8x<--77SQ_FKi zskf_jzS$jY)@R?T#{5g4tiZL_=*#&TD|$Z;X?Yt5<20(Bu`qZ7MX>3!72!~p!PJ5M zk@&nH^qK7T2>~@92X?>p77{ADMVa^mNM3*Yjh>nb+;#(sqE7anMsG)*>BBih1i+%@qG#t5wV)Hq z;1#&QL$aObeu3G&^fBiq&-U2AAZtoiwB&9{VK|+x3?h+|MKpF|@ z?%ITOw{%HKNlTY>cb9Z`*SD|R+xtA{oM*n7_nmoX)IrC&_FmUsd#(Ta)!)hLHdGf= z!Tcyl5cBcy@xHmiP;UFCc))3Vv##p?-R~}Z8K(%!TM1$QgS+AUAnxkU%%#zc9xvKv zi|#&R!C+oJt%>ffSjtFvuClY8jiX6Q!nc|7j)bZUBol`bVUFY(vyj~%pQfxqt(Fu3 zFq_cf<)34o0#?;8GtnxO7wVrlV0c?!E;uE}KzA1L#x+8m6P<*3I=8b^dkHR#Ry)DX zAq&QSr&+~74FwM@fnl3BRM%TGC9@BDrRboogrhH0VaeGO#8PW(PxB(RKgCyl<|o7p zJr1D>TI&3pz_TbDRvJM3Ps2?0J8PtqB?(G`_xG8wr%zc<6DSkA=Qp}&WLhfC42 zK5-D6B}(57$Hkc=^-g=c%*VfwuW(ZnLXptxYrqlS}|`+xj=faQ7xJ%SV{MH8#*Opc$;o(EXA==tP_ zUQmgJFHcO4tE)8q%*?r8xz3?5QdhTf+5vApi?%%Zi%}O0JRW(#ktuDf3lz1I5@I^D z`=lKI`M3ls^7yHtsC9|G*sK=hP6_6IV@q3H(8WuE8LKx&GW9`Eni^0D*^D`>7F!3Z zS<&-Tpo5MIaX?ra03}ny{Mfl$T)kffksd)(tkEvT#A-SpNz4 zb^7foX8M&_&+CL`B|1UqX#}jiTHRGu^Ow&8aN}cjYoEzwwWiSp&U05t<-3@D>K}42 z3sU@Ra`whNx%^2pv^lw#|F~PXyLJJd?LRcWQxIB{@&k+EDt5#{BrZY69sIp_5#2&p z2f#qh0#&0rch}@m1_Pw*sq}yHu-E{`nV9Q~iy17xzskL$UYSpl_KXKpeE2deywD&#zyfomQ zkIcn(BqE@N8X(F2k}F1_gkY8VuSxP(5&F9$BKTO+!E@dIC$(~V-O?aNEgL^%VwSH4 zU0;a4Fw)PIdDM#=wS4f-q1xzIfQL^ZoQBWV9HkbxmQLh0Q>jHxSpBDC>EF1kcQj;p z(t>Hg1)AmOgNOS#Zo9AP#3m}1h*5aXGo#NNa}yF`+cg(~n{C@2lf1Zg1#XGI(WXDp z?QzDZBXG&U>McIW^WITZ-aPtm!s|DX-kaRwa`V(Q^UUsE5iI{^g>+FVm}iBG zdEd95z&CvP2cgIM=O?L*aYT>?cn63Ok|aRcK)nFGz{%}P0`s3EhkXCu(YZyyUD6R+_8JYV47{>Pt({fqQpyvJV(qu-a= z`nmk+fBf}d*UoqiAsDbDf_(pT4*tbnfFn%*>xVyA{c}<8a^U~{5dU24uRHk95d!}j z#9t%(e=x-V-w^^{|CdkETU!j|0bYM-P{U?ae`z*Z6oo>-A?4xWF$6d2GozX>C)@1F zVm{4;C*c00{|mR0>w8$~0-Zl00;)9`RPP}}2mbwe&O%fY7sGU8b!IB1@k@^vH78pX z5eO-`Z}%w_l$0nAxz^CRkH5z3%{EP{CI8!`gM3;BE;zY@qqhCmLDnHI*$P}qad{p0 zw)|Q5l3sc5`hp$lN62iZx%`Ll6QmCKNz zZ5uRy)BH$hulu#f-u&VEQ+gb5f0nm?Ab4M(Phe#BuXPymvO|7}P)nd)p*I}g?4Hbo zFvizlGweZC?BBdPn5~j2Y23iS?m*$Rzt`o0eh&P{l-!blQ1cRK6~oGt#TwMA+BSaX z^FPWWzZlj>wG1>rRL$E>Y1Nm(bIAT#Q~q3&KLmW~7VcagyHuNL3ssAEHY#2(Y-@pW zoIN1EPO|`IYw({psvrRafcr*vz{G5(Kt{4`(^VT%ak0cb>dWtTn{wBOyQPOM*fan1 zo&U2bCcK&D8DET_n<6b_!1L*(CpIW&G#nD5bn4i{h6- zJeG_MT7PCVM?CpkNl83^E+9)so0s7Lvt!RX#JMp*r@lROIZpvkXs@8i4f~(>D+E0N z5qr5v7#19Z(}IorfUMoW2c+kc#xuV=z|at*^5_`qdsH3|Rg`;LVWyuItvHYxux7RXUeNn{H5Q)?Ew1(ie=lx9&1Ti{4Kfn0)?OSwk@G}!*<49N}?Cy3n!Po1K zH=SRY_1C%qiilW{2n>`9odjO0{g#XTj}?I@6`a$l;SCMEpDTXFscJLB!x0jIv{ek) z{znb$=mRNkX$pJx=WEA0cc;qn`QZO+=J7{@wd$5PS|denC<5|pYDj<5_3O>_gpq8? zz6?Ovx5z}ynDkw?!ndNL{uo1tGIQ8IJ_T(W7Z?PC;ez7gI51&;qd)}y{)Nn z{_Oj=aqIv6ASlJaI-T;2sn>yKS_v9aE)=Ard!gV7Ng!kNbNh94Gq0l3$@t|V&x_>DsMk54GP?v+oiMwfh2W+6xjMW z=zCrVB<>1Ah%3o)cMuYQX-FZeG9|2^1}hDjA&r$lAzFLyLShsR^It&pzul-pG^9-I z>3XN_i_c}9fr5()gjRnQ@VMzV$xEeTY`!apL=8^<1U=WUAjkFfbmw0|4MvLLG?5@L z*_A>i>W>@+W?rP8fMJ$8mQB}2W}D!IsoIJJ+ZAt4qzZV{SxD45( z$e=1+EV@~F$55nxcV9cGKa7Xu8_roZ(}!Twvjo6pv4D@0BvBA(0;Bh}&>f=Wz;-t1 z<{Q^wAE*yyyo`5AlZL-72LEGLNoAaYnx5>lG-+ud0wD@HP`70fE3id~xU1-4oe?mZ z`hmlsIi3H|;BvaBHnq|o&qlknBMLOSso0=9woPRGE#{MnO zQ2gsXyt{|Ap96{Y>INFADqf{{)cW;9+^JI^V^(J0aodme$S(|DtnzF>j9$n0YLyPC zrhnmB)_+?Q#~`z*MXj~rq8Zb$( zBsd|Qc=-1#Fx&z2BjsxdiICGCak2&Z3eAMQ&ncj{CUqaLOe&k0wUopHo}|U3bxT9+ z+lcX+%zyTQQRMW2!%~N--eJNkKZNF-8$n9l(Y|o170b

GyeqO+G_=e<>g#*!`Ck zdAg_C8Z*Dv93gJLI@BsIo|_Bh%<&%SbaezvBoh zgh~pjF_CJ`xcyyj8Vny;tEBfUQwdLK4>eWV+D6N z;_6Q{7M<{6GKeC@FHz3z(5+u^(oGbQv1|^*al5}Y*lu5r`@2+p;{|Rglt<`wbLiit zH$5(a1!_q`o6m%H{mdNvDO4w*q5vUWxFf1)#vWu(k^~H<*q2HOB1f=HRk9!gyIe+8oJKro8 zHmk)f((-yKoW*t`SdL%c#oZUQtcmBvia5A=lco8{s~sSsTr}`y>KVhOqo~1~ zocZP-?=11iS#ql1Nu0N5B>r7;WY|NFM?6DWUnQaQTEV=|80-iPH~D410r0@O-Xjkq z{B+wG(F$EIMDT6}%`po>PUx8O6@$EvO#>Y{^^wSD*eu?1H>)24y~pAV1b$H5on_9) zAMLDv2$cSQxxx_n>WYL9H0DX?oHht?TNV7p4b!tvc1k;<{oa%(BXi68-43Z-h-{etSVRQ*n>}5Y7PWkXJzdym z9@}s!XmK2ycXf4yFB9F3m)5uFDogbp1k~fZnPG_l+lXfv8Rua(9oK$kTg425Gffr3 z57j^3gyT(-=E?UB^n5!F`+EY^eE}x`DEX^%y9{hGmIZvqGGD<HUG zA}tocd2RQ}PZlkE++lY?+v40pM$VtzH4?g@OCps>xQRrU%VUyzg#qnInd=B<0e!MMHlOE8hy5-;7+JYKiagFnO=ZT7~O38U+NemOxtd+9h&~+qT zO^W)=^~rF+hZSd;J_kHM_OPJ&zVtU zZ|4_mKr^YL;3QhzZ_*7Jc3yK<`NvVhu7 z;>w_w9(Ad(sawa|2=-XXfMC>4LOR!lTt!ajgFkh=f+?hcsiJN>u1szLHGi)`#nVMw zRN?fK*xy3Z3?dj^gLbdZM`>lRY8+sDs!i9vy+JP2EY6G#2HCO@0c9&M^j25lmhql8 zpsCjv5J>V7F1ajwBt@h5U(wavQrc~0Ue@d)JaL5 zNXafCQ%gMt;qWrjnbZNruB;Jc6_W55va@d*0^#kS1bf#76ZH?z3I_bcaN z%o~xm6Eq$F=in3x`GlQ<6oYWH_nsl?rx@8^aB8?0eq}4EzYR)&@DDV9 z_E7!lra(zKN1r5}wlfdT(CW26?S8GT;vV>=`h$#dc{ZB}~D)6se%l&;01IuK& z(C4nW{5CWoW`F@Ss3$G|G-en`7i{Ln>iv!SsEa;;4Rr5_KSfSrOk z`1@yHcJo{tZEkyC1<3wP^=nY6D{2~ zYT(&%ixFQhiBukaTU``)*@LSn&nx$>%We0~scsUn>N`e$?2W$>u?#cFd9UhjhWBsS zB31wjw?b_aDw&hWAquw^-Qc+aQy@Jh9^-J~luhDNAwqbdxld9;vgx>F?b2$}R;^|! zbFu}?{3pMe+qXcm!C=|^jU>^)%lGX1F7#$^4rDYMvL;#yXsg&iP|OP6Ou9EzO%50F zeu&-}dxm%4&?^mV^k-XY)eQHaTX_n_Zi%@%#gABEQ%{sq)z~oPD`=dW; z?Ab80WDsI8n~SKM33sSHiQK4aRxutxFUGCi)K5WQ?LN+2`^wcXKZr$k#0B#PO+1rt zV?j@M)y~D7pvG^lQ`sT9N$EWDe8t)320tKf^YDlzz2>;OMu9cTO>_n|3wmScwz!V= z?+xjt0y$)*h=Om`gA~b-I=Sb$m&KgdDMz;7L3Qa&!-y0IMWY{J`<89CuX}@%E~0HZ zrDvr`>Od(@Y3ApSJg-E#gXU7-{mxSnEjqgnXZja2%Z9kRjViX1ekizBWj1EylwBS# z62Dyr5gbmgd!i*K7@i6&+1CeI)5{VgO`CNu#^<@@3+G%QYWkx%T z%E1d}E_M7{N#AM+l4W|&7tb<3yZ`uXrfjN=eO?s&Ow028oazJWM_4l2mmDO7um#UL z8Fywn;6gN|UcIL~>PAagO`1G*Z}6Wy>)a`@1b&^3un>L9tsy^|R%=*u`a+Cw`lnuY zfFMyk7h1D+9$KjoqEw5=|6u&u|9p47$?afUPU)8>WFnA?3l*#L3b0!|a}&@WI67xh z4s&5WdylY+e``8Diip*oU(@iuf2L2GO;iFEX_11Y=-J}YoAZJiEUdU$pt6)%kvV!h z;I$l^$xF`E3>gLNoR>+}8q@u^=lI**SBAl)@%eZ|WzUo~2H$+!?6I4$z8-Lm5${I!+HiA%H{M1@yu?w4;L=NkhXr`AZ6_ zBScq9E zjnffg@{lBFe|xzv$^AW}KLvg=pB)#!hROkW8&~(UgIqx*K+ilWK$G(=d!8@_H(b6g z7^@W;ocoGZ2-7-r8ljk>bJI@Rq2=}8i{F3GE)VF| ztpH|oINngr5STy-OU>S8TRXUxBgxvGR$Pe|k!S@2ptA;lAYPKUgrE|CNAGi?9!k(; z0KbJtHZeIj?FkX~WZKS`A*d)A6`gbU{vSI)t8g@(q}8x63%u91$p?F4V+Q6M*@6td z@QxREC{IycNRVdB9|xo{KXWv5sU&|r2VIWcc9+7`6OyibG?Q-W6{viur2Pv#Q_tP7 zdvJeM08l>pBwQJm%g^yw{@G9<9?& zsB6LQAbUj>)#5UvpK!Nx7X-}Ay$he3)p z{v$F7u>XcLXe^+=PpuRMZZs`YuClvnS?O`P{q!bS05;ISONG+Z=-lYj8DkE@a&9$B zhb=RqIJ{YI7DJ^VG2?p&hCxNS%~d}Wm-KSOy$BL*<(2X;`K7iL>@(k$HYS3~lB_om zw9Spu5k8635GT+cpF-*l=_y8Z^ZoetM+6F`hsfIchxfr$kmGQMJ&5q4-6ndIZTQw6uyy&RQ08xkuX1pwFrUJwI$@ug zRuFyY<;4^eU6!G_zI~G$&e>-`dlLWW00(i0YW1Zz{#Knv3gMwE=ugI*83ZJ8*p9hO z$t1W4XxsG6?yF=#t2)#!)$`4{lRF8!l_YlFaSUzAS1qLwe#_0aaN)N9t$7o7 zlS%F7nCN#yHelAc?)5@|xUaFWtGP5Wp7NQ`$FQ#i27fTiI)BJ$+fy5V2P=T1#ZXw~ zAPQP>6TU+3Kbj)oEGg!*K(CJ?bin6+HflRzVj!9gm{kVVREqFK(8?|pB7Zy_3-x&M zb?2q+z?C$y`1)cx=T_X9>J}TNe2)T9To45nf} zOA;*DOZ11*{w&^n2rXY^2`abwkT)B`Xq7s@8=en@?kd;vK50m;oJX;V6pj<~e@i=~ zjb&n(Kpm&dO&6hml=-#8c((VvIFj$x*jt{R);grVRdaArQkg>i?A+H9t|6M)vvX)1EnL zEiz6FeCfD=cP}PfR4~M-{dVfw+ioQI9iZ1wwp1M^@YZGhQDkH4zsmkoDgSH7gOs9B z(8(MY(GdF^kgu5i)#-2%mQ76zI#udPbrD|MkFO{i?9~=7uxq9WyBd-0qt(z3y2guE z=ccw5^xj2YN-d#`_5bJF!rlDlG=F`_a}Xjhgtz2V4z& z%6XxRN>q^ai{(2Bb5jWH(=@x5FF{9eHlLWvRbyWjfOM91!bF{*VN$eOhnp!!Xm!&( zC9EffV9H#(lOed}vXI|~^ryNj|)v&(!QbFoW zWL_Ism6=JRj)}F0H9KL>Pfj}wh-m4#goX;UTT$aBOo%^n_%OwDEzW-dt1&_hT-^E# z{M#_CTZ6OsKR(qre&7q4bMlf471T!%i|S5%d%uy73$`0|2YcSgZD{>YIISwutbKPIK z<{Or5)_Ow8t>HS46V7s>N1;&WgFd12yC1QQ=5|?vbtBs|0ua%%)mbgW&5~OYN zbBRyj)fFkVNi)V6__)YC+Qu`Y_;LuDT&XE*QQ@cRE+Ml3|OfDsXNpqTaxq3c$r zO9cUoLEv8PCXmJg9)lWAYV9_AgR$t=)?(!2L1&_%Jlq19jnE6K$xnNoHf7Dant8k0 zs_VZz3H^Y3YBUeex|D*dz6a+hde1;$@H9Tb*tQn$z!j~QmqnKj9$v&={flNQ+&A+< z7%_IWxy=3>_D}xU-wML=y^AzqIj}WH!V`b-9Hc~{0bOF#jBPiHc)4+mHIwXDnZmT} z&;}_y^xu8`n@2%gVNBm@EXkfqbVRQqMg)JJ} zm;F{!>|SJWeL51c3|29c!OB2_6%z%vC~@b>XhrDVl&Wt=oE_U6%0`N_y#y|1hF|Rb z9Ng2^kg%Jc6plHM!_mw1m|Gqf3aIFK0lt4rC2$2L&u6UO336Yy2-}WU;wLI-6bwv& z&RU0^x%?O+Ua@hVsD$CS#h%$b&h~zU0+wFxJ4eDNKck6kcPo!*M(L6SKiuE;1!7P{pL~4kBM|R= zwmT&c1{xJeNDi_AQd2HlnF0N3vsGpZ^ibZ&bxqRLor(p5=PIgZp{{R1qP2?9o>bC@ z&{fUUr+QSM({DUE0!93bOj#pqwdDe>+H;>{p;D`*rUDg_YWh`q&R_Z_;g}oBr4qSz z!USq^PpO}Au+wt{*z5E=K|`@7P4ud?lb|BF?+tKgCZb~iD}7SS240$_rs%7tgHX8Z zmb|;x$9Zsy7?F|$d~$7ZJ`_LKT*k&YR@K_LhM#LEDU^uVxo>^yU8g!XVs`8oM)4RE zWe=UolEgPCW%gKaYY*r)sW3HAYlgGa1SwHEe*3d=n#^mS4y8Q1#U``7u&r*JINRwf zvXh8gv`7*_uuk~E(A6N&3@&B}(x>|fHTVP57Kgc?MM$*U8U%uh%dz4SZr>m3$y zPRj&{0=!3mHQ40rZaDP*;dZxJAX602)e#If8lHjSuv&bLqiOB!zWkIV5>t*#7<6Qk zbb}3kO(obm!GvOxhZT}F(0FE*okgT+kS08nhl=SygJT7K7G=*{? z6nah5IsI7sJ*01}8<`*|D4IiR@A9Uk4D7y|TY8{^m~~)0NIf=rm&)iC8Jey>a_{74 zuYo4iXq|_X1ltjDoF0%#PVSBpZrm+x)?Nfn4F={k0O%4T1J`3``0I z0`Q)6Q>-_f4#s#tg|9ZbTSP6PUte>utlOrl1zm~jn}UzE`?trpOOM*1(R%q~h(RkW z0l%yLyUw>b=q;a!n@8KF(ZNotF2()9*~bLy->gnv(vtFSY>5cf9}g)F3(=pg4x+_& zqVk*3&I%yAYy1K}@(bfDGYg%icasJ3IJV-B1Yqx8(b*$PTFAz^>o&KZFdh=VX7yL; zmUFF}(ah>Q(K0qDb)ftDc zvuZiEDni*@)6?O`cuA)oSXh| zGiZn(_|nyxL~`9N`TE%^Xfk}>;0gLqzf_PlM!=qxK~ZOsE`om29!SW^yC*jw;~N0+ z-`cLnsU{KfP^a2Q^MU5UlcRRDKISgMm^}|gnqN??l59WS7Eg(JJ=P!%7Vf@E#{kH^ zpbR4EvoEuz-2i*;(@nTe|9liKjZuF=a{1+!7TiJpOU;m}2*N*+=uUv=H}~Ue)2lAkOB?_mF`fqwEx2~k%Js{4 zS1$EPFHRjtILBn;67AsY)UiVdL{F=Ku}A1hbpAQzZIMIU10U@%oE<^Y%CG|r zI=wY$83mmk5zr&3Oj{7MRbQ&pVxoCx&^ju_A&obz^LR4_3s+5T-hzlnj)?vW3LZX- zd-?5jxnW3EKp2dWWOptCZe^JvFR!+wcm%5Ck-9T4&s>slVm6( zeUX%KFqrf?@Il+EkUvFxv>V&6;+}LTtt=q|aI~L*4d9tbuu( zu61rEQb}Hj-+F-g2wYQC_Cp8n+ajc3L-)6`BP=Jqy^nK2M~|e>7;HFpDABD!C3{r@ z<`wvF0;q(nA+erR469YFh+CfsWH?{rQ>03MXqb}aCFm&*?|aYbVHJg5CL5dGbh)Cs z%a{|>G_BfYQm z#=e8Y;*o+eZxEqHu1=ZUbUMt<@w&$^0TWJ2(dK`+w2v^jL4e{%w6DCVdD_jmO;z@Z zuQkixRv%8kq9$@sb4sDwRF;78MD+b0HwMaKefXT}|NF*v&ua`@6e=u}$ zJH>uFEQr;+$QoolnIojz9Z4o0pqC7l`;{2VOO`u?(n(Wj>a@e2x7@uW7;92fN&oag zcb*TpUW+-IYJPaXF_26>tyxK-v)dZcWfJ;i=J)L?Mm@ z)7pSF8o_HiPVk%2Z zsJh4HSSQo-IKObRn1*J(pVl3I=B_9w^BUmPNP;9ke3PZevib0dV161Mz$~D=zgZ-j z9(yWd0*TlRlxmeoZ@!r*T?2RRit5>$No~39Y@<0IxXHON7~THPA&p<`!#CIw zG_olut>maDMP%j<<@)q$U*6G@PUZV}PQ=+x^7?mw3MVQVL3xjFQKnRlt#Iy-9ylCD z;N)6wQ9D^cvAXq&y?hzSXf3zDNBz)b6QHbIfGPZlgbM$7T5QPd0}V{>Z>c*tvweNI z%X>r>Sv-4PM{#%WRj%nGm-bLkvGr5mDo)AQB`L{kCSJPYx0@H#4nKi-QlQXh#Pp$e zIn2%1TD&H=Fgkz%%lT(AQW?95ZxdNM;JkClJEHqW^Spr=uEtYMXb6 z93-iHF6Hj41WVs33_ydHj-3IiEljd)HD?@4-o;?pd7KwFx$aD^w#^W%`L3=a{*iHu zwTkbY=c*I;lib~c@E#@A@lzJFr~3xI&$(|#s&DfdPf~mXdJVhK5_;uUo2xSxzq?J2MNveJ{R^7Q$U`^29*W}kL)e@lgZcg$rg`V9l7jLZ6Qc#(zqr_6 zdhC6RalYNJv2cOA=oB*Wr6x299#8Y2YAF7wN{A8ixr_*uM0Sj?g>f!2%|KL^jc%8N zW9{imDU;E%#YBJxx8d!&$M$okPkyLF50(Mqp)drvz|^YtV=yYl6H^3HFBo5LBQ0zo zctVQ9=7-T~iCJf*NmfCAA&Sb*?%D_6b!e?{W=GweG}_UbM}eQhRi{1!VqGZTqGOCu zqVsUf<5gA7J8r%#4=V=1Osjxq%W&k7CIrP7(lwE{VH-poc2}{P8HGKTQ`V%EvqKzE3+0(S( zZuvpHTz4OvACJ)!lObzvq+`oMVaXKS@F>>WC_4MRF->{vkg8STU?B09iEJj(U;{v3 z+cre%Kr6PO%yzCHVDR36qPNnUQGc()uwyXEXO=m)UjG|J_cRZH#uUL)x zX{HACEhRm-q|vgFL!{{e(01=HQa!X3g#V zF08>$9dOY<2RLT1uCK~5R^ifp83fC&lL?0?s+YClxhRCVD9{`-c5TJ9UpCIMB05y! zDzZ%{w<{5bES_Ts^^h|8Q^B)8?RII7!0~ z^--)@Wy(t4&mq~Vx3G|-Pm8fM`o0qd%v9qCnEHM&Tnt_P!fB?_x$adp0GlgsbbGai zBZTIqxxQJ({Q_!QQ`}E_Tq-_`LUknwT+Z8_WRu)Wq4FIG721Ju9h=)#n{bL)pjs?V z6V%N?D&SegLQHD8N+n5cFqn;(0edx#->teO>UgKHv={8AtVMt%N14d$RMK!U3z%W+ zom{O(Y@*~;tyHE_BGspew~ueeW>8u6w)BeRyp>HL9N5GOMBSB3KFyz($-C08dfU&migt&&mCew#& zU=!;4d9a%@$Ia}lI`?WQt9f?6dF)7w_tSNy^qW{suqCW5*dk~SDcRWZE9O(*7M5s8 zYp9d4^oMbBmL0Y|Ld09cs}mf;OxGF1gc-H(-qhN0adAE#uN83eQVddYE${#ht{L5H z6>J!vg+f4d7I@szYyqs9oMF74>5>G55i;dmg*4A}<-gdOZbCKU6Ggp*S06Qqvk|6{ zn*5=KS*w2M7G4}hk$VwC#y;IWR^&d$u*unPby((MxO99!9#lqOKHApZ7Ju@^myEM- z&BZwCxYbvBRY*@P=$>Jo>?8fl(9|mJn1K(9jPbV2wKi}=)G#kIk87Oxn@epa>b?T;B_-VKE^LR83Q(D6Pc*yZ?A>z?Q z@cN+fbe&#Hzq~#iyG&jp3Gr27$(BeYEe@ip?UN_SzD*G(|jh(`mU~ zN`a_y(=o^ERV2D~Bx<=R#uO&@yx1NKwPtMr_k-HR(Yv__ZSW+2lwx;+VO{DUTTa`zJ!AgPNv8lQqNns!{{ zuasF-iuG!~T{X25w?@xiV44FN>&QUROP$h3jsBHWfkjHW)sO@F>zD z737l&9kaW!PSFgu2UfX?8_Vs+%ENiADK#us2mu{Jd6-=C^5S%{o)5`OFK7WHJVZ80 zh;1%ORLq6gJJs}M@zQr`4vR(d`ZJs*sCzSmtH{Zb#g?r0@rj80Z&Y(H}?9O_CX20wToS~MQ*%f@jSW>J#*W<$$` z7a@D7n5o$>X}>QwluX^y-UDcQDH}WFE)z#nQfi51GuZPYNq@DJr6xYCGqasi@^(EyTZm zCd3-AP=eaJ;_KRnya2DSCd;UG9=YT={<;sz=v_AIWn#9efxCs(%n@*5bl){#{0i-@ z^pZ8Z(J?X3%h=>_Z8G=-AM=lH`7z4h2|Q%_Ms2O8&;OQhlY&R9;Re{5bNw}hH(o7s z8r8jKRt&MQAqme0tL3ThzHyjdDa@UIoX^L=&TWz*dJ>XQs&H>uZn|Gr=^8D`pQ2KJ z8EP_GBmWSD81xRH@?D>vDOIPTQ7dsc_CRIqCh*7$VQE~e3Mw_vZ~yJFK}TF>96o!% zbTtFybNe#zC;4Fr@PG&-3*Bz^Z!HhO4tY|0Su-IQ><#HWJ8+lr0uxv}QbQbz=14ik z8440;MbRTwjcXk_JT+&6RS#CropFBcu*!VFe)r}S=8r zMrRmtqGfga$v{|kJI_Z^2)Z(?h1e3b0>|?3PS#v^K*)d1(DTsG6Rk9Wn?Lv-DBeTS z=;*YXZHD{Uy`1zW?EC2;eqo%MbYnRl^Y@xid`%0~EbF2lgJZeh%-yAfR@yz3SS{Y= zV=~a`vz5OC3ROqnBa@;x`_L&( z@|x5p+&>tH9KIaBhOzFy1|32t;oMy`kaWH&EvHm4`l1ESZ|LwZZt3_Z=DxsvHRwlb zE!*rOw0m0-j>;t#|M~+t*efoaXe>E8It}oD3gMz@+xsa#d44ew_Dqy0vJ&jS24&#$9>*s=-E-WYy8LvT!-v|-l~xO;5x3vy;vo=9=c5w zaF}zDv!0{lLLC)3Ephs-$jO3G9~?vkdJKK#W?e0HHG>k~E?!)su!+OQh< z<gNS~)z8oO0q9f0ieWGLFK3yR|g8UGh8?wZBEN+rt^UDh(}iXb)%mGR}U9}N1ycQAgYx9CH~i3GFLfhI5c-9NmR%9hcR z$7P%!5>79Ooe}^+7@5cIBo7LZ;7+h;WTWl^dv(AJB8s{3K}yZkL-(#MF7)jv0TX0u zUoD4;_a_i%(>QDj4QL;#h-pC|@U|f@hltfPRzWr#Ohc%DFEgF@v5$klunBWCl%I-Y zzh#)YCEe?2rPwuE3d=L`4W)ybl!JI9aT&fGfQdI}0aoj`pCI^8P0&R{Ver|SHNo>hYVah#ce1rSLnQX-r15a;k@Fzej z_c>ls6wi$=(Y7ILp5Rp^=O-!OetbcpL0+SVl)6K7yj+<#JKx2uIVrDtI4x#gHG@W% z`SW?68Fd|#sUC`(-s`UL1gLx0UEx>T%rzFI2hKtkV2fD$@Gm@4xgO^7*Y`?=>j`M| zaV|0(ep?96#C#?k(UYz;VjehIjXZ#z=2|a?2W~=;*u#Z9VbZv&uVu7)CZ@b#4NWh5 z9f955r7>sQKAi08S}{nqu_g6@EM*Zgs&D*Ph!4(3m7`dzUIh}$sPW7ew4(KaMmnS9 z@w{`DQf+!jDy6vXGQueu7zh@01wp6bJ0XWvovSvSU+IlvudM-F-9$t%Aw;MPA^}=e zb1aNsRQr*yw4pRs6VabGa))Fi;HAfJ6@dT7c@Jf1hXm# zmcn0=W-B(%@rgs@#PdRe^#MKP3%)9mVPUt-5*OM2KE*3M@nR00t3$=)k@M-`xf-h) zLEedpI$(pAii;%jdldDWROD?sGo4gpYogbXw#sI_hGp3eBufZFV@XYP8wQ|}FhD4! z^=KJ}sQQCC89AQquWMIl*QcAw;m~ddAHmP?wMT?*!QCIm~<>xStsUlU1 zX3WvWotCW}orBq!J38!#8Qcs-TpVI#(bvwfMrb8i)*j2xnFz435 z{o?A?NzmicqD$9|!+Wr=SNe!Cn<;BF<$zRq(tFUCtGQ;$)ai%}H>H3Kg((H?(n8|G z_|;vzcXOTcWdvH!sv`#Qr$$ETeqIrJSn zr57Sii{zFJ{?gr0JP}m|*cNR4k0R4rJ*acfid}O6-YCi3@SIk%z;D6Pd%S;C;cNKiWnMTk6UY<7D47bC zs{VM9J#eCvq|M%>R+7ZI_)wBkpw5Ii7=pTwDX{hF>gQ?OmJfpf)Ax+A$w}G@x@YTF zhqVgW@8f!>(q`v{k%Rvv4$#lp2N}q@E1^$_21yL*$O`ZMq>spbUiY{UgNaMVMSgRlmRh+!Xj*^Om zjZK+WtpV^7h0{t(R{`8lne&|`jaI1beFriToQLuA|G)OWGN`IPdY2CAP`X>XyQM^0 z>F(~XO{3B+ozmSYAky94-QD3m_{#gQduQ(4&(}HQ96rF_zgYFGwVq}0=@fsu)PZfu zq4y)r;BZXv^g#{TP5H6d_oHA1k80t)>}IJip)_e>Uj0bH81I3z9;d4pLtPj9usX5%pamABN$K zq1uF;TWNXj+xiD)eLe5?594`m5+V1%8tkuBZ;y{tDL9Al47vo3=a8IzY;^OiH*OcP zu6p}<<>s|9YaAj@U_0+?lQJAtVL*Cm0`liay|E`U7pAY zuJjXyv`L7v`6!zVc$&_V7hr2q|2~`1sI;zo3LAn|7-$63!0PVga>prfEZ;q2SyWLe^ylo;ng+6=sk|=Yg)?Q4tGjvW@w8<6nJ)I7YOoh&B?bJM!<;2-_nA7+?6R*vPIZtvcl z;58n__(B1a#7%IzQ}dpSGe_5;jH-akz#B+p=i66Z<=kWs0|>tcDV2eDxqQ*> zG(K-s-RepA!tCfx5{K+>&YO&TYaF^Hi)4Q**D#R85Y;w+9(G=>5WH*iIIF77O0 zD$R9!mGI+QjEl8oAi^D-rvFoE3n*{?w3Q57lc4vev)vzd@QZI4TLPV$y{uD^7yDaU zS`Q$O2>I0mz`h}x+Zlq@51LQ5391u{Vf0)@u%EZ8>wTu$%*(ha9Pxfz@|el7@!B#0RE^=>XEBx0w zL}|>){-BN@;(IvDkxhNZo%x@@?cDU;3^%*E6}(?kTm7En*OYP-2 zX~_@B2I{{P@dYQ6ILE<#gTCpNu)bkP=2jN)(5TU5Z7L3dB-`)@2VW3V1z4ao zMe${!ehqVAKseRyJ>kifa+3>=dojuG7V~Ru=WC-{R^iMY{bne%w{i%6@Vq2RZdg|tWVV*abA>@^*-R~K$vx5P_0r~EJwWn>nR{HIRs#b{StqOf*Q|=NYy`9&w z#wU~h_073-R_G^w9*op;B@UZ*KLBm=RMflct+C4mrEV@JK2G<=cQjcR8b-!COHg^l z_GY)>Qw6c%1B$pyTbw+cN~4{VJzCx_oSaEWJT5m+!}F z{ zZwPgVYe}|sr-my*#i^AcZD?LAk2R&+N8_Q0tj2mHKZSimIQOCquRqt{;B5Aww0u}s zeT1IGkiLM5F0k(qTc5B6f*~Qk7J%hJBf4pxy1ca=v|;}16tD7yO;MsdRL<)G zu&+8qFz8$=Al;Qh+dwzOX)Db)gjkTddyxDg2>nEUq15JDb|0^t&&fEzXS>AH3(s}< zJ64Y@zv3kp4+21@gT*0Oz5(H-F-7^iR9gCk>1r^+x%YR2M^u~LDUfg+pSR3Milq`3 zmAoYzYqO__u>lW`lKK5kmvcc{ru@nC7SxnD3|x@So3d6%{3)2;Ve~!JsQr9lqy`^4 zt2?s}i*tPg-Zflt%ZmEtyKqodg=kWjJ7S@R;x}3sfUY1`gE3LJb(f2T9IE;D*8l<+ zS@{6zfGiv`!cOOUefP1eEp^+8IL?g_3XEjr>Tz#!Bink@@Nx9C^JF{v=)zp)$4hF4 zH_bxlEwxRuKdv9N6WMB2847W!{Mkd$ti(M!b`jzXq&JR=a!s2oHqH30q_bMTWR9-l zCJ`L50%eh8GJ^HG^{7l~-a8O*Py8$_4}BsK&oe)?3ApWZR9gJcG4WjE|2zjTWUE&C%`YmJ$>II`lMqL3QQhs~M4>)=-fhxv%=2)u zv6x6w2`9NFTQgs@rvr(aK+eLiQ}>(dwQME8hq0J?a&VclM@46*AUs65A<^qS8>aU5F zRb=kFHm~f`f`_r`RtDgy4xn|}8`T*%89F#C7g#tnd<5Z9WD#vCx99gurVk8ru>Ant z3Eu88J#vR&kErG)lRr65JAeq8jZ4cAD#_u1WjB z`>s8C)75rPC7a9HPocQyl!p6w;OOwTO|yu+SJ z3x*Wp<7qF}AC;bYJ9~SXJND`OJ>$VQw;^w4w*^weO)VlXH_%c9Sg<|xFB*IYKu91{ z7KqXl#@S2#z28zhF^5T@_9SrS1a3z1uIwmPeWYgj(@x;BN;(yXw1K6W??SU_mZm1Z z`r+xv#BW}{ax)t&18H#VY5lK_Rt#8KtEGY+)q0jNN}}^53c_hd)v(pQ5aMmBbB!(D zUFLsy1W`e3NM|z8v?B@($j{j2NFk@0$M@M$e5IUxqFx3QUkNZ9%{B%kcDrUc8H!_H zCr9)>eY%{Z5~Rk?^WiC>|DhG7c}y=AHy&=#*}{SC4!62@bYa8ro6rrj*%01$Z_ixg zm7kIRakn#tBP@j$b2 z+t76c2z+~7Pl#*i?+3)^QFwA!kez2dPRa+81Z3WJT@Ob2cGL2G*5+|4W`Iv5PWLj* zX4~&LmT<)Bor#9H-TJzCbr47-1*Iv+QQPODJx8X~XcD!+WYS!`6$VYkHn6K#F zQXqbXUo`Da1=x>arxv;nf`BequMlVd&|KOP@Ya~ry(m?AEr#D$z2Cy(2cja3enlxhU9{>nywCPp(DmOXN+J z&4^9{nnPpW7%@T_h!mL07!2Mx<=jA>-DUAe+QgQpH&5VRt(^!5<{AHE zf?x_T=(7F#YU~pEsu|km@h6@S8!%s@+1VNBR%v>No%pGs3foZ%3h|^K5>i?ShL+1f z=UV9PK-B1+u*2xVnSQE~9_QT62rN*h5didIYuTwO6vEr;=YJLT4-65-IN@w8sgZf* zbk#F9i($Ar!NToXtia=>WU*^&B_cgQGP?M!bDRY?bqmanU|%Wk<~m=lK0gH&!e!rn z5lhEY!5c&bJ*!v)OX!->PniNL^^XC;sQsY%Fpt;EjJDnZ<-l+6M9}1+O(e6`uK*6V z&5zsM6}V|oxqHwCc*~mPe7nGuvk>0EPf1-c5TeHnhFVqexetClc;L%uv64Z$&Sjyd z*DQsJmb%|Iy~oyA@S@sYwJM)gsOJu^g{AuOwoM|5%|TgA9tTnU8h+ipV@`zdm`M|d zSLXH1ohT26fgfK!UbdIVq=1&OJ@AebCY3a%Upi;&V+^5Mo=u_nPKLhMs*#GO9+4wB zXjUZaNqa?sOk-{{Cpbzk;&VbHQoJox=lA|+1aHd7pk;)EUR^=FyVqkG26inlc`&hl znkIT5_n5z*=f(Bbj|OtYfb%|deDR%y@!xG5c_Ris6!UR}Ol?#-wZQjC7ijqGg!uOJ z{%f;u^_d}3#k6m6&V0O*%c&+D`3a1Ck0L7U`_as%#M|NZs_5IWNfs=KvX`AS-1S?O zpq-X$`%>?LvF%SpY2B`e8 z(qx#>;hnBHH2yPXxr%xj@Z;h;W8xAhWCxW<4D#>q?;C-}hMffo0IQsb4(a!r>V!+6 z!1>~@%BpE7%KH!>Hortz`P3eDy4G)DY1SJZh~-p(HEh78?{tt4@!Myz;QDCRO}W#w zLDNKOfvZSF;K{${PMltF4gr#}ukV5o#r!F1h%i=1zPl5EjhBsC>`pQ~`=;+9P7g{n zHORgm8r>ZVyu%%8N!TBYMT?U!uwY(xo42|$o90ZK2k{yrH6CHehVeH(kRO&LAJ1lW zh8P_X%edhyoXn_#&?iiA><*^6!5JhN7H|IwMyR7p3~$41F2wD6(5!H6l?1S%LVWrv zs)$M%W?tZ;4h!X8bq_69Cl8k?fcc?aSm&nz#uQOHj18h;2R>*NfMqCi_E*CzOecul zAEdAmob`fV?}CRVJM4TF&L5dzgIR*cAyUgdevRlL4Y~Px-y!R3iY~C-U3a!hJg#>y z_)F`820xue{Jx2Jt}~r^dd;O~xY-w{Omo%yEf46o1Qil$HyPJ%fT|;E6Y&{aE)Y1s>z=m`-G=O-aVxZ;#x&(_UE9+G-V`wV+E zZn6Fl-cjbau8_);Wccx5?{lRicM>78Kc!*_t5&1l17n{V z33eG6!#{SyR&kuPOTF*$k8nVCP6#mr3Hu`nsPY5YF>+htW-Sa__`+P(Xd=g+MpNP7 z6)d2#8da>-+FGlhV9Bq@m_1>4Dy>DSkJ47Lc(~fvX6IFMC+rQSi9E^CucAFeVR1dt zmxh6KHdm??zm)4%Vp(Q^QwdzqI*8WN9a1)lf&3#Os1&q_x_gFt&Ii}3bbHHpChd1dm=y?^jTu#YVdez{-NvS{LvFEfo`eX9BR zOZ5I;OX@d*(0qBdk*8WF;pem-IOCbma*a zs(pXqHA6%n4EM?LC^4k*sTZZsdTO3b@>HIut?Nq1v;TGjVno39>>{fTGQ;{1Jyv2P zcyPPI z`x3s|bvkd<^JYzPhaN=acs64WL_FU=6j zh5`+ZjBN2{^b%UsAzfZu2>MCc<>-u$zga0zHx|MuTTr- znV;B(4mSimZSW`DeG7grSQLK?Zc-2Miq3dD46d#q8F<7Uhi>nyUCQHs@eyl&oMy{&CkWWcV1f;rp6pEA>pcmNn3=p{8m)NlTKz-+>KlNz zVjmrVB#E9}b+HD0Ht==Qy%3hr5k>%WU;KT@_As|ayQ`{22V}BRAbjBFPvt;nYz0O33KcsvK!%A;1OSq?v*AKt*J5LvuxB zk(|c2Ck^F=OF@(3wyBmi!w+`TXP^-vZ$1eW?#HN`Df|c>m)YKPYDN6x3vwO9uLN^h z*XQ9hoG!~Vwuy_rS*yIr8JD3~oX%h+5IJMwWfI|CxkwYplsA?sl)o3a5N#?uw6NMA zLCUQFH&*lm(x$#2nolPnZmG5-BHZKQSm>?bb`6x?1v>s(?Gb{r|0Q}AiDmZ3?|F88 zP$9HRegv?E4obf9-BqHJ*79nxbhFs@;Xq_%qLjg3c1U!)y|bMnm9s34il8s54X!zg zJyb(P(OnEkGjtUn-yA$@rzayyA>s|61f^)ZfEq}Y3h(SjME0fU4(~QM5g~wXFrzaf z7pCc^Uix%-H5j{+wWp?7oS)_1(5s3Y=ECt)Dsw{YERw2J7IKJlYGBj}*xWaY*&J!@ z1&h?3iJBR{2(cTtSUrtZy9gZ$P|%97X{IaOsX%A)I(c%rgJ zMnSJfA@eBuAl zEkl3EQdke$;Q_UZ6P~+v5xWHhIdeNTN~xq|tjGlZ9+%FY7QCIqShb03@EYLEC1jUJC5Bs!tcW z<_#XF8&&La_Rpb4k2b{CtPD5t-M9i*g&n4agF!GpzXIcB7`=P5^K>iGW5K#-Z^&j` z4bq_fg{yycA!`rx19<<1!951$9y14IMNO z`)(4M0Gbfd!ls_L*j_@DsY}Boq4YG7I^Jhz4n4he&%U-01f)0^ObPup9E|OPB=V`P zSP4lutsiUXVB{1(g>6U+#T7wujDI(7j=8^9uX(Xh?UJiz42XhfI zAve7yO=_(id{=fd^XRG5UA?=P%PQyd89nn)kcWdssLCuvmJ9#$MDj=`2wVLbi3kaH z0P1Mcv{vqOlSL!n#<&`UHfK+T!j|`+-HcszL=V5aZq##>3I~TvxMrAyUf`wNS@0g*WeEFRN~ARX+mj7 zvyO#7q&SYbC_#`&_+j8`caJ1YUeuc}9tm$!-t!>y$a347o1$}!`{1t|82H;MHY|!h z<1wHQAOrzV3c6Q*F#a-s8Bl!<(c!wvcxamKLW^*^K}LBa3avQEmMNuU(y)DGiYgL@ z|C7P_yoBL!rh4z>BLNp)_H}l8LW0FYTUo`A!7k`@HufoZwTv*w%m``OX zE!W_KVa__zp|~I4w-BM2|HJ2i2oQj7Lr^%o#S7IK8fb#iEBlF`omALOTaj(a9$q0f zHkXswK~a`njPARsuR(C5yX$^g?@f*&cct65otu|N*h+P@W~x@3tuut}l@C_E)vVJ` zS#T814n*v3u1uelW}opZg9~KaMbi~UrZd&lzxwExOoQx#8;$xJGx>K zO(-JMBh;|-3@01C8e?MKBgUZmmgR zCRLHl8W>k`ry$!YpOBgMgxLq#R_W5?g5 z2HHs)^|5k=lgbDZj_MjNNqiMR2k|assNkL39xL9yu*FL~4Zb&~F!s*nLx7a0~qVJ6}CX=wmb8xga=0jW*y`i9rYc z{1LK;v!xWb@A9K30ZnFp_7*@Q_c>H+x%npGRY(V#uNwGb4?TRB{f9S;H}5nZm4+d^ z@isve&$92oo^Aecp^whWf-tjDfxPEK;qtC6Xb|(h8W6u7Vw~<>jR_;Yy@P|@hKA_s zhJb+tzpfBwaf?j!`|Wp5x)97)Q5;409~PxU&IgbUT_u97{pVdL{k5KlicIZsaXt32(0GPBu_ytme(&K7^2J{=zF zX{5M3Ll?nUBm3htrlzt0wlOk*6od_l414%b zRa0psg1+{05#!R++F|ls)_;0n?CGeCNlDRkkar!+#W%r;;LW6sSbk9)CAJ z&0k@bBn9U}YRevjaMnzezm4e zuw}27xYljE>kxJ`uXUDKj$xUSoyze_%-h$ULr4+w4kzV}^YOUMPB2Y(Zmp}9N>f;} z^&AfVhpmy3$_4(?Tp*2d8Z#mB-$f8VFT#{*2J>YRZ^3QIlD~(zQpr}xS2Ze`$hLuX zofd3~Graw}+ZZ=&9Z%pu^aP_<&*++prf6uAO6;p|cFS2s zqRCzpPsQPI|<_@va;i|u3zfFg{HTOR55IbVGVA+Vy_TG_?&DmB?@&VJwQ zyp2m4*o{DyrTA%%qlEQ5^_26h3?Ty1aBo{=--t|6!PSY8-`ri{O-RAq)cA0ms-MVIQJz<=lAufvSLuJ0ru?Fogc)Dr)4w%uWYXRfvkB zf|>l)LQSk}oOPNj*_BbCa!C zN_fuTx>ZW}x(y!uwV_?1vl#dfObewv_b(&L(jk35qL2q#e&Z4gv>B*>f)kKplY|3_ z4LS>|YiH-xCy7}&Z23E$b1-4 z!ORJV*@l*Hh)X7k2++1Z5#fu6Wu+_krj)yG9FddFsFEac7gRKe=BaaA50f%~lCjc{S-fQGv_Q7c3=Y&8gq{g4gWFWzV zr(6k}|8{6$Y;7y_ttHu-&!lgZn~PpCsDhS`B}1kZq!kuo7WQ}2aF}i!Y}JFIC+mJ5 zAiUor9wlepY3lnh3w+XRWGD+!w}X5P^bXAJ><^#I_!61y4~rdZA|6D|+xK-lByJnK z8=daeCeuAc|NE@y<}BI)MfyUWdU1o*N!J&r4GI+wxWyR3{1?fPBu)g~E&T=&CU3n} zb9`3l$cy5^BZ2xEMOKle#)bv=I7k{K8g{{{Q^FWb#5@uT940~ zSEJH&fNqXxcr$-csg<xCksp_Nx?EkjX)|8Kmo-){{mzC35|S!ZNfLxW9;@m0 z3_P9?kFf4;_M}dGbN?nS|5*-8yMVwiTQ(AuR@Sit6|w zC6|+k#>ykS-F~tYW!%;)!G4$gCaM~sp6}OXp~Ot18k?!NB#P0FS3))M`U{O;&@=4b z(VfQrm+P&qheWrZQ}-gPm&w+P54+JA(ggSC;{jnG2iY<&q@P6Fm={C6>@ZyCo# z5(U0yiNxm%?3jHXV<%*0gKvG&RLmggPjW!MoaDva$V1rb&OE)D6R7$!`I9|Qyt$$&#qM#))I6BQ1tcGB`~Y`WXt4Gx)JSc- zYw5A~C|&GZch7wL(tWM_?YV+*0J3fGFHM{7FH|_2qmJm$3`i)-jHT__s49E1gku?4 z5iTt?(Q9u{UHO{6@2dd0eDov?h^MwSNe?P~^n?-nrVogurq24qA*ghPIu$v@KWijR z#8!w@!n?;eGHs7DnDdk*MJY%OuI&$0*RHtX-J4&i=~$k%d#If*?aQ7uK4j=%rhYcQIkDQM7MY^eiSmu)bAuXc9_Vv@jD&)!|{w5ng!R#I$H z`(z$ldr)x>3l}FU+^TEw5vngx&?|E~j%}*ja-LBS8W!|LO>?t|s82sAER7JqYy>g* z^Fg%{m&3mtlqJL>cD)%Aa*(aM{sE;DVN-Jsa%z@?cM8dq+7D(1X!W2SBYcpttVB0pNP zoow*@O5d$1^*KAm2$0-tr1xPXmBCRUk&jB)l@mZcmjOj>@F=)c!=iHhOAdD zt4L%#*1Do(TGsJihFp1}4m-E@tF}I5?Ps}rd$QK=m%d8y!wp4t*J$+*#GEmIS5#gg z<+gGfn~0@#k_j9O;F<7^)QM#T3?!T+rL1GDuYG0foi{c&3yw+T!c+HR=e9Iy2;-;> zzVd$Os#8ePIM1nN*1^@_`JRz4)YpHO!`3R5gojsi0AXg@8{@Yo(x9vOMUy34)mZjz zT>Kr(Y{hks<=i4UdktyH)<}<-(~z33)#Q()b10QggLi!+GO?rMRd6)>Kv%D!q{)kNf&vxElL`B`=f0>>7Wn+kVk8G~ zW_<>zZm~YF;L(LorBjW@&O=|yIp5iGagp&*1iK-tX{K?IwS{`6wxF_(Sbc>|%DEMB zgARnYp9G={&bqI4-kzH%_f@sJiT!x$P%&D6;)rU7pn1y>zuan($>%st!IJBlvhkBS zL&nC;EKZBpxo;g*%-*dsA?aY2=y}&6y^-cZ7x}4GgX;ION0HHBDP`|4eXK>iaxc}f z8fi^;cz^3txBYB=nNq2$It@{Sf$xItCWWH5wl%OQ;CWNdcYP6Z<}bn7<34Ft!!M?v z(*{FSvb+P$ZS6DIzX*jP^NT+P>&~iuxdTV<2r!r|b`Sfrf zZY3s-fd7K6{1<42Ojo=b#1XGLbro25K?5t=S1*3PZqEu7>p2!Bv~de~Dim%XrNW#w zB*JNJMw%7w&f}t4A;gQSCgH4=%J!F4jxh(?kETdf>Vk^PN(6A{tw1%vt+ALQ=8nec$ zkbcAY((Fp0%(x}R(nh5_c<2h7Q$Zzq2Ql;~dO_L(Nh>g~@3vi&(3@0~ywSPb!eG#y z(3@JfNPOIS%s)1hMAq$HE$&P>{SAwpFD1Hcz7h zTx`0VceG1$+dGtq&Vf~=bQVn9SL#0CB{;UnW$gu-OK>vNhE*#~Q5xuH=CV~=?0(hx zbR~EapVd=stuZApebFS`=hJENsqCqWpV-v}&S5$GVUHVSOI2CqI1b#z<|g$&k7Z z)OSd|d@aKyaGT1q{_~X@lTB`OgI$s5V^Kuk8Kq-5hR;!LV!EnyE+AO%20{*GmvE>!mFNP&w+-Ounb)jV|igag?~;0 zioo~{zQ|z?x~(`nB4AQ3QAIa_>SA*&sUAkzLzVTXx%->Z zfjqPZV=&xj&e@DTufHW1MTj0kj}_3$Bqd4o_BJA$Sy;q0XNjDbZES7!`TE0d^h6o3 z?E1Y*RjYVMK-kKf2cM)ToQj{fkDHU3sb)NsM&i<9@+CHGp1cXUu4k^s!*H|k_rxQU zqa1*=n4GOez+fFDwi6lelYjq}LAms}tTUT2{TroplU))?FFqv+D>~ZGn!NhH@iR3_ z@4rm$ZRH>)cY~Q=AEcLE3Bd4SMt}{}PU!$Uyd3gJG~nXGROJ7P*H0pdPXK3^7$FhF z`u=M#{oeSR9W7OEp_ocI5kMjR=40>8Xkex1Ex6lJoWCM}o$}UjS{5tCTch(M0)^2T zuxi7Pz8}io#@fZ*vi#0EwI4K68W^-c$Y9_%v#fe#QBO(+aSkj+;;@?ZAgSn(&est| zX20G4h=P*Bms(O%Y1P5twpv%#lLC7j8S%I(v3Yba*Asp?Z!{i%cm{OM)fwF;iP~2R zUnBXlQf;Q5hDBUs*%6Tvl7LTV6m4RM)FYm%l4dE37Y|7C?>JHQQ&aVI!2N{*5E-9w zfdoN|7Z?LgNGNQP&435H)s)B39p1S{X8yAi{H=Sm+LfzXg{Pe;-}~_Wu61qU{XSZ{ z=w2)!bn20bQhKp~$L+92rqZtH$gRRELX*R#fKH1|RJnM8hP`nBs$b{~;nn64uT7lB zl3OYd8Bb1r{;#og&%3&_nX1O?&Rss4;V3?<;daQ&O0VCPi5vz=3r|P18rF+5i@93%^D+pI2BU#2E>9wWntkV_eLua2(UF`t#qwh>?yPNw(n14C z=3>1$K&s<+jCa-HQw1rIF1h7&xV9-D%%^{NE=u)k@jJ9$&_FXwQqb8m>)`W;Snt{O znDHs+esMjxAj*x%{A*!5ILIa3E3_S{5X_j_v5+9D`q*g(-G@hltbq@u;a|q0NgE8W zpjqxAQn*OZ(s<*0YWmHM+%H{m*b6^w4VA?2j`wZOXs3#0%0l3GH?AKNR9bhuF`J5! z!o^EA>`(UCY?y2^y4H)58mCl8QUzDkn5Jg5=Ay$Iny0MOX%Y%298bi(q$){y7(-9w zZ&joWe>2;9p8rs$k`6>ateF@s1sZ?|`Ly321IJApjmh!7(s;;yxuQ)@>0!;)xf5~=YB^QKW!AYFP^4s(zOwXXV%9v_Xq@q)!O_vFg?!|Y?6EW@QchseJ|?BmCOSc9k#f+D!hUj$ zo5kkn19!7YI=-OoJNuP3CKJd;!hPy2=LicpJMOhR<`&{(cc&uZ=F%_YtZlQP*`bY< zV;f1iV01uIvjxG2mpiZuN~?6)Mwzs{+yQ;Kw)#mFOB-H2ayI;+a+u^)-y(0IF(z5K zSR`MR3aURX5iV0Mq@TVttDJ=LNEDY;{Wt)=lLNuvtMx&HvWaN(k1Zcd4-FIkjXiCw z?`~&Z$-$di65;(R2vq$K2;I_l+D+DGqjUs~Wn$rnQJIbHA>e|cf_JZZRjcc23XjD% z)q%rP_uIq1l1kSn%z|(7rCN%><`f5L$WAgJ-!0BmHW99^PO z+k5SOhNsrDTVCy=n=3Ie>MsyD|1qx`+!WHM;i;1c5j+QX0iJn?X4NrOhpHzvyx<-O z7de@6y6?me!&FLEI0P9@X$|WIHhmt9`~@3^!|#vA@PPu*KL~}*o;WWrtx0r&IMCRA z?2fgU_X(~NPu?_OHKlR;bMXT^RWX50_1^0E<_e3y`SlDtipqL?K^Z#F!cR>Ztjt+wH7xuN zHCH$Aw?O+fKri=DELwY979#=W2# zRgum-iHeRgJt&(hCG8P>u&6{<AwJ0+-QyQV&pzgeJVCMyk74Y%V8Sir16Q^rx zzi7RKeX@x$MI?Z#yMM7>FP4dcf$@E91Gc+`H-KvuGVZ^?%a#$V*iG;PH|lX^wP|hpCVbo$TBDx zmC#BgROd%;O<%djzOD8dmy6`SK)C*#r`3|(PQU4^8FKEPi9hX4`!4f&()xfJ_PY5t{CE#s2dr(iJoj;OELD7!`D=KC6ot z?pUgD7!EemSAS+icte3Q?E&4|A_voNg*c!JKSo?0hH_3`EtXXdyMxatMm0OCOJ>UnUO^kgq;ZwX^kds@7F-JbdUK_UBILlLfh zR3W(2ss<#fn>$;Px8}%43?71XQ>*ePJ(>_o_d@m0OE?-irs57lrpZp+A-hGj4z8}; zM_%_N*PqP3OyM>;&kdlIEQ3dw`yvBz_S({tXk3JEIH?S5jzOJo{-!nAcxNmGpo83wZ=P9<8Jvt_xlurw z`}|Xj-_)!J5-@ocuIJ=+apG~RTs>Ta85R)VHwm7Z{5hzS1Z9X| zC-^G!FdUWzbdJV!U+f-~4nOyoXiwU1YU~QMPFlO6Rheeg|l^>3M| zz3hHI?sli)$kOACjDwM)Xi}vm1$=Xi{U~mx$>OUI<(u>ZgReU2kamPWr6MH)XR6$? zM~?Inzbo}cyw}kZ8lSk9{oabTyPF*%z-f_vBzZeROQsQPj3#qp6iCY6kT2ieESb>u ze}?qUptc6nNUL&H_Owx&oZn6=}y4XKT$8WAFH=>8&e5XX(SR1Zu@RK27RnMPv87+BTAIr&Z!yLsgPB#^AF zS$b-_pKPW5S~{ecl%ixZ-YDZLlDYcVvZ%Fdqd~xXRF?C`i5@ioJ>fcMPRX5m5Ah7y z>8;+IuCVC=tkA!2_rHC)414{Cg~zla!}0jVvw?F93PHhEJP84dth{XJr z%j{{C*VlH79~vq|^gn)%&$LVK())SA*q=^w?PgW`uCZ}3kcYJ_u@Dd@98;hhV;T47 zJ9Ovx4nkvVAVTi$<%#-g7-kdpE@YQ7S*7QkS|cpVT2+s{mYo#Um^n%U|Mm39pMh=o z>^6=UN9QNJW{qRo!({p*6-DRm*@Z({6Aq55G8(9rR2G?)VxTg}_b_bRb@_uF##+{Z zE3kl#;+Baa5b2UQu!2z0jC);2;^BBmdi^!CB=hLzHKFg1zU)^Xc*4B$W^yDwq8^#s z>zO5|#a(&VXB??|N*^_;U79@#9%i?X;%F0w!VvBKnmVb`|Hb##@skO6I9J|%1h+Yf2ki+$MNU6jqSM|GUvfE(r_UV|G z7q)m>GQ-n26r@?u25*9l5YIyUST>d8_W~^CCE#XP5I@I%xpC|fg|lBElQSmD@)Lz7 zF{lr6)EqoVg>o0e6=_zekJ$E|>GxO1;y%kShvkls(5x^F=eubKT>3n$TNU5ZazjG? z`Wr|@KabHi4DWYaF4W`?LY5dMndzty$k0oobq?ze{zrT2y25<~>0Z>@F?n(Fvbwx0QP+TJ`BjpUL;%BfwKP&DeI6NGinu>3ms*?I^S3vbIf4>Pq z_&-0lJ*U6&{vB~^h7jl1aU5)(O)fbQ;rfN4&MSPJZ(+Xj`R*kpB`I;MvnL||@tgnr ziET)5VCMdIUBcF$F5JKZ?gl34RU8%7>lVg%1HTpihn)q=WvS_E@e@F;Hz~d zh7={LvGzrmFWPZ1J@+Ycq$|(*zpMK9%k1;=4)CYZ#%VQ>vsmBW?X?NP0-|ZQUwc3A zvf=%^ga7V`tt`k0b5U6iu*pODk&$ZNt23OXS}gsT67%|t$^MP}pYtZG&mqsr8By%q zFlV-ai99v3XJ!M>`oD;rq|emB4J;TK?6%Z9;g2tiSpgP6k%HaP0jTn`x_ZLOGjZk( zvSo+u#hxVGCa8@kz_>E(-v#{r5~=!}BX%~un=S{j99@?Akn}CC5};>WEW>PIZ2jfl4>iG50F6)ef|-&a`(H;n}L4)}_>y?qtPTFno_6*38nYqjkTOSHi z*v#^ajJ*EGdw+UCBI$#1hn;9~m; zJB09yY|&vx!hj2V!C~2pC7vn<5!QW5>c3w4NTcUJR|y{Gl2=)&DDX5QdYbdAd$r!w z%o^0*$IZ4faT1QGx!U7XMP|8|c!4~a#wu~-wc?w@8FTnY4F0Kq`9~mp(Vo+*Xv`nB zmwK9xerQ;?9M(E8>VC7=Pe3eKk+;?=G z|18n}$ONbdxHS_ayA@7C^@)s~{p|7BQz8vGYCyBA?3Vng!SB`R`GAogNeh(ya3^O^ zw)!70A0-0XizpUF$i*Ry?uh=qPemI>j|cO0a^Xb0lrl0hkXkZR@d*hDRGaQ=l7WOq zO*doGMzieGJwoUu>Cba?tIkxrio|kugAwL9)}j6jM7o%Xb*mZ{OmM9-6HG_lxNRRhbN?Lt%1#Q|a>GcJcYg zNcQI&l9XvE@gJJ&-zN|^iGsvGYH_`P=`X7IPleRqI;p8=<7yEUP4G9S{`Y8~70v-A z2$Xe>VDykkh_VI8pi&bBZCEkRd*>H>_n)5!dc{=iS^ggf1PS1F;23}*5(u}eG^UX&*%R^e*W+78{Pl*zMcFA&tog?oa+2F R2?qKnB_{i>R7BVBe*s(Be^LMd From 1756aa2f39db181b1721fd626ca3359b35bf5275 Mon Sep 17 00:00:00 2001 From: Charlie Cruzan <35579283+cruzach@users.noreply.github.com> Date: Tue, 14 Jan 2020 16:22:12 -0500 Subject: [PATCH 016/103] [docs] how to clear certs, backport android improvements (#6768) --- .../unversioned/distribution/app-signing.md | 6 +- .../versions/unversioned/expokit/expokit.md | 8 +- .../v36.0.0/distribution/app-signing.md | 77 +++++++++++-------- .../pages/versions/v36.0.0/expokit/expokit.md | 8 +- 4 files changed, 57 insertions(+), 42 deletions(-) diff --git a/docs/pages/versions/unversioned/distribution/app-signing.md b/docs/pages/versions/unversioned/distribution/app-signing.md index af441ace3f7f1..32b2921153b9b 100644 --- a/docs/pages/versions/unversioned/distribution/app-signing.md +++ b/docs/pages/versions/unversioned/distribution/app-signing.md @@ -15,18 +15,18 @@ The 3 primary iOS credentials, all of which are associated with your Apple Devel - Provisioning Profiles - Push Notification Keys -Whether you let Expo handle all your credentials, or you handle them all yourself, it can be valuable to understand what each of these credentials mean, when and where they're used, and what happens when they expire or are revoked. +Whether you let Expo handle all your credentials, or you handle them all yourself, it can be valuable to understand what each of these credentials mean, when and where they're used, and what happens when they expire or are revoked. You can inspect and manage all your credentials with Expo CLI by running `expo credentials:manager`. ### Distribution Certificate The distribution certificate is all about you, the developer, and not about any particular app. You may only have one distribution certificate associated with your Apple Developer account. -This certificate will be used for all of your apps. If this certificate expires, your apps in production will not be affected. However, you will need to generate a new certificate if you want to upload new apps to the App Store, or update any of your existing apps. Deleting a distribution certificate has no effect on any apps already on the App Store. +This certificate will be used for all of your apps. If this certificate expires, your apps in production will not be affected. However, you will need to generate a new certificate if you want to upload new apps to the App Store, or update any of your existing apps. Deleting a distribution certificate has no effect on any apps already on the App Store. You can clear the distribution certificate Expo currently has stored for your app the next time you build by running `expo build:ios --clear-dist-cert`. ### Push Notification Keys Apple Push Notification Keys (often abbreviated as APN keys) allow the associated apps to send and receive push notifications. By default, any app built with Expo will require an APN key. This is so that you can enable push notifications for your app through a quick [OTA update](../../guides/configuring-ota-updates/), rather than needing to submit an entirely new binary. -You can have a maximum of 2 APN keys associated with your Apple Developer account, and a single key can be used with any number of apps. If you revoke an APN key, all apps that rely on that key will no longer be able to send or receive push notifications until you upload a new key to replace it. Uploading a new APN key **will not** change your users' [Expo Push Tokens](../../sdk/notifications/#notificationsgetexpopushtokenasync). Push notification keys do not expire. +You can have a maximum of 2 APN keys associated with your Apple Developer account, and a single key can be used with any number of apps. If you revoke an APN key, all apps that rely on that key will no longer be able to send or receive push notifications until you upload a new key to replace it. Uploading a new APN key **will not** change your users' [Expo Push Tokens](../../sdk/notifications/#notificationsgetexpopushtokenasync). Push notification keys do not expire. You can clear the APN key Expo currently has stored for your app the next time you build by running `expo build:ios --clear-push-key`. ### Provisioning Profiles diff --git a/docs/pages/versions/unversioned/expokit/expokit.md b/docs/pages/versions/unversioned/expokit/expokit.md index 90fc145a07f1f..6ceb8cea5519a 100644 --- a/docs/pages/versions/unversioned/expokit/expokit.md +++ b/docs/pages/versions/unversioned/expokit/expokit.md @@ -84,11 +84,12 @@ ExpoKit's release cycle follows the Expo SDK release cycle. When a new version o - Open up `ios/Podfile` in your project, and update the `ExpoKit` tag to point at the [release](https://github.com/expo/expo/releases) corresponding to your SDK version. Run `pod update` then `pod install`. - Open `ios/your-project/Supporting/EXSDKVersions.plist` in your project and change all the values to the new SDK version. -- Install or upgrade `react-native-unimodules@^0.5.0` in your project (`yarn add -D react-native-unimodules@^0.5.0` or `npm install --save-dev react-native-unimodules@^0.5.0` if you prefer npm over Yarn). +- Install or upgrade `react-native-unimodules@^0.7.0` in your project (`yarn add -D react-native-unimodules@^0.7.0` or `npm install --save-dev react-native-unimodules@^0.7.0` if you prefer npm over Yarn). Additionally, if upgrading from SDK 35 or below: - Replace + ```ruby pod 'React', (...) @@ -98,6 +99,7 @@ pod 'React', ``` with + ```ruby # Install React Native and its dependencies require_relative '../node_modules/react-native/scripts/autolink-ios.rb' @@ -106,7 +108,7 @@ with If upgrading from SDK 32 or below: -1. If you haven't already done so install `react-native-unimodules@^0.5.0` in your project (`yarn add -D react-native-unimodules@^0.5.0` or `npm install --save-dev react-native-unimodules@^0.5.0` if you prefer npm over Yarn). +1. If you haven't already done so install `react-native-unimodules@^0.7.0` in your project (`yarn add -D react-native-unimodules@^0.7.0` or `npm install --save-dev react-native-unimodules@^0.7.0` if you prefer npm over Yarn). 2. Remove the list of unimodules' dependencies: ```ruby pod 'EXAdsAdMob', @@ -208,7 +210,7 @@ If upgrading from SDK34: If upgrading from SDK32 or below: -1. If you haven't already done so when upgrading your iOS project, install `react-native-unimodules@^0.5.0` in your project (`yarn add -D react-native-unimodules@^0.5.0` or `npm install --save-dev react-native-unimodules@^0.5.0` if you prefer npm over Yarn). +1. If you haven't already done so when upgrading your iOS project, install `react-native-unimodules@^0.7.0` in your project (`yarn add -D react-native-unimodules@^0.7.0` or `npm install --save-dev react-native-unimodules@^0.7.0` if you prefer npm over Yarn). 2. In `android/settings.gradle` add to the bottom of the file: ```groovy diff --git a/docs/pages/versions/v36.0.0/distribution/app-signing.md b/docs/pages/versions/v36.0.0/distribution/app-signing.md index ec3f15b849d38..32b2921153b9b 100644 --- a/docs/pages/versions/v36.0.0/distribution/app-signing.md +++ b/docs/pages/versions/v36.0.0/distribution/app-signing.md @@ -15,18 +15,18 @@ The 3 primary iOS credentials, all of which are associated with your Apple Devel - Provisioning Profiles - Push Notification Keys -Whether you let Expo handle all your credentials, or you handle them all yourself, it can be valuable to understand what each of these credentials mean, when and where they're used, and what happens when they expire or are revoked. +Whether you let Expo handle all your credentials, or you handle them all yourself, it can be valuable to understand what each of these credentials mean, when and where they're used, and what happens when they expire or are revoked. You can inspect and manage all your credentials with Expo CLI by running `expo credentials:manager`. ### Distribution Certificate The distribution certificate is all about you, the developer, and not about any particular app. You may only have one distribution certificate associated with your Apple Developer account. -This certificate will be used for all of your apps. If this certificate expires, your apps in production will not be affected. However, you will need to generate a new certificate if you want to upload new apps to the App Store, or update any of your existing apps. Deleting a distribution certificate has no effect on any apps already on the App Store. +This certificate will be used for all of your apps. If this certificate expires, your apps in production will not be affected. However, you will need to generate a new certificate if you want to upload new apps to the App Store, or update any of your existing apps. Deleting a distribution certificate has no effect on any apps already on the App Store. You can clear the distribution certificate Expo currently has stored for your app the next time you build by running `expo build:ios --clear-dist-cert`. ### Push Notification Keys Apple Push Notification Keys (often abbreviated as APN keys) allow the associated apps to send and receive push notifications. By default, any app built with Expo will require an APN key. This is so that you can enable push notifications for your app through a quick [OTA update](../../guides/configuring-ota-updates/), rather than needing to submit an entirely new binary. -You can have a maximum of 2 APN keys associated with your Apple Developer account, and a single key can be used with any number of apps. If you revoke an APN key, all apps that rely on that key will no longer be able to send or receive push notifications until you upload a new key to replace it. Uploading a new APN key **will not** change your users' [Expo Push Tokens](../../sdk/notifications/#notificationsgetexpopushtokenasync). Push notification keys do not expire. +You can have a maximum of 2 APN keys associated with your Apple Developer account, and a single key can be used with any number of apps. If you revoke an APN key, all apps that rely on that key will no longer be able to send or receive push notifications until you upload a new key to replace it. Uploading a new APN key **will not** change your users' [Expo Push Tokens](../../sdk/notifications/#notificationsgetexpopushtokenasync). Push notification keys do not expire. You can clear the APN key Expo currently has stored for your app the next time you build by running `expo build:ios --clear-push-key`. ### Provisioning Profiles @@ -52,45 +52,56 @@ When you use the `expo credentials:manager` or `expo build:ios --clear-credentia Google requires all Android apps to be digitally signed with a certificate before they are installed on a device or updated. Usually a private key and its public certificate are stored in a keystore. In the past, APKs uploaded to the store were required to be signed with -the **app signing certificate** (certificate that will be attached to the app in store), and if the keystore was lost there was no way to -recover or reset it. If you opt in to App Signing by Google Play you need to upload an APK signed with an **upload certificate**, and Google Play will -strip that signature and replace it with one generated using the **app signing certificate**. Both the upload keystore and keystore with -the **app signing key** are essentially the same mechanism, but if your upload keystore is lost or compromised, you can contact -the Google Play support team to reset the key. +the **app signing certificate** (certificate that will be attached to the app in the Play Store), and if the keystore was lost there was no way to +recover or reset it. Now, you can opt in to App Signing by Google Play and simply upload an APK signed with an **upload certificate**, and Google Play will automatically replace it with the **app signing certificate**. Both the old method (app signing certificate) and new method (upload certificate) are essentially the same mechanism, but using the new method, if your upload keystore is lost or compromised, you can contact the Google Play support team to reset the key. -From the build process's perspective, there is no difference whether an app is signed with an **upload certificate** or an **app signing certificate**. Either way, `expo build:android` will generate an APK signed with the keystore currently assigned to your application. If you want to generate an upload keystore manually, you can do -that the same way you created your original keystore. +From the Expo build process's perspective, there is no difference whether an app is signed with an **upload certificate** or an **app signing key**. Either way, `expo build:android` will generate an APK signed with the keystore currently associated with your application. If you want to generate an upload keystore manually, you can do that the same way you created your original keystore. See [here](https://developer.android.com/studio/publish/app-signing) to find more information about this process. -### 1. Using App Signing by Google Play (recommended) +### Option 1- Using App Signing by Google Play (recommended) -Create a new application and allow Google Play to handle your **app signing key**. The certificate used to sign the first APK uploaded to the store -will be your **upload certificate** and each new release needs to be signed with it. +#### If you're deploying a new app... -If you want to use Google Play App Signing in an existing app, run `expo opt-in-google-play-signing` and follow its instructions. After -this process, the original keystore will be backed up to your current working directory and credentials for that keystore will be printed on the screen, -Remove that keystore only when you are sure that everything works correctly. +1. Go to the [Google Play Console](https://play.google.com/apps/publish/) and create a new application -In case you lose your upload keystore (or it's compromised), you can ask Google Support Team to reset your upload key. +2. After providing a name, select the `App Signing` option on the sidebar, and then select `Continue` to allow Google Play to handle your app signing key -- If you want Expo to handle creating the upload certificate: +3. The certificate used to sign the first APK uploaded to the store will be your upload certificate and each new release needs to be signed with it. - - `expo build:android --clear-credentials` and select the option `Let Expo handle the process!`, which generates a new keystore and signs a new APK with it - - `expo fetch:android:upload-cert` extracts public certificate from the keystore into `.pem` file - - Add the upload certificate to the Google Play console. Select `Export and upload a key (not using a Java keystore)` and a dropdown will appear for `(Optional) Create a new upload key for increased security (recommended)`. Steps 1 & 2 were already completed, so move to step 3 +#### If you're working on an existing app... -- If you want to handle it create the upload certificate yourself: - - Generate a new keystore - - Extract the upload certificate with - ```bash - keytool -export -rfc - -keystore your-upload-keystore.jks - -alias upload-alias - -file output_upload_certificate.pem - ``` - - Add the upload certificate to the Google Play console +1. Run `expo opt-in-google-play-signing` from your project directory and follow the instructions. Afterwards, the keystore will be backed up to your working directory, and the credentials for that keystore will be printed in the CLI. -### 2. Signing APKs with an **app signing key** (deprecated) +2. Run `expo build:android --clear-credentials` and select the option `Let Expo handle the process!`, which generates a new keystore and signs a new APK with it -The first time you run `expo build:android`, you can choose for Expo to generate a keystore or manually specify all of the required credentials. These credentials are used to sign APKs created by Expo services. +3. Run `expo fetch:android:upload-cert` which extracts the public certificate from the keystore into a `.pem` file + +4. Add the upload certificate to the [Google Play console](https://play.google.com/apps/publish/) under your application's `App Signing` tab + +5. Open the dropdown for `(Advanced options) Provide the app signing key that Google Play uses for this app` + +6. Select `Export and upload a key (not using a Java keystore)` + +7. Select the dropdown for `(Optional) Create a new upload key for increased security (recommended)` + +8. You've already generated a new upload key and extracted the certificate, so move to step 3 and upload the public key certificate (the `.pem` file you received in step 2) + +If you want to create the upload certificate yourself, replace steps 2 and 3 from above with: + +2. Generate a new keystore + +3. Extract the upload certificate with + + ``` + bash keytool -export -rfc + -keystore your-upload-keystore.jks + -alias upload-alias + -file output_upload_certificate.pem + ``` + +> If you lose your upload keystore (or it's compromised), you must ask the Google Support Team to reset your upload key. + +### Option 2- Signing APKs with an **app signing key** (deprecated) + +The first time you run `expo build:android`, you can choose for Expo to generate a keystore or manually specify all of the required credentials. These credentials are used to sign APKs created by Expo services. **We highly reccommend you backup your keystore to a safe location**. diff --git a/docs/pages/versions/v36.0.0/expokit/expokit.md b/docs/pages/versions/v36.0.0/expokit/expokit.md index 90fc145a07f1f..6ceb8cea5519a 100644 --- a/docs/pages/versions/v36.0.0/expokit/expokit.md +++ b/docs/pages/versions/v36.0.0/expokit/expokit.md @@ -84,11 +84,12 @@ ExpoKit's release cycle follows the Expo SDK release cycle. When a new version o - Open up `ios/Podfile` in your project, and update the `ExpoKit` tag to point at the [release](https://github.com/expo/expo/releases) corresponding to your SDK version. Run `pod update` then `pod install`. - Open `ios/your-project/Supporting/EXSDKVersions.plist` in your project and change all the values to the new SDK version. -- Install or upgrade `react-native-unimodules@^0.5.0` in your project (`yarn add -D react-native-unimodules@^0.5.0` or `npm install --save-dev react-native-unimodules@^0.5.0` if you prefer npm over Yarn). +- Install or upgrade `react-native-unimodules@^0.7.0` in your project (`yarn add -D react-native-unimodules@^0.7.0` or `npm install --save-dev react-native-unimodules@^0.7.0` if you prefer npm over Yarn). Additionally, if upgrading from SDK 35 or below: - Replace + ```ruby pod 'React', (...) @@ -98,6 +99,7 @@ pod 'React', ``` with + ```ruby # Install React Native and its dependencies require_relative '../node_modules/react-native/scripts/autolink-ios.rb' @@ -106,7 +108,7 @@ with If upgrading from SDK 32 or below: -1. If you haven't already done so install `react-native-unimodules@^0.5.0` in your project (`yarn add -D react-native-unimodules@^0.5.0` or `npm install --save-dev react-native-unimodules@^0.5.0` if you prefer npm over Yarn). +1. If you haven't already done so install `react-native-unimodules@^0.7.0` in your project (`yarn add -D react-native-unimodules@^0.7.0` or `npm install --save-dev react-native-unimodules@^0.7.0` if you prefer npm over Yarn). 2. Remove the list of unimodules' dependencies: ```ruby pod 'EXAdsAdMob', @@ -208,7 +210,7 @@ If upgrading from SDK34: If upgrading from SDK32 or below: -1. If you haven't already done so when upgrading your iOS project, install `react-native-unimodules@^0.5.0` in your project (`yarn add -D react-native-unimodules@^0.5.0` or `npm install --save-dev react-native-unimodules@^0.5.0` if you prefer npm over Yarn). +1. If you haven't already done so when upgrading your iOS project, install `react-native-unimodules@^0.7.0` in your project (`yarn add -D react-native-unimodules@^0.7.0` or `npm install --save-dev react-native-unimodules@^0.7.0` if you prefer npm over Yarn). 2. In `android/settings.gradle` add to the bottom of the file: ```groovy From 49e074d69385a7a2567b561a6906f171d6f10578 Mon Sep 17 00:00:00 2001 From: James Ide Date: Wed, 15 Jan 2020 14:18:34 -0800 Subject: [PATCH 017/103] [changelog] Add note about Linking's standards-compliant parsing behavior to the changelog Adding a note about https://github.com/expo/expo/issues/6497#issuecomment-574882448 to the changelog. Since the new parsing is more standards-compliant, URLs like `myapp://hello/world` now consider `hello` to be the hostname, not part of the path (think about `http://localhost/path`). Closes #6497. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb189d217fab2..4ec626ebd2f44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,7 +46,7 @@ This is the log of notable changes to the Expo client that are developer-facing. - **`jest-expo`**: Removed `mockPlatformIOS()`, `mockPlatformAndroid()`, `mockPlatformWeb()`, `describeCrossPlatform()` in favor of platform specific presets like `jest-expo/universal`. ([#5645](https://github.com/expo/expo/pull/5645) by [@EvanBacon](https://github.com/EvanBacon)) - **`expo`**: Removed Branch export from `expo/Branch`. ([#6190](https://github.com/expo/expo/pull/6190) by [@sjchmiela](https://github.com/sjchmiela)) - **`expo`**: Removed `ErrorRecovery` from the `expo` package and extracted into `expo-error-recovery` unimodule. ([#5357](https://github.com/expo/expo/pull/5357) by [@lukmccall](https://github.com/lukmccall)) -- **`expo`**: Updated `Linking.parse` to better handle non-expo URLs. ([#5179](https://github.com/expo/expo/pull/5179) by [@koenpunt](https://github.com/koenpunt)) +- **`expo`**: Updated `Linking.parse` to better handle non-expo URLs. URLs like `myapp://hello/world` are now parsed so that `hello` is the hostname and `world` is the path, according to the URI specification; [more info here](https://github.com/expo/expo/issues/6497#issuecomment-574882448). ([#5179](https://github.com/expo/expo/pull/5179) by [@koenpunt](https://github.com/koenpunt)) - **`expo-analytics-segment`**: Fixed `enabled` behavior inverted on iOS. ([#6242](https://github.com/expo/expo/pull/6242) by [@sjchmiela](https://github.com/sjchmiela)) - **`expo-facebook`**: Disabled autoinitialization of the Facebook SDK and added an `initializeAsync` method and `autoinit` app.json setting. ([#5924] by [@sjchmiela](https://github.com/sjchmiela)) - **`expo-keep-awake`**: Removed deprecated methods and components. ([#6006](https://github.com/expo/expo/pull/6006) by [@EvanBacon](https://github.com/EvanBacon)) From e50f4c3836921d1a5d1e604162fefc29973e31a5 Mon Sep 17 00:00:00 2001 From: Charlie Cruzan <35579283+cruzach@users.noreply.github.com> Date: Thu, 16 Jan 2020 13:27:46 -0500 Subject: [PATCH 018/103] [linking] decode query params (#6774) * [linking] decode query params * move code to beforeEach and afterEach --- packages/expo/build/Linking/Linking.js | 3 ++ packages/expo/build/Linking/Linking.js.map | 2 +- packages/expo/src/Linking/Linking.ts | 3 ++ packages/expo/src/__tests__/Linking-test.ts | 25 +++++++++++ .../Linking-test.ts.snap.android | 43 +++++++++++++++++++ .../__snapshots__/Linking-test.ts.snap.ios | 43 +++++++++++++++++++ .../__snapshots__/Linking-test.ts.snap.node | 43 +++++++++++++++++++ .../__snapshots__/Linking-test.ts.snap.web | 43 +++++++++++++++++++ 8 files changed, 204 insertions(+), 1 deletion(-) diff --git a/packages/expo/build/Linking/Linking.js b/packages/expo/build/Linking/Linking.js index 6c47a9ddd26e2..56c599efad625 100644 --- a/packages/expo/build/Linking/Linking.js +++ b/packages/expo/build/Linking/Linking.js @@ -90,6 +90,9 @@ function parse(url) { throw new Error('parse cannot be called with a null value'); } const parsed = URL(url, /* parseQueryString */ true); + for (const param in parsed.query) { + parsed.query[param] = decodeURIComponent(parsed.query[param]); + } let queryParams = parsed.query; let hostUri = HOST_URI || ''; let hostUriStripped = _removePort(_removeTrailingSlashAndQueryString(hostUri)); diff --git a/packages/expo/build/Linking/Linking.js.map b/packages/expo/build/Linking/Linking.js.map index e1ea30ce61f53..4cf3a72649bf6 100644 --- a/packages/expo/build/Linking/Linking.js.map +++ b/packages/expo/build/Linking/Linking.js.map @@ -1 +1 @@ -{"version":3,"file":"Linking.js","sourceRoot":"","sources":["../../src/Linking/Linking.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,OAAO,GAAG,MAAM,WAAW,CAAC;AAE5B,OAAO,OAAO,MAAM,iBAAiB,CAAC;AAEtC,MAAM,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAC;AAE/B,MAAM,kBAAkB,GAAG,SAAS,CAAC,YAAY,KAAK,YAAY,IAAI,QAAQ,CAAC,MAAM,CAAC;AAEtF,IAAI,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC;AAChC,IAAI,CAAC,QAAQ,IAAI,CAAC,kBAAkB,EAAE;IACpC,mEAAmE;IACnE,gFAAgF;IAChF,QAAQ,GAAG,aAAa,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;CAC7E;AACD,MAAM,cAAc,GAClB,QAAQ;IACR,CAAC,mEAAmE,CAAC,IAAI,CAAC,QAAQ,CAAC;QACjF,QAAQ,CAAC,SAAS,CAAC,CAAC;AAExB,SAAS,aAAa,CAAC,GAAW;IAChC,OAAO,GAAG,CAAC,OAAO,CAAC,uBAAuB,EAAE,EAAE,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,WAAW,CAAC,GAAW;IAC9B,OAAO,GAAG,CAAC,OAAO,CAAC,qCAAqC,EAAE,EAAE,CAAC,CAAC;AAChE,CAAC;AAED,SAAS,mBAAmB,CAAC,GAAW;IACtC,OAAO,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,oBAAoB,CAAC,GAAW;IACvC,OAAO,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,kCAAkC,CAAC,GAAW;IACrD,OAAO,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,OAAO,CAAC,OAAe,EAAE,EAAE,cAA2B,EAAE;IAC/D,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,IAAI,cAAc,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAEpF,IAAI,SAAS,CAAC,YAAY,KAAK,YAAY,IAAI,cAAc,EAAE;QAC7D,MAAM,GAAG,cAAc,CAAC;KACzB;SAAM,IAAI,SAAS,CAAC,YAAY,KAAK,YAAY,IAAI,CAAC,cAAc,EAAE;QACrE,MAAM,IAAI,KAAK,CAAC,6EAA6E,CAAC,CAAC;KAChG;SAAM,IAAI,SAAS,CAAC,YAAY,KAAK,MAAM,IAAI,CAAC,cAAc,EAAE;QAC/D,OAAO,CAAC,IAAI,CACV,kZAAkZ,CACnZ,CAAC;KACH;IAED,IAAI,OAAO,GAAG,QAAQ,IAAI,EAAE,CAAC;IAC7B,IAAI,kBAAkB,IAAI,cAAc,EAAE;QACxC,OAAO,GAAG,EAAE,CAAC;KACd;IAED,IAAI,IAAI,EAAE;QACR,IAAI,cAAc,IAAI,OAAO,EAAE;YAC7B,IAAI,GAAG,OAAO,mBAAmB,CAAC,IAAI,CAAC,EAAE,CAAC;SAC3C;QAED,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,OAAO,EAAE;YACpC,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;SACnB;aAAM,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE;YAC3C,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;SACvB;KACF;SAAM;QACL,IAAI,GAAG,EAAE,CAAC;KACX;IAED,6EAA6E;IAC7E,uBAAuB;IACvB,IAAI,WAAW,GAAG,EAAE,CAAC;IACrB,IAAI,sBAAsB,GAAG,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACzD,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,IAAI,YAAY,GAAG,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YACzC,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,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAExC,OAAO,SAAS,CAAC,GAAG,MAAM,MAAM,OAAO,GAAG,IAAI,GAAG,WAAW,EAAE,CAAC,CAAC;AAClE,CAAC;AAED,SAAS,KAAK,CAAC,GAAW;IACxB,IAAI,CAAC,GAAG,EAAE;QACR,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;KAC7D;IAED,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,sBAAsB,CAAC,IAAI,CAAC,CAAC;IAErD,IAAI,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC;IAE/B,IAAI,OAAO,GAAG,QAAQ,IAAI,EAAE,CAAC;IAC7B,IAAI,eAAe,GAAG,WAAW,CAAC,kCAAkC,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,mBAAmB,CAAC,IAAI,CAAC,CAAC;QAEjC,IAAI,UAAU,GAAkB,IAAI,CAAC;QACrC,IAAI,eAAe,EAAE;YACnB,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACzC,UAAU,GAAG,KAAK;iBACf,KAAK,CAAC,CAAC,CAAC;iBACR,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC;iBACf,IAAI,CAAC,GAAG,CAAC,CAAC;SACd;QAED,IAAI,cAAc,IAAI,CAAC,kBAAkB,IAAI,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE;YACtF,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,KAAK,UAAU,oBAAoB;IACjC,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,aAAa,EAAE,CAAC;IACjD,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;AAQD,yBAAyB;AACzB,IAAI,UAAU,GAAG,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;AAE3C,UAAU,CAAC,OAAO,GAAG,OAAO,CAAC;AAC7B,UAAU,CAAC,KAAK,GAAG,KAAK,CAAC;AACzB,UAAU,CAAC,oBAAoB,GAAG,oBAAoB,CAAC;AAEvD,eAAe,UAAyB,CAAC","sourcesContent":["import Constants from 'expo-constants';\nimport qs from 'qs';\nimport { LinkingStatic } from 'react-native';\nimport URL from 'url-parse';\nimport { ParsedURL, QueryParams } from './Linking.types';\nimport Linking from './LinkingModule';\n\nconst { manifest } = Constants;\n\nconst USES_CUSTOM_SCHEME = Constants.appOwnership === 'standalone' && manifest.scheme;\n\nlet HOST_URI = manifest.hostUri;\nif (!HOST_URI && !USES_CUSTOM_SCHEME) {\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 HOST_URI = _removeScheme(Constants.linkingUri).replace(/\\/--($|\\/.*$)/, '');\n}\nconst IS_EXPO_HOSTED =\n HOST_URI &&\n (/^(.*\\.)?(expo\\.io|exp\\.host|exp\\.direct|expo\\.test)(:.*)?(\\/.*)?$/.test(HOST_URI) ||\n manifest.developer);\n\nfunction _removeScheme(url: string) {\n return url.replace(/^[a-zA-Z0-9+.-]+:\\/\\//, '');\n}\n\nfunction _removePort(url: string) {\n return url.replace(/(?=([a-zA-Z0-9+.-]+:\\/\\/)?[^/]):\\d+/, '');\n}\n\nfunction _removeLeadingSlash(url: string) {\n return url.replace(/^\\//, '');\n}\n\nfunction _removeTrailingSlash(url: string) {\n return url.replace(/\\/$/, '');\n}\n\nfunction _removeTrailingSlashAndQueryString(url: string) {\n return url.replace(/\\/?\\?.*$/, '');\n}\n\nfunction makeUrl(path: string = '', queryParams: QueryParams = {}): string {\n let scheme = 'exp';\n let manifestScheme = manifest.scheme || (manifest.detach && manifest.detach.scheme);\n\n if (Constants.appOwnership === 'standalone' && manifestScheme) {\n scheme = manifestScheme;\n } else if (Constants.appOwnership === 'standalone' && !manifestScheme) {\n throw new Error('Cannot make a deep link into a standalone app with no custom scheme defined');\n } else if (Constants.appOwnership === 'expo' && !manifestScheme) {\n console.warn(\n 'Linking requires that you provide a `scheme` in app.json for standalone apps - if it is 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. Add a `scheme` to silence this warning. Learn more about Linking at https://docs.expo.io/versions/latest/workflow/linking/'\n );\n }\n\n let hostUri = HOST_URI || '';\n if (USES_CUSTOM_SCHEME && IS_EXPO_HOSTED) {\n hostUri = '';\n }\n\n if (path) {\n if (IS_EXPO_HOSTED && hostUri) {\n path = `/--/${_removeLeadingSlash(path)}`;\n }\n\n if (!path.startsWith('/') && hostUri) {\n path = `/${path}`;\n } else if (path.startsWith('/') && !hostUri) {\n path = path.substr(1);\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 let queryStringMatchResult = hostUri.match(/(.*)\\?(.+)/);\n if (queryStringMatchResult) {\n hostUri = queryStringMatchResult[1];\n queryString = queryStringMatchResult[2];\n let paramsFromHostUri = {};\n try {\n let 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 = _removeTrailingSlash(hostUri);\n\n return encodeURI(`${scheme}://${hostUri}${path}${queryString}`);\n}\n\nfunction parse(url: string): ParsedURL {\n if (!url) {\n throw new Error('parse cannot be called with a null value');\n }\n\n const parsed = URL(url, /* parseQueryString */ true);\n\n let queryParams = parsed.query;\n\n let hostUri = HOST_URI || '';\n let 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\n .slice(1)\n .concat(['--/'])\n .join('/');\n }\n\n if (IS_EXPO_HOSTED && !USES_CUSTOM_SCHEME && 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\nasync function parseInitialURLAsync(): Promise {\n const initialUrl = await Linking.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\ninterface ExpoLinking extends LinkingStatic {\n makeUrl: typeof makeUrl;\n parse: typeof parse;\n parseInitialURLAsync: typeof parseInitialURLAsync;\n}\n\n// @ts-ignore fix this...\nlet newLinking = new Linking.constructor();\n\nnewLinking.makeUrl = makeUrl;\nnewLinking.parse = parse;\nnewLinking.parseInitialURLAsync = parseInitialURLAsync;\n\nexport default newLinking as ExpoLinking;\n"]} \ No newline at end of file +{"version":3,"file":"Linking.js","sourceRoot":"","sources":["../../src/Linking/Linking.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,OAAO,GAAG,MAAM,WAAW,CAAC;AAE5B,OAAO,OAAO,MAAM,iBAAiB,CAAC;AAEtC,MAAM,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAC;AAE/B,MAAM,kBAAkB,GAAG,SAAS,CAAC,YAAY,KAAK,YAAY,IAAI,QAAQ,CAAC,MAAM,CAAC;AAEtF,IAAI,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC;AAChC,IAAI,CAAC,QAAQ,IAAI,CAAC,kBAAkB,EAAE;IACpC,mEAAmE;IACnE,gFAAgF;IAChF,QAAQ,GAAG,aAAa,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;CAC7E;AACD,MAAM,cAAc,GAClB,QAAQ;IACR,CAAC,mEAAmE,CAAC,IAAI,CAAC,QAAQ,CAAC;QACjF,QAAQ,CAAC,SAAS,CAAC,CAAC;AAExB,SAAS,aAAa,CAAC,GAAW;IAChC,OAAO,GAAG,CAAC,OAAO,CAAC,uBAAuB,EAAE,EAAE,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,WAAW,CAAC,GAAW;IAC9B,OAAO,GAAG,CAAC,OAAO,CAAC,qCAAqC,EAAE,EAAE,CAAC,CAAC;AAChE,CAAC;AAED,SAAS,mBAAmB,CAAC,GAAW;IACtC,OAAO,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,oBAAoB,CAAC,GAAW;IACvC,OAAO,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,kCAAkC,CAAC,GAAW;IACrD,OAAO,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,OAAO,CAAC,OAAe,EAAE,EAAE,cAA2B,EAAE;IAC/D,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,IAAI,cAAc,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAEpF,IAAI,SAAS,CAAC,YAAY,KAAK,YAAY,IAAI,cAAc,EAAE;QAC7D,MAAM,GAAG,cAAc,CAAC;KACzB;SAAM,IAAI,SAAS,CAAC,YAAY,KAAK,YAAY,IAAI,CAAC,cAAc,EAAE;QACrE,MAAM,IAAI,KAAK,CAAC,6EAA6E,CAAC,CAAC;KAChG;SAAM,IAAI,SAAS,CAAC,YAAY,KAAK,MAAM,IAAI,CAAC,cAAc,EAAE;QAC/D,OAAO,CAAC,IAAI,CACV,kZAAkZ,CACnZ,CAAC;KACH;IAED,IAAI,OAAO,GAAG,QAAQ,IAAI,EAAE,CAAC;IAC7B,IAAI,kBAAkB,IAAI,cAAc,EAAE;QACxC,OAAO,GAAG,EAAE,CAAC;KACd;IAED,IAAI,IAAI,EAAE;QACR,IAAI,cAAc,IAAI,OAAO,EAAE;YAC7B,IAAI,GAAG,OAAO,mBAAmB,CAAC,IAAI,CAAC,EAAE,CAAC;SAC3C;QAED,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,OAAO,EAAE;YACpC,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;SACnB;aAAM,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE;YAC3C,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;SACvB;KACF;SAAM;QACL,IAAI,GAAG,EAAE,CAAC;KACX;IAED,6EAA6E;IAC7E,uBAAuB;IACvB,IAAI,WAAW,GAAG,EAAE,CAAC;IACrB,IAAI,sBAAsB,GAAG,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACzD,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,IAAI,YAAY,GAAG,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YACzC,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,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAExC,OAAO,SAAS,CAAC,GAAG,MAAM,MAAM,OAAO,GAAG,IAAI,GAAG,WAAW,EAAE,CAAC,CAAC;AAClE,CAAC;AAED,SAAS,KAAK,CAAC,GAAW;IACxB,IAAI,CAAC,GAAG,EAAE;QACR,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;KAC7D;IAED,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,IAAI,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC;IAE/B,IAAI,OAAO,GAAG,QAAQ,IAAI,EAAE,CAAC;IAC7B,IAAI,eAAe,GAAG,WAAW,CAAC,kCAAkC,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,mBAAmB,CAAC,IAAI,CAAC,CAAC;QAEjC,IAAI,UAAU,GAAkB,IAAI,CAAC;QACrC,IAAI,eAAe,EAAE;YACnB,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACzC,UAAU,GAAG,KAAK;iBACf,KAAK,CAAC,CAAC,CAAC;iBACR,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC;iBACf,IAAI,CAAC,GAAG,CAAC,CAAC;SACd;QAED,IAAI,cAAc,IAAI,CAAC,kBAAkB,IAAI,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE;YACtF,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,KAAK,UAAU,oBAAoB;IACjC,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,aAAa,EAAE,CAAC;IACjD,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;AAQD,yBAAyB;AACzB,IAAI,UAAU,GAAG,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;AAE3C,UAAU,CAAC,OAAO,GAAG,OAAO,CAAC;AAC7B,UAAU,CAAC,KAAK,GAAG,KAAK,CAAC;AACzB,UAAU,CAAC,oBAAoB,GAAG,oBAAoB,CAAC;AAEvD,eAAe,UAAyB,CAAC","sourcesContent":["import Constants from 'expo-constants';\nimport qs from 'qs';\nimport { LinkingStatic } from 'react-native';\nimport URL from 'url-parse';\nimport { ParsedURL, QueryParams } from './Linking.types';\nimport Linking from './LinkingModule';\n\nconst { manifest } = Constants;\n\nconst USES_CUSTOM_SCHEME = Constants.appOwnership === 'standalone' && manifest.scheme;\n\nlet HOST_URI = manifest.hostUri;\nif (!HOST_URI && !USES_CUSTOM_SCHEME) {\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 HOST_URI = _removeScheme(Constants.linkingUri).replace(/\\/--($|\\/.*$)/, '');\n}\nconst IS_EXPO_HOSTED =\n HOST_URI &&\n (/^(.*\\.)?(expo\\.io|exp\\.host|exp\\.direct|expo\\.test)(:.*)?(\\/.*)?$/.test(HOST_URI) ||\n manifest.developer);\n\nfunction _removeScheme(url: string) {\n return url.replace(/^[a-zA-Z0-9+.-]+:\\/\\//, '');\n}\n\nfunction _removePort(url: string) {\n return url.replace(/(?=([a-zA-Z0-9+.-]+:\\/\\/)?[^/]):\\d+/, '');\n}\n\nfunction _removeLeadingSlash(url: string) {\n return url.replace(/^\\//, '');\n}\n\nfunction _removeTrailingSlash(url: string) {\n return url.replace(/\\/$/, '');\n}\n\nfunction _removeTrailingSlashAndQueryString(url: string) {\n return url.replace(/\\/?\\?.*$/, '');\n}\n\nfunction makeUrl(path: string = '', queryParams: QueryParams = {}): string {\n let scheme = 'exp';\n let manifestScheme = manifest.scheme || (manifest.detach && manifest.detach.scheme);\n\n if (Constants.appOwnership === 'standalone' && manifestScheme) {\n scheme = manifestScheme;\n } else if (Constants.appOwnership === 'standalone' && !manifestScheme) {\n throw new Error('Cannot make a deep link into a standalone app with no custom scheme defined');\n } else if (Constants.appOwnership === 'expo' && !manifestScheme) {\n console.warn(\n 'Linking requires that you provide a `scheme` in app.json for standalone apps - if it is 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. Add a `scheme` to silence this warning. Learn more about Linking at https://docs.expo.io/versions/latest/workflow/linking/'\n );\n }\n\n let hostUri = HOST_URI || '';\n if (USES_CUSTOM_SCHEME && IS_EXPO_HOSTED) {\n hostUri = '';\n }\n\n if (path) {\n if (IS_EXPO_HOSTED && hostUri) {\n path = `/--/${_removeLeadingSlash(path)}`;\n }\n\n if (!path.startsWith('/') && hostUri) {\n path = `/${path}`;\n } else if (path.startsWith('/') && !hostUri) {\n path = path.substr(1);\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 let queryStringMatchResult = hostUri.match(/(.*)\\?(.+)/);\n if (queryStringMatchResult) {\n hostUri = queryStringMatchResult[1];\n queryString = queryStringMatchResult[2];\n let paramsFromHostUri = {};\n try {\n let 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 = _removeTrailingSlash(hostUri);\n\n return encodeURI(`${scheme}://${hostUri}${path}${queryString}`);\n}\n\nfunction parse(url: string): ParsedURL {\n if (!url) {\n throw new Error('parse cannot be called with a null value');\n }\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 let queryParams = parsed.query;\n\n let hostUri = HOST_URI || '';\n let 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\n .slice(1)\n .concat(['--/'])\n .join('/');\n }\n\n if (IS_EXPO_HOSTED && !USES_CUSTOM_SCHEME && 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\nasync function parseInitialURLAsync(): Promise {\n const initialUrl = await Linking.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\ninterface ExpoLinking extends LinkingStatic {\n makeUrl: typeof makeUrl;\n parse: typeof parse;\n parseInitialURLAsync: typeof parseInitialURLAsync;\n}\n\n// @ts-ignore fix this...\nlet newLinking = new Linking.constructor();\n\nnewLinking.makeUrl = makeUrl;\nnewLinking.parse = parse;\nnewLinking.parseInitialURLAsync = parseInitialURLAsync;\n\nexport default newLinking as ExpoLinking;\n"]} \ No newline at end of file diff --git a/packages/expo/src/Linking/Linking.ts b/packages/expo/src/Linking/Linking.ts index 1666c4f480197..2be0b8c7357cf 100644 --- a/packages/expo/src/Linking/Linking.ts +++ b/packages/expo/src/Linking/Linking.ts @@ -109,6 +109,9 @@ function parse(url: string): ParsedURL { const parsed = URL(url, /* parseQueryString */ true); + for (const param in parsed.query) { + parsed.query[param] = decodeURIComponent(parsed.query[param]!); + } let queryParams = parsed.query; let hostUri = HOST_URI || ''; diff --git a/packages/expo/src/__tests__/Linking-test.ts b/packages/expo/src/__tests__/Linking-test.ts index 5f73e87b9c86f..d1057503f33da 100644 --- a/packages/expo/src/__tests__/Linking-test.ts +++ b/packages/expo/src/__tests__/Linking-test.ts @@ -1,4 +1,5 @@ import Linking from '../Linking/Linking'; +import { QueryParams } from '../Linking/Linking.types'; describe('parse', () => { test.each([ @@ -11,6 +12,9 @@ describe('parse', () => { 'https://example.com/test/path', 'https://example.com:8000/test/path', 'https://example.com:8000/test/path+with+plus', + 'https://example.com/test/path?query=do+not+escape', + 'https://example.com/test/path?missingQueryValue=', + 'custom:///?shouldBeEscaped=x%252By%2540xxx.com', 'custom:///test/path?foo=bar', 'custom:///', 'custom://', @@ -20,3 +24,24 @@ describe('parse', () => { expect(Linking.parse(url)).toMatchSnapshot(); }); }); + +describe('makeUrl queries', () => { + const consoleWarn = console.warn; + beforeEach(() => { + console.warn = jest.fn(); + }); + + afterEach(() => { + console.warn = consoleWarn; + }); + + test.each([ + { shouldEscape: '%2b%20' }, + { escapePluses: 'email+with+plus@whatever.com' }, + { emptyParam: '' }, + { undefinedParam: undefined }, + { lotsOfSlashes: '/////' }, + ])(`makes url %p`, queryParams => { + expect(Linking.makeUrl('some/path', queryParams)).toMatchSnapshot(); + }); +}); diff --git a/packages/expo/src/__tests__/__snapshots__/Linking-test.ts.snap.android b/packages/expo/src/__tests__/__snapshots__/Linking-test.ts.snap.android index 34e3971491b79..b2b9a960f47e2 100644 --- a/packages/expo/src/__tests__/__snapshots__/Linking-test.ts.snap.android +++ b/packages/expo/src/__tests__/__snapshots__/Linking-test.ts.snap.android @@ -1,5 +1,15 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`makeUrl queries makes url {"emptyParam": ""} 1`] = `"exp://exp.host/@test/test/--/some/path?emptyParam="`; + +exports[`makeUrl queries makes url {"escapePluses": "email+with+plus@whatever.com"} 1`] = `"exp://exp.host/@test/test/--/some/path?escapePluses=email%252Bwith%252Bplus%2540whatever.com"`; + +exports[`makeUrl queries makes url {"lotsOfSlashes": "/////"} 1`] = `"exp://exp.host/@test/test/--/some/path?lotsOfSlashes=%252F%252F%252F%252F%252F"`; + +exports[`makeUrl queries makes url {"shouldEscape": "%2b%20"} 1`] = `"exp://exp.host/@test/test/--/some/path?shouldEscape=%25252b%252520"`; + +exports[`makeUrl queries makes url {"undefinedParam": undefined} 1`] = `"exp://exp.host/@test/test/--/some/path"`; + exports[`parse parses "custom://" 1`] = ` Object { "hostname": null, @@ -18,6 +28,17 @@ Object { } `; +exports[`parse parses "custom:///?shouldBeEscaped=x%252By%2540xxx.com" 1`] = ` +Object { + "hostname": null, + "path": "", + "queryParams": Object { + "shouldBeEscaped": "x+y@xxx.com", + }, + "scheme": "custom", +} +`; + exports[`parse parses "custom:///test/path?foo=bar" 1`] = ` Object { "hostname": null, @@ -100,6 +121,28 @@ Object { } `; +exports[`parse parses "https://example.com/test/path?missingQueryValue=" 1`] = ` +Object { + "hostname": "example.com", + "path": "test/path", + "queryParams": Object { + "missingQueryValue": "", + }, + "scheme": "https", +} +`; + +exports[`parse parses "https://example.com/test/path?query=do+not+escape" 1`] = ` +Object { + "hostname": "example.com", + "path": "test/path", + "queryParams": Object { + "query": "do not escape", + }, + "scheme": "https", +} +`; + exports[`parse parses "https://example.com/test/path?query=param" 1`] = ` Object { "hostname": "example.com", diff --git a/packages/expo/src/__tests__/__snapshots__/Linking-test.ts.snap.ios b/packages/expo/src/__tests__/__snapshots__/Linking-test.ts.snap.ios index 34e3971491b79..b2b9a960f47e2 100644 --- a/packages/expo/src/__tests__/__snapshots__/Linking-test.ts.snap.ios +++ b/packages/expo/src/__tests__/__snapshots__/Linking-test.ts.snap.ios @@ -1,5 +1,15 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`makeUrl queries makes url {"emptyParam": ""} 1`] = `"exp://exp.host/@test/test/--/some/path?emptyParam="`; + +exports[`makeUrl queries makes url {"escapePluses": "email+with+plus@whatever.com"} 1`] = `"exp://exp.host/@test/test/--/some/path?escapePluses=email%252Bwith%252Bplus%2540whatever.com"`; + +exports[`makeUrl queries makes url {"lotsOfSlashes": "/////"} 1`] = `"exp://exp.host/@test/test/--/some/path?lotsOfSlashes=%252F%252F%252F%252F%252F"`; + +exports[`makeUrl queries makes url {"shouldEscape": "%2b%20"} 1`] = `"exp://exp.host/@test/test/--/some/path?shouldEscape=%25252b%252520"`; + +exports[`makeUrl queries makes url {"undefinedParam": undefined} 1`] = `"exp://exp.host/@test/test/--/some/path"`; + exports[`parse parses "custom://" 1`] = ` Object { "hostname": null, @@ -18,6 +28,17 @@ Object { } `; +exports[`parse parses "custom:///?shouldBeEscaped=x%252By%2540xxx.com" 1`] = ` +Object { + "hostname": null, + "path": "", + "queryParams": Object { + "shouldBeEscaped": "x+y@xxx.com", + }, + "scheme": "custom", +} +`; + exports[`parse parses "custom:///test/path?foo=bar" 1`] = ` Object { "hostname": null, @@ -100,6 +121,28 @@ Object { } `; +exports[`parse parses "https://example.com/test/path?missingQueryValue=" 1`] = ` +Object { + "hostname": "example.com", + "path": "test/path", + "queryParams": Object { + "missingQueryValue": "", + }, + "scheme": "https", +} +`; + +exports[`parse parses "https://example.com/test/path?query=do+not+escape" 1`] = ` +Object { + "hostname": "example.com", + "path": "test/path", + "queryParams": Object { + "query": "do not escape", + }, + "scheme": "https", +} +`; + exports[`parse parses "https://example.com/test/path?query=param" 1`] = ` Object { "hostname": "example.com", diff --git a/packages/expo/src/__tests__/__snapshots__/Linking-test.ts.snap.node b/packages/expo/src/__tests__/__snapshots__/Linking-test.ts.snap.node index bcd73e2cfc850..e4574313d5d2f 100644 --- a/packages/expo/src/__tests__/__snapshots__/Linking-test.ts.snap.node +++ b/packages/expo/src/__tests__/__snapshots__/Linking-test.ts.snap.node @@ -1,5 +1,15 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`makeUrl queries makes url {"emptyParam": ""} 1`] = `"exp://some/path?emptyParam="`; + +exports[`makeUrl queries makes url {"escapePluses": "email+with+plus@whatever.com"} 1`] = `"exp://some/path?escapePluses=email%252Bwith%252Bplus%2540whatever.com"`; + +exports[`makeUrl queries makes url {"lotsOfSlashes": "/////"} 1`] = `"exp://some/path?lotsOfSlashes=%252F%252F%252F%252F%252F"`; + +exports[`makeUrl queries makes url {"shouldEscape": "%2b%20"} 1`] = `"exp://some/path?shouldEscape=%25252b%252520"`; + +exports[`makeUrl queries makes url {"undefinedParam": undefined} 1`] = `"exp://some/path"`; + exports[`parse parses "custom://" 1`] = ` Object { "hostname": null, @@ -18,6 +28,17 @@ Object { } `; +exports[`parse parses "custom:///?shouldBeEscaped=x%252By%2540xxx.com" 1`] = ` +Object { + "hostname": null, + "path": "", + "queryParams": Object { + "shouldBeEscaped": "x+y@xxx.com", + }, + "scheme": "custom", +} +`; + exports[`parse parses "custom:///test/path?foo=bar" 1`] = ` Object { "hostname": null, @@ -100,6 +121,28 @@ Object { } `; +exports[`parse parses "https://example.com/test/path?missingQueryValue=" 1`] = ` +Object { + "hostname": "example.com", + "path": "test/path", + "queryParams": Object { + "missingQueryValue": "", + }, + "scheme": "https", +} +`; + +exports[`parse parses "https://example.com/test/path?query=do+not+escape" 1`] = ` +Object { + "hostname": "example.com", + "path": "test/path", + "queryParams": Object { + "query": "do not escape", + }, + "scheme": "https", +} +`; + exports[`parse parses "https://example.com/test/path?query=param" 1`] = ` Object { "hostname": "example.com", diff --git a/packages/expo/src/__tests__/__snapshots__/Linking-test.ts.snap.web b/packages/expo/src/__tests__/__snapshots__/Linking-test.ts.snap.web index 9adc1b01ee3ee..bcc5cfb73b80e 100644 --- a/packages/expo/src/__tests__/__snapshots__/Linking-test.ts.snap.web +++ b/packages/expo/src/__tests__/__snapshots__/Linking-test.ts.snap.web @@ -1,5 +1,15 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`makeUrl queries makes url {"emptyParam": ""} 1`] = `"exp://localhost/some/path?emptyParam="`; + +exports[`makeUrl queries makes url {"escapePluses": "email+with+plus@whatever.com"} 1`] = `"exp://localhost/some/path?escapePluses=email%252Bwith%252Bplus%2540whatever.com"`; + +exports[`makeUrl queries makes url {"lotsOfSlashes": "/////"} 1`] = `"exp://localhost/some/path?lotsOfSlashes=%252F%252F%252F%252F%252F"`; + +exports[`makeUrl queries makes url {"shouldEscape": "%2b%20"} 1`] = `"exp://localhost/some/path?shouldEscape=%25252b%252520"`; + +exports[`makeUrl queries makes url {"undefinedParam": undefined} 1`] = `"exp://localhost/some/path"`; + exports[`parse parses "custom://" 1`] = ` Object { "hostname": null, @@ -18,6 +28,17 @@ Object { } `; +exports[`parse parses "custom:///?shouldBeEscaped=x%252By%2540xxx.com" 1`] = ` +Object { + "hostname": null, + "path": "", + "queryParams": Object { + "shouldBeEscaped": "x+y@xxx.com", + }, + "scheme": "custom", +} +`; + exports[`parse parses "custom:///test/path?foo=bar" 1`] = ` Object { "hostname": null, @@ -100,6 +121,28 @@ Object { } `; +exports[`parse parses "https://example.com/test/path?missingQueryValue=" 1`] = ` +Object { + "hostname": "example.com", + "path": "test/path", + "queryParams": Object { + "missingQueryValue": "", + }, + "scheme": "https", +} +`; + +exports[`parse parses "https://example.com/test/path?query=do+not+escape" 1`] = ` +Object { + "hostname": "example.com", + "path": "test/path", + "queryParams": Object { + "query": "do not escape", + }, + "scheme": "https", +} +`; + exports[`parse parses "https://example.com/test/path?query=param" 1`] = ` Object { "hostname": "example.com", From 7c7ab8541eb56e25f4e04c9809ece335fdb944b4 Mon Sep 17 00:00:00 2001 From: Brent Vatne Date: Thu, 16 Jan 2020 11:27:43 -0800 Subject: [PATCH 019/103] [docs] First pass at tutorial (#6769) --- docs/common/navigation-data.js | 1 + docs/common/navigation.js | 16 +- docs/components/base/code.js | 9 +- docs/components/icons/BrandLogo.js | 9 +- docs/components/plugins/Highlight.js | 11 ++ docs/components/plugins/SnackInline.js | 10 +- docs/global-styles/tippy.js | 4 + .../get-started/create-a-new-app.md | 5 +- .../unversioned/introduction/why-not-expo.md | 4 +- .../pages/versions/unversioned/sdk/sharing.md | 27 +++ .../versions/unversioned/tutorial/button.md | 126 ++++++++++++++ .../unversioned/tutorial/follow-up.md | 69 ++++++++ .../unversioned/tutorial/image-picker.md | 159 ++++++++++++++++++ .../versions/unversioned/tutorial/image.md | 143 ++++++++++++++++ .../versions/unversioned/tutorial/planning.md | 17 ++ .../tutorial/platform-differences.md | 79 +++++++++ .../versions/unversioned/tutorial/sharing.md | 110 ++++++++++++ .../versions/unversioned/tutorial/text.md | 88 ++++++++++ .../v36.0.0/get-started/create-a-new-app.md | 5 +- .../v36.0.0/introduction/why-not-expo.md | 4 +- docs/pages/versions/v36.0.0/sdk/sharing.md | 27 +++ .../pages/versions/v36.0.0/tutorial/button.md | 126 ++++++++++++++ .../versions/v36.0.0/tutorial/follow-up.md | 69 ++++++++ .../versions/v36.0.0/tutorial/image-picker.md | 159 ++++++++++++++++++ docs/pages/versions/v36.0.0/tutorial/image.md | 143 ++++++++++++++++ .../versions/v36.0.0/tutorial/planning.md | 17 ++ .../v36.0.0/tutorial/platform-differences.md | 79 +++++++++ .../versions/v36.0.0/tutorial/sharing.md | 110 ++++++++++++ docs/pages/versions/v36.0.0/tutorial/text.md | 88 ++++++++++ .../unversioned/tutorial/image-picker-log.js | 59 +++++++ .../unversioned/tutorial/image-picker-show.js | 78 +++++++++ .../unversioned/tutorial/sharing-simple.js | 91 ++++++++++ .../tutorial/sharing-web-workaround.js | 97 +++++++++++ .../v36.0.0/tutorial/image-picker-log.js | 59 +++++++ .../v36.0.0/tutorial/image-picker-show.js | 78 +++++++++ .../v36.0.0/tutorial/sharing-simple.js | 91 ++++++++++ .../tutorial/sharing-web-workaround.js | 97 +++++++++++ docs/static/images/favicon.ico | Bin 21822 -> 15406 bytes docs/static/images/header-logo.png | Bin 0 -> 14790 bytes docs/static/videos/tutorial/cli-install.mp4 | Bin 0 -> 537793 bytes docs/static/videos/tutorial/cli-logs.mp4 | Bin 0 -> 1166567 bytes docs/static/videos/tutorial/picker-show.mp4 | Bin 0 -> 516011 bytes .../static/videos/tutorial/sharing-native.mp4 | Bin 0 -> 890227 bytes .../tutorial/sharing-web-unavailable.mp4 | Bin 0 -> 645736 bytes docs/static/videos/tutorial/snack-install.mp4 | Bin 0 -> 528685 bytes 45 files changed, 2339 insertions(+), 25 deletions(-) create mode 100644 docs/components/plugins/Highlight.js create mode 100644 docs/pages/versions/unversioned/tutorial/button.md create mode 100644 docs/pages/versions/unversioned/tutorial/follow-up.md create mode 100644 docs/pages/versions/unversioned/tutorial/image-picker.md create mode 100644 docs/pages/versions/unversioned/tutorial/image.md create mode 100644 docs/pages/versions/unversioned/tutorial/planning.md create mode 100644 docs/pages/versions/unversioned/tutorial/platform-differences.md create mode 100644 docs/pages/versions/unversioned/tutorial/sharing.md create mode 100644 docs/pages/versions/unversioned/tutorial/text.md create mode 100644 docs/pages/versions/v36.0.0/tutorial/button.md create mode 100644 docs/pages/versions/v36.0.0/tutorial/follow-up.md create mode 100644 docs/pages/versions/v36.0.0/tutorial/image-picker.md create mode 100644 docs/pages/versions/v36.0.0/tutorial/image.md create mode 100644 docs/pages/versions/v36.0.0/tutorial/planning.md create mode 100644 docs/pages/versions/v36.0.0/tutorial/platform-differences.md create mode 100644 docs/pages/versions/v36.0.0/tutorial/sharing.md create mode 100644 docs/pages/versions/v36.0.0/tutorial/text.md create mode 100644 docs/static/examples/unversioned/tutorial/image-picker-log.js create mode 100644 docs/static/examples/unversioned/tutorial/image-picker-show.js create mode 100644 docs/static/examples/unversioned/tutorial/sharing-simple.js create mode 100644 docs/static/examples/unversioned/tutorial/sharing-web-workaround.js create mode 100644 docs/static/examples/v36.0.0/tutorial/image-picker-log.js create mode 100644 docs/static/examples/v36.0.0/tutorial/image-picker-show.js create mode 100644 docs/static/examples/v36.0.0/tutorial/sharing-simple.js create mode 100644 docs/static/examples/v36.0.0/tutorial/sharing-web-workaround.js create mode 100644 docs/static/images/header-logo.png create mode 100644 docs/static/videos/tutorial/cli-install.mp4 create mode 100644 docs/static/videos/tutorial/cli-logs.mp4 create mode 100644 docs/static/videos/tutorial/picker-show.mp4 create mode 100644 docs/static/videos/tutorial/sharing-native.mp4 create mode 100644 docs/static/videos/tutorial/sharing-web-unavailable.mp4 create mode 100644 docs/static/videos/tutorial/snack-install.mp4 diff --git a/docs/common/navigation-data.js b/docs/common/navigation-data.js index 584ff52dd77a8..0403324c7391d 100644 --- a/docs/common/navigation-data.js +++ b/docs/common/navigation-data.js @@ -15,6 +15,7 @@ const DIR_MAPPING = { sdk: 'Expo SDK', 'react-native': 'React Native', 'get-started': 'Get Started', + tutorial: 'Tutorial', 'next-steps': 'Next Steps', workflow: 'Fundamentals', distribution: 'Distributing Your App', diff --git a/docs/common/navigation.js b/docs/common/navigation.js index 1befbb1104696..25ec209cd4cc9 100644 --- a/docs/common/navigation.js +++ b/docs/common/navigation.js @@ -5,7 +5,7 @@ const packageVersion = require('../package.json').version; // - Each section is a top-level folder within the version directory // - The groups of sections are expressed only below, there is no representation of them in the filesystem const GROUPS = { - 'The Basics': ['Introduction', 'Get Started', 'Next Steps'], + 'The Basics': ['Introduction', 'Get Started', 'Tutorial', 'Next Steps'], 'Managed Workflow': ['Fundamentals', 'Guides', 'Distributing Your App', 'ExpoKit'], 'Bare Workflow': ['Essentials'], 'API Reference': ['Expo SDK', 'React Native'], @@ -28,6 +28,19 @@ const sections = [ name: 'Get Started', reference: ['Installation', 'Create a new app'], }, + { + name: 'Tutorial', + reference: [ + 'Introduction', + 'Styling text', + 'Adding an image', + 'Creating a button', + 'Picking an image', + 'Sharing the image', + 'Handling platform differences', + 'Learning more', + ], + }, { name: 'Next Steps', reference: ['Using the documentation', 'Join the community', 'Additional resources'], @@ -235,6 +248,7 @@ const sections = [ const ROOT = [ 'Introduction', 'Get Started', + 'Tutorial', 'Fundamentals', 'Guides', 'Distributing Your App', diff --git a/docs/components/base/code.js b/docs/components/base/code.js index b1290f74e0621..6204c9ca87984 100644 --- a/docs/components/base/code.js +++ b/docs/components/base/code.js @@ -1,4 +1,4 @@ -import styled, { keyframes, css } from 'react-emotion'; +import { css } from 'react-emotion'; import Prism from 'prismjs'; import * as React from 'react'; @@ -20,7 +20,8 @@ const STYLES_CODE_BLOCK = css` .code-annotation { transition: 200ms ease all; transition-property: text-shadow, opacity; - text-shadow: rgba(255,255,0,1) 0px 0px 10px, rgba(255,255,0,1) 0px 0px 10px, rgba(255,255,0,1) 0px 0px 10px, rgba(255,255,0,1) 0px 0px 10px; + text-shadow: rgba(255, 255, 0, 1) 0px 0px 10px, rgba(255, 255, 0, 1) 0px 0px 10px, + rgba(255, 255, 0, 1) 0px 0px 10px, rgba(255, 255, 0, 1) 0px 0px 10px; } .code-annotation:hover { @@ -129,4 +130,6 @@ export class Code extends React.Component { } } -export const InlineCode = ({ children }) => {children}; +export const InlineCode = ({ children }) => ( + {children} +); diff --git a/docs/components/icons/BrandLogo.js b/docs/components/icons/BrandLogo.js index 15a85a03360c5..d895fcfb61cdf 100644 --- a/docs/components/icons/BrandLogo.js +++ b/docs/components/icons/BrandLogo.js @@ -3,13 +3,6 @@ import * as React from 'react'; // TODO(jim): Figure out why this was wrapped in a span. export default () => ( - - Expo - - - - - - + Expo ); diff --git a/docs/components/plugins/Highlight.js b/docs/components/plugins/Highlight.js new file mode 100644 index 0000000000000..83b20cca290d6 --- /dev/null +++ b/docs/components/plugins/Highlight.js @@ -0,0 +1,11 @@ +import React from 'react'; +import { css } from 'react-emotion'; + +const STYLES_HIGHLIGHT = css` + text-shadow: rgba(255, 255, 0, 1) 0px 0px 10px, rgba(255, 255, 0, 1) 0px 0px 10px, + rgba(255, 255, 0, 1) 0px 0px 10px, rgba(255, 255, 0, 1) 0px 0px 10px; +`; + +const Highlight = ({ children }) => {children}; + +export default Highlight; diff --git a/docs/components/plugins/SnackInline.js b/docs/components/plugins/SnackInline.js index 270a8193b5fd8..2218062ecf474 100644 --- a/docs/components/plugins/SnackInline.js +++ b/docs/components/plugins/SnackInline.js @@ -60,7 +60,7 @@ export default class SnackInline extends React.Component { let templateId = this.props.templateId; let baseUrl = - `https://snack.expo.io?platform=${DEFAULT_PLATFORM}&name=` + + `https://snack.expo.io?platform=${this.props.defaultPlatform || DEFAULT_PLATFORM}&name=` + encodeURIComponent(label) + `&sdkVersion=${this._getSnackSdkVersion()}` + `&dependencies=${encodeURIComponent(this._getDependencies())}`; @@ -99,8 +99,12 @@ export default class SnackInline extends React.Component {

{/* TODO: this should be a POST request, need to change Snack to support it though */} -
- + + diff --git a/docs/global-styles/tippy.js b/docs/global-styles/tippy.js index cdc9c4c297750..259cf8bcef1c4 100644 --- a/docs/global-styles/tippy.js +++ b/docs/global-styles/tippy.js @@ -21,4 +21,8 @@ export const globalTippy = ` color: ${Constants.colors.white}; font-family: ${Constants.fonts.book}; } + + .tippy-content a { + color: #eee; + } `; diff --git a/docs/pages/versions/unversioned/get-started/create-a-new-app.md b/docs/pages/versions/unversioned/get-started/create-a-new-app.md index 2434ab44af550..90983e2ef8ac5 100644 --- a/docs/pages/versions/unversioned/get-started/create-a-new-app.md +++ b/docs/pages/versions/unversioned/get-started/create-a-new-app.md @@ -63,6 +63,7 @@ The Expo client is configured by default to automatically reload the app wheneve ## Up next -You are now in a good place to start digging in to the rest of the documentation! +Depending on your experience level with tools similar to Expo, you may now in a good place to start digging in to the rest of the documentation! -[Continue to "Using the documentation"](../../next-steps/using-the-documentation/) for suggestions on how to continue your learning journey. \ No newline at end of file +- **If you are new to React Native**, we suggest [following a tutorial](../../tutorial/planning/) before proceeding to the rest of the documentation. +- **If you have used React Native before**, [continue to "Using the documentation"](../../next-steps/using-the-documentation/) for suggestions on how to continue your learning journey. \ No newline at end of file diff --git a/docs/pages/versions/unversioned/introduction/why-not-expo.md b/docs/pages/versions/unversioned/introduction/why-not-expo.md index c739ee007752c..687cad40ae6bb 100644 --- a/docs/pages/versions/unversioned/introduction/why-not-expo.md +++ b/docs/pages/versions/unversioned/introduction/why-not-expo.md @@ -3,9 +3,7 @@ title: Limitations sidebar_title: Limitations --- -> *Your success will be limited if you don't know the limitations of your tools.* -> -> — *Confucius (but not really)* +Your success will be limited if you don't know the limitations of your tools. A good software engineer strives to understand the tradeoffs in the decisions she makes. ## Limitations of the managed workflow diff --git a/docs/pages/versions/unversioned/sdk/sharing.md b/docs/pages/versions/unversioned/sdk/sharing.md index 9ba313ceb48a3..044fc52f9e195 100644 --- a/docs/pages/versions/unversioned/sdk/sharing.md +++ b/docs/pages/versions/unversioned/sdk/sharing.md @@ -15,6 +15,18 @@ import Video from '../../../../components/plugins/Video' | -------------- | ---------------- | ---------- | ------------- | --- | | ✅ | ✅ | ✅ | ✅ | ✅ | +
+ +> 🚨 **Web browser support**: expo-sharing for web is built on top of the Web Share API, which still has [very limited browser support](https://caniuse.com/#feat=web-share). Be sure to check that the API can be used before calling it by using `Sharing.isAvailableAsync()`. + +
+ +> 💡 **HTTPS required on web**: The Web Share API is only available on web when the page is served over https. Run your app with `expo start --https` to enable it. + +
+ +> ⚠️ **No local file sharing on web**: Sharing local files by URI works on iOS and Android, but not on web. You cannot share local files on web by URI — you will need to upload them somewhere and share that URI. + ## Installation For [managed](../../introduction/managed-vs-bare/#managed-workflow) apps, you'll need to run `expo install expo-sharing`. To use it in a [bare](../../introduction/managed-vs-bare/#bare-workflow) React Native app, follow its [installation instructions](https://github.com/expo/expo/tree/master/packages/expo-sharing). @@ -25,6 +37,21 @@ For [managed](../../introduction/managed-vs-bare/#managed-workflow) apps, you'll import * as Sharing from 'expo-sharing'; ``` +**[Methods](#methods)** + +- [`Sharing.isAvailableAsync()`](#sharingisavailableasync) +- [`Sharing.shareAsync(url, options)`](#sharingshareasyncurl-options) + +## Methods + +### `Sharing.isAvailableAsync()` + +Determine if the sharing API can be used in this app. + +#### Returns + +A promise that resolves to `true` if the sharing API can be used, and `false` otherwise. + ### `Sharing.shareAsync(url, options)` Opens action sheet to share file to different applications which can handle this type of file. diff --git a/docs/pages/versions/unversioned/tutorial/button.md b/docs/pages/versions/unversioned/tutorial/button.md new file mode 100644 index 0000000000000..c402eba50bc7d --- /dev/null +++ b/docs/pages/versions/unversioned/tutorial/button.md @@ -0,0 +1,126 @@ +--- +title: Creating a button +--- + +import SnackInline from '~/components/plugins/SnackInline'; + +We're going to create our own custom button using the `TouchableOpacity` component and some styled `Text` inside of it. + + + +```jsx +import React from 'react'; +import { Image, StyleSheet, Text, /* @info Add the TouchableOpacity component to your list of imports */ TouchableOpacity,/* @end */ View } from 'react-native'; + +export default function App() { + return ( + + + + To share a photo from your phone with a friend, just press the button below! + + + /* @info onPress takes a function that should be called when the button is pressed */ + alert('Hello, world!')} + style={{ backgroundColor: 'blue' }}> + Pick a photo + /* @end */ + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: '#fff', + alignItems: 'center', + justifyContent: 'center', + }, + logo: { + width: 305, + height: 159, + marginBottom: 20, + }, + instructions: { + color: '#888', + fontSize: 18, + marginHorizontal: 15, + marginBottom: 10, + }, +}); +``` + + + +
+ +Give it a try! Notice that when you press on the button it fades a little bit — this is because our background is white and the button becomes slightly translucent. When you release, you will see an alert dialog. You can show this dialog any time in your apps by calling the `alert` function. + +## Making it easier to press the button + +When you are using your finger to tap on a button, you don't want to have to hold your breathe and carefully aim your finger — the button should be big enough that it's easy to press for people with varying levels of dexterity and an assortment of finger sizes, from baby right up to big boy. + +We can make our button bigger by adding some `padding` to our `TouchableOpacity`. We've already seen `width`, `height`, and various `margin` properties on our styles, `padding` is in the same family as those. They all tell React Native's layout system how big components should be and how they should be positioned relative to other components. The layout system is called [flexbox](https://facebook.github.io/react-native/docs/flexbox), but don't worry about that for now, in this tutorial we will tell you exactly what styles to use and you can learn about flexbox later. + + + +```jsx +import React from 'react'; +import { Image, StyleSheet, Text, TouchableOpacity, View } from 'react-native'; + +export default function App() { + return ( + + + + To share a photo from your phone with a friend, just press the button below! + + + alert('Hello, world!')} /* @info We moved our our style down to the StyleSheet, keep scrolling! */ style={styles.button}/* @end */> + Pick a photo + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: '#fff', + alignItems: 'center', + justifyContent: 'center', + }, + logo: { + width: 305, + height: 159, + marginBottom: 20, + }, + instructions: { + color: '#888', + fontSize: 18, + marginHorizontal: 15, + marginBottom: 10, + }, + /* @info Our button, now with some padding. Rounded corners are a bonus thanks to borderRadius. */ + button: { + backgroundColor: "blue", + padding: 20, + borderRadius: 5, + }, + buttonText: { + fontSize: 20, + color: '#fff', + }, /* @end */ + +}); +``` + + + +
+ +> 📜 Yikes, these code snippets are getting long. For the rest of the tutorial we'll show only relevant code here, and you can click through to Snack to see the full code. + +- We have a button! We can now make that button do what we want it to do: open an "image picker" - a screen with a gallery of images on your device. [Continue to the next section](../../tutorial/image-picker/). \ No newline at end of file diff --git a/docs/pages/versions/unversioned/tutorial/follow-up.md b/docs/pages/versions/unversioned/tutorial/follow-up.md new file mode 100644 index 0000000000000..dea9a71599430 --- /dev/null +++ b/docs/pages/versions/unversioned/tutorial/follow-up.md @@ -0,0 +1,69 @@ +--- +title: Learning more +--- + +We tried to set expectations early on that this tutorial is more focused towards *doing* than *explaining*. Now that the doing is done, explanations are in order. + +
+ +# Filling in the gaps on concepts that we applied + +## React + +We used React components and APIs here with little explaination. Having a solid understanding of React is essential to using Expo to build your app. We recommend reading the [Main Concepts section](https://reactjs.org/docs/hello-world.html) and the [Hooks section](https://reactjs.org/docs/hooks-intro.html) of the React documentation. + + + +### How to verify your Learning + +- You understand how to use `React.useState`, that it is a *hook*, and what the equivalent for React *class* components is. +- Add a new button to clear the selected image state. +- You can create a reusable `Button` component to clean up duplication of `TouchableOpacity` / `Text`. + +## async/await, import, and other JavaScript features + +Read about [Modern JavaScript on React Native Express](http://www.reactnativeexpress.com/modern_javascript). + +### How to verify your Learning + +- You can move part of the code from our app into a separate file, export it, and import it successfully into App.js. + +## View and Text styles + +Read through the [View API reference](https://facebook.github.io/react-native/docs/view) and [Text API reference](https://facebook.github.io/react-native/docs/text) in the React Native documentation. + +### How to verify your Learning + +- Remove all of the styles from your app and attempt to re-create them from scratch, only referring to the View and Text API reference pages when needed. + +## Flexbox + +This is the way you position and size the components on your screen. Learn more about it in [Height & Width](https://facebook.github.io/react-native/docs/height-and-width) and [Layout with Flexbox](https://facebook.github.io/react-native/docs/flexbox) in the React Native documentation. + +### How to verify your Learning + +- Remove the logo image and re-build it using just `View`, `Text`. Use the "sunrise over mountains" 🌄 emoji where needed. + +
+ +# Topics that we didn't cover and you will soon care about + +## Deployment + +How can you take what you have built and turn it into an app that you ship to the App Store and Play Store. Learn more about [distributing your app to stores](../../distribution/introduction/) and [deploying websites](../../guides/deploying-websites/). + +## Configuration with app.json + +You will want to configure your app icon, splash screen, and other things that are done in `app.json` rather than in your app code. Learn more about [app icons](../../guides/splash-screens/) and [splash screens](../../guides/app-icons/). + +## Navigation + +Most apps have multiple screens, we just have one here! Learn more about how to add navigation to your app by following the [Fundamentals guide](https://reactnavigation.org/docs/en/getting-started.html) in the React Navigation documentation. + +## Debugging + +Sometimes things go wrong, and when they do you need to use debugging tools to figure out where your code is having trouble. [Read more about debugging](../../workflow/debugging/). + +## Using the documentation + +[Read more about how you can navigate this documentation and use it effectively](../../next-steps/using-the-documentation/). \ No newline at end of file diff --git a/docs/pages/versions/unversioned/tutorial/image-picker.md b/docs/pages/versions/unversioned/tutorial/image-picker.md new file mode 100644 index 0000000000000..cb8a29ba32bbe --- /dev/null +++ b/docs/pages/versions/unversioned/tutorial/image-picker.md @@ -0,0 +1,159 @@ +--- +title: Picking an image +--- + +import SnackInline from '~/components/plugins/SnackInline'; +import Video from '../../../../components/plugins/Video' + +So far we have been using code from React and React Native in our app. React gives us a nice way to build components and React Native gives us pre-built components that work on iOS, Android, and web — like `View`, `Text`, `TouchableOpacity`. React Native does *not* provide us with an image picker. For this, we can use an Expo library called [expo-image-picker](../../sdk/imagepicker/): + +> **`expo-image-picker`** provides access to the system's UI for selecting images and videos from the phone's library or taking a photo with the camera. + + + + +## Installing expo-image-picker + +To use expo-image-picker in our project, we first need to install it. + +In your project directory, run `expo install expo-image-picker`. This will tell npm (or yarn) to install the a version of the `expo-image-picker` library that is compatible with your project. That's it! + +
+ +

Want to learn more about why we can't use expo-sharing in Chrome?

+ +

+ +Sharing didn't work here because the desktop Chrome browser doesn't yet implement the [Web Share API](https://web.dev/web-share/). *"But wait,"* you say, *"aren't we using expo-sharing, not the Web Share API?"* You can you can think of the Expo SDK libraries as translators for different platforms. They speak the language of Expo and turn it into the language of iOS, Android, and web. It isn't always possible to translate from Expo's language to the platform that you're working with. In other words, if the platform doesn't implement a feature, Expo can't tell it to invoke that feature. In some cases Expo can attempt to [polyfill](https://en.wikipedia.org/wiki/Polyfill_(programming)) the feature for you, but this isn't always possible. Invoking your operating system's built-in share dialog to share content with other applications needs to be implemented by the platform itself — Chrome in this case. + +

+
+ +## Working with what we have available + +In the next section we are going to look at how we can handle this and another import platform difference. [Continue to Handling platform differences](../../tutorial/platform-differences/). + + + + + \ No newline at end of file diff --git a/docs/pages/versions/unversioned/tutorial/text.md b/docs/pages/versions/unversioned/tutorial/text.md new file mode 100644 index 0000000000000..6bf21cbc83706 --- /dev/null +++ b/docs/pages/versions/unversioned/tutorial/text.md @@ -0,0 +1,88 @@ +--- +title: Styling text +--- + +import SnackInline from '~/components/plugins/SnackInline'; +import Highlight from '~/components/plugins/Highlight'; + +> 👶🏻 We believe in "learning by doing" and so this tutorial emphasizes **doing** over *explaining*. If you find yourself typing code that you do not understand, do not worry — we will link to you to appropriate resources to help you get a deeper understanding at the end of the tutorial. + +Let's change the text that's currently instructing us to "Open up App.js to start working on your app!" to instead instruct our users how to use the app. The app doesn't yet do anything but we can pretend that it does, such is the way of programming. + +Change your code according to the following example. Throughout the tutorial, any important code or code that has changed between examples will be highlighted in yellow. You can hover on the highlights (on desktop) or tap them (on mobile) to see more context on the change. + + + +```jsx +import React from 'react'; +import { StyleSheet, Text, View } from 'react-native'; + +export default function App() { + return ( + + /* @info This used to say "Open up App.js to start working on your app!" and now it is slightly more useful. */ + To share a photo from your phone with a friend, just press the button below! + /* @end */ + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: '#fff', + alignItems: 'center', + justifyContent: 'center', + }, +}); +``` + + + + +
+ +> 😳 **Wait, what is this "Try this example on Snack" button!?** +> +> Snack is a web-based editor that works similar to a managed Expo project. It's a great way to share code snippets with people and try things out without needing to get a project running on your own computer with `expo-cli`. Go ahead, press the button. You will see the above code running in it. Switch between iOS, Android, or web. Open it on your device in the Expo client by pressing the "Run" button. + +## Adding style + +Our text is black and small. We should change the color because, according to some folks, [you should never use pure black for text or backgrounds](https://uxmovement.com/content/why-you-should-never-use-pure-black-for-text-or-backgrounds/). We'll also increase the font size to make it easier to read. + + + +```jsx +import React from 'react'; +import { StyleSheet, Text, View } from 'react-native'; + +export default function App() { + return ( + + /* @info Set the style property with color and fontSize. There are many other styles available! Look at them in the
React Native Text API reference sometime after you're done with this tutorial. */ /* @end */ + + To share a photo from your phone with a friend, just press the button below! + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: '#fff', + alignItems: 'center', + justifyContent: 'center', + }, +}); +``` + + + +
+ +> 🎨 **Help, I'm not familiar with any color by the name "#888"!** `#888` is equal parts red, green, and blue, which creates a nice readable grey. React Native uses the same color format as the web, so it supports hex triplets (this is what `#888` is), `rgba`, `hsl`, and a set of named colors like `red`, `green`, `blue`, and, uh, `peru` and `papayawhip`. [Read more about colors in React Native here](https://facebook.github.io/react-native/docs/colors). + +Good, that looks better! If you want to learn more about the other styles available on the Text component, [you can read more here](https://facebook.github.io/react-native/docs/text#style). + +Next we're going to look at adding the logo, [let's continue to looking at the Image component for that](../../tutorial/image/). \ No newline at end of file diff --git a/docs/pages/versions/v36.0.0/get-started/create-a-new-app.md b/docs/pages/versions/v36.0.0/get-started/create-a-new-app.md index 2434ab44af550..68bf30eb71e2c 100644 --- a/docs/pages/versions/v36.0.0/get-started/create-a-new-app.md +++ b/docs/pages/versions/v36.0.0/get-started/create-a-new-app.md @@ -63,6 +63,7 @@ The Expo client is configured by default to automatically reload the app wheneve ## Up next -You are now in a good place to start digging in to the rest of the documentation! +Depending on your experience level with tools similar to Expo, you may now in a good place to start digging in to the rest of the documentation! -[Continue to "Using the documentation"](../../next-steps/using-the-documentation/) for suggestions on how to continue your learning journey. \ No newline at end of file +- **If you are new to React Native**, we suggest [following a tutorial](../../tutorial/planning/) before proceeding to the rest of the documentation. +- **If you have used React Native before**, [continue to "Using the documentation"](../../next-steps/using-the-documentation/) for suggestions on how to continue your learning journey. diff --git a/docs/pages/versions/v36.0.0/introduction/why-not-expo.md b/docs/pages/versions/v36.0.0/introduction/why-not-expo.md index c739ee007752c..687cad40ae6bb 100644 --- a/docs/pages/versions/v36.0.0/introduction/why-not-expo.md +++ b/docs/pages/versions/v36.0.0/introduction/why-not-expo.md @@ -3,9 +3,7 @@ title: Limitations sidebar_title: Limitations --- -> *Your success will be limited if you don't know the limitations of your tools.* -> -> — *Confucius (but not really)* +Your success will be limited if you don't know the limitations of your tools. A good software engineer strives to understand the tradeoffs in the decisions she makes. ## Limitations of the managed workflow diff --git a/docs/pages/versions/v36.0.0/sdk/sharing.md b/docs/pages/versions/v36.0.0/sdk/sharing.md index 9ba313ceb48a3..044fc52f9e195 100644 --- a/docs/pages/versions/v36.0.0/sdk/sharing.md +++ b/docs/pages/versions/v36.0.0/sdk/sharing.md @@ -15,6 +15,18 @@ import Video from '../../../../components/plugins/Video' | -------------- | ---------------- | ---------- | ------------- | --- | | ✅ | ✅ | ✅ | ✅ | ✅ | +
+ +> 🚨 **Web browser support**: expo-sharing for web is built on top of the Web Share API, which still has [very limited browser support](https://caniuse.com/#feat=web-share). Be sure to check that the API can be used before calling it by using `Sharing.isAvailableAsync()`. + +
+ +> 💡 **HTTPS required on web**: The Web Share API is only available on web when the page is served over https. Run your app with `expo start --https` to enable it. + +
+ +> ⚠️ **No local file sharing on web**: Sharing local files by URI works on iOS and Android, but not on web. You cannot share local files on web by URI — you will need to upload them somewhere and share that URI. + ## Installation For [managed](../../introduction/managed-vs-bare/#managed-workflow) apps, you'll need to run `expo install expo-sharing`. To use it in a [bare](../../introduction/managed-vs-bare/#bare-workflow) React Native app, follow its [installation instructions](https://github.com/expo/expo/tree/master/packages/expo-sharing). @@ -25,6 +37,21 @@ For [managed](../../introduction/managed-vs-bare/#managed-workflow) apps, you'll import * as Sharing from 'expo-sharing'; ``` +**[Methods](#methods)** + +- [`Sharing.isAvailableAsync()`](#sharingisavailableasync) +- [`Sharing.shareAsync(url, options)`](#sharingshareasyncurl-options) + +## Methods + +### `Sharing.isAvailableAsync()` + +Determine if the sharing API can be used in this app. + +#### Returns + +A promise that resolves to `true` if the sharing API can be used, and `false` otherwise. + ### `Sharing.shareAsync(url, options)` Opens action sheet to share file to different applications which can handle this type of file. diff --git a/docs/pages/versions/v36.0.0/tutorial/button.md b/docs/pages/versions/v36.0.0/tutorial/button.md new file mode 100644 index 0000000000000..c402eba50bc7d --- /dev/null +++ b/docs/pages/versions/v36.0.0/tutorial/button.md @@ -0,0 +1,126 @@ +--- +title: Creating a button +--- + +import SnackInline from '~/components/plugins/SnackInline'; + +We're going to create our own custom button using the `TouchableOpacity` component and some styled `Text` inside of it. + + + +```jsx +import React from 'react'; +import { Image, StyleSheet, Text, /* @info Add the TouchableOpacity component to your list of imports */ TouchableOpacity,/* @end */ View } from 'react-native'; + +export default function App() { + return ( + + + + To share a photo from your phone with a friend, just press the button below! + + + /* @info onPress takes a function that should be called when the button is pressed */ + alert('Hello, world!')} + style={{ backgroundColor: 'blue' }}> + Pick a photo + /* @end */ + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: '#fff', + alignItems: 'center', + justifyContent: 'center', + }, + logo: { + width: 305, + height: 159, + marginBottom: 20, + }, + instructions: { + color: '#888', + fontSize: 18, + marginHorizontal: 15, + marginBottom: 10, + }, +}); +``` + + + +
+ +Give it a try! Notice that when you press on the button it fades a little bit — this is because our background is white and the button becomes slightly translucent. When you release, you will see an alert dialog. You can show this dialog any time in your apps by calling the `alert` function. + +## Making it easier to press the button + +When you are using your finger to tap on a button, you don't want to have to hold your breathe and carefully aim your finger — the button should be big enough that it's easy to press for people with varying levels of dexterity and an assortment of finger sizes, from baby right up to big boy. + +We can make our button bigger by adding some `padding` to our `TouchableOpacity`. We've already seen `width`, `height`, and various `margin` properties on our styles, `padding` is in the same family as those. They all tell React Native's layout system how big components should be and how they should be positioned relative to other components. The layout system is called [flexbox](https://facebook.github.io/react-native/docs/flexbox), but don't worry about that for now, in this tutorial we will tell you exactly what styles to use and you can learn about flexbox later. + + + +```jsx +import React from 'react'; +import { Image, StyleSheet, Text, TouchableOpacity, View } from 'react-native'; + +export default function App() { + return ( + + + + To share a photo from your phone with a friend, just press the button below! + + + alert('Hello, world!')} /* @info We moved our our style down to the StyleSheet, keep scrolling! */ style={styles.button}/* @end */> + Pick a photo + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: '#fff', + alignItems: 'center', + justifyContent: 'center', + }, + logo: { + width: 305, + height: 159, + marginBottom: 20, + }, + instructions: { + color: '#888', + fontSize: 18, + marginHorizontal: 15, + marginBottom: 10, + }, + /* @info Our button, now with some padding. Rounded corners are a bonus thanks to borderRadius. */ + button: { + backgroundColor: "blue", + padding: 20, + borderRadius: 5, + }, + buttonText: { + fontSize: 20, + color: '#fff', + }, /* @end */ + +}); +``` + + + +
+ +> 📜 Yikes, these code snippets are getting long. For the rest of the tutorial we'll show only relevant code here, and you can click through to Snack to see the full code. + +- We have a button! We can now make that button do what we want it to do: open an "image picker" - a screen with a gallery of images on your device. [Continue to the next section](../../tutorial/image-picker/). \ No newline at end of file diff --git a/docs/pages/versions/v36.0.0/tutorial/follow-up.md b/docs/pages/versions/v36.0.0/tutorial/follow-up.md new file mode 100644 index 0000000000000..dea9a71599430 --- /dev/null +++ b/docs/pages/versions/v36.0.0/tutorial/follow-up.md @@ -0,0 +1,69 @@ +--- +title: Learning more +--- + +We tried to set expectations early on that this tutorial is more focused towards *doing* than *explaining*. Now that the doing is done, explanations are in order. + +
+ +# Filling in the gaps on concepts that we applied + +## React + +We used React components and APIs here with little explaination. Having a solid understanding of React is essential to using Expo to build your app. We recommend reading the [Main Concepts section](https://reactjs.org/docs/hello-world.html) and the [Hooks section](https://reactjs.org/docs/hooks-intro.html) of the React documentation. + + + +### How to verify your Learning + +- You understand how to use `React.useState`, that it is a *hook*, and what the equivalent for React *class* components is. +- Add a new button to clear the selected image state. +- You can create a reusable `Button` component to clean up duplication of `TouchableOpacity` / `Text`. + +## async/await, import, and other JavaScript features + +Read about [Modern JavaScript on React Native Express](http://www.reactnativeexpress.com/modern_javascript). + +### How to verify your Learning + +- You can move part of the code from our app into a separate file, export it, and import it successfully into App.js. + +## View and Text styles + +Read through the [View API reference](https://facebook.github.io/react-native/docs/view) and [Text API reference](https://facebook.github.io/react-native/docs/text) in the React Native documentation. + +### How to verify your Learning + +- Remove all of the styles from your app and attempt to re-create them from scratch, only referring to the View and Text API reference pages when needed. + +## Flexbox + +This is the way you position and size the components on your screen. Learn more about it in [Height & Width](https://facebook.github.io/react-native/docs/height-and-width) and [Layout with Flexbox](https://facebook.github.io/react-native/docs/flexbox) in the React Native documentation. + +### How to verify your Learning + +- Remove the logo image and re-build it using just `View`, `Text`. Use the "sunrise over mountains" 🌄 emoji where needed. + +
+ +# Topics that we didn't cover and you will soon care about + +## Deployment + +How can you take what you have built and turn it into an app that you ship to the App Store and Play Store. Learn more about [distributing your app to stores](../../distribution/introduction/) and [deploying websites](../../guides/deploying-websites/). + +## Configuration with app.json + +You will want to configure your app icon, splash screen, and other things that are done in `app.json` rather than in your app code. Learn more about [app icons](../../guides/splash-screens/) and [splash screens](../../guides/app-icons/). + +## Navigation + +Most apps have multiple screens, we just have one here! Learn more about how to add navigation to your app by following the [Fundamentals guide](https://reactnavigation.org/docs/en/getting-started.html) in the React Navigation documentation. + +## Debugging + +Sometimes things go wrong, and when they do you need to use debugging tools to figure out where your code is having trouble. [Read more about debugging](../../workflow/debugging/). + +## Using the documentation + +[Read more about how you can navigate this documentation and use it effectively](../../next-steps/using-the-documentation/). \ No newline at end of file diff --git a/docs/pages/versions/v36.0.0/tutorial/image-picker.md b/docs/pages/versions/v36.0.0/tutorial/image-picker.md new file mode 100644 index 0000000000000..cb8a29ba32bbe --- /dev/null +++ b/docs/pages/versions/v36.0.0/tutorial/image-picker.md @@ -0,0 +1,159 @@ +--- +title: Picking an image +--- + +import SnackInline from '~/components/plugins/SnackInline'; +import Video from '../../../../components/plugins/Video' + +So far we have been using code from React and React Native in our app. React gives us a nice way to build components and React Native gives us pre-built components that work on iOS, Android, and web — like `View`, `Text`, `TouchableOpacity`. React Native does *not* provide us with an image picker. For this, we can use an Expo library called [expo-image-picker](../../sdk/imagepicker/): + +> **`expo-image-picker`** provides access to the system's UI for selecting images and videos from the phone's library or taking a photo with the camera. + + + + +## Installing expo-image-picker + +To use expo-image-picker in our project, we first need to install it. + +In your project directory, run `expo install expo-image-picker`. This will tell npm (or yarn) to install the a version of the `expo-image-picker` library that is compatible with your project. That's it! + +