expo-callkit-telecom 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.
- package/LICENSE +21 -0
- package/README.md +197 -0
- package/android/build.gradle +32 -0
- package/android/src/main/AndroidManifest.xml +33 -0
- package/android/src/main/java/expo/modules/callkittelecom/ExpoCallKitTelecomModule.kt +384 -0
- package/android/src/main/java/expo/modules/callkittelecom/IncomingCallActivity.kt +275 -0
- package/android/src/main/java/expo/modules/callkittelecom/events/CallEventEmitter.kt +151 -0
- package/android/src/main/java/expo/modules/callkittelecom/events/CallEvents.kt +59 -0
- package/android/src/main/java/expo/modules/callkittelecom/managers/CallAudioManager.kt +361 -0
- package/android/src/main/java/expo/modules/callkittelecom/managers/CallManager.kt +891 -0
- package/android/src/main/java/expo/modules/callkittelecom/managers/CallNotificationManager.kt +445 -0
- package/android/src/main/java/expo/modules/callkittelecom/managers/CaptureSessionManager.kt +27 -0
- package/android/src/main/java/expo/modules/callkittelecom/managers/DialtonePlayer.kt +171 -0
- package/android/src/main/java/expo/modules/callkittelecom/managers/FulfillRequestManager.kt +150 -0
- package/android/src/main/java/expo/modules/callkittelecom/managers/VoIPPushManager.kt +54 -0
- package/android/src/main/java/expo/modules/callkittelecom/models/CallModels.kt +269 -0
- package/android/src/main/java/expo/modules/callkittelecom/services/CallNotificationReceiver.kt +54 -0
- package/android/src/main/java/expo/modules/callkittelecom/services/ExpoCallKitTelecomMessagingService.kt +161 -0
- package/android/src/main/java/expo/modules/callkittelecom/store/CallStore.kt +181 -0
- package/android/src/main/java/expo/modules/callkittelecom/utils/CallKitTelecomLog.kt +52 -0
- package/android/src/main/java/expo/modules/callkittelecom/utils/PermissionUtils.kt +28 -0
- package/android/src/main/res/drawable/expo_callkit_telecom_bg_answer.xml +9 -0
- package/android/src/main/res/drawable/expo_callkit_telecom_bg_avatar.xml +5 -0
- package/android/src/main/res/drawable/expo_callkit_telecom_bg_decline.xml +9 -0
- package/android/src/main/res/drawable/expo_callkit_telecom_ic_answer.xml +9 -0
- package/android/src/main/res/drawable/expo_callkit_telecom_ic_decline.xml +9 -0
- package/android/src/main/res/drawable/expo_callkit_telecom_ic_videocam.xml +9 -0
- package/android/src/main/res/layout/activity_incoming_call.xml +169 -0
- package/app.json +8 -0
- package/app.plugin.js +1 -0
- package/build/Calls.d.ts +577 -0
- package/build/Calls.d.ts.map +1 -0
- package/build/Calls.js +715 -0
- package/build/Calls.js.map +1 -0
- package/build/Calls.types.d.ts +203 -0
- package/build/Calls.types.d.ts.map +1 -0
- package/build/Calls.types.js +2 -0
- package/build/Calls.types.js.map +1 -0
- package/build/ExpoCallKitTelecomModule.d.ts +3 -0
- package/build/ExpoCallKitTelecomModule.d.ts.map +1 -0
- package/build/ExpoCallKitTelecomModule.js +4 -0
- package/build/ExpoCallKitTelecomModule.js.map +1 -0
- package/build/hooks/index.d.ts +2 -0
- package/build/hooks/index.d.ts.map +1 -0
- package/build/hooks/index.js +2 -0
- package/build/hooks/index.js.map +1 -0
- package/build/hooks/useVoIPPushToken.d.ts +14 -0
- package/build/hooks/useVoIPPushToken.d.ts.map +1 -0
- package/build/hooks/useVoIPPushToken.js +26 -0
- package/build/hooks/useVoIPPushToken.js.map +1 -0
- package/build/index.d.ts +4 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +4 -0
- package/build/index.js.map +1 -0
- package/expo-module.config.json +10 -0
- package/ios/AppDelegateSubscriber.swift +93 -0
- package/ios/ExpoCallKitTelecom.podspec +31 -0
- package/ios/ExpoCallKitTelecomLogger.swift +55 -0
- package/ios/ExpoCallKitTelecomModule.swift +503 -0
- package/ios/Managers/AudioManager.swift +363 -0
- package/ios/Managers/CallEventEmitter.swift +199 -0
- package/ios/Managers/CallManager+CXProviderDelegate.swift +195 -0
- package/ios/Managers/CallManager.swift +714 -0
- package/ios/Managers/CaptureSessionManager.swift +54 -0
- package/ios/Managers/DialtonePlayer.swift +126 -0
- package/ios/Managers/FulfillRequestManager.swift +154 -0
- package/ios/Managers/VoIPPushManager+PKPushRegistryDelegate.swift +123 -0
- package/ios/Managers/VoIPPushManager.swift +58 -0
- package/ios/Models/CallEvents.swift +263 -0
- package/ios/Models/CallOptions.swift +15 -0
- package/ios/Models/CallParticipant.swift +37 -0
- package/ios/Models/CallSession.swift +80 -0
- package/ios/Models/IncomingCallEvent.swift +196 -0
- package/ios/Stores/CallStore.swift +149 -0
- package/package.json +56 -0
- package/plugin/build/constants.d.ts +3 -0
- package/plugin/build/constants.js +7 -0
- package/plugin/build/withExpoCallKitTelecom.d.ts +67 -0
- package/plugin/build/withExpoCallKitTelecom.js +16 -0
- package/plugin/build/withExpoCallKitTelecomAndroid.d.ts +3 -0
- package/plugin/build/withExpoCallKitTelecomAndroid.js +177 -0
- package/plugin/build/withExpoCallKitTelecomIos.d.ts +3 -0
- package/plugin/build/withExpoCallKitTelecomIos.js +195 -0
- package/plugin/src/constants.ts +4 -0
- package/plugin/src/withExpoCallKitTelecom.ts +83 -0
- package/plugin/src/withExpoCallKitTelecomAndroid.ts +293 -0
- package/plugin/src/withExpoCallKitTelecomIos.ts +276 -0
- package/src/Calls.ts +848 -0
- package/src/Calls.types.ts +275 -0
- package/src/ExpoCallKitTelecomModule.ts +4 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useVoIPPushToken.ts +34 -0
- package/src/index.ts +3 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import AVFoundation
|
|
2
|
+
import CallKit
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
extension CallManager: CXProviderDelegate {
|
|
6
|
+
|
|
7
|
+
/// Timeout for waiting for the call to connect after answering.
|
|
8
|
+
private static let answerCallTimeout: Duration = {
|
|
9
|
+
let seconds =
|
|
10
|
+
Bundle.main.object(
|
|
11
|
+
forInfoDictionaryKey: "ExpoCallKitTelecomFulfillAnswerCallTimeout"
|
|
12
|
+
) as? Int ?? 30
|
|
13
|
+
return .seconds(seconds)
|
|
14
|
+
}()
|
|
15
|
+
|
|
16
|
+
// MARK: - providerDidReset
|
|
17
|
+
|
|
18
|
+
func providerDidReset(_ provider: CXProvider) {
|
|
19
|
+
Log.call.debug("Provider did reset - removing all sessions")
|
|
20
|
+
DialtonePlayer.shared.stop()
|
|
21
|
+
cancelAllCallTimeouts()
|
|
22
|
+
Task {
|
|
23
|
+
await FulfillRequestManager.shared.cancelAll()
|
|
24
|
+
await store.removeAll()
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// MARK: - CXStartCallAction
|
|
29
|
+
|
|
30
|
+
func provider(_ provider: CXProvider, perform action: CXStartCallAction) {
|
|
31
|
+
Log.call.debug("CXStartCallAction - id: \(action.callUUID), isVideo: \(action.isVideo)")
|
|
32
|
+
provider.reportOutgoingCall(with: action.callUUID, startedConnectingAt: Date())
|
|
33
|
+
|
|
34
|
+
// Start timeout timer for outgoing call
|
|
35
|
+
startCallTimeout(for: action.callUUID, timeout: Self.outgoingCallTimeout)
|
|
36
|
+
|
|
37
|
+
Task {
|
|
38
|
+
if let session = await store.session(for: action.callUUID),
|
|
39
|
+
let participant = session.remoteParticipants.first
|
|
40
|
+
{
|
|
41
|
+
let update = CXCallUpdate()
|
|
42
|
+
setLocalizedCallerNameIfNeeded(for: participant, on: update)
|
|
43
|
+
provider.reportCall(with: action.callUUID, updated: update)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
await store.updateStatus(for: action.callUUID, status: .connecting)
|
|
47
|
+
|
|
48
|
+
await MainActor.run {
|
|
49
|
+
CallEventEmitter.shared.send(OutgoingCallStartedEvent(id: action.callUUID))
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
action.fulfill()
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// MARK: - CXAnswerCallAction
|
|
57
|
+
|
|
58
|
+
func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
|
|
59
|
+
Log.call.debug("CXAnswerCallAction - id: \(action.callUUID)")
|
|
60
|
+
|
|
61
|
+
// Cancel the incoming call timeout since user answered
|
|
62
|
+
cancelCallTimeout(for: action.callUUID)
|
|
63
|
+
|
|
64
|
+
Task {
|
|
65
|
+
await store.updateStatus(for: action.callUUID, status: .connecting)
|
|
66
|
+
|
|
67
|
+
// Create pending fulfill request with associated call ID
|
|
68
|
+
let (requestId, resultTask) = await FulfillRequestManager.shared.createRequest(
|
|
69
|
+
callId: action.callUUID,
|
|
70
|
+
timeout: Self.answerCallTimeout
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
// Send event with request ID
|
|
74
|
+
await MainActor.run {
|
|
75
|
+
CallEventEmitter.shared.send(
|
|
76
|
+
CallAnsweredEvent(id: action.callUUID, requestId: requestId)
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Wait for fulfill or timeout
|
|
81
|
+
let result = await resultTask.value
|
|
82
|
+
|
|
83
|
+
switch result {
|
|
84
|
+
case .fulfilled:
|
|
85
|
+
Log.call.debug("CXAnswerCallAction fulfilled - id: \(action.callUUID)")
|
|
86
|
+
action.fulfill()
|
|
87
|
+
case .cancelled:
|
|
88
|
+
Log.call.debug("CXAnswerCallAction failed - cancelled - id: \(action.callUUID)")
|
|
89
|
+
action.fail()
|
|
90
|
+
case .timedOut:
|
|
91
|
+
Log.call.debug("CXAnswerCallAction failed - timeout - id: \(action.callUUID)")
|
|
92
|
+
action.fail()
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// MARK: - CXEndCallAction
|
|
98
|
+
|
|
99
|
+
func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
|
|
100
|
+
Log.call.debug("CXEndCallAction - id: \(action.callUUID)")
|
|
101
|
+
|
|
102
|
+
// Stop dialtone and cancel timeout
|
|
103
|
+
DialtonePlayer.shared.stop()
|
|
104
|
+
cancelCallTimeout(for: action.callUUID)
|
|
105
|
+
|
|
106
|
+
Task {
|
|
107
|
+
await MainActor.run {
|
|
108
|
+
CallEventEmitter.shared.send(CallEndedEvent(id: action.callUUID))
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
await store.remove(for: action.callUUID)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
action.fulfill()
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// MARK: - CXSetMutedCallAction
|
|
118
|
+
|
|
119
|
+
func provider(_ provider: CXProvider, perform action: CXSetMutedCallAction) {
|
|
120
|
+
Log.call.debug("CXSetMutedCallAction - id: \(action.callUUID), isMuted: \(action.isMuted)")
|
|
121
|
+
|
|
122
|
+
Task {
|
|
123
|
+
await store.updateMuted(for: action.callUUID, isMuted: action.isMuted)
|
|
124
|
+
|
|
125
|
+
await MainActor.run {
|
|
126
|
+
CallEventEmitter.shared.send(
|
|
127
|
+
SetMutedActionEvent(id: action.callUUID, isMuted: action.isMuted))
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
action.fulfill()
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// MARK: - CXSetHeldCallAction
|
|
135
|
+
|
|
136
|
+
func provider(_ provider: CXProvider, perform action: CXSetHeldCallAction) {
|
|
137
|
+
Log.call.debug("CXSetHeldCallAction - id: \(action.callUUID), isOnHold: \(action.isOnHold)")
|
|
138
|
+
|
|
139
|
+
Task {
|
|
140
|
+
await store.updateHeld(for: action.callUUID, isOnHold: action.isOnHold)
|
|
141
|
+
|
|
142
|
+
await MainActor.run {
|
|
143
|
+
CallEventEmitter.shared.send(
|
|
144
|
+
SetHeldActionEvent(id: action.callUUID, isOnHold: action.isOnHold))
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
action.fulfill()
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// MARK: - CXPlayDTMFCallAction
|
|
152
|
+
|
|
153
|
+
func provider(_ provider: CXProvider, perform action: CXPlayDTMFCallAction) {
|
|
154
|
+
Log.call.debug("CXPlayDTMFCallAction - id: \(action.callUUID), length: \(action.digits.count)")
|
|
155
|
+
|
|
156
|
+
Task {
|
|
157
|
+
await MainActor.run {
|
|
158
|
+
CallEventEmitter.shared.send(DTMFEvent(id: action.callUUID, digits: action.digits))
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
action.fulfill()
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// MARK: - AVAudioSession didActivate
|
|
166
|
+
|
|
167
|
+
func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) {
|
|
168
|
+
Log.call.debug("CallKit audio session activated")
|
|
169
|
+
|
|
170
|
+
Task {
|
|
171
|
+
let sessions = await store.allSessions
|
|
172
|
+
AudioManager.shared.onAVAudioSessionActivated(calls: sessions)
|
|
173
|
+
|
|
174
|
+
// Play dialtone for outgoing calls that are still connecting
|
|
175
|
+
if let session = sessions.first,
|
|
176
|
+
session.origin == .outgoingApp || session.origin == .outgoingSystem,
|
|
177
|
+
session.status == .connecting
|
|
178
|
+
{
|
|
179
|
+
DialtonePlayer.shared.play()
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// MARK: - AVAudioSession didDeactivate
|
|
185
|
+
|
|
186
|
+
func provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) {
|
|
187
|
+
Log.call.debug("CallKit audio session deactivated")
|
|
188
|
+
DialtonePlayer.shared.stop()
|
|
189
|
+
|
|
190
|
+
Task {
|
|
191
|
+
let sessions = await store.allSessions
|
|
192
|
+
AudioManager.shared.onAVAudioSessionDeactivated(calls: sessions)
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|