omikit-plugin 3.3.28 → 4.0.1
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 +949 -1223
- package/android/build.gradle +1 -1
- package/android/src/main/java/com/omikitplugin/FLLocalCameraModule.kt +1 -1
- package/android/src/main/java/com/omikitplugin/FLRemoteCameraModule.kt +1 -1
- package/android/src/main/java/com/omikitplugin/OmikitPluginModule.kt +277 -325
- package/android/src/main/java/com/omikitplugin/constants/constant.kt +2 -1
- package/ios/CallProcess/CallManager.swift +45 -35
- package/ios/Constant/Constant.swift +1 -0
- package/ios/Library/OmikitPlugin.m +75 -1
- package/ios/Library/OmikitPlugin.swift +199 -16
- package/ios/OmikitPlugin-Protocol.h +161 -0
- package/lib/commonjs/NativeOmikitPlugin.js +9 -0
- package/lib/commonjs/NativeOmikitPlugin.js.map +1 -0
- package/lib/commonjs/index.js +11 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/omi_audio_type.js +20 -0
- package/lib/commonjs/omi_audio_type.js.map +1 -0
- package/lib/commonjs/omi_local_camera.js +12 -2
- package/lib/commonjs/omi_local_camera.js.map +1 -1
- package/lib/commonjs/omi_remote_camera.js +12 -2
- package/lib/commonjs/omi_remote_camera.js.map +1 -1
- package/lib/commonjs/omi_start_call_status.js +30 -0
- package/lib/commonjs/omi_start_call_status.js.map +1 -1
- package/lib/commonjs/omikit.js +110 -16
- package/lib/commonjs/omikit.js.map +1 -1
- package/lib/module/NativeOmikitPlugin.js +3 -0
- package/lib/module/NativeOmikitPlugin.js.map +1 -0
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/omi_audio_type.js +14 -0
- package/lib/module/omi_audio_type.js.map +1 -0
- package/lib/module/omi_local_camera.js +13 -2
- package/lib/module/omi_local_camera.js.map +1 -1
- package/lib/module/omi_remote_camera.js +13 -2
- package/lib/module/omi_remote_camera.js.map +1 -1
- package/lib/module/omi_start_call_status.js +30 -0
- package/lib/module/omi_start_call_status.js.map +1 -1
- package/lib/module/omikit.js +104 -17
- package/lib/module/omikit.js.map +1 -1
- package/omikit-plugin.podspec +26 -24
- package/package.json +11 -2
- package/src/NativeOmikitPlugin.ts +160 -0
- package/src/index.tsx +2 -1
- package/src/omi_audio_type.tsx +9 -0
- package/src/omi_local_camera.tsx +12 -3
- package/src/omi_remote_camera.tsx +12 -3
- package/src/omi_start_call_status.tsx +29 -10
- package/src/omikit.tsx +96 -19
- package/src/types/index.d.ts +111 -11
|
@@ -30,11 +30,12 @@ const val CALL_STATE_CHANGED = "CALL_STATE_CHANGED"
|
|
|
30
30
|
const val VIDEO = "VIDEO"
|
|
31
31
|
const val SPEAKER = "SPEAKER"
|
|
32
32
|
const val MUTED = "MUTED"
|
|
33
|
+
const val HOLD = "HOLD"
|
|
34
|
+
const val REMOTE_VIDEO_READY = "REMOTE_VIDEO_READY"
|
|
33
35
|
const val CLICK_MISSED_CALL = "CLICK_MISSED_CALL"
|
|
34
36
|
const val SWITCHBOARD_ANSWER = "SWITCHBOARD_ANSWER"
|
|
35
37
|
const val CALL_QUALITY = "CALL_QUALITY"
|
|
36
38
|
const val AUDIO_CHANGE = "AUDIO_CHANGE"
|
|
37
|
-
const val HOLD = "HOLD"
|
|
38
39
|
const val REQUEST_PERMISSION = "REQUEST_PERMISSION"
|
|
39
40
|
|
|
40
41
|
//PREFFERENCES
|
|
@@ -13,9 +13,12 @@ import OmiKit
|
|
|
13
13
|
import AVFoundation
|
|
14
14
|
|
|
15
15
|
class CallManager {
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
static private var instance: CallManager? = nil // Instance
|
|
18
|
-
|
|
18
|
+
// Use lazy initialization to avoid crash during New Architecture module loading
|
|
19
|
+
private lazy var omiLib: OMISIPLib = {
|
|
20
|
+
return OMISIPLib.sharedInstance()
|
|
21
|
+
}()
|
|
19
22
|
var videoManager: OMIVideoViewManager?
|
|
20
23
|
var isSpeaker = false
|
|
21
24
|
private var guestPhone : String = ""
|
|
@@ -149,40 +152,36 @@ class CallManager {
|
|
|
149
152
|
|
|
150
153
|
|
|
151
154
|
func initWithUserPasswordEndpoint(params: [String: Any]) -> Bool {
|
|
152
|
-
//
|
|
155
|
+
// Validate required parameters
|
|
153
156
|
guard let userName = params["userName"] as? String,
|
|
154
157
|
let password = params["password"] as? String,
|
|
155
158
|
let realm = params["realm"] as? String,
|
|
156
159
|
let token = params["fcmToken"] as? String else {
|
|
157
|
-
print("🚨
|
|
160
|
+
print("🚨 Missing login credentials!")
|
|
158
161
|
return false
|
|
159
162
|
}
|
|
160
163
|
|
|
164
|
+
// Use host as SIP proxy (matching Android behavior)
|
|
165
|
+
let host = (params["host"] as? String) ?? ""
|
|
166
|
+
let proxy = host.isEmpty ? "" : host
|
|
161
167
|
|
|
162
|
-
//
|
|
168
|
+
// Set FCM project ID if provided
|
|
163
169
|
if let projectID = params["projectId"] as? String, !projectID.isEmpty {
|
|
164
170
|
OmiClient.setFcmProjectId(projectID)
|
|
165
171
|
}
|
|
166
172
|
|
|
167
|
-
//
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
} catch {
|
|
171
|
-
print("🚨 Lỗi khởi tạo OmiClient: \(error.localizedDescription)")
|
|
172
|
-
return false
|
|
173
|
-
}
|
|
173
|
+
// Initialize OmiClient with username & password
|
|
174
|
+
let isSkipDevices = (params["isSkipDevices"] as? Bool) ?? false
|
|
175
|
+
OmiClient.initWithUsername(userName, password: password, realm: realm, proxy: proxy, isSkipDevices: isSkipDevices)
|
|
174
176
|
|
|
175
|
-
//
|
|
177
|
+
// Set FCM token for push notifications
|
|
176
178
|
OmiClient.setUserPushNotificationToken(token)
|
|
177
179
|
|
|
178
|
-
//
|
|
180
|
+
// Request permissions on main thread
|
|
179
181
|
let isVideo = (params["isVideo"] as? Bool) ?? false
|
|
180
182
|
if isVideo {
|
|
181
183
|
DispatchQueue.main.async { [weak self] in
|
|
182
|
-
guard let strongSelf = self else {
|
|
183
|
-
print("⚠️ Không thể gọi requestPermission vì self đã bị giải phóng!")
|
|
184
|
-
return
|
|
185
|
-
}
|
|
184
|
+
guard let strongSelf = self else { return }
|
|
186
185
|
strongSelf.requestPermission(isVideo: isVideo)
|
|
187
186
|
}
|
|
188
187
|
}
|
|
@@ -249,25 +248,25 @@ class CallManager {
|
|
|
249
248
|
|
|
250
249
|
func registerNotificationCenter(showMissedCall: Bool) {
|
|
251
250
|
DispatchQueue.main.async { [weak self] in
|
|
252
|
-
guard let self = self else { return }
|
|
253
|
-
NotificationCenter.default.removeObserver(
|
|
254
|
-
NotificationCenter.default.addObserver(
|
|
251
|
+
guard let self = self, let instance = CallManager.instance else { return }
|
|
252
|
+
NotificationCenter.default.removeObserver(instance)
|
|
253
|
+
NotificationCenter.default.addObserver(instance,
|
|
255
254
|
selector: #selector(self.callStateChanged(_:)),
|
|
256
255
|
name: NSNotification.Name.OMICallStateChanged,
|
|
257
256
|
object: nil
|
|
258
257
|
)
|
|
259
|
-
NotificationCenter.default.addObserver(
|
|
258
|
+
NotificationCenter.default.addObserver(instance,
|
|
260
259
|
selector: #selector(self.callDealloc(_:)),
|
|
261
260
|
name: NSNotification.Name.OMICallDealloc,
|
|
262
261
|
object: nil
|
|
263
262
|
)
|
|
264
|
-
NotificationCenter.default.addObserver(
|
|
263
|
+
NotificationCenter.default.addObserver(instance,
|
|
265
264
|
selector: #selector(self.switchBoardAnswer(_:)),
|
|
266
265
|
name: NSNotification.Name.OMICallSwitchBoardAnswer,
|
|
267
266
|
object: nil
|
|
268
267
|
)
|
|
269
|
-
NotificationCenter.default.addObserver(
|
|
270
|
-
NotificationCenter.default.addObserver(
|
|
268
|
+
NotificationCenter.default.addObserver(instance, selector: #selector(self.updateNetworkHealth(_:)), name: NSNotification.Name.OMICallNetworkQuality, object: nil)
|
|
269
|
+
NotificationCenter.default.addObserver(instance, selector: #selector(self.audioChanged(_:)), name: NSNotification.Name.OMICallAudioRouteChange, object: nil)
|
|
271
270
|
if (showMissedCall) {
|
|
272
271
|
self.showMissedCall()
|
|
273
272
|
}
|
|
@@ -275,8 +274,9 @@ class CallManager {
|
|
|
275
274
|
}
|
|
276
275
|
|
|
277
276
|
func registerVideoEvent() {
|
|
278
|
-
DispatchQueue.main.async {
|
|
279
|
-
|
|
277
|
+
DispatchQueue.main.async { [weak self] in
|
|
278
|
+
guard let self = self, let instance = CallManager.instance else { return }
|
|
279
|
+
NotificationCenter.default.addObserver(instance,
|
|
280
280
|
selector: #selector(self.videoUpdate(_:)),
|
|
281
281
|
name: NSNotification.Name.OMICallVideoInfo,
|
|
282
282
|
object: nil
|
|
@@ -286,7 +286,8 @@ class CallManager {
|
|
|
286
286
|
|
|
287
287
|
func removeVideoEvent() {
|
|
288
288
|
DispatchQueue.main.async {
|
|
289
|
-
|
|
289
|
+
guard let instance = CallManager.instance else { return }
|
|
290
|
+
NotificationCenter.default.removeObserver(instance, name: NSNotification.Name.OMICallVideoInfo, object: nil)
|
|
290
291
|
}
|
|
291
292
|
}
|
|
292
293
|
|
|
@@ -306,7 +307,16 @@ class CallManager {
|
|
|
306
307
|
let state = userInfo[OMINotificationNetworkStatusKey] as? Int else {
|
|
307
308
|
return;
|
|
308
309
|
}
|
|
309
|
-
|
|
310
|
+
// Build stat map with full diagnostics
|
|
311
|
+
var stat: [String: Any] = [:]
|
|
312
|
+
if let mos = userInfo[OMINotificationMOSKey] as? Double { stat["mos"] = mos }
|
|
313
|
+
if let jitter = userInfo[OMINotificationJitterKey] as? Double { stat["jitter"] = jitter }
|
|
314
|
+
if let latency = userInfo[OMINotificationLatencyKey] as? Double { stat["latency"] = latency }
|
|
315
|
+
if let ppl = userInfo[OMINotificationPPLKey] as? Double { stat["packetLoss"] = ppl }
|
|
316
|
+
OmikitPlugin.instance?.sendEvent(withName: CALL_QUALITY, body: [
|
|
317
|
+
"quality": state,
|
|
318
|
+
"stat": stat
|
|
319
|
+
])
|
|
310
320
|
}
|
|
311
321
|
|
|
312
322
|
@objc func videoUpdate(_ notification: NSNotification) {
|
|
@@ -316,7 +326,7 @@ class CallManager {
|
|
|
316
326
|
}
|
|
317
327
|
switch (state) {
|
|
318
328
|
case 1:
|
|
319
|
-
OmikitPlugin.instance
|
|
329
|
+
OmikitPlugin.instance?.sendEvent(withName: REMOTE_VIDEO_READY, body: nil)
|
|
320
330
|
break
|
|
321
331
|
default:
|
|
322
332
|
break
|
|
@@ -329,13 +339,13 @@ class CallManager {
|
|
|
329
339
|
return;
|
|
330
340
|
}
|
|
331
341
|
guestPhone = sip
|
|
332
|
-
OmikitPlugin.instance
|
|
342
|
+
OmikitPlugin.instance?.sendEvent(withName: SWITCHBOARD_ANSWER, body: ["sip": sip])
|
|
333
343
|
}
|
|
334
344
|
|
|
335
345
|
@objc func callDealloc(_ notification: NSNotification) {
|
|
336
346
|
if (tempCallInfo != nil) {
|
|
337
347
|
tempCallInfo!["status"] = OMICallState.disconnected.rawValue
|
|
338
|
-
OmikitPlugin.instance
|
|
348
|
+
OmikitPlugin.instance?.sendEvent(withName: CALL_STATE_CHANGED, body: tempCallInfo!)
|
|
339
349
|
}
|
|
340
350
|
}
|
|
341
351
|
|
|
@@ -380,7 +390,7 @@ class CallManager {
|
|
|
380
390
|
}
|
|
381
391
|
isSpeaker = call.speaker
|
|
382
392
|
lastStatusCall = "answered"
|
|
383
|
-
OmikitPlugin.instance
|
|
393
|
+
OmikitPlugin.instance?.sendMuteStatus()
|
|
384
394
|
break
|
|
385
395
|
case OMICallState.incoming.rawValue:
|
|
386
396
|
guestPhone = call.callerNumber ?? ""
|
|
@@ -518,7 +528,7 @@ func startCall(_ phoneNumber: String, isVideo: Bool, completion: @escaping (_: S
|
|
|
518
528
|
let callInfo = [
|
|
519
529
|
"status": OMICallState.disconnected.rawValue,
|
|
520
530
|
]
|
|
521
|
-
OmikitPlugin.instance
|
|
531
|
+
OmikitPlugin.instance?.sendEvent(withName: CALL_STATE_CHANGED, body: callInfo)
|
|
522
532
|
return [:]
|
|
523
533
|
}
|
|
524
534
|
tempCallInfo = getCallInfo(call: call)
|
|
@@ -571,7 +581,7 @@ func startCall(_ phoneNumber: String, isVideo: Bool, completion: @escaping (_: S
|
|
|
571
581
|
func toogleSpeaker() {
|
|
572
582
|
let result = omiLib.callManager.audioController.toggleSpeaker();
|
|
573
583
|
isSpeaker = result
|
|
574
|
-
OmikitPlugin.instance
|
|
584
|
+
OmikitPlugin.instance?.sendSpeakerStatus()
|
|
575
585
|
}
|
|
576
586
|
|
|
577
587
|
func getAudioOutputs() -> [[String: String]] {
|
|
@@ -12,7 +12,8 @@ RCT_EXTERN_METHOD(configPushNotification:(id)data
|
|
|
12
12
|
rejecter:(RCTPromiseRejectBlock)reject)
|
|
13
13
|
|
|
14
14
|
// Get initial call
|
|
15
|
-
RCT_EXTERN_METHOD(getInitialCall:(
|
|
15
|
+
RCT_EXTERN_METHOD(getInitialCall:(id)data
|
|
16
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
16
17
|
rejecter:(RCTPromiseRejectBlock)reject)
|
|
17
18
|
|
|
18
19
|
// Initialize call with user password
|
|
@@ -97,6 +98,25 @@ RCT_EXTERN_METHOD(getUserInfo:(id)data
|
|
|
97
98
|
resolver:(RCTPromiseResolveBlock)resolve
|
|
98
99
|
rejecter:(RCTPromiseRejectBlock)reject)
|
|
99
100
|
|
|
101
|
+
// Getter functions
|
|
102
|
+
RCT_EXTERN_METHOD(getProjectId:(RCTPromiseResolveBlock)resolve
|
|
103
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
104
|
+
|
|
105
|
+
RCT_EXTERN_METHOD(getSipInfo:(RCTPromiseResolveBlock)resolve
|
|
106
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
107
|
+
|
|
108
|
+
RCT_EXTERN_METHOD(getDeviceId:(RCTPromiseResolveBlock)resolve
|
|
109
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
110
|
+
|
|
111
|
+
RCT_EXTERN_METHOD(getFcmToken:(RCTPromiseResolveBlock)resolve
|
|
112
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
113
|
+
|
|
114
|
+
RCT_EXTERN_METHOD(getAppId:(RCTPromiseResolveBlock)resolve
|
|
115
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
116
|
+
|
|
117
|
+
RCT_EXTERN_METHOD(getVoipToken:(RCTPromiseResolveBlock)resolve
|
|
118
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
119
|
+
|
|
100
120
|
// Get audio
|
|
101
121
|
RCT_EXTERN_METHOD(getAudio:(RCTPromiseResolveBlock)resolve
|
|
102
122
|
rejecter:(RCTPromiseRejectBlock)reject)
|
|
@@ -118,6 +138,60 @@ RCT_EXTERN_METHOD(transferCall:(id)data
|
|
|
118
138
|
RCT_EXTERN_METHOD(rejectCall:(RCTPromiseResolveBlock)resolve
|
|
119
139
|
rejecter:(RCTPromiseRejectBlock)reject)
|
|
120
140
|
|
|
141
|
+
// Hold
|
|
142
|
+
RCT_EXTERN_METHOD(onHold:(id)data
|
|
143
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
144
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
145
|
+
|
|
146
|
+
// System notification (Android-only stubs)
|
|
147
|
+
RCT_EXTERN_METHOD(hideSystemNotificationSafely:(RCTPromiseResolveBlock)resolve
|
|
148
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
149
|
+
|
|
150
|
+
RCT_EXTERN_METHOD(hideSystemNotificationOnly:(RCTPromiseResolveBlock)resolve
|
|
151
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
152
|
+
|
|
153
|
+
RCT_EXTERN_METHOD(hideSystemNotificationAndUnregister:(id)data
|
|
154
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
155
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
156
|
+
|
|
157
|
+
// Permission management (Android-only stubs)
|
|
158
|
+
RCT_EXTERN_METHOD(checkAndRequestPermissions:(id)data
|
|
159
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
160
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
161
|
+
|
|
162
|
+
RCT_EXTERN_METHOD(checkPermissionStatus:(RCTPromiseResolveBlock)resolve
|
|
163
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
164
|
+
|
|
165
|
+
RCT_EXTERN_METHOD(requestPermissionsByCodes:(id)data
|
|
166
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
167
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
168
|
+
|
|
169
|
+
// System alert window (Android-only stubs)
|
|
170
|
+
RCT_EXTERN_METHOD(systemAlertWindow:(RCTPromiseResolveBlock)resolve
|
|
171
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
172
|
+
|
|
173
|
+
RCT_EXTERN_METHOD(requestSystemAlertWindowPermission:(RCTPromiseResolveBlock)resolve
|
|
174
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
175
|
+
|
|
176
|
+
RCT_EXTERN_METHOD(openSystemAlertSetting:(RCTPromiseResolveBlock)resolve
|
|
177
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
178
|
+
|
|
179
|
+
// Credentials & registration
|
|
180
|
+
RCT_EXTERN_METHOD(checkCredentials:(id)data
|
|
181
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
182
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
183
|
+
|
|
184
|
+
RCT_EXTERN_METHOD(registerWithOptions:(id)data
|
|
185
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
186
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
187
|
+
|
|
188
|
+
// Keep alive (Android-only stubs)
|
|
189
|
+
RCT_EXTERN_METHOD(getKeepAliveStatus:(RCTPromiseResolveBlock)resolve
|
|
190
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
191
|
+
|
|
192
|
+
RCT_EXTERN_METHOD(triggerKeepAlivePing:(RCTPromiseResolveBlock)resolve
|
|
193
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
194
|
+
|
|
121
195
|
// Required to run on the main thread
|
|
122
196
|
+ (BOOL)requiresMainQueueSetup
|
|
123
197
|
{
|
|
@@ -2,22 +2,60 @@ import Foundation
|
|
|
2
2
|
import React
|
|
3
3
|
import OmiKit
|
|
4
4
|
|
|
5
|
+
#if RCT_NEW_ARCH_ENABLED
|
|
6
|
+
import React_Codegen
|
|
7
|
+
#endif
|
|
8
|
+
|
|
5
9
|
@objc(OmikitPlugin)
|
|
6
10
|
public class OmikitPlugin: RCTEventEmitter {
|
|
7
|
-
|
|
11
|
+
|
|
8
12
|
@objc public static var instance : OmikitPlugin!
|
|
9
|
-
|
|
13
|
+
|
|
10
14
|
public override init() {
|
|
11
15
|
super.init()
|
|
12
16
|
OmikitPlugin.instance = self
|
|
13
17
|
}
|
|
18
|
+
|
|
19
|
+
// TurboModule conformance
|
|
20
|
+
#if RCT_NEW_ARCH_ENABLED
|
|
21
|
+
@objc public static func moduleName() -> String {
|
|
22
|
+
return "OmikitPlugin"
|
|
23
|
+
}
|
|
24
|
+
#endif
|
|
25
|
+
|
|
26
|
+
@objc public override static func moduleName() -> String! {
|
|
27
|
+
return "OmikitPlugin"
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Export constants for event names
|
|
31
|
+
@objc public override func constantsToExport() -> [AnyHashable : Any]! {
|
|
32
|
+
return [
|
|
33
|
+
"CALL_STATE_CHANGED": CALL_STATE_CHANGED,
|
|
34
|
+
"MUTED": MUTED,
|
|
35
|
+
"HOLD": HOLD,
|
|
36
|
+
"SPEAKER": SPEAKER,
|
|
37
|
+
"REMOTE_VIDEO_READY": REMOTE_VIDEO_READY,
|
|
38
|
+
"CLICK_MISSED_CALL": CLICK_MISSED_CALL,
|
|
39
|
+
"SWITCHBOARD_ANSWER": SWITCHBOARD_ANSWER,
|
|
40
|
+
"CALL_QUALITY": CALL_QUALITY,
|
|
41
|
+
"AUDIO_CHANGE": AUDIO_CHANGE,
|
|
42
|
+
"REQUEST_PERMISSION": REQUEST_PERMISSION
|
|
43
|
+
]
|
|
44
|
+
}
|
|
14
45
|
|
|
15
46
|
|
|
16
47
|
// MARK: - Service Methods
|
|
17
48
|
@objc(startServices:rejecter:)
|
|
18
|
-
func startServices(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
|
|
19
|
-
|
|
20
|
-
|
|
49
|
+
func startServices(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
50
|
+
// Ensure instance is set for callbacks
|
|
51
|
+
if OmikitPlugin.instance == nil {
|
|
52
|
+
OmikitPlugin.instance = self
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
DispatchQueue.main.async {
|
|
56
|
+
CallManager.shareInstance().registerNotificationCenter(showMissedCall: true)
|
|
57
|
+
resolve(true)
|
|
58
|
+
}
|
|
21
59
|
}
|
|
22
60
|
|
|
23
61
|
@objc(configPushNotification:resolver:rejecter:)
|
|
@@ -31,8 +69,8 @@ public class OmikitPlugin: RCTEventEmitter {
|
|
|
31
69
|
}
|
|
32
70
|
|
|
33
71
|
|
|
34
|
-
@objc(getInitialCall:rejecter:)
|
|
35
|
-
func getInitialCall(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
|
|
72
|
+
@objc(getInitialCall:resolver:rejecter:)
|
|
73
|
+
func getInitialCall(_ data: Any, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
|
|
36
74
|
if let call = CallManager.shareInstance().getAvailableCall() {
|
|
37
75
|
let data: [String: Any] = [
|
|
38
76
|
"callerNumber": call.callerNumber,
|
|
@@ -211,13 +249,19 @@ public class OmikitPlugin: RCTEventEmitter {
|
|
|
211
249
|
}
|
|
212
250
|
}
|
|
213
251
|
|
|
214
|
-
@objc(
|
|
215
|
-
func
|
|
216
|
-
|
|
217
|
-
|
|
252
|
+
@objc(getUserInfo:resolver:rejecter:)
|
|
253
|
+
func getUserInfo(data: Any, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
254
|
+
// Support both {phone: "xxx"} object and direct string
|
|
255
|
+
let phone: String
|
|
256
|
+
if let dict = data as? [String: Any], let p = dict["phone"] as? String {
|
|
257
|
+
phone = p
|
|
258
|
+
} else if let p = data as? String {
|
|
259
|
+
phone = p
|
|
260
|
+
} else {
|
|
261
|
+
reject("INVALID_DATA", "Expected a dictionary with phone key or a phone number string.", nil)
|
|
218
262
|
return
|
|
219
263
|
}
|
|
220
|
-
|
|
264
|
+
|
|
221
265
|
CallManager.shareInstance().getUserInfo(phone: phone) { userInfo in
|
|
222
266
|
if userInfo.isEmpty {
|
|
223
267
|
reject("USER_NOT_FOUND", "User not found for phone number: \(phone)", nil)
|
|
@@ -226,7 +270,38 @@ public class OmikitPlugin: RCTEventEmitter {
|
|
|
226
270
|
}
|
|
227
271
|
}
|
|
228
272
|
}
|
|
229
|
-
|
|
273
|
+
|
|
274
|
+
// MARK: - Getter Functions
|
|
275
|
+
@objc(getProjectId:rejecter:)
|
|
276
|
+
func getProjectId(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
|
|
277
|
+
resolve(OmiClient.getProjectId())
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
@objc(getSipInfo:rejecter:)
|
|
281
|
+
func getSipInfo(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
|
|
282
|
+
resolve(OmiClient.getSipInfo())
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
@objc(getDeviceId:rejecter:)
|
|
286
|
+
func getDeviceId(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
|
|
287
|
+
resolve(OmiClient.getDeviceId())
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
@objc(getFcmToken:rejecter:)
|
|
291
|
+
func getFcmToken(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
|
|
292
|
+
resolve(OmiClient.getFcmToken())
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
@objc(getAppId:rejecter:)
|
|
296
|
+
func getAppId(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
|
|
297
|
+
resolve(OmiClient.getAppId())
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
@objc(getVoipToken:rejecter:)
|
|
301
|
+
func getVoipToken(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
|
|
302
|
+
resolve(OmiClient.getVoipToken())
|
|
303
|
+
}
|
|
304
|
+
|
|
230
305
|
// MARK: - Audio Methods
|
|
231
306
|
@objc(getAudio:rejecter:)
|
|
232
307
|
func getAudio(resolve: @escaping RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
|
|
@@ -236,12 +311,21 @@ public class OmikitPlugin: RCTEventEmitter {
|
|
|
236
311
|
|
|
237
312
|
@objc(setAudio:resolver:rejecter:)
|
|
238
313
|
func setAudio(data: Any, resolve: @escaping RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
|
|
239
|
-
guard let dataOmi = data as? [String: Any]
|
|
240
|
-
let portType = dataOmi["portType"] as? String else {
|
|
314
|
+
guard let dataOmi = data as? [String: Any] else {
|
|
241
315
|
reject("INVALID_DATA", "Expected a dictionary with port type.", nil)
|
|
242
316
|
return
|
|
243
317
|
}
|
|
244
|
-
|
|
318
|
+
// Support both number and string for portType
|
|
319
|
+
let portType: String
|
|
320
|
+
if let pt = dataOmi["portType"] as? String {
|
|
321
|
+
portType = pt
|
|
322
|
+
} else if let pt = dataOmi["portType"] as? NSNumber {
|
|
323
|
+
portType = pt.stringValue
|
|
324
|
+
} else {
|
|
325
|
+
reject("INVALID_DATA", "portType must be a number or string.", nil)
|
|
326
|
+
return
|
|
327
|
+
}
|
|
328
|
+
|
|
245
329
|
CallManager.shareInstance().setAudioOutputs(portType: portType)
|
|
246
330
|
resolve(true)
|
|
247
331
|
}
|
|
@@ -315,6 +399,105 @@ public class OmikitPlugin: RCTEventEmitter {
|
|
|
315
399
|
SWITCHBOARD_ANSWER,
|
|
316
400
|
CALL_QUALITY,
|
|
317
401
|
AUDIO_CHANGE,
|
|
402
|
+
REQUEST_PERMISSION
|
|
318
403
|
]
|
|
319
404
|
}
|
|
405
|
+
|
|
406
|
+
// MARK: - Stub Methods for TurboModule Compatibility
|
|
407
|
+
// These methods are Android-only but required by Codegen spec
|
|
408
|
+
|
|
409
|
+
@objc(onHold:resolver:rejecter:)
|
|
410
|
+
func onHold(data: Any, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
|
|
411
|
+
// iOS uses toggleHold instead
|
|
412
|
+
resolve(true)
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
@objc(hideSystemNotificationSafely:rejecter:)
|
|
416
|
+
func hideSystemNotificationSafely(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
|
|
417
|
+
// Android-only feature
|
|
418
|
+
resolve(true)
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
@objc(hideSystemNotificationOnly:rejecter:)
|
|
422
|
+
func hideSystemNotificationOnly(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
|
|
423
|
+
// Android-only feature
|
|
424
|
+
resolve(true)
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
@objc(hideSystemNotificationAndUnregister:resolver:rejecter:)
|
|
428
|
+
func hideSystemNotificationAndUnregister(data: Any, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
|
|
429
|
+
// Android-only feature
|
|
430
|
+
resolve(true)
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
@objc(checkAndRequestPermissions:resolver:rejecter:)
|
|
434
|
+
func checkAndRequestPermissions(data: Any, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
|
|
435
|
+
// Android-only feature, iOS handles permissions differently
|
|
436
|
+
resolve(true)
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
@objc(checkPermissionStatus:rejecter:)
|
|
440
|
+
func checkPermissionStatus(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
|
|
441
|
+
// Android-only feature
|
|
442
|
+
resolve(nil)
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
@objc(requestPermissionsByCodes:resolver:rejecter:)
|
|
446
|
+
func requestPermissionsByCodes(data: Any, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
|
|
447
|
+
// Android-only feature
|
|
448
|
+
resolve(true)
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
@objc(systemAlertWindow:rejecter:)
|
|
452
|
+
func systemAlertWindow(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
|
|
453
|
+
// Android-only feature
|
|
454
|
+
resolve(true)
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
@objc(requestSystemAlertWindowPermission:rejecter:)
|
|
458
|
+
func requestSystemAlertWindowPermission(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
|
|
459
|
+
// Android-only feature
|
|
460
|
+
resolve(true)
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
@objc(openSystemAlertSetting:rejecter:)
|
|
464
|
+
func openSystemAlertSetting(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
|
|
465
|
+
// Android-only feature
|
|
466
|
+
resolve(nil)
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
@objc(checkCredentials:resolver:rejecter:)
|
|
470
|
+
func checkCredentials(data: Any, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
|
|
471
|
+
// Stub for iOS - not implemented yet
|
|
472
|
+
resolve([
|
|
473
|
+
"success": true,
|
|
474
|
+
"statusCode": 200,
|
|
475
|
+
"message": "iOS stub"
|
|
476
|
+
])
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
@objc(registerWithOptions:resolver:rejecter:)
|
|
480
|
+
func registerWithOptions(data: Any, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
|
|
481
|
+
// Stub for iOS - not implemented yet
|
|
482
|
+
resolve([
|
|
483
|
+
"success": true,
|
|
484
|
+
"statusCode": 200,
|
|
485
|
+
"message": "iOS stub"
|
|
486
|
+
])
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
@objc(getKeepAliveStatus:rejecter:)
|
|
490
|
+
func getKeepAliveStatus(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
|
|
491
|
+
// Android-only feature
|
|
492
|
+
resolve([
|
|
493
|
+
"isActive": false,
|
|
494
|
+
"platform": "ios"
|
|
495
|
+
])
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
@objc(triggerKeepAlivePing:rejecter:)
|
|
499
|
+
func triggerKeepAlivePing(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
|
|
500
|
+
// Android-only feature
|
|
501
|
+
resolve(true)
|
|
502
|
+
}
|
|
320
503
|
}
|