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.
Files changed (143) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +7 -111
  3. package/android/build.gradle +2 -2
  4. package/android/src/main/java/com/twiliovoicereactnative/CallInviteModuleProxy.java +114 -0
  5. package/android/src/main/java/com/twiliovoicereactnative/CallModuleProxy.java +223 -0
  6. package/android/src/main/java/com/twiliovoicereactnative/CallRecordDatabase.java +12 -9
  7. package/android/src/main/java/com/twiliovoicereactnative/CommonConstants.java +149 -1
  8. package/android/src/main/java/com/twiliovoicereactnative/ConfigurationProperties.java +0 -11
  9. package/android/src/main/java/com/twiliovoicereactnative/Constants.java +2 -0
  10. package/android/src/main/java/com/twiliovoicereactnative/ExpoActivityLifecycleListener.kt +62 -0
  11. package/android/src/main/java/com/twiliovoicereactnative/ExpoApplicationLifecycleListener.kt +18 -0
  12. package/android/src/main/java/com/twiliovoicereactnative/ExpoModule.kt +404 -35
  13. package/android/src/main/java/com/twiliovoicereactnative/ExpoPackage.kt +16 -0
  14. package/android/src/main/java/com/twiliovoicereactnative/ModuleProxy.java +57 -0
  15. package/android/src/main/java/com/twiliovoicereactnative/NotificationUtility.java +12 -24
  16. package/android/src/main/java/com/twiliovoicereactnative/PreflightTestListenerProxy.java +97 -0
  17. package/android/src/main/java/com/twiliovoicereactnative/PreflightTestModuleProxy.java +119 -0
  18. package/android/src/main/java/com/twiliovoicereactnative/PreflightTestRecordDatabase.java +37 -0
  19. package/android/src/main/java/com/twiliovoicereactnative/ReactNativeArgumentsSerializer.java +37 -7
  20. package/android/src/main/java/com/twiliovoicereactnative/RegistrationListenerProxy.java +88 -0
  21. package/android/src/main/java/com/twiliovoicereactnative/StatsListenerProxy.java +19 -24
  22. package/android/src/main/java/com/twiliovoicereactnative/TwilioVoiceReactNativeModule.java +293 -611
  23. package/android/src/main/java/com/twiliovoicereactnative/VoiceApplicationProxy.java +4 -0
  24. package/android/src/main/java/com/twiliovoicereactnative/VoiceModuleProxy.java +339 -0
  25. package/android/src/main/java/com/twiliovoicereactnative/VoiceService.java +76 -21
  26. package/android/src/main/res/values/config.xml +0 -1
  27. package/expo-module.config.json +1 -1
  28. package/ios/TwilioVoiceReactNative+CallKit.m +6 -29
  29. package/ios/TwilioVoiceReactNative+PreflightTest.m +350 -0
  30. package/ios/TwilioVoiceReactNative+PromiseAdapter.m +39 -0
  31. package/ios/TwilioVoiceReactNative.h +18 -2
  32. package/ios/TwilioVoiceReactNative.m +345 -275
  33. package/ios/TwilioVoiceReactNative.xcodeproj/project.pbxproj +8 -2
  34. package/ios/TwilioVoiceReactNativeConstants.h +149 -1
  35. package/lib/commonjs/AudioDevice.js +2 -2
  36. package/lib/commonjs/AudioDevice.js.map +1 -1
  37. package/lib/commonjs/Call.js +13 -10
  38. package/lib/commonjs/Call.js.map +1 -1
  39. package/lib/commonjs/CallInvite.js +14 -25
  40. package/lib/commonjs/CallInvite.js.map +1 -1
  41. package/lib/commonjs/PreflightTest.js +683 -0
  42. package/lib/commonjs/PreflightTest.js.map +1 -0
  43. package/lib/commonjs/Voice.js +117 -86
  44. package/lib/commonjs/Voice.js.map +1 -1
  45. package/lib/commonjs/__mock-data__/PreflightTest.js +271 -0
  46. package/lib/commonjs/__mock-data__/PreflightTest.js.map +1 -0
  47. package/lib/commonjs/common.js +9 -5
  48. package/lib/commonjs/common.js.map +1 -1
  49. package/lib/commonjs/constants.js +107 -1
  50. package/lib/commonjs/constants.js.map +1 -1
  51. package/lib/commonjs/error/UnexpectedNativeError.js +36 -0
  52. package/lib/commonjs/error/UnexpectedNativeError.js.map +1 -0
  53. package/lib/commonjs/error/index.js +8 -0
  54. package/lib/commonjs/error/index.js.map +1 -1
  55. package/lib/commonjs/index.js +43 -3
  56. package/lib/commonjs/index.js.map +1 -1
  57. package/lib/commonjs/type/AudioCodec.js +24 -0
  58. package/lib/commonjs/type/AudioCodec.js.map +1 -0
  59. package/lib/commonjs/type/Ice.js +24 -0
  60. package/lib/commonjs/type/Ice.js.map +1 -0
  61. package/lib/commonjs/type/PreflightTest.js +4 -0
  62. package/lib/commonjs/type/PreflightTest.js.map +1 -0
  63. package/lib/commonjs/utility/nativePromise.js +46 -0
  64. package/lib/commonjs/utility/nativePromise.js.map +1 -0
  65. package/lib/commonjs/utility/preflightTestOptions.js +213 -0
  66. package/lib/commonjs/utility/preflightTestOptions.js.map +1 -0
  67. package/lib/module/AudioDevice.js +2 -2
  68. package/lib/module/AudioDevice.js.map +1 -1
  69. package/lib/module/Call.js +12 -10
  70. package/lib/module/Call.js.map +1 -1
  71. package/lib/module/CallInvite.js +13 -25
  72. package/lib/module/CallInvite.js.map +1 -1
  73. package/lib/module/PreflightTest.js +670 -0
  74. package/lib/module/PreflightTest.js.map +1 -0
  75. package/lib/module/Voice.js +127 -86
  76. package/lib/module/Voice.js.map +1 -1
  77. package/lib/module/__mock-data__/PreflightTest.js +248 -0
  78. package/lib/module/__mock-data__/PreflightTest.js.map +1 -0
  79. package/lib/module/common.js +4 -2
  80. package/lib/module/common.js.map +1 -1
  81. package/lib/module/constants.js +107 -1
  82. package/lib/module/constants.js.map +1 -1
  83. package/lib/module/error/UnexpectedNativeError.js +27 -0
  84. package/lib/module/error/UnexpectedNativeError.js.map +1 -0
  85. package/lib/module/error/index.js +1 -0
  86. package/lib/module/error/index.js.map +1 -1
  87. package/lib/module/index.js +3 -1
  88. package/lib/module/index.js.map +1 -1
  89. package/lib/module/type/AudioCodec.js +15 -0
  90. package/lib/module/type/AudioCodec.js.map +1 -0
  91. package/lib/module/type/Ice.js +15 -0
  92. package/lib/module/type/Ice.js.map +1 -0
  93. package/lib/module/type/PreflightTest.js +2 -0
  94. package/lib/module/type/PreflightTest.js.map +1 -0
  95. package/lib/module/utility/nativePromise.js +32 -0
  96. package/lib/module/utility/nativePromise.js.map +1 -0
  97. package/lib/module/utility/preflightTestOptions.js +204 -0
  98. package/lib/module/utility/preflightTestOptions.js.map +1 -0
  99. package/lib/typescript/PreflightTest.d.ts +710 -0
  100. package/lib/typescript/Voice.d.ts +66 -27
  101. package/lib/typescript/__mock-data__/PreflightTest.d.ts +120 -0
  102. package/lib/typescript/common.d.ts +2 -1
  103. package/lib/typescript/constants.d.ts +108 -2
  104. package/lib/typescript/error/UnexpectedNativeError.d.ts +13 -0
  105. package/lib/typescript/error/index.d.ts +1 -0
  106. package/lib/typescript/index.d.ts +3 -1
  107. package/lib/typescript/type/AudioCodec.d.ts +41 -0
  108. package/lib/typescript/type/Ice.d.ts +22 -0
  109. package/lib/typescript/type/NativeModule.d.ts +56 -31
  110. package/lib/typescript/type/PreflightTest.d.ts +28 -0
  111. package/lib/typescript/utility/nativePromise.d.ts +2 -0
  112. package/lib/typescript/utility/preflightTestOptions.d.ts +13 -0
  113. package/package.json +26 -21
  114. package/react-native.config.js +7 -0
  115. package/src/AudioDevice.tsx +2 -2
  116. package/src/Call.tsx +26 -14
  117. package/src/CallInvite.tsx +31 -28
  118. package/src/PreflightTest.ts +1481 -0
  119. package/src/Voice.tsx +140 -88
  120. package/src/__mock-data__/PreflightTest.ts +272 -0
  121. package/src/common.ts +13 -5
  122. package/src/constants.ts +149 -1
  123. package/src/error/UnexpectedNativeError.ts +21 -0
  124. package/src/error/index.ts +1 -0
  125. package/src/index.tsx +8 -1
  126. package/src/type/AudioCodec.ts +45 -0
  127. package/src/type/Ice.ts +24 -0
  128. package/src/type/NativeModule.ts +80 -31
  129. package/src/type/PreflightTest.ts +40 -0
  130. package/src/utility/nativePromise.ts +40 -0
  131. package/src/utility/preflightTestOptions.ts +237 -0
  132. package/twilio-voice-react-native.podspec +1 -1
  133. package/android/src/main/java/com/twiliovoicereactnative/ExpoActivityLifecycleListener.java +0 -39
  134. package/android/src/main/java/com/twiliovoicereactnative/ExpoApplicationLifecycleListener.java +0 -14
  135. package/android/src/main/java/com/twiliovoicereactnative/ExpoPackage.java +0 -20
  136. package/expo-config-plugin/android.js +0 -191
  137. package/expo-config-plugin/ios.js +0 -22
  138. package/lib/commonjs/ExpoModule.js +0 -74
  139. package/lib/commonjs/ExpoModule.js.map +0 -1
  140. package/lib/module/ExpoModule.js +0 -63
  141. package/lib/module/ExpoModule.js.map +0 -1
  142. package/lib/typescript/ExpoModule.d.ts +0 -13
  143. package/src/ExpoModule.ts +0 -64
