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.
Files changed (93) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +197 -0
  3. package/android/build.gradle +32 -0
  4. package/android/src/main/AndroidManifest.xml +33 -0
  5. package/android/src/main/java/expo/modules/callkittelecom/ExpoCallKitTelecomModule.kt +384 -0
  6. package/android/src/main/java/expo/modules/callkittelecom/IncomingCallActivity.kt +275 -0
  7. package/android/src/main/java/expo/modules/callkittelecom/events/CallEventEmitter.kt +151 -0
  8. package/android/src/main/java/expo/modules/callkittelecom/events/CallEvents.kt +59 -0
  9. package/android/src/main/java/expo/modules/callkittelecom/managers/CallAudioManager.kt +361 -0
  10. package/android/src/main/java/expo/modules/callkittelecom/managers/CallManager.kt +891 -0
  11. package/android/src/main/java/expo/modules/callkittelecom/managers/CallNotificationManager.kt +445 -0
  12. package/android/src/main/java/expo/modules/callkittelecom/managers/CaptureSessionManager.kt +27 -0
  13. package/android/src/main/java/expo/modules/callkittelecom/managers/DialtonePlayer.kt +171 -0
  14. package/android/src/main/java/expo/modules/callkittelecom/managers/FulfillRequestManager.kt +150 -0
  15. package/android/src/main/java/expo/modules/callkittelecom/managers/VoIPPushManager.kt +54 -0
  16. package/android/src/main/java/expo/modules/callkittelecom/models/CallModels.kt +269 -0
  17. package/android/src/main/java/expo/modules/callkittelecom/services/CallNotificationReceiver.kt +54 -0
  18. package/android/src/main/java/expo/modules/callkittelecom/services/ExpoCallKitTelecomMessagingService.kt +161 -0
  19. package/android/src/main/java/expo/modules/callkittelecom/store/CallStore.kt +181 -0
  20. package/android/src/main/java/expo/modules/callkittelecom/utils/CallKitTelecomLog.kt +52 -0
  21. package/android/src/main/java/expo/modules/callkittelecom/utils/PermissionUtils.kt +28 -0
  22. package/android/src/main/res/drawable/expo_callkit_telecom_bg_answer.xml +9 -0
  23. package/android/src/main/res/drawable/expo_callkit_telecom_bg_avatar.xml +5 -0
  24. package/android/src/main/res/drawable/expo_callkit_telecom_bg_decline.xml +9 -0
  25. package/android/src/main/res/drawable/expo_callkit_telecom_ic_answer.xml +9 -0
  26. package/android/src/main/res/drawable/expo_callkit_telecom_ic_decline.xml +9 -0
  27. package/android/src/main/res/drawable/expo_callkit_telecom_ic_videocam.xml +9 -0
  28. package/android/src/main/res/layout/activity_incoming_call.xml +169 -0
  29. package/app.json +8 -0
  30. package/app.plugin.js +1 -0
  31. package/build/Calls.d.ts +577 -0
  32. package/build/Calls.d.ts.map +1 -0
  33. package/build/Calls.js +715 -0
  34. package/build/Calls.js.map +1 -0
  35. package/build/Calls.types.d.ts +203 -0
  36. package/build/Calls.types.d.ts.map +1 -0
  37. package/build/Calls.types.js +2 -0
  38. package/build/Calls.types.js.map +1 -0
  39. package/build/ExpoCallKitTelecomModule.d.ts +3 -0
  40. package/build/ExpoCallKitTelecomModule.d.ts.map +1 -0
  41. package/build/ExpoCallKitTelecomModule.js +4 -0
  42. package/build/ExpoCallKitTelecomModule.js.map +1 -0
  43. package/build/hooks/index.d.ts +2 -0
  44. package/build/hooks/index.d.ts.map +1 -0
  45. package/build/hooks/index.js +2 -0
  46. package/build/hooks/index.js.map +1 -0
  47. package/build/hooks/useVoIPPushToken.d.ts +14 -0
  48. package/build/hooks/useVoIPPushToken.d.ts.map +1 -0
  49. package/build/hooks/useVoIPPushToken.js +26 -0
  50. package/build/hooks/useVoIPPushToken.js.map +1 -0
  51. package/build/index.d.ts +4 -0
  52. package/build/index.d.ts.map +1 -0
  53. package/build/index.js +4 -0
  54. package/build/index.js.map +1 -0
  55. package/expo-module.config.json +10 -0
  56. package/ios/AppDelegateSubscriber.swift +93 -0
  57. package/ios/ExpoCallKitTelecom.podspec +31 -0
  58. package/ios/ExpoCallKitTelecomLogger.swift +55 -0
  59. package/ios/ExpoCallKitTelecomModule.swift +503 -0
  60. package/ios/Managers/AudioManager.swift +363 -0
  61. package/ios/Managers/CallEventEmitter.swift +199 -0
  62. package/ios/Managers/CallManager+CXProviderDelegate.swift +195 -0
  63. package/ios/Managers/CallManager.swift +714 -0
  64. package/ios/Managers/CaptureSessionManager.swift +54 -0
  65. package/ios/Managers/DialtonePlayer.swift +126 -0
  66. package/ios/Managers/FulfillRequestManager.swift +154 -0
  67. package/ios/Managers/VoIPPushManager+PKPushRegistryDelegate.swift +123 -0
  68. package/ios/Managers/VoIPPushManager.swift +58 -0
  69. package/ios/Models/CallEvents.swift +263 -0
  70. package/ios/Models/CallOptions.swift +15 -0
  71. package/ios/Models/CallParticipant.swift +37 -0
  72. package/ios/Models/CallSession.swift +80 -0
  73. package/ios/Models/IncomingCallEvent.swift +196 -0
  74. package/ios/Stores/CallStore.swift +149 -0
  75. package/package.json +56 -0
  76. package/plugin/build/constants.d.ts +3 -0
  77. package/plugin/build/constants.js +7 -0
  78. package/plugin/build/withExpoCallKitTelecom.d.ts +67 -0
  79. package/plugin/build/withExpoCallKitTelecom.js +16 -0
  80. package/plugin/build/withExpoCallKitTelecomAndroid.d.ts +3 -0
  81. package/plugin/build/withExpoCallKitTelecomAndroid.js +177 -0
  82. package/plugin/build/withExpoCallKitTelecomIos.d.ts +3 -0
  83. package/plugin/build/withExpoCallKitTelecomIos.js +195 -0
  84. package/plugin/src/constants.ts +4 -0
  85. package/plugin/src/withExpoCallKitTelecom.ts +83 -0
  86. package/plugin/src/withExpoCallKitTelecomAndroid.ts +293 -0
  87. package/plugin/src/withExpoCallKitTelecomIos.ts +276 -0
  88. package/src/Calls.ts +848 -0
  89. package/src/Calls.types.ts +275 -0
  90. package/src/ExpoCallKitTelecomModule.ts +4 -0
  91. package/src/hooks/index.ts +1 -0
  92. package/src/hooks/useVoIPPushToken.ts +34 -0
  93. 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
+ }