-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[@unimodules/react-native-adapter] Use Proxy to throw UnavailabilityErrors #6881
Conversation
… it (#6882) # Why While performance testing #6881 I bumped into a strange performance difference between calling ```tsx import * as Cellular from 'expo-cellular'; await Cellular.getCellularGenerationAsync(); ``` and ```tsx import { NativeModulesProxy } from '@unimodules/core'; await NativeModulesProxy.ExpoCellular.getCellularGenerationAsync(); ``` where the latter was noticeably quicker (10%, 4188 ms vs 3764 ms). After sharing my results with the team, @wkozyra95 has come up with an explanation — calling `return await promise` requires an extra event loop round comparing with `return promise`. In situations where we don't wrap `return await` with a try-catch it should be safe to replace `return await` with `return`. # How - replaced `return await` with `return`, - replaced `throw new Error` with `Promise.reject(new Error` not to throw errors outside of a Promise, - removed `async` annotation from the function. # Test Plan Calling `await Application.getInstallReferrerAsync()` in a for loop 5000 times in `bare-expo` project resulted took: - 78.5 s, **68.6 s**, 70.8 s, 70.7 s — **mean 72.1 s** whereas on `master` the same benchmark took - 75.5 s, **75.0 s**, 76.4 s, 75.6 s — **mean 75.6 s** On average this PR should make calls to native about 4.5% faster. Once this PR is accepted I will go through all other places where we `return await` and fix this issue there.
272a0a4
to
6f36b16
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC Hermes has some issues with Proxies (that might have been fixed, though).
packages/@unimodules/react-native-adapter/src/NativeModulesProxy.ts
Outdated
Show resolved
Hide resolved
packages/@unimodules/react-native-adapter/src/NativeModulesProxy.ts
Outdated
Show resolved
Hide resolved
packages/@unimodules/react-native-adapter/src/NativeModulesProxy.ts
Outdated
Show resolved
Hide resolved
6f36b16
to
e7ae829
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 'property' in object
checks make me think this needs more work. It needs to be really obvious when standard JavaScript (object.property
) doesn't work, or ideally standard JS would just work everywhere. Generally when libraries become more mature they remove magic and dynamic features and move towards plain, static code that requires less context to understand. Proxies add magic and I think this is one of the (very many) scenarios in which they might not be right.
I agree. I consider this PR more of a "wouldn't it be good if" than a serious change proposal. Maybe a prerequisite for this kind of change would be introducing the aforementioned {
// getConstants returns a plain object
getConstants: () => { constantName: "constantValue", ... },
// existing native methods return what they already are
existingNativeMethodAsync: () => NativeProxy.callMethod(...),
anotherExistingNativeMethodAsync: () => NativeProxy.callMethod(...),
// since constants only belong to getConstants,
// any other `get` must expect to receive an exported method
[default]: () => { throw new UnavailabilityError() }
} Even though this still would have to use |
Yeah. I think getConstants and Turbomodules helps a lot since all native implementations have to implement the same interface. There are no more “if (Module.method)” checks. |
… it (#6882) # Why While performance testing #6881 I bumped into a strange performance difference between calling ```tsx import * as Cellular from 'expo-cellular'; await Cellular.getCellularGenerationAsync(); ``` and ```tsx import { NativeModulesProxy } from '@unimodules/core'; await NativeModulesProxy.ExpoCellular.getCellularGenerationAsync(); ``` where the latter was noticeably quicker (10%, 4188 ms vs 3764 ms). After sharing my results with the team, @wkozyra95 has come up with an explanation — calling `return await promise` requires an extra event loop round comparing with `return promise`. In situations where we don't wrap `return await` with a try-catch it should be safe to replace `return await` with `return`. # How - replaced `return await` with `return`, - replaced `throw new Error` with `Promise.reject(new Error` not to throw errors outside of a Promise, - removed `async` annotation from the function. # Test Plan Calling `await Application.getInstallReferrerAsync()` in a for loop 5000 times in `bare-expo` project resulted took: - 78.5 s, **68.6 s**, 70.8 s, 70.7 s — **mean 72.1 s** whereas on `master` the same benchmark took - 75.5 s, **75.0 s**, 76.4 s, 75.6 s — **mean 75.6 s** On average this PR should make calls to native about 4.5% faster. Once this PR is accepted I will go through all other places where we `return await` and fix this issue there.
…acts (#6694) * Prevent invalid dates from throwing an error on Android fix #4757 * parse as many dates as possible * Added raw dates * [ios] Reinstall pods * [payments-stripe] make index.js TS and move to src/ (#6686) * [payments-stripe] move index to src/ * update docs * Fix typo in react-native appstate.md (#6691) * Fix typo * unversioned Co-authored-by: Charlie Cruzan <35579283+cruzach@users.noreply.github.com> * Update ErrorRecover import for SDK 36 (#6624) import * as ErrorRecovery from 'expo-error-recovery' * update import for SDK 36 (#6623) import * as ErrorRecovery from 'expo-error-recovery' * [contributing] Update instructions to attempt to be more clear (#6702) * [bare-expo][test-suite] Link to contributing from bare-expo/test-suite READMEs * Install next adapter as a dev dep (#6703) * Fix build script using react-native-cli (#6706) * Use community version of unimodules linking on ios (#6707) * [linking] don't add extra slash to expoPrefix (#6688) * [linking] dont add extra slash to expoPrefix * fix host for published projects, fix/add tests * change test to localhost address * make host null in client * remove string interplation * publish expo-payments-stripe 8.0.1 * Use expanded pods to match bare template (#6708) * Added community linking to bare-expo android (#6705) * [store-review] fix undef error in bare (#6713) * [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 * [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] removed duplicate "is" in CONTRIBUTING.md (#6728) * @cruzach/error recov (#6731) * [docs] errorRecovery supported in bare * v36 * [docs] clarify FB app id directions (#6732) * [docs] clarify FB app id directions * v36 * typo * typo * [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> * Create using-preact.md (#6718) * [image-picker][sharing] Small fixes while working on tutorial (#6757) * [sharing] Fix build * [bare] Enable singleton modules creation (#6751) This is a reapplication of #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. * [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. * [@unimodules/react-native-adapter] Export ProxyNativeModule (#6759) # 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 ✅ * [expo-notifications] Device push token fetching module (#6577) # 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`](0bd4687#diff-66b6995155cd1e190f53b012f5c2a857R43-R44) to get away with it. ### Notable changes to native implementation - we use singleton module for listening to token changes [android](69ee9ef#diff-5f9ef5ef7358f7a9c8cc386d42ee934f), [ios](0aa2b66#diff-f8332f28b28ad9a24e0af0cb435876c7) - on Android there's a service subclassing `FirebaseMessagingService` to which the singleton above subscribes [link](69ee9ef#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](82e54ae) # 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](puppeteer/puppeteer#3279)) - push notifications sent to device push tokens are received on **all three platforms** * [templates] make typescript templates strict by default (#6755) * [docs] improvements to push notification guide (#6766) * [docs] how to clear certs, backport android improvements (#6768) * [changelog] Add note about Linking's standards-compliant parsing behavior to the changelog Adding a note about #6497 (comment) 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. * [linking] decode query params (#6774) * [linking] decode query params * move code to beforeEach and afterEach * [docs] First pass at tutorial (#6769) * [docs] Use js rather than jsx for syntax highlighting * [docs] Clarify the documentation to highlight that BackgroundFetch is broken on devices (#6767) * Clarify the documentation to highlight that BackgroundFetch is broken on devices * Add a known issues section instead * small wording changes * v36 Co-authored-by: Charlie Cruzan <35579283+cruzach@users.noreply.github.com> * [app-auth] add try-catch in authWithConfiguration, set responseType on builder * [expo-contacts]: fix date decodeDates's handling of years (#6744) There was a copy-paste error there setting the day again instead of the year. * [linking] makeUrl should follow the URI spec (#6781) * always prepend path with slash * add tests * make docs better * Update CHANGELOG.md * [docs] Add missing async keyword * [expo-notifications] Post-review fixes (#6779) # Why [A new review](#6577 (review)) came in. # How Applied all the suggestions. # Test Plan Code compiled. * [bare-expo] Update app.json as for a separate bare-expo project (#6734) # Why This will let us treat `@[username]/bare-expo` as a proper experience, eg. assign push notifications keys to it. # How I used this change to make a configuration change described in #6733. # Test Plan I don't think this should do any harm. I have used Credentials Manager with `app.json` from this PR (`sdkVersion` wasn't at this time removed) and I achieved what I wanted. * [bare-expo] Remove extra comma from JSON * [docs] update Slider deprecation note * docs: add sdk 36 in sdk overview (#6785) * change splash screen images for templates (#6797) * change splash screen images for templates * reduce image size * [expo-application] Add methods for app release type and APNs environment (#6724) # Why APNs environment will be useful for `expo-notifications` module. App release type could be useful for users' analytics. # How In the gist of things, I moved `EXProvisioningProfile` from `ExpoKit` to `EXApplication`. Kernel either uses `EXApplication/EXProvisioningProfile` (if it's present) or uses sensible fallback values. # Test Plan Added tests to `test-suite`, verified in `bare-expo` that they pass. * [expo-notifications] Add private InstallationIdProvider (#6749) # Why To be able to register at Expo server we need to identify the device with a UUID. # How Implemented a non-exported module which: - uses the same storage as kernel does for the UUID (in native, on web uses `localStorage`) - if the ID is missing, it generates and saves a new one. # Test Plan None yet, implementing `getExpoPushTokenAsync` will be a test for this module. * [docs] Add configuration section to tutorial * [docs][ios] securestore data persists across installs (#6820) * [docs][ios] securestore data persists across installs * v36 * v34 * v35 * Fix typo in button.md (#6812) * Fix typo in button.md I've changed 'hold your breathe' to 'hold your breath'. * v36 docs Co-authored-by: Charlie Cruzan <35579283+cruzach@users.noreply.github.com> * [docs] Fix typo in walkthrough.md (#6810) * Fix typo * Fix same typo in unversioned docs * [docs] storeReview available in bare (#6821) * [docs] storeReview available in bare * v36 * [docs][barcodescanner] add note about battery usage (#6822) * [Android][expo-filesystem] Fix FileSystem.downloadAsync throwing NullPointerException * add null safe check in FileSystem#downloadAsync java implementation fix #6818 * document fix in changelog * Remove UA Parser from expo-constants (#6809) * Remove UA Parser * Update CHANGELOG.md * Remove navigator reference * expand switch statement * [docs] fix configuration.md no title * [docs] Suggestions from James, remove app icon transparency * [docs] notifications: better format, fix links (#6845) * [docs] notifications: better format, fix links * v36 docs, and fix sourcecode urls * [Audio] Fix setAudioModeAsync type (#6833) * [Audio] Fix setAudioModeAsync type Previously in #5593, setAudioModeAsync was changed to support passing a partial object (which would be merged with the previously set values, falling back to the default values). However, the TypeScript type was unchanged which means TypeScript will complain unless you pass an object with every key. This commit relaxes the type to match the newer implementation. * Improve naming I was initially reluctant to change the argument name for setAudioModeAsync since it would also change the TypeScript declaration but I think it's preferable to be explicit since it makes it less likely someone will accidentally use the partial mode. * Fix formatting * Don't set currentAudioMode until checks are done * [android][maps] add MapsPackage handling (#6844) * [eslint-config-universe] Add more lint rules for TypeScript (#6847) * [eslint-config-universe] Add more lint rules for TypeScript * expotools check-packages --no-build --no-test --fix-lint * expotools check-packages * [eslint-config-universe] Fix readme error for new typescript analysis config (#6853) * [expo] Prevent from starting application twice * Updated EMS docs (#6855) * Updated EMS docs * Update README.md * Apply suggestions from code review Co-Authored-By: James Ide <ide@users.noreply.github.com> Co-authored-by: James Ide <ide@users.noreply.github.com> * [docs] Fix url to TypeScript website (#6834) * [docs] Fix url to TypeScript website * [docs] Fix url to TypeScript website in v36 docs * [@unimodules/core] Unpack InvocationTargetException when rejecting promise (#6870) # Why I noticed helpful messages of exception thrown inside exported methods aren't readable in JS. # How Noticed that when an exception is thrown inside exported methods it gets wrapped in `InvocationTargetException` – the original exception is then available under `getCause()`. # Test Plan With ```java String a = ""; a = null; a.charAt(0); ``` added to the implementation of `getDevicePushTokenAsync`: ## With ![with](https://user-images.githubusercontent.com/1151041/73197849-5a74dd80-4132-11ea-8626-e889023f344c.png) ## Without ![without](https://user-images.githubusercontent.com/1151041/73197866-6365af00-4132-11ea-94c0-a9a912665ee9.png) * Publish - expo-module-scripts@1.2.0 * expo-module-scripts@1.2.0 (#6873) * Use createElement on Video component (#6863) * Use createElement on Video component * fix build * [local-authentication] Use BiometricPrompt instead of FingerprintManager (#6846) * [bare-expo][ncl] Add native-component-list to bare-expo (#6868) # Why Make it easier to test things on both workflows at the same time. # How - Added `native-component-list` as a dependency of `bare-expo`. - Updated `app.json` config for web as now we need to tell babel to transpile files from NCL. - Resolved some issues caused by the fact that NCL was intended for use in managed workflow. - Added new bottom tab bar navigator for switching between TestSuite, Expo APIs and Expo Components. - Removed `standalone-ncl` app - it's useless now. # Test Plan - [x] Test bare-expo on mobile - [x] Test bare-expo on web - [x] Test native-component-list on mobile - [x] CI tests are passing I haven't tested whether every NCL screen works inside BareExpo, hopefully we will be fixing them separately once we use those screens. # Demo ![Simulator Screen Shot - iPhone 11 - 2020-01-27 at 12 05 38](https://user-images.githubusercontent.com/1714764/73179384-87fe5e80-4113-11ea-9a35-ec9b47c993cf.png) # Proposals for improvements in the future - Create `managed-expo` app that is actually the same as `bare-expo` but for managed workflow. That would make it really easy to debug every thing in both workflow at once. - Add the possibility to exclude `native-component-list` when running on the CI - with NCL it takes a bit more time to load the page. - I noticed the first tests (Basic) are taking much more time than subsequent ones and I guess it's because the first `page.goto` call triggers webpack to start bundling the app and until then we don't receive any response. Maybe we should open that page at the root path before running tests and give it as much time as it needs to and thus prevent timeouts in the first tests 🤔 * [permissions] Prevent from crashing on devices with Android below M (#6736) # Why On devices with API 21 and 22, app crashes when the user requested permissions. # How Added version check before delegating to the activity. # Test Plan I've tested this module on the device with Android 22 and with 28. - bare-expo ✅ - expo-client ✅ * [permissions] Update docs (#6699) # Why Resolves #6682 * [expo-screen-orientation] Extract to unimodule (#6760) * create screen-orientation unimodule * [screen-orientation] Apply PR suggestions & comments * [expo-screen-orientation] Rewrite to kotlin * [expo-screen-orientation] Apply requested changes * [expo-screen-orientation] Fix NCL * [expo-screen-orientation] Fix test-suite * [expo-screen-orientation] Fix notch detection * [expo-screen-orientation] Remove unused enum * [expo-screen-orientation] Fix NCL on iOS * [expo-screen-orientation] Change the scoped logic * [expo-screen-orientation] Remove EXModuleRegisterBinding * [expo-screen-orientation] Fix test-suite on iOS * [expo-screen-orientation] Apply requested changes * [expo-screen-orientation] Use traitCollectionsDidChange * [expo-screen-orientation] Fix orientation on iPads * [expo-screen-orientation] Apply requested changes * [expo-screen-orientation] Remove ALL_BUT_UPSIDE_DOWN * [expo-screen-orientation] Rename & refactor * [expo-screen-orientation] Update pods * [expo-screen-orientation] Update module-scripts version * [expo-screen-orientation] Fix bare-expo & CI Co-authored-by: Wojciech Lewicki <wojciech.lewicki@swmansion.com> * [TS][location][docs] add `maximumAge` to TS, `timeout` to docs, & fix docs error (#6808) * [location] add TS for maximumAge * update docs for timeout option * add unique key prop to TableOfContentSection * [docs] Set up Danger to warn about updating changed docs on other versions (#6890) * [@unimodules/react-native-adapter] Return Promise instead of awaiting it (#6882) # Why While performance testing #6881 I bumped into a strange performance difference between calling ```tsx import * as Cellular from 'expo-cellular'; await Cellular.getCellularGenerationAsync(); ``` and ```tsx import { NativeModulesProxy } from '@unimodules/core'; await NativeModulesProxy.ExpoCellular.getCellularGenerationAsync(); ``` where the latter was noticeably quicker (10%, 4188 ms vs 3764 ms). After sharing my results with the team, @wkozyra95 has come up with an explanation — calling `return await promise` requires an extra event loop round comparing with `return promise`. In situations where we don't wrap `return await` with a try-catch it should be safe to replace `return await` with `return`. # How - replaced `return await` with `return`, - replaced `throw new Error` with `Promise.reject(new Error` not to throw errors outside of a Promise, - removed `async` annotation from the function. # Test Plan Calling `await Application.getInstallReferrerAsync()` in a for loop 5000 times in `bare-expo` project resulted took: - 78.5 s, **68.6 s**, 70.8 s, 70.7 s — **mean 72.1 s** whereas on `master` the same benchmark took - 75.5 s, **75.0 s**, 76.4 s, 75.6 s — **mean 75.6 s** On average this PR should make calls to native about 4.5% faster. Once this PR is accepted I will go through all other places where we `return await` and fix this issue there. * [docs][screen-orientation] add ALL_BUT_UPSIDE_DOWN to SDK36 docs (#6852) * [docs] Fix Facebook init example in Firebase guide (#6830) * [task-manager] Fix crash in HeadlessAppLoader after the activity is killed (#6879) devSupportManager can be null. This is evident both from my experience and from similar code in: https://github.com/expo/expo/blob/0ec9e78c4e4ff0656eaa861b50618a80b8650952/android/expoview/src/main/java/host/exp/exponent/experience/ReactNativeActivity.java#L293 I tried it on an ejected to ExpoKit app, though I believe it's the same for expo client too. # Why This crash was preventing background fetch from working, as the app was crashing when trying to restart. This is probably related to the many background task issues in the issue tracker such as: #3503, #3582, #4860 and potentially others. # How I have not been able to test it locally (no idea how to build expo kit, and wasn't able to get help on the Slack), though the code seems right, and it's a trivial change. (How can I build ExpoKit locally)? # Test Plan 1. Add a background fetch task on Android: ``` BackgroundFetch.registerTaskAsync(BACKGROUND_SYNC_TASK_NAME, { minimumInterval: 1 * 60, // one minute stopOnTerminate: false, startOnBoot: true, }); ``` 2. Move the activity to background (maybe let it even run the task once, for good measure). 3. Go to the app switcher -> swipe out the task application 4. Wait another minute and see that the task isn't running. Look in the logs and see it's because it's crashing. This patch should fix it. * [docs] Fix Facebook init example in Firebase guide (SDK36 update) * [docs] Quick start for @lydiahallie aka Coco * [docs] clarify need for buildNumber and versionCode (#6908) * Handle nullable InAppPurchase product data description as empty string (#6909) * [bare-expo] Clean Pods reinstall (#6914) # Why Not to have obsolete files inside our repository. # How While developing `expo-notifications` I had some problem with `EXNotifications.xcodeproj` after rebasing onto `master` so I decided to delete `Pods` and reinstall Pods. Then I noticed that there are numerous files that are no longer used by CocoaPods. Most probably they have been used by CocoaPods before we used RN's autolinking. Now, that we use autolinking and the files are included from `node_modules` we should be safe to remove them. # Test Plan `bare-expo` compiled. * [ios] Clean Pods reinstall * [bare-expo] Update bare-expo BasePackageList after adding new unimodules * [android][web-browser] add web-browser's showInRecents option to AuthSession (#6701) * [android][web-browser] add web-browser's showInRecents option to AuthSession * Fix tests. Co-authored-by: Michał Czernek <czernekmichal@gmail.com> * [ios][home] Redesign DevMenu on iOS (#6793) # Why Part of #6521 # How - Refactored JS code responsible for rendering DevMenu and converted it to TypeScript. - Redesigned DevMenu to be a bottom sheet instead of a modal to improve user experience. - Upgraded `react-navigation-stack` to `^2.0.15`. - In/out DevMenu animations are now controlled by JavaScript side (less native code). - Moved Kernel's module methods related to DevMenu to separate `DevMenuModule` file (I think it makes the code using it clearer). - `Nux` wasn't clear to me what it is and what it does, so I suggest renaming it to `Onboarding`. - Prepared some stuff to be used on Android as well (Android support will come in a separate PR). - Removed legacy menu gesture from both native code and from home user settings. - Published dev home with those changes. # Test Plan - [x] Test on experience in debug mode - [x] Test on experience in production mode - [x] Test on snacks - [x] Test on older SDKs - [x] Test on simulators - [x] Test that onboarding shows up once you open the experience for the first time or you didn't accept it yet (clicked `Got it` button). # Demo Expanding/collapsing demo on the left, onboarding screen on the right. ![ezgif com-resize](https://user-images.githubusercontent.com/1714764/72625046-423ddb00-3948-11ea-937a-155aa154857a.gif) ![Simulator Screen Shot - iPhone 11 Pro Max - 2020-01-20 at 16 11 21](https://user-images.githubusercontent.com/1714764/72737399-c5a53980-3b9f-11ea-99fb-d246bfb8491e.png) * [home] Publish dev home with redesigned dev menu * [docs] Fix sidebar link selection when at /versions/latest * [docs] Make it a bit easier to flow from one page to another in a couple of places * [docs] Fix title of tutorial * [@unimodules/react-native-adapter] Add support for fetching images using Futures (#6933) # Why In some places it may be easier to use `Future` instead of a full-fledged `Listener`. # How Added two methods analogous to existing ones for fetching images by URI, but returning `Future`s. # Test Plan Tested as a part of #6932. * [expo-permissions] Make it extendable by expo-notifications (#6917) # Why We want to be able to: - redirect notification permission requests to `expo-notifications` if it's present - handle notification permission requests ourselves otherwise. # How - optional, lazy registration of notification requesters - making `EXRemoteNotificationPermissionRequester` extendable by loosening the type requirement on `userNotificationPermissionRequester` # Test Plan Getting notifications permissions in both Expo client and in `bare-expo` (with `expo-notifications` plugged in) work as expected. * [bare-expo] Add GoogleService-Info.plist to bare-expo (#6934) * [secrets][template-files] Add GoogleService-Info.plist secrets & templates for bare-expo * [bare-expo] Add optional GoogleService-Info.plist file linking * [docs] use captureRef from react-native-view-shot (#6956) * Update CONTRIBUTING.md (#6941) seems the anchor has to include the extra chars * [docs] Fixed typo in example snippet (#6947) * Fixed typo in example snippet * Fixed typo in example snippet for unversioned docs * [docs] Fix links to app-icons and splash-screens (#6942) * Fix links to app-icons and splash-screens In the "Configuring your app with app.json" the links to the guide pages for app icons and splash screens are backwards. * Fix links to app-icons and splash-screens The links to the app-icons and splash-screens pages were reversed. I just switched them so they would be correct. * [github] Fix incorrect format in stale.yml * add expo-facebook to bare-expo (#6958) * Add expo-facebook to bare-expo * Add facebook test shim to test-suite * Update bare-expo pods * update jest-expo-puppeteer dependencies (#6959) - "@expo/babel-preset-cli": "^0.2.5", - "@expo/config": "^2.5.6", - "@expo/xdl": "^57.4.6", - "getenv": "^1.0.0", - "@types/getenv": "^1.0.0", * [contacts] Fixed 'fields' parameter type in getContactByIdAsync function (#6910) * [expo-notifications] Smaller fixes (#6790) # Why, How Whilst preparing #6773 I noticed two commits that don't belong to that PR. So I created a separate one to make the other one simpler to review. # Test Plan Code compiles. * [local-authentication] Give proper error when device is unsecured (#6962) # Why Follow up to #6846 to fix a wrongly returned `user_cancel`. Now returns `not_enrolled` if the device is not secured with any method. # How Before trying to initialise the BiometricPrompt we ask the KeyGuard if the device is "secured". If it isn't, we return the `not_enrolled` error right away. # Test Plan We intend to use this in a commercial product so I will test this on a number of devices by simply copying over the source into my node_modules, building the app, and testing on multiple devices. I'm also hoping for some help from @tsapeta ❤️ * [local-authentication] Bail early when in background (#6971) # Why Follow up to #6962, fail with a proper error when `getCurrentActivity()` returns `null`. # How Reject the promise if we cannot get ahold of the current activity # Test Plan Try triggering local authentication when in the background * [expo] Remove Glide from UIManagerModuleWrapper (#6400) * Remove glide from UIManagerModuleWrapper Move loadImageForUrl to EXImageLoader Fix android build Add new module to ExperiencePackagePicker Add requested changes Update react-native-unimodules Change UMBridgeModule to RCTBridgeModule * [expo] Update react-native-unimodules * [tools] Prevent from checking whether google-services.json is present in bare-expo app. (#6931) * [tools] Prevent from checking whether google-services.json is present in bare-expo app. * [github] fix stale bot part 2 * [home] Allow users to paste https experience urls * [templates] Add .expo/ to gitignore for bare templates (#6811) * [docs] Add missing end quote to config doc * Create styled-components guide (#6961) * Create using-styled-components.md * Update docs/pages/versions/unversioned/guides/using-styled-components.md Co-Authored-By: Juwan Wheatley <datwheat@gmail.com> Co-authored-by: Juwan Wheatley <datwheat@gmail.com> * [android][local-authentication] Load Android Gradle Plugin conditionally (#6977) # Why This wraps the Android Gradle plugin dependency in the buildscripts section of android/build.gradle in a conditional: ``` if (project == rootProject) { // ... (dependency here) } ``` The Android Gradle plugin is only required when opening the project stand-alone, not when it is included as a dependency. By doing this, the project opens correctly in Android Studio, and it can also be consumed as a native module dependency from an application project without affecting the app project (avoiding unnecessary downloads/conflicts/etc). for more info, you can refer to [this thread](facebook/react-native#25569) and especially [this comment.](facebook/react-native#25569 (comment)) # How I used a condition to check this module is the root project opened in IDE or it's just a module used by another root project; then based on the result of the condition I loaded the AGP for building the module. So the AGP will be downloaded and used only when the module is opened as a standalone project (for developing the module itself) # Test Plan I'm currently using AGP 3.5.3 in one of my projects. before this change when I try to build my project, Android Gradle Plugin 3.5.1 is also downloaded to build this module which is completely unnecessary. After this change, the AGP 3.5.1 is not downloaded and this module still built successfully. please be aware this change has no break changes for users and developers of this module and it's a completely safe change. you can check more successful similar PRs on famous RN libraries from the thread I linked above. * [local-authentication] Add more options to the iOS authenticateAsync options (#6891) # Why This resolves an open issue [#4799](#4799). I also added the option to customize the cancel label. # How I reviewed the [Apple documentation](https://developer.apple.com/documentation/localauthentication/logging_a_user_into_your_app_with_face_id_or_touch_id?language=objc) and added the appropriate options to select the correct policy to evaluate against. # Test Plan I will test this on a number of devices by copying over the source into my node_modules, building the app, and testing on multiple devices. * [local-authentication] Rebuild local authentication package * [docs] update segmentedcontrolios deprecation note (#6972) * [docs] update segmentedcontrolios deprecation note * [docs] update segmentedcontrolios deprecation note for unversioned * [docs] Improve AppAuth docs (#6876) * [docs] Improve AppAuth docs - Explain OAuth a little bit more - Mention that there are specialized modules for Google and Facebook - Give a complete example as an inline Snack rather than just as sourc code * Update docs/pages/versions/unversioned/sdk/app-auth.md lg Co-Authored-By: Evan Bacon <baconbrix@gmail.com> * Update docs/pages/versions/unversioned/sdk/app-auth.md lg Co-Authored-By: Evan Bacon <baconbrix@gmail.com> * Apply suggestions from code review Co-Authored-By: Evan Bacon <baconbrix@gmail.com> * Apply suggestions from code review Co-Authored-By: Evan Bacon <baconbrix@gmail.com> Co-authored-by: Evan Bacon <baconbrix@gmail.com> * [expo-notifications] Add NotificationChannelsManager (#6842) # Why `NotificationChannelsManager` singleton module will be the manager of notification channels — modules should proxy any changes to channels through it. (There are no modules allowing to create, modify or delete notification channels at the moment, so the only thing this module does is providing a fallback notification channel — a channel `expo-notifications` creates for notifications not assigned to any other channel. It's a rather common practice — [FCM does it too](https://stackoverflow.com/a/45930522).) # How Added a singleton module, which on appropriate platforms (Android && SDK > .O) tries to create a notification channel reactively (only when asked for a fallback channel). Name is fetched from Android resources, so it will should easy to overwrite or localize by developers. ![excalidraw-202012311929-12](https://user-images.githubusercontent.com/1151041/73084749-d28e9980-3ecd-11ea-850d-f76b176c2040.png) More complete diagram (receiving + handling + building + side effects) ![excalidraw-202012311929-13](https://user-images.githubusercontent.com/1151041/73084918-1e414300-3ece-11ea-8096-f228d6ceb835.png) # Test Plan I have confirmed that when a new app is installed and no other action is taken, the settings say that the app hasn't created any channels yet. Once `.getFallbackChannel()` is called, settings say that there exists a single _"Miscellaneous"_ channel. * [expo-notifications] Add getExpoPushTokenAsync() (#6733) # Why We will want to still allow developers to use Expo backend for sending push notifications. # How Implemented fetching of the token in JS. > Note: In Expo client, where we wouldn't want to expose device push token to developers, we will export a native `getExpoPushTokenAsync` method that will implement this behavior. # Test Plan Tested on iOS 13, Android 7.1 and 9. - ✅ added test to `test-suite` that checks whether fetching of the token renders proper, stringy result passes. It is run on iOS and Android (backend not only doesn't support Web push notifications, but it also doesn't allow requests from origins other than `*.expo.io`). - ✅ notification sent with Expo push notification tool to the Expo token received reaches the device To be able to test whether the notification does reach the device I had to manually call `Permissions.askAsync(Permissions.USER_FACING_NOTIFICATIONS)` since it seems that our server can't send silent notifications (the device was receiving them only when sent via device push token). Moreover, I added one of the Exponent push tokens to `@exponent` account and assigned the push token to `(@exponent/bare-expo, dev.expo.Payments)` app/experience. <center><img width="375" alt="obrazek PNG 6" src="https://user-images.githubusercontent.com/1151041/72167596-b2d67c00-33cb-11ea-8416-1c640d83ae77.png"></center> * [bare-expo] Install pods * [ios][web-browser] Fix bug where `safariViewControllerDidFinish` is not called (#6581) # Why To fix a bug where `safariViewControllerDidFinish` is not called if you close the webview with the "Swipe to dismiss" gesture. This bug was re-introduce by #6345 # Test Plan Open a web browser and try to close the webview with the "Swipe to dismiss" gesture (from left to right). You shouldn't be able to close it. ``` <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}> <Button title="Open a web browser" onPress={() => { WebBrowser.openBrowserAsync('https://expo.io'); }} /> </View> ``` * [templates] Migrate React Navigation to 5.0 (#6974) * Update README.md * fix(mock): fix missing sdkVersion causing jest fail with react-navigation 5 (#6999) See react-navigation/react-navigation#6793 (comment) * [templates] Clean up tabs template * Enable tablet support in bare-expo ios project (#7009) * [expo-notifications] Receiving notifications (#6773) # Why Another step of `expo-notifications` extraction. # How - A singleton `EXNotificationCenterDelegate | NotificationManager` is informed of new notifications. The information is redirected to `EXNotificationDelegates | NotificationListeners`, which in fact are - `EXNotificationsEmitters | NotificationsEmitters` which serialize the notifications and emit events to JS. ![excalidraw-202012311929-4](https://user-images.githubusercontent.com/1151041/73066742-1b7f2780-3ea7-11ea-83fb-0fd392643b82.png) > Multiple `EventEmitter`s on the image show the situation that will happen in Expo client or when React instance is restarting. In normal situation there is only one emitter per bridge. > **Note:** what happens to the notification (if it's presented, dismissed, etc) will be decided in another module/PR (handling notifications). Since handling is a non-trivial task (requires communication back and forth) I think splitting those concerns may make the module easier to maintain. # Test Plan Received notifications can be printed to `console` when a listener is registered. * [bare-expo] Update BasePackageList after creating expo-image-loader * [bare-expo] Fix GoogleService-Info.plist no longer bundled * [docs] Fix image source prop uri in introduction (#6928) * Fix image source prop uri I found that the source prop needed to be an object with a `uri` key, the same as the example earlier in the file. I think this is just a typo. * Fix image source prop uri in unversioned docs too * [android][sqlite] small improvements to error messages (#6996) * [docs] Fix google-sign-in example & GoogleService-Info.plist updates (#6791) - fixed several imports which no longer worked - rename ‘GoogleService-info.plist’ -> ‘GoogleService-Info.plist’ - update ios workflow to include GoogleService-Info.plist - fix REVERSED_CLIENT_ID reference - fixed several typos - Add optional firebase usage scenario * [docs] Fix typo in webbrowser.md (#7015) * Update webbrowser.md Fix typo * Update webbrowser.md Typo fix * Update webbrowser.md Typo fix * Update webbrowser.md Typo fix * Created @expo/html-elements (#6986) * Created @expo/html-elements package * Created Anchor element * Created Article * Created Header * Created Main * Created Section * Created Footer * Created P * Created B * Created Strong * Created Strike * Created I * Created Br * Created Hr * Created Code * Created Table elements * Updated text elements * Updated Hr * Created Nav * Created Small * Created Lists * Created Mark * Create Tfooter * Update package.json * Updated docs * Update README.md * Update README.md * Update README.md * Update packages/html-elements/README.md Co-Authored-By: Brent Vatne <brentvatne@gmail.com> * extract target from anchor * Strike -> Del * Updated headings docs * Update README.md * simplify ts method * removed ts-ignores * Ul => UL * Ol => OL * Li => LI * Hr => HR * Thead => THead * Tbody => TBody * Tfoot => TFoot * Td => TD * Br => BR * Tr => TR * Th => TH * Em => EM * Fix NCL screen * Added E2E tests * Updated .npmignore to remove tests, snapshots, and jest tsconfig * Created Q and BlockQuote * pixels -> value * Added audio tag * Update README.md * update build files * fix view and text styles * Created Time * Update README.md * Update README.md * updated tests * Remove unused tests * Created Pre * Update README.md * Update README.md * Update README.md * Update README.md * internal links * unify blocks * Update README.md Co-authored-by: Brent Vatne <brentvatne@gmail.com> * Force flex direction to column on web (#7023) Force colors to black on web * [expo-notifications] Handling notifications (#6796) # Why Next `expo-notifications` feature. # How - `NotificationsHandlerModule` registers at singleton for new notifications/messages - for each message it _starts up_ a task which emits an event to JS - in response to the JS event, delegate responds with the appropriate behavior (eg. `shouldShowAlert: true`) - the behavior is pushed to native side using `NotificationsHandler.handleNotificationAsync` call - which directs it to the appropriate task - task handles the behavior (on iOS calls `completionHandler`, on Android it will show the notification once implemented) and finishes - if for whatever reason delegate didn't respond in 3 seconds, `onTimeout` is called on task, which emits another event to JS (for debugging purposes) and the task finishes ![excalidraw-202012311929-7](https://user-images.githubusercontent.com/1151041/73078318-3ca14180-3ec2-11ea-9220-c7a2f3c1e558.png) # Test Plan Tested manually by sending notifications and logging messages that the scheme works both when the delegate responds and when it does not. * [expo-notifications] Add permissions requesting methods (#6807) # Why Part of `expo-notifications` rework. BTW fixes #5093. # How - on iOS: - implemented a requester that returns full information on current notification settings - implemented an exported module capable of getting and asking for notification permissions - added a method so that developers are able to ask for specific notification permissions - on Android: - implemented a native module that returns a response based on `NotificationManagerCompat` - moreover, it also returns `importance` of notifications - on web: - nothing yet, to be researched - in TS: - added methods and type definitions for all the new features # Test Plan Added a simple test to `test-suite` and manually checked if the values returned match the settings. * [bare-expo] Update Android google-services.json to use Bare Expo firebase project * [tools] Fix google-services.json for bare-expo never generated (fixes #6931) * [html-elements] Update layout elements (#7027) * Created new layout elements * Updated docs * Updated small size * updated heading snapshots * lint fix * fix format * publish @expo/html-elements@0.0.0-alpha.2 Co-authored-by: Stanisław Chmiela <sjchmiela@users.noreply.github.com> Co-authored-by: Charlie Cruzan <35579283+cruzach@users.noreply.github.com> Co-authored-by: Zubair Ahmed <zubair.ahmed@alumni.stanford.edu> Co-authored-by: Michael Chow <michael.chow@alumni.stanford.edu> Co-authored-by: Brent Vatne <brentvatne@gmail.com> Co-authored-by: Hein Rutjes <IjzerenHein@users.noreply.github.com> Co-authored-by: Hamdi Gatri <hamdigatri92@gmail.com> Co-authored-by: Hays Stanford <stanfordhays@gmail.com> Co-authored-by: Juwan Wheatley <datwheat@gmail.com> Co-authored-by: James Ide <ide@users.noreply.github.com> Co-authored-by: Jerome Cornet <jeromecornet@users.noreply.github.com> Co-authored-by: Eric Samelson <esamelson@users.noreply.github.com> Co-authored-by: Tom Hacohen <tasn@users.noreply.github.com> Co-authored-by: Henrique <henrique.j.graca@gmail.com> Co-authored-by: Cedric van Putten <me@bycedric.com> Co-authored-by: joshnatis <31445542+joshnatis@users.noreply.github.com> Co-authored-by: Glenn Reyes <glenn@glennreyes.com> Co-authored-by: Jules Sam. Randolph <jules.sam.randolph@gmail.com> Co-authored-by: Max Holder <mxhold@gmail.com> Co-authored-by: Will Schurman <wschurman@gmail.com> Co-authored-by: Łukasz Kosmaty <lukasz.kosmaty@student.uj.edu.pl> Co-authored-by: Dennis Paagman <dennispaagman@gmail.com> Co-authored-by: Linus Unnebäck <linus@folkdatorn.se> Co-authored-by: Tomasz Sapeta <1714764+tsapeta@users.noreply.github.com> Co-authored-by: Wojciech Lewicki <wojciech.lewicki@swmansion.com> Co-authored-by: Sébastien Lorber <slorber@users.noreply.github.com> Co-authored-by: Eugene Zharkov <eu.zharkov@gmail.com> Co-authored-by: Michał Czernek <czernekmichal@gmail.com> Co-authored-by: guanw <guanw0826@gmail.com> Co-authored-by: Frank Calise <fcalise@gmail.com> Co-authored-by: Jason Carter <j-carter@users.noreply.github.com> Co-authored-by: Aryan J <aryanjabbari@gmail.com> Co-authored-by: Michael Meyer <michael@meyer.io> Co-authored-by: SaeedZhiany <SaeedZhiany@users.noreply.github.com> Co-authored-by: BeauR <793453+beaur@users.noreply.github.com> Co-authored-by: Daiki Ihara <sasurau4@gmail.com> Co-authored-by: Charlie Cheever <ccheever@gmail.com> Co-authored-by: Axel Delafosse <axel.delafosse@epitech.eu> Co-authored-by: Michał Osadnik <micosa97@gmail.com> Co-authored-by: Dimitri KOPRIWA <kopx@free.fr> Co-authored-by: thejimmyg <james@jimmyg.org> Co-authored-by: Chris <chris@altruisticsoftware.com>
This won't get merged in current state so I'll let myself close this pull request. Adding to the topic of discussion: I quite like the approach I took with
if the native module is typed like this, it's obvious and the types enforce it that we need to either check |
Why
We tend to have our unimodules' code littered with
I wanted to write the proxy like this some time ago, but the Android's JSC version didn't let us use
Proxy
. Now, as JSC is up-to-date, we can.Searching for
throw new UnavailabilityError
results in 224 results in 56 files. Most of it is as simple as the example snippet above, some of them do parse arguments in some way. In my opinion going fromto
(i.e. changing the order of errors thrown in case
uri
isn't a string) shouldn't be a big change.Disadvantages
On the other hand, throwing errors on
get
of a property will result in a breaking change of behavior. For example the following code will no longer be correct:it would need to be rewritten to
Same would go for
which would need to be
Another way of solving this constants issue would be to introduce the
getConstants
method through which constants will be accessed in TurboModules environment. It would return a plain object so there wouldn't be any problem with executingExponentConstants.getConstants().manifest
ifExponentConstants
wouldn't expose amanifest
constant.How
Instead of constructing a big "proxy" object when starting up the application we can use
Proxy
to create the modulesProxies
on demand.Test Plan
Calling await
Application.getInstallReferrerAsync()
in a for loop 5000 times inbare-expo
project took:whereas on
master
the same benchmark tookIt seems that replacing
if (Module.method) { … }
withProxy
shouldn't affect performance negatively.