diff --git a/.npmignore b/.npmignore index e45b559b..e5be9c99 100644 --- a/.npmignore +++ b/.npmignore @@ -1,2 +1,5 @@ example/ node_modules/ +.idea/ +.github/ +docs/ diff --git a/AUTHORS b/AUTHORS index 1574eba1..94147d7f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -10,3 +10,4 @@ Since react-native-callkit only targets iOS devices, we created react-native-cal Linus Unnebäck Geraint White Samuel Bégin + Jonas Swiatek diff --git a/MIGRATION_v3_v4.md b/MIGRATION_v3_v4.md new file mode 100644 index 00000000..dec23113 --- /dev/null +++ b/MIGRATION_v3_v4.md @@ -0,0 +1,20 @@ +# Migration from CallKeep v3 to v4 + +The `reportNewIncomingCall` method on iOS is now more consistent. + +Please update your `AppDelegate.m` file with this new signature: + +```objc +[RNCallKeep reportNewIncomingCall: uuidString + handle: handle + handleType: handleType + hasVideo: YES + localizedCallerName: localizedCallerName + supportsHolding: YES + supportsDTMF: YES + supportsGrouping: YES + supportsUngrouping: YES + fromPushKit: YES + payload: nil + withCompletionHandler: nil]; +``` diff --git a/README.md b/README.md index a2d81997..be61547f 100644 --- a/README.md +++ b/README.md @@ -9,18 +9,35 @@ For more information about **CallKit** on iOS, please see [Official CallKit Fram For more information about **ConnectionService** on Android, please see [Android Documentation](https://developer.android.com/reference/android/telecom/ConnectionService) and [Build a calling app](https://developer.android.com/guide/topics/connectivity/telecom/selfManaged) -# Demo +⚠️ **CallKit** and **ConnectionService** are only available on real devices, this library will not work on simulators. + +# Summary +- [Demo](#Demo) +- [Installation](#Installation) +- [Usage](#Usage) + - [Expo](#Usage-with-Expo) + - [Constants](#Constants) + - [Android Self Managed](#Android-Self-Managed-Mode) + - [API](#Api) + - [Example](#Example) +- [PushKit](#PushKit) +- [Android 11](#Android-11) +- [Debug](#Debug) +- [Troubleshooting](#Troubleshooting) +- [Contributing](#Contributing) +- [License](#License) + +# Demo A demo of `react-native-callkeep` is available in the [wazo-react-native-demo](https://github.com/wazo-pbx/wazo-react-native-demo) repository. -## Android +#### Android ![Connection Service](docs/pictures/connection-service.jpg) -## iOS +#### iOS ![Connection Service](docs/pictures/call-kit.png) # Installation - ```sh npm install --save react-native-callkeep # or @@ -32,7 +49,7 @@ yarn add react-native-callkeep # Usage -## Setup +#### Setup ```js import RNCallKeep from 'react-native-callkeep'; @@ -47,13 +64,48 @@ const options = { cancelButton: 'Cancel', okButton: 'ok', imageName: 'phone_account_icon', - additionalPermissions: [PermissionsAndroid.PERMISSIONS.example] + additionalPermissions: [PermissionsAndroid.PERMISSIONS.example], + // Required to get audio in background when using Android 11 + foregroundService: { + channelId: 'com.company.my', + channelName: 'Foreground service for my app', + notificationTitle: 'My app is running on background', + notificationIcon: 'Path to the resource icon of the notification', + }, } }; RNCallKeep.setup(options).then(accepted => {}); ``` +iOS only. + +Alternative on iOS you can perform setup in `AppDelegate.m`. Doing this allows capturing events prior to the react native event bridge being up. Please be aware that calling setup in `AppDelegate.m` will ignore any subsequent calls to `RNCallKeep.setup();`. + +```objective-c +@implementation AppDelegate +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + self.bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; + + [RNCallKeep setup:@{ + @"appName": @"Awesome App", + @"maximumCallGroups": @3, + @"maximumCallsPerCallGroup": @1, + @"supportsVideo": @NO, + }]; + + RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:self.bridge + moduleName:@"App" + initialProperties:nil]; + + // ======== OTHER CODE REDACTED ========== + + return YES; +} + +``` + - `options`: Object - `ios`: object - `appName`: string (required) @@ -62,14 +114,27 @@ RNCallKeep.setup(options).then(accepted => {}); If provided, it will be displayed on system UI during the call - `ringtoneSound`: string (optional) If provided, it will be played when incoming calls received; the system will use the default ringtone if this is not provided + - `handleType`: string|array (optional) + If provided, it will tell iOS what kind of handle(s) (number) your app can handle. + - `generic` + - `number` (default) + - `email` - `includesCallsInRecents`: boolean (optional) - If provided, calls will be shown in the recent calls when true and not when false (ios 11 and above) + If provided, calls will be shown in the recent calls when true and not when false (ios 11 and above) (Default: true) - `maximumCallGroups`: string (optional) If provided, the maximum number of call groups supported by this application (Default: 3) - `maximumCallsPerCallGroup`: string (optional) If provided, the maximum number of calls in a single group, used for conferencing (Default: 1, no conferencing) - `supportsVideo`: boolean (optional) If provided, whether or not the application supports video calling (Default: true) + - `displayCallReachabilityTimeout`: number in ms (optional) + If provided, starts a timeout that checks if the application is reachable and ends the call if not (Default: null) + You'll have to call `setReachable()` as soon as your Javascript application is started. + - `audioSession`: object + - `categoryOptions`: AudioSessionCategoryOption|number (optional) + If provided, it will override the default AVAudioSession setCategory options. + - `mode`: AudioSessionMode|string (optional) + If provided, it will override the default AVAudioSession setMode mode. - `android`: object - `alertTitle`: string (required) When asking for _phone account_ permission, we need to provider a title for the `Alert` to ask the user for it @@ -86,8 +151,21 @@ RNCallKeep.setup(options).then(accepted => {}); - `additionalPermissions`: [PermissionsAndroid] (optional) Any additional permissions you'd like your app to have at first launch. Can be used to simplify permission flows and avoid multiple popups to the user at different times. + - `selfManaged`: boolean (optional) + When set to true, call keep will configure itself to run as a self managed connection service. This is an advanced topic, and it's best to refer to [Googles Documentation](https://developer.android.com/guide/topics/connectivity/telecom/selfManaged) on the matter. + - `displayCallReachabilityTimeout`: number in ms (optional) + If provided, starts a timeout that checks if the application is reachable and ends the call if not (Default: null) + You'll have to call `setReachable()` as soon as your Javascript application is started. + +`setup` calls internally `registerPhoneAccount`, `registerEvents` and `setSettings`. + +You can alternatively just call `setSettings()` with the same option as `setup()` to define only your settings. -## Constants +# Usage with Expo + +To use this library with Expo, you will need to create a development build. Expo Go does not support custom native modules. For information on how to create and run a development build, visit: [Create a development build - Expo Documentation](https://docs.expo.dev/develop/development-builds/create-a-build/). You can use and test this library with a development build installed on your physical device (iOS and Android). + +# Constants To make passing the right integer into methods easier, there are constants that are exported from the module. @@ -108,7 +186,83 @@ const { CONSTANTS as CK_CONSTANTS, RNCallKeep } from 'react-native-callkeep'; console.log(CK_CONSTANTS.END_CALL_REASONS.FAILED) // outputs 1 ``` -## Methods +# Android Self Managed Mode +_This feature is available only on Android._ + +Android supports calling apps running in what's called "Self Managed". This means the apps are able (and required) to provide their own UI for managing calls. This includes both in call UI elements and incoming call notification UI. This method is all or nothing. You can't mix partial elements, such as having a custom in call view, but use the default incoming call UI. + +To implement a self managed calling app, the following steps are necessary: +- Set `selfManaged: true` in setup. +- On an incoming call, from react native, call `RNCallKeep.displayIncomingCall` +- CallKeep will then fire the `showIncomingCallUi` event. +- When `showIncomingCallUi` is fired, you must show an incoming call UI. This would be a high priority notification ([Android: Display time-sensitive notifications](https://developer.android.com/training/notify-user/time-sensitive)). +- If the user answers the call, you call the appropriate RNCallKeep actions such as `answerCall` or `endCall` +- In certain cases Android will not allow you to show an incoming call notification. In that case the 'createIncomingConnectionFailed' event is fired and you should reject the incoming SIP Invite. + +Self Managed calling apps are an advanced topic, and there are many steps involved in implementing them, but here are some things to keep in mind: +- React Native Headless Tasks are a great way to execute React Native code. Remember to start up the headless task as a Foreground Service. +- Android will deprioritize your high priority FCM notifications if you fail to show an incoming call ui when receiving them. +- You can avoid getting flooded with sticky foreground service notifications by not defining a Foreground Service for CallKeep, and instead managing this on your own. + +⚠️ To be able to use the self managed mode, you'll have to add the `READ_CALL_LOG` permission in your `android/src/main/AndroidManifest.xml` file: +``` + +``` + +# API + +| Method | Return Type | iOS | Android | +| ----------------------------------------------------------------- | ------------------- | :--: | :-----: | +| [getInitialEvents()](#getInitialEvents) | `Promise` | ✅ | ✅ | +| [clearInitialEvents()](#clearInitialEvents) | `void>` | ✅ | ✅ | +| [setAvailable()](#setAvailable) | `Promise` | ❌ | ✅ | +| [setForegroundServiceSettings()](#setForegroundServiceSettings) | `Promise` | ❌ | ✅ | +| [canMakeMultipleCalls()](#canMakeMultipleCalls) | `Promise` | ❌ | ✅ | +| [setCurrentCallActive()](#setCurrentCallActive) | `Promise` | ❌ | ✅ | +| [checkIsInManagedCall()](#setAvailable) | `Promise` | ❌ | ✅ | +| [isCallActive()](#isCallActive) | `Promise` | ✅ | ❌ | +| [getCalls()](#getCalls) | `Promise` | ✅ | ❌ | +| [displayIncomingCall()](#displayIncomingCall) | `Promise` | ✅ | ✅ | +| [answerIncomingCall()](#answerIncomingCall) | `Promise` | ✅ | ✅ | +| [startCall()](#startCall) | `Promise` | ✅ | ✅ | +| [updateDisplay()](#updateDisplay) | `Promise` | ✅ | ✅ | +| [endCall()](#endCall) | `Promise` | ✅ | ✅ | +| [endAllCalls()](#endAllCalls) | `Promise` | ✅ | ✅ | +| [rejectCall()](#rejectCall) | `Promise` | ✅ | ✅ | +| [reportEndCallWithUUID()](#reportEndCallWithUUID) | `Promise` | ✅ | ✅ | +| [setMutedCall()](#setMutedCall) | `Promise` | ✅ | ✅ | +| [setOnHold()](#setOnHold) | `Promise` | ✅ | ✅ | +| [setConnectionState()](#setConnectionState) | `Promise` | ❌ | ✅ | +| [checkIfBusy()](#checkIfBusy) | `Promise` | ✅ | ❌ | +| [checkSpeaker()](#checkSpeaker) | `Promise` | ✅ | ❌ | +| [toggleAudioRouteSpeaker()](#toggleAudioRouteSpeaker) | `Promise` | ❌ | ✅ | +| [supportConnectionService()](#supportConnectionService) | `Promise` | ❌ | ✅ | +| [hasPhoneAccount()](#hasPhoneAccount) | `Promise` | ❌ | ✅ | +| [hasOutgoingCall()](#hasOutgoingCall) | `Promise` | ❌ | ✅ | +| [hasDefaultPhoneAccount()](#hasDefaultPhoneAccount) | `Promise` | ❌ | ✅ | +| [checkPhoneAccountEnabled()](#checkPhoneAccountEnabled) | `Promise` | ❌ | ✅ | +| [isConnectionServiceAvailable()](#isConnectionServiceAvailable) | `Promise` | ❌ | ✅ | +| [backToForeground()](#backToForeground) | `Promise` | ❌ | ✅ | +| [removeEventListener()](#removeEventListener) | `void` | ✅ | ✅ | +| [registerPhoneAccount()](#registerPhoneAccount) | `void` | ❌ | ✅ | +| [registerAndroidEvents()](#registerAndroidEvents) | `void` | ❌ | ✅ | + + +### getInitialEvents + +If there were some actions performed by user before JS context has been created, this method would return early fired events. This is alternative to "didLoadWithEvents" event. + +```js +RNCallKeep.getInitialEvents(); +``` + +### clearInitialEvents + +Clear all pending actions returned by `getInitialEvents()`. + +```js +RNCallKeep.clearInitialEvents(); +``` ### setAvailable _This feature is available only on Android._ @@ -122,6 +276,30 @@ Eg: When your used log out (or the connection to your server is broken, etc..), RNCallKeep.setAvailable(true); ``` +### setForegroundServiceSettings +_This feature is available only on Android._ + +Configures the [Foreground Service](https://developer.android.com/about/versions/11/privacy/foreground-services) used for Android 11 to get microphone access on background. +Similar to set the `foregroundService` key in the `setup()` method. + +```js +RNCallKeep.setForegroundServiceSettings({ + channelId: 'com.company.my', + channelName: 'Foreground service for my app', + notificationTitle: 'My app is running on background', + notificationIcon: 'Path to the resource icon of the notification', +}); +``` + +### canMakeMultipleCalls +_This feature is available only on Android._ + +Disable the "Add call" button in ConnectionService UI. + +```js +RNCallKeep.canMakeMultipleCalls(false); // Enabled by default +``` + - `active`: boolean - Tell whether the app is ready or not @@ -139,13 +317,58 @@ RNCallKeep.setCurrentCallActive(uuid); - `uuid`: string - The `uuid` used for `startCall` or `displayIncomingCall` +### checkIsInManagedCall +_This feature is available only on Android._ + +Returns true if there is an active native call + +```js +RNCallKeep.checkIsInManagedCall(); +``` + + +### isCallActive +_This feature is available only on IOS._ + +Returns true if the UUID passed matches an existing and answered call. +This will return true ONLY if the call exists and the user has already answered the call. It will return false +if the call does not exist or has not been answered. This is exposed to both React Native and Native sides. +This was exposed so a call can be canceled if ringing and the user answered on a different device. + +```js +RNCallKeep.isCallActive(uuid); +``` + +- `uuid`: string + - The `uuid` used for `startCall` or `displayIncomingCall` + + +### getCalls + +_This feature is available only on IOS._ + +Returns a Promise. The result will be an array with all current calls and their states. + +```js +RNCallKeep.getCalls(); + +response: +[{ + callUUID: "E26B14F7-2CDF-48D0-9925-532199AE7C48", + hasConnected: true, + hasEnded: false, + onHold: false, + outgoing: false, +}] +``` + ### displayIncomingCall Display system UI for incoming calls -````js -RNCallKeep.displayIncomingCall(uuid, handle, localizedCallerName); -```` +```js +RNCallKeep.displayIncomingCall(uid, handle, localizedCallerName = '', handleType = 'number', hasVideo = false, options = null); +``` - `uuid`: string - An `uuid` that should be stored and re-used for `stopCall`. @@ -160,9 +383,15 @@ RNCallKeep.displayIncomingCall(uuid, handle, localizedCallerName); - `hasVideo`: boolean (optional, iOS only) - `false` (default) - `true` (you know... when not false) +- `options`: object (optional) + - `ios`: object + - `supportsHolding`: boolean (optional, default true) + - `supportsDTMF`: boolean (optional, default true) + - `supportsGrouping`: boolean (optional, default true) + - `supportsUngrouping`: boolean (optional, default true) + - `android`: object (currently no-op) ### answerIncomingCall -_This feature is available only on Android._ Use this to tell the sdk a user answered a call from the app UI. @@ -215,6 +444,14 @@ RNCallKeep.updateDisplay(uuid, displayName, handle) - Name of the caller to be displayed on the native UI - `handle`: string - Phone number of the caller +- `options`: object (optional) + - `ios`: object + - `hasVideo`: boolean (optional) + - `supportsHolding`: boolean (optional) + - `supportsDTMF`: boolean (optional) + - `supportsGrouping`: boolean (optional) + - `supportsUngrouping`: boolean (optional) + - `android`: object (currently no-op) ### endCall @@ -298,10 +535,25 @@ RNCallKeep.setOnHold(uuid, true) - uuid of the current call. - `hold`: boolean +### setConnectionState + +_This feature is available only on Android._ + +Change the state of the call + +```js +RNCallKeep.setConnectionState(uuid, state) +``` + +- `uuid`: string + - uuid of the current call. +- `state`: [See Connection.STATE_*](https://developer.android.com/reference/android/telecom/Connection#STATE_ACTIVE) documentation + ### checkIfBusy +_This feature is available only on IOS._ + Checks if there are any active calls on the device and returns a promise with a boolean value (`true` if there're active calls, `false` otherwise). -_This feature is available only on iOS._ ```js RNCallKeep.checkIfBusy(); @@ -309,32 +561,76 @@ RNCallKeep.checkIfBusy(); ### checkSpeaker +_This feature is available only on IOS._ + Checks if the device speaker is on and returns a promise with a boolean value (`true` if speaker is on, `false` otherwise). -_This feature is available only on iOS._ ```js RNCallKeep.checkSpeaker(); ``` -### supportConnectionService (async) +### toggleAudioRouteSpeaker -Tells if `ConnectionService` is available on the device (returns a boolean). +_This feature is available only on Android._ + +Update the audio route of Audio Service on Android with a `routeSpeaker` boolean value (`true` if speaker need on, `false` otherwise). +When Phone call is active, Android control the audio via connection service. so this function help to toggle the audio to Speaker or wired/ear-piece or vice-versa + +```js +RNCallKeep.toggleAudioRouteSpeaker(uuid, true); +``` + +- `uuid`: string + - uuid of the current call. +- `routeSpeaker`: boolean + +### getAudioRoutes + +Get the list of available audio routes. i.e. bluetooth, wired/ear-piece, speaker and phone. + +```js +await RNCallKeep.getAudioRoutes(): AudioRoute; +``` + +``` +type AudioRoute = { + name: string, + type: string +} +``` + +### setAudioRoute + +Set audio route using a route from `getAudioRoutes`. + +```js +await RNCallKeep.setAudioRoute(uuid, routeName); +``` + +- `uuid`: string + - uuid of the current call. +- `routeName`: String + - AudioRoute.name. + +### supportConnectionService _This feature is available only on Android._ +Tells if `ConnectionService` is available on the device (returns a boolean). + ```js RNCallKeep.supportConnectionService(); ``` ### hasPhoneAccount (async) +_This feature is available only on Android._ + Checks if the user has enabled the [phone account](https://developer.android.com/reference/android/telecom/PhoneAccount) for your application. A phone account must be enable to be able to display UI screen on incoming call and make outgoing calls from native Contact application. Returns a promise of a boolean. -_This feature is available only on Android._ - ```js await RNCallKeep.hasPhoneAccount(); ``` @@ -355,13 +651,13 @@ const hasOutgoingCall = await RNCallKeep.hasOutgoingCall(); ### hasDefaultPhoneAccount +_This feature is available only on Android._ + Checks if the user has set a default [phone account](https://developer.android.com/reference/android/telecom/PhoneAccount). If the user has not set a default they will be prompted to do so with an alert. This is a workaround for an [issue](https://github.com/wazo-pbx/react-native-callkeep/issues/33) affecting some Samsung devices. -_This feature is available only on Android._ - ```js const options = { alertTitle: 'Default not set', @@ -371,9 +667,93 @@ const options = { RNCallKeep.hasDefaultPhoneAccount(options); ``` +### checkPhoneAccountEnabled + +_This feature is available only on Android._ + +Checks if the user has set a default [phone account](https://developer.android.com/reference/android/telecom/PhoneAccount) and it's enabled. + +It's useful for custom permission prompts. It should be used in pair with `registerPhoneAccount` +Similar to `hasDefaultPhoneAccount` but without trigering a prompt if the user doesn't have a phone account. + + +```js +RNCallKeep.checkPhoneAccountEnabled(); +``` + +### isConnectionServiceAvailable + +_This feature is available only on Android._ + +Check if the device support ConnectionService. + + +```js +RNCallKeep.checkPhoneAccountEnabled(); +``` + +### backToForeground + +_This feature is available only on Android._ + +Use this to display the application in foreground if the application was in background state. +This method will open the application if it was closed. + +```js +RNCallKeep.backToForeground(); +``` + +### removeEventListener + +Allows to remove the listener on an event. + +```js +RNCallKeep.removeEventListener('checkReachability'); +``` + +### registerPhoneAccount + +Registers Android phone account manually, useful for custom permission prompts when you don't want to call `setup()`. +This method is called by `setup`, if you already use setup you don't need it. + +_This feature is available only on Android._ +_On iOS you still have to call `setup()`._ + +```js +RNCallKeep.registerPhoneAccount(options); +``` + +### registerAndroidEvents + +Registers Android UI events, useful when you don't want to call `setup()`. +This method is called by `setup`, if you already use setup you don't need it. + +_This feature is available only on Android._ +_On iOS you still have to call `setup()`._ + +```js +RNCallKeep.registerAndroidEvents(); +``` ## Events +| Event | iOS | Android | +| ----------------------------------------------------------------- | :--: | :-----: | +| [didReceiveStartCallAction](#didReceiveStartCallAction) | ✅ | ✅ | +| [answerCall](#answerCall) | ✅ | ✅ | +| [endCall](#endCall) | ✅ | ✅ | +| [didActivateAudioSession](#didActivateAudioSession) | ✅ | ✅ | +| [didDisplayIncomingCall](#didDisplayIncomingCall) | ✅ | ✅ | +| [didPerformSetMutedCallAction](#didPerformSetMutedCallAction) | ✅ | ✅ | +| [didToggleHoldCallAction](#didToggleHoldCallAction) | ✅ | ✅ | +| [didPerformDTMFAction](#didPerformDTMFAction) | ✅ | ✅ | +| [didLoadWithEvents](#didLoadWithEvents) | ✅ | ❌ | +| [showIncomingCallUi](#showIncomingCallUi) | ❌ | ✅ | +| [silenceIncomingCall](#silenceIncomingCall) | ❌ | ✅ | +| [checkReachability](#checkReachability) | ❌ | ✅ | +| [didChangeAudioRoute](#didChangeAudioRoute) | ✅ | ✅ | +| [onHasActiveCall](#onHasActiveCall) | ❌ | ✅ | + ### didReceiveStartCallAction Device sends this event once it decides the app is allowed to start a call, either from the built-in phone screens (iOS/_Recents_, Android/_Contact_), @@ -396,7 +776,7 @@ RNCallKeep.addEventListener('didReceiveStartCallAction', ({ handle, callUUID, na - `name` (string) - Name of the callee -### - answerCall +### answerCall User answer the incoming call @@ -409,7 +789,7 @@ RNCallKeep.addEventListener('answerCall', ({ callUUID }) => { - `callUUID` (string) - The UUID of the call that is to be answered. -### - endCall +### endCall User finish the call. @@ -422,7 +802,7 @@ RNCallKeep.addEventListener('endCall', ({ callUUID }) => { - `callUUID` (string) - The UUID of the call that is to be ended. -### - didActivateAudioSession +### didActivateAudioSession The `AudioSession` has been activated by **RNCallKeep**. @@ -433,7 +813,7 @@ RNCallKeep.addEventListener('didActivateAudioSession', () => { }); ``` -### - didDisplayIncomingCall +### didDisplayIncomingCall Callback for `RNCallKeep.displayIncomingCall` @@ -446,6 +826,8 @@ RNCallKeep.addEventListener('didDisplayIncomingCall', ({ error, callUUID, handle - `error` (string) - iOS only. +- `errorCode` (string) + - iOS only. Possible values: "Unentitled", "CallUUIDAlreadyExists", "FilteredByDoNotDisturb", "FilteredByBlockList", "Unknown". See https://developer.apple.com/documentation/callkit/cxerrorcodeincomingcallerror for more information. - `callUUID` (string) - The UUID of the call. - `handle` (string) @@ -461,7 +843,7 @@ RNCallKeep.addEventListener('didDisplayIncomingCall', ({ error, callUUID, handle - `payload` (object) - VOIP push payload. -### - didPerformSetMutedCallAction +### didPerformSetMutedCallAction A call was muted by the system or the user: @@ -475,7 +857,7 @@ RNCallKeep.addEventListener('didPerformSetMutedCallAction', ({ muted, callUUID } - `callUUID` (string) - The UUID of the call. -### - didToggleHoldCallAction +### didToggleHoldCallAction A call was held or unheld by the current user @@ -489,7 +871,22 @@ RNCallKeep.addEventListener('didToggleHoldCallAction', ({ hold, callUUID }) => { - `callUUID` (string) - The UUID of the call. -### - didPerformDTMFAction +### didChangeAudioRoute + +Triggered when the audio route has been changed. + +```js +RNCallKeep.addEventListener('didChangeAudioRoute', ({ output }) => { + +}); +``` + +- `output` (string) ⚠️ Will send `Speaker` on iOS but `SPEAKER` on Android. +- `reason` (number, iOS only) See case's in https://developer.apple.com/documentation/avfaudio/avaudiosession/routechangereason +- `handle` (string, Android only) Phone number of the incoming caller +- `callUUID` (string, Android only) The UUID of the call + +### didPerformDTMFAction Used type a number on his dialer @@ -504,7 +901,99 @@ RNCallKeep.addEventListener('didPerformDTMFAction', ({ digits, callUUID }) => { - `callUUID` (string) - The UUID of the call. -### - checkReachability +### didLoadWithEvents + +iOS only. + +Called as soon as JS context initializes if there were some actions performed by user before JS context has been created. + +Since iOS 13, you must display incoming call on receiving PushKit push notification. But if app was killed, it takes some time to create JS context. If user answers the call (or ends it) before JS context has been initialized, user actions will be passed as events array of this event. Similar situation can happen if user would like to start a call from Recents or similar iOS app, assuming that your app was in killed state. + +In order for this event to reliably fire, it's necessary to perform setup in `AppDelegate.m` + +**NOTE: You still need to subscribe / handle the rest events as usuall. This is just a helper whcih cache and propagate early fired events if and only if for "the native events which DID fire BEFORE js bridge is initialed", it does NOT mean this will have events each time when the app reopened.** + +```js +// register `didLoadWithEvents` somewhere early in your app when it is ready to handle callkeep events. + +RNCallKeep.addEventListener('didLoadWithEvents', (events) => { + // `events` is passed as an Array chronologically, handle or ignore events based on the app's logic + // see example usage in https://github.com/react-native-webrtc/react-native-callkeep/pull/169 or https://github.com/react-native-webrtc/react-native-callkeep/pull/205 +}); +``` + +- `events` Array + - `name`: string + Native event name like: `RNCallKeepPerformAnswerCallAction` + - `data`: object + Object with data passed together with specific event so it can be handled in the same way like original event, for example `({ callUUID })` for `answerCall` event if `name` is `RNCallKeepPerformAnswerCallAction` + +### showIncomingCallUi + +_Android only. Self Managed only._ + +Only when CallKeep is setup to be in self managed mode. Signals that the app must show an incoming call UI. The implementor must either call `displayIncomingCall` from react native or native android code to make this event fire. + +```js +RNCallKeep.addEventListener('showIncomingCallUi', ({ handle, callUUID, name }) => { + +}); +``` + +The following values will match those initially passed to `displayIncomingCall` + +- `handle` (string) + - Phone number of the incoming caller. +- `callUUID` (string) + - The UUID of the call. +- `name` (string) + - Caller Name. + +### silenceIncomingCall + +_Android only. Self Managed only._ + +Corresponds to the native [onSilence event](https://developer.android.com/reference/android/telecom/Connection#onSilence()). The implementor should silence the corresponding incoming calls notification sound when and if this event is fired. + +```js +RNCallKeep.addEventListener('silenceIncomingCall', ({ handle, callUUID, name }) => { + +}); +``` + +The following values will match those initially passed to `silenceIncomingCall` + +- `handle` (string) + - Phone number of the incoming caller. +- `callUUID` (string) + - The UUID of the call. +- `name` (string) + - Caller Name. + +### createIncomingConnectionFailed + +_Android only. Self Managed only._ + +Corresponds to the native [onCreateIncomingConnectionFailed callback](https://developer.android.com/reference/android/telecom/ConnectionService#onCreateIncomingConnectionFailed(android.telecom.PhoneAccountHandle,%20android.telecom.ConnectionRequest)). The implementor should reject the incoming SIP INVITE with an appropriate status code, such as 483 User Busy. Android unfortunately does not provide the exact reason for refusing to let you accept an incoming call, but they do list a set of reasons [here](https://developer.android.com/guide/topics/connectivity/telecom/selfManaged#constraints) + +```js +RNCallKeep.addEventListener('createIncomingConnectionFailed', ({ handle, callUUID, name }) => { + +}); +``` + +The following values will match those initially passed to `silenceIncomingCall` + +- `handle` (string) + - Phone number of the incoming caller. +- `callUUID` (string) + - The UUID of the call. +- `name` (string) + - Caller Name. + +### checkReachability + +_Android only._ On Android when the application is in background, after a certain delay the OS will close every connection with informing about it. So we have to check if the application is reachable before making a call from the native phone application. @@ -515,12 +1004,18 @@ RNCallKeep.addEventListener('checkReachability', () => { }); ``` -### removeEventListener -Allows to remove the listener on an event. +### onHasActiveCall + +_Android only._ + +A listener that tells the JS side if a native call has been answered while there was an active self-managed call ```js -RNCallKeep.removeEventListener('checkReachability'); +RNCallKeep.addEventListener('onHasActiveCall', () => { + // eg: End active app call if native call is answered +}); + ``` ## Example @@ -590,7 +1085,7 @@ class RNCallKeepExample extends React.Component { // Event Listener Callbacks - didReceiveStartCallAction(data) => { + didReceiveStartCallAction = (data) => { let { handle, callUUID, name } = data; // Get this event after the system decides you can start a call // You can now start a call from within your app @@ -648,17 +1143,18 @@ class RNCallKeepExample extends React.Component { } ``` + ## Receiving a call when the application is not reachable. In some case your application can be unreachable : - when the user kill the application - when it's in background since a long time (eg: after ~5mn the os will kill all connections). -To be able to wake up your application to display the incoming call, you can use [https://github.com/ianlin/react-native-voip-push-notification](react-native-voip-push-notification) on iOS or BackgroundMessaging from [react-native-firebase](https://rnfirebase.io/docs/v5.x.x/messaging/receiving-messages#4)-(Optional)(Android-only)-Listen-for-FCM-messages-in-the-background). +To be able to wake up your application to display the incoming call, you can use [https://github.com/react-native-webrtc/react-native-voip-push-notification](react-native-voip-push-notification) on iOS or BackgroundMessaging from [react-native-firebase](https://rnfirebase.io/messaging/usage#receiving-messages)-(Optional)(Android-only)-Listen-for-FCM-messages-in-the-background). You have to send a push to your application, like with Firebase for Android and with a library supporting PushKit pushes for iOS. -### PushKit +## PushKit Since iOS 13, you'll have to report the incoming calls that wakes up your application with a VoIP push. Add this in your `AppDelegate.m` if you're using VoIP pushes to wake up your application : @@ -673,18 +1169,34 @@ Since iOS 13, you'll have to report the incoming calls that wakes up your applic // NSString *handle = @"caller number here"; // NSDictionary *extra = [payload.dictionaryPayload valueForKeyPath:@"custom.path.to.data"]; /* use this to pass any special data (ie. from your notification) down to RN. Can also be `nil` */ - [RNCallKeep reportNewIncomingCall:uuid handle:handle handleType:@"generic" hasVideo:false localizedCallerName:callerName fromPushKit: YES payload:extra]; - - completion(); + [RNCallKeep reportNewIncomingCall: uuid + handle: handle + handleType: @"generic" + hasVideo: NO + localizedCallerName: callerName + supportsHolding: YES + supportsDTMF: YES + supportsGrouping: YES + supportsUngrouping: YES + fromPushKit: YES + payload: extra + withCompletionHandler: completion]; } ``` +## Android 11 + +Since Android 11, your application [requires to start a foregroundService](https://developer.android.com/about/versions/11/privacy/foreground-services) in order to access the microphone in background. +You'll need to upgrade your `compileSdkVersion` to `30` to be able to use this feature. + +You have to set the `foregroundService` key in the [`setup()`](#setup) method and add a `foregroundServiceType` in the [`AndroidManifest` file](docs/android-installation.md#android-common-step-installation). + ## Debug ### Android ``` -adb logcat *:S RNCallKeepModule:V +adb logcat *:S RNCallKeep:V ``` ## Troubleshooting diff --git a/actions.js b/actions.js index 2e5ff59e..fbbe4ca2 100644 --- a/actions.js +++ b/actions.js @@ -14,6 +14,12 @@ const RNCallKeepDidToggleHoldAction = 'RNCallKeepDidToggleHoldAction'; const RNCallKeepDidPerformDTMFAction = 'RNCallKeepDidPerformDTMFAction'; const RNCallKeepProviderReset = 'RNCallKeepProviderReset'; const RNCallKeepCheckReachability = 'RNCallKeepCheckReachability'; +const RNCallKeepDidLoadWithEvents = 'RNCallKeepDidLoadWithEvents'; +const RNCallKeepShowIncomingCallUi = 'RNCallKeepShowIncomingCallUi'; +const RNCallKeepOnSilenceIncomingCall = 'RNCallKeepOnSilenceIncomingCall'; +const RNCallKeepOnIncomingConnectionFailed = 'RNCallKeepOnIncomingConnectionFailed'; +const RNCallKeepDidChangeAudioRoute = 'RNCallKeepDidChangeAudioRoute'; +const RNCallKeepHasActiveCall = 'RNCallKeepHasActiveCall'; const isIOS = Platform.OS === 'ios'; const didReceiveStartCallAction = handler => { @@ -31,18 +37,33 @@ const answerCall = handler => const endCall = handler => eventEmitter.addListener(RNCallKeepPerformEndCallAction, (data) => handler(data)); +const didChangeAudioRoute = handler => + eventEmitter.addListener(RNCallKeepDidChangeAudioRoute, handler); + const didActivateAudioSession = handler => eventEmitter.addListener(RNCallKeepDidActivateAudioSession, handler); const didDeactivateAudioSession = handler => eventEmitter.addListener(RNCallKeepDidDeactivateAudioSession, handler); -const didDisplayIncomingCall = handler => - eventEmitter.addListener(RNCallKeepDidDisplayIncomingCall, (data) => handler(data)); +const didDisplayIncomingCall = handler => eventEmitter.addListener(RNCallKeepDidDisplayIncomingCall, data => { + // On Android the payload parameter is sent a String + // As it requires too much code on Android to convert it to WritableMap, let's do it here. + if (data.payload && typeof data.payload === 'string') { + try { + data.payload = JSON.parse(data.payload); + } catch (_) { + } + } + handler(data); +}); const didPerformSetMutedCallAction = handler => eventEmitter.addListener(RNCallKeepDidPerformSetMutedCallAction, (data) => handler(data)); +const onHasActiveCall = handler => + eventEmitter.addListener(RNCallKeepHasActiveCall, handler); + const didToggleHoldCallAction = handler => eventEmitter.addListener(RNCallKeepDidToggleHoldAction, handler); @@ -55,6 +76,20 @@ const didResetProvider = handler => const checkReachability = handler => eventEmitter.addListener(RNCallKeepCheckReachability, handler); +const didLoadWithEvents = handler => + eventEmitter.addListener(RNCallKeepDidLoadWithEvents, handler); + +const showIncomingCallUi = handler => + eventEmitter.addListener(RNCallKeepShowIncomingCallUi, (data) => handler(data)); + +const silenceIncomingCall = handler => + eventEmitter.addListener(RNCallKeepOnSilenceIncomingCall, (data) => handler(data)); + +const createIncomingConnectionFailed = handler => + eventEmitter.addListener(RNCallKeepOnIncomingConnectionFailed, (data) => handler(data)); + +export const emit = (eventName, payload) => eventEmitter.emit(eventName, payload); + export const listeners = { didReceiveStartCallAction, answerCall, @@ -67,4 +102,10 @@ export const listeners = { didPerformDTMFAction, didResetProvider, checkReachability, + didLoadWithEvents, + showIncomingCallUi, + silenceIncomingCall, + createIncomingConnectionFailed, + didChangeAudioRoute, + onHasActiveCall }; diff --git a/android/build.gradle b/android/build.gradle index eacca2ec..5a9971bf 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,7 +1,7 @@ buildscript { repositories { + mavenCentral() google() - jcenter() } dependencies { @@ -16,8 +16,7 @@ def safeExtGet(prop, fallback) { } android { - compileSdkVersion safeExtGet('compileSdkVersion', 23) - buildToolsVersion safeExtGet('buildToolsVersion', "23.0.1") + compileSdkVersion safeExtGet('compileSdkVersion', 28) defaultConfig { minSdkVersion safeExtGet('minSdkVersion', 23) @@ -33,4 +32,5 @@ repositories { dependencies { implementation 'com.facebook.react:react-native:+' + implementation "androidx.localbroadcastmanager:localbroadcastmanager:1.1.0" } diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 9eb5933f..fe2b6cce 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -2,5 +2,8 @@ - + + + diff --git a/android/src/main/java/io/wazo/callkeep/Constants.java b/android/src/main/java/io/wazo/callkeep/Constants.java new file mode 100644 index 00000000..5a8f7c6e --- /dev/null +++ b/android/src/main/java/io/wazo/callkeep/Constants.java @@ -0,0 +1,31 @@ +package io.wazo.callkeep; + +public class Constants { + public static final String ACTION_ANSWER_CALL = "ACTION_ANSWER_CALL"; + public static final String ACTION_AUDIO_SESSION = "ACTION_AUDIO_SESSION"; + public static final String ACTION_CHECK_REACHABILITY = "ACTION_CHECK_REACHABILITY"; + public static final String ACTION_DTMF_TONE = "ACTION_DTMF_TONE"; + public static final String ACTION_END_CALL = "ACTION_END_CALL"; + public static final String ACTION_HOLD_CALL = "ACTION_HOLD_CALL"; + public static final String ACTION_MUTE_CALL = "ACTION_MUTE_CALL"; + public static final String ACTION_ONGOING_CALL = "ACTION_ONGOING_CALL"; + public static final String ACTION_UNHOLD_CALL = "ACTION_UNHOLD_CALL"; + public static final String ACTION_UNMUTE_CALL = "ACTION_UNMUTE_CALL"; + public static final String ACTION_WAKE_APP = "ACTION_WAKE_APP"; + public static final String ACTION_SHOW_INCOMING_CALL_UI = "ACTION_SHOW_INCOMING_CALL_UI"; + public static final String ACTION_ON_SILENCE_INCOMING_CALL = "ACTION_ON_SILENCE_INCOMING_CALL"; + public static final String ACTION_ON_CREATE_CONNECTION_FAILED = "ACTION_ON_CREATE_CONNECTION_FAILED"; + public static final String ACTION_DID_CHANGE_AUDIO_ROUTE = "ACTION_DID_CHANGE_AUDIO_ROUTE"; + + + public static final String EXTRA_CALL_NUMBER = "EXTRA_CALL_NUMBER"; + public static final String EXTRA_CALL_NUMBER_SCHEMA = "EXTRA_CALL_NUMBER_SCHEMA"; + public static final String EXTRA_CALL_UUID = "EXTRA_CALL_UUID"; + public static final String EXTRA_CALLER_NAME = "EXTRA_CALLER_NAME"; + public static final String EXTRA_HAS_VIDEO = "EXTRA_HAS_VIDEO"; + public static final String EXTRA_PAYLOAD = "EXTRA_PAYLOAD"; + // Can't use telecom.EXTRA_DISABLE_ADD_CALL ... + public static final String EXTRA_DISABLE_ADD_CALL = "android.telecom.extra.DISABLE_ADD_CALL"; + + public static final int FOREGROUND_SERVICE_TYPE_MICROPHONE = 128; +} diff --git a/android/src/main/java/io/wazo/callkeep/MapUtils.java b/android/src/main/java/io/wazo/callkeep/MapUtils.java new file mode 100644 index 00000000..cc42ec82 --- /dev/null +++ b/android/src/main/java/io/wazo/callkeep/MapUtils.java @@ -0,0 +1,76 @@ +package io.wazo.callkeep; + +import java.util.Iterator; +import java.util.Map; + +import com.facebook.react.bridge.ReadableMapKeySetIterator; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.bridge.WritableNativeMap; + +import org.json.JSONObject; +import org.json.JSONException; + +public class MapUtils { + // @see https://gist.github.com/viperwarp/2beb6bbefcc268dee7ad + public static WritableMap convertJsonToMap(JSONObject jsonObject) throws JSONException { + WritableMap map = new WritableNativeMap(); + + Iterator iterator = jsonObject.keys(); + while (iterator.hasNext()) { + String key = iterator.next(); + Object value = jsonObject.get(key); + if (value instanceof JSONObject) { + map.putMap(key, convertJsonToMap((JSONObject) value)); + } else if (value instanceof Boolean) { + map.putBoolean(key, (Boolean) value); + } else if (value instanceof Integer) { + map.putInt(key, (Integer) value); + } else if (value instanceof Double) { + map.putDouble(key, (Double) value); + } else if (value instanceof String) { + map.putString(key, (String) value); + } else { + map.putString(key, value.toString()); + } + } + return map; + } + + public static JSONObject convertMapToJson(ReadableMap readableMap) throws JSONException { + JSONObject object = new JSONObject(); + ReadableMapKeySetIterator iterator = readableMap.keySetIterator(); + while (iterator.hasNextKey()) { + String key = iterator.nextKey(); + switch (readableMap.getType(key)) { + case Null: + object.put(key, JSONObject.NULL); + break; + case Boolean: + object.put(key, readableMap.getBoolean(key)); + break; + case Number: + object.put(key, readableMap.getDouble(key)); + break; + case String: + object.put(key, readableMap.getString(key)); + break; + case Map: + object.put(key, convertMapToJson(readableMap.getMap(key))); + break; + } + } + return object; + } + + public static WritableMap readableToWritableMap(ReadableMap readableMap) { + try { + JSONObject json = convertMapToJson(readableMap); + + return convertJsonToMap(json); + } catch (JSONException e) { + } + + return null; + } +} diff --git a/android/src/main/java/io/wazo/callkeep/RNCallKeepBackgroundMessagingService.java b/android/src/main/java/io/wazo/callkeep/RNCallKeepBackgroundMessagingService.java index 8770342f..c7cca5f2 100644 --- a/android/src/main/java/io/wazo/callkeep/RNCallKeepBackgroundMessagingService.java +++ b/android/src/main/java/io/wazo/callkeep/RNCallKeepBackgroundMessagingService.java @@ -25,10 +25,12 @@ import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.Arguments; import com.facebook.react.jstasks.HeadlessJsTaskConfig; +import com.facebook.react.jstasks.HeadlessJsTaskRetryPolicy; +import com.facebook.react.jstasks.LinearCountingRetryPolicy; -import static io.wazo.callkeep.RNCallKeepModule.EXTRA_CALLER_NAME; -import static io.wazo.callkeep.RNCallKeepModule.EXTRA_CALL_NUMBER; -import static io.wazo.callkeep.RNCallKeepModule.EXTRA_CALL_UUID; +import static io.wazo.callkeep.Constants.EXTRA_CALLER_NAME; +import static io.wazo.callkeep.Constants.EXTRA_CALL_NUMBER; +import static io.wazo.callkeep.Constants.EXTRA_CALL_UUID; import javax.annotation.Nullable; @@ -38,11 +40,17 @@ public class RNCallKeepBackgroundMessagingService extends HeadlessJsTaskService HeadlessJsTaskConfig getTaskConfig(Intent intent) { Bundle extras = intent.getExtras(); + HeadlessJsTaskRetryPolicy retryPolicy = new LinearCountingRetryPolicy( + 5, // Max number of retry attempts + 500 // Delay between each retry attempt + ); + return new HeadlessJsTaskConfig( "RNCallKeepBackgroundMessage", Arguments.fromBundle(extras), 60000, - false + false, + retryPolicy ); } } diff --git a/android/src/main/java/io/wazo/callkeep/RNCallKeepModule.java b/android/src/main/java/io/wazo/callkeep/RNCallKeepModule.java index 124de3ba..025480ac 100644 --- a/android/src/main/java/io/wazo/callkeep/RNCallKeepModule.java +++ b/android/src/main/java/io/wazo/callkeep/RNCallKeepModule.java @@ -16,7 +16,7 @@ */ package io.wazo.callkeep; - +import com.facebook.react.bridge.LifecycleEventListener; import android.Manifest; import android.app.Activity; import android.content.BroadcastReceiver; @@ -24,19 +24,24 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.SharedPreferences; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.Resources; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Icon; +import android.media.AudioDeviceInfo; +import android.media.AudioManager; import android.net.Uri; import android.os.Build; import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.ActivityCompat; -import android.support.v4.content.ContextCompat; -import android.support.v4.content.LocalBroadcastManager; +import android.os.Looper; +import android.view.WindowManager; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; import android.telecom.CallAudioState; import android.telecom.Connection; import android.telecom.DisconnectCause; @@ -44,6 +49,8 @@ import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; import android.telephony.TelephonyManager; +import android.telephony.TelephonyCallback; +import android.telephony.PhoneStateListener; import android.util.Log; import com.facebook.react.bridge.Arguments; @@ -54,8 +61,13 @@ import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; +import com.facebook.react.bridge.WritableNativeArray; +import com.facebook.react.bridge.WritableNativeMap; +import com.facebook.react.HeadlessJsTaskService; import com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEmitter; +import com.facebook.react.modules.permissions.PermissionsModule; import java.lang.reflect.Array; import java.util.ArrayList; @@ -65,47 +77,99 @@ import java.util.Map; import java.util.ResourceBundle; -import static android.support.v4.app.ActivityCompat.requestPermissions; +import org.json.JSONObject; +import org.json.JSONException; + +import static androidx.core.app.ActivityCompat.requestPermissions; + +import static io.wazo.callkeep.Constants.EXTRA_CALLER_NAME; +import static io.wazo.callkeep.Constants.EXTRA_CALL_UUID; +import static io.wazo.callkeep.Constants.EXTRA_CALL_NUMBER; +import static io.wazo.callkeep.Constants.EXTRA_HAS_VIDEO; +import static io.wazo.callkeep.Constants.EXTRA_PAYLOAD; +import static io.wazo.callkeep.Constants.ACTION_END_CALL; +import static io.wazo.callkeep.Constants.ACTION_ANSWER_CALL; +import static io.wazo.callkeep.Constants.ACTION_MUTE_CALL; +import static io.wazo.callkeep.Constants.ACTION_UNMUTE_CALL; +import static io.wazo.callkeep.Constants.ACTION_DTMF_TONE; +import static io.wazo.callkeep.Constants.ACTION_HOLD_CALL; +import static io.wazo.callkeep.Constants.ACTION_UNHOLD_CALL; +import static io.wazo.callkeep.Constants.ACTION_ONGOING_CALL; +import static io.wazo.callkeep.Constants.ACTION_AUDIO_SESSION; +import static io.wazo.callkeep.Constants.ACTION_CHECK_REACHABILITY; +import static io.wazo.callkeep.Constants.ACTION_WAKE_APP; +import static io.wazo.callkeep.Constants.ACTION_SHOW_INCOMING_CALL_UI; +import static io.wazo.callkeep.Constants.ACTION_ON_SILENCE_INCOMING_CALL; +import static io.wazo.callkeep.Constants.ACTION_ON_CREATE_CONNECTION_FAILED; +import static io.wazo.callkeep.Constants.ACTION_DID_CHANGE_AUDIO_ROUTE; // @see https://github.com/kbagchiGWC/voice-quickstart-android/blob/9a2aff7fbe0d0a5ae9457b48e9ad408740dfb968/exampleConnectionService/src/main/java/com/twilio/voice/examples/connectionservice/VoiceConnectionServiceActivity.java -public class RNCallKeepModule extends ReactContextBaseJavaModule { +public class RNCallKeepModule extends ReactContextBaseJavaModule implements LifecycleEventListener { public static final int REQUEST_READ_PHONE_STATE = 1337; public static final int REQUEST_REGISTER_CALL_PROVIDER = 394859; - public static final String CHECKING_PERMS = "CHECKING_PERMS"; - public static final String EXTRA_CALLER_NAME = "EXTRA_CALLER_NAME"; - public static final String EXTRA_CALL_UUID = "EXTRA_CALL_UUID"; - public static final String EXTRA_CALL_NUMBER = "EXTRA_CALL_NUMBER"; - public static final String ACTION_END_CALL = "ACTION_END_CALL"; - public static final String ACTION_ANSWER_CALL = "ACTION_ANSWER_CALL"; - public static final String ACTION_MUTE_CALL = "ACTION_MUTE_CALL"; - public static final String ACTION_UNMUTE_CALL = "ACTION_UNMUTE_CALL"; - public static final String ACTION_DTMF_TONE = "ACTION_DTMF_TONE"; - public static final String ACTION_HOLD_CALL = "ACTION_HOLD_CALL"; - public static final String ACTION_UNHOLD_CALL = "ACTION_UNHOLD_CALL"; - public static final String ACTION_ONGOING_CALL = "ACTION_ONGOING_CALL"; - public static final String ACTION_AUDIO_SESSION = "ACTION_AUDIO_SESSION"; - public static final String ACTION_CHECK_REACHABILITY = "ACTION_CHECK_REACHABILITY"; + public static RNCallKeepModule instance = null; private static final String E_ACTIVITY_DOES_NOT_EXIST = "E_ACTIVITY_DOES_NOT_EXIST"; private static final String REACT_NATIVE_MODULE_NAME = "RNCallKeep"; - private static final String[] permissions = { Manifest.permission.READ_PHONE_STATE, - Manifest.permission.CALL_PHONE, Manifest.permission.RECORD_AUDIO }; + private static String[] permissions = { + Build.VERSION.SDK_INT < 30 ? Manifest.permission.READ_PHONE_STATE : Manifest.permission.READ_PHONE_NUMBERS, + Manifest.permission.CALL_PHONE, + Manifest.permission.RECORD_AUDIO + }; - private static final String TAG = "RNCK:RNCallKeepModule"; + private static final String TAG = "RNCallKeep"; private static TelecomManager telecomManager; + private LegacyCallStateListener legacyCallStateListener; + private CallStateListener callStateListener; private static TelephonyManager telephonyManager; private static Promise hasPhoneAccountPromise; private ReactApplicationContext reactContext; public static PhoneAccountHandle handle; private boolean isReceiverRegistered = false; private VoiceBroadcastReceiver voiceBroadcastReceiver; - private ReadableMap _settings; + private static WritableMap _settings; + private WritableNativeArray delayedEvents; + private boolean hasListeners = false; + private boolean hasActiveCall = false; + + public static RNCallKeepModule getInstance(ReactApplicationContext reactContext, boolean realContext) { + if (instance == null) { + Log.d(TAG, "[RNCallKeepModule] getInstance : " + (reactContext == null ? "null" : "ok")); + instance = new RNCallKeepModule(reactContext); + instance.registerReceiver(); + instance.fetchStoredSettings(reactContext); + } + if (realContext) { + instance.setContext(reactContext); + } + return instance; + } - public RNCallKeepModule(ReactApplicationContext reactContext) { + public static WritableMap getSettings(@Nullable Context context) { + if (_settings == null) { + fetchStoredSettings(context); + } + + return _settings; + } + + private RNCallKeepModule(ReactApplicationContext reactContext) { super(reactContext); + // This line for listening to the Activity Lifecycle Events so we can end the calls onDestroy + reactContext.addLifecycleEventListener(this); + Log.d(TAG, "[RNCallKeepModule] constructor"); this.reactContext = reactContext; + delayedEvents = new WritableNativeArray(); + } + + private boolean isSelfManaged() { + try { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && _settings.hasKey("selfManaged") && _settings.getBoolean("selfManaged"); + } catch (Exception e) { + return false; + } } @Override @@ -113,26 +177,280 @@ public String getName() { return REACT_NATIVE_MODULE_NAME; } + public void setContext(ReactApplicationContext reactContext) { + Log.d(TAG, "[RNCallKeepModule] updating react context"); + this.reactContext = reactContext; + } + + public ReactApplicationContext getContext() { + return this.reactContext; + } + + public void reportNewIncomingCall(String uuid, String number, String callerName, boolean hasVideo, String payload) { + Log.d(TAG, "[RNCallKeepModule] reportNewIncomingCall, uuid: " + uuid + ", number: " + number + ", callerName: " + callerName); + + this.displayIncomingCall(uuid, number, callerName, hasVideo); + + // Send event to JS + WritableMap args = Arguments.createMap(); + args.putString("handle", number); + args.putString("callUUID", uuid); + args.putString("name", callerName); + args.putString("hasVideo", String.valueOf(hasVideo)); + if (payload != null) { + args.putString("payload", payload); + } + sendEventToJS("RNCallKeepDidDisplayIncomingCall", args); + } + + public void startObserving() { + int count = delayedEvents.size(); + Log.d(TAG, "[RNCallKeepModule] startObserving, event count: " + count); + if (count > 0) { + this.reactContext.getJSModule(RCTDeviceEventEmitter.class).emit("RNCallKeepDidLoadWithEvents", delayedEvents); + delayedEvents = new WritableNativeArray(); + } + } + + public void initializeTelecomManager() { + Context context = this.getAppContext(); + if (context == null) { + Log.w(TAG, "[RNCallKeepModule][initializeTelecomManager] no react context found."); + return; + } + ComponentName cName = new ComponentName(context, VoiceConnectionService.class); + String appName = this.getApplicationName(context); + + handle = new PhoneAccountHandle(cName, appName); + telecomManager = (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE); + } + + + + /** + * Monitors and logs phone call activities, and shows the phone state + */ + private class LegacyCallStateListener extends PhoneStateListener { + + @Override + public void onCallStateChanged(int state, String incomingNumber) { + switch (state) { + case TelephonyManager.CALL_STATE_RINGING: + // Incoming call is ringing (not used for outgoing call). + break; + case TelephonyManager.CALL_STATE_OFFHOOK: + // Phone call is active -- off the hook. + // Check if there is active call in native + boolean isInManagedCall = RNCallKeepModule.this.checkIsInManagedCall(); + + // Only let the JS side know if there is active app call & active native call + if(RNCallKeepModule.this.hasActiveCall && isInManagedCall){ + WritableMap args = Arguments.createMap(); + RNCallKeepModule.this.sendEventToJS("RNCallKeepHasActiveCall",args); + }else if(VoiceConnectionService.currentConnections.size() > 0){ + // Will enter here for the first time to mark the app has active call + RNCallKeepModule.this.hasActiveCall = true; + } + break; + case TelephonyManager.CALL_STATE_IDLE: + // Phone is idle before and after phone call. + // If running on version older than 19 (KitKat), + // restart activity when phone call ends. + break; + default: + break; + } + } + } + + private class CallStateListener extends TelephonyCallback implements TelephonyCallback.CallStateListener { + + @Override + public void onCallStateChanged(int state) { + switch (state) { + case TelephonyManager.CALL_STATE_RINGING: + // Incoming call is ringing (not used for outgoing call). + break; + case TelephonyManager.CALL_STATE_OFFHOOK: + // Phone call is active -- off the hook. + + // Check if there is active call in native + boolean isInManagedCall = RNCallKeepModule.this.checkIsInManagedCall(); + + // Only let the JS side know if there is active app call & active native call + if(RNCallKeepModule.this.hasActiveCall && isInManagedCall){ + WritableMap args = Arguments.createMap(); + RNCallKeepModule.this.sendEventToJS("RNCallKeepHasActiveCall",args); + }else if(VoiceConnectionService.currentConnections.size() > 0){ + // Will enter here for the first time to mark the app has active call + RNCallKeepModule.this.hasActiveCall = true; + } + break; + case TelephonyManager.CALL_STATE_IDLE: + // Phone is idle before and after phone call. + // If running on version older than 19 (KitKat), + // restart activity when phone call ends. + break; + default: + break; + } + } + } + + public void stopListenToNativeCallsState() { + Log.d(TAG, "[RNCallKeepModule] stopListenToNativeCallsState"); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && callStateListener !=null){ + telephonyManager.unregisterTelephonyCallback(callStateListener); + } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S && legacyCallStateListener != null){ + telephonyManager.listen(legacyCallStateListener, PhoneStateListener.LISTEN_NONE); + Looper.myLooper().quit(); + } + } + + public void listenToNativeCallsState() { + Log.d(TAG, "[RNCallKeepModule] listenToNativeCallsState"); + Context context = this.getAppContext(); + int permissionCheck = ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE); + + if (permissionCheck == PackageManager.PERMISSION_GRANTED) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + callStateListener = new CallStateListener(); + telephonyManager.registerTelephonyCallback(context.getMainExecutor(),callStateListener); + } else { + if (Looper.myLooper() == null) { + Looper.prepare(); + } + legacyCallStateListener = new LegacyCallStateListener(); + telephonyManager.listen(legacyCallStateListener, PhoneStateListener.LISTEN_CALL_STATE); + Looper.loop(); + } + } + } + + public boolean checkIsInManagedCall() { + Context context = this.getAppContext(); + int permissionCheck = ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE); + + if (permissionCheck == PackageManager.PERMISSION_GRANTED) { + return telecomManager.isInManagedCall(); + } + return false; + } + + @ReactMethod + public void checkIsInManagedCall(Promise promise) { + boolean isInManagedCall = this.checkIsInManagedCall(); + promise.resolve(isInManagedCall); + } + + @ReactMethod + public void setSettings(ReadableMap options) { + Log.d(TAG, "[RNCallKeepModule] setSettings : " + options); + if (options == null) { + return; + } + _settings = storeSettings(options); + } + + @ReactMethod + public void addListener(String eventName) { + // Keep: Required for RN built in Event Emitter Calls. + } + + @ReactMethod + public void removeListeners(Integer count) { + // Keep: Required for RN built in Event Emitter Calls. + } + @ReactMethod public void setup(ReadableMap options) { + Log.d(TAG, "[RNCallKeepModule] setup : " + options); + VoiceConnectionService.setAvailable(false); - this._settings = options; + VoiceConnectionService.setInitialized(true); + this.setSettings(options); + + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (isSelfManaged()) { + Log.d(TAG, "[RNCallKeepModule] API Version supports self managed, and is enabled in setup"); + } + else { + Log.d(TAG, "[RNCallKeepModule] API Version supports self managed, but it is not enabled in setup"); + } + } + + // If we're running in self managed mode we need fewer permissions. + if(isSelfManaged()) { + Log.d(TAG, "[RNCallKeepModule] setup, adding RECORD_AUDIO in permissions in self managed"); + permissions = new String[]{ Manifest.permission.RECORD_AUDIO }; + } if (isConnectionServiceAvailable()) { - this.registerPhoneAccount(this.getAppContext()); - voiceBroadcastReceiver = new VoiceBroadcastReceiver(); - registerReceiver(); + this.registerPhoneAccount(options); + this.registerEvents(); + this.startObserving(); VoiceConnectionService.setAvailable(true); } } + @ReactMethod + public void registerPhoneAccount(ReadableMap options) { + setSettings(options); + + if (!isConnectionServiceAvailable()) { + Log.w(TAG, "[RNCallKeepModule] registerPhoneAccount ignored due to no ConnectionService"); + return; + } + + Log.d(TAG, "[RNCallKeepModule] registerPhoneAccount"); + Context context = this.getAppContext(); + if (context == null) { + Log.w(TAG, "[RNCallKeepModule][registerPhoneAccount] no react context found."); + return; + } + + this.registerPhoneAccount(context); + } + + @ReactMethod + public void registerEvents() { + if (!isConnectionServiceAvailable()) { + Log.w(TAG, "[RNCallKeepModule] registerEvents ignored due to no ConnectionService"); + return; + } + + Log.d(TAG, "[RNCallKeepModule] registerEvents"); + + this.hasListeners = true; + this.startObserving(); + VoiceConnectionService.setPhoneAccountHandle(handle); + } + + @ReactMethod + public void unregisterEvents() { + Log.d(TAG, "[RNCallKeepModule] unregisterEvents"); + + this.hasListeners = false; + } + @ReactMethod public void displayIncomingCall(String uuid, String number, String callerName) { + this.displayIncomingCall(uuid, number, callerName, false, null); + } + + @ReactMethod + public void displayIncomingCall(String uuid, String number, String callerName, boolean hasVideo) { + this.displayIncomingCall(uuid, number, callerName, hasVideo, null); + } + + public void displayIncomingCall(String uuid, String number, String callerName, boolean hasVideo, @Nullable Bundle payload) { if (!isConnectionServiceAvailable() || !hasPhoneAccount()) { + Log.w(TAG, "[RNCallKeepModule] displayIncomingCall ignored due to no ConnectionService or no phone account"); return; } - Log.d(TAG, "displayIncomingCall number: " + number + ", callerName: " + callerName); + Log.d(TAG, "[RNCallKeepModule] displayIncomingCall, uuid: " + uuid + ", number: " + number + ", callerName: " + callerName + ", hasVideo: " + hasVideo + ", payload: " + payload); Bundle extras = new Bundle(); Uri uri = Uri.fromParts(PhoneAccount.SCHEME_TEL, number, null); @@ -140,18 +458,25 @@ public void displayIncomingCall(String uuid, String number, String callerName) { extras.putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, uri); extras.putString(EXTRA_CALLER_NAME, callerName); extras.putString(EXTRA_CALL_UUID, uuid); - + extras.putString(EXTRA_HAS_VIDEO, String.valueOf(hasVideo)); + if (payload != null) { + extras.putBundle(EXTRA_PAYLOAD, payload); + } + this.listenToNativeCallsState(); telecomManager.addNewIncomingCall(handle, extras); } @ReactMethod public void answerIncomingCall(String uuid) { + Log.d(TAG, "[RNCallKeepModule] answerIncomingCall, uuid: " + uuid); if (!isConnectionServiceAvailable() || !hasPhoneAccount()) { + Log.w(TAG, "[RNCallKeepModule] answerIncomingCall ignored due to no ConnectionService or no phone account"); return; } Connection conn = VoiceConnectionService.getConnection(uuid); if (conn == null) { + Log.w(TAG, "[RNCallKeepModule] answerIncomingCall ignored because no connection found, uuid: " + uuid); return; } @@ -160,12 +485,22 @@ public void answerIncomingCall(String uuid) { @ReactMethod public void startCall(String uuid, String number, String callerName) { + this.startCall(uuid, number, callerName, false, null); + } + + @ReactMethod + public void startCall(String uuid, String number, String callerName, boolean hasVideo) { + this.startCall(uuid, number, callerName, hasVideo, null); + } + + public void startCall(String uuid, String number, String callerName, boolean hasVideo, @Nullable Bundle payload) { + Log.d(TAG, "[RNCallKeepModule] startCall called, uuid: " + uuid + ", number: " + number + ", callerName: " + callerName + ", payload: " + payload); + if (!isConnectionServiceAvailable() || !hasPhoneAccount() || !hasPermissions() || number == null) { + Log.w(TAG, "[RNCallKeepModule] startCall ignored: " + isConnectionServiceAvailable() + ", " + hasPhoneAccount() + ", " + hasPermissions() + ", " + number); return; } - Log.d(TAG, "startCall number: " + number + ", callerName: " + callerName); - Bundle extras = new Bundle(); Uri uri = Uri.fromParts(PhoneAccount.SCHEME_TEL, number, null); @@ -173,55 +508,74 @@ public void startCall(String uuid, String number, String callerName) { callExtras.putString(EXTRA_CALLER_NAME, callerName); callExtras.putString(EXTRA_CALL_UUID, uuid); callExtras.putString(EXTRA_CALL_NUMBER, number); + callExtras.putString(EXTRA_HAS_VIDEO, String.valueOf(hasVideo)); + if (payload != null) { + callExtras.putBundle(EXTRA_PAYLOAD, payload); + } extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, handle); extras.putParcelable(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, callExtras); + Log.d(TAG, "[RNCallKeepModule] startCall, uuid: " + uuid); + this.listenToNativeCallsState(); telecomManager.placeCall(uri, extras); } @ReactMethod public void endCall(String uuid) { - Log.d(TAG, "endCall called"); + Log.d(TAG, "[RNCallKeepModule] endCall called, uuid: " + uuid); if (!isConnectionServiceAvailable() || !hasPhoneAccount()) { + Log.w(TAG, "[RNCallKeepModule] endCall ignored due to no ConnectionService or no phone account"); return; } Connection conn = VoiceConnectionService.getConnection(uuid); if (conn == null) { + Log.w(TAG, "[RNCallKeepModule] endCall ignored because no connection found, uuid: " + uuid); return; } + Context context = this.getAppContext(); + AudioManager audioManager = (AudioManager) context.getSystemService(context.AUDIO_SERVICE); + audioManager.setMode(0); conn.onDisconnect(); - - Log.d(TAG, "endCall executed"); + this.stopListenToNativeCallsState(); + this.hasActiveCall = false; + Log.d(TAG, "[RNCallKeepModule] endCall executed, uuid: " + uuid); } @ReactMethod public void endAllCalls() { - Log.d(TAG, "endAllCalls called"); + Log.d(TAG, "[RNCallKeepModule] endAllCalls called"); if (!isConnectionServiceAvailable() || !hasPhoneAccount()) { + Log.w(TAG, "[RNCallKeepModule] endAllCalls ignored due to no ConnectionService or no phone account"); return; } - Map currentConnections = VoiceConnectionService.currentConnections; - for (Map.Entry connectionEntry : currentConnections.entrySet()) { + ArrayList> connections = + new ArrayList>(VoiceConnectionService.currentConnections.entrySet()); + for (Map.Entry connectionEntry : connections) { Connection connectionToEnd = connectionEntry.getValue(); connectionToEnd.onDisconnect(); } - - Log.d(TAG, "endAllCalls executed"); + this.stopListenToNativeCallsState(); + this.hasActiveCall = false; + Log.d(TAG, "[RNCallKeepModule] endAllCalls executed"); } @ReactMethod public void checkPhoneAccountPermission(ReadableArray optionalPermissions, Promise promise) { - Activity currentActivity = this.getCurrentActivity(); + Activity currentActivity = this.getCurrentReactActivity(); if (!isConnectionServiceAvailable()) { - promise.reject(E_ACTIVITY_DOES_NOT_EXIST, "ConnectionService not available for this version of Android."); + String error = "ConnectionService not available for this version of Android."; + Log.w(TAG, "[RNCallKeepModule] checkPhoneAccountPermission error " + error); + promise.reject(E_ACTIVITY_DOES_NOT_EXIST, error); return; } if (currentActivity == null) { - promise.reject(E_ACTIVITY_DOES_NOT_EXIST, "Activity doesn't exist"); + String error = "Activity doesn't exist"; + Log.w(TAG, "[RNCallKeepModule] checkPhoneAccountPermission error " + error); + promise.reject(E_ACTIVITY_DOES_NOT_EXIST, error); return; } String[] optionalPermsArr = new String[optionalPermissions.size()]; @@ -229,14 +583,84 @@ public void checkPhoneAccountPermission(ReadableArray optionalPermissions, Promi optionalPermsArr[i] = optionalPermissions.getString(i); } - String[] allPermissions = Arrays.copyOf(permissions, permissions.length + optionalPermsArr.length); + final String[] allPermissions = Arrays.copyOf(permissions, permissions.length + optionalPermsArr.length); System.arraycopy(optionalPermsArr, 0, allPermissions, permissions.length, optionalPermsArr.length); hasPhoneAccountPromise = promise; if (!this.hasPermissions()) { - requestPermissions(currentActivity, allPermissions, REQUEST_READ_PHONE_STATE); - return; + WritableArray allPermissionaw = Arguments.createArray(); + for (String allPermission : allPermissions) { + allPermissionaw.pushString(allPermission); + } + + this.reactContext + .getNativeModule(PermissionsModule.class) + .requestMultiplePermissions(allPermissionaw, new Promise() { + @Override + public void resolve(@Nullable Object value) { + WritableMap grantedPermission = (WritableMap) value; + int[] grantedResult = new int[allPermissions.length]; + for (int i=0; i> connections = + new ArrayList>(VoiceConnectionService.currentConnections.entrySet()); + for (Map.Entry connectionEntry : connections) { + Connection connectionToEnd = connectionEntry.getValue(); + connectionToEnd.onDisconnect(); + } + this.stopListenToNativeCallsState(); + Log.d(TAG, "[RNCallKeepModule] onHostDestroy executed"); + // This line will kill the android process after ending all calls + android.os.Process.killProcess(android.os.Process.myPid()); + } + @ReactMethod public void rejectCall(String uuid) { + Log.d(TAG, "[RNCallKeepModule] rejectCall, uuid: " + uuid); if (!isConnectionServiceAvailable() || !hasPhoneAccount()) { + Log.w(TAG, "[RNCallKeepModule] rejectCall ignored due to no ConnectionService or no phone account"); return; } Connection conn = VoiceConnectionService.getConnection(uuid); if (conn == null) { + Log.w(TAG, "[RNCallKeepModule] rejectCall ignored because no connection found, uuid: " + uuid); return; } - + this.stopListenToNativeCallsState(); conn.onReject(); } + @ReactMethod + public void setConnectionState(String uuid, int state) { + Log.d(TAG, "[RNCallKeepModule] setConnectionState, uuid: " + uuid + ", state :" + state); + if (!isConnectionServiceAvailable() || !hasPhoneAccount()) { + Log.w(TAG, "[RNCallKeepModule] String ignored due to no ConnectionService or no phone account"); + return; + } + + VoiceConnectionService.setState(uuid, state); + } + @ReactMethod public void setMutedCall(String uuid, boolean shouldMute) { + Log.d(TAG, "[RNCallKeepModule] setMutedCall, uuid: " + uuid + ", shouldMute: " + (shouldMute ? "true" : "false")); Connection conn = VoiceConnectionService.getConnection(uuid); if (conn == null) { + Log.w(TAG, "[RNCallKeepModule] setMutedCall ignored because no connection found, uuid: " + uuid); return; } @@ -319,11 +807,128 @@ public void setMutedCall(String uuid, boolean shouldMute) { } conn.onCallAudioStateChanged(newAudioState); } + /** + * toggle audio route for speaker via connection service function + * @param uuid + * @param routeSpeaker + */ + @ReactMethod + public void toggleAudioRouteSpeaker(String uuid, boolean routeSpeaker) { + Log.d(TAG, "[RNCallKeepModule] toggleAudioRouteSpeaker, uuid: " + uuid + ", routeSpeaker: " + (routeSpeaker ? "true" : "false")); + VoiceConnection conn = (VoiceConnection) VoiceConnectionService.getConnection(uuid); + if (conn == null) { + Log.w(TAG, "[RNCallKeepModule] toggleAudioRouteSpeaker ignored because no connection found, uuid: " + uuid); + return; + } + if (routeSpeaker) { + conn.setAudioRoute(CallAudioState.ROUTE_SPEAKER); + } else { + conn.setAudioRoute(CallAudioState.ROUTE_EARPIECE); + } + } + + @ReactMethod + public void setAudioRoute(String uuid, String audioRoute, Promise promise){ + try { + VoiceConnection conn = (VoiceConnection) VoiceConnectionService.getConnection(uuid); + if (conn == null) { + return; + } + if(audioRoute.equals("Bluetooth")) { + Log.d(TAG,"[RNCallKeepModule] setting audio route: Bluetooth"); + conn.setAudioRoute(CallAudioState.ROUTE_BLUETOOTH); + promise.resolve(true); + return; + } + if(audioRoute.equals("Headset")) { + Log.d(TAG,"[RNCallKeepModule] setting audio route: Headset"); + conn.setAudioRoute(CallAudioState.ROUTE_WIRED_HEADSET); + promise.resolve(true); + return; + } + if(audioRoute.equals("Speaker")) { + Log.d(TAG,"[RNCallKeepModule] setting audio route: Speaker"); + conn.setAudioRoute(CallAudioState.ROUTE_SPEAKER); + promise.resolve(true); + return; + } + Log.d(TAG,"[RNCallKeepModule] setting audio route: Wired/Earpiece"); + conn.setAudioRoute(CallAudioState.ROUTE_WIRED_OR_EARPIECE); + promise.resolve(true); + } catch (Exception e) { + promise.reject("SetAudioRoute", e.getMessage()); + } + } + + @ReactMethod + public void getAudioRoutes(Promise promise){ + try { + Context context = this.getAppContext(); + if (context == null) { + Log.w(TAG, "[RNCallKeepModule][getAudioRoutes] no react context found."); + promise.reject("No react context found to list audio routes"); + return; + } + AudioManager audioManager = (AudioManager) context.getSystemService(context.AUDIO_SERVICE); + WritableArray devices = Arguments.createArray(); + ArrayList typeChecker = new ArrayList<>(); + AudioDeviceInfo[] audioDeviceInfo = audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS + AudioManager.GET_DEVICES_OUTPUTS); + String selectedAudioRoute = getSelectedAudioRoute(audioManager); + for (AudioDeviceInfo device : audioDeviceInfo){ + String type = getAudioRouteType(device.getType()); + if(type != null && !typeChecker.contains(type)) { + WritableMap deviceInfo = Arguments.createMap(); + deviceInfo.putString("name", type); + deviceInfo.putString("type", type); + if(type.equals(selectedAudioRoute)) { + deviceInfo.putBoolean("selected", true); + } + typeChecker.add(type); + devices.pushMap(deviceInfo); + } + } + promise.resolve(devices); + } catch(Exception e) { + promise.reject("GetAudioRoutes Error", e.getMessage()); + } + } + + private String getAudioRouteType(int type){ + switch (type){ + case(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP): + case(AudioDeviceInfo.TYPE_BLUETOOTH_SCO): + return "Bluetooth"; + case(AudioDeviceInfo.TYPE_WIRED_HEADPHONES): + case(AudioDeviceInfo.TYPE_WIRED_HEADSET): + return "Headset"; + case(AudioDeviceInfo.TYPE_BUILTIN_MIC): + return "Phone"; + case(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER): + return "Speaker"; + default: + return null; + } + } + + private String getSelectedAudioRoute(AudioManager audioManager){ + if(audioManager.isBluetoothScoOn()){ + return "Bluetooth"; + } + if(audioManager.isSpeakerphoneOn()){ + return "Speaker"; + } + if(audioManager.isWiredHeadsetOn()){ + return "Headset"; + } + return "Phone"; + } @ReactMethod public void sendDTMF(String uuid, String key) { + Log.d(TAG, "[RNCallKeepModule] sendDTMF, uuid: " + uuid + ", key: " + key); Connection conn = VoiceConnectionService.getConnection(uuid); if (conn == null) { + Log.w(TAG, "[RNCallKeepModule] sendDTMF ignored because no connection found, uuid: " + uuid); return; } char dtmf = key.charAt(0); @@ -332,8 +937,10 @@ public void sendDTMF(String uuid, String key) { @ReactMethod public void updateDisplay(String uuid, String displayName, String uri) { + Log.d(TAG, "[RNCallKeepModule] updateDisplay, uuid: " + uuid + ", displayName: " + displayName+ ", uri: " + uri); Connection conn = VoiceConnectionService.getConnection(uuid); if (conn == null) { + Log.w(TAG, "[RNCallKeepModule] updateDisplay ignored because no connection found, uuid: " + uuid); return; } @@ -343,6 +950,10 @@ public void updateDisplay(String uuid, String displayName, String uri) { @ReactMethod public void hasPhoneAccount(Promise promise) { + if (telecomManager == null) { + this.initializeTelecomManager(); + } + promise.resolve(hasPhoneAccount()); } @@ -361,6 +972,26 @@ public void setAvailable(Boolean active) { VoiceConnectionService.setAvailable(active); } + @ReactMethod + public void setForegroundServiceSettings(ReadableMap foregroundServerSettings) { + if (foregroundServerSettings == null) { + return; + } + + // Retrieve settings and set the `foregroundService` value + WritableMap settings = getSettings(null); + if (settings != null) { + settings.putMap("foregroundService", MapUtils.readableToWritableMap(foregroundServerSettings)); + } + + setSettings(settings); + } + + @ReactMethod + public void canMakeMultipleCalls(Boolean allow) { + VoiceConnectionService.setCanMakeMultipleCalls(allow); + } + @ReactMethod public void setReachable() { VoiceConnectionService.setReachable(); @@ -368,8 +999,10 @@ public void setReachable() { @ReactMethod public void setCurrentCallActive(String uuid) { + Log.d(TAG, "[RNCallKeepModule] setCurrentCallActive, uuid: " + uuid); Connection conn = VoiceConnectionService.getConnection(uuid); if (conn == null) { + Log.w(TAG, "[RNCallKeepModule] setCurrentCallActive ignored because no connection found, uuid: " + uuid); return; } @@ -379,17 +1012,25 @@ public void setCurrentCallActive(String uuid) { @ReactMethod public void openPhoneAccounts() { + Log.d(TAG, "[RNCallKeepModule] openPhoneAccounts"); if (!isConnectionServiceAvailable()) { + Log.w(TAG, "[RNCallKeepModule] openPhoneAccounts ignored due to no ConnectionService"); return; } - if (Build.MANUFACTURER.equalsIgnoreCase("Samsung")) { + if (Build.MANUFACTURER.equalsIgnoreCase("Samsung") || Build.MANUFACTURER.equalsIgnoreCase("OnePlus")) { Intent intent = new Intent(); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK); intent.setComponent(new ComponentName("com.android.server.telecom", "com.android.server.telecom.settings.EnableAccountPreferenceActivity")); - this.getAppContext().startActivity(intent); + Context context = this.getAppContext(); + if (context == null) { + Log.w(TAG, "[RNCallKeepModule][openPhoneAccounts] no react context found."); + return; + } + + context.startActivity(intent); return; } @@ -398,45 +1039,101 @@ public void openPhoneAccounts() { @ReactMethod public void openPhoneAccountSettings() { + Log.d(TAG, "[RNCallKeepModule] openPhoneAccountSettings"); if (!isConnectionServiceAvailable()) { + Log.w(TAG, "[RNCallKeepModule] openPhoneAccountSettings ignored due to no ConnectionService"); return; } Intent intent = new Intent(TelecomManager.ACTION_CHANGE_PHONE_ACCOUNTS); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK); - this.getAppContext().startActivity(intent); + Context context = this.getAppContext(); + if (context == null) { + Log.w(TAG, "[RNCallKeepModule][openPhoneAccountSettings] no react context found."); + return; + } + context.startActivity(intent); } - @ReactMethod public static Boolean isConnectionServiceAvailable() { // PhoneAccount is available since api level 23 return Build.VERSION.SDK_INT >= 23; } + @ReactMethod + public void isConnectionServiceAvailable(Promise promise) { + promise.resolve(isConnectionServiceAvailable()); + } + + @ReactMethod + public void checkPhoneAccountEnabled(Promise promise) { + promise.resolve(hasPhoneAccount()); + } + @ReactMethod public void backToForeground() { Context context = getAppContext(); + if (context == null) { + Log.w(TAG, "[RNCallKeepModule][backToForeground] no react context found."); + return; + } String packageName = context.getApplicationContext().getPackageName(); Intent focusIntent = context.getPackageManager().getLaunchIntentForPackage(packageName).cloneFilter(); + Activity activity = getCurrentReactActivity(); + boolean isOpened = activity != null; + Log.d(TAG, "[RNCallKeepModule] backToForeground, app isOpened ?" + (isOpened ? "true" : "false")); - focusIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); + if (isOpened) { + focusIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); + activity.startActivity(focusIntent); + } else { + focusIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK + + WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED + + WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD + + WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); - Activity activity = getCurrentActivity(); - activity.startActivity(focusIntent); + getReactApplicationContext().startActivity(focusIntent); + } + } + + public static void onRequestPermissionsResult(int requestCode, String[] grantedPermissions, int[] grantResults) { + int permissionsIndex = 0; + List permsList = Arrays.asList(permissions); + for (int result : grantResults) { + if (permsList.contains(grantedPermissions[permissionsIndex]) && result != PackageManager.PERMISSION_GRANTED) { + hasPhoneAccountPromise.resolve(false); + return; + } + permissionsIndex++; + } + hasPhoneAccountPromise.resolve(true); + } + + public Activity getCurrentReactActivity() { + return this.reactContext.getCurrentActivity(); } private void registerPhoneAccount(Context appContext) { if (!isConnectionServiceAvailable()) { + Log.w(TAG, "[RNCallKeepModule] registerPhoneAccount ignored due to no ConnectionService"); return; } - ComponentName cName = new ComponentName(this.getAppContext(), VoiceConnectionService.class); - String appName = this.getApplicationName(appContext); - - handle = new PhoneAccountHandle(cName, appName); + this.initializeTelecomManager(); + Context context = this.getAppContext(); + if (context == null) { + Log.w(TAG, "[RNCallKeepModule][registerPhoneAccount] no react context found."); + return; + } + String appName = this.getApplicationName(context); - PhoneAccount.Builder builder = new PhoneAccount.Builder(handle, appName) - .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER); + PhoneAccount.Builder builder = new PhoneAccount.Builder(handle, appName); + if (isSelfManaged()) { + builder.setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED); + } + else { + builder.setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER); + } if (_settings != null && _settings.hasKey("imageName")) { int identifier = appContext.getResources().getIdentifier(_settings.getString("imageName"), "drawable", appContext.getPackageName()); @@ -446,14 +1143,27 @@ private void registerPhoneAccount(Context appContext) { PhoneAccount account = builder.build(); - telephonyManager = (TelephonyManager) this.getAppContext().getSystemService(Context.TELEPHONY_SERVICE); - telecomManager = (TelecomManager) this.getAppContext().getSystemService(Context.TELECOM_SERVICE); + telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); telecomManager.registerPhoneAccount(account); } - private void sendEventToJS(String eventName, @Nullable WritableMap params) { - this.reactContext.getJSModule(RCTDeviceEventEmitter.class).emit(eventName, params); + public void sendEventToJS(String eventName, @Nullable WritableMap params) { + boolean isBoundToJS = this.reactContext.hasActiveCatalystInstance(); + Log.v(TAG, "[RNCallKeepModule] sendEventToJS, eventName: " + eventName + ", bound: " + isBoundToJS + ", hasListeners: " + hasListeners + " args : " + (params != null ? params.toString() : "null")); + + if (isBoundToJS && hasListeners) { + this.reactContext.getJSModule(RCTDeviceEventEmitter.class).emit(eventName, params); + } else { + WritableMap data = Arguments.createMap(); + if (params == null) { + params = Arguments.createMap(); + } + + data.putString("name", eventName); + data.putMap("data", params); + delayedEvents.pushMap(data); + } } private String getApplicationName(Context appContext) { @@ -464,11 +1174,11 @@ private String getApplicationName(Context appContext) { } private Boolean hasPermissions() { - Activity currentActivity = this.getCurrentActivity(); + ReactApplicationContext context = getContext(); boolean hasPermissions = true; for (String permission : permissions) { - int permissionCheck = ContextCompat.checkSelfPermission(currentActivity, permission); + int permissionCheck = ContextCompat.checkSelfPermission(context, permission); if (permissionCheck != PackageManager.PERMISSION_GRANTED) { hasPermissions = false; } @@ -477,12 +1187,24 @@ private Boolean hasPermissions() { return hasPermissions; } - private static boolean hasPhoneAccount() { - return isConnectionServiceAvailable() && telecomManager != null && telecomManager.getPhoneAccount(handle).isEnabled(); + private boolean hasPhoneAccount() { + if (telecomManager == null) { + this.initializeTelecomManager(); + } + + if (isSelfManaged()) { + return true; + } + + return isConnectionServiceAvailable() && telecomManager != null && + hasPermissions() && telecomManager.getPhoneAccount(handle) != null && + telecomManager.getPhoneAccount(handle).isEnabled(); } - private void registerReceiver() { + protected void registerReceiver() { if (!isReceiverRegistered) { + isReceiverRegistered = true; + voiceBroadcastReceiver = new VoiceBroadcastReceiver(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(ACTION_END_CALL); intentFilter.addAction(ACTION_ANSWER_CALL); @@ -494,26 +1216,67 @@ private void registerReceiver() { intentFilter.addAction(ACTION_ONGOING_CALL); intentFilter.addAction(ACTION_AUDIO_SESSION); intentFilter.addAction(ACTION_CHECK_REACHABILITY); - LocalBroadcastManager.getInstance(this.reactContext).registerReceiver(voiceBroadcastReceiver, intentFilter); - isReceiverRegistered = true; + intentFilter.addAction(ACTION_SHOW_INCOMING_CALL_UI); + intentFilter.addAction(ACTION_ON_SILENCE_INCOMING_CALL); + intentFilter.addAction(ACTION_ON_CREATE_CONNECTION_FAILED); + intentFilter.addAction(ACTION_DID_CHANGE_AUDIO_ROUTE); + + if (this.reactContext != null) { + LocalBroadcastManager.getInstance(this.reactContext).registerReceiver(voiceBroadcastReceiver, intentFilter); + + + VoiceConnectionService.startObserving(); + } else { + isReceiverRegistered = false; + } } } private Context getAppContext() { - return this.reactContext.getApplicationContext(); + return this.reactContext != null ? this.reactContext.getApplicationContext() : null; } - public static void onRequestPermissionsResult(int requestCode, String[] grantedPermissions, int[] grantResults) { - int permissionsIndex = 0; - List permsList = Arrays.asList(permissions); - for (int result : grantResults) { - if (permsList.contains(grantedPermissions[permissionsIndex]) && result != PackageManager.PERMISSION_GRANTED) { - hasPhoneAccountPromise.resolve(false); - return; + // Store all callkeep settings in JSON + private WritableMap storeSettings(ReadableMap options) { + Context context = getAppContext(); + if (context == null) { + Log.w(TAG, "[RNCallKeepModule][storeSettings] no react context found."); + return MapUtils.readableToWritableMap(options); + } + + SharedPreferences sharedPref = context.getSharedPreferences("rn-callkeep", Context.MODE_PRIVATE); + try { + JSONObject jsonObject = MapUtils.convertMapToJson(options); + String jsonString = jsonObject.toString(); + sharedPref.edit().putString("settings", jsonString).apply(); + } catch (JSONException e) { + Log.w(TAG, "[RNCallKeepModule][storeSettings] exception: " + e); + } + return MapUtils.readableToWritableMap(options); + } + + protected static void fetchStoredSettings(@Nullable Context fromContext) { + if (instance == null && fromContext == null) { + Log.w(TAG, "[RNCallKeepModule][fetchStoredSettings] no instance nor fromContext."); + return; + } + Context context = fromContext != null ? fromContext : instance.getAppContext(); + _settings = new WritableNativeMap(); + if (context == null) { + Log.w(TAG, "[RNCallKeepModule][fetchStoredSettings] no react context found."); + return; + } + + SharedPreferences sharedPref = context.getSharedPreferences("rn-callkeep", Context.MODE_PRIVATE); + try { + String jsonString = sharedPref.getString("settings", (new JSONObject()).toString()); + if (jsonString != null) { + JSONObject jsonObject = new JSONObject(jsonString); + + _settings = MapUtils.convertJsonToMap(jsonObject); } - permissionsIndex++; + } catch(JSONException e) { } - hasPhoneAccountPromise.resolve(true); } private class VoiceBroadcastReceiver extends BroadcastReceiver { @@ -522,6 +1285,8 @@ public void onReceive(Context context, Intent intent) { WritableMap args = Arguments.createMap(); HashMap attributeMap = (HashMap)intent.getSerializableExtra("attributeMap"); + Log.d(TAG, "[RNCallKeepModule][onReceive] " + intent.getAction()); + switch (intent.getAction()) { case ACTION_END_CALL: args.putString("callUUID", attributeMap.get(EXTRA_CALL_UUID)); @@ -529,6 +1294,7 @@ public void onReceive(Context context, Intent intent) { break; case ACTION_ANSWER_CALL: args.putString("callUUID", attributeMap.get(EXTRA_CALL_UUID)); + args.putBoolean("withVideo", Boolean.valueOf(attributeMap.get(EXTRA_HAS_VIDEO))); sendEventToJS("RNCallKeepPerformAnswerCallAction", args); break; case ACTION_HOLD_CALL: @@ -568,6 +1334,43 @@ public void onReceive(Context context, Intent intent) { case ACTION_CHECK_REACHABILITY: sendEventToJS("RNCallKeepCheckReachability", null); break; + case ACTION_SHOW_INCOMING_CALL_UI: + args.putString("handle", attributeMap.get(EXTRA_CALL_NUMBER)); + args.putString("callUUID", attributeMap.get(EXTRA_CALL_UUID)); + args.putString("name", attributeMap.get(EXTRA_CALLER_NAME)); + args.putString("hasVideo", attributeMap.get(EXTRA_HAS_VIDEO)); + sendEventToJS("RNCallKeepShowIncomingCallUi", args); + break; + case ACTION_WAKE_APP: + Intent headlessIntent = new Intent(reactContext, RNCallKeepBackgroundMessagingService.class); + headlessIntent.putExtra("callUUID", attributeMap.get(EXTRA_CALL_UUID)); + headlessIntent.putExtra("name", attributeMap.get(EXTRA_CALLER_NAME)); + headlessIntent.putExtra("handle", attributeMap.get(EXTRA_CALL_NUMBER)); + Log.d(TAG, "[RNCallKeepModule] wakeUpApplication: " + attributeMap.get(EXTRA_CALL_UUID) + ", number : " + attributeMap.get(EXTRA_CALL_NUMBER) + ", displayName:" + attributeMap.get(EXTRA_CALLER_NAME)); + + ComponentName name = reactContext.startService(headlessIntent); + if (name != null) { + HeadlessJsTaskService.acquireWakeLockNow(reactContext); + } + break; + case ACTION_ON_SILENCE_INCOMING_CALL: + args.putString("handle", attributeMap.get(EXTRA_CALL_NUMBER)); + args.putString("callUUID", attributeMap.get(EXTRA_CALL_UUID)); + args.putString("name", attributeMap.get(EXTRA_CALLER_NAME)); + sendEventToJS("RNCallKeepOnSilenceIncomingCall", args); + break; + case ACTION_ON_CREATE_CONNECTION_FAILED: + args.putString("handle", attributeMap.get(EXTRA_CALL_NUMBER)); + args.putString("callUUID", attributeMap.get(EXTRA_CALL_UUID)); + args.putString("name", attributeMap.get(EXTRA_CALLER_NAME)); + sendEventToJS("RNCallKeepOnIncomingConnectionFailed", args); + break; + case ACTION_DID_CHANGE_AUDIO_ROUTE: + args.putString("handle", attributeMap.get(EXTRA_CALL_NUMBER)); + args.putString("callUUID", attributeMap.get(EXTRA_CALL_UUID)); + args.putString("output", attributeMap.get("output")); + sendEventToJS("RNCallKeepDidChangeAudioRoute", args); + break; } } } diff --git a/android/src/main/java/io/wazo/callkeep/RNCallKeepPackage.java b/android/src/main/java/io/wazo/callkeep/RNCallKeepPackage.java index 6070a75c..640c0f3d 100644 --- a/android/src/main/java/io/wazo/callkeep/RNCallKeepPackage.java +++ b/android/src/main/java/io/wazo/callkeep/RNCallKeepPackage.java @@ -30,7 +30,7 @@ public class RNCallKeepPackage implements ReactPackage { @Override public List createNativeModules(ReactApplicationContext reactContext) { - return Collections.singletonList(new RNCallKeepModule(reactContext)); + return Collections.singletonList(RNCallKeepModule.getInstance(reactContext, true)); } // Deprecated RN 0.47 diff --git a/android/src/main/java/io/wazo/callkeep/VoiceConnection.java b/android/src/main/java/io/wazo/callkeep/VoiceConnection.java index bb19b369..1ea76fba 100644 --- a/android/src/main/java/io/wazo/callkeep/VoiceConnection.java +++ b/android/src/main/java/io/wazo/callkeep/VoiceConnection.java @@ -23,8 +23,8 @@ import android.os.Build; import android.os.Bundle; import android.os.Handler; -import android.support.annotation.Nullable; -import android.support.v4.content.LocalBroadcastManager; +import androidx.annotation.Nullable; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; import android.telecom.CallAudioState; import android.telecom.Connection; import android.telecom.DisconnectCause; @@ -37,24 +37,29 @@ import java.util.HashMap; -import static io.wazo.callkeep.RNCallKeepModule.ACTION_ANSWER_CALL; -import static io.wazo.callkeep.RNCallKeepModule.ACTION_AUDIO_SESSION; -import static io.wazo.callkeep.RNCallKeepModule.ACTION_DTMF_TONE; -import static io.wazo.callkeep.RNCallKeepModule.ACTION_END_CALL; -import static io.wazo.callkeep.RNCallKeepModule.ACTION_HOLD_CALL; -import static io.wazo.callkeep.RNCallKeepModule.ACTION_MUTE_CALL; -import static io.wazo.callkeep.RNCallKeepModule.ACTION_UNHOLD_CALL; -import static io.wazo.callkeep.RNCallKeepModule.ACTION_UNMUTE_CALL; -import static io.wazo.callkeep.RNCallKeepModule.EXTRA_CALLER_NAME; -import static io.wazo.callkeep.RNCallKeepModule.EXTRA_CALL_NUMBER; -import static io.wazo.callkeep.RNCallKeepModule.EXTRA_CALL_UUID; +import static io.wazo.callkeep.Constants.ACTION_ANSWER_CALL; +import static io.wazo.callkeep.Constants.ACTION_AUDIO_SESSION; +import static io.wazo.callkeep.Constants.ACTION_DTMF_TONE; +import static io.wazo.callkeep.Constants.ACTION_END_CALL; +import static io.wazo.callkeep.Constants.ACTION_HOLD_CALL; +import static io.wazo.callkeep.Constants.ACTION_MUTE_CALL; +import static io.wazo.callkeep.Constants.ACTION_UNHOLD_CALL; +import static io.wazo.callkeep.Constants.ACTION_UNMUTE_CALL; +import static io.wazo.callkeep.Constants.EXTRA_CALLER_NAME; +import static io.wazo.callkeep.Constants.EXTRA_CALL_NUMBER; +import static io.wazo.callkeep.Constants.EXTRA_CALL_UUID; +import static io.wazo.callkeep.Constants.ACTION_SHOW_INCOMING_CALL_UI; +import static io.wazo.callkeep.Constants.ACTION_ON_SILENCE_INCOMING_CALL; +import static io.wazo.callkeep.Constants.ACTION_DID_CHANGE_AUDIO_ROUTE; @TargetApi(Build.VERSION_CODES.M) public class VoiceConnection extends Connection { private boolean isMuted = false; + private boolean answered = false; + private boolean rejected = false; private HashMap handle; private Context context; - private static final String TAG = "RNCK:VoiceConnection"; + private static final String TAG = "RNCallKeep"; VoiceConnection(Context context, HashMap handle) { super(); @@ -83,6 +88,11 @@ public void onExtrasChanged(Bundle extras) { @Override public void onCallAudioStateChanged(CallAudioState state) { + Log.d(TAG, "[VoiceConnection] onCallAudioStateChanged muted :" + (state.isMuted() ? "true" : "false")); + + handle.put("output", CallAudioState.audioRouteToString(state.getRoute())); + sendCallRequestToActivity(ACTION_DID_CHANGE_AUDIO_ROUTE, handle); + if (state.isMuted() == this.isMuted) { return; } @@ -91,25 +101,29 @@ public void onCallAudioStateChanged(CallAudioState state) { sendCallRequestToActivity(isMuted ? ACTION_MUTE_CALL : ACTION_UNMUTE_CALL, handle); } + @Override + public void onAnswer(int videoState) { + super.onAnswer(videoState); + Log.d(TAG, "[VoiceConnection] onAnswer(int) executed"); + + this._onAnswer(videoState); + } + @Override public void onAnswer() { super.onAnswer(); - Log.d(TAG, "onAnswer called"); + Log.d(TAG, "[VoiceConnection] onAnswer() executed"); - setConnectionCapabilities(getConnectionCapabilities() | Connection.CAPABILITY_HOLD); - setAudioModeIsVoip(true); - - sendCallRequestToActivity(ACTION_ANSWER_CALL, handle); - sendCallRequestToActivity(ACTION_AUDIO_SESSION, handle); - Log.d(TAG, "onAnswer executed"); + this._onAnswer(0); } @Override public void onPlayDtmfTone(char dtmf) { + Log.d(TAG, "[VoiceConnection] Playing DTMF : " + dtmf); try { handle.put("DTMF", Character.toString(dtmf)); } catch (Throwable exception) { - Log.e(TAG, "Handle map error", exception); + Log.e(TAG, "[VoiceConnection] Handle map error", exception); } sendCallRequestToActivity(ACTION_DTMF_TONE, handle); } @@ -119,11 +133,11 @@ public void onDisconnect() { super.onDisconnect(); setDisconnected(new DisconnectCause(DisconnectCause.LOCAL)); sendCallRequestToActivity(ACTION_END_CALL, handle); - Log.d(TAG, "onDisconnect executed"); + Log.d(TAG, "[VoiceConnection] onDisconnect executed"); try { ((VoiceConnectionService) context).deinitConnection(handle.get(EXTRA_CALL_UUID)); } catch(Throwable exception) { - Log.e(TAG, "Handle map error", exception); + Log.e(TAG, "[VoiceConnection] onDisconnect handle map error", exception); } destroy(); } @@ -159,17 +173,18 @@ public void onAbort() { super.onAbort(); setDisconnected(new DisconnectCause(DisconnectCause.REJECTED)); sendCallRequestToActivity(ACTION_END_CALL, handle); - Log.d(TAG, "onAbort executed"); + Log.d(TAG, "[VoiceConnection] onAbort executed"); try { ((VoiceConnectionService) context).deinitConnection(handle.get(EXTRA_CALL_UUID)); } catch(Throwable exception) { - Log.e(TAG, "Handle map error", exception); + Log.e(TAG, "[VoiceConnection] onAbort handle map error", exception); } destroy(); } @Override public void onHold() { + Log.d(TAG, "[VoiceConnection] onHold"); super.onHold(); this.setOnHold(); sendCallRequestToActivity(ACTION_HOLD_CALL, handle); @@ -177,25 +192,151 @@ public void onHold() { @Override public void onUnhold() { + Log.d(TAG, "[VoiceConnection] onUnhold"); super.onUnhold(); sendCallRequestToActivity(ACTION_UNHOLD_CALL, handle); setActive(); } + public void onReject(int rejectReason) { + Log.d(TAG, "[VoiceConnection] onReject(int) executed"); + + this._onReject(rejectReason, null); + } + @Override public void onReject() { super.onReject(); + Log.d(TAG, "[VoiceConnection] onReject() executed"); + + this._onReject(0, null); + } + + @Override + public void onReject(String replyMessage) { + super.onReject(replyMessage); + Log.d(TAG, "[VoiceConnection] onReject(String) executed"); + + this._onReject(0, replyMessage); + } + + @Override + public void onCallEvent(String event, Bundle extras) { + super.onCallEvent(event, extras); + + Log.d(TAG, "[VoiceConnection] onCallEvent called, event: " + event); + } + + @Override + public void onDeflect(Uri address) { + super.onDeflect(address); + + Log.d(TAG, "[VoiceConnection] onDeflect called, address: " + address); + } + + @Override + public void onHandoverComplete() { + super.onHandoverComplete(); + + Log.d(TAG, "[VoiceConnection] onHandoverComplete called"); + } + + @Override + public void onPostDialContinue(boolean proceed) { + super.onPostDialContinue(proceed); + + Log.d(TAG, "[VoiceConnection] onPostDialContinue called, proceed: " + proceed); + } + + @Override + public void onPullExternalCall() { + super.onPullExternalCall(); + + Log.d(TAG, "[VoiceConnection] onPullExternalCall called"); + } + + @Override + public void onSeparate() { + super.onSeparate(); + + Log.d(TAG, "[VoiceConnection] onSeparate called"); + } + + @Override + public void onStateChanged(int state) { + super.onStateChanged(state); + + Log.d(TAG, "[VoiceConnection] onStateChanged called, state : " + state); + } + + @Override + public void onSilence() { + // onSilence was added on API level 29 + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { + return; + } + + super.onSilence(); + + sendCallRequestToActivity(ACTION_ON_SILENCE_INCOMING_CALL, handle); + Log.d(TAG, "[VoiceConnection] onSilence called"); + } + + @Override + public void onStopDtmfTone() { + super.onStopDtmfTone(); + + Log.d(TAG, "[VoiceConnection] onStopDtmfTone called"); + } + + @Override + public void onStopRtt() { + super.onStopRtt(); + + Log.d(TAG, "[VoiceConnection] onStopRtt called"); + } + + private void _onAnswer(int videoState) { + Log.d(TAG, "[VoiceConnection] onAnswer called, videoState: " + videoState + ", answered: " + answered); + // On some device (like Huawei P30 lite), both onAnswer() and onAnswer(int) are called + // we have to trigger the callback only once + if (answered) { + return; + } + answered = true; + + setConnectionCapabilities(getConnectionCapabilities() | Connection.CAPABILITY_HOLD); + setAudioModeIsVoip(true); + + sendCallRequestToActivity(ACTION_ANSWER_CALL, handle); + sendCallRequestToActivity(ACTION_AUDIO_SESSION, handle); + Log.d(TAG, "[VoiceConnection] onAnswer executed"); + } + + private void _onReject(int rejectReason, String replyMessage) { + Log.d(TAG, "[VoiceConnection] onReject executed, rejectReason: " + rejectReason + ", replyMessage: " + replyMessage + ", rejected:" + rejected); + if (rejected) { + return; + } + rejected = true; + setDisconnected(new DisconnectCause(DisconnectCause.REJECTED)); sendCallRequestToActivity(ACTION_END_CALL, handle); - Log.d(TAG, "onReject executed"); + Log.d(TAG, "[VoiceConnection] onReject executed"); try { ((VoiceConnectionService) context).deinitConnection(handle.get(EXTRA_CALL_UUID)); } catch(Throwable exception) { - Log.e(TAG, "Handle map error", exception); + Log.e(TAG, "[VoiceConnection] onReject, handle map error", exception); } destroy(); } + @Override + public void onShowIncomingCallUi() { + Log.d(TAG, "[VoiceConnection] onShowIncomingCallUi"); + sendCallRequestToActivity(ACTION_SHOW_INCOMING_CALL_UI, handle); + } + /* * Send call request to the RNCallKeepModule */ diff --git a/android/src/main/java/io/wazo/callkeep/VoiceConnectionService.java b/android/src/main/java/io/wazo/callkeep/VoiceConnectionService.java index f6480da7..5d586923 100644 --- a/android/src/main/java/io/wazo/callkeep/VoiceConnectionService.java +++ b/android/src/main/java/io/wazo/callkeep/VoiceConnectionService.java @@ -18,6 +18,14 @@ package io.wazo.callkeep; import android.annotation.TargetApi; +import android.app.ActivityManager; +import android.app.ActivityManager.RunningTaskInfo; +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.Activity; +import android.content.res.Resources; import android.content.Intent; import android.content.Context; import android.content.ComponentName; @@ -25,24 +33,24 @@ import android.os.Build; import android.os.Bundle; import android.os.Handler; +import android.os.Looper; import android.speech.tts.Voice; -import android.support.annotation.Nullable; -import android.support.v4.content.LocalBroadcastManager; +import androidx.annotation.Nullable; +import androidx.core.app.NotificationCompat; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; import android.telecom.CallAudioState; import android.telecom.Connection; import android.telecom.ConnectionRequest; import android.telecom.ConnectionService; import android.telecom.DisconnectCause; +import android.telecom.PhoneAccount; import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; import android.util.Log; -import android.app.ActivityManager; -import android.app.ActivityManager.RunningTaskInfo; - import com.facebook.react.HeadlessJsTaskService; -import com.facebook.react.bridge.ReactContext; -import com.facebook.react.common.LifecycleState; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.WritableMap; import java.util.ArrayList; import java.util.HashMap; @@ -53,30 +61,34 @@ import java.util.UUID; import java.util.stream.Collectors; -import static io.wazo.callkeep.RNCallKeepModule.ACTION_ANSWER_CALL; -import static io.wazo.callkeep.RNCallKeepModule.ACTION_AUDIO_SESSION; -import static io.wazo.callkeep.RNCallKeepModule.ACTION_DTMF_TONE; -import static io.wazo.callkeep.RNCallKeepModule.ACTION_END_CALL; -import static io.wazo.callkeep.RNCallKeepModule.ACTION_HOLD_CALL; -import static io.wazo.callkeep.RNCallKeepModule.ACTION_MUTE_CALL; -import static io.wazo.callkeep.RNCallKeepModule.ACTION_ONGOING_CALL; -import static io.wazo.callkeep.RNCallKeepModule.ACTION_UNHOLD_CALL; -import static io.wazo.callkeep.RNCallKeepModule.ACTION_UNMUTE_CALL; -import static io.wazo.callkeep.RNCallKeepModule.ACTION_CHECK_REACHABILITY; -import static io.wazo.callkeep.RNCallKeepModule.EXTRA_CALLER_NAME; -import static io.wazo.callkeep.RNCallKeepModule.EXTRA_CALL_NUMBER; -import static io.wazo.callkeep.RNCallKeepModule.EXTRA_CALL_UUID; -import static io.wazo.callkeep.RNCallKeepModule.handle; +import static io.wazo.callkeep.Constants.ACTION_AUDIO_SESSION; +import static io.wazo.callkeep.Constants.ACTION_ONGOING_CALL; +import static io.wazo.callkeep.Constants.ACTION_CHECK_REACHABILITY; +import static io.wazo.callkeep.Constants.ACTION_WAKE_APP; +import static io.wazo.callkeep.Constants.EXTRA_CALLER_NAME; +import static io.wazo.callkeep.Constants.EXTRA_CALL_NUMBER; +import static io.wazo.callkeep.Constants.EXTRA_CALL_NUMBER_SCHEMA; +import static io.wazo.callkeep.Constants.EXTRA_CALL_UUID; +import static io.wazo.callkeep.Constants.EXTRA_DISABLE_ADD_CALL; +import static io.wazo.callkeep.Constants.FOREGROUND_SERVICE_TYPE_MICROPHONE; +import static io.wazo.callkeep.Constants.ACTION_ON_CREATE_CONNECTION_FAILED; // @see https://github.com/kbagchiGWC/voice-quickstart-android/blob/9a2aff7fbe0d0a5ae9457b48e9ad408740dfb968/exampleConnectionService/src/main/java/com/twilio/voice/examples/connectionservice/VoiceConnectionService.java @TargetApi(Build.VERSION_CODES.M) public class VoiceConnectionService extends ConnectionService { - private static Boolean isAvailable; - private static Boolean isInitialized; - private static Boolean isReachable; + private static Boolean isAvailable = false; + private static Boolean isInitialized = false; + private static Boolean isReachable = false; + private static Boolean canMakeMultipleCalls = true; private static String notReachableCallUuid; private static ConnectionRequest currentConnectionRequest; - private static String TAG = "RNCK:VoiceConnectionService"; + private static PhoneAccountHandle phoneAccountHandle; + private static String TAG = "RNCallKeep"; + private static int NOTIFICATION_ID = -4567; + + // Delay events sent to RNCallKeepModule when there is no listener available + private static List delayedEvents = new ArrayList(); + public static Map currentConnections = new HashMap<>(); public static Boolean hasOutgoingCall = false; public static VoiceConnectionService currentConnectionService = null; @@ -90,62 +102,139 @@ public static Connection getConnection(String connectionId) { public VoiceConnectionService() { super(); - Log.e(TAG, "Constructor"); - isReachable = false; - isInitialized = false; - isAvailable = false; + Log.d(TAG, "[VoiceConnectionService] Constructor"); currentConnectionRequest = null; currentConnectionService = this; } + public static void setPhoneAccountHandle(PhoneAccountHandle phoneAccountHandle) { + VoiceConnectionService.phoneAccountHandle = phoneAccountHandle; + } + public static void setAvailable(Boolean value) { - Log.d(TAG, "setAvailable: " + (value ? "true" : "false")); + Log.d(TAG, "[VoiceConnectionService] setAvailable: " + (value ? "true" : "false")); if (value) { - isInitialized = true; + setInitialized(true); } isAvailable = value; } + public static WritableMap getSettings(@Nullable Context context) { + WritableMap settings = RNCallKeepModule.getSettings(context); + return settings; + } + + public static ReadableMap getForegroundSettings(@Nullable Context context) { + WritableMap settings = VoiceConnectionService.getSettings(context); + if (settings == null) { + return null; + } + + return settings.getMap("foregroundService"); + } + + public static void setCanMakeMultipleCalls(Boolean value) { + Log.d(TAG, "[VoiceConnectionService] setCanMakeMultipleCalls: " + (value ? "true" : "false")); + + VoiceConnectionService.canMakeMultipleCalls = value; + } + public static void setReachable() { - Log.d(TAG, "setReachable"); + Log.d(TAG, "[VoiceConnectionService] setReachable"); isReachable = true; VoiceConnectionService.currentConnectionRequest = null; } + public static void setInitialized(boolean value) { + Log.d(TAG, "[VoiceConnectionService] setInitialized: " + (value ? "true" : "false")); + + isInitialized = value; + } + public static void deinitConnection(String connectionId) { - Log.d(TAG, "deinitConnection:" + connectionId); + Log.d(TAG, "[VoiceConnectionService] deinitConnection:" + connectionId); VoiceConnectionService.hasOutgoingCall = false; + currentConnectionService.stopForegroundService(); + if (currentConnections.containsKey(connectionId)) { currentConnections.remove(connectionId); } } + public static void setState(String uuid, int state) { + Connection conn = VoiceConnectionService.getConnection(uuid); + if (conn == null) { + Log.w(TAG, "[VoiceConnectionService] setState ignored because no connection found, uuid: " + uuid); + return; + } + + switch (state) { + case Connection.STATE_ACTIVE: + conn.setActive(); + break; + case Connection.STATE_DIALING: + conn.setDialing(); + break; + case Connection.STATE_HOLDING: + conn.setOnHold(); + break; + case Connection.STATE_INITIALIZING: + conn.setInitializing(); + break; + case Connection.STATE_RINGING: + conn.setRinging(); + break; + } + } + @Override public Connection onCreateIncomingConnection(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request) { - Bundle extra = request.getExtras(); + final Bundle extra = request.getExtras(); Uri number = request.getAddress(); String name = extra.getString(EXTRA_CALLER_NAME); + String callUUID = extra.getString(EXTRA_CALL_UUID); + Boolean isForeground = VoiceConnectionService.isRunning(this.getApplicationContext()); + WritableMap settings = this.getSettings(this); + Integer timeout = settings.hasKey("displayCallReachabilityTimeout") ? settings.getInt("displayCallReachabilityTimeout") : null; + + Log.d(TAG, "[VoiceConnectionService] onCreateIncomingConnection, name:" + name + ", number" + number + + ", isForeground: " + isForeground + ", isReachable:" + isReachable + ", timeout: " + timeout); + Connection incomingCallConnection = createConnection(request); incomingCallConnection.setRinging(); incomingCallConnection.setInitialized(); + startForegroundService(); + + if (timeout != null) { + this.checkForAppReachability(callUUID, timeout); + } + return incomingCallConnection; } @Override public Connection onCreateOutgoingConnection(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request) { VoiceConnectionService.hasOutgoingCall = true; - String uuid = UUID.randomUUID().toString(); + + Bundle extras = request.getExtras(); + String callUUID = extras.getString(EXTRA_CALL_UUID); + + if(callUUID == null || callUUID == ""){ + callUUID = UUID.randomUUID().toString(); + } + + Log.d(TAG, "[VoiceConnectionService] onCreateOutgoingConnection, uuid:" + callUUID); if (!isInitialized && !isReachable) { - this.notReachableCallUuid = uuid; + this.notReachableCallUuid = callUUID; this.currentConnectionRequest = request; this.checkReachability(); } - return this.makeOutgoingCall(request, uuid, false); + return this.makeOutgoingCall(request, callUUID, false); } private Connection makeOutgoingCall(ConnectionRequest request, String uuid, Boolean forceWakeUp) { @@ -156,14 +245,14 @@ private Connection makeOutgoingCall(ConnectionRequest request, String uuid, Bool String displayName = extras.getString(EXTRA_CALLER_NAME); Boolean isForeground = VoiceConnectionService.isRunning(this.getApplicationContext()); - Log.d(TAG, "makeOutgoingCall:" + uuid + ", number: " + number + ", displayName:" + displayName); + Log.d(TAG, "[VoiceConnectionService] makeOutgoingCall, uuid:" + uuid + ", number: " + number + ", displayName:" + displayName); // Wakeup application if needed if (!isForeground || forceWakeUp) { - Log.d(TAG, "onCreateOutgoingConnection: Waking up application"); + Log.d(TAG, "[VoiceConnectionService] onCreateOutgoingConnection: Waking up application"); this.wakeUpApplication(uuid, number, displayName); } else if (!this.canMakeOutgoingCall() && isReachable) { - Log.d(TAG, "onCreateOutgoingConnection: not available"); + Log.d(TAG, "[VoiceConnectionService] onCreateOutgoingConnection: not available"); return Connection.createFailedConnection(new DisconnectCause(DisconnectCause.LOCAL)); } @@ -174,40 +263,141 @@ private Connection makeOutgoingCall(ConnectionRequest request, String uuid, Bool extras.putString(EXTRA_CALL_NUMBER, number); } + if (!canMakeMultipleCalls) { + Log.d(TAG, "[VoiceConnectionService] onCreateOutgoingConnection: disabling multi calls"); + extras.putBoolean(EXTRA_DISABLE_ADD_CALL, true); + } + outgoingCallConnection = createConnection(request); outgoingCallConnection.setDialing(); outgoingCallConnection.setAudioModeIsVoip(true); outgoingCallConnection.setCallerDisplayName(displayName, TelecomManager.PRESENTATION_ALLOWED); + startForegroundService(); + // ‍️Weirdly on some Samsung phones (A50, S9...) using `setInitialized` will not display the native UI ... // when making a call from the native Phone application. The call will still be displayed correctly without it. if (!Build.MANUFACTURER.equalsIgnoreCase("Samsung")) { + Log.d(TAG, "[VoiceConnectionService] onCreateOutgoingConnection: initializing connection on non-Samsung device"); outgoingCallConnection.setInitialized(); } HashMap extrasMap = this.bundleToMap(extras); - sendCallRequestToActivity(ACTION_ONGOING_CALL, extrasMap); - sendCallRequestToActivity(ACTION_AUDIO_SESSION, extrasMap); + sendCallRequestToActivity(ACTION_ONGOING_CALL, extrasMap, true); + sendCallRequestToActivity(ACTION_AUDIO_SESSION, extrasMap, true); - Log.d(TAG, "onCreateOutgoingConnection: calling"); + Log.d(TAG, "[VoiceConnectionService] onCreateOutgoingConnection: done"); return outgoingCallConnection; } + private void startForegroundService() { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { + // Foreground services not required before SDK 28 + return; + } + Log.d(TAG, "[VoiceConnectionService] startForegroundService"); + ReadableMap foregroundSettings = getForegroundSettings(null); + + if (!this.isForegroundServiceConfigured()) { + Log.w(TAG, "[VoiceConnectionService] Not creating foregroundService because not configured"); + return; + } + + String NOTIFICATION_CHANNEL_ID = foregroundSettings.getString("channelId"); + String channelName = foregroundSettings.getString("channelName"); + NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_NONE); + chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE); + NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + assert manager != null; + manager.createNotificationChannel(chan); + + NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID); + notificationBuilder.setOngoing(true) + .setContentTitle(foregroundSettings.getString("notificationTitle")) + .setPriority(NotificationManager.IMPORTANCE_MIN) + .setCategory(Notification.CATEGORY_SERVICE); + + Activity currentActivity = RNCallKeepModule.instance.getCurrentReactActivity(); + if (currentActivity != null) { + Intent notificationIntent = new Intent(this, currentActivity.getClass()); + notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); + + final int flag = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE : PendingIntent.FLAG_UPDATE_CURRENT; + + PendingIntent pendingIntent = PendingIntent.getActivity(this, NOTIFICATION_ID, notificationIntent, flag); + + notificationBuilder.setContentIntent(pendingIntent); + } + + if (foregroundSettings.hasKey("notificationIcon")) { + Context context = this.getApplicationContext(); + Resources res = context.getResources(); + String smallIcon = foregroundSettings.getString("notificationIcon"); + notificationBuilder.setSmallIcon(res.getIdentifier(smallIcon, "mipmap", context.getPackageName())); + } + + Log.d(TAG, "[VoiceConnectionService] Starting foreground service"); + + Notification notification = notificationBuilder.build(); + + try { + startForeground(FOREGROUND_SERVICE_TYPE_MICROPHONE, notification); + } catch (Exception e) { + Log.w(TAG, "[VoiceConnectionService] Can't start foreground service : " + e.toString()); + } + } + + private void stopForegroundService() { + Log.d(TAG, "[VoiceConnectionService] stopForegroundService"); + ReadableMap foregroundSettings = getForegroundSettings(null); + + if (!this.isForegroundServiceConfigured()) { + Log.w(TAG, "[VoiceConnectionService] Not creating foregroundService because not configured"); + return; + } + + try { + stopForeground(FOREGROUND_SERVICE_TYPE_MICROPHONE); + } catch (Exception e) { + Log.w(TAG, "[VoiceConnectionService] can't stop foreground service :" + e.toString()); + } + } + + private boolean isForegroundServiceConfigured() { + ReadableMap foregroundSettings = getForegroundSettings(null); + try { + return foregroundSettings != null && foregroundSettings.hasKey("channelId"); + } catch (Exception e) { + // Fix ArrayIndexOutOfBoundsException thrown by ReadableNativeMap.hasKey + Log.w(TAG, "[VoiceConnectionService] Not creating foregroundService due to configuration retrieval error" + e.toString()); + return false; + } + } + private void wakeUpApplication(String uuid, String number, String displayName) { - Intent headlessIntent = new Intent( - this.getApplicationContext(), - RNCallKeepBackgroundMessagingService.class - ); - headlessIntent.putExtra("callUUID", uuid); - headlessIntent.putExtra("name", displayName); - headlessIntent.putExtra("handle", number); - Log.d(TAG, "wakeUpApplication: " + uuid + ", number : " + number + ", displayName:" + displayName); - - ComponentName name = this.getApplicationContext().startService(headlessIntent); - if (name != null) { - HeadlessJsTaskService.acquireWakeLockNow(this.getApplicationContext()); + Log.d(TAG, "[VoiceConnectionService] wakeUpApplication, uuid:" + uuid + ", number :" + number + ", displayName:" + displayName); + + // Avoid to call wake up the app again in wakeUpAfterReachabilityTimeout. + this.currentConnectionRequest = null; + + try { + Intent headlessIntent = new Intent( + this.getApplicationContext(), + RNCallKeepBackgroundMessagingService.class + ); + headlessIntent.putExtra("callUUID", uuid); + headlessIntent.putExtra("name", displayName); + headlessIntent.putExtra("handle", number); + + ComponentName name = this.getApplicationContext().startService(headlessIntent); + if (name != null) { + Log.d(TAG, "[VoiceConnectionService] wakeUpApplication, acquiring lock for application:" + name); + HeadlessJsTaskService.acquireWakeLockNow(this.getApplicationContext()); + } + } catch (Exception e) { + Log.w(TAG, "[VoiceConnectionService] wakeUpApplication, error" + e.toString()); } } @@ -215,20 +405,21 @@ private void wakeUpAfterReachabilityTimeout(ConnectionRequest request) { if (this.currentConnectionRequest == null) { return; } - Log.d(TAG, "checkReachability timeout, force wakeup"); Bundle extras = request.getExtras(); String number = request.getAddress().getSchemeSpecificPart(); String displayName = extras.getString(EXTRA_CALLER_NAME); + Log.d(TAG, "[VoiceConnectionService] checkReachability timeout, force wakeup, number :" + number + ", displayName: " + displayName); + wakeUpApplication(this.notReachableCallUuid, number, displayName); VoiceConnectionService.currentConnectionRequest = null; } private void checkReachability() { - Log.d(TAG, "checkReachability"); + Log.d(TAG, "[VoiceConnectionService] checkReachability"); final VoiceConnectionService instance = this; - sendCallRequestToActivity(ACTION_CHECK_REACHABILITY, null); + sendCallRequestToActivity(ACTION_CHECK_REACHABILITY, null, true); new android.os.Handler().postDelayed( new Runnable() { @@ -244,10 +435,44 @@ private Boolean canMakeOutgoingCall() { private Connection createConnection(ConnectionRequest request) { Bundle extras = request.getExtras(); + if (request.getAddress() == null) { + return null; + } HashMap extrasMap = this.bundleToMap(extras); - extrasMap.put(EXTRA_CALL_NUMBER, request.getAddress().toString()); + + String callerNumber = request.getAddress().toString(); + Log.d(TAG, "[VoiceConnectionService] createConnection, callerNumber:" + callerNumber); + + if (callerNumber.contains(":")) { + //CallerNumber contains a schema which we'll separate out + int schemaIndex = callerNumber.indexOf(":"); + String number = callerNumber.substring(schemaIndex + 1); + String schema = callerNumber.substring(0, schemaIndex); + + extrasMap.put(EXTRA_CALL_NUMBER, number); + extrasMap.put(EXTRA_CALL_NUMBER_SCHEMA, schema); + } else { + extrasMap.put(EXTRA_CALL_NUMBER, callerNumber); + } + VoiceConnection connection = new VoiceConnection(this, extrasMap); connection.setConnectionCapabilities(Connection.CAPABILITY_MUTE | Connection.CAPABILITY_SUPPORT_HOLD); + + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + Context context = getApplicationContext(); + TelecomManager telecomManager = (TelecomManager) context.getSystemService(context.TELECOM_SERVICE); + PhoneAccount phoneAccount = telecomManager.getPhoneAccount(request.getAccountHandle()); + + //If the phone account is self managed, then this connection must also be self managed. + if((phoneAccount.getCapabilities() & PhoneAccount.CAPABILITY_SELF_MANAGED) == PhoneAccount.CAPABILITY_SELF_MANAGED) { + Log.d(TAG, "[VoiceConnectionService] PhoneAccount is SELF_MANAGED, so connection will be too"); + connection.setConnectionProperties(Connection.PROPERTY_SELF_MANAGED); + } + else { + Log.d(TAG, "[VoiceConnectionService] PhoneAccount is not SELF_MANAGED, so connection won't be either"); + } + } + connection.setInitializing(); connection.setExtras(extras); currentConnections.put(extras.getString(EXTRA_CALL_UUID), connection); @@ -267,13 +492,12 @@ private Connection createConnection(ConnectionRequest request) { @Override public void onConference(Connection connection1, Connection connection2) { + Log.d(TAG, "[VoiceConnectionService] onConference"); super.onConference(connection1, connection2); VoiceConnection voiceConnection1 = (VoiceConnection) connection1; VoiceConnection voiceConnection2 = (VoiceConnection) connection2; - PhoneAccountHandle phoneAccountHandle = RNCallKeepModule.handle; - - VoiceConference voiceConference = new VoiceConference(handle); + VoiceConference voiceConference = new VoiceConference(phoneAccountHandle); voiceConference.addConnection(voiceConnection1); voiceConference.addConnection(voiceConnection2); @@ -283,23 +507,77 @@ public void onConference(Connection connection1, Connection connection2) { this.addConference(voiceConference); } + @Override + public void onCreateIncomingConnectionFailed(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request) { + super.onCreateIncomingConnectionFailed(connectionManagerPhoneAccount, request); + Log.w(TAG, "[VoiceConnectionService] onCreateIncomingConnectionFailed: " + request); + + Bundle extras = request.getExtras(); + HashMap extrasMap = this.bundleToMap(extras); + + String callerNumber = request.getAddress().toString(); + if (callerNumber.contains(":")) { + //CallerNumber contains a schema which we'll separate out + int schemaIndex = callerNumber.indexOf(":"); + String number = callerNumber.substring(schemaIndex + 1); + String schema = callerNumber.substring(0, schemaIndex); + + extrasMap.put(EXTRA_CALL_NUMBER, number); + extrasMap.put(EXTRA_CALL_NUMBER_SCHEMA, schema); + } else { + extrasMap.put(EXTRA_CALL_NUMBER, callerNumber); + } + + sendCallRequestToActivity(ACTION_ON_CREATE_CONNECTION_FAILED, extrasMap, true); + } + + // When a listener is available for `sendCallRequestToActivity`, send delayed events. + public static void startObserving() { + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + // Run this in a Looper to avoid : java.lang.RuntimeException: Can't create handler inside thread Thread + int count = delayedEvents.size(); + Log.d(TAG, "[VoiceConnectionService] startObserving, event count: " + count); + + for (Bundle event : delayedEvents) { + String action = event.getString("action"); + HashMap attributeMap = (HashMap) event.getSerializable("attributeMap"); + + currentConnectionService.sendCallRequestToActivity(action, attributeMap, false); + } + + delayedEvents = new ArrayList(); + } + }); + } + /* * Send call request to the RNCallKeepModule */ - private void sendCallRequestToActivity(final String action, @Nullable final HashMap attributeMap) { + private void sendCallRequestToActivity(final String action, @Nullable final HashMap attributeMap, final boolean retry) { final VoiceConnectionService instance = this; final Handler handler = new Handler(); + Log.d(TAG, "[VoiceConnectionService] sendCallRequestToActivity, action:" + action); + handler.post(new Runnable() { @Override public void run() { Intent intent = new Intent(action); + Bundle extras = new Bundle(); + extras.putString("action", action); + if (attributeMap != null) { - Bundle extras = new Bundle(); extras.putSerializable("attributeMap", attributeMap); intent.putExtras(extras); } - LocalBroadcastManager.getInstance(instance).sendBroadcast(intent); + + boolean result = LocalBroadcastManager.getInstance(instance).sendBroadcast(intent); + if (!result && retry) { + // Event will be sent later when a listener will be available. + delayedEvents.add(extras); + } } }); } @@ -329,10 +607,34 @@ public static boolean isRunning(Context context) { List tasks = activityManager.getRunningTasks(Integer.MAX_VALUE); for (RunningTaskInfo task : tasks) { - if (context.getPackageName().equalsIgnoreCase(task.baseActivity.getPackageName())) + if (context.getPackageName().equalsIgnoreCase(task.baseActivity.getPackageName())) { return true; + } } + Log.d(TAG, "[VoiceConnectionService] isRunning: no running package found."); + return false; } + + private void checkForAppReachability(final String callUUID, final Integer timeout) { + final VoiceConnectionService instance = this; + + new android.os.Handler().postDelayed(new Runnable() { + public void run() { + if (instance.isReachable) { + return; + } + Connection conn = VoiceConnectionService.getConnection(callUUID); + Log.w(TAG, "[VoiceConnectionService] checkForAppReachability timeout after " + timeout + " ms, isReachable:" + instance.isReachable + ", uuid: " + callUUID); + + if (conn == null) { + Log.w(TAG, "[VoiceConnectionService] checkForAppReachability timeout, no connection to close with uuid: " + callUUID); + + return; + } + conn.onDisconnect(); + } + }, timeout); + } } diff --git a/docs/android-installation.md b/docs/android-installation.md index 9238ab9d..fcbb8e37 100644 --- a/docs/android-installation.md +++ b/docs/android-installation.md @@ -60,18 +60,27 @@ public class MainActivity extends ReactActivity { 1. In `android/app/src/main/AndroidManifest.xml` add these permissions: - ```xml + +// Use this to target android >= 14 + + // ... + android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE" + // Use this to target android >= 11 + android:foregroundServiceType="camera|microphone" + // For android < 11 + android:foregroundServiceType="phoneCall" + > + @@ -80,6 +89,8 @@ public class MainActivity extends ReactActivity { ``` +Beware to choose the right `foregroundServiceType` depending on the version of Android you want to target. + 2. To be able to wake up your killed application when making an outgoing call form the native Phone application: Add this in the `application` node of `android/app/src/main/AndroidManifest.xml` : diff --git a/docs/ios-installation.md b/docs/ios-installation.md index 9849fe90..14622475 100644 --- a/docs/ios-installation.md +++ b/docs/ios-installation.md @@ -96,7 +96,7 @@ Add it before the `@end` tag. ```diff + - (BOOL)application:(UIApplication *)application + continueUserActivity:(NSUserActivity *)userActivity -+ restorationHandler:(void(^)(NSArray * __nullable restorableObjects))restorationHandler ++ restorationHandler:(void(^)(NSArray> * __nullable restorableObjects))restorationHandler + { + return [RNCallKeep application:application + continueUserActivity:userActivity diff --git a/example/App.js b/example/App.js index 82feed7c..c96213db 100644 --- a/example/App.js +++ b/example/App.js @@ -77,7 +77,7 @@ export default function App() { const { [callUUID]: __, ...updatedHeldCalls } = heldCalls; setCalls(updated); - setCalls(updatedHeldCalls); + setHeldCalls(updatedHeldCalls); }; const setCallHeld = (callUUID, held) => { diff --git a/example/package.json b/example/package.json index 3924f2ad..a24d1b5f 100644 --- a/example/package.json +++ b/example/package.json @@ -9,12 +9,12 @@ "expo": "^34.0.1", "react": "16.8.3", "react-dom": "^16.8.6", - "react-native": "0.59.8", + "react-native": "0.62.3", "react-native-background-timer": "^2.1.1", "react-native-callkeep": "3.0.7", "react-native-device-info": "^2.3.2", "react-native-gesture-handler": "~1.3.0", - "react-native-reanimated": "~1.1.0", + "react-native-reanimated": "~2.10.0", "react-native-unimodules": "~0.5.2", "react-native-web": "^0.11.4", "uuid": "^3.3.2" diff --git a/example/yarn.lock b/example/yarn.lock index c367e12f..f1401464 100644 --- a/example/yarn.lock +++ b/example/yarn.lock @@ -9,6 +9,20 @@ dependencies: "@babel/highlight" "^7.0.0" +"@babel/code-frame@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb" + integrity sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw== + dependencies: + "@babel/highlight" "^7.14.5" + +"@babel/code-frame@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" + integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== + dependencies: + "@babel/highlight" "^7.18.6" + "@babel/core@^7.0.0", "@babel/core@^7.1.0": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.5.5.tgz#17b2686ef0d6bc58f963dddd68ab669755582c30" @@ -29,7 +43,25 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.0.0", "@babel/generator@^7.5.5": +"@babel/generator@^7.15.0", "@babel/generator@^7.5.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.15.0.tgz#a7d0c172e0d814974bad5aa77ace543b97917f15" + integrity sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ== + dependencies: + "@babel/types" "^7.15.0" + jsesc "^2.5.1" + source-map "^0.5.0" + +"@babel/generator@^7.19.6": + version "7.19.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.19.6.tgz#9e481a3fe9ca6261c972645ae3904ec0f9b34a1d" + integrity sha512-oHGRUQeoX1QrKeJIKVe0hwjGqNnVYsM5Nep5zo0uE0m42sLH+Fsd2pStJ5sRM1bNyTUUoz0pe2lTeMJrb/taTA== + dependencies: + "@babel/types" "^7.19.4" + "@jridgewell/gen-mapping" "^0.3.2" + jsesc "^2.5.1" + +"@babel/generator@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.5.5.tgz#873a7f936a3c89491b43536d12245b626664e3cf" integrity sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ== @@ -47,6 +79,20 @@ dependencies: "@babel/types" "^7.0.0" +"@babel/helper-annotate-as-pure@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.14.5.tgz#7bf478ec3b71726d56a8ca5775b046fc29879e61" + integrity sha512-EivH9EgBIb+G8ij1B2jAwSH36WnGvkQSEC6CkX/6v6ZFlw5fVOHvsgGF4uiEHO2GzMvunZb6tDLQEQSdrdocrA== + dependencies: + "@babel/types" "^7.14.5" + +"@babel/helper-annotate-as-pure@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" + integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA== + dependencies: + "@babel/types" "^7.18.6" + "@babel/helper-builder-binary-assignment-operator-visitor@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz#6b69628dfe4087798e0c4ed98e3d4a6b2fbd2f5f" @@ -72,6 +118,31 @@ "@babel/traverse" "^7.4.4" "@babel/types" "^7.4.4" +"@babel/helper-create-class-features-plugin@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.15.0.tgz#c9a137a4d137b2d0e2c649acf536d7ba1a76c0f7" + integrity sha512-MdmDXgvTIi4heDVX/e9EFfeGpugqm9fobBVg/iioE8kueXrOHdRDe36FAY7SnE9xXLVeYCoJR/gdrBEIHRC83Q== + dependencies: + "@babel/helper-annotate-as-pure" "^7.14.5" + "@babel/helper-function-name" "^7.14.5" + "@babel/helper-member-expression-to-functions" "^7.15.0" + "@babel/helper-optimise-call-expression" "^7.14.5" + "@babel/helper-replace-supers" "^7.15.0" + "@babel/helper-split-export-declaration" "^7.14.5" + +"@babel/helper-create-class-features-plugin@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz#bfd6904620df4e46470bae4850d66be1054c404b" + integrity sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" + "@babel/helper-member-expression-to-functions" "^7.18.9" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/helper-replace-supers" "^7.18.9" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/helper-create-class-features-plugin@^7.4.4", "@babel/helper-create-class-features-plugin@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.5.5.tgz#401f302c8ddbc0edd36f7c6b2887d8fa1122e5a4" @@ -93,6 +164,11 @@ "@babel/types" "^7.5.5" lodash "^4.17.13" +"@babel/helper-environment-visitor@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" + integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== + "@babel/helper-explode-assignable-expression@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz#537fa13f6f1674df745b0c00ec8fe4e99681c8f6" @@ -110,6 +186,23 @@ "@babel/template" "^7.1.0" "@babel/types" "^7.0.0" +"@babel/helper-function-name@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz#89e2c474972f15d8e233b52ee8c480e2cfcd50c4" + integrity sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ== + dependencies: + "@babel/helper-get-function-arity" "^7.14.5" + "@babel/template" "^7.14.5" + "@babel/types" "^7.14.5" + +"@babel/helper-function-name@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" + integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w== + dependencies: + "@babel/template" "^7.18.10" + "@babel/types" "^7.19.0" + "@babel/helper-get-function-arity@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3" @@ -117,6 +210,27 @@ dependencies: "@babel/types" "^7.0.0" +"@babel/helper-get-function-arity@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz#25fbfa579b0937eee1f3b805ece4ce398c431815" + integrity sha512-I1Db4Shst5lewOM4V+ZKJzQ0JGGaZ6VY1jYvMghRjqs6DWgxLCIyFt30GlnKkfUeFLpJt2vzbMVEXVSXlIFYUg== + dependencies: + "@babel/types" "^7.14.5" + +"@babel/helper-hoist-variables@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz#e0dd27c33a78e577d7c8884916a3e7ef1f7c7f8d" + integrity sha512-R1PXiz31Uc0Vxy4OEOm07x0oSjKAdPPCh3tPivn/Eo8cvz6gveAeuyUUPB21Hoiif0uoPQSSdhIPS3352nvdyQ== + dependencies: + "@babel/types" "^7.14.5" + +"@babel/helper-hoist-variables@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" + integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== + dependencies: + "@babel/types" "^7.18.6" + "@babel/helper-hoist-variables@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz#0298b5f25c8c09c53102d52ac4a98f773eb2850a" @@ -124,6 +238,20 @@ dependencies: "@babel/types" "^7.4.4" +"@babel/helper-member-expression-to-functions@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.0.tgz#0ddaf5299c8179f27f37327936553e9bba60990b" + integrity sha512-Jq8H8U2kYiafuj2xMTPQwkTBnEEdGKpT35lJEQsRRjnG0LW3neucsaMWLgKcwu3OHKNeYugfw+Z20BXBSEs2Lg== + dependencies: + "@babel/types" "^7.15.0" + +"@babel/helper-member-expression-to-functions@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz#1531661e8375af843ad37ac692c132841e2fd815" + integrity sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg== + dependencies: + "@babel/types" "^7.18.9" + "@babel/helper-member-expression-to-functions@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz#1fb5b8ec4453a93c439ee9fe3aeea4a84b76b590" @@ -157,11 +285,35 @@ dependencies: "@babel/types" "^7.0.0" +"@babel/helper-optimise-call-expression@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz#f27395a8619e0665b3f0364cddb41c25d71b499c" + integrity sha512-IqiLIrODUOdnPU9/F8ib1Fx2ohlgDhxnIDU7OEVi+kAbEZcyiF7BLU8W6PfvPi9LzztjS7kcbzbmL7oG8kD6VA== + dependencies: + "@babel/types" "^7.14.5" + +"@babel/helper-optimise-call-expression@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz#9369aa943ee7da47edab2cb4e838acf09d290ffe" + integrity sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA== + dependencies: + "@babel/types" "^7.18.6" + "@babel/helper-plugin-utils@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== +"@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.8.0": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9" + integrity sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ== + +"@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz#4796bb14961521f0f8715990bee2fb6e51ce21bf" + integrity sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw== + "@babel/helper-regex@^7.0.0", "@babel/helper-regex@^7.4.4": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.5.5.tgz#0aa6824f7100a2e0e89c1527c23936c152cab351" @@ -180,6 +332,27 @@ "@babel/traverse" "^7.1.0" "@babel/types" "^7.0.0" +"@babel/helper-replace-supers@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.15.0.tgz#ace07708f5bf746bf2e6ba99572cce79b5d4e7f4" + integrity sha512-6O+eWrhx+HEra/uJnifCwhwMd6Bp5+ZfZeJwbqUTuqkhIT6YcRhiZCOOFChRypOIe0cV46kFrRBlm+t5vHCEaA== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.15.0" + "@babel/helper-optimise-call-expression" "^7.14.5" + "@babel/traverse" "^7.15.0" + "@babel/types" "^7.15.0" + +"@babel/helper-replace-supers@^7.18.9": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.19.1.tgz#e1592a9b4b368aa6bdb8784a711e0bcbf0612b78" + integrity sha512-T7ahH7wV0Hfs46SFh5Jz3s0B6+o8g3c+7TMxu7xKfmHikg7EAZ3I2Qk9LFhjxXq8sL7UkP5JflezNwoZa8WvWw== + dependencies: + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-member-expression-to-functions" "^7.18.9" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/traverse" "^7.19.1" + "@babel/types" "^7.19.0" + "@babel/helper-replace-supers@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz#f84ce43df031222d2bad068d2626cb5799c34bc2" @@ -198,6 +371,20 @@ "@babel/template" "^7.1.0" "@babel/types" "^7.0.0" +"@babel/helper-split-export-declaration@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz#22b23a54ef51c2b7605d851930c1976dd0bc693a" + integrity sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA== + dependencies: + "@babel/types" "^7.14.5" + +"@babel/helper-split-export-declaration@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" + integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== + dependencies: + "@babel/types" "^7.18.6" + "@babel/helper-split-export-declaration@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz#ff94894a340be78f53f06af038b205c49d993677" @@ -205,6 +392,26 @@ dependencies: "@babel/types" "^7.4.4" +"@babel/helper-string-parser@^7.19.4": + version "7.19.4" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" + integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== + +"@babel/helper-validator-identifier@^7.14.5", "@babel/helper-validator-identifier@^7.14.9": + version "7.14.9" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz#6654d171b2024f6d8ee151bf2509699919131d48" + integrity sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g== + +"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" + integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== + +"@babel/helper-validator-option@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" + integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== + "@babel/helper-wrap-function@^7.1.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz#c4e0012445769e2815b55296ead43a958549f6fa" @@ -233,11 +440,39 @@ esutils "^2.0.2" js-tokens "^4.0.0" +"@babel/highlight@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9" + integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg== + dependencies: + "@babel/helper-validator-identifier" "^7.14.5" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/highlight@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" + integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== + dependencies: + "@babel/helper-validator-identifier" "^7.18.6" + chalk "^2.0.0" + js-tokens "^4.0.0" + "@babel/parser@^7.0.0", "@babel/parser@^7.4.4", "@babel/parser@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.5.5.tgz#02f077ac8817d3df4a832ef59de67565e71cca4b" integrity sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g== +"@babel/parser@^7.14.5", "@babel/parser@^7.15.0": + version "7.15.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.3.tgz#3416d9bea748052cfcb63dbcc27368105b1ed862" + integrity sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA== + +"@babel/parser@^7.18.10", "@babel/parser@^7.19.6": + version "7.19.6" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.19.6.tgz#b923430cb94f58a7eae8facbffa9efd19130e7f8" + integrity sha512-h1IUp81s2JYJ3mRkdxJgs4UvmSsRvDrx5ICSJbPvtWYv5i1nTBGcBpnog+89rAFMwvvru6E5NUHdBe01UeSzYA== + "@babel/plugin-external-helpers@^7.0.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-external-helpers/-/plugin-external-helpers-7.2.0.tgz#7f4cb7dee651cd380d2034847d914288467a6be4" @@ -392,6 +627,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-syntax-nullish-coalescing-operator@^7.0.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + "@babel/plugin-syntax-nullish-coalescing-operator@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.2.0.tgz#f75083dfd5ade73e783db729bbd87e7b9efb7624" @@ -413,6 +655,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-syntax-optional-chaining@^7.0.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + "@babel/plugin-syntax-optional-chaining@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.2.0.tgz#a59d6ae8c167e7608eaa443fda9fa8fa6bf21dff" @@ -420,6 +669,20 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-syntax-typescript@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.14.5.tgz#b82c6ce471b165b5ce420cf92914d6fb46225716" + integrity sha512-u6OXzDaIXjEstBRRoBCQ/uKQKlbuaeE5in0RvWdA4pN6AhqxTIwUsnHPU1CFZA/amYObMsuWhYfRl3Ch90HD0Q== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-typescript@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz#1c09cd25795c7c2b8a4ba9ae49394576d4133285" + integrity sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-typescript@^7.2.0": version "7.3.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.3.3.tgz#a7cc3f66119a9f7ebe2de5383cce193473d65991" @@ -597,12 +860,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-object-assign@^7.0.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.2.0.tgz#6fdeea42be17040f119e38e23ea0f49f31968bde" - integrity sha512-nmE55cZBPFgUktbF2OuoZgPRadfxosLOpSgzEPYotKSls9J4pEPcembi8r78RU37Rph6UApCpNmsQA4QMWK9Ng== +"@babel/plugin-transform-object-assign@^7.0.0", "@babel/plugin-transform-object-assign@^7.16.7": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.18.6.tgz#7830b4b6f83e1374a5afb9f6111bcfaea872cdd2" + integrity sha512-mQisZ3JfqWh2gVXvfqYCAAyRs6+7oev+myBsTwW5RnPhYXOTuCEw2oe3YgxlXMViXUS53lG8koulI7mJ+8JE+A== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-object-super@^7.0.0", "@babel/plugin-transform-object-super@^7.5.5": version "7.5.5" @@ -635,6 +898,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-react-jsx-self@^7.0.0": + version "7.14.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.14.9.tgz#33041e665453391eb6ee54a2ecf3ba1d46bd30f4" + integrity sha512-Fqqu0f8zv9W+RyOnx29BX/RlEsBRANbOf5xs5oxb2aHP4FKbLXxIaVPUiCti56LAR1IixMH4EyaixhUsKqoBHw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-transform-react-jsx-source@^7.0.0": version "7.5.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.5.0.tgz#583b10c49cf057e237085bcbd8cc960bd83bd96b" @@ -722,6 +992,24 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-typescript" "^7.2.0" +"@babel/plugin-transform-typescript@^7.18.6": + version "7.19.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.19.3.tgz#4f1db1e0fe278b42ddbc19ec2f6cd2f8262e35d6" + integrity sha512-z6fnuK9ve9u/0X0rRvI9MY0xg+DOUaABDYOe+/SQTxtlptaBB/V9JIUxJn6xp3lMBeb9qe8xSFmHU35oZDXD+w== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.19.0" + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/plugin-syntax-typescript" "^7.18.6" + +"@babel/plugin-transform-typescript@^7.5.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.15.0.tgz#553f230b9d5385018716586fc48db10dd228eb7e" + integrity sha512-WIIEazmngMEEHDaPTx0IZY48SaAmjVWe3TRSX7cmJXn0bEv9midFzAjxiruOWYIVf5iQ10vFx7ASDpgEO08L5w== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.15.0" + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-syntax-typescript" "^7.14.5" + "@babel/plugin-transform-unicode-regex@^7.0.0", "@babel/plugin-transform-unicode-regex@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz#ab4634bb4f14d36728bf5978322b35587787970f" @@ -787,6 +1075,15 @@ js-levenshtein "^1.1.3" semver "^5.5.0" +"@babel/preset-typescript@^7.16.7": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz#ce64be3e63eddc44240c6358daefac17b3186399" + integrity sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-validator-option" "^7.18.6" + "@babel/plugin-transform-typescript" "^7.18.6" + "@babel/register@^7.0.0": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.5.5.tgz#40fe0d474c8c8587b28d6ae18a03eddad3dac3c1" @@ -815,6 +1112,24 @@ "@babel/parser" "^7.4.4" "@babel/types" "^7.4.4" +"@babel/template@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.14.5.tgz#a9bc9d8b33354ff6e55a9c60d1109200a68974f4" + integrity sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g== + dependencies: + "@babel/code-frame" "^7.14.5" + "@babel/parser" "^7.14.5" + "@babel/types" "^7.14.5" + +"@babel/template@^7.18.10": + version "7.18.10" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71" + integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/parser" "^7.18.10" + "@babel/types" "^7.18.10" + "@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.4.4", "@babel/traverse@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.5.5.tgz#f664f8f368ed32988cd648da9f72d5ca70f165bb" @@ -830,6 +1145,37 @@ globals "^11.1.0" lodash "^4.17.13" +"@babel/traverse@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.15.0.tgz#4cca838fd1b2a03283c1f38e141f639d60b3fc98" + integrity sha512-392d8BN0C9eVxVWd8H6x9WfipgVH5IaIoLp23334Sc1vbKKWINnvwRpb4us0xtPaCumlwbTtIYNA0Dv/32sVFw== + dependencies: + "@babel/code-frame" "^7.14.5" + "@babel/generator" "^7.15.0" + "@babel/helper-function-name" "^7.14.5" + "@babel/helper-hoist-variables" "^7.14.5" + "@babel/helper-split-export-declaration" "^7.14.5" + "@babel/parser" "^7.15.0" + "@babel/types" "^7.15.0" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/traverse@^7.19.1": + version "7.19.6" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.19.6.tgz#7b4c865611df6d99cb131eec2e8ac71656a490dc" + integrity sha512-6l5HrUCzFM04mfbG09AagtYyR2P0B71B1wN7PfSPiksDPz2k5H9CBC1tcZpz2M8OxbKTPccByoOJ22rUKbpmQQ== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.19.6" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/parser" "^7.19.6" + "@babel/types" "^7.19.4" + debug "^4.1.0" + globals "^11.1.0" + "@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.3.0", "@babel/types@^7.4.4", "@babel/types@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.5.5.tgz#97b9f728e182785909aa4ab56264f090a028d18a" @@ -839,6 +1185,31 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" +"@babel/types@^7.14.5", "@babel/types@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.15.0.tgz#61af11f2286c4e9c69ca8deb5f4375a73c72dcbd" + integrity sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ== + dependencies: + "@babel/helper-validator-identifier" "^7.14.9" + to-fast-properties "^2.0.0" + +"@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.19.4": + version "7.19.4" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.19.4.tgz#0dd5c91c573a202d600490a35b33246fed8a41c7" + integrity sha512-M5LK7nAeS6+9j7hAq+b3fQs+pNfUtTGq+yFFfHnauFA8zQtLRfmuipmsKDKKLuyG+wC8ABW43A153YNawNTEtw== + dependencies: + "@babel/helper-string-parser" "^7.19.4" + "@babel/helper-validator-identifier" "^7.19.1" + to-fast-properties "^2.0.0" + +"@cnakazawa/watch@^1.0.3": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a" + integrity sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ== + dependencies: + exec-sh "^0.3.2" + minimist "^1.2.0" + "@expo/vector-icons@^10.0.2": version "10.0.3" resolved "https://registry.yarnpkg.com/@expo/vector-icons/-/vector-icons-10.0.3.tgz#9dec25cf6c29871f2bb1fe932029878c221f1f75" @@ -857,55 +1228,274 @@ pouchdb-collections "^1.0.1" tiny-queue "^0.2.1" -"@react-native-community/cli@^1.2.1": - version "1.11.2" - resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-1.11.2.tgz#b14967f24a389f5a16889a747345cf0e5757a2f1" - integrity sha512-5NuYd30f5PCTrGUbZLnusZKv5nfTWvTDTRa/3Q4vwdMnUQrhm9sZXWGQ5CnFoQ7cE58EAqhj6/ShXeJF3DZ9uQ== +"@hapi/address@2.x.x": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.1.4.tgz#5d67ed43f3fd41a69d4b9ff7b56e7c0d1d0a81e5" + integrity sha512-QD1PhQk+s31P1ixsX0H0Suoupp3VMXzIVMSwobR3F3MSUO2YCV0B7xqLcUw/Bh8yuvd3LhpyqLQWTNcRmp6IdQ== + +"@hapi/bourne@1.x.x": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@hapi/bourne/-/bourne-1.3.2.tgz#0a7095adea067243ce3283e1b56b8a8f453b242a" + integrity sha512-1dVNHT76Uu5N3eJNTYcvxee+jzX4Z9lfciqRRHCU27ihbUcYi+iSc2iml5Ke1LXe1SyJCLA0+14Jh4tXJgOppA== + +"@hapi/hoek@8.x.x", "@hapi/hoek@^8.3.0": + version "8.5.1" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-8.5.1.tgz#fde96064ca446dec8c55a8c2f130957b070c6e06" + integrity sha512-yN7kbciD87WzLGc5539Tn0sApjyiGHAJgKvG9W8C7O+6c7qmoQMfVs0W4bX17eqz6C78QJqqFrtgdK5EWf6Qow== + +"@hapi/joi@^15.0.3": + version "15.1.1" + resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-15.1.1.tgz#c675b8a71296f02833f8d6d243b34c57b8ce19d7" + integrity sha512-entf8ZMOK8sc+8YfeOlM8pCfg3b5+WZIKBfUaaJT8UsjAAPjartzxIYm3TIbjvA4u+u++KbcXD38k682nVHDAQ== + dependencies: + "@hapi/address" "2.x.x" + "@hapi/bourne" "1.x.x" + "@hapi/hoek" "8.x.x" + "@hapi/topo" "3.x.x" + +"@hapi/topo@3.x.x": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-3.1.6.tgz#68d935fa3eae7fdd5ab0d7f953f3205d8b2bfc29" + integrity sha512-tAag0jEcjwH+P2quUfipd7liWCNX2F8NvYjQp2wtInsZxnMlypdw0FtAOLxtvvkO+GSRRbmNi8m/5y42PQJYCQ== + dependencies: + "@hapi/hoek" "^8.3.0" + +"@jest/console@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.9.0.tgz#79b1bc06fb74a8cfb01cbdedf945584b1b9707f0" + integrity sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ== + dependencies: + "@jest/source-map" "^24.9.0" + chalk "^2.0.1" + slash "^2.0.0" + +"@jest/fake-timers@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-24.9.0.tgz#ba3e6bf0eecd09a636049896434d306636540c93" + integrity sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A== dependencies: - chalk "^1.1.1" - commander "^2.19.0" + "@jest/types" "^24.9.0" + jest-message-util "^24.9.0" + jest-mock "^24.9.0" + +"@jest/source-map@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-24.9.0.tgz#0e263a94430be4b41da683ccc1e6bffe2a191714" + integrity sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg== + dependencies: + callsites "^3.0.0" + graceful-fs "^4.1.15" + source-map "^0.6.0" + +"@jest/test-result@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-24.9.0.tgz#11796e8aa9dbf88ea025757b3152595ad06ba0ca" + integrity sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA== + dependencies: + "@jest/console" "^24.9.0" + "@jest/types" "^24.9.0" + "@types/istanbul-lib-coverage" "^2.0.0" + +"@jest/types@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.9.0.tgz#63cb26cb7500d069e5a389441a7c6ab5e909fc59" + integrity sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^1.1.1" + "@types/yargs" "^13.0.0" + +"@jest/types@^25.5.0": + version "25.5.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-25.5.0.tgz#4d6a4793f7b9599fc3680877b856a97dbccf2a9d" + integrity sha512-OXD0RgQ86Tu3MazKo8bnrkDRaDXXMGUqd+kTtLtK1Zb7CRzQcaSRPPPV37SvYTdevXEBVxe0HXylEjs8ibkmCw== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^1.1.1" + "@types/yargs" "^15.0.0" + chalk "^3.0.0" + +"@jridgewell/gen-mapping@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" + integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + +"@jridgewell/trace-mapping@^0.3.9": + version "0.3.17" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" + integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== + dependencies: + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" + +"@react-native-community/cli-debugger-ui@^4.13.1": + version "4.13.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-4.13.1.tgz#07de6d4dab80ec49231de1f1fbf658b4ad39b32c" + integrity sha512-UFnkg5RTq3s2X15fSkrWY9+5BKOFjihNSnJjTV2H5PtTUFbd55qnxxPw8CxSfK0bXb1IrSvCESprk2LEpqr5cg== + dependencies: + serve-static "^1.13.1" + +"@react-native-community/cli-hermes@^4.13.0": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-hermes/-/cli-hermes-4.13.0.tgz#6243ed9c709dad5e523f1ccd7d21066b32f2899d" + integrity sha512-oG+w0Uby6rSGsUkJGLvMQctZ5eVRLLfhf84lLyz942OEDxFRa9U19YJxOe9FmgCKtotbYiM3P/XhK+SVCuerPQ== + dependencies: + "@react-native-community/cli-platform-android" "^4.13.0" + "@react-native-community/cli-tools" "^4.13.0" + chalk "^3.0.0" + hermes-profile-transformer "^0.0.6" + ip "^1.1.5" + +"@react-native-community/cli-platform-android@^4.13.0", "@react-native-community/cli-platform-android@^4.5.1": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-4.13.0.tgz#922681ec82ee1aadd993598b814df1152118be02" + integrity sha512-3i8sX8GklEytUZwPnojuoFbCjIRzMugCdzDIdZ9UNmi/OhD4/8mLGO0dgXfT4sMWjZwu3qjy45sFfk2zOAgHbA== + dependencies: + "@react-native-community/cli-tools" "^4.13.0" + chalk "^3.0.0" + execa "^1.0.0" + fs-extra "^8.1.0" + glob "^7.1.3" + jetifier "^1.6.2" + lodash "^4.17.15" + logkitty "^0.7.1" + slash "^3.0.0" + xmldoc "^1.1.2" + +"@react-native-community/cli-platform-ios@^4.5.0": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-4.13.0.tgz#a738915c68cac86df54e578b59a1311ea62b1aef" + integrity sha512-6THlTu8zp62efkzimfGr3VIuQJ2514o+vScZERJCV1xgEi8XtV7mb/ZKt9o6Y9WGxKKkc0E0b/aVAtgy+L27CA== + dependencies: + "@react-native-community/cli-tools" "^4.13.0" + chalk "^3.0.0" + glob "^7.1.3" + js-yaml "^3.13.1" + lodash "^4.17.15" + plist "^3.0.1" + xcode "^2.0.0" + +"@react-native-community/cli-server-api@^4.13.1": + version "4.13.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-server-api/-/cli-server-api-4.13.1.tgz#bee7ee9702afce848e9d6ca3dcd5669b99b125bd" + integrity sha512-vQzsFKD9CjHthA2ehTQX8c7uIzlI9A7ejaIow1I9RlEnLraPH2QqVDmzIdbdh5Od47UPbRzamCgAP8Bnqv3qwQ== + dependencies: + "@react-native-community/cli-debugger-ui" "^4.13.1" + "@react-native-community/cli-tools" "^4.13.0" compression "^1.7.1" connect "^3.6.5" - denodeify "^1.2.1" - envinfo "^5.7.0" errorhandler "^1.5.0" - escape-string-regexp "^1.0.5" + nocache "^2.1.0" + pretty-format "^25.1.0" + serve-static "^1.13.1" + ws "^1.1.0" + +"@react-native-community/cli-tools@^4.13.0": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-4.13.0.tgz#b406463d33af16cedc4305a9a9257ed32845cf1b" + integrity sha512-s4f489h5+EJksn4CfheLgv5PGOM0CDmK1UEBLw2t/ncWs3cW2VI7vXzndcd/WJHTv3GntJhXDcJMuL+Z2IAOgg== + dependencies: + chalk "^3.0.0" + lodash "^4.17.15" + mime "^2.4.1" + node-fetch "^2.6.0" + open "^6.2.0" + shell-quote "1.6.1" + +"@react-native-community/cli-types@^4.10.1": + version "4.10.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-4.10.1.tgz#d68a2dcd1649d3b3774823c64e5e9ce55bfbe1c9" + integrity sha512-ael2f1onoPF3vF7YqHGWy7NnafzGu+yp88BbFbP0ydoCP2xGSUzmZVw0zakPTC040Id+JQ9WeFczujMkDy6jYQ== + +"@react-native-community/cli@^4.5.1": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-4.14.0.tgz#bb106a98341bfa2db36060091ff90bfe82ea4f55" + integrity sha512-EYJKBuxFxAu/iwNUfwDq41FjORpvSh1wvQ3qsHjzcR5uaGlWEOJrd3uNJDuKBAS0TVvbEesLF9NEXipjyRVr4Q== + dependencies: + "@hapi/joi" "^15.0.3" + "@react-native-community/cli-debugger-ui" "^4.13.1" + "@react-native-community/cli-hermes" "^4.13.0" + "@react-native-community/cli-server-api" "^4.13.1" + "@react-native-community/cli-tools" "^4.13.0" + "@react-native-community/cli-types" "^4.10.1" + chalk "^3.0.0" + command-exists "^1.2.8" + commander "^2.19.0" + cosmiconfig "^5.1.0" + deepmerge "^3.2.0" + envinfo "^7.7.2" execa "^1.0.0" - fs-extra "^7.0.1" - glob "^7.1.1" + find-up "^4.1.0" + fs-extra "^8.1.0" + glob "^7.1.3" graceful-fs "^4.1.3" inquirer "^3.0.6" - lodash "^4.17.5" - metro "^0.51.0" - metro-config "^0.51.0" - metro-core "^0.51.0" - metro-memory-fs "^0.51.0" - metro-react-native-babel-transformer "^0.51.0" - mime "^1.3.4" + leven "^3.1.0" + lodash "^4.17.15" + metro "^0.59.0" + metro-config "^0.59.0" + metro-core "^0.59.0" + metro-react-native-babel-transformer "^0.59.0" + metro-resolver "^0.59.0" minimist "^1.2.0" mkdirp "^0.5.1" - morgan "^1.9.0" - node-fetch "^2.2.0" - node-notifier "^5.2.1" - opn "^3.0.2" - plist "^3.0.0" - semver "^5.0.3" + node-stream-zip "^1.9.1" + ora "^3.4.0" + pretty-format "^25.2.0" + semver "^6.3.0" serve-static "^1.13.1" - shell-quote "1.6.1" - slash "^2.0.0" - ws "^1.1.0" - xcode "^2.0.0" - xmldoc "^0.4.0" + strip-ansi "^5.2.0" + sudo-prompt "^9.0.0" + wcwidth "^1.0.1" "@types/fbemitter@^2.0.32": version "2.0.32" resolved "https://registry.yarnpkg.com/@types/fbemitter/-/fbemitter-2.0.32.tgz#8ed204da0f54e9c8eaec31b1eec91e25132d082c" integrity sha1-jtIE2g9U6cjq7DGx7skeJRMtCCw= -"@types/invariant@^2.2.29": - version "2.2.30" - resolved "https://registry.yarnpkg.com/@types/invariant/-/invariant-2.2.30.tgz#20efa342807606ada5483731a8137cb1561e5fe9" - integrity sha512-98fB+yo7imSD2F7PF7GIpELNgtLNgo5wjivu0W5V4jx+KVVJxo6p/qN4zdzSTBWy4/sN3pPyXwnhRSD28QX+ag== +"@types/invariant@^2.2.29", "@types/invariant@^2.2.35": + version "2.2.35" + resolved "https://registry.yarnpkg.com/@types/invariant/-/invariant-2.2.35.tgz#cd3ebf581a6557452735688d8daba6cf0bd5a3be" + integrity sha512-DxX1V9P8zdJPYQat1gHyY0xj3efl8gnMVjiM9iCY6y27lj+PoQWkgjt8jDqmovPqULkKVpKRg8J36iQiA+EtEg== + +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762" + integrity sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw== + +"@types/istanbul-lib-report@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" + integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^1.1.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz#e875cc689e47bce549ec81f3df5e6f6f11cfaeb2" + integrity sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw== + dependencies: + "@types/istanbul-lib-coverage" "*" + "@types/istanbul-lib-report" "*" "@types/lodash.zipobject@^4.1.4": version "4.1.6" @@ -924,6 +1514,11 @@ resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.5.3.tgz#1c3b71b091eaeaf5924538006b7f70603ce63d38" integrity sha512-Jugo5V/1bS0fRhy2z8+cUAHEyWOATaz4rbyLVvcFs7+dXp5HfwpEwzF1Q11bB10ApUqHf+yTauxI0UXQDwGrbA== +"@types/stack-utils@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" + integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw== + "@types/uuid-js@^0.7.1": version "0.7.2" resolved "https://registry.yarnpkg.com/@types/uuid-js/-/uuid-js-0.7.2.tgz#5b5552fcbaaf4acf026fb6dc66f7e5bd6b4be92f" @@ -934,6 +1529,25 @@ resolved "https://registry.yarnpkg.com/@types/websql/-/websql-0.0.27.tgz#621a666a7f02018e7cbb4abab956a25736c27d71" integrity sha1-Yhpman8CAY58u0q6uVaiVzbCfXE= +"@types/yargs-parser@*": + version "20.2.1" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.1.tgz#3b9ce2489919d9e4fea439b76916abc34b2df129" + integrity sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw== + +"@types/yargs@^13.0.0": + version "13.0.12" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.12.tgz#d895a88c703b78af0465a9de88aa92c61430b092" + integrity sha512-qCxJE1qgz2y0hA4pIxjBR+PelCH0U5CK1XJXFwCNqfmliatKp47UCXXE9Dyk1OXBDLvsCF57TqQEJaeLfDYEOQ== + dependencies: + "@types/yargs-parser" "*" + +"@types/yargs@^15.0.0": + version "15.0.14" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.14.tgz#26d821ddb89e70492160b66d10a0eb6df8f6fb06" + integrity sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ== + dependencies: + "@types/yargs-parser" "*" + "@unimodules/core@3.0.2", "@unimodules/core@~3.0.0": version "3.0.2" resolved "https://registry.yarnpkg.com/@unimodules/core/-/core-3.0.2.tgz#a2b143fb1e743809ba17c60ae1848f82b8637901" @@ -950,10 +1564,12 @@ lodash "^4.5.0" prop-types "^15.6.1" -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" absolute-path@^0.0.0: version "0.0.0" @@ -968,6 +1584,11 @@ accepts@~1.3.5, accepts@~1.3.7: mime-types "~2.1.24" negotiator "0.6.2" +anser@^1.4.9: + version "1.4.10" + resolved "https://registry.yarnpkg.com/anser/-/anser-1.4.10.tgz#befa3eddf282684bd03b63dcda3927aef8c2e35b" + integrity sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww== + ansi-colors@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-1.1.0.tgz#6374b4dd5d4718ff3ce27a671a3b1cad077132a9" @@ -987,6 +1608,15 @@ ansi-escapes@^3.0.0: resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== +ansi-fragments@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/ansi-fragments/-/ansi-fragments-0.2.1.tgz#24409c56c4cc37817c3d7caa99d8969e2de5a05e" + integrity sha512-DykbNHxuXQwUDRv5ibc2b0x7uw7wmwOGLBUd5RmaQ5z8Lhx19vwvKV+FAsM5rEA6dEcHxX+/Ad5s9eF2k2bB+w== + dependencies: + colorette "^1.0.7" + slice-ansi "^2.0.0" + strip-ansi "^5.0.0" + ansi-gray@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" @@ -1001,25 +1631,20 @@ ansi-red@^0.1.1: dependencies: ansi-wrap "0.1.0" -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" + integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== -ansi-regex@^4.0.0: +ansi-regex@^4.0.0, ansi-regex@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" @@ -1028,16 +1653,18 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + ansi-wrap@0.1.0, ansi-wrap@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= -ansi@^0.3.0, ansi@~0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/ansi/-/ansi-0.3.1.tgz#0c42d4fb17160d5a9af1e484bace1c66922c1b21" - integrity sha1-DELU+xcWDVqa8eSEus4cZpIsGyE= - anymatch@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" @@ -1046,19 +1673,6 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" -aproba@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== - -are-we-there-yet@~1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -1079,13 +1693,6 @@ arr-diff@^1.0.1: arr-flatten "^1.0.1" array-slice "^0.2.3" -arr-diff@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" - integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8= - dependencies: - arr-flatten "^1.0.1" - arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" @@ -1131,21 +1738,11 @@ array-slice@^0.2.3: resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5" integrity sha1-3Tz7gO15c6dRF82sabC5nshhhvU= -array-unique@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" - integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM= - array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= -art@^0.10.0: - version "0.10.3" - resolved "https://registry.yarnpkg.com/art/-/art-0.10.3.tgz#b01d84a968ccce6208df55a733838c96caeeaea2" - integrity sha512-HXwbdofRTiJT6qZX/FnchtldzJjS3vkLJxQilc3Xj+ma2MXjY4UAyQ0ls1XZYVnDvVIBiFZbC6QsvtW86TD6tQ== - asap@~2.0.3: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" @@ -1156,15 +1753,15 @@ assign-symbols@^1.0.0: resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= -async-limiter@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" - integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== async@^2.4.0: - version "2.6.3" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" - integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== + version "2.6.4" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" + integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== dependencies: lodash "^4.17.14" @@ -1214,7 +1811,7 @@ babel-preset-expo@^6.0.0: babel-plugin-react-native-web "^0.11.2" metro-react-native-babel-preset "^0.51.1" -babel-preset-fbjs@^3.0.1, babel-preset-fbjs@^3.2.0: +babel-preset-fbjs@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/babel-preset-fbjs/-/babel-preset-fbjs-3.2.0.tgz#c0e6347d3e0379ed84b3c2434d3467567aa05297" integrity sha512-5Jo+JeWiVz2wHUUyAlvb/sSYnXNig9r+HqGAOSfh5Fzxp7SnAaR/tEGRJ1ZX7C77kfk82658w6R5Z+uPATTD9g== @@ -1247,15 +1844,48 @@ babel-preset-fbjs@^3.0.1, babel-preset-fbjs@^3.2.0: "@babel/plugin-transform-template-literals" "^7.0.0" babel-plugin-syntax-trailing-function-commas "^7.0.0-beta.0" +babel-preset-fbjs@^3.3.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/babel-preset-fbjs/-/babel-preset-fbjs-3.4.0.tgz#38a14e5a7a3b285a3f3a86552d650dca5cf6111c" + integrity sha512-9ywCsCvo1ojrw0b+XYk7aFvTH6D9064t0RIL1rtMf3nsa02Xw41MS7sZw216Im35xj/UY0PDBQsa1brUDDF1Ow== + dependencies: + "@babel/plugin-proposal-class-properties" "^7.0.0" + "@babel/plugin-proposal-object-rest-spread" "^7.0.0" + "@babel/plugin-syntax-class-properties" "^7.0.0" + "@babel/plugin-syntax-flow" "^7.0.0" + "@babel/plugin-syntax-jsx" "^7.0.0" + "@babel/plugin-syntax-object-rest-spread" "^7.0.0" + "@babel/plugin-transform-arrow-functions" "^7.0.0" + "@babel/plugin-transform-block-scoped-functions" "^7.0.0" + "@babel/plugin-transform-block-scoping" "^7.0.0" + "@babel/plugin-transform-classes" "^7.0.0" + "@babel/plugin-transform-computed-properties" "^7.0.0" + "@babel/plugin-transform-destructuring" "^7.0.0" + "@babel/plugin-transform-flow-strip-types" "^7.0.0" + "@babel/plugin-transform-for-of" "^7.0.0" + "@babel/plugin-transform-function-name" "^7.0.0" + "@babel/plugin-transform-literals" "^7.0.0" + "@babel/plugin-transform-member-expression-literals" "^7.0.0" + "@babel/plugin-transform-modules-commonjs" "^7.0.0" + "@babel/plugin-transform-object-super" "^7.0.0" + "@babel/plugin-transform-parameters" "^7.0.0" + "@babel/plugin-transform-property-literals" "^7.0.0" + "@babel/plugin-transform-react-display-name" "^7.0.0" + "@babel/plugin-transform-react-jsx" "^7.0.0" + "@babel/plugin-transform-shorthand-properties" "^7.0.0" + "@babel/plugin-transform-spread" "^7.0.0" + "@babel/plugin-transform-template-literals" "^7.0.0" + babel-plugin-syntax-trailing-function-commas "^7.0.0-beta.0" + balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -base64-js@^1.1.2, base64-js@^1.2.3: - version "1.3.0" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" - integrity sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw== +base64-js@^1.1.2, base64-js@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== base@^0.11.1: version "0.11.2" @@ -1270,36 +1900,36 @@ base@^0.11.1: mixin-deep "^1.2.0" pascalcase "^0.1.1" -basic-auth@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.1.tgz#b998279bf47ce38344b4f3cf916d4679bbf51e3a" - integrity sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg== - dependencies: - safe-buffer "5.1.2" +big-integer@1.6.x: + version "1.6.51" + resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686" + integrity sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg== -big-integer@^1.6.7: - version "1.6.44" - resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.44.tgz#4ee9ae5f5839fc11ade338fea216b4513454a539" - integrity sha512-7MzElZPTyJ2fNvBkPxtFQ2fWIkVmuzw41+BZHSzpEq3ymB2MfeKp1+yXl/tS75xCx+WnyV+yb0kp+K1C3UNwmQ== +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" blueimp-md5@^2.10.0: version "2.11.0" resolved "https://registry.yarnpkg.com/blueimp-md5/-/blueimp-md5-2.11.0.tgz#eff55d30fe3daddd7e801072e2c4483e5fcfc87c" integrity sha512-xvA4mdnIevstCvNKTRLMOKi7L76U/X/CTs9Yz+PLWmWAC/7SuYi5Xv2J7bAhJnE2+LcLv+x4+0vusvKgM9LnZQ== -bplist-creator@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/bplist-creator/-/bplist-creator-0.0.7.tgz#37df1536092824b87c42f957b01344117372ae45" - integrity sha1-N98VNgkoJLh8QvlXsBNEEXNyrkU= +bplist-creator@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/bplist-creator/-/bplist-creator-0.1.0.tgz#018a2d1b587f769e379ef5519103730f8963ba1e" + integrity sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg== dependencies: - stream-buffers "~2.2.0" + stream-buffers "2.2.x" -bplist-parser@0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.1.1.tgz#d60d5dcc20cba6dc7e1f299b35d3e1f95dafbae6" - integrity sha1-1g1dzCDLptx+HymbNdPh+V2vuuY= +bplist-parser@0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.3.1.tgz#e1c90b2ca2a9f9474cc72f6862bbf3fee8341fd1" + integrity sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA== dependencies: - big-integer "^1.6.7" + big-integer "1.6.x" brace-expansion@^1.1.7: version "1.1.11" @@ -1309,15 +1939,6 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^1.8.2: - version "1.8.5" - resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" - integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc= - dependencies: - expand-range "^1.8.1" - preserve "^0.2.0" - repeat-element "^1.1.2" - braces@^2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" @@ -1335,13 +1956,15 @@ braces@^2.3.1: to-regex "^3.0.1" browserslist@^4.6.0, browserslist@^4.6.2: - version "4.6.6" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.6.6.tgz#6e4bf467cde520bc9dbdf3747dafa03531cec453" - integrity sha512-D2Nk3W9JL9Fp/gIcWei8LrERCS+eXu9AM5cfXA8WEZ84lFks+ARnZ0q/R69m2SV3Wjma83QDDPxsNKXUwdIsyA== + version "4.16.6" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.6.tgz#d7901277a5a88e554ed305b183ec9b0c08f66fa2" + integrity sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ== dependencies: - caniuse-lite "^1.0.30000984" - electron-to-chromium "^1.3.191" - node-releases "^1.1.25" + caniuse-lite "^1.0.30001219" + colorette "^1.2.2" + electron-to-chromium "^1.3.723" + escalade "^3.1.1" + node-releases "^1.1.71" bser@^2.0.0: version "2.1.0" @@ -1398,6 +2021,14 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" +call-bind@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + caller-callsite@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" @@ -1417,35 +2048,29 @@ callsites@^2.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= -camelcase@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" - integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -caniuse-lite@^1.0.30000984: - version "1.0.30000988" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000988.tgz#742f35ec1b8b75b9628d705d7652eea1fef983db" - integrity sha512-lPj3T8poYrRc/bniW5SQPND3GRtSrQdUM/R4mCYTbZxyi3jQiggLvZH4+BYUuX0t4TXjU+vMM7KFDQg+rSzZUQ== +camelcase@^5.0.0, camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -capture-exit@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-1.2.0.tgz#1c5fcc489fd0ab00d4f1ac7ae1072e3173fbab6f" - integrity sha1-HF/MSJ/QqwDU8ax64QcuMXP7q28= - dependencies: - rsvp "^3.3.3" +caniuse-lite@^1.0.30001219: + version "1.0.30001228" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001228.tgz#bfdc5942cd3326fa51ee0b42fbef4da9d492a7fa" + integrity sha512-QQmLOGJ3DEgokHbMSA8cj2a+geXqmnpyOFT0lhQV6P3/YOJvGDEwoedcwxEQ30gJIwIIunHIicunJ2rzK5gB2A== -chalk@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= +capture-exit@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" + integrity sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g== dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" + rsvp "^4.8.4" -chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -1454,15 +2079,23 @@ chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chardet@^0.4.0: version "0.4.2" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" integrity sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I= -chownr@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.2.tgz#a18f1e0b269c8a6a5d3c86eb298beb14c3dd7bf6" - integrity sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A== +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== class-utils@^0.3.5: version "0.3.6" @@ -1481,24 +2114,38 @@ cli-cursor@^2.1.0: dependencies: restore-cursor "^2.0.0" +cli-spinners@^2.0.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.6.0.tgz#36c7dc98fb6a9a76bd6238ec3f77e2425627e939" + integrity sha512-t+4/y50K/+4xcCRosKkA7W4gTr1MySvLV0q+PxmG7FJ5g+66ChKurYjxBCjHggHH3HA5Hh9cy+lcUGWDqVH+4Q== + cli-width@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= -cliui@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" - integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - wrap-ansi "^2.0.0" + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= collection-visit@^1.0.0: version "1.0.0" @@ -1515,17 +2162,44 @@ color-convert@^1.9.0: dependencies: color-name "1.1.3" +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + color-support@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== -commander@^2.19.0, commander@^2.9.0: +colorette@^1.0.7: + version "1.3.0" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.3.0.tgz#ff45d2f0edb244069d3b772adeb04fed38d0a0af" + integrity sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w== + +colorette@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94" + integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w== + +command-exists@^1.2.8: + version "1.2.9" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" + integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== + +commander@^2.19.0: version "2.20.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== @@ -1573,7 +2247,7 @@ compression@^1.7.1: concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== concat-stream@^1.6.0: version "1.6.2" @@ -1595,11 +2269,6 @@ connect@^3.6.5: parseurl "~1.3.3" utils-merge "1.0.1" -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - convert-source-map@^1.1.0: version "1.6.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" @@ -1646,7 +2315,7 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= -cosmiconfig@^5.0.5: +cosmiconfig@^5.0.5, cosmiconfig@^5.1.0: version "5.2.1" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== @@ -1665,7 +2334,7 @@ create-react-class@^15.6.2, create-react-class@^15.6.3: loose-envify "^1.3.1" object-assign "^4.1.1" -cross-spawn@^5.0.1, cross-spawn@^5.1.0: +cross-spawn@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= @@ -1693,6 +2362,11 @@ css-in-js-utils@^2.0.0: hyphenate-style-name "^1.0.2" isobject "^3.0.1" +dayjs@^1.8.15: + version "1.10.6" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.6.tgz#288b2aa82f2d8418a6c9d4df5898c0737ad02a63" + integrity sha512-AztC/IOW4L1Q41A86phW5Thhcrco3xuAA+YX/BLpLWWjRcTj5TOt/QImBLmCKlrF7u7k47arTnOyL6GnbG8Hvw== + debounce@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.0.tgz#44a540abc0ea9943018dc0eaa95cce87f65cd131" @@ -1705,13 +2379,6 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3: dependencies: ms "2.0.0" -debug@^3.2.6: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== - dependencies: - ms "^2.1.1" - debug@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" @@ -1719,15 +2386,15 @@ debug@^4.1.0: dependencies: ms "^2.1.1" -decamelize@^1.1.1: +decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + version "0.2.2" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" + integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== deep-assign@^3.0.0: version "3.0.0" @@ -1736,10 +2403,17 @@ deep-assign@^3.0.0: dependencies: is-obj "^1.0.0" -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== +deepmerge@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-3.3.0.tgz#d3c47fd6f3a93d517b14426b0628a17b0125f5f7" + integrity sha512-GRQOafGHwMHpjPx9iCvTgpu9NojZ49q794EEL94JVEw6VaeA8XTUyBKvAkOOjBX9oJNiV6G3P+T+tihFjo2TqA== + +defaults@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" + integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= + dependencies: + clone "^1.0.2" define-properties@^1.1.2: version "1.1.3" @@ -1770,11 +2444,6 @@ define-property@^2.0.2: is-descriptor "^1.0.2" isobject "^3.0.1" -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= - denodeify@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/denodeify/-/denodeify-1.2.1.tgz#3a36287f5034e699e7577901052c2e6c94251631" @@ -1790,11 +2459,6 @@ destroy@~1.0.4: resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= -detect-libc@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= - dom-walk@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" @@ -1805,10 +2469,20 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= -electron-to-chromium@^1.3.191: - version "1.3.211" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.211.tgz#0c39d17316bf342d1971fed68e754fa1775918f7" - integrity sha512-GZAiK3oHrs0K+LwH+HD+bdjZ17v40oQQdXbbd3dgrwgbENvazrGpcuIADSAREWnxzo9gADB1evuizrbXsnoU2Q== +electron-to-chromium@^1.3.723: + version "1.3.738" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.738.tgz#aec24b091c82acbfabbdcce08076a703941d17ca" + integrity sha512-vCMf4gDOpEylPSLPLSwAEsz+R3ShP02Y3cAKMZvTqule3XcPp7tgc/0ESI7IS6ZeyBlGClE50N53fIOkcIVnpw== + +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== encodeurl@~1.0.2: version "1.0.2" @@ -1829,18 +2503,25 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" -envinfo@^5.7.0: - version "5.12.1" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-5.12.1.tgz#83068c33e0972eb657d6bc69a6df30badefb46ef" - integrity sha512-pwdo0/G3CIkQ0y6PCXq4RdkvId2elvtPCJMG0konqlrfkWQbf1DWeH9K2b/cvu2YgGvPPTOnonZxXM1gikFu1w== +envinfo@^7.7.2: + version "7.8.1" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" + integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== -error-ex@^1.2.0, error-ex@^1.3.1: +error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== dependencies: is-arrayish "^0.2.1" +error-stack-parser@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.0.6.tgz#5a99a707bd7a4c58a797902d48d82803ede6aad8" + integrity sha512-d51brTeqC+BHlwF0BhPtcYgF5nlzf9ZZ0ZIUQNZpc9ZB9qw5IJ2diTrBY9jlCJkTLITYPjmiX6OWCwH+fuyNgQ== + dependencies: + stackframe "^1.1.1" + errorhandler@^1.5.0: version "1.5.1" resolved "https://registry.yarnpkg.com/errorhandler/-/errorhandler-1.5.1.tgz#b9ba5d17cf90744cd1e851357a6e75bf806a9a91" @@ -1849,16 +2530,33 @@ errorhandler@^1.5.0: accepts "~1.3.7" escape-html "~1.0.3" +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +eslint-plugin-relay@1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-relay/-/eslint-plugin-relay-1.4.1.tgz#5af2ac13e24bd01ad17b6a4014204918d65021cd" + integrity sha512-yb+p+4AxZTi2gXN7cZRfXMBFlRa5j6TtiVeq3yHXyy+tlgYNpxi/dDrP1+tcUTNP9vdaJovnfGZ5jp6kMiH9eg== + dependencies: + graphql "^14.0.0" + esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" @@ -1874,35 +2572,20 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= -event-target-shim@^1.0.5: - version "1.1.1" - resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-1.1.1.tgz#a86e5ee6bdaa16054475da797ccddf0c55698491" - integrity sha1-qG5e5r2qFgVEddp5fM3fDFVphJE= +event-target-shim@^5.0.0, event-target-shim@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== eventemitter3@^3.0.0: version "3.1.2" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7" integrity sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q== -exec-sh@^0.2.0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.2.tgz#2a5e7ffcbd7d0ba2755bdecb16e5a427dfbdec36" - integrity sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw== - dependencies: - merge "^1.2.0" - -execa@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" - integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= - dependencies: - cross-spawn "^5.0.1" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" +exec-sh@^0.3.2: + version "0.3.6" + resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.6.tgz#ff264f9e325519a60cb5e273692943483cca63bc" + integrity sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w== execa@^1.0.0: version "1.0.0" @@ -1917,13 +2600,6 @@ execa@^1.0.0: signal-exit "^3.0.0" strip-eof "^1.0.0" -expand-brackets@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" - integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s= - dependencies: - is-posix-bracket "^0.1.0" - expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" @@ -1937,13 +2613,6 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -expand-range@^1.8.1: - version "1.8.2" - resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" - integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc= - dependencies: - fill-range "^2.1.0" - expo-app-loader-provider@6.0.0, expo-app-loader-provider@~6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/expo-app-loader-provider/-/expo-app-loader-provider-6.0.0.tgz#c187a39942ac27cfaec3b394a5c9851d3f39678b" @@ -2096,13 +2765,6 @@ external-editor@^2.0.4: iconv-lite "^0.4.17" tmp "^0.0.33" -extglob@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" - integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE= - dependencies: - is-extglob "^1.0.0" - extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" @@ -2146,7 +2808,7 @@ fbjs-css-vars@^1.0.0: resolved "https://registry.yarnpkg.com/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz#216551136ae02fe255932c3ec8775f18e2c078b8" integrity sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ== -fbjs-scripts@^1.0.0: +fbjs-scripts@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/fbjs-scripts/-/fbjs-scripts-1.2.0.tgz#069a0c0634242d10031c6460ef1fccefcdae8b27" integrity sha512-5krZ8T0Bf8uky0abPoCLrfa7Orxd8UH4Qq8hRUF2RZYNMu+FmEOrBc7Ib3YVONmxTXTlLAvyrrdrVmksDb2OqQ== @@ -2196,21 +2858,10 @@ figures@^2.0.0: dependencies: escape-string-regexp "^1.0.5" -filename-regex@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" - integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY= - -fill-range@^2.1.0: - version "2.2.4" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" - integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q== - dependencies: - is-number "^2.1.0" - isobject "^2.0.0" - randomatic "^3.0.0" - repeat-element "^1.1.2" - repeat-string "^1.5.2" +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== fill-range@^4.0.0: version "4.0.0" @@ -2252,7 +2903,7 @@ find-cache-dir@^2.0.0: make-dir "^2.0.0" pkg-dir "^3.0.0" -find-up@^2.0.0, find-up@^2.1.0: +find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= @@ -2266,23 +2917,24 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" +find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + fontfaceobserver@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fontfaceobserver/-/fontfaceobserver-2.1.0.tgz#e2705d293e2c585a6531c2a722905657317a2991" integrity sha512-ReOsO2F66jUa0jmv2nlM/s1MiutJx/srhAe2+TE8dJCMi02ZZOcCTxTCQFr3Yet+uODUtnr4Mewg+tNQ+4V1Ng== -for-in@^1.0.1, for-in@^1.0.2: +for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= -for-own@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" - integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4= - dependencies: - for-in "^1.0.1" - fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" @@ -2304,74 +2956,46 @@ fs-extra@^1.0.0: jsonfile "^2.1.0" klaw "^1.0.0" -fs-extra@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" - integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== +fs-extra@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== dependencies: - graceful-fs "^4.1.2" + graceful-fs "^4.2.0" jsonfile "^4.0.0" universalify "^0.1.0" -fs-minipass@^1.2.5: - version "1.2.6" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.6.tgz#2c5cc30ded81282bfe8a0d7c7c1853ddeb102c07" - integrity sha512-crhvyXcMejjv3Z5d2Fa9sf5xLYVCF5O1c71QxbVnbLsmYMBEvDAftewesN/HhY03YRoA7zOMxjNGrF5svGaaeQ== - dependencies: - minipass "^2.2.1" - fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= -fsevents@^1.2.3: - version "1.2.9" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.9.tgz#3f5ed66583ccd6f400b5a00db6f7e861363e388f" - integrity sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw== +fsevents@^1.2.7: + version "1.2.13" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" + integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== dependencies: + bindings "^1.5.0" nan "^2.12.1" - node-pre-gyp "^0.12.0" function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== -gauge@~1.2.5: - version "1.2.7" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-1.2.7.tgz#e9cec5483d3d4ee0ef44b60a7d99e4935e136d93" - integrity sha1-6c7FSD09TuDvRLYKfZnkk14TbZM= - dependencies: - ansi "^0.3.0" - has-unicode "^2.0.0" - lodash.pad "^4.1.0" - lodash.padend "^4.1.0" - lodash.padstart "^4.1.0" - -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - -get-caller-file@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" - integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= +get-intrinsic@^1.0.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" + integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.3" get-stream@^4.0.0: version "4.1.0" @@ -2385,22 +3009,7 @@ get-value@^2.0.3, get-value@^2.0.6: resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= -glob-base@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" - integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q= - dependencies: - glob-parent "^2.0.0" - is-glob "^2.0.0" - -glob-parent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" - integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg= - dependencies: - is-glob "^2.0.0" - -glob@^7.1.1, glob@^7.1.2, glob@^7.1.3: +glob@^7.1.2, glob@^7.1.3: version "7.1.4" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== @@ -2425,37 +3034,42 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9: +graceful-fs@^4.1.15, graceful-fs@^4.2.0: + version "4.2.8" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" + integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== + +graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9: version "4.2.0" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.0.tgz#8d8fdc73977cb04104721cb53666c1ca64cd328b" integrity sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg== -growly@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" - integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= - -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= +graphql@^14.0.0: + version "14.7.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.7.0.tgz#7fa79a80a69be4a31c27dda824dc04dac2035a72" + integrity sha512-l0xWZpoPKpppFzMfvVyFmp9vLN7w/ZZJPefUicMCepfJeQ8sMcztloGYY9DfjVPo6tIUDzU5Hw3MUbIjj9AVVA== dependencies: - ansi-regex "^2.0.0" + iterall "^1.2.2" has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + has-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= +has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== has-value@^0.3.1: version "0.3.1" @@ -2488,16 +3102,30 @@ has-values@^1.0.0: is-number "^3.0.0" kind-of "^4.0.0" +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hermes-engine@~0.4.0: + version "0.4.3" + resolved "https://registry.yarnpkg.com/hermes-engine/-/hermes-engine-0.4.3.tgz#1754932f989daddd149172600f01e69cb8f27298" + integrity sha512-qkk85ezG+w70C3tQ4iDs22B8talvByGeJQ1VIb2KG5+rMZWVizRq6r+NYptOC/HWAFxkdYb6F3OPca7RxvjYew== + +hermes-profile-transformer@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/hermes-profile-transformer/-/hermes-profile-transformer-0.0.6.tgz#bd0f5ecceda80dd0ddaae443469ab26fb38fc27b" + integrity sha512-cnN7bQUm65UWOy6cbGcCcZ3rpwW8Q/j4OP5aWRhEry4Z2t2aR1cjrbp0BS+KiBN0smvP1caBgAuxutvyvJILzQ== + dependencies: + source-map "^0.7.3" + hoist-non-react-statics@^2.3.1: version "2.5.5" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47" integrity sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw== -hosted-git-info@^2.1.4: - version "2.7.1" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" - integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w== - http-errors@~1.7.2: version "1.7.3" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" @@ -2514,20 +3142,13 @@ hyphenate-style-name@^1.0.2: resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.3.tgz#097bb7fa0b8f1a9cf0bd5c734cf95899981a9b48" integrity sha512-EcuixamT82oplpoJ2XU4pDtKGWQ7b00CD9f1ug9IaQ3p1bkHMiKCZ9ut9QDI6qsa6cpUuB+A/I+zLtdNK4n2DQ== -iconv-lite@^0.4.17, iconv-lite@^0.4.4, iconv-lite@~0.4.13: +iconv-lite@^0.4.17, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: safer-buffer ">= 2.1.2 < 3" -ignore-walk@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" - integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ== - dependencies: - minimatch "^3.0.4" - image-size@^0.6.0: version "0.6.3" resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.6.3.tgz#e7e5c65bb534bd7cdcedd6cb5166272a85f75fb2" @@ -2546,11 +3167,6 @@ import-fresh@^2.0.0: caller-path "^2.0.0" resolve-from "^3.0.0" -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= - inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -2564,11 +3180,6 @@ inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@~2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -ini@~1.3.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== - inline-style-prefixer@^5.0.3: version "5.1.0" resolved "https://registry.yarnpkg.com/inline-style-prefixer/-/inline-style-prefixer-5.1.0.tgz#cb63195f9456dcda25cf59743e45c4d9815b0811" @@ -2603,10 +3214,10 @@ invariant@^2.2.2, invariant@^2.2.4: dependencies: loose-envify "^1.0.0" -invert-kv@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= +ip@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" + integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= is-accessor-descriptor@^0.1.6: version "0.1.6" @@ -2632,6 +3243,13 @@ is-buffer@^1.1.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -2669,18 +3287,6 @@ is-directory@^0.3.1: resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= -is-dotfile@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" - integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE= - -is-equal-shallow@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" - integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ= - dependencies: - is-primitive "^2.0.0" - is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" @@ -2693,36 +3299,15 @@ is-extendable@^1.0.1: dependencies: is-plain-object "^2.0.4" -is-extglob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA= - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= - dependencies: - number-is-nan "^1.0.0" - is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= -is-glob@^2.0.0, is-glob@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" - integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM= - dependencies: - is-extglob "^1.0.0" - -is-number@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= - dependencies: - kind-of "^3.0.2" +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== is-number@^3.0.0: version "3.0.0" @@ -2731,11 +3316,6 @@ is-number@^3.0.0: dependencies: kind-of "^3.0.2" -is-number@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" - integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== - is-obj@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" @@ -2748,16 +3328,6 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" -is-posix-bracket@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" - integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q= - -is-primitive@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" - integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= - is-promise@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" @@ -2808,44 +3378,104 @@ isomorphic-fetch@^2.1.1: node-fetch "^1.0.1" whatwg-fetch ">=0.10.0" -jest-haste-map@24.0.0-alpha.6: - version "24.0.0-alpha.6" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.0.0-alpha.6.tgz#fb2c785080f391b923db51846b86840d0d773076" - integrity sha512-+NO2HMbjvrG8BC39ieLukdpFrcPhhjCJGhpbHodHNZygH1Tt06WrlNYGpZtWKx/zpf533tCtMQXO/q59JenjNw== +iterall@^1.2.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.3.0.tgz#afcb08492e2915cbd8a0884eb93a8c94d0d72fea" + integrity sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg== + +jest-get-type@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.9.0.tgz#1684a0c8a50f2e4901b6644ae861f579eed2ef0e" + integrity sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q== + +jest-haste-map@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.9.0.tgz#b38a5d64274934e21fa417ae9a9fbeb77ceaac7d" + integrity sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ== dependencies: + "@jest/types" "^24.9.0" + anymatch "^2.0.0" fb-watchman "^2.0.0" - graceful-fs "^4.1.11" + graceful-fs "^4.1.15" invariant "^2.2.4" - jest-serializer "^24.0.0-alpha.6" - jest-worker "^24.0.0-alpha.6" - micromatch "^2.3.11" - sane "^3.0.0" - -jest-serializer@24.0.0-alpha.6: - version "24.0.0-alpha.6" - resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.0.0-alpha.6.tgz#27d2fee4b1a85698717a30c3ec2ab80767312597" - integrity sha512-IPA5T6/GhlE6dedSk7Cd7YfuORnYjN0VD5iJVFn1Q81RJjpj++Hen5kJbKcg547vXsQ1TddV15qOA/zeIfOCLw== - -jest-serializer@^24.0.0-alpha.6: - version "24.4.0" - resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.4.0.tgz#f70c5918c8ea9235ccb1276d232e459080588db3" - integrity sha512-k//0DtglVstc1fv+GY/VHDIjrtNjdYvYjMlbLUed4kxrE92sIUewOi5Hj3vrpB8CXfkJntRPDRjCrCvUhBdL8Q== - -jest-worker@24.0.0-alpha.6: - version "24.0.0-alpha.6" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.0.0-alpha.6.tgz#463681b92c117c57107135c14b9b9d6cd51d80ce" - integrity sha512-iXtH7MR9bjWlNnlnRBcrBRrb4cSVxML96La5vsnmBvDI+mJnkP5uEt6Fgpo5Y8f3z9y2Rd7wuPnKRxqQsiU/dA== + jest-serializer "^24.9.0" + jest-util "^24.9.0" + jest-worker "^24.9.0" + micromatch "^3.1.10" + sane "^4.0.3" + walker "^1.0.7" + optionalDependencies: + fsevents "^1.2.7" + +jest-message-util@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.9.0.tgz#527f54a1e380f5e202a8d1149b0ec872f43119e3" + integrity sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw== dependencies: - merge-stream "^1.0.1" + "@babel/code-frame" "^7.0.0" + "@jest/test-result" "^24.9.0" + "@jest/types" "^24.9.0" + "@types/stack-utils" "^1.0.1" + chalk "^2.0.1" + micromatch "^3.1.10" + slash "^2.0.0" + stack-utils "^1.0.1" + +jest-mock@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.9.0.tgz#c22835541ee379b908673ad51087a2185c13f1c6" + integrity sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w== + dependencies: + "@jest/types" "^24.9.0" + +jest-serializer@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.9.0.tgz#e6d7d7ef96d31e8b9079a714754c5d5c58288e73" + integrity sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ== + +jest-util@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.9.0.tgz#7396814e48536d2e85a37de3e4c431d7cb140162" + integrity sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg== + dependencies: + "@jest/console" "^24.9.0" + "@jest/fake-timers" "^24.9.0" + "@jest/source-map" "^24.9.0" + "@jest/test-result" "^24.9.0" + "@jest/types" "^24.9.0" + callsites "^3.0.0" + chalk "^2.0.1" + graceful-fs "^4.1.15" + is-ci "^2.0.0" + mkdirp "^0.5.1" + slash "^2.0.0" + source-map "^0.6.0" -jest-worker@^24.0.0-alpha.6: - version "24.6.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.6.0.tgz#7f81ceae34b7cde0c9827a6980c35b7cdc0161b3" - integrity sha512-jDwgW5W9qGNvpI1tNnvajh0a5IE/PuGLFmHk6aR/BZFz8tSgGw17GsDPXAJ6p91IvYDjOw8GpFbvvZGAK+DPQQ== +jest-validate@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-24.9.0.tgz#0775c55360d173cd854e40180756d4ff52def8ab" + integrity sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ== dependencies: - merge-stream "^1.0.1" + "@jest/types" "^24.9.0" + camelcase "^5.3.1" + chalk "^2.0.1" + jest-get-type "^24.9.0" + leven "^3.1.0" + pretty-format "^24.9.0" + +jest-worker@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.9.0.tgz#5dbfdb5b2d322e98567898238a9697bcce67b3e5" + integrity sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw== + dependencies: + merge-stream "^2.0.0" supports-color "^6.1.0" +jetifier@^1.6.2: + version "1.6.8" + resolved "https://registry.yarnpkg.com/jetifier/-/jetifier-1.6.8.tgz#e88068697875cbda98c32472902c4d3756247798" + integrity sha512-3Zi16h6L5tXDRQJTb221cnRoVG9/9OvreLdLU2/ZjRv/GILL+2Cemt0IKvkowwkDpvouAU1DQPOJ7qaiHeIdrw== + js-levenshtein@^1.1.3: version "1.1.6" resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" @@ -2864,6 +3494,11 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" +jsc-android@^245459.0.0: + version "245459.0.0" + resolved "https://registry.yarnpkg.com/jsc-android/-/jsc-android-245459.0.0.tgz#e584258dd0b04c9159a27fb104cd5d491fd202c9" + integrity sha512-wkjURqwaB1daNkDi2OYYbsLnIdC/lUM2nPXQKRs5pqEU9chDg435bjvo+LSaHotDENygHQDHe+ntUkkw2gwMtg== + jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -2953,22 +3588,10 @@ klaw@^1.0.0: optionalDependencies: graceful-fs "^4.1.9" -lcid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= - dependencies: - invert-kv "^1.0.0" - -load-json-file@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" - integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - strip-bom "^3.0.0" +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== locate-path@^2.0.0: version "2.0.0" @@ -2986,30 +3609,43 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" -lodash.pad@^4.1.0: - version "4.5.1" - resolved "https://registry.yarnpkg.com/lodash.pad/-/lodash.pad-4.5.1.tgz#4330949a833a7c8da22cc20f6a26c4d59debba70" - integrity sha1-QzCUmoM6fI2iLMIPaibE1Z3runA= - -lodash.padend@^4.1.0: - version "4.6.1" - resolved "https://registry.yarnpkg.com/lodash.padend/-/lodash.padend-4.6.1.tgz#53ccba047d06e158d311f45da625f4e49e6f166e" - integrity sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4= +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" -lodash.padstart@^4.1.0: - version "4.6.1" - resolved "https://registry.yarnpkg.com/lodash.padstart/-/lodash.padstart-4.6.1.tgz#d2e3eebff0d9d39ad50f5cbd1b52a7bce6bb611b" - integrity sha1-0uPuv/DZ05rVD1y9G1KnvOa7YRs= +lodash.isequal@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== lodash.throttle@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ= -lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0, lodash@^4.5.0, lodash@^4.6.0, lodash@^4.6.1: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" - integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== +lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.3.0, lodash@^4.5.0, lodash@^4.6.0, lodash@^4.6.1: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log-symbols@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" + integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== + dependencies: + chalk "^2.0.1" + +logkitty@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/logkitty/-/logkitty-0.7.1.tgz#8e8d62f4085a826e8d38987722570234e33c6aa7" + integrity sha512-/3ER20CTTbahrCrpYfPn7Xavv9diBROZpoXGVZDWMw4b/X4uuUwAC0ki85tgsdMRONURyIJbcOvS94QsUBYPbQ== + dependencies: + ansi-fragments "^0.2.1" + dayjs "^1.8.15" + yargs "^15.1.0" loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1, loose-envify@^1.4.0: version "1.4.0" @@ -3053,11 +3689,6 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" -math-random@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c" - integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A== - md5-file@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/md5-file/-/md5-file-3.2.3.tgz#f9bceb941eca2214a4c0727f5e700314e770f06f" @@ -3065,13 +3696,6 @@ md5-file@^3.2.3: dependencies: buffer-alloc "^1.1.0" -mem@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" - integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y= - dependencies: - mimic-fn "^1.0.0" - merge-stream@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" @@ -3079,15 +3703,15 @@ merge-stream@^1.0.1: dependencies: readable-stream "^2.0.1" -merge@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.1.tgz#38bebf80c3220a8a487b6fcfb3941bb11720c145" - integrity sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ== +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -metro-babel-register@0.51.0: - version "0.51.0" - resolved "https://registry.yarnpkg.com/metro-babel-register/-/metro-babel-register-0.51.0.tgz#d86d3f2d90b45c7a3c6ae67a53bd1e50bad7a24d" - integrity sha512-rhdvHFOZ7/ub019A3+aYs8YeLydb02/FAMsKr2Nz2Jlf6VUxWrMnrcT0NYX16F9TGdi2ulRlJ9dwvUmdhkk+Bw== +metro-babel-register@0.58.0: + version "0.58.0" + resolved "https://registry.yarnpkg.com/metro-babel-register/-/metro-babel-register-0.58.0.tgz#5c44786d49a044048df56cf476a2263491d4f53a" + integrity sha512-P5+G3ufhSYL6cA3a7xkbSJzzFBvtivj/PhWvGXFXnuFssDlMAX1CTktff+0gpka5Cd6B6QLt0UAMWulUAAE4Eg== dependencies: "@babel/core" "^7.0.0" "@babel/plugin-proposal-class-properties" "^7.0.0" @@ -3102,26 +3726,35 @@ metro-babel-register@0.51.0: core-js "^2.2.2" escape-string-regexp "^1.0.5" -metro-babel-transformer@0.51.0: - version "0.51.0" - resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.51.0.tgz#9ee5199163ac46b2057527b3f8cbd8b089ffc03e" - integrity sha512-M7KEY/hjD3E8tJEliWgI0VOSaJtqaznC0ItM6FiMrhoGDqqa1BvGofl+EPcKqjBSOV1UgExua/T1VOIWbjwQsw== +metro-babel-register@0.59.0: + version "0.59.0" + resolved "https://registry.yarnpkg.com/metro-babel-register/-/metro-babel-register-0.59.0.tgz#2bcff65641b36794cf083ba732fbc46cf870fb43" + integrity sha512-JtWc29erdsXO/V3loenXKw+aHUXgj7lt0QPaZKPpctLLy8kcEpI/8pfXXgVK9weXICCpCnYtYncIosAyzh0xjg== dependencies: "@babel/core" "^7.0.0" + "@babel/plugin-proposal-class-properties" "^7.0.0" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.0.0" + "@babel/plugin-proposal-optional-chaining" "^7.0.0" + "@babel/plugin-transform-flow-strip-types" "^7.0.0" + "@babel/plugin-transform-modules-commonjs" "^7.0.0" + "@babel/register" "^7.0.0" + escape-string-regexp "^1.0.5" -metro-babel-transformer@0.51.1: - version "0.51.1" - resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.51.1.tgz#97be9e2b96c78aa202b52ae05fb86f71327aef72" - integrity sha512-+tOnZZzOzufB86ASdfimUEGB1jBKsdsVpPdjNJZkueTFyvYlGqWDQKHM1w9bwKMeM/czPQ48Y6m8Bou6le0X4w== +metro-babel-transformer@0.58.0: + version "0.58.0" + resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.58.0.tgz#317c83b863cceb0573943815f1711fbcbe69b106" + integrity sha512-yBX3BkRhw2TCNPhe+pmLSgsAEA3huMvnX08UwjFqSXXI1aiqzRQobn92uKd1U5MM1Vx8EtXVomlJb95ZHNAv6A== dependencies: "@babel/core" "^7.0.0" + metro-source-map "0.58.0" -metro-babel7-plugin-react-transform@0.51.0: - version "0.51.0" - resolved "https://registry.yarnpkg.com/metro-babel7-plugin-react-transform/-/metro-babel7-plugin-react-transform-0.51.0.tgz#af27dd81666b91f05d2b371b0d6d283c585e38b6" - integrity sha512-dZ95kXcE2FJMoRsYhxr7YLCbOlHWKwe0bOpihRhfImDTgFfuKIzU4ROQwMUbE0NCbzB+ATFsa2FZ3pHDJ5GI0w== +metro-babel-transformer@0.59.0: + version "0.59.0" + resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.59.0.tgz#dda99c75d831b00142c42c020c51c103b29f199d" + integrity sha512-fdZJl8rs54GVFXokxRdD7ZrQ1TJjxWzOi/xSP25VR3E8tbm3nBZqS+/ylu643qSr/IueABR+jrlqAyACwGEf6w== dependencies: - "@babel/helper-module-imports" "^7.0.0" + "@babel/core" "^7.0.0" + metro-source-map "0.59.0" metro-babel7-plugin-react-transform@0.51.1: version "0.51.1" @@ -3130,53 +3763,58 @@ metro-babel7-plugin-react-transform@0.51.1: dependencies: "@babel/helper-module-imports" "^7.0.0" -metro-cache@0.51.1: - version "0.51.1" - resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.51.1.tgz#d0b296eab8e009214413bba87e4eac3d9b44cd04" - integrity sha512-0m1+aicsw77LVAehNuTxDpE1c/7Xv/ajRD+UL/lFCWUxnrjSbxVtIKr8l5DxEY11082c1axVRuaV9e436W+eXg== +metro-cache@0.59.0: + version "0.59.0" + resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.59.0.tgz#ef3c055f276933979b731455dc8317d7a66f0f2d" + integrity sha512-ryWNkSnpyADfRpHGb8BRhQ3+k8bdT/bsxMH2O0ntlZYZ188d8nnYWmxbRvFmEzToJxe/ol4uDw0tJFAaQsN8KA== dependencies: - jest-serializer "24.0.0-alpha.6" - metro-core "0.51.1" + jest-serializer "^24.9.0" + metro-core "0.59.0" mkdirp "^0.5.1" rimraf "^2.5.4" -metro-config@0.51.1, metro-config@^0.51.0: - version "0.51.1" - resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.51.1.tgz#8f1a241ce2c0b521cd492c39bc5c6c69e3397b82" - integrity sha512-WCNd0tTI9gb/ubgTqK1+ljZL4b3hsXVinsOAtep4nHiVb6DSDdbO2yXDD2rpYx3NE6hDRMFS9HHg6G0139pAqQ== +metro-config@0.59.0, metro-config@^0.59.0: + version "0.59.0" + resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.59.0.tgz#9844e388069321dd7403e49f0d495a81f9aa0fef" + integrity sha512-MDsknFG9vZ4Nb5VR6OUDmGHaWz6oZg/FtE3up1zVBKPVRTXE1Z+k7zypnPtMXjMh3WHs/Sy4+wU1xnceE/zdnA== dependencies: cosmiconfig "^5.0.5" - metro "0.51.1" - metro-cache "0.51.1" - metro-core "0.51.1" - pretty-format "24.0.0-alpha.6" + jest-validate "^24.9.0" + metro "0.59.0" + metro-cache "0.59.0" + metro-core "0.59.0" -metro-core@0.51.1, metro-core@^0.51.0: - version "0.51.1" - resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.51.1.tgz#e7227fb1dd1bb3f953272fad9876e6201140b038" - integrity sha512-sG1yACjdFqmIzZN50HqLTKUMp1oy0AehHhmIuYeIllo1DjX6Y2o3UAT3rGP8U+SAqJGXf/OWzl6VNyRPGDENfA== +metro-core@0.59.0, metro-core@^0.59.0: + version "0.59.0" + resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.59.0.tgz#958cde3fe5c8cd84a78e1899af801ad69e9c83b1" + integrity sha512-kb5LKvV5r2pqMEzGyTid8ai2mIjW13NMduQ8oBmfha7/EPTATcTQ//s+bkhAs1toQD8vqVvjAb0cPNjWQEmcmQ== dependencies: - jest-haste-map "24.0.0-alpha.6" + jest-haste-map "^24.9.0" lodash.throttle "^4.1.1" - metro-resolver "0.51.1" + metro-resolver "0.59.0" wordwrap "^1.0.0" -metro-memory-fs@^0.51.0: - version "0.51.1" - resolved "https://registry.yarnpkg.com/metro-memory-fs/-/metro-memory-fs-0.51.1.tgz#624291f5956b0fd11532d80b1b85d550926f96c9" - integrity sha512-dXVUpLPLwfQcYHd1HlqHGVzBsiwvUdT92TDSbdc10152TP+iynHBqLDWbxt0MAtd6c/QXwOuGZZ1IcX3+lv5iw== +metro-inspector-proxy@0.59.0: + version "0.59.0" + resolved "https://registry.yarnpkg.com/metro-inspector-proxy/-/metro-inspector-proxy-0.59.0.tgz#39d1390772d13767fc595be9a1a7074e2425cf8e" + integrity sha512-hPeAuQcofTOH0F+2GEZqWkvkVY1/skezSSlMocDQDaqds+Kw6JgdA7FlZXxnKmQ/jYrWUzff/pl8SUCDwuYthQ== + dependencies: + connect "^3.6.5" + debug "^2.2.0" + ws "^1.1.5" + yargs "^14.2.0" -metro-minify-uglify@0.51.1: - version "0.51.1" - resolved "https://registry.yarnpkg.com/metro-minify-uglify/-/metro-minify-uglify-0.51.1.tgz#60cd8fe4d3e82d6670c717b8ddb52ae63199c0e4" - integrity sha512-HAqd/rFrQ6mnbqVAszDXIKTg2rqHlY9Fm8DReakgbkAeyMbF2mH3kEgtesPmTrhajdFk81UZcNSm6wxj1JMgVg== +metro-minify-uglify@0.59.0: + version "0.59.0" + resolved "https://registry.yarnpkg.com/metro-minify-uglify/-/metro-minify-uglify-0.59.0.tgz#6491876308d878742f7b894d7fca4af356886dd5" + integrity sha512-7IzVgCVWZMymgZ/quieg/9v5EQ8QmZWAgDc86Zp9j0Vy6tQTjUn6jlU+YAKW3mfMEjMr6iIUzCD8YklX78tFAw== dependencies: uglify-es "^3.1.9" -metro-react-native-babel-preset@0.51.0: - version "0.51.0" - resolved "https://registry.yarnpkg.com/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.51.0.tgz#978d960acf2d214bbbe43e59145878d663bd07de" - integrity sha512-Y/aPeLl4RzY8IEAneOyDcpdjto/8yjIuX9eUWRngjSqdHYhGQtqiSBpfTpo0BvXpwNRLwCLHyXo58gNpckTJFw== +metro-react-native-babel-preset@0.58.0: + version "0.58.0" + resolved "https://registry.yarnpkg.com/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.58.0.tgz#18f48d33fe124280ffabc000ab8b42c488d762a2" + integrity sha512-MRriNW+fF6jxABsgPphocUY6mIhmCm8idcrQZ58fT3Iti2vCdtkaK32TyCGUNUptzhUe2/cbE57j4aC+eaodAA== dependencies: "@babel/plugin-proposal-class-properties" "^7.0.0" "@babel/plugin-proposal-export-default-from" "^7.0.0" @@ -3186,6 +3824,7 @@ metro-react-native-babel-preset@0.51.0: "@babel/plugin-proposal-optional-chaining" "^7.0.0" "@babel/plugin-syntax-dynamic-import" "^7.0.0" "@babel/plugin-syntax-export-default-from" "^7.0.0" + "@babel/plugin-syntax-flow" "^7.2.0" "@babel/plugin-transform-arrow-functions" "^7.0.0" "@babel/plugin-transform-block-scoping" "^7.0.0" "@babel/plugin-transform-classes" "^7.0.0" @@ -3208,13 +3847,56 @@ metro-react-native-babel-preset@0.51.0: "@babel/plugin-transform-spread" "^7.0.0" "@babel/plugin-transform-sticky-regex" "^7.0.0" "@babel/plugin-transform-template-literals" "^7.0.0" - "@babel/plugin-transform-typescript" "^7.0.0" + "@babel/plugin-transform-typescript" "^7.5.0" "@babel/plugin-transform-unicode-regex" "^7.0.0" "@babel/template" "^7.0.0" - metro-babel7-plugin-react-transform "0.51.0" - react-transform-hmr "^1.0.4" + react-refresh "^0.4.0" + +metro-react-native-babel-preset@0.59.0: + version "0.59.0" + resolved "https://registry.yarnpkg.com/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.59.0.tgz#20e020bc6ac9849e1477de1333d303ed42aba225" + integrity sha512-BoO6ncPfceIDReIH8pQ5tQptcGo5yRWQXJGVXfANbiKLq4tfgdZB1C1e2rMUJ6iypmeJU9dzl+EhPmIFKtgREg== + dependencies: + "@babel/plugin-proposal-class-properties" "^7.0.0" + "@babel/plugin-proposal-export-default-from" "^7.0.0" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.0.0" + "@babel/plugin-proposal-object-rest-spread" "^7.0.0" + "@babel/plugin-proposal-optional-catch-binding" "^7.0.0" + "@babel/plugin-proposal-optional-chaining" "^7.0.0" + "@babel/plugin-syntax-dynamic-import" "^7.0.0" + "@babel/plugin-syntax-export-default-from" "^7.0.0" + "@babel/plugin-syntax-flow" "^7.2.0" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.0.0" + "@babel/plugin-syntax-optional-chaining" "^7.0.0" + "@babel/plugin-transform-arrow-functions" "^7.0.0" + "@babel/plugin-transform-block-scoping" "^7.0.0" + "@babel/plugin-transform-classes" "^7.0.0" + "@babel/plugin-transform-computed-properties" "^7.0.0" + "@babel/plugin-transform-destructuring" "^7.0.0" + "@babel/plugin-transform-exponentiation-operator" "^7.0.0" + "@babel/plugin-transform-flow-strip-types" "^7.0.0" + "@babel/plugin-transform-for-of" "^7.0.0" + "@babel/plugin-transform-function-name" "^7.0.0" + "@babel/plugin-transform-literals" "^7.0.0" + "@babel/plugin-transform-modules-commonjs" "^7.0.0" + "@babel/plugin-transform-object-assign" "^7.0.0" + "@babel/plugin-transform-parameters" "^7.0.0" + "@babel/plugin-transform-react-display-name" "^7.0.0" + "@babel/plugin-transform-react-jsx" "^7.0.0" + "@babel/plugin-transform-react-jsx-self" "^7.0.0" + "@babel/plugin-transform-react-jsx-source" "^7.0.0" + "@babel/plugin-transform-regenerator" "^7.0.0" + "@babel/plugin-transform-runtime" "^7.0.0" + "@babel/plugin-transform-shorthand-properties" "^7.0.0" + "@babel/plugin-transform-spread" "^7.0.0" + "@babel/plugin-transform-sticky-regex" "^7.0.0" + "@babel/plugin-transform-template-literals" "^7.0.0" + "@babel/plugin-transform-typescript" "^7.5.0" + "@babel/plugin-transform-unicode-regex" "^7.0.0" + "@babel/template" "^7.0.0" + react-refresh "^0.4.0" -metro-react-native-babel-preset@0.51.1, metro-react-native-babel-preset@^0.51.1: +metro-react-native-babel-preset@^0.51.1: version "0.51.1" resolved "https://registry.yarnpkg.com/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.51.1.tgz#44aeeedfea37f7c2ab8f6f273fa71b90fe65f089" integrity sha512-e9tsYDFhU70gar0jQWcZXRPJVCv4k7tEs6Pm74wXO2OO/T1MEumbvniDIGwGG8bG8RUnYdHhjcaiub2Vc5BRWw== @@ -3255,47 +3937,91 @@ metro-react-native-babel-preset@0.51.1, metro-react-native-babel-preset@^0.51.1: metro-babel7-plugin-react-transform "0.51.1" react-transform-hmr "^1.0.4" -metro-react-native-babel-transformer@0.51.0: - version "0.51.0" - resolved "https://registry.yarnpkg.com/metro-react-native-babel-transformer/-/metro-react-native-babel-transformer-0.51.0.tgz#57a695e97a19d95de63c9633f9d0dc024ee8e99a" - integrity sha512-VFnqtE0qrVmU1HV9B04o53+NZHvDwR+CWCoEx4+7vCqJ9Tvas741biqCjah9xtifoKdElQELk6x0soOAWCDFJA== +metro-react-native-babel-transformer@0.58.0: + version "0.58.0" + resolved "https://registry.yarnpkg.com/metro-react-native-babel-transformer/-/metro-react-native-babel-transformer-0.58.0.tgz#5da0e5a1b83c01d11626905fa59f34fda53a21a5" + integrity sha512-3A73+cRq1eUPQ8g+hPNGgMUMCGmtQjwqHfoG1DwinAoJ/kr4WOXWWbGZo0xHJNBe/zdHGl0uHcDCp2knPglTdQ== dependencies: "@babel/core" "^7.0.0" - babel-preset-fbjs "^3.0.1" - metro-babel-transformer "0.51.0" - metro-react-native-babel-preset "0.51.0" + babel-preset-fbjs "^3.3.0" + metro-babel-transformer "0.58.0" + metro-react-native-babel-preset "0.58.0" + metro-source-map "0.58.0" -metro-react-native-babel-transformer@^0.51.0: - version "0.51.1" - resolved "https://registry.yarnpkg.com/metro-react-native-babel-transformer/-/metro-react-native-babel-transformer-0.51.1.tgz#bac34f988c150c725cd1875c13701cc2032615f9" - integrity sha512-D0KU+JPb/Z76nUWt3+bkjKggOlGvqAVI2BpIH2JFKprpUyBjWaCRqHnkBfZGixYwUfmu93MIlKJWr6iKzzFrlg== +metro-react-native-babel-transformer@^0.59.0: + version "0.59.0" + resolved "https://registry.yarnpkg.com/metro-react-native-babel-transformer/-/metro-react-native-babel-transformer-0.59.0.tgz#9b3dfd6ad35c6ef37fc4ce4d20a2eb67fabbb4be" + integrity sha512-1O3wrnMq4NcPQ1asEcl9lRDn/t+F1Oef6S9WaYVIKEhg9m/EQRGVrrTVP+R6B5Eeaj3+zNKbzM8Dx/NWy1hUbQ== dependencies: "@babel/core" "^7.0.0" - babel-preset-fbjs "^3.0.1" - metro-babel-transformer "0.51.1" - metro-react-native-babel-preset "0.51.1" + babel-preset-fbjs "^3.3.0" + metro-babel-transformer "0.59.0" + metro-react-native-babel-preset "0.59.0" + metro-source-map "0.59.0" + +metro-resolver@0.59.0, metro-resolver@^0.59.0: + version "0.59.0" + resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.59.0.tgz#fbc9d7c95f094c52807877d0011feffb9e896fad" + integrity sha512-lbgiumnwoVosffEI96z0FGuq1ejTorHAj3QYUPmp5dFMfitRxLP7Wm/WP9l4ZZjIptxTExsJwuEff1SLRCPD9w== + dependencies: + absolute-path "^0.0.0" + +metro-source-map@0.58.0: + version "0.58.0" + resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.58.0.tgz#e951b99f4c653239ce9323bb08339c6f1978a112" + integrity sha512-yvN1YPmejmgiiS7T1aKBiiUTHPw2Vcm3r2TZ+DY92z/9PR4alysIywrCs/fTHs8rbDcKM5VfPCKGLpkBrbKeOw== + dependencies: + "@babel/traverse" "^7.0.0" + "@babel/types" "^7.0.0" + invariant "^2.2.4" + metro-symbolicate "0.58.0" + ob1 "0.58.0" + source-map "^0.5.6" + vlq "^1.0.0" + +metro-source-map@0.59.0: + version "0.59.0" + resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.59.0.tgz#e9beb9fc51bfb4e060f95820cf1508fc122d23f7" + integrity sha512-0w5CmCM+ybSqXIjqU4RiK40t4bvANL6lafabQ2GP2XD3vSwkLY+StWzCtsb4mPuyi9R/SgoLBel+ZOXHXAH0eQ== + dependencies: + "@babel/traverse" "^7.0.0" + "@babel/types" "^7.0.0" + invariant "^2.2.4" + metro-symbolicate "0.59.0" + ob1 "0.59.0" + source-map "^0.5.6" + vlq "^1.0.0" -metro-resolver@0.51.1: - version "0.51.1" - resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.51.1.tgz#4c26f0baee47d30250187adca3d34c902e627611" - integrity sha512-zmWbD/287NDA/jLPuPV0hne/YMMSG0dljzu21TYMg2lXRLur/zROJHHhyepZvuBHgInXBi4Vhr2wvuSnY39SuA== +metro-symbolicate@0.58.0: + version "0.58.0" + resolved "https://registry.yarnpkg.com/metro-symbolicate/-/metro-symbolicate-0.58.0.tgz#ba9fd52549c41fc1b656adaad7c8875726dd5abe" + integrity sha512-uIVxUQC1E26qOMj13dKROhwAa2FmZk5eR0NcBqej/aXmQhpr8LjJg2sondkoLKUp827Tf/Fm9+pS4icb5XiqCw== dependencies: - absolute-path "^0.0.0" + invariant "^2.2.4" + metro-source-map "0.58.0" + source-map "^0.5.6" + through2 "^2.0.1" + vlq "^1.0.0" -metro-source-map@0.51.1: - version "0.51.1" - resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.51.1.tgz#1a8da138e98e184304d5558b4f92a5c2141822d0" - integrity sha512-JyrE+RV4YumrboHPHTGsUUGERjQ681ImRLrSYDGcmNv4tfpk9nvAK26UAas4IvBYFCC9oW90m0udt3kaQGv59Q== +metro-symbolicate@0.59.0: + version "0.59.0" + resolved "https://registry.yarnpkg.com/metro-symbolicate/-/metro-symbolicate-0.59.0.tgz#fc7f93957a42b02c2bfc57ed1e8f393f5f636a54" + integrity sha512-asLaF2A7rndrToGFIknL13aiohwPJ95RKHf0NM3hP/nipiLDoMzXT6ZnQvBqDxkUKyP+51AI75DMtb+Wcyw4Bw== dependencies: + invariant "^2.2.4" + metro-source-map "0.59.0" source-map "^0.5.6" + through2 "^2.0.1" + vlq "^1.0.0" -metro@0.51.1, metro@^0.51.0: - version "0.51.1" - resolved "https://registry.yarnpkg.com/metro/-/metro-0.51.1.tgz#b0aad4731593b9f244261bad1abb2a006d1c8969" - integrity sha512-nM0dqn8LQlMjhChl2fzTUq2EWiUebZM7nkesD9vQe47W10bj/tbRLPiIIAxht6SRDbPd/hRA+t39PxLhPSKEKg== +metro@0.59.0, metro@^0.59.0: + version "0.59.0" + resolved "https://registry.yarnpkg.com/metro/-/metro-0.59.0.tgz#64a87cd61357814a4f279518e0781b1eab5934b8" + integrity sha512-OpVgYXyuTvouusFZQJ/UYKEbwfLmialrSCUUTGTFaBor6UMUHZgXPYtK86LzesgMqRc8aiuTQVO78iKW2Iz3wg== dependencies: + "@babel/code-frame" "^7.0.0" "@babel/core" "^7.0.0" - "@babel/generator" "^7.0.0" + "@babel/generator" "^7.5.0" "@babel/parser" "^7.0.0" "@babel/plugin-external-helpers" "^7.0.0" "@babel/template" "^7.0.0" @@ -3303,69 +4029,54 @@ metro@0.51.1, metro@^0.51.0: "@babel/types" "^7.0.0" absolute-path "^0.0.0" async "^2.4.0" - babel-preset-fbjs "^3.0.1" + babel-preset-fbjs "^3.3.0" buffer-crc32 "^0.2.13" chalk "^2.4.1" + ci-info "^2.0.0" concat-stream "^1.6.0" connect "^3.6.5" debug "^2.2.0" denodeify "^1.2.1" + error-stack-parser "^2.0.6" eventemitter3 "^3.0.0" fbjs "^1.0.0" fs-extra "^1.0.0" graceful-fs "^4.1.3" image-size "^0.6.0" invariant "^2.2.4" - jest-haste-map "24.0.0-alpha.6" - jest-worker "24.0.0-alpha.6" + jest-haste-map "^24.9.0" + jest-worker "^24.9.0" json-stable-stringify "^1.0.1" lodash.throttle "^4.1.1" merge-stream "^1.0.1" - metro-babel-transformer "0.51.1" - metro-cache "0.51.1" - metro-config "0.51.1" - metro-core "0.51.1" - metro-minify-uglify "0.51.1" - metro-react-native-babel-preset "0.51.1" - metro-resolver "0.51.1" - metro-source-map "0.51.1" + metro-babel-register "0.59.0" + metro-babel-transformer "0.59.0" + metro-cache "0.59.0" + metro-config "0.59.0" + metro-core "0.59.0" + metro-inspector-proxy "0.59.0" + metro-minify-uglify "0.59.0" + metro-react-native-babel-preset "0.59.0" + metro-resolver "0.59.0" + metro-source-map "0.59.0" + metro-symbolicate "0.59.0" mime-types "2.1.11" mkdirp "^0.5.1" node-fetch "^2.2.0" - nullthrows "^1.1.0" - react-transform-hmr "^1.0.4" + nullthrows "^1.1.1" resolve "^1.5.0" rimraf "^2.5.4" serialize-error "^2.1.0" source-map "^0.5.6" + strip-ansi "^4.0.0" temp "0.8.3" throat "^4.1.0" wordwrap "^1.0.0" - write-file-atomic "^1.2.0" ws "^1.1.5" xpipe "^1.0.5" - yargs "^9.0.0" - -micromatch@^2.3.11: - version "2.3.11" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" - integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU= - dependencies: - arr-diff "^2.0.0" - array-unique "^0.2.1" - braces "^1.8.2" - expand-brackets "^0.1.4" - extglob "^0.3.1" - filename-regex "^2.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.1" - kind-of "^3.0.2" - normalize-path "^2.0.1" - object.omit "^2.0.0" - parse-glob "^3.0.4" - regex-cache "^0.4.2" + yargs "^14.2.0" -micromatch@^3.1.4: +micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== @@ -3408,11 +4119,16 @@ mime-types@~2.1.24: dependencies: mime-db "1.40.0" -mime@1.6.0, mime@^1.3.4: +mime@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== +mime@^2.4.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe" + integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg== + mimic-fn@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" @@ -3426,41 +4142,16 @@ min-document@^2.19.0: dom-walk "^0.1.0" minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= - -minimist@^1.1.1, minimist@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= - -minimist@~0.0.1: - version "0.0.10" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" - integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= - -minipass@^2.2.1, minipass@^2.3.5: - version "2.3.5" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" - integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA== - dependencies: - safe-buffer "^5.1.2" - yallist "^3.0.0" - -minizlib@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614" - integrity sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA== - dependencies: - minipass "^2.2.1" +minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5: + version "1.2.6" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" + integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== mixin-deep@^1.2.0: version "1.3.2" @@ -3470,23 +4161,12 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@^0.5.0, mkdirp@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= - dependencies: - minimist "0.0.8" - -morgan@^1.9.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.9.1.tgz#0a8d16734a1d9afbc824b99df87e738e58e2da59" - integrity sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA== +mkdirp@^0.5.1: + version "0.5.5" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" + integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== dependencies: - basic-auth "~2.0.0" - debug "2.6.9" - depd "~1.1.2" - on-finished "~2.3.0" - on-headers "~1.0.1" + minimist "^1.2.5" ms@2.0.0: version "2.0.0" @@ -3530,15 +4210,6 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" -needle@^2.2.1: - version "2.4.0" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c" - integrity sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg== - dependencies: - debug "^3.2.6" - iconv-lite "^0.4.4" - sax "^1.2.4" - negotiator@0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" @@ -3549,6 +4220,11 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +nocache@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/nocache/-/nocache-2.1.0.tgz#120c9ffec43b5729b1d5de88cd71aa75a0ba491f" + integrity sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q== + node-fetch@^1.0.1: version "1.7.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" @@ -3562,6 +4238,11 @@ node-fetch@^2.2.0: resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== +node-fetch@^2.6.0: + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -3572,88 +4253,33 @@ node-modules-regexp@^1.0.0: resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= -node-notifier@^5.2.1: - version "5.4.0" - resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.4.0.tgz#7b455fdce9f7de0c63538297354f3db468426e6a" - integrity sha512-SUDEb+o71XR5lXSTyivXd9J7fCloE3SyP4lSgt3lU2oSANiox+SxlNRGPjDKrwU1YN3ix2KN/VGGCg0t01rttQ== - dependencies: - growly "^1.3.0" - is-wsl "^1.1.0" - semver "^5.5.0" - shellwords "^0.1.1" - which "^1.3.0" +node-releases@^1.1.71: + version "1.1.72" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.72.tgz#14802ab6b1039a79a0c7d662b610a5bbd76eacbe" + integrity sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw== -node-pre-gyp@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149" - integrity sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A== - dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.2.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4" - -node-releases@^1.1.25: - version "1.1.26" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.26.tgz#f30563edc5c7dc20cf524cc8652ffa7be0762937" - integrity sha512-fZPsuhhUHMTlfkhDLGtfY80DSJTjOcx+qD1j5pqPkuhUHVS7xHZIg9EE4DHK8O3f0zTxXHX5VIkDG8pu98/wfQ== - dependencies: - semver "^5.3.0" +node-stream-zip@^1.9.1: + version "1.14.0" + resolved "https://registry.yarnpkg.com/node-stream-zip/-/node-stream-zip-1.14.0.tgz#fdf9b86d10d55c1e50aa1be4fea88bae256c4eba" + integrity sha512-SKXyiBy9DBemsPHf/piHT00Y+iPK+zwru1G6+8UdOBzITnmmPMHYBMV6M1znyzyhDhUFQW0HEmbGiPqtp51M6Q== noop-fn@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/noop-fn/-/noop-fn-1.0.0.tgz#5f33d47f13d2150df93e0cb036699e982f78ffbf" integrity sha1-XzPUfxPSFQ35PgywNmmemC94/78= -nopt@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= - dependencies: - abbrev "1" - osenv "^0.1.4" - normalize-css-color@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/normalize-css-color/-/normalize-css-color-1.0.2.tgz#02991e97cccec6623fe573afbbf0de6a1f3e9f8d" integrity sha1-Apkel8zOxmI/5XOvu/Deah8+n40= -normalize-package-data@^2.3.2: - version "2.5.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" - integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== - dependencies: - hosted-git-info "^2.1.4" - resolve "^1.10.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - -normalize-path@^2.0.1, normalize-path@^2.1.1: +normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= dependencies: remove-trailing-separator "^1.0.1" -npm-bundled@^1.0.1: - version "1.0.6" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd" - integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== - -npm-packlist@^1.1.6: - version "1.4.4" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.4.tgz#866224233850ac534b63d1a6e76050092b5d2f44" - integrity sha512-zTLo8UcVYtDU3gdeaFu2Xu0n0EvelfHDGuqtNIn5RO7yQj4H1TqNdBc/yZjxnWA0PVB8D3Woyp0i5B43JwQ6Vw== - dependencies: - ignore-walk "^3.0.1" - npm-bundled "^1.0.1" - npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" @@ -3661,34 +4287,20 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" -npmlog@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-2.0.4.tgz#98b52530f2514ca90d09ec5b22c8846722375692" - integrity sha1-mLUlMPJRTKkNCexbIsiEZyI3VpI= - dependencies: - ansi "~0.3.1" - are-we-there-yet "~1.1.2" - gauge "~1.2.5" - -npmlog@^4.0.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - -nullthrows@^1.1.0: +nullthrows@^1.1.0, nullthrows@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/nullthrows/-/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1" integrity sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw== -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= +ob1@0.58.0: + version "0.58.0" + resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.58.0.tgz#484a1e9a63a8b79d9ea6f3a83b2a42110faac973" + integrity sha512-uZP44cbowAfHafP1k4skpWItk5iHCoRevMfrnUvYCfyNNPPJd3rfDCyj0exklWi2gDXvjlj2ObsfiqP/bs/J7Q== + +ob1@0.59.0: + version "0.59.0" + resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.59.0.tgz#ee103619ef5cb697f2866e3577da6f0ecd565a36" + integrity sha512-opXMTxyWJ9m68ZglCxwo0OPRESIC/iGmKFPXEXzMZqsVIrgoRXOHmoMDkQzz4y3irVjbyPJRAh5pI9fd0MJTFQ== object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" @@ -3704,6 +4316,11 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" +object-inspect@^1.9.0: + version "1.12.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" + integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== + object-keys@^1.0.11, object-keys@^1.0.12: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" @@ -3726,14 +4343,6 @@ object.assign@^4.1.0: has-symbols "^1.0.0" object-keys "^1.0.11" -object.omit@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" - integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo= - dependencies: - for-own "^0.1.4" - is-extendable "^0.1.1" - object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" @@ -3748,7 +4357,7 @@ on-finished@~2.3.0: dependencies: ee-first "1.1.1" -on-headers@~1.0.1, on-headers@~1.0.2: +on-headers@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== @@ -3767,53 +4376,35 @@ onetime@^2.0.0: dependencies: mimic-fn "^1.0.0" -opn@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/opn/-/opn-3.0.3.tgz#b6d99e7399f78d65c3baaffef1fb288e9b85243a" - integrity sha1-ttmec5n3jWXDuq/+8fsojpuFJDo= - dependencies: - object-assign "^4.0.1" - -optimist@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" - integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= +open@^6.2.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/open/-/open-6.4.0.tgz#5c13e96d0dc894686164f18965ecfe889ecfc8a9" + integrity sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg== dependencies: - minimist "~0.0.1" - wordwrap "~0.0.2" + is-wsl "^1.1.0" options@>=0.0.5: version "0.0.6" resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f" integrity sha1-7CLTEoBrtT5zF3Pnza788cZDEo8= -os-homedir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= - -os-locale@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" - integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA== +ora@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/ora/-/ora-3.4.0.tgz#bf0752491059a3ef3ed4c85097531de9fdbcd318" + integrity sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg== dependencies: - execa "^0.7.0" - lcid "^1.0.0" - mem "^1.1.0" + chalk "^2.4.2" + cli-cursor "^2.1.0" + cli-spinners "^2.0.0" + log-symbols "^2.2.0" + strip-ansi "^5.2.0" + wcwidth "^1.0.1" os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= -osenv@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.0" - p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" @@ -3833,6 +4424,13 @@ p-limit@^2.0.0: dependencies: p-try "^2.0.0" +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" @@ -3847,6 +4445,13 @@ p-locate@^3.0.0: dependencies: p-limit "^2.0.0" +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" @@ -3857,23 +4462,6 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== -parse-glob@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" - integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw= - dependencies: - glob-base "^0.3.0" - is-dotfile "^1.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.0" - -parse-json@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= - dependencies: - error-ex "^1.2.0" - parse-json@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" @@ -3907,6 +4495,11 @@ path-exists@^3.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -3918,21 +4511,9 @@ path-key@^2.0.0, path-key@^2.0.1: integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= path-parse@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== - -path-type@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" - integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= - dependencies: - pify "^2.0.0" - -pify@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== pify@^4.0.1: version "4.0.1" @@ -3960,14 +4541,13 @@ pkg-up@^2.0.0: dependencies: find-up "^2.1.0" -plist@^3.0.0, plist@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/plist/-/plist-3.0.1.tgz#a9b931d17c304e8912ef0ba3bdd6182baf2e1f8c" - integrity sha512-GpgvHHocGRyQm74b6FWEZZVRroHKE1I0/BTjAmySaohK+cUn+hZpbqXkc3KWgW3gQYkqcQej35FohcT0FRlkRQ== +plist@^3.0.1, plist@^3.0.5: + version "3.0.5" + resolved "https://registry.yarnpkg.com/plist/-/plist-3.0.5.tgz#2cbeb52d10e3cdccccf0c11a63a85d830970a987" + integrity sha512-83vX4eYdQp3vP9SxuYgEM/G/pJQqLUz/V/xzPrzruLs7fz7jxGQ1msZ/mg1nwZxUSuOp4sb+/bEIbRrbzZRxDA== dependencies: - base64-js "^1.2.3" + base64-js "^1.5.1" xmlbuilder "^9.0.7" - xmldom "0.1.x" plugin-error@^0.1.2: version "0.1.2" @@ -3990,19 +4570,6 @@ pouchdb-collections@^1.0.1: resolved "https://registry.yarnpkg.com/pouchdb-collections/-/pouchdb-collections-1.0.1.tgz#fe63a17da977611abef7cb8026cb1a9553fd8359" integrity sha1-/mOhfal3YRq+98uAJssalVP9g1k= -preserve@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" - integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= - -pretty-format@24.0.0-alpha.6: - version "24.0.0-alpha.6" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.0.0-alpha.6.tgz#25ad2fa46b342d6278bf241c5d2114d4376fbac1" - integrity sha512-zG2m6YJeuzwBFqb5EIdmwYVf30sap+iMRuYNPytOccEXZMAJbPIFGKVJ/U0WjQegmnQbRo9CI7j6j3HtDaifiA== - dependencies: - ansi-regex "^4.0.0" - ansi-styles "^3.2.0" - pretty-format@^23.6.0: version "23.6.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-23.6.0.tgz#5eaac8eeb6b33b987b7fe6097ea6a8a146ab5760" @@ -4011,6 +4578,26 @@ pretty-format@^23.6.0: ansi-regex "^3.0.0" ansi-styles "^3.2.0" +pretty-format@^24.7.0, pretty-format@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.9.0.tgz#12fac31b37019a4eea3c11aa9a959eb7628aa7c9" + integrity sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA== + dependencies: + "@jest/types" "^24.9.0" + ansi-regex "^4.0.0" + ansi-styles "^3.2.0" + react-is "^16.8.4" + +pretty-format@^25.1.0, pretty-format@^25.2.0: + version "25.5.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-25.5.0.tgz#7873c1d774f682c34b8d48b6743a2bf2ac55791a" + integrity sha512-kbo/kq2LQ/A/is0PQwsEHM7Ca6//bGPPvU6UnsdDRSKTWxT/ru/xb88v4BJf6a69H+uTytOEsTusT9ksd/1iWQ== + dependencies: + "@jest/types" "^25.5.0" + ansi-regex "^5.0.0" + ansi-styles "^4.0.0" + react-is "^16.12.0" + private@^0.1.6: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" @@ -4033,7 +4620,7 @@ promise@^7.1.1: dependencies: asap "~2.0.3" -prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2: +prop-types@^15.5.10, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -4056,56 +4643,34 @@ pump@^3.0.0: once "^1.3.1" qs@^6.5.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" - integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== + version "6.11.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== + dependencies: + side-channel "^1.0.4" querystringify@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e" - integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA== - -randomatic@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed" - integrity sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw== - dependencies: - is-number "^4.0.0" - kind-of "^6.0.0" - math-random "^1.0.1" + version "2.2.0" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" + integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== range-parser@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -rc@^1.2.7: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - -react-clone-referenced-element@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/react-clone-referenced-element/-/react-clone-referenced-element-1.1.0.tgz#9cdda7f2aeb54fea791f3ab8c6ab96c7a77d0158" - integrity sha512-FKOsfKbBkPxYE8576EM6uAfHC4rnMpLyH6/TJUL4WcHUEB3EUn8AxPjnnV/IiwSSzsClvHYK+sDELKN/EJ0WYg== - react-deep-force-update@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/react-deep-force-update/-/react-deep-force-update-1.1.2.tgz#3d2ae45c2c9040cbb1772be52f8ea1ade6ca2ee1" integrity sha512-WUSQJ4P/wWcusaH+zZmbECOk7H5N2pOIl0vzheeornkIMhu+qrNdGFm0bDZLCb0hSF0jf/kH1SgkNGfBdTc4wA== -react-devtools-core@^3.6.0: - version "3.6.3" - resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-3.6.3.tgz#977d95b684c6ad28205f0c62e1e12c5f16675814" - integrity sha512-+P+eFy/yo8Z/UH9J0DqHZuUM5+RI2wl249TNvMx3J2jpUomLQa4Zxl56GEotGfw3PIP1eI+hVf1s53FlUONStQ== +react-devtools-core@^4.0.6: + version "4.17.0" + resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-4.17.0.tgz#83eb8a2c79b542d6b7bfa5406084a969cb7897ba" + integrity sha512-+9/aF7Gc8gswkAsoyUyQdIrhKHY/hOaMdK0oPIHuxzckJC5Cd4R1Mx75DKaqn84znwrYvXQ65kAseA+X44jMTw== dependencies: shell-quote "^1.6.1" - ws "^3.3.1" + ws "^7" react-dom@^16.8.6: version "16.8.6" @@ -4117,6 +4682,11 @@ react-dom@^16.8.6: prop-types "^15.6.2" scheduler "^0.13.6" +react-is@^16.12.0, react-is@^16.8.4: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + react-is@^16.8.1: version "16.8.6" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16" @@ -4151,10 +4721,18 @@ react-native-gesture-handler@~1.3.0: invariant "^2.2.2" prop-types "^15.5.10" -react-native-reanimated@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-1.1.0.tgz#ba6864055ec3a206cdd5209a293fe653ce276206" - integrity sha512-UGDVNfvuIkMqYUx6aytSzihuzv6sWubn0MQi8dRcw7BjgezhjJnVnJ/NSOcpL3cO+Ld7lFcRX6GKcskwkHdPkw== +react-native-reanimated@~2.10.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-2.10.0.tgz#ed53be66bbb553b5b5e93e93ef4217c87b8c73db" + integrity sha512-jKm3xz5nX7ABtHzzuuLmawP0pFWP77lXNdIC6AWOceBs23OHUaJ29p4prxr/7Sb588GwTbkPsYkDqVFaE3ezNQ== + dependencies: + "@babel/plugin-transform-object-assign" "^7.16.7" + "@babel/preset-typescript" "^7.16.7" + "@types/invariant" "^2.2.35" + invariant "^2.2.4" + lodash.isequal "^4.5.0" + setimmediate "^1.0.5" + string-hash-64 "^1.0.3" react-native-unimodules@~0.5.2: version "0.5.2" @@ -4201,61 +4779,42 @@ react-native-web@^0.11.4: prop-types "^15.6.0" react-timer-mixin "^0.13.4" -react-native@0.59.8: - version "0.59.8" - resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.59.8.tgz#ade4141c777c60f5ec4889d9811d0f80a9d56547" - integrity sha512-x1T+/pEXrjgdH9uDzd5doJy5aFlBqW04j7ljDKIGALchhnvdFbtXXrUZ/1PfWHMrIdZxtaDt4tkSttp662GSQA== +react-native@0.62.3: + version "0.62.3" + resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.62.3.tgz#9a2e96af3dedd0723c8657831eec4ed3c30f3299" + integrity sha512-b2/hDHDlO5Of2Zn1K5ZgvzOoUrvMEvlYU4miS9rcEBp5jK/9cRQn81HZ7NBmf4gzigGl8CxbSx1l10GUj1k8XQ== dependencies: "@babel/runtime" "^7.0.0" - "@react-native-community/cli" "^1.2.1" - absolute-path "^0.0.0" - art "^0.10.0" + "@react-native-community/cli" "^4.5.1" + "@react-native-community/cli-platform-android" "^4.5.1" + "@react-native-community/cli-platform-ios" "^4.5.0" + abort-controller "^3.0.0" + anser "^1.4.9" base64-js "^1.1.2" - chalk "^2.4.1" - commander "^2.9.0" - compression "^1.7.1" connect "^3.6.5" create-react-class "^15.6.3" - debug "^2.2.0" - denodeify "^1.2.1" - errorhandler "^1.5.0" escape-string-regexp "^1.0.5" - event-target-shim "^1.0.5" + eslint-plugin-relay "1.4.1" + event-target-shim "^5.0.1" fbjs "^1.0.0" - fbjs-scripts "^1.0.0" - fs-extra "^1.0.0" - glob "^7.1.1" - graceful-fs "^4.1.3" - inquirer "^3.0.6" + fbjs-scripts "^1.1.0" + hermes-engine "~0.4.0" invariant "^2.2.4" - lodash "^4.17.5" - metro-babel-register "0.51.0" - metro-react-native-babel-transformer "0.51.0" - mime "^1.3.4" - minimist "^1.2.0" - mkdirp "^0.5.1" - morgan "^1.9.0" - node-fetch "^2.2.0" - node-notifier "^5.2.1" - npmlog "^2.0.4" - nullthrows "^1.1.0" - opn "^3.0.2" - optimist "^0.6.1" - plist "^3.0.0" - pretty-format "24.0.0-alpha.6" + jsc-android "^245459.0.0" + metro-babel-register "0.58.0" + metro-react-native-babel-transformer "0.58.0" + metro-source-map "0.58.0" + nullthrows "^1.1.1" + pretty-format "^24.7.0" promise "^7.1.1" - prop-types "^15.5.8" - react-clone-referenced-element "^1.0.1" - react-devtools-core "^3.6.0" - regenerator-runtime "^0.11.0" - rimraf "^2.5.4" - semver "^5.0.3" - serve-static "^1.13.1" - shell-quote "1.6.1" + prop-types "^15.7.2" + react-devtools-core "^4.0.6" + react-refresh "^0.4.0" + regenerator-runtime "^0.13.2" + scheduler "0.17.0" stacktrace-parser "^0.1.3" - ws "^1.1.5" - xmldoc "^0.4.0" - yargs "^9.0.0" + use-subscription "^1.0.0" + whatwg-fetch "^3.0.0" react-proxy@^1.1.7: version "1.1.8" @@ -4265,6 +4824,11 @@ react-proxy@^1.1.7: lodash "^4.6.1" react-deep-force-update "^1.0.0" +react-refresh@^0.4.0: + version "0.4.3" + resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.4.3.tgz#966f1750c191672e76e16c2efa569150cc73ab53" + integrity sha512-Hwln1VNuGl/6bVwnd0Xdn1e84gT/8T9aYNL+HAKDArLCS7LWjwr7StE30IEYbIkx0Vi3vs+coQxe+SQDbGbbpA== + react-timer-mixin@^0.13.4: version "0.13.4" resolved "https://registry.yarnpkg.com/react-timer-mixin/-/react-timer-mixin-0.13.4.tgz#75a00c3c94c13abe29b43d63b4c65a88fc8264d3" @@ -4288,24 +4852,7 @@ react@16.8.3: prop-types "^15.6.2" scheduler "^0.13.3" -read-pkg-up@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" - integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= - dependencies: - find-up "^2.0.0" - read-pkg "^2.0.0" - -read-pkg@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" - integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= - dependencies: - load-json-file "^2.0.0" - normalize-package-data "^2.3.2" - path-type "^2.0.0" - -readable-stream@^2.0.1, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@~2.3.6: +readable-stream@^2.0.1, readable-stream@^2.2.2, readable-stream@~2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== @@ -4330,11 +4877,6 @@ regenerate@^1.4.0: resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== -regenerator-runtime@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== - regenerator-runtime@^0.13.2: version "0.13.3" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5" @@ -4347,13 +4889,6 @@ regenerator-transform@^0.14.0: dependencies: private "^0.1.6" -regex-cache@^0.4.2: - version "0.4.4" - resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" - integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ== - dependencies: - is-equal-shallow "^0.1.3" - regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" @@ -4401,7 +4936,7 @@ repeat-element@^1.1.2: resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== -repeat-string@^1.5.2, repeat-string@^1.6.1: +repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= @@ -4411,10 +4946,10 @@ require-directory@^2.1.1: resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= -require-main-filename@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== requires-port@^1.0.0: version "1.0.0" @@ -4436,7 +4971,7 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.10.0, resolve@^1.3.2, resolve@^1.4.0, resolve@^1.5.0, resolve@^1.8.1: +resolve@^1.3.2, resolve@^1.4.0, resolve@^1.5.0, resolve@^1.8.1: version "1.12.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== @@ -4456,7 +4991,7 @@ ret@~0.1.10: resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== -rimraf@^2.5.4, rimraf@^2.6.1: +rimraf@^2.5.4: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== @@ -4468,10 +5003,10 @@ rimraf@~2.2.6: resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.2.8.tgz#e439be2aaee327321952730f99a8929e4fc50582" integrity sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI= -rsvp@^3.3.3: - version "3.6.2" - resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a" - integrity sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw== +rsvp@^4.8.4: + version "4.8.5" + resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" + integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== run-async@^2.2.0: version "2.3.0" @@ -4497,11 +5032,6 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@^5.1.2: - version "5.2.0" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" - integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== - safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" @@ -4514,32 +5044,33 @@ safe-regex@^1.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sane@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/sane/-/sane-3.1.0.tgz#995193b7dc1445ef1fe41ddfca2faf9f111854c6" - integrity sha512-G5GClRRxT1cELXfdAq7UKtUsv8q/ZC5k8lQGmjEm4HcAl3HzBy68iglyNCmw4+0tiXPCBZntslHlRhbnsSws+Q== +sane@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/sane/-/sane-4.1.0.tgz#ed881fd922733a6c461bc189dc2b6c006f3ffded" + integrity sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA== dependencies: + "@cnakazawa/watch" "^1.0.3" anymatch "^2.0.0" - capture-exit "^1.2.0" - exec-sh "^0.2.0" + capture-exit "^2.0.0" + exec-sh "^0.3.2" execa "^1.0.0" fb-watchman "^2.0.0" micromatch "^3.1.4" minimist "^1.1.1" walker "~1.0.5" - watch "~0.18.0" - optionalDependencies: - fsevents "^1.2.3" -sax@^1.2.4: +sax@^1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== -sax@~1.1.1: - version "1.1.6" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.1.6.tgz#5d616be8a5e607d54e114afae55b7eaf2fcc3240" - integrity sha1-XWFr6KXmB9VOEUr65Vt+ry/MMkA= +scheduler@0.17.0: + version "0.17.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.17.0.tgz#7c9c673e4ec781fac853927916d1c426b6f3ddfe" + integrity sha512-7rro8Io3tnCPuY4la/NuI5F2yfESpnfZyT6TtkXnSWVkcu0BCDJ+8gk5ozUaFaxpIyNuWAPXrH0yFcSi28fnDA== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" scheduler@^0.13.3, scheduler@^0.13.6: version "0.13.6" @@ -4549,15 +5080,15 @@ scheduler@^0.13.3, scheduler@^0.13.6: loose-envify "^1.1.0" object-assign "^4.1.1" -"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: - version "5.7.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" - integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== +semver@^5.1.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== -semver@^6.1.1: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^6.1.1, semver@^6.3.0: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== send@0.17.1: version "0.17.1" @@ -4593,7 +5124,7 @@ serve-static@^1.13.1: parseurl "~1.3.3" send "0.17.1" -set-blocking@^2.0.0, set-blocking@~2.0.0: +set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= @@ -4640,10 +5171,14 @@ shell-quote@1.6.1, shell-quote@^1.6.1: array-reduce "~0.0.0" jsonify "~0.0.0" -shellwords@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" - integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" @@ -4651,23 +5186,32 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= simple-plist@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/simple-plist/-/simple-plist-1.0.0.tgz#bed3085633b22f371e111f45d159a1ccf94b81eb" - integrity sha512-043L2rO80LVF7zfZ+fqhsEkoJFvW8o59rt/l4ctx1TJWoTx7/jkiS1R5TatD15Z1oYnuLJytzE7gcnnBuIPL2g== + version "1.3.1" + resolved "https://registry.yarnpkg.com/simple-plist/-/simple-plist-1.3.1.tgz#16e1d8f62c6c9b691b8383127663d834112fb017" + integrity sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw== dependencies: - bplist-creator "0.0.7" - bplist-parser "0.1.1" - plist "^3.0.1" + bplist-creator "0.1.0" + bplist-parser "0.3.1" + plist "^3.0.5" slash@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== -slide@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" - integrity sha1-VusCfWW00tzmyy4tMsTUr8nh1wc= +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slice-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" + integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== + dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" + is-fullwidth-code-point "^2.0.0" snapdragon-node@^2.0.1: version "2.1.1" @@ -4733,31 +5277,10 @@ source-map@^0.6.0, source-map@~0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -spdx-correct@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" - integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" - integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== - -spdx-expression-parse@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" - integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.5" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" - integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== +source-map@^0.7.3: + version "0.7.3" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" + integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" @@ -4771,6 +5294,18 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= +stack-utils@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.5.tgz#a19b0b01947e0029c8e451d5d61a498f5bb1471b" + integrity sha512-KZiTzuV3CnSnSvgMRrARVCj+Ht7rMbauGDK0LdVFRGyenwdylpajAp4Q0i6SX8rEmbTpMMf6ryq2gb8pPq2WgQ== + dependencies: + escape-string-regexp "^2.0.0" + +stackframe@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.2.0.tgz#52429492d63c62eb989804c11552e3d22e779303" + integrity sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA== + stacktrace-parser@^0.1.3: version "0.1.6" resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.6.tgz#c17d466d15ba51bee2f753d064f17327a886ff37" @@ -4791,21 +5326,17 @@ static-extend@^0.1.1: resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= -stream-buffers@~2.2.0: +stream-buffers@2.2.x: version "2.2.0" resolved "https://registry.yarnpkg.com/stream-buffers/-/stream-buffers-2.2.0.tgz#91d5f5130d1cef96dcfa7f726945188741d09ee4" integrity sha1-kdX1Ew0c75bc+n9yaUUYh0HQnuQ= -string-width@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" +string-hash-64@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string-hash-64/-/string-hash-64-1.0.3.tgz#0deb56df58678640db5c479ccbbb597aaa0de322" + integrity sha512-D5OKWKvDhyVWWn2x5Y9b+37NUllks34q1dCDhk/vYcso9fmhs+Tl3KR/gE4v5UNj2UA35cnX4KdVVGkG1deKqw== -"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0: +string-width@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -4813,6 +5344,24 @@ string-width@^1.0.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" +string-width@^3.0.0, string-width@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" + integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" @@ -4820,13 +5369,6 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - strip-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" @@ -4834,25 +5376,29 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= +sudo-prompt@^9.0.0: + version "9.2.1" + resolved "https://registry.yarnpkg.com/sudo-prompt/-/sudo-prompt-9.2.1.tgz#77efb84309c9ca489527a4e749f287e6bdd52afd" + integrity sha512-Mu7R0g4ig9TUuGSxJavny5Rv0egCEtpZRNMrZaYS1vxkiIxGiGUwoezU3LazIQ+KE04hTrTfNPgxU5gzi7F5Pw== supports-color@^5.3.0: version "5.5.0" @@ -4868,18 +5414,12 @@ supports-color@^6.1.0: dependencies: has-flag "^3.0.0" -tar@^4: - version "4.4.10" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.10.tgz#946b2810b9a5e0b26140cf78bea6b0b0d689eba1" - integrity sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA== +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: - chownr "^1.1.1" - fs-minipass "^1.2.5" - minipass "^2.3.5" - minizlib "^1.2.1" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.3" + has-flag "^4.0.0" temp@0.8.3: version "0.8.3" @@ -4894,7 +5434,7 @@ throat@^4.1.0: resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" integrity sha1-iQN8vJLFarGJJua6TLsgDhVnKmo= -through2@^2.0.0: +through2@^2.0.0, through2@^2.0.1: version "2.0.5" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== @@ -4925,9 +5465,9 @@ tmp@^0.0.33: os-tmpdir "~1.0.2" tmpl@1.0.x: - version "1.0.4" - resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" - integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE= + version "1.0.5" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== to-fast-properties@^2.0.0: version "2.0.0" @@ -4980,9 +5520,9 @@ typedarray@^0.0.6: integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= ua-parser-js@^0.7.18, ua-parser-js@^0.7.19: - version "0.7.20" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.20.tgz#7527178b82f6a62a0f243d1f94fd30e3e3c21098" - integrity sha512-8OaIKfzL5cpx8eCMAhhvTlft8GYF8b2eQr6JkCyVdrgjcytyOmPCXrqXFcUnhonRpLlh5yxEZVohm6mzaowUOw== + version "0.7.33" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.33.tgz#1d04acb4ccef9293df6f70f2c3d22f3030d8b532" + integrity sha512-s8ax/CeZdK9R/56Sui0WM6y9OFREJarMRHqLB2EwkovemBxNQ+Bqu8GAsUnVcXKgphb++ghr/B2BZx4mahujPw== uglify-es@^3.1.9: version "3.3.9" @@ -4997,11 +5537,6 @@ ultron@1.0.x: resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa" integrity sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po= -ultron@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" - integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== - unicode-canonical-property-names-ecmascript@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" @@ -5109,13 +5644,20 @@ urix@^0.1.0: integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= url-parse@^1.4.4: - version "1.4.7" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278" - integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg== + version "1.5.10" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" + integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== dependencies: querystringify "^2.1.1" requires-port "^1.0.0" +use-subscription@^1.0.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/use-subscription/-/use-subscription-1.5.1.tgz#73501107f02fad84c6dd57965beb0b75c68c42d1" + integrity sha512-Xv2a1P/yReAjAbhylMfFplFKj9GssgTwN7RlcTxBujFQcloStWNDQdc4g4NRWH9xS4i/FDk04vQBptAXoF3VcA== + dependencies: + object-assign "^4.1.1" + use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" @@ -5141,90 +5683,75 @@ uuid@^3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== -validate-npm-package-license@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= -walker@~1.0.5: +vlq@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/vlq/-/vlq-1.0.1.tgz#c003f6e7c0b4c1edd623fd6ee50bbc0d6a1de468" + integrity sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w== + +walker@^1.0.7, walker@~1.0.5: version "1.0.7" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs= dependencies: makeerror "1.0.x" -watch@~0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/watch/-/watch-0.18.0.tgz#28095476c6df7c90c963138990c0a5423eb4b986" - integrity sha1-KAlUdsbffJDJYxOJkMClQj60uYY= +wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g= dependencies: - exec-sh "^0.2.0" - minimist "^1.2.0" + defaults "^1.0.3" -whatwg-fetch@>=0.10.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb" - integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q== +whatwg-fetch@>=0.10.0, whatwg-fetch@^3.0.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" + integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA== which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which@^1.2.9, which@^1.3.0: +which@^1.2.9: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== dependencies: isexe "^2.0.0" -wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== - dependencies: - string-width "^1.0.2 || 2" - wordwrap@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= -wordwrap@~0.0.2: - version "0.0.3" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" - integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" -wrap-ansi@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" - integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -write-file-atomic@^1.2.0: - version "1.3.4" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f" - integrity sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8= - dependencies: - graceful-fs "^4.1.11" - imurmurhash "^0.1.4" - slide "^1.1.5" - ws@^1.1.0, ws@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.5.tgz#cbd9e6e75e09fc5d2c90015f21f0c40875e0dd51" @@ -5233,14 +5760,10 @@ ws@^1.1.0, ws@^1.1.5: options ">=0.0.5" ultron "1.0.x" -ws@^3.3.1: - version "3.3.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" - integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== - dependencies: - async-limiter "~1.0.0" - safe-buffer "~5.1.0" - ultron "~1.1.0" +ws@^7: + version "7.5.4" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.4.tgz#56bfa20b167427e138a7795de68d134fe92e21f9" + integrity sha512-zP9z6GXm6zC27YtspwH99T3qTG7bBFv2VIkeHstMLrLlDJuzA7tQ5ls3OJ1hOGGCzTQPniNJoHXIAOS0Jljohg== xcode@^2.0.0: version "2.0.0" @@ -5255,17 +5778,12 @@ xmlbuilder@^9.0.7: resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= -xmldoc@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/xmldoc/-/xmldoc-0.4.0.tgz#d257224be8393eaacbf837ef227fd8ec25b36888" - integrity sha1-0lciS+g5PqrL+DfvIn/Y7CWzaIg= +xmldoc@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/xmldoc/-/xmldoc-1.1.2.tgz#6666e029fe25470d599cd30e23ff0d1ed50466d7" + integrity sha512-ruPC/fyPNck2BD1dpz0AZZyrEwMOrWTO5lDdIXS91rs3wtm4j+T8Rp2o+zoOYkkAxJTZRPOSnOGei1egoRmKMQ== dependencies: - sax "~1.1.1" - -xmldom@0.1.x: - version "0.1.27" - resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.27.tgz#d501f97b3bdb403af8ef9ecc20573187aadac0e9" - integrity sha1-1QH5ezvbQDr4757MIFcxh6rawOk= + sax "^1.2.1" xpipe@^1.0.5: version "1.0.5" @@ -5277,43 +5795,62 @@ xtend@~4.0.1: resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== -y18n@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" - integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= +y18n@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= -yallist@^3.0.0, yallist@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" - integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== +yargs-parser@^15.0.1: + version "15.0.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-15.0.3.tgz#316e263d5febe8b38eef61ac092b33dfcc9b1115" + integrity sha512-/MVEVjTXy/cGAjdtQf8dW3V9b97bPN7rNn8ETj6BmAQL7ibC7O1Q9SPJbGjgh3SlwoBNXMzj/ZGIj8mBgl12YA== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-parser@^18.1.2: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" -yargs-parser@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" - integrity sha1-jQrELxbqVd69MyyvTEA4s+P139k= - dependencies: - camelcase "^4.1.0" - -yargs@^9.0.0: - version "9.0.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-9.0.1.tgz#52acc23feecac34042078ee78c0c007f5085db4c" - integrity sha1-UqzCP+7Kw0BCB47njAwAf1CF20w= - dependencies: - camelcase "^4.1.0" - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - os-locale "^2.0.0" - read-pkg-up "^2.0.0" +yargs@^14.2.0: + version "14.2.3" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-14.2.3.tgz#1a1c3edced1afb2a2fea33604bc6d1d8d688a414" + integrity sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg== + dependencies: + cliui "^5.0.0" + decamelize "^1.2.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^15.0.1" + +yargs@^15.1.0: + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" require-directory "^2.1.1" - require-main-filename "^1.0.1" + require-main-filename "^2.0.0" set-blocking "^2.0.0" - string-width "^2.0.0" + string-width "^4.2.0" which-module "^2.0.0" - y18n "^3.2.1" - yargs-parser "^7.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.2" diff --git a/index.d.ts b/index.d.ts index 2f86c02a..25b43da9 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,176 +1,284 @@ -export type Events = - 'didReceiveStartCallAction' | - 'answerCall' | - 'endCall' | - 'didActivateAudioSession' | - 'didDeactivateAudioSession' | - 'didDisplayIncomingCall' | - 'didToggleHoldCallAction' | - 'didPerformDTMFAction' | - 'didResetProvider' | - 'checkReachability' | - 'didPerformSetMutedCallAction'; - -type HandleType = 'generic' | 'number' | 'email'; - -interface IOptions { - ios: { - appName: string, - imageName?: string, - supportsVideo?: boolean, - maximumCallGroups?: string, - maximumCallsPerCallGroup?: string, - ringtoneSound?: string, - }, - android: { - alertTitle: string, - alertDescription: string, - cancelButton: string, - okButton: string, - imageName?: string, - additionalPermissions: string[], - }, -} +declare module 'react-native-callkeep' { + export type NativeEvents = { + didReceiveStartCallAction: 'RNCallKeepDidReceiveStartCallAction'; + answerCall: 'RNCallKeepPerformAnswerCallAction'; + endCall: 'RNCallKeepPerformEndCallAction'; + didActivateAudioSession: 'RNCallKeepDidActivateAudioSession'; + didDeactivateAudioSession: 'RNCallKeepDidDeactivateAudioSession'; + didDisplayIncomingCall: 'RNCallKeepDidDisplayIncomingCall'; + didPerformSetMutedCallAction: 'RNCallKeepDidPerformSetMutedCallAction'; + didToggleHoldCallAction: 'RNCallKeepDidToggleHoldAction'; + didChangeAudioRoute: 'RNCallKeepDidChangeAudioRoute'; + didPerformDTMFAction: 'RNCallKeepDidPerformDTMFAction'; + showIncomingCallUi: 'RNCallKeepShowIncomingCallUi'; + silenceIncomingCall: 'RNCallKeepOnSilenceIncomingCall'; + createIncomingConnectionFailed: 'RNCallKeepOnIncomingConnectionFailed'; + checkReachability: 'RNCallKeepCheckReachability'; + didResetProvider: 'RNCallKeepProviderReset'; + didLoadWithEvents: 'RNCallKeepDidLoadWithEvents'; + onHasActiveCall : 'onHasActiveCall'; + } -export type DidReceiveStartCallActionPayload = { handle: string }; -export type AnswerCallPayload = { callUUID: string }; -export type EndCallPayload = AnswerCallPayload; -export type DidDisplayIncomingCallPayload = string | undefined; -export type DidPerformSetMutedCallActionPayload = boolean; + export type InitialEvents = Array<{ + [Event in Events]: { name: NativeEvents[Event], data: EventsPayload[Event] } + }[Events]> + + export type Events = keyof NativeEvents; + export type EventsPayload = { + didReceiveStartCallAction: { handle: string, callUUID?: string, name?: string }; + answerCall: { callUUID: string }; + endCall: { callUUID: string }; + didActivateAudioSession: undefined; + didDeactivateAudioSession: undefined; + didDisplayIncomingCall: { + error?: string, + errorCode?: 'Unentitled' | 'CallUUIDAlreadyExists' | 'FilteredByDoNotDisturb' | 'FilteredByBlockList' | 'Unknown', + callUUID: string, + handle: string, + localizedCallerName: string, + hasVideo: '1' | '0', + fromPushKit: '1' | '0', + payload: object, + }; + didPerformSetMutedCallAction: { muted: boolean, callUUID: string }; + didToggleHoldCallAction: { hold: boolean, callUUID: string }; + didChangeAudioRoute: { + output: string, + reason?: number, + handle?: string, + callUUID?: string, + }; + didPerformDTMFAction: { digits: string, callUUID: string }; + showIncomingCallUi: { handle: string, callUUID: string, name: string }; + silenceIncomingCall: { handle: string, callUUID: string, name: string }; + createIncomingConnectionFailed: { handle: string, callUUID: string, name: string }; + checkReachability: undefined; + didResetProvider: undefined; + didLoadWithEvents: InitialEvents; + onHasActiveCall : undefined; + } -export default class RNCallKeep { - static addEventListener(type: Events, handler: (args: any) => void) { + type HandleType = 'generic' | 'number' | 'email'; + export type AudioRoute = { + name: string, + type: string, + selected?: boolean } - static removeEventListener(type: Events) { + export enum AudioSessionCategoryOption { + mixWithOthers = 0x1, + duckOthers = 0x2, + interruptSpokenAudioAndMixWithOthers = 0x11, + allowBluetooth = 0x4, + allowBluetoothA2DP = 0x20, + allowAirPlay = 0x40, + defaultToSpeaker = 0x8, + overrideMutedMicrophoneInterruption = 0x80, + } + export enum AudioSessionMode { + default = 'AVAudioSessionModeDefault', + gameChat = 'AVAudioSessionModeGameChat', + measurement = 'AVAudioSessionModeMeasurement', + moviePlayback = 'AVAudioSessionModeMoviePlayback', + spokenAudio = 'AVAudioSessionModeSpokenAudio', + videoChat = 'AVAudioSessionModeVideoChat', + videoRecording = 'AVAudioSessionModeVideoRecording', + voiceChat = 'AVAudioSessionModeVoiceChat', + voicePrompt = 'AVAudioSessionModeVoicePrompt', } - static async setup(options: IOptions): Promise { + interface IOptions { + ios: { + appName: string, + imageName?: string, + supportsVideo?: boolean, + maximumCallGroups?: string, + maximumCallsPerCallGroup?: string, + ringtoneSound?: string, + includesCallsInRecents?: boolean + audioSession?: { + categoryOptions?: AudioSessionCategoryOption | number, + mode?: AudioSessionMode | string, + } + }, + android: { + alertTitle: string, + alertDescription: string, + cancelButton: string, + okButton: string, + imageName?: string, + additionalPermissions: string[], + selfManaged?: boolean, + foregroundService?: { + channelId: string, + channelName: string, + notificationTitle: string, + notificationIcon?: string + } + } + } + export const CONSTANTS: { + END_CALL_REASONS: { + FAILED: 1, + REMOTE_ENDED: 2, + UNANSWERED: 3, + ANSWERED_ELSEWHERE: 4, + DECLINED_ELSEWHERE: 5 | 2, + MISSED: 2 | 6 + } + }; + + export class EventListener { + remove(): void } - static hasDefaultPhoneAccount(): boolean { + export default class RNCallKeep { + static getInitialEvents(): Promise - } + static clearInitialEvents(): void - static displayIncomingCall( - uuid: string, - handle: string, - localizedCallerName?: string, - handleType?: HandleType, - hasVideo?: boolean, - ) { + static addEventListener( + type: Event, + handler: (args: EventsPayload[Event]) => void, + ): EventListener - } + static removeEventListener(type: Events): void - static startCall( - uuid: string, - handle: string, - contactIdentifier?: string, - handleType?: HandleType, - hasVideo?: boolean, - ) { + static setup(options: IOptions): Promise - } - static updateDisplay( - uuid: string, - displayName: string, - handle: string, - ) { + static hasDefaultPhoneAccount(): boolean - } + static answerIncomingCall(uuid: string): void - /** - * @description reportConnectedOutgoingCallWithUUID method is available only on iOS. - */ - static reportConnectedOutgoingCallWithUUID(uuid: string) { + static registerPhoneAccount(options: IOptions): void - } + static registerAndroidEvents(): void - /** - * @description reportConnectedOutgoingCallWithUUID method is available only on iOS. - */ - static reportConnectingOutgoingCallWithUUID(uuid: string): void { + static unregisterAndroidEvents(): void - } - static reportEndCallWithUUID(uuid: string, reason: number): void { + static displayIncomingCall( + uuid: string, + handle: string, + localizedCallerName?: string, + handleType?: HandleType, + hasVideo?: boolean, + options?: object, + ): void - } + static startCall( + uuid: string, + handle: string, + contactIdentifier?: string, + handleType?: HandleType, + hasVideo?: boolean, + ): void - static rejectCall(uuid: string) { + static updateDisplay( + uuid: string, + displayName: string, + handle: string, + options?: object, + ): void - } + static checkPhoneAccountEnabled(): Promise; - static endCall(uuid: string) { + static isConnectionServiceAvailable(): Promise; - } + /** + * @description reportConnectedOutgoingCallWithUUID method is available only on iOS. + */ + static reportConnectedOutgoingCallWithUUID(uuid: string): void - static endAllCalls() { + /** + * @description reportConnectedOutgoingCallWithUUID method is available only on iOS. + */ + static reportConnectingOutgoingCallWithUUID(uuid: string): void - } + static reportEndCallWithUUID(uuid: string, reason: number): void - static setReachable() { + static rejectCall(uuid: string): void - } + static endCall(uuid: string): void - /** - * @description supportConnectionService method is available only on Android. - */ - static supportConnectionService(): boolean { + static endAllCalls(): void - } + static setReachable(): void - /** - * @description hasPhoneAccount method is available only on Android. - */ - static async hasPhoneAccount(): Promise { + static setSettings(settings: IOptions): void; - } + /** + * @description isCallActive method is available only on iOS. + */ + static isCallActive(uuid: string): Promise - static async hasOutgoingCall(): Promise { + static getCalls(): Promise<{ + callUUID: string, + hasConnected: boolean, + hasEnded: boolean, + onHold: boolean, + outgoing: boolean + }[] | void> - } + static getAudioRoutes(): Promise - /** - * @description setMutedCall method is available only on iOS. - */ - static setMutedCall(uuid: string, muted: boolean) { + static setAudioRoute: (uuid: string, inputName: string) => Promise - } + /** + * @description supportConnectionService method is available only on Android. + */ + static supportConnectionService(): boolean - static setOnHold(uuid: string, held: boolean) { + /** + * @description hasPhoneAccount method is available only on Android. + */ + static hasPhoneAccount(): Promise - } + static hasOutgoingCall(): Promise - /** - * @descriptions sendDTMF is used to send DTMF tones to the PBX. - */ - static sendDTMF(uuid: string, key: string) { + /** + * @description setMutedCall method is available only on iOS. + */ + static setMutedCall(uuid: string, muted: boolean): void - } + /** + * @description toggleAudioRouteSpeaker method is available only on Android. + * @param uuid + * @param routeSpeaker + */ + static toggleAudioRouteSpeaker(uuid: string, routeSpeaker: boolean): void - static checkIfBusy(): Promise { + static setOnHold(uuid: string, held: boolean): void - } + static setConnectionState(uuid: string, state: number): void - static checkSpeaker(): Promise { + /** + * @descriptions sendDTMF is used to send DTMF tones to the PBX. + */ + static sendDTMF(uuid: string, key: string): void - } + static checkIfBusy(): Promise + + static checkSpeaker(): Promise - /** + /** * @description setAvailable method is available only on Android. - */ - static setAvailable(active: boolean) { + */ + static setAvailable(active: boolean): void - } + static setForegroundServiceSettings(settings: NonNullable): void - static setCurrentCallActive() { + static canMakeMultipleCalls(allow: boolean): void - } + static setCurrentCallActive(callUUID: string): void - static backToForeground() { + static backToForeground(): void + /** + * @descriptions Android Only, Check if there is active native call + */ + static checkIsInManagedCall(): Promise } } diff --git a/index.js b/index.js index 38b61301..a011f677 100644 --- a/index.js +++ b/index.js @@ -1,11 +1,34 @@ import { NativeModules, Platform, Alert } from 'react-native'; -import { listeners } from './actions' +import { listeners, emit } from './actions'; const RNCallKeepModule = NativeModules.RNCallKeep; const isIOS = Platform.OS === 'ios'; const supportConnectionService = !isIOS && Platform.Version >= 23; +const AudioSessionCategoryOption = { + mixWithOthers: 0x1, + duckOthers: 0x2, + interruptSpokenAudioAndMixWithOthers: 0x11, + allowBluetooth: 0x4, + allowBluetoothA2DP: 0x20, + allowAirPlay: 0x40, + defaultToSpeaker: 0x8, + overrideMutedMicrophoneInterruption: 0x80, +} + +const AudioSessionMode = { + default: 'AVAudioSessionModeDefault', + gameChat: 'AVAudioSessionModeGameChat', + measurement: 'AVAudioSessionModeMeasurement', + moviePlayback: 'AVAudioSessionModeMoviePlayback', + spokenAudio: 'AVAudioSessionModeSpokenAudio', + videoChat: 'AVAudioSessionModeVideoChat', + videoRecording: 'AVAudioSessionModeVideoRecording', + voiceChat: 'AVAudioSessionModeVoiceChat', + voicePrompt: 'AVAudioSessionModeVoicePrompt', +} + const CONSTANTS = { END_CALL_REASONS: { FAILED: 1, @@ -13,13 +36,25 @@ const CONSTANTS = { UNANSWERED: 3, ANSWERED_ELSEWHERE: 4, DECLINED_ELSEWHERE: isIOS ? 5 : 2, // make declined elsewhere link to "Remote ended" on android because that's kinda true - MISSED: isIOS ? 2 : 6 } + MISSED: isIOS ? 2 : 6, + }, }; -export { CONSTANTS }; +export { emit, CONSTANTS, AudioSessionCategoryOption, AudioSessionMode }; -class RNCallKeep { +class EventListener { + constructor(type, listener, callkeep) { + this._type = type; + this._listener = listener; + this._callkeep = callkeep; + } + remove = () => { + this._callkeep.removeEventListener(this._type, this._listener); + }; +} + +class RNCallKeep { constructor() { this._callkeepEventHandlers = new Map(); } @@ -27,17 +62,32 @@ class RNCallKeep { addEventListener = (type, handler) => { const listener = listeners[type](handler); - this._callkeepEventHandlers.set(type, listener); + const listenerSet = this._callkeepEventHandlers.get(type) ?? new Set(); + listenerSet.add(listener); + + this._callkeepEventHandlers.set(type, listenerSet); + + return new EventListener(type, listener, this); }; - removeEventListener = (type) => { - const listener = this._callkeepEventHandlers.get(type); - if (!listener) { + removeEventListener = (type, listener = undefined) => { + const listenerSet = this._callkeepEventHandlers.get(type); + if (!listenerSet) { return; } - listener.remove(); - this._callkeepEventHandlers.delete(type); + if (listener) { + listenerSet.delete(listener); + listener.remove(); + if (listenerSet.size <= 0) { + this._callkeepEventHandlers.delete(type); + } + } else { + listenerSet.forEach((listener) => { + listener.remove(); + }); + this._callkeepEventHandlers.delete(type); + } }; setup = async (options) => { @@ -48,6 +98,29 @@ class RNCallKeep { return this._setupIOS(options.ios); }; + setSettings = (settings) => RNCallKeepModule.setSettings(settings[isIOS ? 'ios' : 'android']); + + registerPhoneAccount = (options) => { + if (isIOS) { + return; + } + RNCallKeepModule.registerPhoneAccount(options.android); + }; + + registerAndroidEvents = () => { + if (isIOS) { + return; + } + RNCallKeepModule.registerEvents(); + }; + + unregisterAndroidEvents = () => { + if (isIOS) { + return; + } + RNCallKeepModule.unregisterEvents(); + }; + hasDefaultPhoneAccount = async (options) => { if (!isIOS) { return this._hasDefaultPhoneAccount(options); @@ -56,30 +129,69 @@ class RNCallKeep { return; }; - displayIncomingCall = (uuid, handle, localizedCallerName = '', handleType = 'number', hasVideo = false) => { + displayIncomingCall = ( + uuid, + handle, + localizedCallerName = '', + handleType = 'number', + hasVideo = false, + options = null + ) => { if (!isIOS) { - RNCallKeepModule.displayIncomingCall(uuid, handle, localizedCallerName); + RNCallKeepModule.displayIncomingCall(uuid, handle, localizedCallerName, hasVideo); return; } - RNCallKeepModule.displayIncomingCall(uuid, handle, handleType, hasVideo, localizedCallerName); + // should be boolean type value + let supportsHolding = !!(options?.ios?.supportsHolding ?? true); + let supportsDTMF = !!(options?.ios?.supportsDTMF ?? true); + let supportsGrouping = !!(options?.ios?.supportsGrouping ?? true); + let supportsUngrouping = !!(options?.ios?.supportsUngrouping ?? true); + + RNCallKeepModule.displayIncomingCall( + uuid, + handle, + handleType, + hasVideo, + localizedCallerName, + supportsHolding, + supportsDTMF, + supportsGrouping, + supportsUngrouping + ); }; + checkIsInManagedCall = async () => isIOS? false: RNCallKeepModule.checkIsInManagedCall(); + answerIncomingCall = (uuid) => { - if (!isIOS) { - RNCallKeepModule.answerIncomingCall(uuid); - } + RNCallKeepModule.answerIncomingCall(uuid); }; - startCall = (uuid, handle, contactIdentifier, handleType = 'number', hasVideo = false ) => { + startCall = (uuid, handle, contactIdentifier, handleType = 'number', hasVideo = false) => { if (!isIOS) { - RNCallKeepModule.startCall(uuid, handle, contactIdentifier); + RNCallKeepModule.startCall(uuid, handle, contactIdentifier, hasVideo); return; } RNCallKeepModule.startCall(uuid, handle, contactIdentifier, handleType, hasVideo); }; + checkPhoneAccountEnabled = async () => { + if (isIOS) { + return; + } + + return RNCallKeepModule.checkPhoneAccountEnabled(); + }; + + isConnectionServiceAvailable = async () => { + if (isIOS) { + return true; + } + + return RNCallKeepModule.isConnectionServiceAvailable(); + }; + reportConnectingOutgoingCallWithUUID = (uuid) => { //only available on iOS if (isIOS) { @@ -108,33 +220,46 @@ class RNCallKeep { } }; + isCallActive = async (uuid) => await RNCallKeepModule.isCallActive(uuid); + + getCalls = () => { + if (isIOS) { + return RNCallKeepModule.getCalls(); + } + }; + endCall = (uuid) => RNCallKeepModule.endCall(uuid); endAllCalls = () => RNCallKeepModule.endAllCalls(); supportConnectionService = () => supportConnectionService; - hasPhoneAccount = async () => - isIOS ? true : await RNCallKeepModule.hasPhoneAccount(); + hasPhoneAccount = async () => (isIOS ? true : await RNCallKeepModule.hasPhoneAccount()); - hasOutgoingCall = async () => - isIOS ? null : await RNCallKeepModule.hasOutgoingCall(); + hasOutgoingCall = async () => (isIOS ? null : await RNCallKeepModule.hasOutgoingCall()); setMutedCall = (uuid, shouldMute) => { RNCallKeepModule.setMutedCall(uuid, shouldMute); }; sendDTMF = (uuid, key) => RNCallKeepModule.sendDTMF(uuid, key); + /** + * @description when Phone call is active, Android control the audio service via connection service. so this function help to toggle the audio to Speaker or wired/ear-piece or vice-versa + * @param {*} uuid + * @param {*} routeSpeaker + * @returns Audio route state of audio service + */ + toggleAudioRouteSpeaker = (uuid, routeSpeaker) => isIOS ? null : RNCallKeepModule.toggleAudioRouteSpeaker(uuid, routeSpeaker); + + getAudioRoutes = () => RNCallKeepModule.getAudioRoutes(); + + setAudioRoute = (uuid, inputName) => RNCallKeepModule.setAudioRoute(uuid, inputName); checkIfBusy = () => - isIOS - ? RNCallKeepModule.checkIfBusy() - : Promise.reject('RNCallKeep.checkIfBusy was called from unsupported OS'); + isIOS ? RNCallKeepModule.checkIfBusy() : Promise.reject('RNCallKeep.checkIfBusy was called from unsupported OS'); checkSpeaker = () => - isIOS - ? RNCallKeepModule.checkSpeaker() - : Promise.reject('RNCallKeep.checkSpeaker was called from unsupported OS'); + isIOS ? RNCallKeepModule.checkSpeaker() : Promise.reject('RNCallKeep.checkSpeaker was called from unsupported OS'); setAvailable = (state) => { if (isIOS) { @@ -145,6 +270,22 @@ class RNCallKeep { RNCallKeepModule.setAvailable(state); }; + setForegroundServiceSettings = (settings) => { + if (isIOS) { + return; + } + + RNCallKeepModule.setForegroundServiceSettings(settings); + }; + + canMakeMultipleCalls = (state) => { + if (isIOS) { + return; + } + + RNCallKeepModule.canMakeMultipleCalls(state); + }; + setCurrentCallActive = (callUUID) => { if (isIOS) { return; @@ -153,10 +294,25 @@ class RNCallKeep { RNCallKeepModule.setCurrentCallActive(callUUID); }; - updateDisplay = (uuid, displayName, handle) => RNCallKeepModule.updateDisplay(uuid, displayName, handle); + updateDisplay = (uuid, displayName, handle, options = null) => { + if (!isIOS) { + RNCallKeepModule.updateDisplay(uuid, displayName, handle); + return; + } + + let iosOptions = {}; + if (options && options.ios) { + iosOptions = { + ...options.ios, + }; + } + RNCallKeepModule.updateDisplay(uuid, displayName, handle, iosOptions); + }; setOnHold = (uuid, shouldHold) => RNCallKeepModule.setOnHold(uuid, shouldHold); + setConnectionState = (uuid, state) => isIOS ? null : RNCallKeepModule.setConnectionState(uuid, state); + setReachable = () => RNCallKeepModule.setReachable(); // @deprecated @@ -168,20 +324,25 @@ class RNCallKeep { : Promise.reject('RNCallKeep.reportUpdatedCall was called from unsupported OS'); }; - _setupIOS = async (options) => new Promise((resolve, reject) => { - if (!options.appName) { - reject('RNCallKeep.setup: option "appName" is required'); - } - if (typeof options.appName !== 'string') { - reject('RNCallKeep.setup: option "appName" should be of type "string"'); - } + _setupIOS = async (options) => + new Promise((resolve, reject) => { + if (!options.appName) { + reject('RNCallKeep.setup: option "appName" is required'); + } + if (typeof options.appName !== 'string') { + reject('RNCallKeep.setup: option "appName" should be of type "string"'); + } - resolve(RNCallKeepModule.setup(options)); - }); + resolve(RNCallKeepModule.setup(options)); + }); _setupAndroid = async (options) => { RNCallKeepModule.setup(options); + if (options.selfManaged) { + return false; + } + const showAccountAlert = await RNCallKeepModule.checkPhoneAccountPermission(options.additionalPermissions || []); const shouldOpenAccounts = await this._alert(options, showAccountAlert); @@ -202,27 +363,26 @@ class RNCallKeep { } }; - _alert = async (options, condition) => new Promise((resolve, reject) => { - if (!condition) { - return resolve(false); - } - - Alert.alert( - options.alertTitle, - options.alertDescription, - [ - { - text: options.cancelButton, - onPress: reject, - style: 'cancel', - }, - { text: options.okButton, - onPress: () => resolve(true) - }, - ], - { cancelable: true }, - ); - }); + _alert = async (options, condition) => + new Promise((resolve, reject) => { + if (!condition) { + return resolve(false); + } + + Alert.alert( + options.alertTitle, + options.alertDescription, + [ + { + text: options.cancelButton, + onPress: reject, + style: 'cancel', + }, + { text: options.okButton, onPress: () => resolve(true) }, + ], + { cancelable: true }, + ); + }); backToForeground() { if (isIOS) { @@ -232,6 +392,13 @@ class RNCallKeep { NativeModules.RNCallKeep.backToForeground(); } + getInitialEvents() { + return RNCallKeepModule.getInitialEvents(); + } + + clearInitialEvents() { + return RNCallKeepModule.clearInitialEvents(); + } } export default new RNCallKeep(); diff --git a/ios/RNCallKeep/RNCallKeep.h b/ios/RNCallKeep/RNCallKeep.h index 4447a780..c8e7bbdf 100644 --- a/ios/RNCallKeep/RNCallKeep.h +++ b/ios/RNCallKeep/RNCallKeep.h @@ -32,9 +32,19 @@ continueUserActivity:(NSUserActivity *)userActivity handleType:(NSString *)handleType hasVideo:(BOOL)hasVideo localizedCallerName:(NSString * _Nullable)localizedCallerName + supportsHolding:(BOOL)supportsHolding + supportsDTMF:(BOOL)supportsDTMF + supportsGrouping:(BOOL)supportsGrouping + supportsUngrouping:(BOOL)supportsUngrouping fromPushKit:(BOOL)fromPushKit - payload:(NSDictionary * _Nullable)payload; + payload:(NSDictionary * _Nullable)payload + withCompletionHandler:(void (^_Nullable)(void))completion; + (void)endCallWithUUID:(NSString *)uuidString reason:(int)reason; -@end \ No newline at end of file + ++ (BOOL)isCallActive:(NSString *)uuidString; + ++ (void)setup:(NSDictionary *)options; + +@end diff --git a/ios/RNCallKeep/RNCallKeep.m b/ios/RNCallKeep/RNCallKeep.m index 8cd01ea3..786045fe 100644 --- a/ios/RNCallKeep/RNCallKeep.m +++ b/ios/RNCallKeep/RNCallKeep.m @@ -12,8 +12,10 @@ #import #import #import +#import #import +#import #ifdef DEBUG static int const OUTGOING_CALL_WAKEUP_DELAY = 10; @@ -33,13 +35,19 @@ static NSString *const RNCallKeepDidToggleHoldAction = @"RNCallKeepDidToggleHoldAction"; static NSString *const RNCallKeepProviderReset = @"RNCallKeepProviderReset"; static NSString *const RNCallKeepCheckReachability = @"RNCallKeepCheckReachability"; +static NSString *const RNCallKeepDidChangeAudioRoute = @"RNCallKeepDidChangeAudioRoute"; +static NSString *const RNCallKeepDidLoadWithEvents = @"RNCallKeepDidLoadWithEvents"; @implementation RNCallKeep { NSOperatingSystemVersion _version; BOOL _isStartCallActionEventListenerAdded; + bool _hasListeners; + bool _isReachable; + NSMutableArray *_delayedEvents; } +static bool isSetupNatively; static CXProvider* sharedProvider; // should initialise in AppDelegate.m @@ -52,6 +60,18 @@ - (instancetype)init #endif if (self = [super init]) { _isStartCallActionEventListenerAdded = NO; + _isReachable = NO; + if (_delayedEvents == nil) _delayedEvents = [NSMutableArray array]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(onAudioRouteChange:) + name:AVAudioSessionRouteChangeNotification + object:nil]; + // Init provider directly, in case of an app killed and when we've already stored our settings + [RNCallKeep initCallKitProvider]; + + self.callKeepProvider = sharedProvider; + [self.callKeepProvider setDelegate:self queue:nil]; } return self; } @@ -76,6 +96,7 @@ - (void)dealloc [self.callKeepProvider invalidate]; } sharedProvider = nil; + _isReachable = NO; } // Override method of RCTEventEmitter @@ -92,28 +113,117 @@ - (void)dealloc RNCallKeepPerformPlayDTMFCallAction, RNCallKeepDidToggleHoldAction, RNCallKeepProviderReset, - RNCallKeepCheckReachability + RNCallKeepCheckReachability, + RNCallKeepDidLoadWithEvents, + RNCallKeepDidChangeAudioRoute ]; } +- (void)startObserving +{ + NSLog(@"[RNCallKeep][startObserving]"); + _hasListeners = YES; + if ([_delayedEvents count] > 0) { + [self sendEventWithName:RNCallKeepDidLoadWithEvents body:_delayedEvents]; + } +} + +- (void)stopObserving +{ + _hasListeners = FALSE; + + // Fix for https://github.com/react-native-webrtc/react-native-callkeep/issues/406 + // We use Objective-C Key Value Coding(KVC) to sync _RTCEventEmitter_ `_listenerCount`. + @try { + [self setValue:@0 forKey:@"_listenerCount"]; + } + @catch ( NSException *e ){ + NSLog(@"[RNCallKeep][stopObserving] exception: %@",e); + NSLog(@"[RNCallKeep][stopObserving] RNCallKeep parent class RTCEventEmitter might have a broken state."); + NSLog(@"[RNCallKeep][stopObserving] Please verify that the parent RTCEventEmitter.m has iVar `_listenerCount`."); + } +} + +- (void)onAudioRouteChange:(NSNotification *)notification +{ + NSDictionary *info = notification.userInfo; + NSInteger reason = [[info valueForKey:AVAudioSessionRouteChangeReasonKey] integerValue]; + NSString *output = [RNCallKeep getAudioOutput]; + + if (output == nil) { + return; + } + + [self sendEventWithName:RNCallKeepDidChangeAudioRoute body:@{ + @"output": output, + @"reason": @(reason), + }]; +} + +- (void)sendEventWithNameWrapper:(NSString *)name body:(id)body { + NSLog(@"[RNCallKeep] sendEventWithNameWrapper: %@, hasListeners : %@", name, _hasListeners ? @"YES": @"NO"); + + if (_hasListeners) { + [self sendEventWithName:name body:body]; + } else { + NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys: + name, @"name", + body, @"data", + nil + ]; + [_delayedEvents addObject:dictionary]; + } +} + ++ (NSDictionary *) getSettings { + return [[NSUserDefaults standardUserDefaults] dictionaryForKey:@"RNCallKeepSettings"]; +} + + (void)initCallKitProvider { if (sharedProvider == nil) { - NSDictionary *settings = [[NSUserDefaults standardUserDefaults] dictionaryForKey:@"RNCallKeepSettings"]; - sharedProvider = [[CXProvider alloc] initWithConfiguration:[RNCallKeep getProviderConfiguration:settings]]; + NSDictionary *settings = [self getSettings]; + if (settings != nil) { + sharedProvider = [[CXProvider alloc] initWithConfiguration:[RNCallKeep getProviderConfiguration:settings]]; + } + } +} + ++ (NSString *) getAudioOutput { + @try{ + NSArray* outputs = [AVAudioSession sharedInstance].currentRoute.outputs; + if(outputs != nil && outputs.count > 0){ + return outputs[0].portType; + } + } @catch(NSException* error) { + NSLog(@"getAudioOutput error :%@", [error description]); } + + return nil; +} + ++ (void)setup:(NSDictionary *)options { + RNCallKeep *callKeep = [RNCallKeep allocWithZone: nil]; + [callKeep setup:options]; + isSetupNatively = YES; } RCT_EXPORT_METHOD(setup:(NSDictionary *)options) { + if (isSetupNatively) { +#ifdef DEBUG + NSLog(@"[RNCallKeep][setup] already setup"); + RCTLog(@"[RNCallKeep][setup] already setup in native code"); +#endif + return; + } + #ifdef DEBUG NSLog(@"[RNCallKeep][setup] options = %@", options); #endif _version = [[[NSProcessInfo alloc] init] operatingSystemVersion]; self.callKeepCallController = [[CXCallController alloc] init]; - NSDictionary *settings = [[NSMutableDictionary alloc] initWithDictionary:options]; - // Store settings in NSUserDefault - [[NSUserDefaults standardUserDefaults] setObject:settings forKey:@"RNCallKeepSettings"]; - [[NSUserDefaults standardUserDefaults] synchronize]; + + [self setSettings: options]; [RNCallKeep initCallKitProvider]; @@ -121,6 +231,26 @@ + (void)initCallKitProvider { [self.callKeepProvider setDelegate:self queue:nil]; } +RCT_EXPORT_METHOD(setSettings:(NSDictionary *)options) +{ +#ifdef DEBUG + NSLog(@"[RNCallKeep][setSettings] options = %@", options); +#endif + NSDictionary *settings = [[NSMutableDictionary alloc] initWithDictionary:options]; + + // Store settings in NSUserDefault + [[NSUserDefaults standardUserDefaults] setObject:settings forKey:@"RNCallKeepSettings"]; + [[NSUserDefaults standardUserDefaults] synchronize]; +} + +RCT_EXPORT_METHOD(setReachable) +{ +#ifdef DEBUG + NSLog(@"[RNCallKeep][setReachable]"); +#endif + _isReachable = YES; +} + RCT_REMAP_METHOD(checkIfBusy, checkIfBusyWithResolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) @@ -138,7 +268,7 @@ + (void)initCallKitProvider { #ifdef DEBUG NSLog(@"[RNCallKeep][checkSpeaker]"); #endif - NSString *output = [AVAudioSession sharedInstance].currentRoute.outputs.count > 0 ? [AVAudioSession sharedInstance].currentRoute.outputs[0].portType : nil; + NSString *output = [RNCallKeep getAudioOutput]; resolve(@([output isEqualToString:@"Speaker"])); } @@ -146,19 +276,66 @@ + (void)initCallKitProvider { // Display the incoming call to the user RCT_EXPORT_METHOD(displayIncomingCall:(NSString *)uuidString - handle:(NSString *)handle - handleType:(NSString *)handleType - hasVideo:(BOOL)hasVideo - localizedCallerName:(NSString * _Nullable)localizedCallerName) + handle:(NSString *)handle + handleType:(NSString *)handleType + hasVideo:(BOOL)hasVideo + localizedCallerName:(NSString * _Nullable)localizedCallerName + supportsHolding:(BOOL)supportsHolding + supportsDTMF:(BOOL)supportsDTMF + supportsGrouping:(BOOL)supportsGrouping + supportsUngrouping:(BOOL)supportsUngrouping) +{ + [RNCallKeep reportNewIncomingCall: uuidString + handle: handle + handleType: handleType + hasVideo: hasVideo + localizedCallerName: localizedCallerName + supportsHolding: supportsHolding + supportsDTMF: supportsDTMF + supportsGrouping: supportsGrouping + supportsUngrouping: supportsUngrouping + fromPushKit: NO + payload: nil + withCompletionHandler: nil]; + + NSDictionary *settings = [RNCallKeep getSettings]; + NSNumber *timeout = settings[@"displayCallReachabilityTimeout"]; + + if (timeout) { + dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)([timeout intValue] * NSEC_PER_MSEC)); + dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ + if (!self->_isReachable) { +#ifdef DEBUG + NSLog(@"[RNCallKeep]Displayed a call without a reachable app, ending the call: %@", uuidString); +#endif + [RNCallKeep endCallWithUUID: uuidString reason: 1]; + } + }); + } +} + +RCT_EXPORT_METHOD(getInitialEvents:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject) +{ +#ifdef DEBUG + NSLog(@"[RNCallKeep][getInitialEvents]"); +#endif + resolve(_delayedEvents); +} + +RCT_EXPORT_METHOD(clearInitialEvents) { - [RNCallKeep reportNewIncomingCall: uuidString handle:handle handleType:handleType hasVideo:hasVideo localizedCallerName:localizedCallerName fromPushKit: NO payload:nil]; +#ifdef DEBUG + NSLog(@"[RNCallKeep][clearInitialEvents]"); +#endif + _delayedEvents = [NSMutableArray array]; } RCT_EXPORT_METHOD(startCall:(NSString *)uuidString - handle:(NSString *)handle - contactIdentifier:(NSString * _Nullable)contactIdentifier - handleType:(NSString *)handleType - video:(BOOL)video) + handle:(NSString *)handle + contactIdentifier:(NSString * _Nullable)contactIdentifier + handleType:(NSString *)handleType + video:(BOOL)video) { #ifdef DEBUG NSLog(@"[RNCallKeep][startCall] uuidString = %@", uuidString); @@ -175,6 +352,19 @@ + (void)initCallKitProvider { [self requestTransaction:transaction]; } +RCT_EXPORT_METHOD(answerIncomingCall:(NSString *)uuidString) +{ +#ifdef DEBUG + NSLog(@"[RNCallKeep][answerIncomingCall] uuidString = %@", uuidString); +#endif + NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:uuidString]; + CXAnswerCallAction *answerCallAction = [[CXAnswerCallAction alloc] initWithCallUUID:uuid]; + CXTransaction *transaction = [[CXTransaction alloc] init]; + [transaction addAction:answerCallAction]; + + [self requestTransaction:transaction]; +} + RCT_EXPORT_METHOD(endCall:(NSString *)uuidString) { #ifdef DEBUG @@ -234,7 +424,7 @@ + (void)initCallKitProvider { [RNCallKeep endCallWithUUID: uuidString reason:reason]; } -RCT_EXPORT_METHOD(updateDisplay:(NSString *)uuidString :(NSString *)displayName :(NSString *)uri) +RCT_EXPORT_METHOD(updateDisplay:(NSString *)uuidString :(NSString *)displayName :(NSString *)uri :(NSDictionary *)options) { #ifdef DEBUG NSLog(@"[RNCallKeep][updateDisplay] uuidString = %@ displayName = %@ uri = %@", uuidString, displayName, uri); @@ -244,6 +434,23 @@ + (void)initCallKitProvider { CXCallUpdate *callUpdate = [[CXCallUpdate alloc] init]; callUpdate.localizedCallerName = displayName; callUpdate.remoteHandle = callHandle; + + if ([options valueForKey:@"hasVideo"] != nil) { + callUpdate.hasVideo = [RCTConvert BOOL:options[@"hasVideo"]]; + } + if ([options valueForKey:@"supportsHolding"] != nil) { + callUpdate.supportsHolding = [RCTConvert BOOL:options[@"supportsHolding"]]; + } + if ([options valueForKey:@"supportsDTMF"] != nil) { + callUpdate.supportsDTMF = [RCTConvert BOOL:options[@"supportsDTMF"]]; + } + if ([options valueForKey:@"supportsGrouping"] != nil) { + callUpdate.supportsGrouping = [RCTConvert BOOL:options[@"supportsGrouping"]]; + } + if ([options valueForKey:@"supportsUngrouping"] != nil) { + callUpdate.supportsUngrouping = [RCTConvert BOOL:options[@"supportsUngrouping"]]; + } + [self.callKeepProvider reportCallWithUUID:uuid updated:callUpdate]; } @@ -273,6 +480,190 @@ + (void)initCallKitProvider { [self requestTransaction:transaction]; } +RCT_EXPORT_METHOD(isCallActive:(NSString *)uuidString + isCallActiveResolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) +{ +#ifdef DEBUG + NSLog(@"[RNCallKeep][isCallActive] uuid = %@", uuidString); +#endif + BOOL isActive = [RNCallKeep isCallActive: uuidString]; + if (isActive) { + resolve(@YES); + } else { + resolve(@NO); + } +} + +RCT_EXPORT_METHOD(getCalls:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) +{ +#ifdef DEBUG + NSLog(@"[RNCallKeep][getCalls]"); +#endif + resolve([RNCallKeep getCalls]); +} + +RCT_EXPORT_METHOD(setAudioRoute: (NSString *)uuid + inputName:(NSString *)inputName + resolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) +{ +#ifdef DEBUG + NSLog(@"[RNCallKeep][setAudioRoute] - inputName: %@", inputName); +#endif + @try { + NSError* err = nil; + AVAudioSession* myAudioSession = [AVAudioSession sharedInstance]; + if ([inputName isEqualToString:@"Speaker"]) { + BOOL isOverrided = [myAudioSession overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:&err]; + if(!isOverrided){ + [NSException raise:@"overrideOutputAudioPort failed" format:@"error: %@", err]; + } + resolve(@"Speaker"); + return; + } + + NSArray *ports = [RNCallKeep getAudioInputs]; + for (AVAudioSessionPortDescription *port in ports) { + if ([port.portName isEqualToString:inputName]) { + BOOL isSetted = [myAudioSession setPreferredInput:(AVAudioSessionPortDescription *)port error:&err]; + if(!isSetted){ + [NSException raise:@"setPreferredInput failed" format:@"error: %@", err]; + } + resolve(inputName); + return; + } + } + } + @catch ( NSException *e ){ + NSLog(@"[RNCallKeep][setAudioRoute] exception: %@",e); + reject(@"Failure to set audio route", e, nil); + } +} + +RCT_EXPORT_METHOD(getAudioRoutes: (RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) +{ +#ifdef DEBUG + NSLog(@"[RNCallKeep][getAudioRoutes]"); +#endif + @try { + NSArray *inputs = [RNCallKeep getAudioInputs]; + NSMutableArray *formatedInputs = [RNCallKeep formatAudioInputs: inputs]; + resolve(formatedInputs); + } + @catch ( NSException *e ) { + NSLog(@"[RNCallKeep][getAudioRoutes] exception: %@",e); + reject(@"Failure to get audio routes", e, nil); + } +} + ++ (NSMutableArray *) formatAudioInputs: (NSMutableArray *)inputs +{ + NSMutableArray *newInputs = [NSMutableArray new]; + NSString * selected = [RNCallKeep getSelectedAudioRoute]; + + NSMutableDictionary *speakerDict = [[NSMutableDictionary alloc]init]; + [speakerDict setObject:@"Speaker" forKey:@"name"]; + [speakerDict setObject:AVAudioSessionPortBuiltInSpeaker forKey:@"type"]; + if(selected && [selected isEqualToString:AVAudioSessionPortBuiltInSpeaker]){ + [speakerDict setObject:@YES forKey:@"selected"]; + } + [newInputs addObject:speakerDict]; + + for (AVAudioSessionPortDescription* input in inputs) + { + NSString *str = [NSString stringWithFormat:@"PORTS :\"%@\": UID:%@", input.portName, input.UID ]; + NSMutableDictionary *dict = [[NSMutableDictionary alloc]init]; + [dict setObject:input.portName forKey:@"name"]; + NSString * type = [RNCallKeep getAudioInputType: input.portType]; + if(type) + { + if([selected isEqualToString:type]){ + [dict setObject:@YES forKey:@"selected"]; + } + [dict setObject:type forKey:@"type"]; + [newInputs addObject:dict]; + } + } + return newInputs; +} + ++ (NSArray *) getAudioInputs +{ + NSError* err = nil; + NSString *str = nil; + + AVAudioSession* myAudioSession = [AVAudioSession sharedInstance]; + NSString *category = [myAudioSession category]; + NSUInteger options = [myAudioSession categoryOptions]; + + + if(![category isEqualToString:AVAudioSessionCategoryPlayAndRecord] && (options != AVAudioSessionCategoryOptionAllowBluetooth) && (options !=AVAudioSessionCategoryOptionAllowBluetoothA2DP)) + { + BOOL isCategorySetted = [myAudioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionAllowBluetooth error:&err]; + if (!isCategorySetted) + { + NSLog(@"setCategory failed"); + [NSException raise:@"setCategory failed" format:@"error: %@", err]; + } + } + + BOOL isCategoryActivated = [myAudioSession setActive:YES error:&err]; + if (!isCategoryActivated) + { + NSLog(@"[RNCallKeep][getAudioInputs] setActive failed"); + [NSException raise:@"setActive failed" format:@"error: %@", err]; + } + + NSArray *inputs = [myAudioSession availableInputs]; + return inputs; +} + ++ (NSString *) getAudioInputType: (NSString *) type +{ + if ([type isEqualToString:AVAudioSessionPortBuiltInMic]){ + return @"Phone"; + } + else if ([type isEqualToString:AVAudioSessionPortHeadsetMic]){ + return @"Headset"; + } + else if ([type isEqualToString:AVAudioSessionPortHeadphones]){ + return @"Headset"; + } + else if ([type isEqualToString:AVAudioSessionPortBluetoothHFP]){ + return @"Bluetooth"; + } + else if ([type isEqualToString:AVAudioSessionPortBluetoothA2DP]){ + return @"Bluetooth"; + } + else if ([type isEqualToString:AVAudioSessionPortBuiltInSpeaker]){ + return @"Speaker"; + } + else if ([type isEqualToString:AVAudioSessionPortCarAudio]) { + return @"CarAudio"; + } + else{ + return nil; + } +} + ++ (NSString *) getSelectedAudioRoute +{ + AVAudioSession* myAudioSession = [AVAudioSession sharedInstance]; + AVAudioSessionRouteDescription *currentRoute = [myAudioSession currentRoute]; + NSArray *selectedOutputs = currentRoute.outputs; + + AVAudioSessionPortDescription *selectedOutput = selectedOutputs[0]; + + if(selectedOutput && [selectedOutput.portType isEqualToString:AVAudioSessionPortBuiltInReceiver]) { + return @"Phone"; + } + + return [RNCallKeep getAudioInputType: selectedOutput.portType]; +} + - (void)requestTransaction:(CXTransaction *)transaction { #ifdef DEBUG @@ -304,6 +695,41 @@ - (void)requestTransaction:(CXTransaction *)transaction }]; } ++ (BOOL)isCallActive:(NSString *)uuidString +{ + CXCallObserver *callObserver = [[CXCallObserver alloc] init]; + NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:uuidString]; + + for(CXCall *call in callObserver.calls){ + NSLog(@"[RNCallKeep] isCallActive %@ %d ?", call.UUID, [call.UUID isEqual:uuid]); + if([call.UUID isEqual:[[NSUUID alloc] initWithUUIDString:uuidString]]){ + return call.hasConnected; + } + } + return false; +} + ++ (NSMutableArray *) getCalls +{ +#ifdef DEBUG + NSLog(@"[RNCallKeep][getCalls]"); +#endif + CXCallObserver *callObserver = [[CXCallObserver alloc] init]; + NSMutableArray *currentCalls = [NSMutableArray array]; + for(CXCall *call in callObserver.calls){ + NSString *uuidString = [call.UUID UUIDString]; + NSDictionary *requestedCall= @{ + @"callUUID": uuidString, + @"outgoing": call.outgoing? @YES : @NO, + @"onHold": call.onHold? @YES : @NO, + @"hasConnected": call.hasConnected ? @YES : @NO, + @"hasEnded": call.hasEnded ? @YES : @NO + }; + [currentCalls addObject:requestedCall]; + } + return currentCalls; +} + + (void)endCallWithUUID:(NSString *)uuidString reason:(int)reason { @@ -338,8 +764,13 @@ + (void)reportNewIncomingCall:(NSString *)uuidString handleType:(NSString *)handleType hasVideo:(BOOL)hasVideo localizedCallerName:(NSString * _Nullable)localizedCallerName + supportsHolding:(BOOL)supportsHolding + supportsDTMF:(BOOL)supportsDTMF + supportsGrouping:(BOOL)supportsGrouping + supportsUngrouping:(BOOL)supportsUngrouping fromPushKit:(BOOL)fromPushKit payload:(NSDictionary * _Nullable)payload + withCompletionHandler:(void (^_Nullable)(void))completion { #ifdef DEBUG NSLog(@"[RNCallKeep][reportNewIncomingCall] uuidString = %@", uuidString); @@ -348,22 +779,27 @@ + (void)reportNewIncomingCall:(NSString *)uuidString NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:uuidString]; CXCallUpdate *callUpdate = [[CXCallUpdate alloc] init]; callUpdate.remoteHandle = [[CXHandle alloc] initWithType:_handleType value:handle]; - callUpdate.supportsDTMF = YES; - callUpdate.supportsHolding = YES; - callUpdate.supportsGrouping = YES; - callUpdate.supportsUngrouping = YES; + callUpdate.supportsHolding = supportsHolding; + callUpdate.supportsDTMF = supportsDTMF; + callUpdate.supportsGrouping = supportsGrouping; + callUpdate.supportsUngrouping = supportsUngrouping; callUpdate.hasVideo = hasVideo; callUpdate.localizedCallerName = localizedCallerName; [RNCallKeep initCallKitProvider]; [sharedProvider reportNewIncomingCallWithUUID:uuid update:callUpdate completion:^(NSError * _Nullable error) { RNCallKeep *callKeep = [RNCallKeep allocWithZone: nil]; - [callKeep sendEventWithName:RNCallKeepDidDisplayIncomingCall body:@{ + [callKeep sendEventWithNameWrapper:RNCallKeepDidDisplayIncomingCall body:@{ @"error": error && error.localizedDescription ? error.localizedDescription : @"", + @"errorCode": error ? [callKeep getIncomingCallErrorCode:error] : @"", @"callUUID": uuidString, @"handle": handle, @"localizedCallerName": localizedCallerName ? localizedCallerName : @"", @"hasVideo": hasVideo ? @"1" : @"0", + @"supportsHolding": supportsHolding ? @"1" : @"0", + @"supportsDTMF": supportsDTMF ? @"1" : @"0", + @"supportsGrouping": supportsGrouping ? @"1" : @"0", + @"supportsUngrouping": supportsUngrouping ? @"1" : @"0", @"fromPushKit": fromPushKit ? @"1" : @"0", @"payload": payload ? payload : @"", }]; @@ -373,19 +809,27 @@ + (void)reportNewIncomingCall:(NSString *)uuidString [callKeep configureAudioSession]; } } + if (completion != nil) { + completion(); + } }]; } -+ (void)reportNewIncomingCall:(NSString *)uuidString - handle:(NSString *)handle - handleType:(NSString *)handleType - hasVideo:(BOOL)hasVideo - localizedCallerName:(NSString * _Nullable)localizedCallerName - fromPushKit:(BOOL)fromPushKit -{ - [RNCallKeep reportNewIncomingCall: uuidString handle:handle handleType:handleType hasVideo:hasVideo localizedCallerName:localizedCallerName fromPushKit: fromPushKit payload:nil]; +- (NSString *)getIncomingCallErrorCode:(NSError *)error { + if ([error code] == CXErrorCodeIncomingCallErrorUnentitled) { + return @"Unentitled"; + } else if ([error code] == CXErrorCodeIncomingCallErrorCallUUIDAlreadyExists) { + return @"CallUUIDAlreadyExists"; + } else if ([error code] == CXErrorCodeIncomingCallErrorFilteredByDoNotDisturb) { + return @"FilteredByDoNotDisturb"; + } else if ([error code] == CXErrorCodeIncomingCallErrorFilteredByBlockList) { + return @"FilteredByBlockList"; + } else { + return @"Unknown"; + } } + - (BOOL)lessThanIos10_2 { if (_version.majorVersion < 10) { @@ -397,19 +841,39 @@ - (BOOL)lessThanIos10_2 } } ++ (NSSet *) getSupportedHandleTypes:(id) handleType { + if(handleType){ + if([handleType isKindOfClass:[NSArray class]]) { + NSSet *types = [NSSet set]; + + for (NSString* type in handleType) { + types = [types setByAddingObject:[NSNumber numberWithInteger:[RNCallKeep getHandleType:type]]]; + } + + return types; + } else { + int _handleType = [RNCallKeep getHandleType:handleType]; + + return [NSSet setWithObjects:[NSNumber numberWithInteger:_handleType], nil]; + } + } else { + return [NSSet setWithObjects:[NSNumber numberWithInteger:CXHandleTypePhoneNumber], nil]; + } +} + + (int)getHandleType:(NSString *)handleType { - int _handleType; if ([handleType isEqualToString:@"generic"]) { - _handleType = CXHandleTypeGeneric; + return CXHandleTypeGeneric; } else if ([handleType isEqualToString:@"number"]) { - _handleType = CXHandleTypePhoneNumber; + return CXHandleTypePhoneNumber; + } else if ([handleType isEqualToString:@"phone"]) { + return CXHandleTypePhoneNumber; } else if ([handleType isEqualToString:@"email"]) { - _handleType = CXHandleTypeEmailAddress; + return CXHandleTypeEmailAddress; } else { - _handleType = CXHandleTypeGeneric; + return CXHandleTypeGeneric; } - return _handleType; } + (CXProviderConfiguration *)getProviderConfiguration:(NSDictionary*)settings @@ -421,12 +885,8 @@ + (CXProviderConfiguration *)getProviderConfiguration:(NSDictionary*)settings providerConfiguration.supportsVideo = YES; providerConfiguration.maximumCallGroups = 3; providerConfiguration.maximumCallsPerCallGroup = 1; - if(settings[@"handleType"]){ - int _handleType = [RNCallKeep getHandleType:settings[@"handleType"]]; - providerConfiguration.supportedHandleTypes = [NSSet setWithObjects:[NSNumber numberWithInteger:_handleType], nil]; - }else{ - providerConfiguration.supportedHandleTypes = [NSSet setWithObjects:[NSNumber numberWithInteger:CXHandleTypeGeneric], nil]; - } + providerConfiguration.supportedHandleTypes = [RNCallKeep getSupportedHandleTypes:settings[@"handleType"]]; + if (settings[@"supportsVideo"]) { providerConfiguration.supportsVideo = [settings[@"supportsVideo"] boolValue]; } @@ -456,10 +916,24 @@ - (void)configureAudioSession NSLog(@"[RNCallKeep][configureAudioSession] Activating audio session"); #endif + NSUInteger categoryOptions = AVAudioSessionCategoryOptionAllowBluetooth | AVAudioSessionCategoryOptionAllowBluetoothA2DP; + NSString *mode = AVAudioSessionModeDefault; + + NSDictionary *settings = [RNCallKeep getSettings]; + if (settings && settings[@"audioSession"]) { + if (settings[@"audioSession"][@"categoryOptions"]) { + categoryOptions = [settings[@"audioSession"][@"categoryOptions"] integerValue]; + } + + if (settings[@"audioSession"][@"mode"]) { + mode = settings[@"audioSession"][@"mode"]; + } + } + AVAudioSession* audioSession = [AVAudioSession sharedInstance]; - [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionAllowBluetooth error:nil]; + [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:categoryOptions error:nil]; - [audioSession setMode:AVAudioSessionModeVoiceChat error:nil]; + [audioSession setMode:mode error:nil]; double sampleRate = 44100.0; [audioSession setPreferredSampleRate:sampleRate error:nil]; @@ -506,8 +980,8 @@ + (BOOL)application:(UIApplication *)application BOOL isAudioCall; BOOL isVideoCall; -//HACK TO AVOID XCODE 10 COMPILE CRASH -//REMOVE ON NEXT MAJOR RELEASE OF RNCALLKIT + // HACK TO AVOID XCODE 10 COMPILE CRASH + // REMOVE ON NEXT MAJOR RELEASE OF RNCALLKIT #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 //XCode 11 // iOS 13 returns an INStartCallIntent userActivity type @@ -523,11 +997,11 @@ + (BOOL)application:(UIApplication *)application } } else { #endif - //XCode 10 and below + // XCode 10 and below isAudioCall = [userActivity.activityType isEqualToString:INStartAudioCallIntentIdentifier]; isVideoCall = [userActivity.activityType isEqualToString:INStartVideoCallIntentIdentifier]; -//HACK TO AVOID XCODE 10 COMPILE CRASH -//REMOVE ON NEXT MAJOR RELEASE OF RNCALLKIT + // HACK TO AVOID XCODE 10 COMPILE CRASH + // REMOVE ON NEXT MAJOR RELEASE OF RNCALLKIT #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 } #endif @@ -551,7 +1025,7 @@ + (BOOL)application:(UIApplication *)application }; RNCallKeep *callKeep = [RNCallKeep allocWithZone: nil]; - [callKeep handleStartCallNotification: userInfo]; + [callKeep sendEventWithNameWrapper:RNCallKeepDidReceiveStartCallAction body:userInfo]; return YES; } return NO; @@ -562,24 +1036,6 @@ + (BOOL)requiresMainQueueSetup return YES; } -- (void)handleStartCallNotification:(NSDictionary *)userInfo -{ -#ifdef DEBUG - NSLog(@"[RNCallKeep][handleStartCallNotification] userInfo = %@", userInfo); -#endif - int delayInSeconds; - if (!_isStartCallActionEventListenerAdded) { - // Workaround for when app is just launched and JS side hasn't registered to the event properly - delayInSeconds = OUTGOING_CALL_WAKEUP_DELAY; - } else { - delayInSeconds = 0; - } - dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); - dispatch_after(popTime, dispatch_get_main_queue(), ^{ - [self sendEventWithName:RNCallKeepDidReceiveStartCallAction body:userInfo]; - }); -} - #pragma mark - CXProviderDelegate - (void)providerDidReset:(CXProvider *)provider{ @@ -588,7 +1044,7 @@ - (void)providerDidReset:(CXProvider *)provider{ #endif //this means something big changed, so tell the JS. The JS should //probably respond by hanging up all calls. - [self sendEventWithName:RNCallKeepProviderReset body:nil]; + [self sendEventWithNameWrapper:RNCallKeepProviderReset body:nil]; } // Starting outgoing call @@ -600,7 +1056,7 @@ - (void)provider:(CXProvider *)provider performStartCallAction:(CXStartCallActio //do this first, audio sessions are flakey [self configureAudioSession]; //tell the JS to actually make the call - [self sendEventWithName:RNCallKeepDidReceiveStartCallAction body:@{ @"callUUID": [action.callUUID.UUIDString lowercaseString], @"handle": action.handle.value }]; + [self sendEventWithNameWrapper:RNCallKeepDidReceiveStartCallAction body:@{ @"callUUID": [action.callUUID.UUIDString lowercaseString], @"handle": action.handle.value }]; [action fulfill]; } @@ -625,7 +1081,7 @@ - (void)provider:(CXProvider *)provider performAnswerCallAction:(CXAnswerCallAct NSLog(@"[RNCallKeep][CXProviderDelegate][provider:performAnswerCallAction]"); #endif [self configureAudioSession]; - [self sendEventWithName:RNCallKeepPerformAnswerCallAction body:@{ @"callUUID": [action.callUUID.UUIDString lowercaseString] }]; + [self sendEventWithNameWrapper:RNCallKeepPerformAnswerCallAction body:@{ @"callUUID": [action.callUUID.UUIDString lowercaseString] }]; [action fulfill]; } @@ -635,7 +1091,7 @@ - (void)provider:(CXProvider *)provider performEndCallAction:(CXEndCallAction *) #ifdef DEBUG NSLog(@"[RNCallKeep][CXProviderDelegate][provider:performEndCallAction]"); #endif - [self sendEventWithName:RNCallKeepPerformEndCallAction body:@{ @"callUUID": [action.callUUID.UUIDString lowercaseString] }]; + [self sendEventWithNameWrapper:RNCallKeepPerformEndCallAction body:@{ @"callUUID": [action.callUUID.UUIDString lowercaseString] }]; [action fulfill]; } @@ -645,7 +1101,7 @@ -(void)provider:(CXProvider *)provider performSetHeldCallAction:(CXSetHeldCallAc NSLog(@"[RNCallKeep][CXProviderDelegate][provider:performSetHeldCallAction]"); #endif - [self sendEventWithName:RNCallKeepDidToggleHoldAction body:@{ @"hold": @(action.onHold), @"callUUID": [action.callUUID.UUIDString lowercaseString] }]; + [self sendEventWithNameWrapper:RNCallKeepDidToggleHoldAction body:@{ @"hold": @(action.onHold), @"callUUID": [action.callUUID.UUIDString lowercaseString] }]; [action fulfill]; } @@ -653,7 +1109,7 @@ - (void)provider:(CXProvider *)provider performPlayDTMFCallAction:(CXPlayDTMFCal #ifdef DEBUG NSLog(@"[RNCallKeep][CXProviderDelegate][provider:performPlayDTMFCallAction]"); #endif - [self sendEventWithName:RNCallKeepPerformPlayDTMFCallAction body:@{ @"digits": action.digits, @"callUUID": [action.callUUID.UUIDString lowercaseString] }]; + [self sendEventWithNameWrapper:RNCallKeepPerformPlayDTMFCallAction body:@{ @"digits": action.digits, @"callUUID": [action.callUUID.UUIDString lowercaseString] }]; [action fulfill]; } @@ -663,7 +1119,7 @@ -(void)provider:(CXProvider *)provider performSetMutedCallAction:(CXSetMutedCall NSLog(@"[RNCallKeep][CXProviderDelegate][provider:performSetMutedCallAction]"); #endif - [self sendEventWithName:RNCallKeepDidPerformSetMutedCallAction body:@{ @"muted": @(action.muted), @"callUUID": [action.callUUID.UUIDString lowercaseString] }]; + [self sendEventWithNameWrapper:RNCallKeepDidPerformSetMutedCallAction body:@{ @"muted": @(action.muted), @"callUUID": [action.callUUID.UUIDString lowercaseString] }]; [action fulfill]; } @@ -687,7 +1143,7 @@ - (void)provider:(CXProvider *)provider didActivateAudioSession:(AVAudioSession [[NSNotificationCenter defaultCenter] postNotificationName:AVAudioSessionInterruptionNotification object:nil userInfo:userInfo]; [self configureAudioSession]; - [self sendEventWithName:RNCallKeepDidActivateAudioSession body:nil]; + [self sendEventWithNameWrapper:RNCallKeepDidActivateAudioSession body:nil]; } - (void)provider:(CXProvider *)provider didDeactivateAudioSession:(AVAudioSession *)audioSession @@ -695,7 +1151,7 @@ - (void)provider:(CXProvider *)provider didDeactivateAudioSession:(AVAudioSessio #ifdef DEBUG NSLog(@"[RNCallKeep][CXProviderDelegate][provider:didDeactivateAudioSession]"); #endif - [self sendEventWithName:RNCallKeepDidDeactivateAudioSession body:nil]; + [self sendEventWithNameWrapper:RNCallKeepDidDeactivateAudioSession body:nil]; } @end diff --git a/package.json b/package.json index 0692d211..b9b821b4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-callkeep", - "version": "3.0.12", + "version": "4.3.16", "description": "iOS 10 CallKit and Android ConnectionService Framework For React Native", "main": "index.js", "scripts": {},