@kapsula-chat/capacitor-push-calls 1.0.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.
- package/Package.swift +31 -0
- package/README.md +252 -0
- package/android/build.gradle +46 -0
- package/android/src/main/AndroidManifest.xml +31 -0
- package/android/src/main/java/com/capacitor/voipcalls/CallManager.kt +213 -0
- package/android/src/main/java/com/capacitor/voipcalls/CapacitorVoipCallsPlugin.kt +584 -0
- package/android/src/main/java/com/capacitor/voipcalls/PushRouterMessagingService.kt +26 -0
- package/android/src/main/java/com/capacitor/voipcalls/VoipConnection.kt +112 -0
- package/android/src/main/java/com/capacitor/voipcalls/VoipConnectionService.kt +101 -0
- package/dist/esm/definitions.d.ts +279 -0
- package/dist/esm/definitions.d.ts.map +1 -0
- package/dist/esm/definitions.js +1 -0
- package/dist/esm/index.d.ts +5 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +6 -0
- package/dist/esm/web.d.ts +67 -0
- package/dist/esm/web.d.ts.map +1 -0
- package/dist/esm/web.js +81 -0
- package/dist/plugin.cjs.js +96 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +99 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Plugin/CallManager.swift +226 -0
- package/ios/Plugin/CapacitorVoipCallsPlugin.swift +517 -0
- package/ios/Plugin/Plugin.m +31 -0
- package/package.json +95 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var core = require('@capacitor/core');
|
|
4
|
+
|
|
5
|
+
const CapacitorPushCalls = core.registerPlugin('CapacitorPushCalls', {
|
|
6
|
+
web: () => Promise.resolve().then(function () { return web; }).then(m => new m.CapacitorPushCallsWeb()),
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
class CapacitorPushCallsWeb extends core.WebPlugin {
|
|
10
|
+
async register() {
|
|
11
|
+
throw this.unimplemented('Push notifications not supported on web');
|
|
12
|
+
}
|
|
13
|
+
async unregister() {
|
|
14
|
+
throw this.unimplemented('Push notifications not supported on web');
|
|
15
|
+
}
|
|
16
|
+
async requestPermissions() {
|
|
17
|
+
return { receive: 'denied' };
|
|
18
|
+
}
|
|
19
|
+
async checkPermissions() {
|
|
20
|
+
return { receive: 'denied' };
|
|
21
|
+
}
|
|
22
|
+
async getDeliveredNotifications() {
|
|
23
|
+
return { notifications: [] };
|
|
24
|
+
}
|
|
25
|
+
async removeDeliveredNotifications(_options) {
|
|
26
|
+
throw this.unimplemented('Push notifications not supported on web');
|
|
27
|
+
}
|
|
28
|
+
async removeAllDeliveredNotifications() {
|
|
29
|
+
throw this.unimplemented('Push notifications not supported on web');
|
|
30
|
+
}
|
|
31
|
+
async getBadgeCount() {
|
|
32
|
+
return { count: 0 };
|
|
33
|
+
}
|
|
34
|
+
async getBadgeNumber() {
|
|
35
|
+
return this.getBadgeCount();
|
|
36
|
+
}
|
|
37
|
+
async setBadgeCount(_options) {
|
|
38
|
+
throw this.unimplemented('Badge count not supported on web');
|
|
39
|
+
}
|
|
40
|
+
async setBadgeNumber(options) {
|
|
41
|
+
return this.setBadgeCount(options);
|
|
42
|
+
}
|
|
43
|
+
async clearBadgeCount() {
|
|
44
|
+
throw this.unimplemented('Badge count not supported on web');
|
|
45
|
+
}
|
|
46
|
+
async createChannel(_channel) {
|
|
47
|
+
throw this.unimplemented('Notification channels not supported on web');
|
|
48
|
+
}
|
|
49
|
+
async deleteChannel(_options) {
|
|
50
|
+
throw this.unimplemented('Notification channels not supported on web');
|
|
51
|
+
}
|
|
52
|
+
async listChannels() {
|
|
53
|
+
return { channels: [] };
|
|
54
|
+
}
|
|
55
|
+
async registerVoipNotifications() {
|
|
56
|
+
throw this.unimplemented('VoIP notifications not supported on web');
|
|
57
|
+
}
|
|
58
|
+
async startCall(_options) {
|
|
59
|
+
throw this.unimplemented('Native calls not supported on web');
|
|
60
|
+
}
|
|
61
|
+
async endCall(_options) {
|
|
62
|
+
throw this.unimplemented('Native calls not supported on web');
|
|
63
|
+
}
|
|
64
|
+
async answerCall(_options) {
|
|
65
|
+
throw this.unimplemented('Native calls not supported on web');
|
|
66
|
+
}
|
|
67
|
+
async rejectCall(_options) {
|
|
68
|
+
throw this.unimplemented('Native calls not supported on web');
|
|
69
|
+
}
|
|
70
|
+
async setCallOnHold(_options) {
|
|
71
|
+
throw this.unimplemented('Call hold not supported on web');
|
|
72
|
+
}
|
|
73
|
+
async setAudioRoute(_options) {
|
|
74
|
+
throw this.unimplemented('Audio routing not supported on web');
|
|
75
|
+
}
|
|
76
|
+
async setMuted(_options) {
|
|
77
|
+
throw this.unimplemented('Mute not supported on web');
|
|
78
|
+
}
|
|
79
|
+
async handleIncomingCall(_options) {
|
|
80
|
+
throw this.unimplemented('Incoming calls not supported on web');
|
|
81
|
+
}
|
|
82
|
+
async updateCallStatus(_options) {
|
|
83
|
+
throw this.unimplemented('Call status updates not supported on web');
|
|
84
|
+
}
|
|
85
|
+
async isSupported() {
|
|
86
|
+
return { supported: false };
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
var web = /*#__PURE__*/Object.freeze({
|
|
91
|
+
__proto__: null,
|
|
92
|
+
CapacitorPushCallsWeb: CapacitorPushCallsWeb
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
exports.CapacitorPushCalls = CapacitorPushCalls;
|
|
96
|
+
//# sourceMappingURL=plugin.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst CapacitorPushCalls = registerPlugin('CapacitorPushCalls', {\n web: () => import('./web').then(m => new m.CapacitorPushCallsWeb()),\n});\nexport * from './definitions';\nexport { CapacitorPushCalls };\n","import { WebPlugin } from '@capacitor/core';\nexport class CapacitorPushCallsWeb extends WebPlugin {\n async register() {\n throw this.unimplemented('Push notifications not supported on web');\n }\n async unregister() {\n throw this.unimplemented('Push notifications not supported on web');\n }\n async requestPermissions() {\n return { receive: 'denied' };\n }\n async checkPermissions() {\n return { receive: 'denied' };\n }\n async getDeliveredNotifications() {\n return { notifications: [] };\n }\n async removeDeliveredNotifications(_options) {\n throw this.unimplemented('Push notifications not supported on web');\n }\n async removeAllDeliveredNotifications() {\n throw this.unimplemented('Push notifications not supported on web');\n }\n async getBadgeCount() {\n return { count: 0 };\n }\n async getBadgeNumber() {\n return this.getBadgeCount();\n }\n async setBadgeCount(_options) {\n throw this.unimplemented('Badge count not supported on web');\n }\n async setBadgeNumber(options) {\n return this.setBadgeCount(options);\n }\n async clearBadgeCount() {\n throw this.unimplemented('Badge count not supported on web');\n }\n async createChannel(_channel) {\n throw this.unimplemented('Notification channels not supported on web');\n }\n async deleteChannel(_options) {\n throw this.unimplemented('Notification channels not supported on web');\n }\n async listChannels() {\n return { channels: [] };\n }\n async registerVoipNotifications() {\n throw this.unimplemented('VoIP notifications not supported on web');\n }\n async startCall(_options) {\n throw this.unimplemented('Native calls not supported on web');\n }\n async endCall(_options) {\n throw this.unimplemented('Native calls not supported on web');\n }\n async answerCall(_options) {\n throw this.unimplemented('Native calls not supported on web');\n }\n async rejectCall(_options) {\n throw this.unimplemented('Native calls not supported on web');\n }\n async setCallOnHold(_options) {\n throw this.unimplemented('Call hold not supported on web');\n }\n async setAudioRoute(_options) {\n throw this.unimplemented('Audio routing not supported on web');\n }\n async setMuted(_options) {\n throw this.unimplemented('Mute not supported on web');\n }\n async handleIncomingCall(_options) {\n throw this.unimplemented('Incoming calls not supported on web');\n }\n async updateCallStatus(_options) {\n throw this.unimplemented('Call status updates not supported on web');\n }\n async isSupported() {\n return { supported: false };\n }\n}\n"],"names":["registerPlugin","WebPlugin"],"mappings":"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"}
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
var capacitorVoipCalls = (function (exports, core) {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const CapacitorPushCalls = core.registerPlugin('CapacitorPushCalls', {
|
|
5
|
+
web: () => Promise.resolve().then(function () { return web; }).then(m => new m.CapacitorPushCallsWeb()),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
class CapacitorPushCallsWeb extends core.WebPlugin {
|
|
9
|
+
async register() {
|
|
10
|
+
throw this.unimplemented('Push notifications not supported on web');
|
|
11
|
+
}
|
|
12
|
+
async unregister() {
|
|
13
|
+
throw this.unimplemented('Push notifications not supported on web');
|
|
14
|
+
}
|
|
15
|
+
async requestPermissions() {
|
|
16
|
+
return { receive: 'denied' };
|
|
17
|
+
}
|
|
18
|
+
async checkPermissions() {
|
|
19
|
+
return { receive: 'denied' };
|
|
20
|
+
}
|
|
21
|
+
async getDeliveredNotifications() {
|
|
22
|
+
return { notifications: [] };
|
|
23
|
+
}
|
|
24
|
+
async removeDeliveredNotifications(_options) {
|
|
25
|
+
throw this.unimplemented('Push notifications not supported on web');
|
|
26
|
+
}
|
|
27
|
+
async removeAllDeliveredNotifications() {
|
|
28
|
+
throw this.unimplemented('Push notifications not supported on web');
|
|
29
|
+
}
|
|
30
|
+
async getBadgeCount() {
|
|
31
|
+
return { count: 0 };
|
|
32
|
+
}
|
|
33
|
+
async getBadgeNumber() {
|
|
34
|
+
return this.getBadgeCount();
|
|
35
|
+
}
|
|
36
|
+
async setBadgeCount(_options) {
|
|
37
|
+
throw this.unimplemented('Badge count not supported on web');
|
|
38
|
+
}
|
|
39
|
+
async setBadgeNumber(options) {
|
|
40
|
+
return this.setBadgeCount(options);
|
|
41
|
+
}
|
|
42
|
+
async clearBadgeCount() {
|
|
43
|
+
throw this.unimplemented('Badge count not supported on web');
|
|
44
|
+
}
|
|
45
|
+
async createChannel(_channel) {
|
|
46
|
+
throw this.unimplemented('Notification channels not supported on web');
|
|
47
|
+
}
|
|
48
|
+
async deleteChannel(_options) {
|
|
49
|
+
throw this.unimplemented('Notification channels not supported on web');
|
|
50
|
+
}
|
|
51
|
+
async listChannels() {
|
|
52
|
+
return { channels: [] };
|
|
53
|
+
}
|
|
54
|
+
async registerVoipNotifications() {
|
|
55
|
+
throw this.unimplemented('VoIP notifications not supported on web');
|
|
56
|
+
}
|
|
57
|
+
async startCall(_options) {
|
|
58
|
+
throw this.unimplemented('Native calls not supported on web');
|
|
59
|
+
}
|
|
60
|
+
async endCall(_options) {
|
|
61
|
+
throw this.unimplemented('Native calls not supported on web');
|
|
62
|
+
}
|
|
63
|
+
async answerCall(_options) {
|
|
64
|
+
throw this.unimplemented('Native calls not supported on web');
|
|
65
|
+
}
|
|
66
|
+
async rejectCall(_options) {
|
|
67
|
+
throw this.unimplemented('Native calls not supported on web');
|
|
68
|
+
}
|
|
69
|
+
async setCallOnHold(_options) {
|
|
70
|
+
throw this.unimplemented('Call hold not supported on web');
|
|
71
|
+
}
|
|
72
|
+
async setAudioRoute(_options) {
|
|
73
|
+
throw this.unimplemented('Audio routing not supported on web');
|
|
74
|
+
}
|
|
75
|
+
async setMuted(_options) {
|
|
76
|
+
throw this.unimplemented('Mute not supported on web');
|
|
77
|
+
}
|
|
78
|
+
async handleIncomingCall(_options) {
|
|
79
|
+
throw this.unimplemented('Incoming calls not supported on web');
|
|
80
|
+
}
|
|
81
|
+
async updateCallStatus(_options) {
|
|
82
|
+
throw this.unimplemented('Call status updates not supported on web');
|
|
83
|
+
}
|
|
84
|
+
async isSupported() {
|
|
85
|
+
return { supported: false };
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
var web = /*#__PURE__*/Object.freeze({
|
|
90
|
+
__proto__: null,
|
|
91
|
+
CapacitorPushCallsWeb: CapacitorPushCallsWeb
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
exports.CapacitorPushCalls = CapacitorPushCalls;
|
|
95
|
+
|
|
96
|
+
return exports;
|
|
97
|
+
|
|
98
|
+
})({}, capacitorExports);
|
|
99
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst CapacitorPushCalls = registerPlugin('CapacitorPushCalls', {\n web: () => import('./web').then(m => new m.CapacitorPushCallsWeb()),\n});\nexport * from './definitions';\nexport { CapacitorPushCalls };\n","import { WebPlugin } from '@capacitor/core';\nexport class CapacitorPushCallsWeb extends WebPlugin {\n async register() {\n throw this.unimplemented('Push notifications not supported on web');\n }\n async unregister() {\n throw this.unimplemented('Push notifications not supported on web');\n }\n async requestPermissions() {\n return { receive: 'denied' };\n }\n async checkPermissions() {\n return { receive: 'denied' };\n }\n async getDeliveredNotifications() {\n return { notifications: [] };\n }\n async removeDeliveredNotifications(_options) {\n throw this.unimplemented('Push notifications not supported on web');\n }\n async removeAllDeliveredNotifications() {\n throw this.unimplemented('Push notifications not supported on web');\n }\n async getBadgeCount() {\n return { count: 0 };\n }\n async getBadgeNumber() {\n return this.getBadgeCount();\n }\n async setBadgeCount(_options) {\n throw this.unimplemented('Badge count not supported on web');\n }\n async setBadgeNumber(options) {\n return this.setBadgeCount(options);\n }\n async clearBadgeCount() {\n throw this.unimplemented('Badge count not supported on web');\n }\n async createChannel(_channel) {\n throw this.unimplemented('Notification channels not supported on web');\n }\n async deleteChannel(_options) {\n throw this.unimplemented('Notification channels not supported on web');\n }\n async listChannels() {\n return { channels: [] };\n }\n async registerVoipNotifications() {\n throw this.unimplemented('VoIP notifications not supported on web');\n }\n async startCall(_options) {\n throw this.unimplemented('Native calls not supported on web');\n }\n async endCall(_options) {\n throw this.unimplemented('Native calls not supported on web');\n }\n async answerCall(_options) {\n throw this.unimplemented('Native calls not supported on web');\n }\n async rejectCall(_options) {\n throw this.unimplemented('Native calls not supported on web');\n }\n async setCallOnHold(_options) {\n throw this.unimplemented('Call hold not supported on web');\n }\n async setAudioRoute(_options) {\n throw this.unimplemented('Audio routing not supported on web');\n }\n async setMuted(_options) {\n throw this.unimplemented('Mute not supported on web');\n }\n async handleIncomingCall(_options) {\n throw this.unimplemented('Incoming calls not supported on web');\n }\n async updateCallStatus(_options) {\n throw this.unimplemented('Call status updates not supported on web');\n }\n async isSupported() {\n return { supported: false };\n }\n}\n"],"names":["registerPlugin","WebPlugin"],"mappings":"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"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import CallKit
|
|
3
|
+
import AVFoundation
|
|
4
|
+
|
|
5
|
+
@available(iOS 13.0, *)
|
|
6
|
+
class CallManager: NSObject {
|
|
7
|
+
private let callController = CXCallController()
|
|
8
|
+
private let provider: CXProvider
|
|
9
|
+
private weak var plugin: CapacitorVoipCallsPlugin?
|
|
10
|
+
|
|
11
|
+
private var activeCalls: [UUID: Call] = [:]
|
|
12
|
+
|
|
13
|
+
struct Call {
|
|
14
|
+
let uuid: UUID
|
|
15
|
+
let handle: String
|
|
16
|
+
let displayName: String
|
|
17
|
+
var isOnHold: Bool = false
|
|
18
|
+
var isOutgoing: Bool = false
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
init(plugin: CapacitorVoipCallsPlugin) {
|
|
22
|
+
self.plugin = plugin
|
|
23
|
+
|
|
24
|
+
let configuration: CXProviderConfiguration
|
|
25
|
+
if #available(iOS 14.0, *) {
|
|
26
|
+
configuration = CXProviderConfiguration()
|
|
27
|
+
} else {
|
|
28
|
+
configuration = CXProviderConfiguration(localizedName: "App Calls")
|
|
29
|
+
}
|
|
30
|
+
configuration.supportsVideo = true
|
|
31
|
+
configuration.maximumCallGroups = 1
|
|
32
|
+
configuration.maximumCallsPerCallGroup = 1
|
|
33
|
+
configuration.supportedHandleTypes = [.generic, .phoneNumber, .emailAddress]
|
|
34
|
+
|
|
35
|
+
// Configure audio
|
|
36
|
+
configuration.includesCallsInRecents = true
|
|
37
|
+
|
|
38
|
+
self.provider = CXProvider(configuration: configuration)
|
|
39
|
+
|
|
40
|
+
super.init()
|
|
41
|
+
|
|
42
|
+
provider.setDelegate(self, queue: nil)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// MARK: - Start Outgoing Call
|
|
46
|
+
func startCall(uuid: UUID, handle: String, displayName: String, handleType: CXHandle.HandleType, video: Bool) {
|
|
47
|
+
let call = Call(uuid: uuid, handle: handle, displayName: displayName, isOutgoing: true)
|
|
48
|
+
activeCalls[uuid] = call
|
|
49
|
+
|
|
50
|
+
let cxHandle = CXHandle(type: handleType, value: handle)
|
|
51
|
+
let startCallAction = CXStartCallAction(call: uuid, handle: cxHandle)
|
|
52
|
+
startCallAction.isVideo = video
|
|
53
|
+
startCallAction.contactIdentifier = displayName
|
|
54
|
+
|
|
55
|
+
let transaction = CXTransaction(action: startCallAction)
|
|
56
|
+
|
|
57
|
+
callController.request(transaction) { error in
|
|
58
|
+
if let error = error {
|
|
59
|
+
print("Error starting call: \(error.localizedDescription)")
|
|
60
|
+
self.activeCalls.removeValue(forKey: uuid)
|
|
61
|
+
} else {
|
|
62
|
+
print("Successfully requested start call")
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// MARK: - Report Incoming Call
|
|
68
|
+
func reportIncomingCall(uuid: UUID, handle: String, displayName: String, handleType: CXHandle.HandleType, video: Bool, completion: @escaping (Error?) -> Void) {
|
|
69
|
+
let call = Call(uuid: uuid, handle: handle, displayName: displayName, isOutgoing: false)
|
|
70
|
+
activeCalls[uuid] = call
|
|
71
|
+
|
|
72
|
+
let update = CXCallUpdate()
|
|
73
|
+
update.remoteHandle = CXHandle(type: handleType, value: handle)
|
|
74
|
+
update.localizedCallerName = displayName
|
|
75
|
+
update.supportsHolding = true
|
|
76
|
+
update.supportsGrouping = false
|
|
77
|
+
update.supportsUngrouping = false
|
|
78
|
+
update.supportsDTMF = true
|
|
79
|
+
update.hasVideo = video
|
|
80
|
+
|
|
81
|
+
provider.reportNewIncomingCall(with: uuid, update: update) { error in
|
|
82
|
+
if let error = error {
|
|
83
|
+
self.activeCalls.removeValue(forKey: uuid)
|
|
84
|
+
}
|
|
85
|
+
completion(error)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// MARK: - End Call
|
|
90
|
+
func endCall(uuid: UUID) {
|
|
91
|
+
let endCallAction = CXEndCallAction(call: uuid)
|
|
92
|
+
let transaction = CXTransaction(action: endCallAction)
|
|
93
|
+
|
|
94
|
+
callController.request(transaction) { error in
|
|
95
|
+
if let error = error {
|
|
96
|
+
print("Error ending call: \(error.localizedDescription)")
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// MARK: - Answer Call
|
|
102
|
+
func answerCall(uuid: UUID) {
|
|
103
|
+
let answerCallAction = CXAnswerCallAction(call: uuid)
|
|
104
|
+
let transaction = CXTransaction(action: answerCallAction)
|
|
105
|
+
|
|
106
|
+
callController.request(transaction) { error in
|
|
107
|
+
if let error = error {
|
|
108
|
+
print("Error answering call: \(error.localizedDescription)")
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// MARK: - Reject Call
|
|
114
|
+
func rejectCall(uuid: UUID) {
|
|
115
|
+
endCall(uuid: uuid)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// MARK: - Hold Call
|
|
119
|
+
func setCallOnHold(uuid: UUID, onHold: Bool) {
|
|
120
|
+
let setHeldCallAction = CXSetHeldCallAction(call: uuid, onHold: onHold)
|
|
121
|
+
let transaction = CXTransaction(action: setHeldCallAction)
|
|
122
|
+
|
|
123
|
+
callController.request(transaction) { error in
|
|
124
|
+
if let error = error {
|
|
125
|
+
print("Error setting call on hold: \(error.localizedDescription)")
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// MARK: - Update Call Status
|
|
131
|
+
func updateCallStatus(uuid: UUID, status: String) {
|
|
132
|
+
let update = CXCallUpdate()
|
|
133
|
+
|
|
134
|
+
switch status {
|
|
135
|
+
case "connecting":
|
|
136
|
+
update.localizedCallerName = activeCalls[uuid]?.displayName ?? "Connecting..."
|
|
137
|
+
case "connected":
|
|
138
|
+
provider.reportOutgoingCall(with: uuid, connectedAt: Date())
|
|
139
|
+
case "failed":
|
|
140
|
+
provider.reportCall(with: uuid, endedAt: Date(), reason: .failed)
|
|
141
|
+
activeCalls.removeValue(forKey: uuid)
|
|
142
|
+
case "disconnected":
|
|
143
|
+
provider.reportCall(with: uuid, endedAt: Date(), reason: .remoteEnded)
|
|
144
|
+
activeCalls.removeValue(forKey: uuid)
|
|
145
|
+
default:
|
|
146
|
+
break
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// MARK: - Configure Audio Session
|
|
151
|
+
private func configureAudioSession() {
|
|
152
|
+
let audioSession = AVAudioSession.sharedInstance()
|
|
153
|
+
do {
|
|
154
|
+
try audioSession.setCategory(.playAndRecord, mode: .voiceChat, options: [.allowBluetooth, .allowBluetoothA2DP])
|
|
155
|
+
try audioSession.setActive(true)
|
|
156
|
+
} catch {
|
|
157
|
+
print("Failed to configure audio session: \(error.localizedDescription)")
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// MARK: - CXProviderDelegate
|
|
163
|
+
extension CallManager: CXProviderDelegate {
|
|
164
|
+
func providerDidReset(_ provider: CXProvider) {
|
|
165
|
+
activeCalls.removeAll()
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
func provider(_ provider: CXProvider, perform action: CXStartCallAction) {
|
|
169
|
+
configureAudioSession()
|
|
170
|
+
|
|
171
|
+
// Start in "connecting" state; app should mark as connected via updateCallStatus.
|
|
172
|
+
provider.reportOutgoingCall(with: action.callUUID, startedConnectingAt: Date())
|
|
173
|
+
plugin?.notifyListeners(event: "callStarted", data: ["callId": action.callUUID.uuidString])
|
|
174
|
+
|
|
175
|
+
action.fulfill()
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
|
|
179
|
+
configureAudioSession()
|
|
180
|
+
|
|
181
|
+
plugin?.notifyListeners(event: "callAnswered", data: ["callId": action.callUUID.uuidString])
|
|
182
|
+
|
|
183
|
+
action.fulfill()
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
|
|
187
|
+
activeCalls.removeValue(forKey: action.callUUID)
|
|
188
|
+
|
|
189
|
+
plugin?.notifyListeners(event: "callEnded", data: ["callId": action.callUUID.uuidString])
|
|
190
|
+
|
|
191
|
+
action.fulfill()
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
func provider(_ provider: CXProvider, perform action: CXSetHeldCallAction) {
|
|
195
|
+
if var call = activeCalls[action.callUUID] {
|
|
196
|
+
call.isOnHold = action.isOnHold
|
|
197
|
+
activeCalls[action.callUUID] = call
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
plugin?.notifyListeners(event: "callHeld", data: [
|
|
201
|
+
"callId": action.callUUID.uuidString,
|
|
202
|
+
"onHold": action.isOnHold
|
|
203
|
+
])
|
|
204
|
+
|
|
205
|
+
action.fulfill()
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
func provider(_ provider: CXProvider, perform action: CXSetMutedCallAction) {
|
|
209
|
+
// Mute handling should be implemented in your media layer
|
|
210
|
+
action.fulfill()
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
func provider(_ provider: CXProvider, timedOutPerforming action: CXAction) {
|
|
214
|
+
print("Action timed out: \(action)")
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) {
|
|
218
|
+
print("Audio session activated")
|
|
219
|
+
// Start your audio processing here
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
func provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) {
|
|
223
|
+
print("Audio session deactivated")
|
|
224
|
+
// Stop your audio processing here
|
|
225
|
+
}
|
|
226
|
+
}
|