omikit-plugin 0.1.0

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 (31) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +31 -0
  3. package/android/build.gradle +134 -0
  4. package/android/gradle.properties +5 -0
  5. package/android/src/main/AndroidManifest.xml +4 -0
  6. package/android/src/main/java/com/omikitplugin/OmikitPluginModule.kt +190 -0
  7. package/android/src/main/java/com/omikitplugin/OmikitPluginPackage.kt +17 -0
  8. package/android/src/main/java/com/omikitplugin/constants/constant.kt +31 -0
  9. package/ios/CallProcess/CallManager.swift +367 -0
  10. package/ios/CallProcess/NSUserActivity.swift +58 -0
  11. package/ios/CallProcess/StringUtils.swift +18 -0
  12. package/ios/Constant/Constant.swift +47 -0
  13. package/ios/OmikitPlugin-Bridging-Header.h +2 -0
  14. package/ios/OmikitPlugin.m +17 -0
  15. package/ios/OmikitPlugin.swift +19 -0
  16. package/ios/OmikitPlugin.xcodeproj/project.pbxproj +321 -0
  17. package/ios/OmikitPlugin.xcodeproj/project.xcworkspace/contents.xcworkspacedata +4 -0
  18. package/ios/OmikitPlugin.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  19. package/ios/OmikitPlugin.xcodeproj/project.xcworkspace/xcuserdata/pro201916.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  20. package/ios/OmikitPlugin.xcodeproj/xcuserdata/pro201916.xcuserdatad/xcschemes/xcschememanagement.plist +14 -0
  21. package/ios/VideoCall/FLLocalCameraView.swift +81 -0
  22. package/ios/VideoCall/FLRemoteCameraView.swift +84 -0
  23. package/lib/commonjs/index.js +58 -0
  24. package/lib/commonjs/index.js.map +1 -0
  25. package/lib/module/index.js +42 -0
  26. package/lib/module/index.js.map +1 -0
  27. package/lib/typescript/index.d.ts +12 -0
  28. package/lib/typescript/index.d.ts.map +1 -0
  29. package/omikit-plugin.podspec +36 -0
  30. package/package.json +166 -0
  31. package/src/index.tsx +59 -0
