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