@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/dist/index.cjs.js CHANGED
@@ -3898,6 +3898,8 @@ class StreamVideoWriteableStateStore {
3898
3898
  * @param call the call to remove
3899
3899
  */
3900
3900
  this.unregisterCall = (call) => {
3901
+ const logger = getLogger(['client-state']);
3902
+ logger('trace', `Unregistering call: ${call.cid}`);
3901
3903
  return this.setCalls((calls) => calls.filter((c) => c !== call));
3902
3904
  };
3903
3905
  /**
@@ -5183,11 +5185,14 @@ class BasePeerConnection {
5183
5185
  */
5184
5186
  constructor(peerType, { sfuClient, connectionConfig, state, dispatcher, onUnrecoverableError, logTag, }) {
5185
5187
  this.isIceRestarting = false;
5188
+ this.isDisposed = false;
5186
5189
  this.subscriptions = [];
5187
5190
  /**
5188
5191
  * Disposes the `RTCPeerConnection` instance.
5189
5192
  */
5190
5193
  this.dispose = () => {
5194
+ this.onUnrecoverableError = undefined;
5195
+ this.isDisposed = true;
5191
5196
  this.detachEventHandlers();
5192
5197
  this.pc.close();
5193
5198
  };
@@ -5198,6 +5203,8 @@ class BasePeerConnection {
5198
5203
  this.on = (event, fn) => {
5199
5204
  this.subscriptions.push(this.dispatcher.on(event, (e) => {
5200
5205
  withoutConcurrency(`pc.${event}`, async () => fn(e)).catch((err) => {
5206
+ if (this.isDisposed)
5207
+ return;
5201
5208
  this.logger('warn', `Error handling ${event}`, err);
5202
5209
  });
5203
5210
  }));
@@ -5213,6 +5220,8 @@ class BasePeerConnection {
5213
5220
  this.unsubscribeIceTrickle?.();
5214
5221
  this.unsubscribeIceTrickle = createSafeAsyncSubscription(observable, async (candidate) => {
5215
5222
  return this.pc.addIceCandidate(candidate).catch((e) => {
5223
+ if (this.isDisposed)
5224
+ return;
5216
5225
  this.logger('warn', `ICE candidate error`, e, candidate);
5217
5226
  });
5218
5227
  });
@@ -5245,7 +5254,11 @@ class BasePeerConnection {
5245
5254
  const iceCandidate = this.toJSON(candidate);
5246
5255
  this.sfuClient
5247
5256
  .iceTrickle({ peerType: this.peerType, iceCandidate })
5248
- .catch((err) => this.logger('warn', `ICETrickle failed`, err));
5257
+ .catch((err) => {
5258
+ if (this.isDisposed)
5259
+ return;
5260
+ this.logger('warn', `ICETrickle failed`, err);
5261
+ });
5249
5262
  };
5250
5263
  /**
5251
5264
  * Converts the ICE candidate to a JSON string.
@@ -5274,6 +5287,8 @@ class BasePeerConnection {
5274
5287
  if (state === 'failed' || state === 'disconnected') {
5275
5288
  this.logger('debug', `Attempting to restart ICE`);
5276
5289
  this.restartIce().catch((e) => {
5290
+ if (this.isDisposed)
5291
+ return;
5277
5292
  this.logger('error', `ICE restart failed`, e);
5278
5293
  this.onUnrecoverableError?.();
5279
5294
  });
@@ -5325,6 +5340,8 @@ class BasePeerConnection {
5325
5340
  this.pc.removeEventListener('icecandidateerror', this.onIceCandidateError);
5326
5341
  this.pc.removeEventListener('signalingstatechange', this.onSignalingChange);
5327
5342
  this.pc.removeEventListener('iceconnectionstatechange', this.onIceConnectionStateChange);
5343
+ // cancel any ongoing ICE restart process
5344
+ withCancellation('onIceConnectionStateChange', () => Promise.resolve());
5328
5345
  this.pc.removeEventListener('icegatheringstatechange', this.onIceGatherChange);
5329
5346
  this.unsubscribeIceTrickle?.();
5330
5347
  this.subscriptions.forEach((unsubscribe) => unsubscribe());
@@ -5840,10 +5857,12 @@ class Publisher extends BasePeerConnection {
5840
5857
  await this.negotiate({ iceRestart: true });
5841
5858
  };
5842
5859
  this.onNegotiationNeeded = () => {
5843
- withoutConcurrency('publisher.negotiate', () => this.negotiate()).catch((err) => {
5860
+ withCancellation('publisher.negotiate', (signal) => this.negotiate().catch((err) => {
5861
+ if (signal.aborted)
5862
+ return;
5844
5863
  this.logger('error', `Negotiation failed.`, err);
5845
5864
  this.onUnrecoverableError?.();
5846
- });
5865
+ }));
5847
5866
  };
5848
5867
  /**
5849
5868
  * Initiates a new offer/answer exchange with the currently connected SFU.
@@ -5970,6 +5989,8 @@ class Publisher extends BasePeerConnection {
5970
5989
  detachEventHandlers() {
5971
5990
  super.detachEventHandlers();
5972
5991
  this.pc.removeEventListener('negotiationneeded', this.onNegotiationNeeded);
5992
+ // abort any ongoing negotiation
5993
+ withCancellation('publisher.negotiate', () => Promise.resolve());
5973
5994
  }
5974
5995
  }
5975
5996
 
@@ -7394,7 +7415,7 @@ const aggregate = (stats) => {
7394
7415
  return report;
7395
7416
  };
7396
7417
 
7397
- const version = "1.16.0";
7418
+ const version = "1.16.2";
7398
7419
  const [major, minor, patch] = version.split('.');
7399
7420
  let sdkInfo = {
7400
7421
  type: SdkType.PLAIN_JAVASCRIPT,
@@ -9251,10 +9272,34 @@ class CameraManager extends InputMediaDeviceManager {
9251
9272
  */
9252
9273
  async selectDirection(direction) {
9253
9274
  if (this.isDirectionSupportedByDevice()) {
9254
- this.state.setDirection(direction);
9255
- // Providing both device id and direction doesn't work, so we deselect the device
9256
- this.state.setDevice(undefined);
9257
- await this.applySettingsToStream();
9275
+ if (isReactNative()) {
9276
+ const videoTrack = this.getTracks()[0];
9277
+ if (!videoTrack)
9278
+ return;
9279
+ // @ts-expect-error _switchCamera() is only present in react-native-webrtc 124 and below
9280
+ if (typeof videoTrack._switchCamera === 'function') {
9281
+ // @ts-expect-error for older versions of react-native-webrtc support
9282
+ videoTrack._switchCamera();
9283
+ }
9284
+ else {
9285
+ const constraints = {
9286
+ facingMode: direction === 'front' ? 'user' : 'environment',
9287
+ };
9288
+ await videoTrack.applyConstraints(constraints);
9289
+ }
9290
+ this.state.setDirection(direction);
9291
+ this.state.setDevice(undefined);
9292
+ }
9293
+ else {
9294
+ // web mobile
9295
+ this.state.setDirection(direction);
9296
+ // Providing both device id and direction doesn't work, so we deselect the device
9297
+ this.state.setDevice(undefined);
9298
+ this.getTracks().forEach((track) => {
9299
+ track.stop();
9300
+ });
9301
+ await this.unmuteStream();
9302
+ }
9258
9303
  }
9259
9304
  else {
9260
9305
  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
  };