@stream-io/react-native-callingx 0.1.0-beta.7 → 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.
Files changed (45) hide show
  1. package/android/build.gradle +7 -1
  2. package/android/src/main/AndroidManifest.xml +31 -1
  3. package/android/src/main/java/io/getstream/rn/callingx/CallEventBroadcastReceiver.kt +17 -0
  4. package/android/src/main/java/io/getstream/rn/callingx/CallRegistrationStore.kt +176 -0
  5. package/android/src/main/java/io/getstream/rn/callingx/CallService.kt +302 -80
  6. package/android/src/main/java/io/getstream/rn/callingx/CallingxModuleImpl.kt +176 -191
  7. package/android/src/main/java/io/getstream/rn/callingx/StreamMessagingService.kt +48 -0
  8. package/android/src/main/java/io/getstream/rn/callingx/model/Call.kt +1 -0
  9. package/android/src/main/java/io/getstream/rn/callingx/notifications/CallNotificationManager.kt +196 -46
  10. package/android/src/main/java/io/getstream/rn/callingx/notifications/NotificationIntentFactory.kt +14 -8
  11. package/android/src/main/java/io/getstream/rn/callingx/notifications/NotificationReceiverActivity.kt +12 -1
  12. package/android/src/main/java/io/getstream/rn/callingx/notifications/NotificationReceiverService.kt +7 -0
  13. package/android/src/main/java/io/getstream/rn/callingx/repo/CallRepository.kt +38 -19
  14. package/android/src/main/java/io/getstream/rn/callingx/repo/LegacyCallRepository.kt +64 -55
  15. package/android/src/main/java/io/getstream/rn/callingx/repo/TelecomCallRepository.kt +241 -195
  16. package/android/src/main/java/io/getstream/rn/callingx/utils/CallEventBus.kt +61 -0
  17. package/android/src/main/java/io/getstream/rn/callingx/utils/SettingsStore.kt +51 -0
  18. package/android/src/newarch/java/io/getstream/rn/callingx/CallingxModule.kt +12 -3
  19. package/android/src/oldarch/java/io/getstream/rn/callingx/CallingxModule.kt +13 -3
  20. package/dist/module/CallingxModule.js +13 -10
  21. package/dist/module/CallingxModule.js.map +1 -1
  22. package/dist/module/spec/NativeCallingx.js.map +1 -1
  23. package/dist/module/utils/constants.js +24 -13
  24. package/dist/module/utils/constants.js.map +1 -1
  25. package/dist/typescript/src/CallingxModule.d.ts +3 -0
  26. package/dist/typescript/src/CallingxModule.d.ts.map +1 -1
  27. package/dist/typescript/src/spec/NativeCallingx.d.ts +7 -1
  28. package/dist/typescript/src/spec/NativeCallingx.d.ts.map +1 -1
  29. package/dist/typescript/src/types.d.ts +31 -0
  30. package/dist/typescript/src/types.d.ts.map +1 -1
  31. package/dist/typescript/src/utils/constants.d.ts +1 -1
  32. package/dist/typescript/src/utils/constants.d.ts.map +1 -1
  33. package/ios/AudioSessionManager.swift +2 -2
  34. package/ios/Callingx.mm +41 -17
  35. package/ios/CallingxImpl.swift +213 -83
  36. package/ios/Settings.swift +2 -2
  37. package/ios/UUIDStorage.swift +10 -10
  38. package/ios/VoipNotificationsManager.swift +8 -8
  39. package/package.json +4 -2
  40. package/src/CallingxModule.ts +14 -10
  41. package/src/spec/NativeCallingx.ts +10 -3
  42. package/src/types.ts +34 -0
  43. package/src/utils/constants.ts +23 -9
  44. /package/android/src/main/java/io/getstream/rn/callingx/{ResourceUtils.kt → utils/ResourceUtils.kt} +0 -0
  45. /package/android/src/main/java/io/getstream/rn/callingx/{Utils.kt → utils/Utils.kt} +0 -0
@@ -3,8 +3,8 @@ package io.getstream.rn.callingx.repo
3
3
  import android.content.Context
4
4
  import android.net.Uri
5
5
  import android.os.Bundle
6
+ import android.telecom.DisconnectCause
6
7
  import android.util.Log
7
- import androidx.core.telecom.CallAttributesCompat
8
8
  import io.getstream.rn.callingx.model.Call
9
9
  import io.getstream.rn.callingx.model.CallAction
10
10
  import kotlinx.coroutines.Job
@@ -21,17 +21,28 @@ class LegacyCallRepository(context: Context) : CallRepository(context) {
21
21
  private const val TAG = "[Callingx] LegacyCallRepository"
22
22
  }
23
23
 
24
- private var observeCallStateJob: Job? = null
24
+ private var observeCallsJob: Job? = null
25
25
 
26
26
  override fun getTag(): String = TAG
27
27
 
