omikit-plugin 3.2.70 → 3.2.72
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/README.md +55 -12
- package/android/build.gradle +1 -1
- package/android/gradle.properties +1 -1
- package/android/src/main/java/com/omikitplugin/OmikitPluginModule.kt +222 -141
- package/android/src/main/java/com/omikitplugin/utils/OmiKitUtils.kt +11 -0
- package/ios/CallProcess/CallManager.swift +92 -81
- package/ios/CallProcess/OmiUtils.swift +43 -12
- package/ios/Library/OmikitPlugin.swift +30 -18
- package/lib/commonjs/omikit.js +15 -6
- package/lib/commonjs/omikit.js.map +1 -1
- package/lib/module/omikit.js +15 -6
- package/lib/module/omikit.js.map +1 -1
- package/omikit-plugin.podspec +1 -1
- package/package.json +2 -2
- package/src/index.tsx +1 -1
- package/src/omikit.tsx +14 -11
- package/src/types/index.d.ts +25 -7
package/README.md
CHANGED
|
@@ -591,7 +591,7 @@ startServices();
|
|
|
591
591
|
- The `initCallWithApiKey()` function is usually used for your client, who only has a certain function, calling a fixed number. For example, you can only call your hotline number
|
|
592
592
|
|
|
593
593
|
```javascript
|
|
594
|
-
import { initCallWithApiKey } from 'omikit-plugin';
|
|
594
|
+
import { initCallWithApiKey, getCurrentUser } from 'omikit-plugin';
|
|
595
595
|
import messaging from '@react-native-firebase/messaging';
|
|
596
596
|
|
|
597
597
|
let token: String;
|
|
@@ -617,7 +617,18 @@ const loginInfo = {
|
|
|
617
617
|
// Initialize call functionality using the provided API key
|
|
618
618
|
const result = await initCallWithApiKey(loginInfo);
|
|
619
619
|
|
|
620
|
-
|
|
620
|
+
/* ❌ ❌ NOTE: Please check the user information again, if the object is not empty then you have successfully logged in.
|
|
621
|
+
Otherwise, if you have not successfully logged in, you should not navigate to the call screen. When startCall with empty information, it may crash your application or not be clear when receiving the startCall error ❌❌*/
|
|
622
|
+
|
|
623
|
+
// Example:
|
|
624
|
+
|
|
625
|
+
if (result){
|
|
626
|
+
const infoUser = await getCurrentUser()
|
|
627
|
+
if (infoUser != null && Object.keys(infoUser).length > 0) {
|
|
628
|
+
// ✅ Login OMI Success
|
|
629
|
+
// Can navigate to call screen or start call 🚀 🚀
|
|
630
|
+
}
|
|
631
|
+
}
|
|
621
632
|
```
|
|
622
633
|
|
|
623
634
|
📌 **initCallWithUserPassword()**
|
|
@@ -628,7 +639,7 @@ const result = await initCallWithApiKey(loginInfo);
|
|
|
628
639
|
- The `initCallWithUserPassword()` function is for employees. They can call any telecommunications number allowed in your business on the OMI system.
|
|
629
640
|
|
|
630
641
|
```javascript
|
|
631
|
-
import { initCallWithUserPassword } from 'omikit-plugin';
|
|
642
|
+
import { initCallWithUserPassword, getCurrentUser } from 'omikit-plugin';
|
|
632
643
|
import messaging from '@react-native-firebase/messaging';
|
|
633
644
|
|
|
634
645
|
let token: String;
|
|
@@ -652,7 +663,20 @@ const loginInfo = {
|
|
|
652
663
|
|
|
653
664
|
// Initialize call functionality using username and password authentication
|
|
654
665
|
const result = await initCallWithUserPassword(loginInfo);
|
|
655
|
-
|
|
666
|
+
|
|
667
|
+
|
|
668
|
+
/* ❌ ❌ NOTE: Please check the user information again, if the object is not empty then you have successfully logged in.
|
|
669
|
+
Otherwise, if you have not successfully logged in, you should not navigate to the call screen. When startCall with empty information, it may crash your application or not be clear when receiving the startCall error ❌❌*/
|
|
670
|
+
|
|
671
|
+
// Example:
|
|
672
|
+
|
|
673
|
+
if (result){
|
|
674
|
+
const infoUser = await getCurrentUser()
|
|
675
|
+
if (infoUser != null && Object.keys(infoUser).length > 0) {
|
|
676
|
+
// ✅ Login OMI Success
|
|
677
|
+
// Can navigate to call screen or start call 🚀 🚀
|
|
678
|
+
}
|
|
679
|
+
}
|
|
656
680
|
```
|
|
657
681
|
|
|
658
682
|
📌 **configPushNotification()**
|
|
@@ -909,7 +933,9 @@ const result = await startCallWithUuid({
|
|
|
909
933
|
{
|
|
910
934
|
"extension": "111",
|
|
911
935
|
"full_name": "chau1",
|
|
936
|
+
"fullName": "chau1",
|
|
912
937
|
"avatar_url": "",
|
|
938
|
+
"avatarUrl": "",
|
|
913
939
|
"uuid": "122aaa"
|
|
914
940
|
}
|
|
915
941
|
```
|
|
@@ -1060,6 +1086,20 @@ const result = await startCallWithUuid({
|
|
|
1060
1086
|
### 🚀🚀 Events listener 🚀🚀
|
|
1061
1087
|
|
|
1062
1088
|
```javascript
|
|
1089
|
+
import { omiEmitter } from 'omikit-plugin';
|
|
1090
|
+
|
|
1091
|
+
/*
|
|
1092
|
+
❌ ❌ With TypeScript, in android, it seems our omiEmitter is not working properly. Please use the following manual declaration, to ensure performance
|
|
1093
|
+
*/
|
|
1094
|
+
|
|
1095
|
+
// 📌 For TypeScript, Android
|
|
1096
|
+
import { NativeEventEmitter, NativeModules } from "react-native";
|
|
1097
|
+
const { OmikitPlugin } = NativeModules;
|
|
1098
|
+
const omiEmitter = new NativeEventEmitter(OmikitPlugin);
|
|
1099
|
+
|
|
1100
|
+
|
|
1101
|
+
|
|
1102
|
+
|
|
1063
1103
|
useEffect(() => {
|
|
1064
1104
|
omiEmitter.addListener(OmiCallEvent.onCallStateChanged, onCallStateChanged);
|
|
1065
1105
|
omiEmitter.addListener(OmiCallEvent.onMuted, onMuted);
|
|
@@ -1129,24 +1169,27 @@ useEffect(() => {
|
|
|
1129
1169
|
```javascript
|
|
1130
1170
|
// The event is updated every time the call status changes
|
|
1131
1171
|
const onCallStateChanged = (data: any) => {
|
|
1172
|
+
// ⚠️ ⚠️ Currently, we support two data formats: camelCase and snake_case. Snake_case is used for data v1, while camelCase is for v2. We encourage customers to use camelCase instead of snake_case, as we plan to completely remove the snake_case format in the future ❌ ❌
|
|
1173
|
+
|
|
1132
1174
|
/*
|
|
1133
1175
|
Call state change event data (Object) includes:
|
|
1134
1176
|
|
|
1135
1177
|
- _id: string (UUID of the call)
|
|
1136
1178
|
- callInfo: object (Detailed call information)
|
|
1137
1179
|
- callerNumber: string (Phone number of the caller)
|
|
1138
|
-
- code_end_call: number (Status code when the call ends)
|
|
1139
|
-
- destination_number?: string (Destination phone number, optional)
|
|
1180
|
+
- code_end_call, codeEndCall: number (Status code when the call ends)
|
|
1181
|
+
- destination_number, destinationNumber?: string (Destination phone number, optional)
|
|
1140
1182
|
- direction: string ("inbound" or "outbound", call direction)
|
|
1141
1183
|
- disposition: string (Call answer status)
|
|
1142
1184
|
- incoming: boolean (true if it is an incoming call)
|
|
1143
1185
|
- isVideo: boolean (true if it is a video call)
|
|
1144
|
-
- sip_user: string (Current SIP user)
|
|
1145
|
-
- source_number: string (SIP number of the user)
|
|
1186
|
+
- sip_user, sipUser: string (Current SIP user)
|
|
1187
|
+
- source_number, sourceNumber: string (SIP number of the user)
|
|
1146
1188
|
- status: string (value matching with List status call)
|
|
1147
|
-
- time_end: number (Timestamp when the call ended)
|
|
1148
|
-
- time_start_to_answer: number (Time taken to answer the call)
|
|
1149
|
-
- transaction_id: string (OMI Call unique ID)
|
|
1189
|
+
- time_end, timeEnd: number (Timestamp when the call ended)
|
|
1190
|
+
- time_start_to_answer, timeStartToAnswer: number (Time taken to answer the call)
|
|
1191
|
+
- transaction_id, transactionId: string (OMI Call unique ID)
|
|
1192
|
+
- typeNumber: string ("", "internal", "phone", "zalo")
|
|
1150
1193
|
*/
|
|
1151
1194
|
};
|
|
1152
1195
|
|
|
@@ -1180,7 +1223,7 @@ const onSwitchboardAnswer = (data: any) => {
|
|
|
1180
1223
|
}
|
|
1181
1224
|
```
|
|
1182
1225
|
|
|
1183
|
-
✨ Table describing `code_end_call` status
|
|
1226
|
+
✨ Table describing `code_end_call, codeEndCall` status
|
|
1184
1227
|
|
|
1185
1228
|
| Code | Description |
|
|
1186
1229
|
| --------------- | --------------------------------------------------------------------------------------------------------------------- |
|
package/android/build.gradle
CHANGED
|
@@ -120,7 +120,7 @@ dependencies {
|
|
|
120
120
|
// use for OMISDK
|
|
121
121
|
implementation("androidx.work:work-runtime:2.8.1")
|
|
122
122
|
implementation "androidx.security:security-crypto:1.1.0-alpha06"
|
|
123
|
-
api 'vn.vihat.omicall:omi-sdk:2.3.
|
|
123
|
+
api 'vn.vihat.omicall:omi-sdk:2.3.22'
|
|
124
124
|
|
|
125
125
|
implementation "com.facebook.react:react-native:+" // From node_modules
|
|
126
126
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
@@ -24,6 +24,7 @@ import kotlinx.coroutines.CoroutineScope
|
|
|
24
24
|
import kotlinx.coroutines.Dispatchers
|
|
25
25
|
import kotlinx.coroutines.launch
|
|
26
26
|
import kotlinx.coroutines.withContext
|
|
27
|
+
import kotlinx.coroutines.delay
|
|
27
28
|
import vn.vihat.omicall.omisdk.OmiAccountListener
|
|
28
29
|
import vn.vihat.omicall.omisdk.OmiClient
|
|
29
30
|
import vn.vihat.omicall.omisdk.OmiListener
|
|
@@ -38,76 +39,105 @@ import vn.vihat.omicall.omisdk.utils.Utils
|
|
|
38
39
|
class OmikitPluginModule(reactContext: ReactApplicationContext?) :
|
|
39
40
|
ReactContextBaseJavaModule(reactContext), ActivityEventListener, OmiListener {
|
|
40
41
|
private val mainScope = CoroutineScope(Dispatchers.Main)
|
|
41
|
-
private var
|
|
42
|
+
private var isIncoming: Boolean = false
|
|
42
43
|
private var isAnserCall: Boolean = false
|
|
43
44
|
|
|
44
45
|
override fun getName(): String {
|
|
45
46
|
return NAME
|
|
46
47
|
}
|
|
47
48
|
|
|
49
|
+
|
|
50
|
+
private val handler = Handler(Looper.getMainLooper())
|
|
51
|
+
|
|
48
52
|
override fun incomingReceived(callerId: Int?, phoneNumber: String?, isVideo: Boolean?) {
|
|
49
|
-
|
|
53
|
+
isIncoming = true;
|
|
50
54
|
Log.d("OMISDK", "=>> START INCOMING CALL REVICED => ")
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
map.
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
|
|
56
|
+
val typeNumber = OmiKitUtils().checkTypeNumber(phoneNumber ?: "")
|
|
57
|
+
|
|
58
|
+
val map: WritableMap = WritableNativeMap().apply {
|
|
59
|
+
putBoolean("isVideo", isVideo ?: true)
|
|
60
|
+
putBoolean("incoming", isIncoming)
|
|
61
|
+
putString("callerNumber", phoneNumber ?: "")
|
|
62
|
+
putString("_id", "")
|
|
63
|
+
putInt("status", CallState.incoming.value)
|
|
64
|
+
putString("typeNumber", typeNumber)
|
|
65
|
+
}
|
|
66
|
+
|
|
57
67
|
sendEvent(CALL_STATE_CHANGED, map)
|
|
58
68
|
}
|
|
59
69
|
|
|
60
70
|
override fun onCallEstablished(
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
71
|
+
callerId: Int,
|
|
72
|
+
phoneNumber: String?,
|
|
73
|
+
isVideo: Boolean?,
|
|
74
|
+
startTime: Long,
|
|
75
|
+
transactionId: String?,
|
|
66
76
|
) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
isAnserCall = true
|
|
78
|
+
Log.d("OMISDK", "=>> ON CALL ESTABLISHED => ")
|
|
79
|
+
|
|
80
|
+
Handler(Looper.getMainLooper()).postDelayed({
|
|
81
|
+
Log.d("OmikitReactNative", "onCallEstablished")
|
|
82
|
+
|
|
83
|
+
val typeNumber = OmiKitUtils().checkTypeNumber(phoneNumber ?: "")
|
|
84
|
+
|
|
85
|
+
val map: WritableMap = WritableNativeMap().apply {
|
|
86
|
+
putString("callerNumber", phoneNumber ?: "")
|
|
87
|
+
putBoolean("isVideo", isVideo ?: true)
|
|
88
|
+
putBoolean("incoming", isIncoming) // 🔹 Kiểm tra lỗi chính tả biến này
|
|
89
|
+
putString("transactionId", transactionId ?: "")
|
|
90
|
+
putInt("status", CallState.confirmed.value)
|
|
91
|
+
putString("typeNumber", typeNumber)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
sendEvent(CALL_STATE_CHANGED, map)
|
|
95
|
+
}, 200)
|
|
79
96
|
}
|
|
80
97
|
|
|
81
98
|
override fun onCallEnd(callInfo: MutableMap<String, Any?>, statusCode: Int) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
+
Log.d("OMISDK RN", "=>> onCallEnd 0000 => $callInfo")
|
|
100
|
+
|
|
101
|
+
// Kiểm tra kiểu dữ liệu trước khi ép kiểu để tránh lỗi
|
|
102
|
+
val call = callInfo ?: mutableMapOf()
|
|
103
|
+
|
|
104
|
+
val timeStartToAnswer = (call["time_start_to_answer"] as? Long) ?: 0L
|
|
105
|
+
val timeEnd = (call["time_end"] as? Long) ?: 0L
|
|
106
|
+
val phoneNumber = (call["destination_number"] as? String) ?: (call["source_number"] as? String) ?: ""
|
|
107
|
+
val typeNumber = OmiKitUtils().checkTypeNumber(phoneNumber)
|
|
108
|
+
|
|
109
|
+
val map: WritableMap = WritableNativeMap().apply {
|
|
110
|
+
putString("direction", call["direction"] as? String ?: "")
|
|
111
|
+
putString("transactionId", call["transaction_id"] as? String ?: "")
|
|
112
|
+
putString("sourceNumber", call["source_number"] as? String ?: "")
|
|
113
|
+
putString("destinationNumber", call["destination_number"] as? String ?: "")
|
|
114
|
+
putDouble("timeStartToAnswer", timeStartToAnswer.toDouble())
|
|
115
|
+
putDouble("timeEnd", timeEnd.toDouble())
|
|
116
|
+
putString("sipUser", call["sip_user"] as? String ?: "")
|
|
117
|
+
putInt("codeEndCall", statusCode)
|
|
118
|
+
putString("disposition", call["disposition"] as? String ?: "")
|
|
119
|
+
putInt("status", CallState.disconnected.value)
|
|
120
|
+
putString("typeNumber", typeNumber)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
Log.d("OMISDK RN", "=>> onCallEnd => $map")
|
|
124
|
+
sendEvent(CALL_STATE_CHANGED, map)
|
|
99
125
|
}
|
|
100
126
|
|
|
101
127
|
override fun onConnecting() {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
128
|
+
Log.d("OMISDK", "=>> ON CONNECTING CALL => ")
|
|
129
|
+
|
|
130
|
+
val map: WritableMap = WritableNativeMap().apply {
|
|
131
|
+
putString("callerNumber", "")
|
|
132
|
+
putBoolean("isVideo", NotificationService.isVideo)
|
|
133
|
+
putBoolean("incoming", isIncoming ?: false)
|
|
134
|
+
putString("transactionId", "")
|
|
135
|
+
putString("_id", "")
|
|
136
|
+
putInt("status", CallState.connecting.value)
|
|
137
|
+
putString("typeNumber", "")
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
sendEvent(CALL_STATE_CHANGED, map)
|
|
111
141
|
}
|
|
112
142
|
|
|
113
143
|
override fun onDescriptionError() {
|
|
@@ -117,25 +147,21 @@ class OmikitPluginModule(reactContext: ReactApplicationContext?) :
|
|
|
117
147
|
}
|
|
118
148
|
|
|
119
149
|
override fun onRinging(callerId: Int, transactionId: String?) {
|
|
120
|
-
|
|
121
|
-
|
|
150
|
+
val callDirection = OmiClient.callDirection
|
|
151
|
+
val prePhoneNumber = OmiClient.prePhoneNumber ?: ""
|
|
152
|
+
val typeNumber = OmiKitUtils().checkTypeNumber(prePhoneNumber)
|
|
153
|
+
|
|
154
|
+
val map: WritableMap = WritableNativeMap().apply {
|
|
155
|
+
putString("callerNumber", if (callDirection == "inbound") prePhoneNumber else "")
|
|
156
|
+
putBoolean("isVideo", NotificationService.isVideo)
|
|
157
|
+
putString("transactionId", transactionId ?: "")
|
|
158
|
+
putInt("status", if (callDirection == "inbound") CallState.incoming.value else CallState.early.value)
|
|
159
|
+
putBoolean("incoming", callDirection == "inbound")
|
|
160
|
+
putString("typeNumber", typeNumber)
|
|
161
|
+
}
|
|
122
162
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
map.putString("callerNumber", OmiClient.prePhoneNumber)
|
|
126
|
-
map.putBoolean("isVideo", NotificationService.isVideo)
|
|
127
|
-
map.putBoolean("incoming", true)
|
|
128
|
-
map.putString("transactionId", transactionId ?: "")
|
|
129
|
-
map.putInt("status", CallState.incoming.value)
|
|
130
|
-
} else {
|
|
131
|
-
map.putString("callerNumber", "")
|
|
132
|
-
map.putBoolean("isVideo", NotificationService.isVideo)
|
|
133
|
-
map.putString("transactionId", transactionId ?: "")
|
|
134
|
-
map.putInt("status", CallState.early.value)
|
|
135
|
-
map.putBoolean("incoming", false)
|
|
136
|
-
Log.d("OMISDK", "=>> ON RINGING CALL => ")
|
|
137
|
-
}
|
|
138
|
-
sendEvent(CALL_STATE_CHANGED, map)
|
|
163
|
+
Log.d("OMISDK", if (callDirection == "inbound") "=>> ON INCOMING CALL => " else "=>> ON RINGING CALL => ")
|
|
164
|
+
sendEvent(CALL_STATE_CHANGED, map)
|
|
139
165
|
}
|
|
140
166
|
|
|
141
167
|
|
|
@@ -166,15 +192,21 @@ class OmikitPluginModule(reactContext: ReactApplicationContext?) :
|
|
|
166
192
|
}
|
|
167
193
|
|
|
168
194
|
override fun onOutgoingStarted(callerId: Int, phoneNumber: String?, isVideo: Boolean?) {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
195
|
+
Log.d("OMISDK", "=>> ON OUTGOING STARTED CALL => ")
|
|
196
|
+
|
|
197
|
+
val typeNumber = OmiKitUtils().checkTypeNumber(phoneNumber ?: "")
|
|
198
|
+
|
|
199
|
+
val map: WritableMap = WritableNativeMap().apply {
|
|
200
|
+
putString("callerNumber", phoneNumber ?: "")
|
|
201
|
+
putBoolean("isVideo", NotificationService.isVideo)
|
|
202
|
+
putString("transactionId", "")
|
|
203
|
+
putInt("status", CallState.calling.value)
|
|
204
|
+
putString("_id", "")
|
|
205
|
+
putBoolean("incoming", isIncoming) // 🔹 Kiểm tra lỗi chính tả của biến này
|
|
206
|
+
putString("typeNumber", typeNumber)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
sendEvent(CALL_STATE_CHANGED, map)
|
|
178
210
|
}
|
|
179
211
|
|
|
180
212
|
override fun onSwitchBoardAnswer(sip: String) {
|
|
@@ -187,13 +219,18 @@ class OmikitPluginModule(reactContext: ReactApplicationContext?) :
|
|
|
187
219
|
Log.d("OMISDK", "=> ON REGISTER COMPLETED => status code: $statusCode")
|
|
188
220
|
|
|
189
221
|
if (statusCode != 200) {
|
|
222
|
+
val normalizedStatusCode = if (statusCode == 403) 853 else statusCode
|
|
223
|
+
val typeNumber = ""
|
|
224
|
+
|
|
190
225
|
val mapObject = WritableNativeMap().apply {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
226
|
+
putBoolean("isVideo", false)
|
|
227
|
+
putBoolean("incoming", true)
|
|
228
|
+
putString("callerNumber", "")
|
|
229
|
+
putString("_id", "")
|
|
230
|
+
putInt("status", 6)
|
|
231
|
+
putInt("code_end_call", normalizedStatusCode)
|
|
232
|
+
putInt("codeEndCall", normalizedStatusCode)
|
|
233
|
+
putString("typeNumber", typeNumber)
|
|
197
234
|
}
|
|
198
235
|
sendEvent(CALL_STATE_CHANGED, mapObject)
|
|
199
236
|
}
|
|
@@ -395,51 +432,68 @@ class OmikitPluginModule(reactContext: ReactApplicationContext?) :
|
|
|
395
432
|
}
|
|
396
433
|
|
|
397
434
|
@ReactMethod
|
|
398
|
-
fun getInitialCall(counter: Int =
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
435
|
+
fun getInitialCall(counter: Int = 1, promise: Promise) {
|
|
436
|
+
val context = reactApplicationContext ?: run {
|
|
437
|
+
Log.e("getInitialCall", "❌ React context is null")
|
|
438
|
+
promise.resolve(false)
|
|
439
|
+
return
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
val call = Utils.getActiveCall(context)
|
|
443
|
+
Log.d("getInitialCall RN", "📞 Active call: $call")
|
|
444
|
+
|
|
445
|
+
if (call == null) {
|
|
404
446
|
if (counter <= 0) {
|
|
405
|
-
|
|
447
|
+
promise.resolve(false)
|
|
406
448
|
} else {
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
}
|
|
412
|
-
} else {
|
|
413
|
-
val phoneNumberTemp: String = call.remoteNumber as String
|
|
414
|
-
if (phoneNumberTemp.isNotEmpty()) {
|
|
415
|
-
val map: WritableMap = WritableNativeMap()
|
|
416
|
-
map.putString("callerNumber", phoneNumberTemp)
|
|
417
|
-
val statusPendingCall = OmiKitUtils().getStatusPendingCall(reactApplicationContext)
|
|
418
|
-
if (call.state == 3) {
|
|
419
|
-
if (statusPendingCall != 0) {
|
|
420
|
-
call.state = statusPendingCall
|
|
449
|
+
mainScope.launch {
|
|
450
|
+
Log.d("getInitialCall RN", "🔄 Retrying in 2s... (Attempts left: $counter)")
|
|
451
|
+
delay(1000) // Chờ 2 giây
|
|
452
|
+
getInitialCall(counter - 1, promise) // Gọi lại hàm đệ quy
|
|
421
453
|
}
|
|
422
|
-
}
|
|
423
|
-
map.putBoolean("incoming", call.direction == "inbound")
|
|
424
|
-
map.putInt("_id", call.id)
|
|
425
|
-
map.putInt("status", call.state)
|
|
426
|
-
map.putBoolean("muted", false)
|
|
427
|
-
map.putBoolean("isVideo", call.isVideo ?: false)
|
|
428
|
-
promise.resolve(map)
|
|
429
|
-
if (statusPendingCall == 2 && call.state != 5) {
|
|
430
|
-
Log.d("getInitialCall RN", "incomingReceive $statusPendingCall")
|
|
431
|
-
val map2: WritableMap = WritableNativeMap()
|
|
432
|
-
map2.putBoolean("isVideo", call.isVideo ?: false)
|
|
433
|
-
map2.putBoolean("incoming", true)
|
|
434
|
-
map2.putString("callerNumber", phoneNumberTemp)
|
|
435
|
-
map2.putString("_id", "")
|
|
436
|
-
map2.putInt("status", 2)
|
|
437
|
-
sendEvent(CALL_STATE_CHANGED, map2)
|
|
438
|
-
}
|
|
439
454
|
}
|
|
440
|
-
|
|
455
|
+
return
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
val phoneNumber = call.remoteNumber as? String ?: ""
|
|
459
|
+
if (phoneNumber.isEmpty()) {
|
|
460
|
+
promise.resolve(false)
|
|
461
|
+
return
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
val typeNumber = OmiKitUtils().checkTypeNumber(phoneNumber ?: "")
|
|
465
|
+
|
|
466
|
+
val map: WritableMap = WritableNativeMap().apply {
|
|
467
|
+
putString("callerNumber", phoneNumber)
|
|
468
|
+
putBoolean("incoming", call.direction == "inbound")
|
|
469
|
+
putInt("_id", call.id)
|
|
470
|
+
putInt("status", call.state)
|
|
471
|
+
putBoolean("muted", false)
|
|
472
|
+
putBoolean("isVideo", call.isVideo ?: false)
|
|
473
|
+
putString("typeNumber", typeNumber)
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
val statusPendingCall = OmiKitUtils().getStatusPendingCall(context)
|
|
477
|
+
if (call.state == 3 && statusPendingCall != 0) {
|
|
478
|
+
call.state = statusPendingCall
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
promise.resolve(map)
|
|
482
|
+
|
|
483
|
+
if (statusPendingCall == 2 && call.state != 5) {
|
|
484
|
+
Log.d("getInitialCall RN", "🚀 Incoming Receive Triggered ($statusPendingCall)")
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
val eventMap: WritableMap = WritableNativeMap().apply {
|
|
488
|
+
putBoolean("isVideo", call.isVideo ?: false)
|
|
489
|
+
putBoolean("incoming", true)
|
|
490
|
+
putString("callerNumber", phoneNumber)
|
|
491
|
+
putString("_id", "")
|
|
492
|
+
putInt("status", 2)
|
|
493
|
+
putString("typeNumber", typeNumber)
|
|
494
|
+
}
|
|
495
|
+
sendEvent(CALL_STATE_CHANGED, eventMap)
|
|
441
496
|
}
|
|
442
|
-
}
|
|
443
497
|
}
|
|
444
498
|
|
|
445
499
|
|
|
@@ -505,17 +559,32 @@ class OmikitPluginModule(reactContext: ReactApplicationContext?) :
|
|
|
505
559
|
|
|
506
560
|
@ReactMethod
|
|
507
561
|
fun joinCall(promise: Promise) {
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
562
|
+
val appContext = reactApplicationContext.applicationContext
|
|
563
|
+
val activity = currentActivity
|
|
564
|
+
|
|
565
|
+
if (appContext == null) {
|
|
566
|
+
promise.reject("E_NULL_CONTEXT", "Application context is null")
|
|
567
|
+
return
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
if (activity == null) {
|
|
571
|
+
promise.reject("E_NULL_ACTIVITY", "Current activity is null")
|
|
572
|
+
return
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
activity.runOnUiThread {
|
|
576
|
+
try {
|
|
577
|
+
OmiClient.getInstance(appContext).pickUp()
|
|
578
|
+
promise.resolve(true)
|
|
579
|
+
} catch (e: Exception) {
|
|
580
|
+
promise.reject("E_JOIN_CALL_FAILED", "Failed to join call", e)
|
|
581
|
+
}
|
|
512
582
|
}
|
|
513
|
-
}
|
|
514
583
|
}
|
|
515
584
|
|
|
516
585
|
@ReactMethod
|
|
517
586
|
fun endCall(promise: Promise) {
|
|
518
|
-
if (
|
|
587
|
+
if (isIncoming && !isAnserCall) {
|
|
519
588
|
OmiClient.getInstance(reactApplicationContext!!).decline()
|
|
520
589
|
} else {
|
|
521
590
|
OmiClient.getInstance(reactApplicationContext!!).hangUp()
|
|
@@ -526,7 +595,7 @@ class OmikitPluginModule(reactContext: ReactApplicationContext?) :
|
|
|
526
595
|
|
|
527
596
|
@ReactMethod
|
|
528
597
|
fun rejectCall(promise: Promise) {
|
|
529
|
-
if (
|
|
598
|
+
if (isIncoming && !isAnserCall) {
|
|
530
599
|
OmiClient.getInstance(reactApplicationContext!!).decline()
|
|
531
600
|
}
|
|
532
601
|
promise.resolve(true)
|
|
@@ -646,6 +715,10 @@ class OmikitPluginModule(reactContext: ReactApplicationContext?) :
|
|
|
646
715
|
map.putString("uuid", call["uuid"] as String?)
|
|
647
716
|
map.putString("full_name", call["full_name"] as String?)
|
|
648
717
|
map.putString("avatar_url", call["avatar_url"] as String?)
|
|
718
|
+
|
|
719
|
+
map.putString("fullName", call["full_name"] as String?)
|
|
720
|
+
map.putString("avatarUrl", call["avatar_url"] as String?)
|
|
721
|
+
|
|
649
722
|
promise.resolve(map)
|
|
650
723
|
} else {
|
|
651
724
|
promise.resolve(null);
|
|
@@ -671,6 +744,10 @@ class OmikitPluginModule(reactContext: ReactApplicationContext?) :
|
|
|
671
744
|
map.putString("uuid", call["uuid"] as String?)
|
|
672
745
|
map.putString("full_name", call["full_name"] as String?)
|
|
673
746
|
map.putString("avatar_url", call["avatar_url"] as String?)
|
|
747
|
+
|
|
748
|
+
map.putString("fullName", call["full_name"] as String?)
|
|
749
|
+
map.putString("avatarUrl", call["avatar_url"] as String?)
|
|
750
|
+
|
|
674
751
|
promise.resolve(map)
|
|
675
752
|
} else {
|
|
676
753
|
promise.resolve(null);
|
|
@@ -695,6 +772,9 @@ class OmikitPluginModule(reactContext: ReactApplicationContext?) :
|
|
|
695
772
|
map.putString("uuid", call["uuid"] as String?)
|
|
696
773
|
map.putString("full_name", call["full_name"] as String?)
|
|
697
774
|
map.putString("avatar_url", call["avatar_url"] as String?)
|
|
775
|
+
|
|
776
|
+
map.putString("fullName", call["full_name"] as String?)
|
|
777
|
+
map.putString("avatarUrl", call["avatar_url"] as String?)
|
|
698
778
|
promise.resolve(map)
|
|
699
779
|
} else {
|
|
700
780
|
promise.resolve(null)
|
|
@@ -806,18 +886,19 @@ class OmikitPluginModule(reactContext: ReactApplicationContext?) :
|
|
|
806
886
|
}
|
|
807
887
|
}
|
|
808
888
|
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
889
|
+
fun sendEvent(eventName: String?, params: Any?) {
|
|
890
|
+
if (eventName == null) {
|
|
891
|
+
Log.e("OmikitPlugin", "❌ eventName is null or empty. Không thể gửi event.")
|
|
892
|
+
return
|
|
893
|
+
}
|
|
894
|
+
if (currentActivity != null) {
|
|
895
|
+
currentActivity!!.runOnUiThread {
|
|
896
|
+
reactApplicationContext.getJSModule(RCTNativeAppEventEmitter::class.java)
|
|
897
|
+
.emit(eventName, params)
|
|
898
|
+
Log.d("OmikitPlugin", "✅ Event $eventName đã được gửi thành công!")
|
|
899
|
+
}
|
|
818
900
|
}
|
|
819
901
|
}
|
|
820
|
-
}
|
|
821
902
|
|
|
822
903
|
private fun requestPermission(isVideo: Boolean) {
|
|
823
904
|
var permissions = arrayOf(
|
|
@@ -38,4 +38,15 @@ class OmiKitUtils {
|
|
|
38
38
|
clearStatusPendingCall(context)
|
|
39
39
|
return status
|
|
40
40
|
}
|
|
41
|
+
|
|
42
|
+
fun checkTypeNumber(phoneNumber: String?): String {
|
|
43
|
+
if (phoneNumber.isNullOrBlank()) return "" //
|
|
44
|
+
|
|
45
|
+
return when {
|
|
46
|
+
phoneNumber.length < 8 -> "internal"
|
|
47
|
+
phoneNumber.any { it.isLetter() } && phoneNumber.any { it.isDigit() } -> "zalo"
|
|
48
|
+
else -> "phone"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
41
52
|
}
|