voice-react-native-sdk 1.6.2-fork.9 → 2.0.0-preview.fork.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +7 -111
- package/android/build.gradle +2 -2
- package/android/src/main/java/com/twiliovoicereactnative/CallInviteModuleProxy.java +114 -0
- package/android/src/main/java/com/twiliovoicereactnative/CallModuleProxy.java +223 -0
- package/android/src/main/java/com/twiliovoicereactnative/CallRecordDatabase.java +12 -9
- package/android/src/main/java/com/twiliovoicereactnative/CommonConstants.java +149 -1
- package/android/src/main/java/com/twiliovoicereactnative/ConfigurationProperties.java +0 -11
- package/android/src/main/java/com/twiliovoicereactnative/Constants.java +2 -0
- package/android/src/main/java/com/twiliovoicereactnative/ExpoActivityLifecycleListener.kt +62 -0
- package/android/src/main/java/com/twiliovoicereactnative/ExpoApplicationLifecycleListener.kt +18 -0
- package/android/src/main/java/com/twiliovoicereactnative/ExpoModule.kt +404 -35
- package/android/src/main/java/com/twiliovoicereactnative/ExpoPackage.kt +16 -0
- package/android/src/main/java/com/twiliovoicereactnative/ModuleProxy.java +57 -0
- package/android/src/main/java/com/twiliovoicereactnative/NotificationUtility.java +12 -24
- package/android/src/main/java/com/twiliovoicereactnative/PreflightTestListenerProxy.java +97 -0
- package/android/src/main/java/com/twiliovoicereactnative/PreflightTestModuleProxy.java +119 -0
- package/android/src/main/java/com/twiliovoicereactnative/PreflightTestRecordDatabase.java +37 -0
- package/android/src/main/java/com/twiliovoicereactnative/ReactNativeArgumentsSerializer.java +37 -7
- package/android/src/main/java/com/twiliovoicereactnative/RegistrationListenerProxy.java +88 -0
- package/android/src/main/java/com/twiliovoicereactnative/StatsListenerProxy.java +19 -24
- package/android/src/main/java/com/twiliovoicereactnative/TwilioVoiceReactNativeModule.java +293 -611
- package/android/src/main/java/com/twiliovoicereactnative/VoiceApplicationProxy.java +4 -0
- package/android/src/main/java/com/twiliovoicereactnative/VoiceModuleProxy.java +339 -0
- package/android/src/main/java/com/twiliovoicereactnative/VoiceService.java +76 -21
- package/android/src/main/res/values/config.xml +0 -1
- package/expo-module.config.json +1 -1
- package/ios/TwilioVoiceReactNative+CallKit.m +6 -29
- package/ios/TwilioVoiceReactNative+PreflightTest.m +350 -0
- package/ios/TwilioVoiceReactNative+PromiseAdapter.m +39 -0
- package/ios/TwilioVoiceReactNative.h +18 -2
- package/ios/TwilioVoiceReactNative.m +345 -275
- package/ios/TwilioVoiceReactNative.xcodeproj/project.pbxproj +8 -2
- package/ios/TwilioVoiceReactNativeConstants.h +149 -1
- package/lib/commonjs/AudioDevice.js +2 -2
- package/lib/commonjs/AudioDevice.js.map +1 -1
- package/lib/commonjs/Call.js +13 -10
- package/lib/commonjs/Call.js.map +1 -1
- package/lib/commonjs/CallInvite.js +14 -25
- package/lib/commonjs/CallInvite.js.map +1 -1
- package/lib/commonjs/PreflightTest.js +683 -0
- package/lib/commonjs/PreflightTest.js.map +1 -0
- package/lib/commonjs/Voice.js +117 -86
- package/lib/commonjs/Voice.js.map +1 -1
- package/lib/commonjs/__mock-data__/PreflightTest.js +271 -0
- package/lib/commonjs/__mock-data__/PreflightTest.js.map +1 -0
- package/lib/commonjs/common.js +9 -5
- package/lib/commonjs/common.js.map +1 -1
- package/lib/commonjs/constants.js +107 -1
- package/lib/commonjs/constants.js.map +1 -1
- package/lib/commonjs/error/UnexpectedNativeError.js +36 -0
- package/lib/commonjs/error/UnexpectedNativeError.js.map +1 -0
- package/lib/commonjs/error/index.js +8 -0
- package/lib/commonjs/error/index.js.map +1 -1
- package/lib/commonjs/index.js +43 -3
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/type/AudioCodec.js +24 -0
- package/lib/commonjs/type/AudioCodec.js.map +1 -0
- package/lib/commonjs/type/Ice.js +24 -0
- package/lib/commonjs/type/Ice.js.map +1 -0
- package/lib/commonjs/type/PreflightTest.js +4 -0
- package/lib/commonjs/type/PreflightTest.js.map +1 -0
- package/lib/commonjs/utility/nativePromise.js +46 -0
- package/lib/commonjs/utility/nativePromise.js.map +1 -0
- package/lib/commonjs/utility/preflightTestOptions.js +213 -0
- package/lib/commonjs/utility/preflightTestOptions.js.map +1 -0
- package/lib/module/AudioDevice.js +2 -2
- package/lib/module/AudioDevice.js.map +1 -1
- package/lib/module/Call.js +12 -10
- package/lib/module/Call.js.map +1 -1
- package/lib/module/CallInvite.js +13 -25
- package/lib/module/CallInvite.js.map +1 -1
- package/lib/module/PreflightTest.js +670 -0
- package/lib/module/PreflightTest.js.map +1 -0
- package/lib/module/Voice.js +127 -86
- package/lib/module/Voice.js.map +1 -1
- package/lib/module/__mock-data__/PreflightTest.js +248 -0
- package/lib/module/__mock-data__/PreflightTest.js.map +1 -0
- package/lib/module/common.js +4 -2
- package/lib/module/common.js.map +1 -1
- package/lib/module/constants.js +107 -1
- package/lib/module/constants.js.map +1 -1
- package/lib/module/error/UnexpectedNativeError.js +27 -0
- package/lib/module/error/UnexpectedNativeError.js.map +1 -0
- package/lib/module/error/index.js +1 -0
- package/lib/module/error/index.js.map +1 -1
- package/lib/module/index.js +3 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/type/AudioCodec.js +15 -0
- package/lib/module/type/AudioCodec.js.map +1 -0
- package/lib/module/type/Ice.js +15 -0
- package/lib/module/type/Ice.js.map +1 -0
- package/lib/module/type/PreflightTest.js +2 -0
- package/lib/module/type/PreflightTest.js.map +1 -0
- package/lib/module/utility/nativePromise.js +32 -0
- package/lib/module/utility/nativePromise.js.map +1 -0
- package/lib/module/utility/preflightTestOptions.js +204 -0
- package/lib/module/utility/preflightTestOptions.js.map +1 -0
- package/lib/typescript/PreflightTest.d.ts +710 -0
- package/lib/typescript/Voice.d.ts +66 -27
- package/lib/typescript/__mock-data__/PreflightTest.d.ts +120 -0
- package/lib/typescript/common.d.ts +2 -1
- package/lib/typescript/constants.d.ts +108 -2
- package/lib/typescript/error/UnexpectedNativeError.d.ts +13 -0
- package/lib/typescript/error/index.d.ts +1 -0
- package/lib/typescript/index.d.ts +3 -1
- package/lib/typescript/type/AudioCodec.d.ts +41 -0
- package/lib/typescript/type/Ice.d.ts +22 -0
- package/lib/typescript/type/NativeModule.d.ts +56 -31
- package/lib/typescript/type/PreflightTest.d.ts +28 -0
- package/lib/typescript/utility/nativePromise.d.ts +2 -0
- package/lib/typescript/utility/preflightTestOptions.d.ts +13 -0
- package/package.json +26 -21
- package/react-native.config.js +7 -0
- package/src/AudioDevice.tsx +2 -2
- package/src/Call.tsx +26 -14
- package/src/CallInvite.tsx +31 -28
- package/src/PreflightTest.ts +1481 -0
- package/src/Voice.tsx +140 -88
- package/src/__mock-data__/PreflightTest.ts +272 -0
- package/src/common.ts +13 -5
- package/src/constants.ts +149 -1
- package/src/error/UnexpectedNativeError.ts +21 -0
- package/src/error/index.ts +1 -0
- package/src/index.tsx +8 -1
- package/src/type/AudioCodec.ts +45 -0
- package/src/type/Ice.ts +24 -0
- package/src/type/NativeModule.ts +80 -31
- package/src/type/PreflightTest.ts +40 -0
- package/src/utility/nativePromise.ts +40 -0
- package/src/utility/preflightTestOptions.ts +237 -0
- package/twilio-voice-react-native.podspec +1 -1
- package/android/src/main/java/com/twiliovoicereactnative/ExpoActivityLifecycleListener.java +0 -39
- package/android/src/main/java/com/twiliovoicereactnative/ExpoApplicationLifecycleListener.java +0 -14
- package/android/src/main/java/com/twiliovoicereactnative/ExpoPackage.java +0 -20
- package/expo-config-plugin/android.js +0 -191
- package/expo-config-plugin/ios.js +0 -22
- package/lib/commonjs/ExpoModule.js +0 -74
- package/lib/commonjs/ExpoModule.js.map +0 -1
- package/lib/module/ExpoModule.js +0 -63
- package/lib/module/ExpoModule.js.map +0 -1
- package/lib/typescript/ExpoModule.d.ts +0 -13
- package/src/ExpoModule.ts +0 -64
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
# Twilio Voice React Native SDK
|
|
2
|
-
|
|
3
2
|
[](https://www.npmjs.com/package/%40twilio/voice-react-native-sdk) [](https://dl.circleci.com/status-badge/redirect/gh/twilio/twilio-voice-react-native/tree/main)
|
|
4
3
|
|
|
5
4
|
Twilio's Voice React Native SDK allows you to add real-time voice and PSTN calling to your React Native apps.
|
|
@@ -14,7 +13,6 @@ Please check out the following if you are new to Twilio's Programmable Voice or
|
|
|
14
13
|
- [React Native](https://reactnative.dev/docs/getting-started)
|
|
15
14
|
|
|
16
15
|
## Installation
|
|
17
|
-
|
|
18
16
|
The package is available through [npm](https://www.npmjs.com/package/@twilio/voice-react-native-sdk).
|
|
19
17
|
|
|
20
18
|
```sh
|
|
@@ -23,144 +21,44 @@ yarn add @twilio/voice-react-native-sdk
|
|
|
23
21
|
|
|
24
22
|
Once the package has been installed to your React Native application, there are further steps that you will need to take for both iOS and Android platforms. Please see the supporting documentation below.
|
|
25
23
|
|
|
26
|
-
##
|
|
27
|
-
|
|
28
|
-
This is a forked version of the Twilio Voice React Native SDK. If you need to build and publish new versions of this package to npm, follow these steps:
|
|
29
|
-
|
|
30
|
-
### Prerequisites
|
|
31
|
-
|
|
32
|
-
1. **Node.js and Yarn**: Ensure you have Node.js and Yarn installed
|
|
33
|
-
2. **NPM Account**: You need to be logged into npm with the appropriate permissions
|
|
34
|
-
3. **Git Repository**: Make sure your changes are committed to your fork
|
|
35
|
-
|
|
36
|
-
### Build Process
|
|
37
|
-
|
|
38
|
-
1. **Install Dependencies**:
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
yarn install
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
2. **Build the Package**:
|
|
45
|
-
|
|
46
|
-
```bash
|
|
47
|
-
yarn prepare
|
|
48
|
-
```
|
|
24
|
+
## 2.x Documentation
|
|
49
25
|
|
|
50
|
-
|
|
26
|
+
### Expo support
|
|
51
27
|
|
|
52
|
-
|
|
53
|
-
- Build CommonJS, ES modules, and TypeScript definitions
|
|
54
|
-
- Create source maps for debugging
|
|
55
|
-
- Output files to the `lib/` directory
|
|
28
|
+
With the release of `2.x` versions (including our preview versions available through `npm` and Github Releases), the Twilio Voice React Native SDK officially supports the Expo framework out-of-the-box.
|
|
56
29
|
|
|
57
|
-
|
|
58
|
-
Check that the following directories are created:
|
|
59
|
-
- `lib/commonjs/` - CommonJS modules
|
|
60
|
-
- `lib/module/` - ES modules
|
|
61
|
-
- `lib/typescript/` - TypeScript definitions
|
|
30
|
+
**Please note that `2.x` versions of the SDK do not support framework-less ("bare") React Native applications!**
|
|
62
31
|
|
|
63
|
-
|
|
32
|
+
**Please note that `2.0.0-preview.1` only supports Expo v52 at this time. Other versions of Expo are not tested or guaranteed to work!**
|
|
64
33
|
|
|
65
|
-
|
|
66
|
-
Edit `package.json` and increment the version number:
|
|
67
|
-
|
|
68
|
-
```json
|
|
69
|
-
{
|
|
70
|
-
"version": "1.6.2-fork.2" // Increment from previous version
|
|
71
|
-
}
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
2. **Verify Package Configuration**:
|
|
75
|
-
Ensure your `package.json` has the correct:
|
|
76
|
-
|
|
77
|
-
- Package name (e.g., `@your-username/voice-react-native-sdk`)
|
|
78
|
-
- Repository URLs pointing to your fork
|
|
79
|
-
- Author information
|
|
80
|
-
|
|
81
|
-
3. **Login to NPM**:
|
|
82
|
-
|
|
83
|
-
```bash
|
|
84
|
-
npm login
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
4. **Publish the Package**:
|
|
88
|
-
```bash
|
|
89
|
-
npm publish --access public
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### Using Your Published Package
|
|
93
|
-
|
|
94
|
-
Once published, you can install your forked version in any React Native project:
|
|
95
|
-
|
|
96
|
-
```bash
|
|
97
|
-
# Install your forked version
|
|
98
|
-
npm install @your-username/voice-react-native-sdk
|
|
99
|
-
# or
|
|
100
|
-
yarn add @your-username/voice-react-native-sdk
|
|
101
|
-
```
|
|
34
|
+
After installing the Twilio Voice React Native SDK to your Expo application, please follow this [doc](./docs/expo/app-config.md) for steps on configuring your Expo app with the proper permissions and grants to use Twilio Voice features.
|
|
102
35
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
```javascript
|
|
106
|
-
import { Voice } from '@your-username/voice-react-native-sdk';
|
|
107
|
-
|
|
108
|
-
const voice = new Voice();
|
|
109
|
-
// Use the SDK as normal
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
### Package Structure
|
|
113
|
-
|
|
114
|
-
The published package includes:
|
|
115
|
-
|
|
116
|
-
- **Source Code**: Original TypeScript/JavaScript source files
|
|
117
|
-
- **Built Libraries**: Compiled CommonJS and ES modules
|
|
118
|
-
- **Type Definitions**: Complete TypeScript definitions
|
|
119
|
-
- **Native Code**: Android (Java) and iOS (Objective-C) implementations
|
|
120
|
-
- **Assets**: Audio files, icons, and other resources
|
|
121
|
-
- **Source Maps**: For debugging compiled code
|
|
122
|
-
|
|
123
|
-
### Troubleshooting
|
|
124
|
-
|
|
125
|
-
- **Build Errors**: Run `yarn install` to ensure all dependencies are installed
|
|
126
|
-
- **Publish Errors**: Verify you're logged into npm with `npm whoami`
|
|
127
|
-
- **Permission Errors**: Ensure you have publish rights to the npm scope/organization
|
|
128
|
-
- **Version Conflicts**: Make sure the version number is unique and higher than the previous version
|
|
129
|
-
|
|
130
|
-
## Supporting Documentation
|
|
36
|
+
## 1.x Documentation
|
|
131
37
|
|
|
132
38
|
### Getting Started
|
|
133
39
|
|
|
134
40
|
#### iOS
|
|
135
|
-
|
|
136
41
|
Learn how to get started for the [iOS platform](/docs/getting-started-ios.md).
|
|
137
42
|
|
|
138
43
|
#### Android
|
|
139
|
-
|
|
140
44
|
Learn how to get started for the Android platform if you are using [Java](/docs/getting-started-android-java.md) or [Kotlin](/docs/getting-started-android-kotlin.md).
|
|
141
45
|
|
|
142
46
|
### Migration Guide
|
|
143
|
-
|
|
144
47
|
If you are migrating from a version of the Twilio Voice React Native SDK `< 1.0.0.beta.4` to a version `>= 1.0.0.beta.4`, please see [this](/docs/migration-guide-beta.4.md) document.
|
|
145
48
|
|
|
146
49
|
### Customizing Notifications
|
|
147
|
-
|
|
148
50
|
To customize the appearance and content of your application's notifications, please see [this](/docs/customize-notifications.md) document.
|
|
149
51
|
|
|
150
52
|
### Outgoing Call Ringback Tone
|
|
151
|
-
|
|
152
53
|
To enable your application to play a ringback tone while making an outgoing call, please see [this](/docs/play-outgoing-call-ringback-tone.md) document.
|
|
153
54
|
|
|
154
55
|
### Out-of-band PushKit Handling
|
|
155
|
-
|
|
156
56
|
To have your application implement or use its own `PushKit` delegate module, please see [this](/docs/applications-own-pushkit-handler.md) document.
|
|
157
57
|
|
|
158
58
|
### Out-of-band Firebase Messaging Service
|
|
159
|
-
|
|
160
59
|
To have your application implement or use a different `FirebaseMessagingService` (such as OneSignal or RNFirebase), please see [this](/docs/out-of-band-firebase-messaging-service.md) document.
|
|
161
60
|
|
|
162
61
|
## Issues and Support
|
|
163
|
-
|
|
164
62
|
Please check out our [common issues](/COMMON_ISSUES.md) page or file any issues you find here on Github. For general inquiries related to the Voice SDK you can file a support ticket.
|
|
165
63
|
|
|
166
64
|
Please ensure that you are not sharing any [Personally Identifiable Information(PII)](https://www.twilio.com/docs/glossary/what-is-personally-identifiable-information-pii) or sensitive account information (API keys, credentials, etc.) when reporting an issue.
|
|
@@ -168,12 +66,10 @@ Please ensure that you are not sharing any [Personally Identifiable Information(
|
|
|
168
66
|
Please check out our [known issues](/KNOWN_ISSUES.md) for known bugs and workarounds.
|
|
169
67
|
|
|
170
68
|
## Related
|
|
171
|
-
|
|
172
69
|
- [Reference App](https://github.com/twilio/twilio-voice-react-native-app)
|
|
173
70
|
- [Twilio Voice JS](https://github.com/twilio/twilio-voice.js)
|
|
174
71
|
- [Twilio Voice iOS](https://github.com/twilio/voice-quickstart-ios)
|
|
175
72
|
- [Twilio Voice Android](https://github.com/twilio/voice-quickstart-android)
|
|
176
73
|
|
|
177
74
|
## License
|
|
178
|
-
|
|
179
75
|
See [LICENSE](/LICENSE)
|
package/android/build.gradle
CHANGED
|
@@ -8,7 +8,7 @@ buildscript {
|
|
|
8
8
|
'androidxLifecycle' : '2.2.0',
|
|
9
9
|
'audioSwitch' : '1.2.2',
|
|
10
10
|
'firebaseMessaging' : '23.4.0',
|
|
11
|
-
'kotlin': '1.9.
|
|
11
|
+
'kotlin' : '1.9.25'
|
|
12
12
|
]
|
|
13
13
|
if (project == rootProject) {
|
|
14
14
|
repositories {
|
|
@@ -77,7 +77,7 @@ dependencies {
|
|
|
77
77
|
implementation "com.google.firebase:firebase-messaging:${versions.firebaseMessaging}"
|
|
78
78
|
implementation "com.twilio:audioswitch:${versions.audioSwitch}"
|
|
79
79
|
implementation 'com.google.android.material:material:1.1.0'
|
|
80
|
-
|
|
80
|
+
|
|
81
81
|
implementation project(':expo-modules-core')
|
|
82
82
|
|
|
83
83
|
constraints {
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
package com.twiliovoicereactnative;
|
|
2
|
+
|
|
3
|
+
import android.os.Handler;
|
|
4
|
+
import android.os.Looper;
|
|
5
|
+
|
|
6
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
7
|
+
import com.twilio.voice.CallMessage;
|
|
8
|
+
|
|
9
|
+
import java.util.function.Consumer;
|
|
10
|
+
import java.util.UUID;
|
|
11
|
+
|
|
12
|
+
class CallInviteModuleProxy {
|
|
13
|
+
private static final SDKLog logger = new SDKLog(CallInviteModuleProxy.class);
|
|
14
|
+
|
|
15
|
+
private final Handler mainHandler = new Handler(Looper.getMainLooper());
|
|
16
|
+
|
|
17
|
+
private final ReactApplicationContext reactApplicationContext;
|
|
18
|
+
|
|
19
|
+
public CallInviteModuleProxy(ReactApplicationContext reactApplicationContext) {
|
|
20
|
+
this.reactApplicationContext = reactApplicationContext;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
private void getCallRecord(
|
|
24
|
+
String uuidStr,
|
|
25
|
+
ModuleProxy.UniversalPromise promise,
|
|
26
|
+
Consumer<CallRecordDatabase.CallRecord> onSuccess
|
|
27
|
+
) {
|
|
28
|
+
logger.debug(String.format(".getCallRecord(%s)", uuidStr));
|
|
29
|
+
|
|
30
|
+
final UUID uuid = UUID.fromString(uuidStr);
|
|
31
|
+
|
|
32
|
+
CallRecordDatabase.CallRecord callRecord = VoiceApplicationProxy
|
|
33
|
+
.getCallRecordDatabase()
|
|
34
|
+
.get(new CallRecordDatabase.CallRecord(uuid));
|
|
35
|
+
|
|
36
|
+
if (null == callRecord || null == callRecord.getCallInvite()) {
|
|
37
|
+
final String warningMsg = this.reactApplicationContext
|
|
38
|
+
.getString(R.string.missing_callinvite_uuid, uuid);
|
|
39
|
+
promise.rejectWithName(CommonConstants.ErrorCodeInvalidArgumentError, warningMsg);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
mainHandler.post(() -> {
|
|
44
|
+
logger.debug(String.format(".getCallRecord(%s) > runnable", uuid));
|
|
45
|
+
onSuccess.accept(callRecord);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public void accept(String uuid, ModuleProxy.UniversalPromise promise) {
|
|
50
|
+
logger.debug(String.format(".accept(%s)", uuid));
|
|
51
|
+
|
|
52
|
+
getCallRecord(uuid, promise, (callRecord) -> {
|
|
53
|
+
logger.debug(String.format(".accept(%s) > runnable", uuid));
|
|
54
|
+
|
|
55
|
+
callRecord.setCallAcceptedPromise(promise);
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
VoiceApplicationProxy
|
|
59
|
+
.getVoiceServiceApi()
|
|
60
|
+
.acceptCall(callRecord);
|
|
61
|
+
} catch (SecurityException e) {
|
|
62
|
+
logger.error(e.toString());
|
|
63
|
+
promise.rejectWithCode(31401, e.getMessage());
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
public void reject(String uuid, ModuleProxy.UniversalPromise promise) {
|
|
69
|
+
logger.debug(String.format(".reject(%s)", uuid));
|
|
70
|
+
|
|
71
|
+
getCallRecord(uuid, promise, (callRecord) -> {
|
|
72
|
+
logger.debug(String.format(".reject(%s) > runnable", uuid));
|
|
73
|
+
|
|
74
|
+
// Store promise for callback
|
|
75
|
+
callRecord.setCallRejectedPromise(promise);
|
|
76
|
+
|
|
77
|
+
// Send Event to service
|
|
78
|
+
VoiceApplicationProxy
|
|
79
|
+
.getVoiceServiceApi()
|
|
80
|
+
.rejectCall(callRecord);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
public void sendMessage(
|
|
85
|
+
String uuid,
|
|
86
|
+
String content,
|
|
87
|
+
String contentType,
|
|
88
|
+
String messageType,
|
|
89
|
+
ModuleProxy.UniversalPromise promise
|
|
90
|
+
) {
|
|
91
|
+
logger.debug(String.format(".sendMessage(%s)", uuid));
|
|
92
|
+
|
|
93
|
+
getCallRecord(uuid, promise, (callRecord) -> {
|
|
94
|
+
logger.debug(String.format(".sendMessage(%s) > runnable", uuid));
|
|
95
|
+
|
|
96
|
+
final CallMessage callMessage = new CallMessage.Builder(messageType)
|
|
97
|
+
.contentType(contentType)
|
|
98
|
+
.content(content)
|
|
99
|
+
.build();
|
|
100
|
+
|
|
101
|
+
if (CallRecordDatabase.CallRecord.CallInviteState.ACTIVE != callRecord.getCallInviteState()) {
|
|
102
|
+
promise.rejectWithName(
|
|
103
|
+
CommonConstants.ErrorCodeInvalidStateError,
|
|
104
|
+
"Attempt to send call message on settled call invite"
|
|
105
|
+
);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
final String callMessageSid = callRecord.getCallInvite().sendMessage(callMessage);
|
|
110
|
+
|
|
111
|
+
promise.resolve(callMessageSid);
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
package com.twiliovoicereactnative;
|
|
2
|
+
|
|
3
|
+
import android.os.Handler;
|
|
4
|
+
import android.os.Looper;
|
|
5
|
+
|
|
6
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
7
|
+
import com.twilio.voice.Call;
|
|
8
|
+
import com.twilio.voice.CallMessage;
|
|
9
|
+
|
|
10
|
+
import java.util.function.Consumer;
|
|
11
|
+
import java.util.Map;
|
|
12
|
+
import java.util.UUID;
|
|
13
|
+
|
|
14
|
+
class CallModuleProxy {
|
|
15
|
+
/**
|
|
16
|
+
* Map of common constant score strings to the Call.Score enum.
|
|
17
|
+
*/
|
|
18
|
+
public static final Map<String, Call.Score> scoreMap = Map.of(
|
|
19
|
+
CommonConstants.CallFeedbackScoreNotReported, Call.Score.NOT_REPORTED,
|
|
20
|
+
CommonConstants.CallFeedbackScoreOne, Call.Score.ONE,
|
|
21
|
+
CommonConstants.CallFeedbackScoreTwo, Call.Score.TWO,
|
|
22
|
+
CommonConstants.CallFeedbackScoreThree, Call.Score.THREE,
|
|
23
|
+
CommonConstants.CallFeedbackScoreFour, Call.Score.FOUR,
|
|
24
|
+
CommonConstants.CallFeedbackScoreFive, Call.Score.FIVE
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Map of common constant issue strings to the Call.Issue enum.
|
|
29
|
+
*/
|
|
30
|
+
public static final Map<String, Call.Issue> issueMap = Map.of(
|
|
31
|
+
CommonConstants.CallFeedbackIssueAudioLatency, Call.Issue.AUDIO_LATENCY,
|
|
32
|
+
CommonConstants.CallFeedbackIssueChoppyAudio, Call.Issue.CHOPPY_AUDIO,
|
|
33
|
+
CommonConstants.CallFeedbackIssueEcho, Call.Issue.ECHO,
|
|
34
|
+
CommonConstants.CallFeedbackIssueDroppedCall, Call.Issue.DROPPED_CALL,
|
|
35
|
+
CommonConstants.CallFeedbackIssueNoisyCall, Call.Issue.NOISY_CALL,
|
|
36
|
+
CommonConstants.CallFeedbackIssueNotReported, Call.Issue.NOT_REPORTED,
|
|
37
|
+
CommonConstants.CallFeedbackIssueOneWayAudio, Call.Issue.ONE_WAY_AUDIO
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Use the score map to get a Call.Score value from a string.
|
|
42
|
+
* @param score The score as a string passed from the JS layer.
|
|
43
|
+
* @return a Call.Score enum value. If the passed string is not in the enum, defaults to
|
|
44
|
+
* Call.Score.NOT_REPORTED.
|
|
45
|
+
*/
|
|
46
|
+
public static Call.Score getScoreFromString(String score) {
|
|
47
|
+
return scoreMap.getOrDefault(score, Call.Score.NOT_REPORTED);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Use the issue map to get a Call.Issue value from a string.
|
|
52
|
+
* @param issue The issue as a string passed from the JS layer.
|
|
53
|
+
* @return a Call.Issue enum value. If the passed string is not in the enum, defaults to
|
|
54
|
+
* Call.Issue.NOT_REPORTED.
|
|
55
|
+
*/
|
|
56
|
+
public static Call.Issue getIssueFromString(String issue) {
|
|
57
|
+
return issueMap.getOrDefault(issue, Call.Issue.NOT_REPORTED);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
private final SDKLog logger = new SDKLog(CallModuleProxy.class);
|
|
61
|
+
|
|
62
|
+
private final Handler mainHandler = new Handler(Looper.getMainLooper());
|
|
63
|
+
|
|
64
|
+
private final ReactApplicationContext reactApplicationContext;
|
|
65
|
+
|
|
66
|
+
public CallModuleProxy(ReactApplicationContext reactApplicationContext) {
|
|
67
|
+
this.reactApplicationContext = reactApplicationContext;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private void getCallRecord(
|
|
71
|
+
String uuidStr,
|
|
72
|
+
ModuleProxy.UniversalPromise promise,
|
|
73
|
+
Consumer<CallRecordDatabase.CallRecord> onSuccess
|
|
74
|
+
) {
|
|
75
|
+
logger.debug(String.format(".getCallRecord(%s)", uuidStr));
|
|
76
|
+
|
|
77
|
+
final UUID uuid = UUID.fromString(uuidStr);
|
|
78
|
+
|
|
79
|
+
final CallRecordDatabase.CallRecord callRecord = VoiceApplicationProxy
|
|
80
|
+
.getCallRecordDatabase()
|
|
81
|
+
.get(new CallRecordDatabase.CallRecord(uuid));
|
|
82
|
+
|
|
83
|
+
if (null == callRecord || null == callRecord.getVoiceCall()) {
|
|
84
|
+
final String warningMsg = this.reactApplicationContext
|
|
85
|
+
.getString(R.string.missing_call_uuid, uuid);
|
|
86
|
+
promise.rejectWithName(CommonConstants.ErrorCodeInvalidArgumentError, warningMsg);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
mainHandler.post(() -> {
|
|
91
|
+
logger.debug(".getCallRecord() > runnable");
|
|
92
|
+
onSuccess.accept(callRecord);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
public void getState(String uuid, ModuleProxy.UniversalPromise promise) {
|
|
97
|
+
logger.debug(".getState()");
|
|
98
|
+
|
|
99
|
+
getCallRecord(uuid, promise, (callRecord) -> {
|
|
100
|
+
final String state = callRecord
|
|
101
|
+
.getVoiceCall()
|
|
102
|
+
.getState()
|
|
103
|
+
.toString()
|
|
104
|
+
.toLowerCase();
|
|
105
|
+
promise.resolve(state);
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
public void isMuted(String uuid, ModuleProxy.UniversalPromise promise) {
|
|
110
|
+
logger.debug(".isMuted()");
|
|
111
|
+
|
|
112
|
+
getCallRecord(uuid, promise, (callRecord) -> {
|
|
113
|
+
final boolean isMuted = callRecord
|
|
114
|
+
.getVoiceCall()
|
|
115
|
+
.isMuted();
|
|
116
|
+
promise.resolve(isMuted);
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
public void isOnHold(String uuid, ModuleProxy.UniversalPromise promise) {
|
|
121
|
+
logger.debug(".isOnHold()");
|
|
122
|
+
|
|
123
|
+
getCallRecord(uuid, promise, (callRecord) -> {
|
|
124
|
+
final boolean isOnHold = callRecord
|
|
125
|
+
.getVoiceCall()
|
|
126
|
+
.isOnHold();
|
|
127
|
+
promise.resolve(isOnHold);
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
public void disconnect(String uuid, ModuleProxy.UniversalPromise promise) {
|
|
132
|
+
logger.debug(String.format(".disconnect(%s)", uuid));
|
|
133
|
+
|
|
134
|
+
getCallRecord(uuid, promise, (callRecord) -> {
|
|
135
|
+
callRecord
|
|
136
|
+
.getVoiceCall()
|
|
137
|
+
.disconnect();
|
|
138
|
+
promise.resolve(null);
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
public void hold(String uuid, boolean hold, ModuleProxy.UniversalPromise promise) {
|
|
143
|
+
logger.debug(".hold()");
|
|
144
|
+
|
|
145
|
+
getCallRecord(uuid, promise, (callRecord) -> {
|
|
146
|
+
callRecord
|
|
147
|
+
.getVoiceCall()
|
|
148
|
+
.hold(hold);
|
|
149
|
+
promise.resolve(hold);
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
public void mute(String uuid, boolean mute, ModuleProxy.UniversalPromise promise) {
|
|
154
|
+
logger.debug(".mute()");
|
|
155
|
+
|
|
156
|
+
getCallRecord(uuid, promise, (callRecord) -> {
|
|
157
|
+
callRecord
|
|
158
|
+
.getVoiceCall()
|
|
159
|
+
.mute(mute);
|
|
160
|
+
promise.resolve(mute);
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
public void sendDigits(String uuid, String digits, ModuleProxy.UniversalPromise promise) {
|
|
165
|
+
logger.debug(".sendDigits()");
|
|
166
|
+
|
|
167
|
+
getCallRecord(uuid, promise, (callRecord) -> {
|
|
168
|
+
callRecord
|
|
169
|
+
.getVoiceCall()
|
|
170
|
+
.sendDigits(digits);
|
|
171
|
+
promise.resolve(null);
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
public void postFeedback(String uuid, String score, String issue, ModuleProxy.UniversalPromise promise) {
|
|
176
|
+
logger.debug(".postFeedback()");
|
|
177
|
+
|
|
178
|
+
getCallRecord(uuid, promise, (callRecord) -> {
|
|
179
|
+
Call.Score parsedScore = CallModuleProxy.getScoreFromString(score);
|
|
180
|
+
Call.Issue parsedIssue = CallModuleProxy.getIssueFromString(issue);
|
|
181
|
+
|
|
182
|
+
callRecord
|
|
183
|
+
.getVoiceCall()
|
|
184
|
+
.postFeedback(parsedScore, parsedIssue);
|
|
185
|
+
|
|
186
|
+
promise.resolve(null);
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
public void getStats(String uuid, ModuleProxy.UniversalPromise promise) {
|
|
191
|
+
logger.debug(".getStats()");
|
|
192
|
+
|
|
193
|
+
getCallRecord(uuid, promise, (callRecord) -> {
|
|
194
|
+
callRecord
|
|
195
|
+
.getVoiceCall()
|
|
196
|
+
.getStats(new StatsListenerProxy(promise));
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
public void sendMessage(
|
|
201
|
+
String uuid,
|
|
202
|
+
String content,
|
|
203
|
+
String contentType,
|
|
204
|
+
String messageType,
|
|
205
|
+
ModuleProxy.UniversalPromise promise
|
|
206
|
+
) {
|
|
207
|
+
logger.debug(".sendMessage()");
|
|
208
|
+
|
|
209
|
+
getCallRecord(uuid, promise, (callRecord) -> {
|
|
210
|
+
final CallMessage callMessage = new CallMessage.Builder(messageType)
|
|
211
|
+
.contentType(contentType)
|
|
212
|
+
.content(content)
|
|
213
|
+
.build();
|
|
214
|
+
|
|
215
|
+
final String callMessageSid =
|
|
216
|
+
CallRecordDatabase.CallRecord.CallInviteState.ACTIVE == callRecord.getCallInviteState()
|
|
217
|
+
? callRecord.getCallInvite().sendMessage(callMessage)
|
|
218
|
+
: callRecord.getVoiceCall().sendMessage(callMessage);
|
|
219
|
+
|
|
220
|
+
promise.resolve(callMessageSid);
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
}
|
|
@@ -13,7 +13,6 @@ import java.util.Map;
|
|
|
13
13
|
|
|
14
14
|
import androidx.annotation.NonNull;
|
|
15
15
|
|
|
16
|
-
import com.facebook.react.bridge.Promise;
|
|
17
16
|
import com.twilio.voice.Call;
|
|
18
17
|
import com.twilio.voice.CallException;
|
|
19
18
|
import com.twilio.voice.CallInvite;
|
|
@@ -32,8 +31,8 @@ class CallRecordDatabase {
|
|
|
32
31
|
private CallInvite callInvite = null;
|
|
33
32
|
private CallInviteState callInviteState = NONE;
|
|
34
33
|
private CancelledCallInvite cancelledCallInvite = null;
|
|
35
|
-
private
|
|
36
|
-
private
|
|
34
|
+
private ModuleProxy.UniversalPromise callAcceptedPromise = null;
|
|
35
|
+
private ModuleProxy.UniversalPromise callRejectedPromise = null;
|
|
37
36
|
private CallException callException = null;
|
|
38
37
|
private Map<String, String> customParameters = null;
|
|
39
38
|
private String notificationDisplayName = null;
|
|
@@ -103,16 +102,18 @@ class CallRecordDatabase {
|
|
|
103
102
|
public CancelledCallInvite getCancelledCallInvite() {
|
|
104
103
|
return this.cancelledCallInvite;
|
|
105
104
|
}
|
|
106
|
-
public
|
|
105
|
+
public ModuleProxy.UniversalPromise getCallAcceptedPromise() {
|
|
107
106
|
return this.callAcceptedPromise;
|
|
108
107
|
}
|
|
109
|
-
public
|
|
108
|
+
public ModuleProxy.UniversalPromise getCallRejectedPromise() {
|
|
110
109
|
return this.callRejectedPromise;
|
|
111
110
|
}
|
|
112
111
|
public CallException getCallException() {
|
|
113
112
|
return this.callException;
|
|
114
113
|
}
|
|
115
|
-
public String getCallRecipient() {
|
|
114
|
+
public String getCallRecipient() {
|
|
115
|
+
return this.callRecipient;
|
|
116
|
+
}
|
|
116
117
|
public void setNotificationId(int notificationId) {
|
|
117
118
|
this.notificationId = notificationId;
|
|
118
119
|
}
|
|
@@ -124,7 +125,9 @@ class CallRecordDatabase {
|
|
|
124
125
|
this.voiceCall = voiceCall;
|
|
125
126
|
}
|
|
126
127
|
public void setCallInviteUsedState() {
|
|
127
|
-
this.callInviteState =
|
|
128
|
+
this.callInviteState = this.callInviteState == ACTIVE
|
|
129
|
+
? USED
|
|
130
|
+
: this.callInviteState;
|
|
128
131
|
}
|
|
129
132
|
public void setCancelledCallInvite(@NonNull CancelledCallInvite cancelledCallInvite) {
|
|
130
133
|
this.callSid = cancelledCallInvite.getCallSid();
|
|
@@ -132,10 +135,10 @@ class CallRecordDatabase {
|
|
|
132
135
|
this.callInvite = null;
|
|
133
136
|
this.callInviteState = NONE;
|
|
134
137
|
}
|
|
135
|
-
public void setCallAcceptedPromise(@NonNull
|
|
138
|
+
public void setCallAcceptedPromise(@NonNull ModuleProxy.UniversalPromise callAcceptedPromise) {
|
|
136
139
|
this.callAcceptedPromise = callAcceptedPromise;
|
|
137
140
|
}
|
|
138
|
-
public void setCallRejectedPromise(@NonNull
|
|
141
|
+
public void setCallRejectedPromise(@NonNull ModuleProxy.UniversalPromise callRejectedPromise) {
|
|
139
142
|
this.callRejectedPromise = callRejectedPromise;
|
|
140
143
|
}
|
|
141
144
|
public void setCallException(CallException callException) {
|