28
28
  override fun setListener(listener: Listener?) {
29
29
  this._listener = listener
30
- // Observe call state changes
31
- observeCallStateJob?.cancel()
32
- observeCallStateJob = scope.launch {
30
+ observeCallsJob?.cancel()
31
+ observeCallsJob = scope.launch {
32
+ var previousCalls: Map<String, Call.Registered> = emptyMap()
33
33
  try {
34
- currentCall.collect { _listener?.onCallStateChanged(it) }
34
+ calls.collect { currentCalls ->
35
+ // Notify about changes per call
36
+ for ((callId, call) in currentCalls) {
37
+ _listener?.onCallStateChanged(callId, call)
38
+ }
39
+ for ((callId, _) in previousCalls) {
40
+ if (!currentCalls.containsKey(callId)) {
41
+ _listener?.onCallStateChanged(callId, Call.None)
42
+ }
43
+ }
44
+ previousCalls = currentCalls
45
+ }
35
46
  } catch (e: Exception) {
36
47
  Log.e(TAG, "[repository] setListener: Error collecting call state", e)
37
48
  }
@@ -39,10 +50,10 @@ class LegacyCallRepository(context: Context) : CallRepository(context) {
39
50
  }
40
51
 
41
52
  override fun release() {
42
- _currentCall.value = Call.None
53
+ _calls.value = emptyMap()
43
54
 
44
- observeCallStateJob?.cancel()
45
- observeCallStateJob = null
55
+ observeCallsJob?.cancel()
56
+ observeCallsJob = null
46
57
  _listener = null
47
58
 
48
59
  scope.cancel()
@@ -55,42 +66,42 @@ class LegacyCallRepository(context: Context) : CallRepository(context) {
55
66
  isIncoming: Boolean,
56
67
  isVideo: Boolean,
57
68
  displayOptions: Bundle?,
58
- ) {
59
- registrationMutex.withLock {
60
- if (currentCall.value is Call.Registered) {
61
- Log.w(
62
- TAG,
63
- "[repository] registerCall: Call already registered, ignoring new call request"
64
- )
65
- return@withLock
66
- }
67
-
68
- val attributes = createCallAttributes(displayName, address, isIncoming, isVideo)
69
- val actionSource = Channel<CallAction>()
70
-
71
- _currentCall.value =
72
- Call.Registered(
73
- id = callId,
74
- isActive = false,
75
- isOnHold = false,
76
- callAttributes = attributes,
77
- displayOptions = displayOptions,
78
- isMuted = false,
79
- errorCode = null,
80
- currentCallEndpoint = null,
81
- availableCallEndpoints = emptyList(),
82
- actionSource = actionSource,
83
- )
84
-
85
- _listener?.onCallRegistered(callId, isIncoming)
69
+ ) = registrationMutex.withLock {
70
+ // Check if this specific call is already registered
71
+ if (_calls.value.containsKey(callId)) {
72
+ Log.w(
73
+ TAG,
74
+ "[repository] registerCall: Call $callId already registered, ignoring duplicate"
75
+ )
76
+ return@withLock
77
+ }
86
78
 
87
- // Process actions without telecom SDK
88
- scope.launch {
89
- try {
90
- actionSource.consumeAsFlow().collect { action -> processActionLegacy(action) }
91
- } catch (e: Exception) {
92
- Log.e(TAG, "[repository] registerCall: Error consuming actions", e)
93
- }
79
+ val attributes = createCallAttributes(displayName, address, isIncoming, isVideo)
80
+ val actionSource = Channel<CallAction>()
81
+
82
+ val registeredCall = Call.Registered(
83
+ id = callId,
84
+ isPending = false,
85
+ isActive = false,
86
+ isOnHold = false,
87
+ callAttributes = attributes,
88
+ displayOptions = displayOptions,
89
+ isMuted = false,
90
+ errorCode = null,
91
+ currentCallEndpoint = null,
92
+ availableCallEndpoints = emptyList(),
93
+ actionSource = actionSource,
94
+ )
95
+
96
+ addCall(callId, registeredCall)
97
+ _listener?.onCallRegistered(callId, isIncoming)
98
+
99
+ // Process actions without telecom SDK
100
+ scope.launch {
101
+ try {
102
+ actionSource.consumeAsFlow().collect { action -> processActionLegacy(callId, action) }
103
+ } catch (e: Exception) {
104
+ Log.e(TAG, "[repository] registerCall: Error consuming actions for $callId", e)
94
105
  }
95
106
  }
96
107
  }
@@ -105,30 +116,28 @@ class LegacyCallRepository(context: Context) : CallRepository(context) {
105
116
  super.updateCall(callId, displayName, address, isVideo, displayOptions)
106
117
  }
107
118
 
108
- private fun processActionLegacy(action: CallAction) {
119
+ private fun processActionLegacy(callId: String, action: CallAction) {
109
120
  when (action) {
110
121
  is CallAction.Answer -> {
111
- updateCurrentCall { copy(isActive = true, isOnHold = false) }
112
- // In legacy mode, all actions are initiated from the app
113
- (currentCall.value as? Call.Registered)?.let {
114
- _listener?.onIsCallAnswered(it.id, EventSource.APP)
122
+ updateCallById(callId) { copy(isActive = true, isOnHold = false) }
123
+ val call = _calls.value[callId]
124
+ if (call != null) {
125
+ _listener?.onIsCallAnswered(callId, EventSource.APP)
115
126
  }
116
127
  }
117
128
  is CallAction.Disconnect -> {
118
- val call = currentCall.value as? Call.Registered
129
+ val call = _calls.value[callId]
119
130
  if (call != null) {
120
- _currentCall.value =
121
- Call.Unregistered(call.id, call.callAttributes, action.cause)
122
- // In legacy mode, all actions are initiated from the app
131
+ removeCall(callId)
123
132
  _listener?.onIsCallDisconnected(
124
- call.id,
133
+ callId,
125
134
  action.cause,
126
135
  EventSource.APP
127
136
  )
128
137
  }
129
138
  }
130
139
  is CallAction.ToggleMute -> {
131
- updateCurrentCall { copy(isMuted = action.isMute) }
140
+ updateCallById(callId) { copy(isMuted = action.isMute) }
132
141
  }
133
142
  // Handle other actions...
134
143
  else -> {