@@ -0,0 +1,367 @@
1
+ //
2
+ // CallUtils.swift
3
+ // OMICall Contact Center
4
+ //
5
+ // Created by Tuan on 22/03/2022.
6
+ //
7
+
8
+ import Foundation
9
+ import AVFoundation
10
+ import MediaPlayer
11
+ import SwiftUI
12
+ import OmiKit
13
+ import AVFoundation
14
+
15
+ class CallManager {
16
+
17
+ static private var instance: CallManager? = nil // Instance
18
+ var call: OMICall? // Call
19
+ private var numberRetry: Int = 0
20
+ var isCallError: Bool = false // check when call error
21
+ private let omiLib = OMISIPLib.sharedInstance()
22
+ private var isSpeaker = false
23
+ var currentConfirmedCall : OMICall?
24
+ var videoManager: OMIVideoViewManager?
25
+
26
+
27
+ /// Get instance
28
+ static func shareInstance() -> CallManager {
29
+ if (instance == nil) {
30
+ instance = CallManager()
31
+ }
32
+ return instance!
33
+ }
34
+
35
+ func updateToken(params: [String: Any]) {
36
+ if let apnsToken = params["apnsToken"] as? String {
37
+ OmiClient.setUserPushNotificationToken(apnsToken)
38
+ }
39
+ }
40
+
41
+ func initEndpoint(params: [String: Any]){
42
+ var isSupportVideoCall = false
43
+ if let userName = params["userName"] as? String, let password = params["password"] as? String, let realm = params["realm"] as? String {
44
+ OmiClient.initWithUsername(userName, password: password, realm: realm)
45
+ if let isVideoCall = params["isVideo"] as? Bool {
46
+ isSupportVideoCall = isVideoCall
47
+ }
48
+ OmiClient.startOmiService(isSupportVideoCall)
49
+ if (isSupportVideoCall) {
50
+ OmiClient.registerAccount()
51
+ videoManager = OMIVideoViewManager.init()
52
+ }
53
+ registerNotificationCenter()
54
+ }
55
+ }
56
+
57
+ func registerNotificationCenter() {
58
+ DispatchQueue.main.async { [weak self] in
59
+ guard let self = self else { return }
60
+ NotificationCenter.default.removeObserver(CallManager.instance!)
61
+ NotificationCenter.default.addObserver(CallManager.instance!,
62
+ selector: #selector(self.callStateChanged(_:)),
63
+ name: NSNotification.Name.OMICallStateChanged,
64
+ object: nil
65
+ )
66
+ NotificationCenter.default.addObserver(CallManager.instance!,
67
+ selector: #selector(self.callDealloc(_:)),
68
+ name: NSNotification.Name.OMICallDealloc,
69
+ object: nil
70
+ )
71
+ }
72
+ }
73
+
74
+ @objc func callDealloc(_ notification: NSNotification) {
75
+ guard let userInfo = notification.userInfo,
76
+ let call = userInfo[OMINotificationUserInfoCallKey] as? OMICall else {
77
+ return;
78
+ }
79
+ if (call.callState == .disconnected) {
80
+ DispatchQueue.main.async {
81
+ // SwiftOmikitPlugin.instance?.sendEvent(onCallEnd, [:])
82
+ self.currentConfirmedCall = nil
83
+ }
84
+ }
85
+ }
86
+
87
+ @objc fileprivate func callStateChanged(_ notification: NSNotification) {
88
+ guard let userInfo = notification.userInfo,
89
+ let call = userInfo[OMINotificationUserInfoCallKey] as? OMICall else {
90
+ return;
91
+ }
92
+ print("call state")
93
+ print(call.callState)
94
+ switch (call.callState) {
95
+ case .calling:
96
+ if (!call.isIncoming) {
97
+ NSLog("Outgoing call, in CALLING state, with UUID \(call.uuid)")
98
+ // SwiftOmikitPlugin.instance?.sendEvent(onRinging, [:])
99
+ }
100
+ break
101
+ case .early:
102
+ if (!call.isIncoming) {
103
+ NSLog("Outgoing call, in EARLY state, with UUID: \(call.uuid)")
104
+ }
105
+ break
106
+ case .connecting:
107
+ if (!call.isIncoming) {
108
+ NSLog("Outgoing call, in CONNECTING state, with UUID: \(call.uuid)")
109
+ }
110
+ break
111
+ case .confirmed:
112
+ DispatchQueue.main.async {
113
+ if (!call.isIncoming) {
114
+ NSLog("Outgoing call, in CONFIRMED state, with UUID: \(call.uuid)")
115
+ // SwiftOmikitPlugin.instance?.sendEvent(onCallEstablished, [:])
116
+ // SwiftOmikitPlugin.instance?.sendEvent(onMuted, ["isMuted": call.muted])
117
+ self.currentConfirmedCall = call
118
+ return
119
+ }
120
+ //call video
121
+ NSLog("Outgoing call, in CONFIRMED state, with UUID: \(call.uuid)")
122
+ // SwiftOmikitPlugin.instance?.sendEvent(onCallEstablished, [:])
123
+ // SwiftOmikitPlugin.instance?.sendEvent(onMuted, ["isMuted": call.muted])
124
+ self.currentConfirmedCall = call
125
+ }
126
+ break
127
+ case .disconnected:
128
+ if (!call.connected) {
129
+ NSLog("Call never connected, in DISCONNECTED state, with UUID: \(call.uuid)")
130
+ } else if (!call.userDidHangUp) {
131
+ NSLog("Call remotly ended, in DISCONNECTED state, with UUID: \(call.uuid)")
132
+ }
133
+ print(omiLib.getCurrentCall()?.uuid.uuidString)
134
+ print(call.uuid.uuidString)
135
+ if let currentActiveCall = currentConfirmedCall, currentActiveCall.uuid.uuidString == call.uuid.uuidString {
136
+ // SwiftOmikitPlugin.instance?.sendEvent(onCallEnd, [:])
137
+ currentConfirmedCall = nil
138
+ break
139
+ }
140
+ if currentConfirmedCall == nil {
141
+ // SwiftOmikitPlugin.instance?.sendEvent(onCallEnd, [:])
142
+ break
143
+ }
144
+ print(omiLib.getNewestCall()?.uuid.uuidString)
145
+ break
146
+ case .incoming:
147
+ // SwiftOmikitPlugin.instance?.sendEvent(incomingReceived, [
148
+ // "callerId": call.callId,
149
+ // "phoneNumber": call.callerNumber
150
+ // ])SwiftOmikitPlugin.instance?.sendEvent(incomingReceived, [
151
+ // "callerId": call.callId,
152
+ // "phoneNumber": call.callerNumber
153
+ // ])
154
+ break
155
+ case .muted:
156
+ // SwiftOmikitPlugin.instance?.sendEvent(onMuted, ["isMuted": call.muted])
157
+ break
158
+ case .hold:
159
+ // SwiftOmikitPlugin.instance?.sendEvent(onHold, ["isHold": call.onHold])
160
+ break
161
+ @unknown default:
162
+ NSLog("Default call state")
163
+ }
164
+ }
165
+
166
+ /// Start call
167
+ func startCall(_ phoneNumber: String, isVideo: Bool) {
168
+ registerNotificationCenter()
169
+ if (isVideo) {
170
+ OmiClient.startVideoCall(phoneNumber)
171
+ return
172
+ }
173
+ OmiClient.startCall(phoneNumber)
174
+ }
175
+
176
+ /// End call
177
+ func endNewestCall() {
178
+ guard let call = omiLib.getNewestCall() else {
179
+ return
180
+ }
181
+ omiLib.callManager.end(call) { error in
182
+ if error != nil {
183
+ NSLog("error hanging up call(\(call.uuid.uuidString)): \(error!)")
184
+ }
185
+ }
186
+ NotificationCenter.default.removeObserver(self)
187
+ }
188
+
189
+ func endCurrentConfirmCall() {
190
+ guard let call = omiLib.getCurrentCall() else {
191
+ endNewestCall()
192
+ return
193
+ }
194
+ omiLib.callManager.end(call) { error in
195
+ if error != nil {
196
+ NSLog("error hanging up call(\(call.uuid.uuidString)): \(error!)")
197
+ }
198
+ }
199
+ NotificationCenter.default.removeObserver(self)
200
+ }
201
+
202
+
203
+ func endAllCalls() {
204
+ omiLib.callManager.endAllCalls()
205
+ // SwiftOmikitPlugin.instance?.sendEvent("onCallEnd", [:])
206
+ NotificationCenter.default.removeObserver(self)
207
+ }
208
+
209
+ func sendDTMF(character: String) {
210
+ guard let call = omiLib.getCurrentCall() else {
211
+ return
212
+ }
213
+ try? call.sendDTMF(character)
214
+ }
215
+
216
+
217
+ /// Toogle mtue
218
+ func toggleMute(completion: @escaping () -> Void?) {
219
+ guard let omicall = OMISIPLib.sharedInstance().getCurrentCall() else {
220
+ return
221
+ }
222
+
223
+ omiLib.callManager.toggleMute(for: omicall) { error in
224
+ if error != nil {
225
+ NSLog("toggle mute error: \(error))")
226
+ }
227
+ }
228
+
229
+ }
230
+
231
+ /// Toogle hold
232
+ func toggleHold(completion: @escaping () -> Void?) {
233
+ guard let omicall = OMISIPLib.sharedInstance().getCurrentCall() else {
234
+ return
235
+ }
236
+ DispatchQueue.main.async {[weak self] in
237
+ guard let self = self else { return }
238
+ self.omiLib.callManager.toggleHold(for: omicall) { error in
239
+ if error != nil {
240
+ NSLog("Error holding current call: \(error!)")
241
+ return
242
+ } else {
243
+ completion()
244
+ }
245
+ }
246
+ }
247
+ }
248
+
249
+
250
+ /// Toogle speaker
251
+ func toogleSpeaker() {
252
+ do {
253
+ if (!isSpeaker) {
254
+ isSpeaker = true
255
+ try AVAudioSession.sharedInstance().overrideOutputAudioPort(.speaker)
256
+
257
+ } else {
258
+ isSpeaker = false
259
+ try AVAudioSession.sharedInstance().overrideOutputAudioPort(.none)
260
+ }
261
+ } catch (let error){
262
+ NSLog("Error toogleSpeaker current call: \(error)")
263
+
264
+ }
265
+ }
266
+
267
+
268
+ func inputs() -> [[String: String]] {
269
+ let inputs = AVAudioSession.sharedInstance().availableInputs ?? []
270
+ let results = inputs.map { item in
271
+ return [
272
+ "name": item.portName,
273
+ "id": item.uid,
274
+ ]
275
+ }
276
+ return results
277
+ }
278
+
279
+ func setInput(id: String) {
280
+ let inputs = AVAudioSession.sharedInstance().availableInputs ?? []
281
+ if let newOutput = inputs.first(where: {$0.uid == id}) {
282
+ try? AVAudioSession.sharedInstance().setPreferredInput(newOutput)
283
+ }
284
+ }
285
+
286
+ func outputs() -> [[String: String]] {
287
+ let outputs = AVAudioSession.sharedInstance().currentRoute.outputs
288
+ var results = outputs.map { item in
289
+ return [
290
+ "name": item.portName,
291
+ "id": item.uid,
292
+ ]
293
+ }
294
+ let hasSpeaker = results.contains{ $0["name"] == "Speaker" }
295
+ if (!hasSpeaker) {
296
+ results.append([
297
+ "name": "Speaker",
298
+ "id": "Speaker",
299
+ ])
300
+ } else {
301
+ results.append([
302
+ "name": "Off Speaker",
303
+ "id": "Off Speaker",
304
+ ])
305
+ }
306
+ return results
307
+ }
308
+
309
+ func setOutput(id: String) {
310
+ if (id == "Speaker") {
311
+ try? AVAudioSession.sharedInstance().overrideOutputAudioPort(.speaker)
312
+ return
313
+ }
314
+ if (id == "Off Speaker") {
315
+ try? AVAudioSession.sharedInstance().overrideOutputAudioPort(.none)
316
+ return
317
+ }
318
+ let outputs = AVAudioSession.sharedInstance().currentRoute.outputs
319
+ if let newOutput = outputs.first(where: {$0.uid == id}) {
320
+ try? AVAudioSession.sharedInstance().setPreferredInput(newOutput)
321
+ }
322
+ }
323
+
324
+ //video call
325
+ func toggleCamera() {
326
+ if let videoManager = videoManager {
327
+ videoManager.toggleCamera()
328
+ }
329
+ }
330
+
331
+ func getCameraStatus() -> Bool {
332
+ guard let videoManager = videoManager else { return false }
333
+ return videoManager.isCameraOn
334
+ }
335
+
336
+ func switchCamera() {
337
+ if let videoManager = videoManager {
338
+ videoManager.switchCamera()
339
+ }
340
+ }
341
+
342
+ // func getLocalPreviewView(callback: @escaping (UIView) -> Void) {
343
+ // guard let videoManager = videoManager else { return }
344
+ // videoManager.localView {previewView in
345
+ // DispatchQueue.main.async {
346
+ // if (previewView != nil) {
347
+ // previewView!.contentMode = .scaleAspectFill
348
+ // callback(previewView!)
349
+ // }
350
+ // }
351
+ // }
352
+ // }
353
+ //
354
+ // func getRemotePreviewView(callback: @escaping (UIView) -> Void) {
355
+ // guard let videoManager = videoManager else { return }
356
+ // videoManager.remoteView { previewView in
357
+ // DispatchQueue.main.async {
358
+ // if (previewView != nil) {
359
+ // previewView!.contentMode = .scaleAspectFill
360
+ // callback(previewView!)
361
+ // }
362
+ // }
363
+ // }
364
+ // }
365
+ }
366
+
367
+
@@ -0,0 +1,58 @@
1
+ //
2
+ // NSUserActivity.swift
3
+ // Runner
4
+ //
5
+ // Created by Hien Nguyen on 20/02/2022.
6
+ //
7
+
8
+ import Foundation
9
+ import Intents
10
+
11
+ extension NSUserActivity: StartCallConvertible {
12
+
13
+ public var handle: String? {
14
+ guard
15
+ let interaction = interaction,
16
+ let startCallIntent = interaction.intent as? SupportedStartCallIntent,
17
+ let contact = startCallIntent.contacts?.first
18
+ else {
19
+ return nil
20
+ }
21
+ print(interaction.intent)
22
+ return contact.personHandle?.value
23
+ }
24
+
25
+ public var isVideo: Bool? {
26
+ guard
27
+ let interaction = interaction,
28
+ let startCallIntent = interaction.intent as? SupportedStartCallIntent
29
+ else {
30
+ return nil
31
+ }
32
+
33
+ return startCallIntent is INStartVideoCallIntent
34
+ }
35
+
36
+ }
37
+
38
+
39
+ protocol StartCallConvertible {
40
+ var handle: String? { get }
41
+ var isVideo: Bool? { get }
42
+ }
43
+
44
+ extension StartCallConvertible {
45
+
46
+ var isVideo: Bool? {
47
+ return nil
48
+ }
49
+
50
+ }
51
+
52
+
53
+ protocol SupportedStartCallIntent {
54
+ var contacts: [INPerson]? { get }
55
+ }
56
+
57
+ extension INStartAudioCallIntent: SupportedStartCallIntent {}
58
+ extension INStartVideoCallIntent: SupportedStartCallIntent {}
@@ -0,0 +1,18 @@
1
+
2
+ import Foundation
3
+
4
+ extension String {
5
+
6
+ func fromBase64() -> String {
7
+ guard let data = Foundation.Data(base64Encoded: self) else {
8
+ return ""
9
+ }
10
+
11
+ return String(data: data, encoding: .utf8)!
12
+ }
13
+
14
+ func toBase64() -> String {
15
+ return Foundation.Data(self.utf8).base64EncodedString()
16
+ }
17
+
18
+ }
@@ -0,0 +1,47 @@
1
+ //
2
+ // Constant.swift
3
+ // omicallsdk
4
+ //
5
+ // Created by LV on 12/12/2022.
6
+ //
7
+
8
+ import Foundation
9
+
10
+
11
+ let INIT_CALL = "INIT_CALL"
12
+ let UPDATE_TOKEN = "UPDATE_TOKEN"
13
+ let START_OMI_SERVICE = "START_OMI_SERVICE"
14
+ let START_CALL = "START_CALL"
15
+ let END_CALL = "END_CALL"
16
+ let TOGGLE_MUTE = "TOGGLE_MUTE"
17
+ let TOGGLE_SPEAK = "TOGGLE_SPEAK"
18
+ let CHECK_ON_GOING_CALL = "CHECK_ON_GOING_CALL"
19
+ let DECLINE = "DECLINE"
20
+ let FORWARD_CALL_TO = "FORWARD_CALL_TO"
21
+ let HANGUP = "HANGUP"
22
+ let ON_CALL_STARTED = "ON_CALL_STARTED"
23
+ let ON_HOLD = "ON_HOLD"
24
+ let ON_IN_COMING_RECEIVE = "ON_IN_COMING_RECEIVE"
25
+ let ON_MUTE = "ON_MUTE"
26
+ let ON_OUT_GOING = "ON_OUT_GOING"
27
+ let ON_OUT_GOING_STARTED = "ON_OUT_GOING"
28
+ let REGISTER = "REGISTER"
29
+ let SEND_DTMF = "SEND_DTMF"
30
+ let SWITCH_CAMERA = "SWITCH_CAMERA"
31
+ let CAMERA_STATUS = "CAMERA_STATUS"
32
+ let TOGGLE_VIDEO = "TOGGLE_VIDEO"
33
+ let INPUTS = "INPUTS"
34
+ let OUTPUTS = "OUTOUTS"
35
+ let SETINPUT = "SET_INPUT"
36
+ let SETOUTPUT = "SET_OUTPUT"
37
+
38
+ //LISTENER
39
+ let onCallEstablished = "CALL_ESTABLISHED"
40
+ let onCallEnd = "CALL_END"
41
+ let incomingReceived = "INCOMING_RECEIVED"
42
+ let onRinging = "RINGING"
43
+ let onConnectionTimeout = "CONNECTION_TIMEOUT"
44
+ let onHold = "HOLD"
45
+ let onMuted = "MUTED"
46
+
47
+
@@ -0,0 +1,2 @@
1
+ #import <React/RCTBridgeModule.h>
2
+ #import <React/RCTViewManager.h>
@@ -0,0 +1,17 @@
1
+ #import <React/RCTBridgeModule.h>
2
+
3
+ @interface RCT_EXTERN_MODULE(OmikitPlugin, NSObject)
4
+
5
+ RCT_EXTERN_METHOD(updateToken:(id)data
6
+ withResolver:(RCTPromiseResolveBlock)resolve
7
+ withRejecter:(RCTPromiseRejectBlock)reject)
8
+ RCT_EXTERN_METHOD(initCall:(id)data
9
+ withResolver:(RCTPromiseResolveBlock)resolve
10
+ withRejecter:(RCTPromiseRejectBlock)reject)
11
+
12
+ + (BOOL)requiresMainQueueSetup
13
+ {
14
+ return NO;
15
+ }
16
+
17
+ @end
@@ -0,0 +1,19 @@
1
+ import Foundation
2
+
3
+ @objc(OmikitPlugin)
4
+ class OmikitPlugin: NSObject {
5
+ @objc(initCall:withResolver:withRejecter:)
6
+ func initCall(data: Any, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
7
+ if let dataOmi = data as? [String: Any] {
8
+ CallManager.shareInstance().initEndpoint(params: dataOmi)
9
+ resolve(true)
10
+ }
11
+ }
12
+ @objc(updateToken:withResolver:withRejecter:)
13
+ func updateToken(data: Any, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
14
+ if let dataOmi = data as? [String: Any] {
15
+ CallManager.shareInstance().updateToken(params: dataOmi)
16
+ resolve(true)
17
+ }
18
+ }
19
+ }