@stream-io/video-react-native-sdk 1.45.1 → 2.0.0-beta.1

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/CHANGELOG.md CHANGED
@@ -2,22 +2,19 @@
2
2
 
3
3
  This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
4
4
 
5
- ## [1.45.1](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-react-native-sdk-1.45.0...@stream-io/video-react-native-sdk-1.45.1) (2026-09-04)
5
+ ## [2.0.0-beta.1](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-react-native-sdk-2.0.0-beta.0...@stream-io/video-react-native-sdk-2.0.0-beta.1) (2026-09-04)
6
6
 
7
- ### Dependency Updates
7
+ ### Bug Fixes
8
+
9
+ - **react-native-sdk:** publish the corrected satellite peer ranges ([15172ec](https://github.com/GetStream/stream-video-js/commit/15172ec5a2e96ec7ad62c83be631776a9f315485)), closes [#2414](https://github.com/GetStream/stream-video-js/issues/2414)
8
10
 
9
- - `@stream-io/react-native-callingx` updated to version `0.11.3`
10
- - `@stream-io/video-client` updated to version `1.59.1`
11
- - **client:** isolate coordinator event listener errors from the dispatch loop ([#2404](https://github.com/GetStream/stream-video-js/issues/2404)) ([4ab49de](https://github.com/GetStream/stream-video-js/commit/4ab49decc4bbc70b0fc35d6b92f2bd18922a105c)), closes [GetStream/stream-chat-js#1850](https://github.com/GetStream/stream-chat-js/issues/1850)
12
- - **client:** keep passive participants out of the spotlight ([#2405](https://github.com/GetStream/stream-video-js/issues/2405)) ([0713650](https://github.com/GetStream/stream-video-js/commit/0713650fa90caa8a82ce0bee75acf4dbaaad33e9))
13
- - `@stream-io/video-react-bindings` updated to version `1.20.2`
11
+ ## [2.0.0-beta.0](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-react-native-sdk-1.45.0...@stream-io/video-react-native-sdk-2.0.0-beta.0) (2026-09-04)
14
12
 
15
13
  ### Bug Fixes
16
14
 
17
15
  - **callingx:** don't tear down concurrent calls on stop service ([#2394](https://github.com/GetStream/stream-video-js/issues/2394)) ([d6e9deb](https://github.com/GetStream/stream-video-js/commit/d6e9debbe98ae91cc349f010eb92f76b35a3f932))
18
16
  - **rn:** auto-leave previous callingx calls on new join ([#2402](https://github.com/GetStream/stream-video-js/issues/2402)) ([5a3dfdd](https://github.com/GetStream/stream-video-js/commit/5a3dfddd8ddbfacf6e8ea109656be82da91a3436))
19
17
  - **rn:** wrong expo plugin Android call-alive foreground service detection ([#2398](https://github.com/GetStream/stream-video-js/issues/2398)) ([eac10b5](https://github.com/GetStream/stream-video-js/commit/eac10b5a390f6949b25535d2b4c4cf9bc3d5f065))
20
- - workaround for android non-telecom path MODE_IN_COMMUNICATION reset edge-case ([#2360](https://github.com/GetStream/stream-video-js/issues/2360)) ([65a1fb7](https://github.com/GetStream/stream-video-js/commit/65a1fb766461f95a3b70fe221e9ace0caad6c64b))
21
18
 
22
19
  ## [1.45.0](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-react-native-sdk-1.44.0...@stream-io/video-react-native-sdk-1.45.0) (2026-08-28)
23
20
 
package/README.md CHANGED
@@ -79,6 +79,21 @@ The monorepo consists of multiple folders, the most important of which are `pack
79
79
  Before running this project please ensure you have set up your [development environment for React Native](https://reactnative.dev/docs/environment-setup).
80
80
  The Stream Video React Native SDK supports apps created with the React Native CLI.
81
81
 
82
+ ### Optional native add-ons
83
+
84
+ Noise cancellation, video filters and CallKit/Telecom ringing ship as separate
85
+ optional peer packages. On the `2.0.0-beta` line they are published on their own
86
+ `1.0.0-beta` line under the `beta` npm tag, so install them from that tag:
87
+
88
+ ```sh
89
+ yarn add @stream-io/noise-cancellation-react-native@beta
90
+ yarn add @stream-io/video-filters-react-native@beta
91
+ yarn add @stream-io/react-native-callingx@beta
92
+ ```
93
+
94
+ Installing the `latest` builds of these packages alongside the v2 beta pulls the
95
+ v1 line and will report an unmet peer dependency.
96
+
82
97
  ## **Contributing** 🤝
83
98
 
84
99
  - How can I submit a sample app?
@@ -107,30 +107,6 @@ class AudioDeviceManager(
107
107
  */
108
108
  var telecomManagedMode: Boolean = false
109
109
 
110
- /**
111
- * Opt-out for the Android 11+ communication-mode keep-alive. Sticky developer preference —
112
- * intentionally NOT reset in [stop], unlike the per-call fields above.
113
- */
114
- var disableCommunicationModeWorkaround: Boolean = false
115
-
116
- /**
117
- * True once [stop]/[close] have torn routing down, until the next [start].
118
- *
119
- * [updateAudioDeviceState] is enqueued from off-thread sources (Bluetooth receivers,
120
- * audio-focus and device callbacks), so a task can still land after teardown. Re-routing
121
- * then would re-assert MODE_IN_COMMUNICATION via AudioManagerUtil, undoing the
122
- * MODE_NORMAL restore in [stop]. Audio-thread confined.
123
- */
124
- private var routingStopped = false
125
-
126
- /** Keeps MODE_IN_COMMUNICATION owned for the whole Communicator call on Android 11+. */
127
- private val communicationModeKeepAlive: CommunicationModeKeepAlive =
128
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
129
- SilentPlaybackKeepAlive(mReactContext)
130
- } else {
131
- NoCommunicationModeKeepAlive
132
- }
133
-
134
110
  val bluetoothManager = BluetoothManager(mReactContext, this)
135
111
 
136
112
  private val proximityManager by lazy { ProximityManager(mReactContext, this) }
@@ -154,64 +130,53 @@ class AudioDeviceManager(
154
130
  audioFocusUtil.setup(callAudioRole, mReactContext)
155
131
  }
156
132
 
157
- /** Runs inline; callers must already be on the audio thread (see [runInAudioThread]). */
158
133
  fun start(activity: Activity) {
159
- routingStopped = false
160
- setup()
161
- selectedAudioDeviceEndpoint = null
162
- if (callAudioRole == CallAudioRole.Communicator) {
163
- // Audio routing is manually controlled by the SDK in communication media mode
164
- // and local microphone can be published
165
- activity.volumeControlStream = AudioManager.STREAM_VOICE_CALL
134
+ runInAudioThread {
135
+ setup()
136
+ selectedAudioDeviceEndpoint = null
137
+ if (callAudioRole == CallAudioRole.Communicator) {
138
+ // Audio routing is manually controlled by the SDK in communication media mode
139
+ // and local microphone can be published
140
+ activity.volumeControlStream = AudioManager.STREAM_VOICE_CALL
141
+ if (!telecomManagedMode) {
142
+ // Telecom owns routing/focus; only run our own routing when not Telecom-managed.
143
+ bluetoothManager.start()
144
+ mAudioManager.registerAudioDeviceCallback(this, null)
145
+ updateAudioDeviceState()
146
+ }
147
+ proximityManager.start()
148
+ } else {
149
+ activity.volumeControlStream = AudioManager.USE_DEFAULT_STREAM_TYPE
150
+ }
166
151
  if (!telecomManagedMode) {
167
- // Telecom owns routing/focus; only run our own routing when not Telecom-managed.
168
- bluetoothManager.start()
169
- mAudioManager.registerAudioDeviceCallback(this, null)
170
- updateAudioDeviceState()
152
+ audioFocusUtil.requestFocus(callAudioRole, mReactContext)
171
153
  }
172
- proximityManager.start()
173
- } else {
174
- activity.volumeControlStream = AudioManager.USE_DEFAULT_STREAM_TYPE
175
- }
176
- if (!telecomManagedMode) {
177
- audioFocusUtil.requestFocus(callAudioRole, mReactContext)
178
- }
179
- // Started last, after focus/routing, so the silent track uses the correct route.
180
- if (callAudioRole == CallAudioRole.Communicator &&
181
- !telecomManagedMode &&
182
- !disableCommunicationModeWorkaround
183
- ) {
184
- communicationModeKeepAlive.start()
185
154
  }
186
155
  }
187
156
 
188
- /** Runs inline; callers must already be on the audio thread (see [runInAudioThread]). */
189
- fun stop(activity: Activity?) {
190
- routingStopped = true
191
- communicationModeKeepAlive.stop()
192
- if (callAudioRole == CallAudioRole.Communicator) {
193
- if (!telecomManagedMode) {
194
- // Only tear down what we set up ourselves; Telecom owns its own teardown.
195
- if (Build.VERSION.SDK_INT >= 31) {
196
- mAudioManager.clearCommunicationDevice()
197
- } else {
198
- mAudioManager.setSpeakerphoneOn(false)
157
+ fun stop(activity: Activity) {
158
+ runInAudioThread {
159
+ if (callAudioRole == CallAudioRole.Communicator) {
160
+ if (!telecomManagedMode) {
161
+ // Only tear down what we set up ourselves; Telecom owns its own teardown.
162
+ if (Build.VERSION.SDK_INT >= 31) {
163
+ mAudioManager.clearCommunicationDevice()
164
+ } else {
165
+ mAudioManager.setSpeakerphoneOn(false)
166
+ }
167
+ bluetoothManager.stop()
199
168
  }
200
- bluetoothManager.stop()
201
- // Restore the mode set in setup(); it was previously left at
202
- // MODE_IN_COMMUNICATION, holding the device in in-call routing.
203
- mAudioManager.mode = AudioManager.MODE_NORMAL
169
+ callAudioRole = CallAudioRole.Communicator
170
+ enableStereo = false
171
+ defaultAudioDevice = AudioDeviceEndpoint.TYPE_SPEAKER
172
+ proximityManager.stop()
204
173
  }
205
- callAudioRole = CallAudioRole.Communicator
206
- enableStereo = false
207
- defaultAudioDevice = AudioDeviceEndpoint.TYPE_SPEAKER
208
- proximityManager.stop()
209
- }
210
- activity?.volumeControlStream = AudioManager.USE_DEFAULT_STREAM_TYPE
211
- if (!telecomManagedMode) {
212
- audioFocusUtil.abandonFocus()
174
+ activity.volumeControlStream = AudioManager.USE_DEFAULT_STREAM_TYPE
175
+ if (!telecomManagedMode) {
176
+ audioFocusUtil.abandonFocus()
177
+ }
178
+ telecomManagedMode = false
213
179
  }
214
- telecomManagedMode = false
215
180
  }
216
181
 
217
182
  fun setMicrophoneMute(enable: Boolean) {
@@ -263,9 +228,6 @@ class AudioDeviceManager(
263
228
  }
264
229
 
265
230
  private fun switchDeviceEndpointType(@EndpointType deviceType: Int) {
266
- // Sole sink for routing changes, and AudioManagerUtil re-asserts MODE_IN_COMMUNICATION
267
- // here — so late work of any origin must not reach it after teardown.
268
- if (routingStopped) return
269
231
  val newDevice = AudioManagerUtil.switchDeviceEndpointType(
270
232
  deviceType,
271
233
  mEndpointMaps,
@@ -275,49 +237,38 @@ class AudioDeviceManager(
275
237
  this.selectedAudioDeviceEndpoint = newDevice
276
238
  }
277
239
 
278
- /** Runs inline; callers must already be on the audio thread (see [runInAudioThread]). */
279
240
  fun switchDeviceById(
280
241
  deviceId: String
281
242
  ) {
282
243
  Log.d(TAG, "switchDeviceById: deviceId = $deviceId")
283
- // Guarded here too: the branch below sets the communication device directly rather
284
- // than going through switchDeviceEndpointType().
285
- if (routingStopped) return
286
- val btDevice = mEndpointMaps.bluetoothEndpoints[deviceId]
287
- if (btDevice != null) {
288
- if (Build.VERSION.SDK_INT >= 31) {
289
- mAudioManager.setCommunicationDevice(btDevice.deviceInfo)
290
- bluetoothManager.updateDevice()
291
- this.selectedAudioDeviceEndpoint = btDevice
292
- } else {
293
- switchDeviceEndpointType(
294
- AudioDeviceEndpoint.TYPE_BLUETOOTH
295
- )
296
- }
297
- } else {
298
- val endpoint = nonBluetoothEndpointById(deviceId)
299
- if (endpoint != null) {
300
- switchDeviceEndpointType(endpoint.type)
244
+ runInAudioThread {
245
+ val btDevice = mEndpointMaps.bluetoothEndpoints[deviceId]
246
+ if (btDevice != null) {
247
+ if (Build.VERSION.SDK_INT >= 31) {
248
+ mAudioManager.setCommunicationDevice(btDevice.deviceInfo)
249
+ bluetoothManager.updateDevice()
250
+ this.selectedAudioDeviceEndpoint = btDevice
251
+ } else {
252
+ switchDeviceEndpointType(
253
+ AudioDeviceEndpoint.TYPE_BLUETOOTH
254
+ )
255
+ }
301
256
  } else {
302
- Log.e(TAG, "switchDeviceById: no endpoint found for id $deviceId")
257
+ val endpoint = nonBluetoothEndpointById(deviceId)
258
+ if (endpoint != null) {
259
+ switchDeviceEndpointType(endpoint.type)
260
+ } else {
261
+ Log.e(TAG, "switchDeviceById: no endpoint found for id $deviceId")
262
+ }
303
263
  }
304
264
  }
305
265
  }
306
266
 
307
267
  override fun close() {
308
- // Unlike start()/stop(), this is called straight from the module, so it must be queued
309
- // to land after any start/stop already pending on the audio thread.
310
- runInAudioThread {
311
- routingStopped = true
312
- communicationModeKeepAlive.release()
313
- mAudioManager.unregisterAudioDeviceCallback(this)
314
- proximityManager.onDestroy()
315
- }
268
+ mAudioManager.unregisterAudioDeviceCallback(this)
269
+ proximityManager.onDestroy()
316
270
  }
317
271
 
318
- /** Short description of the keep-alive state, for the audio debug log. */
319
- fun communicationModeKeepAliveState(): String = communicationModeKeepAlive.describeState()
320
-
321
272
  override fun onAudioDevicesAdded(addedDevices: Array<out AudioDeviceInfo>?) {
322
273
  if (addedDevices != null) {
323
274
  runInAudioThread {
@@ -472,9 +423,6 @@ class AudioDeviceManager(
472
423
  */
473
424
  fun updateAudioDeviceState() {
474
425
  runInAudioThread {
475
- // Bail early: on API < 31 bluetoothState survives stop(), so a late pass could
476
- // still start SCO after the call ended.
477
- if (routingStopped) return@runInAudioThread
478
426
  if (telecomManagedMode) {
479
427
  // Telecom is the single source of truth for routing/endpoints in this mode.
480
428
  return@runInAudioThread
@@ -75,18 +75,6 @@ class StreamInCallManagerModule(reactContext: ReactApplicationContext) :
75
75
  }
76
76
  }
77
77
 
78
- @ReactMethod
79
- fun setDisableCommunicationModeWorkaround(disabled: Boolean) {
80
- AudioDeviceManager.runInAudioThread {
81
- if (audioManagerActivated) {
82
- Log.e(TAG, "setDisableCommunicationModeWorkaround(): AudioManager is already activated and so it cannot be changed")
83
- return@runInAudioThread
84
- }
85
- Log.d(TAG, "setDisableCommunicationModeWorkaround(): $disabled")
86
- mAudioDeviceManager.disableCommunicationModeWorkaround = disabled
87
- }
88
- }
89
-
90
78
  @ReactMethod
91
79
  fun setDefaultAudioDeviceEndpointType(endpointDeviceTypeName: String) {
92
80
  AudioDeviceManager.runInAudioThread {
@@ -141,8 +129,10 @@ class StreamInCallManagerModule(reactContext: ReactApplicationContext) :
141
129
  AudioDeviceManager.runInAudioThread {
142
130
  if (audioManagerActivated) {
143
131
  Log.d(TAG, "stop() mAudioDeviceManager")
144
- mAudioDeviceManager.stop(reactApplicationContext.currentActivity)
145
- audioManagerActivated = false
132
+ reactApplicationContext.currentActivity?.let {
133
+ mAudioDeviceManager.stop(it)
134
+ audioManagerActivated = false
135
+ }
146
136
  setMicrophoneMute(false)
147
137
  setKeepScreenOn(false)
148
138
  }
@@ -195,8 +185,7 @@ class StreamInCallManagerModule(reactContext: ReactApplicationContext) :
195
185
 
196
186
  @ReactMethod(isBlockingSynchronousMethod = true)
197
187
  fun getAudioStateLog(): String {
198
- return WebRtcAudioUtils.getAudioStateLog(reactApplicationContext) +
199
- "Communication mode keep-alive: ${mAudioDeviceManager.communicationModeKeepAliveState()}\n"
188
+ return WebRtcAudioUtils.getAudioStateLog(reactApplicationContext)
200
189
  }
201
190
 
202
191
  @Suppress("unused")
@@ -131,29 +131,6 @@ class StreamVideoRN {
131
131
  _pushLogoutCallback.default.current = [];
132
132
  }
133
133
 
134
- /**
135
- * Android only. Opt out of the Android 11+ communication-mode keep-alive.
136
- *
137
- * By default the SDK plays a silent voice-communication track for the duration of a
138
- * communicator-role call, so Android does not reset `MODE_IN_COMMUNICATION` ~6s after it is
139
- * set (which breaks audio routing and echo cancellation).
140
- * See {@link https://issuetracker.google.com/issues/209493718}
141
- *
142
- * Call this at app start, alongside {@link setPushConfig} — the native audio manager
143
- * rejects the change once it has been activated for a call. No-op on iOS and on
144
- * Android below API 30.
145
- */
146
- static setDisableCommunicationModeWorkaround(disabled) {
147
- if (_reactNative.Platform.OS !== 'android') {
148
- return;
149
- }
150
- try {
151
- _reactNative.NativeModules.StreamInCallManager?.setDisableCommunicationModeWorkaround(disabled);
152
- } catch (error) {
153
- _videoClient.videoLoggerSystem.getLogger('StreamVideoRN').warn('setDisableCommunicationModeWorkaround failed', error);
154
- }
155
- }
156
-
157
134
  /**
158
135
  * Play native busy tone for call rejection
159
136
  */
@@ -1 +1 @@
1
- {"version":3,"names":["_pushLogoutCallback","_interopRequireDefault","require","_setupIosVoipPushEvents","_setupAndroidPushEvents","_setupCallingExpEvents","_callingx","_reactNative","_videoClient","e","__esModule","default","deepMerge","target","source","result","key","undefined","Array","isArray","DEFAULT_STREAM_VIDEO_CONFIG","foregroundService","android","channel","id","name","notificationTexts","title","body","taskToRun","Promise","StreamVideoRN","config","updateConfig","setPushConfig","pushConfig","push","callingx","getCallingxLib","videoLoggerSystem","getLogger","info","JSON","stringify","options","extractCallingExpOptions","setup","Error","setupCallingExpEvents","setupIosVoipPushEvents","setupAndroidPushEvents","getConfig","onPushLogout","callbacks","pushLogoutCallbacks","current","resolve","all","map","callback","then","clearPushLogoutCallbacks","setDisableCommunicationModeWorkaround","disabled","Platform","OS","NativeModules","StreamInCallManager","error","warn","playBusyTone","StreamVideoReactNative","stopBusyTone","androidHasAudioOutputHardware","hasAudioOutputHardware","androidHasMicrophoneHardware","hasMicrophoneHardware","androidHasCameraHardware","hasCameraHardware","exports"],"sourceRoot":"../../../../src","sources":["utils/StreamVideoRN/index.ts"],"mappings":";;;;;;AACA,IAAAA,mBAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,uBAAA,GAAAD,OAAA;AACA,IAAAE,uBAAA,GAAAF,OAAA;AACA,IAAAG,sBAAA,GAAAH,OAAA;AACA,IAAAI,SAAA,GAAAJ,OAAA;AAIA,IAAAK,YAAA,GAAAL,OAAA;AACA,IAAAM,YAAA,GAAAN,OAAA;AAA4D,SAAAD,uBAAAQ,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAE5D;;AAKA;AACA,SAASG,SAASA,CAChBC,MAAS,EACTC,MAAsB,EACnB;EACH,MAAMC,MAAM,GAAG;IAAE,GAAGF;EAAO,CAAC;EAE5B,KAAK,MAAMG,GAAG,IAAIF,MAAM,EAAE;IACxB,IAAIA,MAAM,CAACE,GAAG,CAAC,KAAKC,SAAS,EAAE;MAC7B,IACE,OAAOH,MAAM,CAACE,GAAG,CAAC,KAAK,QAAQ,IAC/BF,MAAM,CAACE,GAAG,CAAC,KAAK,IAAI,IACpB,CAACE,KAAK,CAACC,OAAO,CAACL,MAAM,CAACE,GAAG,CAAC,CAAC,IAC3B,OAAOH,MAAM,CAACG,GAAG,CAAC,KAAK,QAAQ,IAC/BH,MAAM,CAACG,GAAG,CAAC,KAAK,IAAI,IACpB,CAACE,KAAK,CAACC,OAAO,CAACN,MAAM,CAACG,GAAG,CAAC,CAAC,EAC3B;QACAD,MAAM,CAACC,GAAG,CAAC,GAAGJ,SAAS,CACrBC,MAAM,CAACG,GAAG,CAAC,EACXF,MAAM,CAACE,GAAG,CACZ,CAAC;MACH,CAAC,MAAM;QACLD,MAAM,CAACC,GAAG,CAAC,GAAGF,MAAM,CAACE,GAAG,CAAkB;MAC5C;IACF;EACF;EAEA,OAAOD,MAAM;AACf;AAEA,MAAMK,2BAA8C,GAAG;EACrDC,iBAAiB,EAAE;IACjBC,OAAO,EAAE;MACPC,OAAO,EAAE;QACPC,EAAE,EAAE,gCAAgC;QACpCC,IAAI,EAAE;MACR,CAAC;MACDC,iBAAiB,EAAE;QACjBC,KAAK,EAAE,kBAAkB;QACzBC,IAAI,EAAE;MACR,CAAC;MACDC,SAAS,EAAEA,CAAA,KAAM,IAAIC,OAAO,CAAC,MAAM,CAAC,CAAC;IACvC;EACF;AACF,CAAC;AAEM,MAAMC,aAAa,CAAC;EACzB,OAAeC,MAAM,GAAGZ,2BAA2B;;EAEnD;AACF;AACA;AACA;AACA;EACE,OAAOa,YAAYA,CACjBA,YAA0D,EAC1D;IACA,IAAI,CAACD,MAAM,GAAGpB,SAAS,CAAC,IAAI,CAACoB,MAAM,EAAEC,YAAY,CAAC;EACpD;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACE,OAAOC,aAAaA,CAACC,UAAkD,EAAE;IACvE,IAAI,IAAI,CAACH,MAAM,CAACI,IAAI,EAAE;MACpB;MACA;IACF;IAEA,IAAI,CAACJ,MAAM,CAACI,IAAI,GAAGD,UAAU;IAE7B,IAAI;MACF,MAAME,QAAQ,GAAG,IAAAC,wBAAc,EAAC,CAAC;MACjCC,8BAAiB,CACdC,SAAS,CAAC,6BAA6B,CAAC,CACxCC,IAAI,CAACC,IAAI,CAACC,SAAS,CAAC,IAAI,CAACX,MAAM,CAAC,CAAC;MACpC,MAAMY,OAAO,GAAG,IAAAC,kCAAwB,EAAC,IAAI,CAACb,MAAM,CAAC;MACrDK,QAAQ,CAACS,KAAK,CAACF,OAAO,CAAC;IACzB,CAAC,CAAC,MAAM;MACN,MAAM,IAAIG,KAAK,CACb,iKACF,CAAC;IACH;IAEA,IAAAC,4CAAqB,EAACb,UAAU,CAAC;IACjC,IAAAc,8CAAsB,EAACd,UAAU,CAAC;IAClC,IAAAe,8CAAsB,EAACf,UAAU,CAAC;EACpC;EAEA,OAAOgB,SAASA,CAAA,EAAG;IACjB,OAAO,IAAI,CAACnB,MAAM;EACpB;;EAEA;AACF;AACA;AACA;EACE,OAAOoB,YAAYA,CAAA,EAAG;IACpB,MAAMC,SAAS,GAAGC,2BAAmB,CAACC,OAAO;IAC7C,IAAI,CAACF,SAAS,EAAE;MACd,OAAOvB,OAAO,CAAC0B,OAAO,CAAC,CAAC;IAC1B;IACAF,2BAAmB,CAACC,OAAO,GAAG,EAAE;IAChC,OAAOzB,OAAO,CAAC2B,GAAG,CAACJ,SAAS,CAACK,GAAG,CAAEC,QAAQ,IAAKA,QAAQ,CAAC,CAAC,CAAC,CAAC,CAACC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;EAC5E;EAEA,OAAOC,wBAAwBA,CAAA,EAAG;IAChCP,2BAAmB,CAACC,OAAO,GAAG,EAAE;EAClC;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACE,OAAOO,qCAAqCA,CAACC,QAAiB,EAAE;IAC9D,IAAIC,qBAAQ,CAACC,EAAE,KAAK,SAAS,EAAE;MAC7B;IACF;IACA,IAAI;MACFC,0BAAa,CAACC,mBAAmB,EAAEL,qCAAqC,CACtEC,QACF,CAAC;IACH,CAAC,CAAC,OAAOK,KAAK,EAAE;MACd7B,8BAAiB,CACdC,SAAS,CAAC,eAAe,CAAC,CAC1B6B,IAAI,CAAC,8CAA8C,EAAED,KAAK,CAAC;IAChE;EACF;;EAEA;AACF;AACA;EACE,aAAaE,YAAYA,CAAA,EAAG;IAC1B,OAAOJ,0BAAa,CAACK,sBAAsB,CAACD,YAAY,CAAC,CAAC;EAC5D;;EAEA;AACF;AACA;EACE,aAAaE,YAAYA,CAAA,EAAG;IAC1B,OAAON,0BAAa,CAACK,sBAAsB,CAACC,YAAY,CAAC,CAAC;EAC5D;;EAEA;AACF;AACA;AACA;EACE,aAAaC,6BAA6BA,CAAA,EAAqB;IAC7D,IAAIT,qBAAQ,CAACC,EAAE,KAAK,SAAS,EAC3B,MAAM,IAAIlB,KAAK,CACb,qEACF,CAAC;IACH,OAAOmB,0BAAa,CAACK,sBAAsB,CAACG,sBAAsB,CAAC,CAAC;EACtE;;EAEA;AACF;AACA;AACA;EACE,aAAaC,4BAA4BA,CAAA,EAAqB;IAC5D,IAAIX,qBAAQ,CAACC,EAAE,KAAK,SAAS,EAC3B,MAAM,IAAIlB,KAAK,CACb,oEACF,CAAC;IACH,OAAOmB,0BAAa,CAACK,sBAAsB,CAACK,qBAAqB,CAAC,CAAC;EACrE;;EAEA;AACF;AACA;AACA;EACE,aAAaC,wBAAwBA,CAAA,EAAqB;IACxD,IAAIb,qBAAQ,CAACC,EAAE,KAAK,SAAS,EAC3B,MAAM,IAAIlB,KAAK,CACb,gEACF,CAAC;IACH,OAAOmB,0BAAa,CAACK,sBAAsB,CAACO,iBAAiB,CAAC,CAAC;EACjE;AACF;AAACC,OAAA,CAAAhD,aAAA,GAAAA,aAAA","ignoreList":[]}
1
+ {"version":3,"names":["_pushLogoutCallback","_interopRequireDefault","require","_setupIosVoipPushEvents","_setupAndroidPushEvents","_setupCallingExpEvents","_callingx","_reactNative","_videoClient","e","__esModule","default","deepMerge","target","source","result","key","undefined","Array","isArray","DEFAULT_STREAM_VIDEO_CONFIG","foregroundService","android","channel","id","name","notificationTexts","title","body","taskToRun","Promise","StreamVideoRN","config","updateConfig","setPushConfig","pushConfig","push","callingx","getCallingxLib","videoLoggerSystem","getLogger","info","JSON","stringify","options","extractCallingExpOptions","setup","Error","setupCallingExpEvents","setupIosVoipPushEvents","setupAndroidPushEvents","getConfig","onPushLogout","callbacks","pushLogoutCallbacks","current","resolve","all","map","callback","then","clearPushLogoutCallbacks","playBusyTone","NativeModules","StreamVideoReactNative","stopBusyTone","androidHasAudioOutputHardware","Platform","OS","hasAudioOutputHardware","androidHasMicrophoneHardware","hasMicrophoneHardware","androidHasCameraHardware","hasCameraHardware","exports"],"sourceRoot":"../../../../src","sources":["utils/StreamVideoRN/index.ts"],"mappings":"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","ignoreList":[]}
@@ -4,5 +4,5 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.version = void 0;
7
- const version = exports.version = '1.45.1';
7
+ const version = exports.version = '2.0.0-beta.1';
8
8
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["version","exports"],"sourceRoot":"../../src","sources":["version.ts"],"mappings":";;;;;;AAAO,MAAMA,OAAO,GAAAC,OAAA,CAAAD,OAAA,GAAG,QAAQ","ignoreList":[]}
1
+ {"version":3,"names":["version","exports"],"sourceRoot":"../../src","sources":["version.ts"],"mappings":";;;;;;AAAO,MAAMA,OAAO,GAAAC,OAAA,CAAAD,OAAA,GAAG,cAAc","ignoreList":[]}
@@ -127,29 +127,6 @@ export class StreamVideoRN {
127
127
  pushLogoutCallbacks.current = [];
128
128
  }
129
129
 
130
- /**
131
- * Android only. Opt out of the Android 11+ communication-mode keep-alive.
132
- *
133
- * By default the SDK plays a silent voice-communication track for the duration of a
134
- * communicator-role call, so Android does not reset `MODE_IN_COMMUNICATION` ~6s after it is
135
- * set (which breaks audio routing and echo cancellation).
136
- * See {@link https://issuetracker.google.com/issues/209493718}
137
- *
138
- * Call this at app start, alongside {@link setPushConfig} — the native audio manager
139
- * rejects the change once it has been activated for a call. No-op on iOS and on
140
- * Android below API 30.
141
- */
142
- static setDisableCommunicationModeWorkaround(disabled) {
143
- if (Platform.OS !== 'android') {
144
- return;
145
- }
146
- try {
147
- NativeModules.StreamInCallManager?.setDisableCommunicationModeWorkaround(disabled);
148
- } catch (error) {
149
- videoLoggerSystem.getLogger('StreamVideoRN').warn('setDisableCommunicationModeWorkaround failed', error);
150
- }
151
- }
152
-
153
130
  /**
154
131
  * Play native busy tone for call rejection
155
132
  */
@@ -1 +1 @@
1
- {"version":3,"names":["pushLogoutCallbacks","setupIosVoipPushEvents","setupAndroidPushEvents","setupCallingExpEvents","extractCallingExpOptions","getCallingxLib","NativeModules","Platform","videoLoggerSystem","deepMerge","target","source","result","key","undefined","Array","isArray","DEFAULT_STREAM_VIDEO_CONFIG","foregroundService","android","channel","id","name","notificationTexts","title","body","taskToRun","Promise","StreamVideoRN","config","updateConfig","setPushConfig","pushConfig","push","callingx","getLogger","info","JSON","stringify","options","setup","Error","getConfig","onPushLogout","callbacks","current","resolve","all","map","callback","then","clearPushLogoutCallbacks","setDisableCommunicationModeWorkaround","disabled","OS","StreamInCallManager","error","warn","playBusyTone","StreamVideoReactNative","stopBusyTone","androidHasAudioOutputHardware","hasAudioOutputHardware","androidHasMicrophoneHardware","hasMicrophoneHardware","androidHasCameraHardware","hasCameraHardware"],"sourceRoot":"../../../../src","sources":["utils/StreamVideoRN/index.ts"],"mappings":";;AACA,OAAOA,mBAAmB,MAAM,gCAAgC;AAChE,SAASC,sBAAsB,QAAQ,gCAAgC;AACvE,SAASC,sBAAsB,QAAQ,gCAAgC;AACvE,SAASC,qBAAqB,QAAQ,+BAA+B;AACrE,SACEC,wBAAwB,EACxBC,cAAc,QACT,uBAAuB;AAC9B,SAASC,aAAa,EAAEC,QAAQ,QAAQ,cAAc;AACtD,SAASC,iBAAiB,QAAQ,yBAAyB;;AAE3D;;AAKA;AACA,SAASC,SAASA,CAChBC,MAAS,EACTC,MAAsB,EACnB;EACH,MAAMC,MAAM,GAAG;IAAE,GAAGF;EAAO,CAAC;EAE5B,KAAK,MAAMG,GAAG,IAAIF,MAAM,EAAE;IACxB,IAAIA,MAAM,CAACE,GAAG,CAAC,KAAKC,SAAS,EAAE;MAC7B,IACE,OAAOH,MAAM,CAACE,GAAG,CAAC,KAAK,QAAQ,IAC/BF,MAAM,CAACE,GAAG,CAAC,KAAK,IAAI,IACpB,CAACE,KAAK,CAACC,OAAO,CAACL,MAAM,CAACE,GAAG,CAAC,CAAC,IAC3B,OAAOH,MAAM,CAACG,GAAG,CAAC,KAAK,QAAQ,IAC/BH,MAAM,CAACG,GAAG,CAAC,KAAK,IAAI,IACpB,CAACE,KAAK,CAACC,OAAO,CAACN,MAAM,CAACG,GAAG,CAAC,CAAC,EAC3B;QACAD,MAAM,CAACC,GAAG,CAAC,GAAGJ,SAAS,CACrBC,MAAM,CAACG,GAAG,CAAC,EACXF,MAAM,CAACE,GAAG,CACZ,CAAC;MACH,CAAC,MAAM;QACLD,MAAM,CAACC,GAAG,CAAC,GAAGF,MAAM,CAACE,GAAG,CAAkB;MAC5C;IACF;EACF;EAEA,OAAOD,MAAM;AACf;AAEA,MAAMK,2BAA8C,GAAG;EACrDC,iBAAiB,EAAE;IACjBC,OAAO,EAAE;MACPC,OAAO,EAAE;QACPC,EAAE,EAAE,gCAAgC;QACpCC,IAAI,EAAE;MACR,CAAC;MACDC,iBAAiB,EAAE;QACjBC,KAAK,EAAE,kBAAkB;QACzBC,IAAI,EAAE;MACR,CAAC;MACDC,SAAS,EAAEA,CAAA,KAAM,IAAIC,OAAO,CAAC,MAAM,CAAC,CAAC;IACvC;EACF;AACF,CAAC;AAED,OAAO,MAAMC,aAAa,CAAC;EACzB,OAAeC,MAAM,GAAGZ,2BAA2B;;EAEnD;AACF;AACA;AACA;AACA;EACE,OAAOa,YAAYA,CACjBA,YAA0D,EAC1D;IACA,IAAI,CAACD,MAAM,GAAGpB,SAAS,CAAC,IAAI,CAACoB,MAAM,EAAEC,YAAY,CAAC;EACpD;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACE,OAAOC,aAAaA,CAACC,UAAkD,EAAE;IACvE,IAAI,IAAI,CAACH,MAAM,CAACI,IAAI,EAAE;MACpB;MACA;IACF;IAEA,IAAI,CAACJ,MAAM,CAACI,IAAI,GAAGD,UAAU;IAE7B,IAAI;MACF,MAAME,QAAQ,GAAG7B,cAAc,CAAC,CAAC;MACjCG,iBAAiB,CACd2B,SAAS,CAAC,6BAA6B,CAAC,CACxCC,IAAI,CAACC,IAAI,CAACC,SAAS,CAAC,IAAI,CAACT,MAAM,CAAC,CAAC;MACpC,MAAMU,OAAO,GAAGnC,wBAAwB,CAAC,IAAI,CAACyB,MAAM,CAAC;MACrDK,QAAQ,CAACM,KAAK,CAACD,OAAO,CAAC;IACzB,CAAC,CAAC,MAAM;MACN,MAAM,IAAIE,KAAK,CACb,iKACF,CAAC;IACH;IAEAtC,qBAAqB,CAAC6B,UAAU,CAAC;IACjC/B,sBAAsB,CAAC+B,UAAU,CAAC;IAClC9B,sBAAsB,CAAC8B,UAAU,CAAC;EACpC;EAEA,OAAOU,SAASA,CAAA,EAAG;IACjB,OAAO,IAAI,CAACb,MAAM;EACpB;;EAEA;AACF;AACA;AACA;EACE,OAAOc,YAAYA,CAAA,EAAG;IACpB,MAAMC,SAAS,GAAG5C,mBAAmB,CAAC6C,OAAO;IAC7C,IAAI,CAACD,SAAS,EAAE;MACd,OAAOjB,OAAO,CAACmB,OAAO,CAAC,CAAC;IAC1B;IACA9C,mBAAmB,CAAC6C,OAAO,GAAG,EAAE;IAChC,OAAOlB,OAAO,CAACoB,GAAG,CAACH,SAAS,CAACI,GAAG,CAAEC,QAAQ,IAAKA,QAAQ,CAAC,CAAC,CAAC,CAAC,CAACC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;EAC5E;EAEA,OAAOC,wBAAwBA,CAAA,EAAG;IAChCnD,mBAAmB,CAAC6C,OAAO,GAAG,EAAE;EAClC;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACE,OAAOO,qCAAqCA,CAACC,QAAiB,EAAE;IAC9D,IAAI9C,QAAQ,CAAC+C,EAAE,KAAK,SAAS,EAAE;MAC7B;IACF;IACA,IAAI;MACFhD,aAAa,CAACiD,mBAAmB,EAAEH,qCAAqC,CACtEC,QACF,CAAC;IACH,CAAC,CAAC,OAAOG,KAAK,EAAE;MACdhD,iBAAiB,CACd2B,SAAS,CAAC,eAAe,CAAC,CAC1BsB,IAAI,CAAC,8CAA8C,EAAED,KAAK,CAAC;IAChE;EACF;;EAEA;AACF;AACA;EACE,aAAaE,YAAYA,CAAA,EAAG;IAC1B,OAAOpD,aAAa,CAACqD,sBAAsB,CAACD,YAAY,CAAC,CAAC;EAC5D;;EAEA;AACF;AACA;EACE,aAAaE,YAAYA,CAAA,EAAG;IAC1B,OAAOtD,aAAa,CAACqD,sBAAsB,CAACC,YAAY,CAAC,CAAC;EAC5D;;EAEA;AACF;AACA;AACA;EACE,aAAaC,6BAA6BA,CAAA,EAAqB;IAC7D,IAAItD,QAAQ,CAAC+C,EAAE,KAAK,SAAS,EAC3B,MAAM,IAAIb,KAAK,CACb,qEACF,CAAC;IACH,OAAOnC,aAAa,CAACqD,sBAAsB,CAACG,sBAAsB,CAAC,CAAC;EACtE;;EAEA;AACF;AACA;AACA;EACE,aAAaC,4BAA4BA,CAAA,EAAqB;IAC5D,IAAIxD,QAAQ,CAAC+C,EAAE,KAAK,SAAS,EAC3B,MAAM,IAAIb,KAAK,CACb,oEACF,CAAC;IACH,OAAOnC,aAAa,CAACqD,sBAAsB,CAACK,qBAAqB,CAAC,CAAC;EACrE;;EAEA;AACF;AACA;AACA;EACE,aAAaC,wBAAwBA,CAAA,EAAqB;IACxD,IAAI1D,QAAQ,CAAC+C,EAAE,KAAK,SAAS,EAC3B,MAAM,IAAIb,KAAK,CACb,gEACF,CAAC;IACH,OAAOnC,aAAa,CAACqD,sBAAsB,CAACO,iBAAiB,CAAC,CAAC;EACjE;AACF","ignoreList":[]}
1
+ {"version":3,"names":["pushLogoutCallbacks","setupIosVoipPushEvents","setupAndroidPushEvents","setupCallingExpEvents","extractCallingExpOptions","getCallingxLib","NativeModules","Platform","videoLoggerSystem","deepMerge","target","source","result","key","undefined","Array","isArray","DEFAULT_STREAM_VIDEO_CONFIG","foregroundService","android","channel","id","name","notificationTexts","title","body","taskToRun","Promise","StreamVideoRN","config","updateConfig","setPushConfig","pushConfig","push","callingx","getLogger","info","JSON","stringify","options","setup","Error","getConfig","onPushLogout","callbacks","current","resolve","all","map","callback","then","clearPushLogoutCallbacks","playBusyTone","StreamVideoReactNative","stopBusyTone","androidHasAudioOutputHardware","OS","hasAudioOutputHardware","androidHasMicrophoneHardware","hasMicrophoneHardware","androidHasCameraHardware","hasCameraHardware"],"sourceRoot":"../../../../src","sources":["utils/StreamVideoRN/index.ts"],"mappings":"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","ignoreList":[]}
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
 
3
- export const version = '1.45.1';
3
+ export const version = '2.0.0-beta.1';
4
4
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["version"],"sourceRoot":"../../src","sources":["version.ts"],"mappings":";;AAAA,OAAO,MAAMA,OAAO,GAAG,QAAQ","ignoreList":[]}
1
+ {"version":3,"names":["version"],"sourceRoot":"../../src","sources":["version.ts"],"mappings":";;AAAA,OAAO,MAAMA,OAAO,GAAG,cAAc","ignoreList":[]}
@@ -54,19 +54,6 @@ export declare class StreamVideoRN {
54
54
  */
55
55
  static onPushLogout(): Promise<void>;
56
56
  static clearPushLogoutCallbacks(): void;
57
- /**
58
- * Android only. Opt out of the Android 11+ communication-mode keep-alive.
59
- *
60
- * By default the SDK plays a silent voice-communication track for the duration of a
61
- * communicator-role call, so Android does not reset `MODE_IN_COMMUNICATION` ~6s after it is
62
- * set (which breaks audio routing and echo cancellation).
63
- * See {@link https://issuetracker.google.com/issues/209493718}
64
- *
65
- * Call this at app start, alongside {@link setPushConfig} — the native audio manager
66
- * rejects the change once it has been activated for a call. No-op on iOS and on
67
- * Android below API 30.
68
- */
69
- static setDisableCommunicationModeWorkaround(disabled: boolean): void;
70
57
  /**
71
58
  * Play native busy tone for call rejection
72
59
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/utils/StreamVideoRN/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAajD,KAAK,WAAW,CAAC,CAAC,IAAI;KACnB,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAChE,CAAC;AAgDF,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAC,MAAM,CAA+B;IAEpD;;;;OAIG;IACH,MAAM,CAAC,YAAY,CACjB,YAAY,EAAE,WAAW,CAAC,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;IAK5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAmCG;IACH,MAAM,CAAC,aAAa,CAAC,UAAU,EAAE,WAAW,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;IA0BvE,MAAM,CAAC,SAAS;IAIhB;;;OAGG;IACH,MAAM,CAAC,YAAY;IASnB,MAAM,CAAC,wBAAwB;IAI/B;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,qCAAqC,CAAC,QAAQ,EAAE,OAAO;IAe9D;;OAEG;WACU,YAAY;IAIzB;;OAEG;WACU,YAAY;IAIzB;;;OAGG;WACU,6BAA6B,IAAI,OAAO,CAAC,OAAO,CAAC;IAQ9D;;;OAGG;WACU,4BAA4B,IAAI,OAAO,CAAC,OAAO,CAAC;IAQ7D;;;OAGG;WACU,wBAAwB,IAAI,OAAO,CAAC,OAAO,CAAC;CAO1D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/utils/StreamVideoRN/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAajD,KAAK,WAAW,CAAC,CAAC,IAAI;KACnB,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAChE,CAAC;AAgDF,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAC,MAAM,CAA+B;IAEpD;;;;OAIG;IACH,MAAM,CAAC,YAAY,CACjB,YAAY,EAAE,WAAW,CAAC,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;IAK5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAmCG;IACH,MAAM,CAAC,aAAa,CAAC,UAAU,EAAE,WAAW,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;IA0BvE,MAAM,CAAC,SAAS;IAIhB;;;OAGG;IACH,MAAM,CAAC,YAAY;IASnB,MAAM,CAAC,wBAAwB;IAI/B;;OAEG;WACU,YAAY;IAIzB;;OAEG;WACU,YAAY;IAIzB;;;OAGG;WACU,6BAA6B,IAAI,OAAO,CAAC,OAAO,CAAC;IAQ9D;;;OAGG;WACU,4BAA4B,IAAI,OAAO,CAAC,OAAO,CAAC;IAQ7D;;;OAGG;WACU,wBAAwB,IAAI,OAAO,CAAC,OAAO,CAAC;CAO1D"}
@@ -1,2 +1,2 @@
1
- export declare const version = "1.45.1";
1
+ export declare const version = "2.0.0-beta.1";
2
2
  //# sourceMappingURL=version.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,WAAW,CAAC"}
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,iBAAiB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stream-io/video-react-native-sdk",
3
- "version": "1.45.1",
3
+ "version": "2.0.0-beta.1",
4
4
  "description": "Stream Video SDK for React Native",
5
5
  "author": "https://getstream.io",
6
6
  "homepage": "https://getstream.io/video/docs/react-native/",
@@ -52,8 +52,8 @@
52
52
  "!**/.*"
53
53
  ],
54
54
  "dependencies": {
55
- "@stream-io/video-client": "1.59.1",
56
- "@stream-io/video-react-bindings": "1.20.2",
55
+ "@stream-io/video-client": "2.0.0-beta.0",
56
+ "@stream-io/video-react-bindings": "2.0.0-beta.0",
57
57
  "intl-pluralrules": "2.0.1",
58
58
  "react-native-url-polyfill": "^3.0.0",
59
59
  "rxjs": "~7.8.2",
@@ -63,10 +63,10 @@
63
63
  "@react-native-community/netinfo": ">=9.0.0",
64
64
  "@react-native-firebase/app": ">=17.5.0",
65
65
  "@react-native-firebase/messaging": ">=17.5.0",
66
- "@stream-io/noise-cancellation-react-native": ">=0.1.0",
67
- "@stream-io/react-native-callingx": ">=0.1.0",
66
+ "@stream-io/noise-cancellation-react-native": ">=1.0.0-beta.0",
67
+ "@stream-io/react-native-callingx": ">=1.0.0-beta.0",
68
68
  "@stream-io/react-native-webrtc": "^145.3.1",
69
- "@stream-io/video-filters-react-native": ">=0.1.0",
69
+ "@stream-io/video-filters-react-native": ">=1.0.0-beta.0",
70
70
  "expo": ">=47.0.0",
71
71
  "expo-notifications": "*",
72
72
  "react": ">=17.0.0",
@@ -117,11 +117,11 @@
117
117
  "@react-native/babel-preset": "0.86.2",
118
118
  "@react-native/jest-preset": "0.86.2",
119
119
  "@react-native/metro-config": "0.86.2",
120
- "@stream-io/noise-cancellation-react-native": "^0.11.0",
121
- "@stream-io/react-native-callingx": "^0.11.3",
120
+ "@stream-io/noise-cancellation-react-native": "^1.0.0-beta.0",
121
+ "@stream-io/react-native-callingx": "^1.0.0-beta.0",
122
122
  "@stream-io/react-native-webrtc": "145.3.1",
123
123
  "@stream-io/typescript-config": "^0.0.0",
124
- "@stream-io/video-filters-react-native": "^0.16.0",
124
+ "@stream-io/video-filters-react-native": "^1.0.0-beta.0",
125
125
  "@testing-library/jest-native": "^5.4.3",
126
126
  "@testing-library/react-native": "13.3.3",
127
127
  "@tsconfig/node18": "^18.2.6",
@@ -32,20 +32,6 @@ export interface CallManager extends NativeModule {
32
32
  */
33
33
  setTelecomManagedMode: (enabled: boolean) => void;
34
34
 
35
- /**
36
- * Opt out of the Android 11+ communication-mode keep-alive workaround.
37
- *
38
- * On Android 11+ (API 30) the OS resets `MODE_IN_COMMUNICATION` ~6s after it is
39
- * set when there is no active voice-communication playback/recording, which
40
- * breaks audio routing and AEC. By default the SDK plays a silent
41
- * voice-communication track for the duration of a communicator-role call to
42
- * prevent this. Pass `true` to disable it. Sticky for the process lifetime.
43
- *
44
- * No-op on iOS and on Android below API 30. See
45
- * https://issuetracker.google.com/issues/209493718
46
- */
47
- setDisableCommunicationModeWorkaround: (disabled: boolean) => void;
48
-
49
35
  /**
50
36
  * Choose an audio device endpoint by its stable id.
51
37
  * @param deviceId - The id of the audio device to choose (`AudioDevice.id`).
@@ -158,33 +158,6 @@ export class StreamVideoRN {
158
158
  pushLogoutCallbacks.current = [];
159
159
  }
160
160
 
161
- /**
162
- * Android only. Opt out of the Android 11+ communication-mode keep-alive.
163
- *
164
- * By default the SDK plays a silent voice-communication track for the duration of a
165
- * communicator-role call, so Android does not reset `MODE_IN_COMMUNICATION` ~6s after it is
166
- * set (which breaks audio routing and echo cancellation).
167
- * See {@link https://issuetracker.google.com/issues/209493718}
168
- *
169
- * Call this at app start, alongside {@link setPushConfig} — the native audio manager
170
- * rejects the change once it has been activated for a call. No-op on iOS and on
171
- * Android below API 30.
172
- */
173
- static setDisableCommunicationModeWorkaround(disabled: boolean) {
174
- if (Platform.OS !== 'android') {
175
- return;
176
- }
177
- try {
178
- NativeModules.StreamInCallManager?.setDisableCommunicationModeWorkaround(
179
- disabled,
180
- );
181
- } catch (error) {
182
- videoLoggerSystem
183
- .getLogger('StreamVideoRN')
184
- .warn('setDisableCommunicationModeWorkaround failed', error);
185
- }
186
- }
187
-
188
161
  /**
189
162
  * Play native busy tone for call rejection
190
163
  */
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = '1.45.1';
1
+ export const version = '2.0.0-beta.1';
@@ -1,247 +0,0 @@
1
- package com.streamvideo.reactnative.audio
2
-
3
- import android.annotation.SuppressLint
4
- import android.content.Context
5
- import android.content.Context.AUDIO_SERVICE
6
- import android.media.AudioAttributes
7
- import android.media.AudioFormat
8
- import android.media.AudioManager
9
- import android.media.AudioTrack
10
- import android.os.Build
11
- import android.util.Log
12
- import androidx.annotation.RequiresApi
13
- import com.streamvideo.reactnative.callmanager.StreamInCallManagerModule
14
- import java.nio.ByteBuffer
15
- import java.util.concurrent.Executors
16
- import java.util.concurrent.ScheduledExecutorService
17
- import java.util.concurrent.TimeUnit
18
-
19
- /**
20
- * Holds the audio system in [AudioManager.MODE_IN_COMMUNICATION] for the duration
21
- * of a communicator-role call.
22
- *
23
- * Why this is needed: from Android 11 (API 30) the platform demotes the
24
- * audio mode back to `MODE_NORMAL` about six seconds after `setMode()` unless the
25
- * call is actively playing or recording on the voice-communication path.
26
- * During a call whose microphone is muted and that has no inbound audio yet,
27
- * neither condition is met, so routing silently falls back to the media path and
28
- * hardware echo cancellation is switched off.
29
- * Details: https://issuetracker.google.com/issues/209493718
30
- *
31
- * We satisfy the "actively playing" condition by continuously looping an inaudible
32
- * audo track on the voice-communication stream, which keeps the platform counting us
33
- * as an active player and therefore keeps the mode in place.
34
- */
35
- interface CommunicationModeKeepAlive {
36
- /** Begin holding the communication mode. Idempotent. */
37
- fun start()
38
-
39
- /** Stop holding the communication mode. Idempotent; the instance can be started again. */
40
- fun stop()
41
-
42
- /** Permanently release all resources. The instance must not be used afterwards. */
43
- fun release()
44
-
45
- /** Short human-readable state, surfaced in the audio-state debug log. */
46
- fun describeState(): String
47
- }
48
-
49
- /** No-op variant used on platforms where the mode reset does not occur (Android API < 30). */
50
- object NoCommunicationModeKeepAlive : CommunicationModeKeepAlive {
51
- override fun start() {}
52
- override fun stop() {}
53
- override fun release() {}
54
- override fun describeState(): String = "disabled (android platform API < 30)"
55
- }
56
-
57
- /**
58
- * Default implementation backed by a silent, looping voice-communication
59
- * [AudioTrack]. If the silent player cannot be created on a given device, it
60
- * degrades to a lightweight poller that re-applies the mode whenever the platform
61
- * has reset it.
62
- *
63
- * All lifecycle transitions and every access to [track] are serialized on [gate],
64
- * so a play/pause can never overlap a release. The poller only ever touches the
65
- * audio mode (never the track), so it runs lock-free.
66
- *
67
- * @suppress
68
- */
69
- @RequiresApi(Build.VERSION_CODES.R)
70
- internal class SilentPlaybackKeepAlive(
71
- private val context: Context,
72
- ) : CommunicationModeKeepAlive {
73
-
74
- private val gate = Any()
75
-
76
- private var track: AudioTrack? = null
77
-
78
- /** Whether we currently intend the silent player to be running. */
79
- private var engaged = false
80
-
81
- /** Read by the poller (off-gate) to drop ticks that were queued before we stopped. */
82
- @Volatile
83
- private var live = false
84
-
85
- private var modePoller: ScheduledExecutorService? = null
86
-
87
- override fun start(): Unit = synchronized(gate) {
88
- live = true
89
- if (engaged) return
90
- engaged = true
91
-
92
- val player = track ?: createSilentTrack()?.also { track = it }
93
- if (player != null && player.state == AudioTrack.STATE_INITIALIZED && play(player)) {
94
- return
95
- }
96
- // No usable silent player on this device — fall back to reactive repair.
97
- player?.release()
98
- track = null
99
- startModePoller()
100
- }
101
-
102
- /**
103
- * Starts playback, reporting whether the track actually entered the playing state.
104
- * `play()` can throw or leave the track stopped even from STATE_INITIALIZED; treating
105
- * that as success would strand the keep-alive with neither a track nor the poller.
106
- */
107
- private fun play(player: AudioTrack): Boolean =
108
- try {
109
- player.play()
110
- player.playState == AudioTrack.PLAYSTATE_PLAYING
111
- } catch (e: IllegalStateException) {
112
- Log.w(TAG, "Silent keep-alive track refused to start.", e)
113
- false
114
- }
115
-
116
- override fun stop() = synchronized(gate) {
117
- live = false
118
- if (engaged) {
119
- engaged = false
120
- track?.takeIf { it.state == AudioTrack.STATE_INITIALIZED }?.pause()
121
- }
122
- stopModePoller()
123
- }
124
-
125
- override fun release() = synchronized(gate) {
126
- live = false
127
- engaged = false
128
- stopModePoller()
129
- track?.let {
130
- if (it.state == AudioTrack.STATE_INITIALIZED) it.pause()
131
- it.release()
132
- }
133
- track = null
134
- }
135
-
136
- override fun describeState(): String = synchronized(gate) {
137
- val playing = track?.playState == AudioTrack.PLAYSTATE_PLAYING
138
- "enabled, engaged=$engaged, built=${track != null}, playing=$playing, " +
139
- "modePoller=${modePoller != null}"
140
- }
141
-
142
- @SuppressLint("Range")
143
- private fun createSilentTrack(): AudioTrack? {
144
- return try {
145
- val audioManager = context.getSystemService(AUDIO_SERVICE) as AudioManager
146
- val sampleRate = positiveOrDefault(
147
- audioManager.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE)?.toIntOrNull(),
148
- DEFAULT_SAMPLE_RATE,
149
- )
150
- // One buffer worth of frames is enough — we loop it forever.
151
- val frameCount = positiveOrDefault(
152
- audioManager.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER)
153
- ?.toIntOrNull(),
154
- sampleRate / 100, // ~10 ms
155
- )
156
- val bufferBytes = frameCount * BYTES_PER_FRAME
157
- // A freshly allocated direct buffer is zero-filled, i.e. pure silence.
158
- val silence = ByteBuffer.allocateDirect(bufferBytes)
159
-
160
- val player = AudioTrack.Builder()
161
- .setAudioAttributes(
162
- AudioAttributes.Builder()
163
- .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
164
- .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
165
- .build(),
166
- )
167
- .setAudioFormat(
168
- AudioFormat.Builder()
169
- .setEncoding(ENCODING)
170
- .setSampleRate(sampleRate)
171
- .setChannelMask(AudioFormat.CHANNEL_OUT_MONO)
172
- .build(),
173
- )
174
- .setBufferSizeInBytes(bufferBytes)
175
- .setTransferMode(AudioTrack.MODE_STATIC)
176
- .setSessionId(AudioManager.AUDIO_SESSION_ID_GENERATE)
177
- .build()
178
-
179
- val written = player.write(silence, silence.remaining(), AudioTrack.WRITE_BLOCKING)
180
- val loopResult = player.setLoopPoints(0, frameCount - 1, -1)
181
- val ready = player.state == AudioTrack.STATE_INITIALIZED &&
182
- written >= 0 &&
183
- loopResult == AudioTrack.SUCCESS
184
- if (ready) {
185
- player
186
- } else {
187
- Log.w(
188
- TAG,
189
- "Silent keep-alive track not usable " +
190
- "(state=${player.state}, written=$written, loop=$loopResult); discarding.",
191
- )
192
- player.release()
193
- null
194
- }
195
- } catch (e: Exception) {
196
- Log.w(TAG, "Could not create silent keep-alive track.", e)
197
- null
198
- }
199
- }
200
-
201
- private fun startModePoller() {
202
- if (modePoller != null) return
203
- modePoller = Executors.newSingleThreadScheduledExecutor().also { poller ->
204
- poller.scheduleWithFixedDelay(
205
- ::reapplyModeIfReset,
206
- MODE_POLL_INTERVAL_MS,
207
- MODE_POLL_INTERVAL_MS,
208
- TimeUnit.MILLISECONDS,
209
- )
210
- }
211
- }
212
-
213
- private fun reapplyModeIfReset() {
214
- // Read/write the mode on the shared audio thread so it can't race routing changes.
215
- AudioDeviceManager.runInAudioThread {
216
- if (!live) return@runInAudioThread
217
- val audioManager = context.getSystemService(AUDIO_SERVICE) as AudioManager
218
- if (audioManager.mode != AudioManager.MODE_IN_COMMUNICATION) {
219
- Log.d(TAG, "Re-applying MODE_IN_COMMUNICATION after a platform reset.")
220
- audioManager.mode = AudioManager.MODE_IN_COMMUNICATION
221
- }
222
- }
223
- }
224
-
225
- private fun stopModePoller() {
226
- modePoller?.shutdownNow()
227
- modePoller = null
228
- }
229
-
230
- private fun positiveOrDefault(value: Int?, default: Int): Int =
231
- if (value != null && value > 0) value else default
232
-
233
- companion object {
234
- private const val TAG = StreamInCallManagerModule.TAG
235
- private const val DEFAULT_SAMPLE_RATE = 16000
236
- private const val ENCODING = AudioFormat.ENCODING_PCM_16BIT
237
-
238
- // We always emit mono 16-bit PCM, so a frame is exactly 2 bytes.
239
- private const val BYTES_PER_FRAME = 2
240
-
241
- // Fallback poll cadence. Deliberately shorter than AOSP's ~6s reset window: the
242
- // interval bounds only the worst-case wrong-routing gap (<= interval), while the
243
- // real setMode/HAL transition rate stays governed by the OS re-arm, so polling
244
- // faster only costs cheap reads and shortens the recovery latency.
245
- private const val MODE_POLL_INTERVAL_MS = 2000L
246
- }
247
- }