package/LICENSE CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
- Copyright (C) 2023-2024 Twilio, Inc.
2
+ Copyright (C) 2023-2026 Twilio, Inc.
3
3
  Licensed under the Apache License, Version 2.0 (the "License");
4
4
  you may not use this file except in compliance with the License.
5
5
 
package/README.md CHANGED
@@ -1,5 +1,4 @@
1
1
  # Twilio Voice React Native SDK
2
-
3
2
  [![NPM](https://img.shields.io/npm/v/%40twilio/voice-react-native-sdk.svg?color=blue)](https://www.npmjs.com/package/%40twilio/voice-react-native-sdk) [![CircleCI](https://dl.circleci.com/status-badge/img/gh/twilio/twilio-voice-react-native/tree/main.svg?style=shield)](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
- ## Building and Publishing New Versions
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
- This command will:
26
+ ### Expo support
51
27
 
52
- - Generate constants from source files
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
- 3. **Verify Build Output**:
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
- ### Publishing to NPM
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
- 1. **Update Version**:
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
- Then import and use it exactly like the original Twilio SDK:
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)
@@ -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.24'
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
- implementation "org.jetbrains.kotlin:kotlin-stdlib:${versions.kotlin}"
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 Promise callAcceptedPromise = null;
36
- private Promise callRejectedPromise = null;
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 Promise getCallAcceptedPromise() {
105
+ public ModuleProxy.UniversalPromise getCallAcceptedPromise() {
107
106
  return this.callAcceptedPromise;
108
107
  }
109
- public Promise getCallRejectedPromise() {
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() { return this.callRecipient; }
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 = (this.callInviteState == ACTIVE) ? USED : 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 Promise callAcceptedPromise) {
138
+ public void setCallAcceptedPromise(@NonNull ModuleProxy.UniversalPromise callAcceptedPromise) {
136
139
  this.callAcceptedPromise = callAcceptedPromise;
137
140
  }
138
- public void setCallRejectedPromise(@NonNull Promise callRejectedPromise) {
141
+ public void setCallRejectedPromise(@NonNull ModuleProxy.UniversalPromise callRejectedPromise) {
139
142
  this.callRejectedPromise = callRejectedPromise;
140
143
  }
141
144
  public void setCallException(CallException callException) {