@stream-io/video-client 1.16.0 → 1.16.2

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,6 +2,23 @@
2
2
 
3
3
  This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
4
4
 
5
+ ## [1.16.2](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.16.1...@stream-io/video-client-1.16.2) (2025-02-05)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * race condition with unrecoverable error handling ([#1672](https://github.com/GetStream/stream-video-js/issues/1672)) ([be8095c](https://github.com/GetStream/stream-video-js/commit/be8095ce946cf98a0dfc1f3ea3391376cc7d2896)), closes [#1649](https://github.com/GetStream/stream-video-js/issues/1649) [#1618](https://github.com/GetStream/stream-video-js/issues/1618)
11
+
12
+ ## [1.16.1](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.16.0...@stream-io/video-client-1.16.1) (2025-02-05)
13
+
14
+
15
+ * add trace log for call unregister ([e20d9dc](https://github.com/GetStream/stream-video-js/commit/e20d9dc28b35c5dd0c921ccc3e18923a344ae5ab))
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * do not mute track on camera flip ([#1671](https://github.com/GetStream/stream-video-js/issues/1671)) ([963eb4d](https://github.com/GetStream/stream-video-js/commit/963eb4d4e5d6b96afb61b4da23a05ad92bcb3973))
21
+
5
22
  ## [1.16.0](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.15.7...@stream-io/video-client-1.16.0) (2025-01-31)
6
23
 
7
24
 
@@ -3896,6 +3896,8 @@ class StreamVideoWriteableStateStore {
3896
3896
  * @param call the call to remove
3897
3897
  */
3898
3898
  this.unregisterCall = (call) => {
3899
+ const logger = getLogger(['client-state']);
3900
+ logger('trace', `Unregistering call: ${call.cid}`);
3899
3901
  return this.setCalls((calls) => calls.filter((c) => c !== call));
3900
3902
  };
3901
3903
  /**
@@ -5181,11 +5183,14 @@ class BasePeerConnection {
5181
5183
  */
5182
5184
  constructor(peerType, { sfuClient, connectionConfig, state, dispatcher, onUnrecoverableError, logTag, }) {
5183
5185
  this.isIceRestarting = false;
5186
+ this.isDisposed = false;
5184
5187
  this.subscriptions = [];
5185
5188
  /**
5186
5189
  * Disposes the `RTCPeerConnection` instance.
5187
5190
  */
5188
5191
  this.dispose = () => {
5192
+ this.onUnrecoverableError = undefined;
5193
+ this.isDisposed = true;
5189
5194
  this.detachEventHandlers();
5190
5195
  this.pc.close();
5191
5196
  };
@@ -5196,6 +5201,8 @@ class BasePeerConnection {
5196
5201
  this.on = (event, fn) => {
5197
5202
  this.subscriptions.push(this.dispatcher.on(event, (e) => {
5198
5203
  withoutConcurrency(`pc.${event}`, async () => fn(e)).catch((err) => {
5204
+ if (this.isDisposed)
5205
+ return;
5199
5206
  this.logger('warn', `Error handling ${event}`, err);
5200
5207
  });
5201
5208
  }));
@@ -5211,6 +5218,8 @@ class BasePeerConnection {
5211
5218
  this.unsubscribeIceTrickle?.();
5212
5219
  this.unsubscribeIceTrickle = createSafeAsyncSubscription(observable, async (candidate) => {
5213
5220
  return this.pc.addIceCandidate(candidate).catch((e) => {
5221
+ if (this.isDisposed)
5222
+ return;
5214
5223
  this.logger('warn', `ICE candidate error`, e, candidate);
5215
5224
  });
5216
5225
  });
@@ -5243,7 +5252,11 @@ class BasePeerConnection {
5243
5252
  const iceCandidate = this.toJSON(candidate);
5244
5253
  this.sfuClient
5245
5254
  .iceTrickle({ peerType: this.peerType, iceCandidate })
5246
- .catch((err) => this.logger('warn', `ICETrickle failed`, err));
5255
+ .catch((err) => {
5256
+ if (this.isDisposed)
5257
+ return;
5258
+ this.logger('warn', `ICETrickle failed`, err);
5259
+ });
5247
5260
  };
5248
5261
  /**
5249
5262
  * Converts the ICE candidate to a JSON string.
@@ -5272,6 +5285,8 @@ class BasePeerConnection {
5272
5285
  if (state === 'failed' || state === 'disconnected') {
5273
5286
  this.logger('debug', `Attempting to restart ICE`);
5274
5287
  this.restartIce().catch((e) => {
5288
+ if (this.isDisposed)
5289
+ return;
5275
5290
  this.logger('error', `ICE restart failed`, e);
5276
5291
  this.onUnrecoverableError?.();
5277
5292
  });
@@ -5323,6 +5338,8 @@ class BasePeerConnection {
5323
5338
  this.pc.removeEventListener('icecandidateerror', this.onIceCandidateError);
5324
5339
  this.pc.removeEventListener('signalingstatechange', this.onSignalingChange);
5325
5340
  this.pc.removeEventListener('iceconnectionstatechange', this.onIceConnectionStateChange);
5341
+ // cancel any ongoing ICE restart process
5342
+ withCancellation('onIceConnectionStateChange', () => Promise.resolve());
5326
5343
  this.pc.removeEventListener('icegatheringstatechange', this.onIceGatherChange);
5327
5344
  this.unsubscribeIceTrickle?.();
5328
5345
  this.subscriptions.forEach((unsubscribe) => unsubscribe());
@@ -5838,10 +5855,12 @@ class Publisher extends BasePeerConnection {
5838
5855
  await this.negotiate({ iceRestart: true });
5839
5856
  };
5840
5857
  this.onNegotiationNeeded = () => {
5841
- withoutConcurrency('publisher.negotiate', () => this.negotiate()).catch((err) => {
5858
+ withCancellation('publisher.negotiate', (signal) => this.negotiate().catch((err) => {
5859
+ if (signal.aborted)
5860
+ return;
5842
5861
  this.logger('error', `Negotiation failed.`, err);
5843
5862
  this.onUnrecoverableError?.();
5844
- });
5863
+ }));
5845
5864
  };
5846
5865
  /**
5847
5866
  * Initiates a new offer/answer exchange with the currently connected SFU.
@@ -5968,6 +5987,8 @@ class Publisher extends BasePeerConnection {
5968
5987
  detachEventHandlers() {
5969
5988
  super.detachEventHandlers();
5970
5989
  this.pc.removeEventListener('negotiationneeded', this.onNegotiationNeeded);
5990
+ // abort any ongoing negotiation
5991
+ withCancellation('publisher.negotiate', () => Promise.resolve());
5971
5992
  }
5972
5993
  }
5973
5994
 
@@ -7392,7 +7413,7 @@ const aggregate = (stats) => {
7392
7413
  return report;
7393
7414
  };
7394
7415
 
7395
- const version = "1.16.0";
7416
+ const version = "1.16.2";
7396
7417
  const [major, minor, patch] = version.split('.');
7397
7418
  let sdkInfo = {
7398
7419
  type: SdkType.PLAIN_JAVASCRIPT,
@@ -9249,10 +9270,34 @@ class CameraManager extends InputMediaDeviceManager {
9249
9270
  */
9250
9271
  async selectDirection(direction) {
9251
9272
  if (this.isDirectionSupportedByDevice()) {
9252
- this.state.setDirection(direction);
9253
- // Providing both device id and direction doesn't work, so we deselect the device
9254
- this.state.setDevice(undefined);
9255
- await this.applySettingsToStream();
9273
+ if (isReactNative()) {
9274
+ const videoTrack = this.getTracks()[0];
9275
+ if (!videoTrack)
9276
+ return;
9277
+ // @ts-expect-error _switchCamera() is only present in react-native-webrtc 124 and below
9278
+ if (typeof videoTrack._switchCamera === 'function') {
9279
+ // @ts-expect-error for older versions of react-native-webrtc support
9280
+ videoTrack._switchCamera();
9281
+ }
9282
+ else {
9283
+ const constraints = {
9284
+ facingMode: direction === 'front' ? 'user' : 'environment',
9285
+ };
9286
+ await videoTrack.applyConstraints(constraints);
9287
+ }
9288
+ this.state.setDirection(direction);
9289
+ this.state.setDevice(undefined);
9290
+ }
9291
+ else {
9292
+ // web mobile
9293
+ this.state.setDirection(direction);
9294
+ // Providing both device id and direction doesn't work, so we deselect the device
9295
+ this.state.setDevice(undefined);
9296
+ this.getTracks().forEach((track) => {
9297
+ track.stop();
9298
+ });
9299
+ await this.unmuteStream();
9300
+ }
9256
9301
  }
9257
9302
  else {
9258
9303
  this.logger('warn', 'Camera direction ignored for desktop devices');
@@ -12975,7 +13020,7 @@ class StreamClient {
12975
13020
  return await this.wsConnection.connect(this.defaultWSTimeout);
12976
13021
  };
12977
13022
  this.getUserAgent = () => {
12978
- const version = "1.16.0";
13023
+ const version = "1.16.2";
12979
13024
  return (this.userAgent ||
12980
13025
  `stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${version}`);
12981
13026
  };