@stream-io/react-native-callingx 0.1.0-beta.6 → 0.1.1-beta.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/android/build.gradle +7 -1
- package/android/src/main/AndroidManifest.xml +31 -1
- package/android/src/main/java/io/getstream/rn/callingx/CallEventBroadcastReceiver.kt +17 -0
- package/android/src/main/java/io/getstream/rn/callingx/CallRegistrationStore.kt +176 -0
- package/android/src/main/java/io/getstream/rn/callingx/CallService.kt +302 -80
- package/android/src/main/java/io/getstream/rn/callingx/CallingxModuleImpl.kt +176 -191
- package/android/src/main/java/io/getstream/rn/callingx/StreamMessagingService.kt +48 -0
- package/android/src/main/java/io/getstream/rn/callingx/model/Call.kt +1 -0
- package/android/src/main/java/io/getstream/rn/callingx/notifications/CallNotificationManager.kt +196 -46
- package/android/src/main/java/io/getstream/rn/callingx/notifications/NotificationIntentFactory.kt +14 -8
- package/android/src/main/java/io/getstream/rn/callingx/notifications/NotificationReceiverActivity.kt +12 -1
- package/android/src/main/java/io/getstream/rn/callingx/notifications/NotificationReceiverService.kt +7 -0
- package/android/src/main/java/io/getstream/rn/callingx/repo/CallRepository.kt +38 -19
- package/android/src/main/java/io/getstream/rn/callingx/repo/LegacyCallRepository.kt +64 -55
- package/android/src/main/java/io/getstream/rn/callingx/repo/TelecomCallRepository.kt +241 -195
- package/android/src/main/java/io/getstream/rn/callingx/utils/CallEventBus.kt +61 -0
- package/android/src/main/java/io/getstream/rn/callingx/utils/SettingsStore.kt +51 -0
- package/android/src/newarch/java/io/getstream/rn/callingx/CallingxModule.kt +12 -3
- package/android/src/oldarch/java/io/getstream/rn/callingx/CallingxModule.kt +13 -3
- package/dist/module/CallingxModule.js +13 -10
- package/dist/module/CallingxModule.js.map +1 -1
- package/dist/module/spec/NativeCallingx.js.map +1 -1
- package/dist/module/utils/constants.js +24 -13
- package/dist/module/utils/constants.js.map +1 -1
- package/dist/typescript/src/CallingxModule.d.ts +3 -0
- package/dist/typescript/src/CallingxModule.d.ts.map +1 -1
- package/dist/typescript/src/spec/NativeCallingx.d.ts +7 -1
- package/dist/typescript/src/spec/NativeCallingx.d.ts.map +1 -1
- package/dist/typescript/src/types.d.ts +31 -0
- package/dist/typescript/src/types.d.ts.map +1 -1
- package/dist/typescript/src/utils/constants.d.ts +1 -1
- package/dist/typescript/src/utils/constants.d.ts.map +1 -1
- package/ios/AudioSessionManager.swift +2 -2
- package/ios/Callingx.mm +41 -17
- package/ios/CallingxImpl.swift +213 -83
- package/ios/Settings.swift +2 -2
- package/ios/UUIDStorage.swift +10 -10
- package/ios/VoipNotificationsManager.swift +8 -8
- package/package.json +4 -2
- package/src/CallingxModule.ts +14 -10
- package/src/spec/NativeCallingx.ts +10 -3
- package/src/types.ts +34 -0
- package/src/utils/constants.ts +23 -9
- package/android/bin/build/generated/source/buildConfig/debug/io/getstream/rn/callingx/BuildConfig.class +0 -0
- package/android/bin/build/generated/source/codegen/java/io/getstream/rn/callingx/NativeCallingxSpec.class +0 -0
- package/android/bin/build/generated/source/codegen/jni/CMakeLists.txt +0 -28
- package/android/bin/build/generated/source/codegen/jni/CallingxSpec-generated.cpp +0 -167
- package/android/bin/build/generated/source/codegen/jni/CallingxSpec.h +0 -31
- package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/CallingxSpecJSI-generated.cpp +0 -196
- package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/CallingxSpecJSI.h +0 -283
- package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/ComponentDescriptors.cpp +0 -22
- package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/ComponentDescriptors.h +0 -24
- package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/EventEmitters.cpp +0 -16
- package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/EventEmitters.h +0 -17
- package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/Props.cpp +0 -19
- package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/Props.h +0 -18
- package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/ShadowNodes.cpp +0 -17
- package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/ShadowNodes.h +0 -23
- package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/States.cpp +0 -16
- package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/States.h +0 -20
- package/android/bin/build/generated/source/codegen/schema.json +0 -1
- package/android/bin/src/main/AndroidManifest.xml +0 -29
- package/android/bin/src/main/java/io/getstream/rn/callingx/notifications/NotificationChannelsManager.kt +0 -104
- /package/android/src/main/java/io/getstream/rn/callingx/{ResourceUtils.kt → utils/ResourceUtils.kt} +0 -0
- /package/android/src/main/java/io/getstream/rn/callingx/{Utils.kt → utils/Utils.kt} +0 -0
package/android/build.gradle
CHANGED
|
@@ -65,7 +65,7 @@ android {
|
|
|
65
65
|
"generated/java",
|
|
66
66
|
"generated/jni",
|
|
67
67
|
"build/generated/source/codegen/java",
|
|
68
|
-
"build/generated/source/codegen/jni"
|
|
68
|
+
"build/generated/source/codegen/jni",
|
|
69
69
|
]
|
|
70
70
|
if (isNewArchitectureEnabled()) {
|
|
71
71
|
java.srcDirs += ["src/newarch"]
|
|
@@ -87,4 +87,10 @@ dependencies {
|
|
|
87
87
|
implementation "com.facebook.react:react-android"
|
|
88
88
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
89
89
|
implementation "androidx.core:core-telecom:1.0.1"
|
|
90
|
+
// Compile-time only dependency so StreamMessagingService can reference RemoteMessage.
|
|
91
|
+
// The consuming app (via @react-native-firebase/messaging) must provide the actual runtime version.
|
|
92
|
+
compileOnly "com.google.firebase:firebase-messaging-ktx:24.1.2"
|
|
93
|
+
// Optional: use Firebase native code when the app has react-native-firebase installed (peer deps)
|
|
94
|
+
implementation project(':react-native-firebase_app')
|
|
95
|
+
implementation project(':react-native-firebase_messaging')
|
|
90
96
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
1
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
2
|
+
xmlns:tools="http://schemas.android.com/tools">
|
|
2
3
|
|
|
3
4
|
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />
|
|
4
5
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
|
@@ -25,5 +26,34 @@
|
|
|
25
26
|
android:foregroundServiceType="phoneCall"
|
|
26
27
|
android:stopWithTask="true" />
|
|
27
28
|
|
|
29
|
+
<service
|
|
30
|
+
android:name="io.getstream.rn.callingx.StreamMessagingService"
|
|
31
|
+
android:exported="false">
|
|
32
|
+
<intent-filter>
|
|
33
|
+
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
|
34
|
+
</intent-filter>
|
|
35
|
+
</service>
|
|
36
|
+
|
|
37
|
+
<!-- Action values must match constants in CallingxModuleImpl.kt -->
|
|
38
|
+
<receiver
|
|
39
|
+
android:name="io.getstream.rn.callingx.CallEventBroadcastReceiver"
|
|
40
|
+
android:exported="false">
|
|
41
|
+
<intent-filter>
|
|
42
|
+
<action android:name="io.getstream.CALL_REGISTERED" />
|
|
43
|
+
<action android:name="io.getstream.CALL_REGISTERED_INCOMING" />
|
|
44
|
+
<action android:name="io.getstream.CALL_ANSWERED" />
|
|
45
|
+
<action android:name="io.getstream.CALL_INACTIVE" />
|
|
46
|
+
<action android:name="io.getstream.CALL_ACTIVE" />
|
|
47
|
+
<action android:name="io.getstream.CALL_MUTED" />
|
|
48
|
+
<action android:name="io.getstream.CALL_ENDPOINT_CHANGED" />
|
|
49
|
+
<action android:name="io.getstream.CALL_END" />
|
|
50
|
+
<action android:name="io.getstream.CALL_REGISTRATION_FAILED" />
|
|
51
|
+
</intent-filter>
|
|
52
|
+
</receiver>
|
|
53
|
+
|
|
54
|
+
<!-- Remove default FCM service so StreamMessagingService is the single handler -->
|
|
55
|
+
<service
|
|
56
|
+
android:name="io.invertase.firebase.messaging.ReactNativeFirebaseMessagingService"
|
|
57
|
+
tools:node="remove" />
|
|
28
58
|
</application>
|
|
29
59
|
</manifest>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
package io.getstream.rn.callingx
|
|
2
|
+
|
|
3
|
+
import android.content.BroadcastReceiver
|
|
4
|
+
import android.content.Context
|
|
5
|
+
import android.content.Intent
|
|
6
|
+
import android.os.Bundle
|
|
7
|
+
|
|
8
|
+
class CallEventBroadcastReceiver : BroadcastReceiver() {
|
|
9
|
+
|
|
10
|
+
override fun onReceive(context: Context, intent: Intent) {
|
|
11
|
+
val action = intent.action ?: return
|
|
12
|
+
val extras = intent.extras ?: Bundle()
|
|
13
|
+
|
|
14
|
+
CallEventBus.publish(CallEvent(action = action, extras = extras))
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
package io.getstream.rn.callingx
|
|
2
|
+
|
|
3
|
+
import android.os.Handler
|
|
4
|
+
import android.os.Looper
|
|
5
|
+
import android.util.Log
|
|
6
|
+
import com.facebook.react.bridge.Promise
|
|
7
|
+
import java.util.concurrent.ConcurrentHashMap
|
|
8
|
+
|
|
9
|
+
object CallRegistrationStore {
|
|
10
|
+
|
|
11
|
+
private const val TAG = "[Callingx] CallRegistrationStore"
|
|
12
|
+
private const val DISPLAY_TIMEOUT_MS = 10_000L
|
|
13
|
+
|
|
14
|
+
private val trackedCallIds: MutableSet<String> = ConcurrentHashMap.newKeySet()
|
|
15
|
+
|
|
16
|
+
/** Pending disconnect cause code (android.telecom.DisconnectCause code) per callId. */
|
|
17
|
+
private val pendingDisconnectCauseByCallId = ConcurrentHashMap<String, Int>()
|
|
18
|
+
private val pendingAnswerByCallId = ConcurrentHashMap<String, Boolean>()
|
|
19
|
+
private val pendingMuteByCallId = ConcurrentHashMap<String, Boolean>()
|
|
20
|
+
|
|
21
|
+
// Per-callId pending promises for displayIncomingCall awaiting CALL_REGISTERED_INCOMING_ACTION
|
|
22
|
+
private val pendingPromises = mutableMapOf<String, Promise>()
|
|
23
|
+
private val pendingTimeouts = mutableMapOf<String, Runnable>()
|
|
24
|
+
private val mainHandler = Handler(Looper.getMainLooper())
|
|
25
|
+
|
|
26
|
+
fun trackCallRegistration(callId: String, promise: Promise?) {
|
|
27
|
+
debugLog(TAG, "[store] trackCallRegistration: Tracking call registration for callId: $callId")
|
|
28
|
+
trackedCallIds.add(callId)
|
|
29
|
+
|
|
30
|
+
if (promise == null) return
|
|
31
|
+
|
|
32
|
+
synchronized(pendingPromises) {
|
|
33
|
+
// Cancel any existing timeout for this callId to avoid a stale runnable
|
|
34
|
+
// rejecting the new promise after it overwrites the old one.
|
|
35
|
+
pendingTimeouts.remove(callId)?.let { mainHandler.removeCallbacks(it) }
|
|
36
|
+
|
|
37
|
+
pendingPromises[callId] = promise
|
|
38
|
+
|
|
39
|
+
val timeoutRunnable = Runnable {
|
|
40
|
+
synchronized(pendingPromises) {
|
|
41
|
+
pendingPromises.remove(callId)?.reject(
|
|
42
|
+
"TIMEOUT",
|
|
43
|
+
"Timed out waiting for call registration: $callId"
|
|
44
|
+
)
|
|
45
|
+
pendingTimeouts.remove(callId)
|
|
46
|
+
trackedCallIds.remove(callId)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
pendingTimeouts[callId] = timeoutRunnable
|
|
50
|
+
mainHandler.postDelayed(timeoutRunnable, DISPLAY_TIMEOUT_MS)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
fun onRegistrationSuccess(callId: String) {
|
|
55
|
+
synchronized(pendingPromises) {
|
|
56
|
+
pendingTimeouts.remove(callId)?.let { mainHandler.removeCallbacks(it) }
|
|
57
|
+
pendingPromises.remove(callId)?.resolve(true)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
fun onRegistrationFailed(callId: String) {
|
|
62
|
+
reportRegistrationFail(
|
|
63
|
+
callId,
|
|
64
|
+
"REGISTRATION_FAILED",
|
|
65
|
+
"Failed to register call with telecom: $callId",
|
|
66
|
+
null
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
fun reportRegistrationFail(
|
|
71
|
+
callId: String,
|
|
72
|
+
code: String,
|
|
73
|
+
message: String?,
|
|
74
|
+
throwable: Throwable?
|
|
75
|
+
) {
|
|
76
|
+
trackedCallIds.remove(callId)
|
|
77
|
+
|
|
78
|
+
synchronized(pendingPromises) {
|
|
79
|
+
pendingTimeouts.remove(callId)?.let { mainHandler.removeCallbacks(it) }
|
|
80
|
+
val promise = pendingPromises.remove(callId)
|
|
81
|
+
if (promise != null) {
|
|
82
|
+
if (throwable != null) {
|
|
83
|
+
promise.reject(code, message, throwable)
|
|
84
|
+
} else if (message != null) {
|
|
85
|
+
promise.reject(code, message)
|
|
86
|
+
} else {
|
|
87
|
+
promise.reject(code, "Unknown error")
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
fun addTrackedCall(callId: String) {
|
|
94
|
+
debugLog(TAG, "[store] addTrackedCall: Adding tracked call: $callId")
|
|
95
|
+
trackedCallIds.add(callId)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
fun removeTrackedCall(callId: String) {
|
|
99
|
+
debugLog(TAG, "[store] removeTrackedCall: Removing tracked call: $callId")
|
|
100
|
+
trackedCallIds.remove(callId)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
fun isCallTracked(callId: String): Boolean {
|
|
104
|
+
val isTracked = trackedCallIds.contains(callId)
|
|
105
|
+
debugLog(TAG, "[store] isCallTracked: Is call $callId tracked: $isTracked")
|
|
106
|
+
return isTracked
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
fun hasRegisteredCall(): Boolean {
|
|
110
|
+
return trackedCallIds.isNotEmpty()
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Records that a disconnect was requested for this call before it was registered.
|
|
115
|
+
* When the call becomes registered, the service should take this and run the disconnect action.
|
|
116
|
+
*/
|
|
117
|
+
fun setPendingDisconnect(callId: String, disconnectCauseCode: Int) {
|
|
118
|
+
debugLog(TAG, "[store] setPendingDisconnect: callId=$callId causeCode=$disconnectCauseCode")
|
|
119
|
+
pendingDisconnectCauseByCallId[callId] = disconnectCauseCode
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
fun setPendingAnswer(callId: String, isAudioCall: Boolean) {
|
|
123
|
+
debugLog(TAG, "[store] setPendingAnswer: callId=$callId")
|
|
124
|
+
pendingAnswerByCallId[callId] = isAudioCall
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
fun setPendingMute(callId: String, isMute: Boolean) {
|
|
128
|
+
debugLog(TAG, "[store] setPendingMute: callId=$callId isMute=$isMute")
|
|
129
|
+
pendingMuteByCallId[callId] = isMute
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Returns and removes the pending disconnect cause code for this call, if any.
|
|
134
|
+
* Used when the call has just become registered so the service can run the disconnect action.
|
|
135
|
+
*/
|
|
136
|
+
fun takePendingDisconnect(callId: String): Int? {
|
|
137
|
+
val code = pendingDisconnectCauseByCallId.remove(callId)
|
|
138
|
+
if (code != null) {
|
|
139
|
+
debugLog(TAG, "[store] takePendingDisconnect: callId=$callId causeCode=$code")
|
|
140
|
+
}
|
|
141
|
+
return code
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
fun takePendingAnswer(callId: String): Boolean? {
|
|
145
|
+
val isAudioCall = pendingAnswerByCallId.remove(callId)
|
|
146
|
+
if (isAudioCall != null) {
|
|
147
|
+
debugLog(TAG, "[store] takePendingAnswer: callId=$callId isAudioCall=$isAudioCall")
|
|
148
|
+
}
|
|
149
|
+
return isAudioCall
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
fun takePendingMute(callId: String): Boolean? {
|
|
153
|
+
val isMute = pendingMuteByCallId.remove(callId)
|
|
154
|
+
if (isMute != null) {
|
|
155
|
+
debugLog(TAG, "[store] takePendingMute: callId=$callId isMute=$isMute")
|
|
156
|
+
}
|
|
157
|
+
return isMute
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
fun clearAll() {
|
|
161
|
+
synchronized(pendingPromises) {
|
|
162
|
+
pendingTimeouts.values.forEach { mainHandler.removeCallbacks(it) }
|
|
163
|
+
pendingTimeouts.clear()
|
|
164
|
+
pendingPromises.clear()
|
|
165
|
+
}
|
|
166
|
+
trackedCallIds.clear()
|
|
167
|
+
pendingDisconnectCauseByCallId.clear()
|
|
168
|
+
pendingAnswerByCallId.clear()
|
|
169
|
+
pendingMuteByCallId.clear()
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
private fun debugLog(tag: String, message: String) {
|
|
173
|
+
Log.d(tag, message)
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|