@stream-io/video-client 1.12.2 → 1.12.4

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,24 @@
2
2
 
3
3
  This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
4
4
 
5
+ ## [1.12.4](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.12.3...@stream-io/video-client-1.12.4) (2024-12-17)
6
+
7
+
8
+ * improve test coverage reporting ([#1624](https://github.com/GetStream/stream-video-js/issues/1624)) ([32bb870](https://github.com/GetStream/stream-video-js/commit/32bb870187f0627c32d2b5692ce3de633d743582))
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * adjust dynascale debouncing for upscaling and downscaling ([#1621](https://github.com/GetStream/stream-video-js/issues/1621)) [skip ci] ([7b3a721](https://github.com/GetStream/stream-video-js/commit/7b3a72192fab79d8af8d1c392a9f0135e2d25b16))
14
+ * prevent auto-dropping already accepted or rejected calls ([#1619](https://github.com/GetStream/stream-video-js/issues/1619)) ([113406a](https://github.com/GetStream/stream-video-js/commit/113406a9ba7fdf2e193a1933b73963e0011f28f0))
15
+
16
+ ## [1.12.3](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.12.2...@stream-io/video-client-1.12.3) (2024-12-13)
17
+
18
+
19
+ ### Bug Fixes
20
+
21
+ * multiple rare ringing issues in react-native ([#1611](https://github.com/GetStream/stream-video-js/issues/1611)) ([4e25264](https://github.com/GetStream/stream-video-js/commit/4e25264808eab469b7b7ab184fb19961d47bdff3))
22
+
5
23
  ## [1.12.2](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.12.1...@stream-io/video-client-1.12.2) (2024-12-11)
6
24
 
7
25
 
@@ -3299,7 +3299,7 @@ const retryable = async (rpc, signal) => {
3299
3299
  return result;
3300
3300
  };
3301
3301
 
3302
- const version = "1.12.2";
3302
+ const version = "1.12.4";
3303
3303
  const [major, minor, patch] = version.split('.');
3304
3304
  let sdkInfo = {
3305
3305
  type: SdkType.PLAIN_JAVASCRIPT,
@@ -7955,17 +7955,27 @@ class DynascaleManager {
7955
7955
  const resizeObserver = boundParticipant.isLocalParticipant
7956
7956
  ? null
7957
7957
  : new ResizeObserver(() => {
7958
- const currentDimensions = `${videoElement.clientWidth},${videoElement.clientHeight}`;
7958
+ const currentDimensions = {
7959
+ width: videoElement.clientWidth,
7960
+ height: videoElement.clientHeight,
7961
+ };
7959
7962
  // skip initial trigger
7960
7963
  if (!lastDimensions) {
7961
7964
  lastDimensions = currentDimensions;
7962
7965
  return;
7963
7966
  }
7964
- if (lastDimensions === currentDimensions ||
7967
+ if ((lastDimensions.width === currentDimensions.width &&
7968
+ lastDimensions.height === currentDimensions.height) ||
7965
7969
  viewportVisibilityState === VisibilityState.INVISIBLE) {
7966
7970
  return;
7967
7971
  }
7968
- requestTrackWithDimensions(DebounceType.SLOW, {
7972
+ const relativeDelta = Math.max(currentDimensions.width / lastDimensions.width, currentDimensions.height / lastDimensions.height);
7973
+ // Low quality video in an upscaled video element is very noticable.
7974
+ // We try to upscale faster, and downscale slower. We also update debounce
7975
+ // more if the size change is not significant, gurading against fast-firing
7976
+ // resize events.
7977
+ const debounceType = relativeDelta > 1.2 ? DebounceType.IMMEDIATE : DebounceType.MEDIUM;
7978
+ requestTrackWithDimensions(debounceType, {
7969
7979
  width: videoElement.clientWidth,
7970
7980
  height: videoElement.clientHeight,
7971
7981
  });
@@ -7981,7 +7991,7 @@ class DynascaleManager {
7981
7991
  .subscribe((isPublishing) => {
7982
7992
  if (isPublishing) {
7983
7993
  // the participant just started to publish a track
7984
- requestTrackWithDimensions(DebounceType.FAST, {
7994
+ requestTrackWithDimensions(DebounceType.IMMEDIATE, {
7985
7995
  width: videoElement.clientWidth,
7986
7996
  height: videoElement.clientHeight,
7987
7997
  });
@@ -8321,7 +8331,7 @@ class BrowserPermission {
8321
8331
  (this.wasPrompted && !forcePrompt)) {
8322
8332
  const isGranted = this.state === 'granted';
8323
8333
  if (!isGranted && throwOnNotAllowed) {
8324
- throw new DOMException('Permission was not granted previously, and prompting again is not allowed', 'NotAllowedError');
8334
+ throw new Error('Permission was not granted previously, and prompting again is not allowed');
8325
8335
  }
8326
8336
  return isGranted;
8327
8337
  }
@@ -8333,7 +8343,10 @@ class BrowserPermission {
8333
8343
  return true;
8334
8344
  }
8335
8345
  catch (e) {
8336
- if (e instanceof DOMException && e.name === 'NotAllowedError') {
8346
+ if (e &&
8347
+ typeof e === 'object' &&
8348
+ 'name' in e &&
8349
+ (e.name === 'NotAllowedError' || e.name === 'SecurityError')) {
8337
8350
  this.logger('info', 'Browser permission was not granted', {
8338
8351
  permission: this.permission,
8339
8352
  });
@@ -8488,6 +8501,14 @@ const getStream = async (constraints) => {
8488
8501
  }
8489
8502
  return stream;
8490
8503
  };
8504
+ function isOverconstrainedError(error) {
8505
+ return (error &&
8506
+ typeof error === 'object' &&
8507
+ (('name' in error && error.name === 'OverconstrainedError') ||
8508
+ ('message' in error &&
8509
+ typeof error.message === 'string' &&
8510
+ error.message.startsWith('OverconstrainedError'))));
8511
+ }
8491
8512
  /**
8492
8513
  * Returns an audio media stream that fulfills the given constraints.
8493
8514
  * If no constraints are provided, it uses the browser's default ones.
@@ -8511,12 +8532,10 @@ const getAudioStream = async (trackConstraints) => {
8511
8532
  return await getStream(constraints);
8512
8533
  }
8513
8534
  catch (error) {
8514
- if (error instanceof DOMException &&
8515
- error.name === 'OverconstrainedError' &&
8516
- trackConstraints?.deviceId) {
8517
- const { deviceId, ...relaxedContraints } = trackConstraints;
8518
- getLogger(['devices'])('warn', 'Failed to get audio stream, will try again with relaxed contraints', { error, constraints, relaxedContraints });
8519
- return getAudioStream(relaxedContraints);
8535
+ if (isOverconstrainedError(error) && trackConstraints?.deviceId) {
8536
+ const { deviceId, ...relaxedConstraints } = trackConstraints;
8537
+ getLogger(['devices'])('warn', 'Failed to get audio stream, will try again with relaxed constraints', { error, constraints, relaxedConstraints });
8538
+ return getAudioStream(relaxedConstraints);
8520
8539
  }
8521
8540
  getLogger(['devices'])('error', 'Failed to get audio stream', {
8522
8541
  error,
@@ -8548,12 +8567,10 @@ const getVideoStream = async (trackConstraints) => {
8548
8567
  return await getStream(constraints);
8549
8568
  }
8550
8569
  catch (error) {
8551
- if (error instanceof DOMException &&
8552
- error.name === 'OverconstrainedError' &&
8553
- trackConstraints?.deviceId) {
8554
- const { deviceId, ...relaxedContraints } = trackConstraints;
8555
- getLogger(['devices'])('warn', 'Failed to get video stream, will try again with relaxed contraints', { error, constraints, relaxedContraints });
8556
- return getVideoStream(relaxedContraints);
8570
+ if (isOverconstrainedError(error) && trackConstraints?.deviceId) {
8571
+ const { deviceId, ...relaxedConstraints } = trackConstraints;
8572
+ getLogger(['devices'])('warn', 'Failed to get video stream, will try again with relaxed constraints', { error, constraints, relaxedConstraints });
8573
+ return getVideoStream(relaxedConstraints);
8557
8574
  }
8558
8575
  getLogger(['devices'])('error', 'Failed to get video stream', {
8559
8576
  error,
@@ -11254,26 +11271,35 @@ class Call {
11254
11271
  * Applicable only for ringing calls.
11255
11272
  */
11256
11273
  this.scheduleAutoDrop = () => {
11257
- clearTimeout(this.dropTimeout);
11258
- this.leaveCallHooks.add(createSubscription(this.state.settings$, (settings) => {
11259
- if (!settings)
11260
- return;
11261
- // ignore if the call is not ringing
11274
+ this.cancelAutoDrop();
11275
+ const settings = this.state.settings;
11276
+ if (!settings)
11277
+ return;
11278
+ // ignore if the call is not ringing
11279
+ if (this.state.callingState !== CallingState.RINGING)
11280
+ return;
11281
+ const timeoutInMs = this.isCreatedByMe
11282
+ ? settings.ring.auto_cancel_timeout_ms
11283
+ : settings.ring.incoming_call_timeout_ms;
11284
+ // 0 means no auto-drop
11285
+ if (timeoutInMs <= 0)
11286
+ return;
11287
+ this.dropTimeout = setTimeout(() => {
11288
+ // the call might have stopped ringing by this point,
11289
+ // e.g. it was already accepted and joined
11262
11290
  if (this.state.callingState !== CallingState.RINGING)
11263
11291
  return;
11264
- const timeoutInMs = this.isCreatedByMe
11265
- ? settings.ring.auto_cancel_timeout_ms
11266
- : settings.ring.incoming_call_timeout_ms;
11267
- // 0 means no auto-drop
11268
- if (timeoutInMs <= 0)
11269
- return;
11270
- clearTimeout(this.dropTimeout);
11271
- this.dropTimeout = setTimeout(() => {
11272
- this.leave({ reject: true, reason: 'timeout' }).catch((err) => {
11273
- this.logger('error', 'Failed to drop call', err);
11274
- });
11275
- }, timeoutInMs);
11276
- }));
11292
+ this.leave({ reject: true, reason: 'timeout' }).catch((err) => {
11293
+ this.logger('error', 'Failed to drop call', err);
11294
+ });
11295
+ }, timeoutInMs);
11296
+ };
11297
+ /**
11298
+ * Cancels a scheduled auto-drop timeout.
11299
+ */
11300
+ this.cancelAutoDrop = () => {
11301
+ clearTimeout(this.dropTimeout);
11302
+ this.dropTimeout = undefined;
11277
11303
  };
11278
11304
  /**
11279
11305
  * Retrieves the list of recordings for the current call or call session.
@@ -11609,15 +11635,17 @@ class Call {
11609
11635
  }
11610
11636
  }));
11611
11637
  this.leaveCallHooks.add(
11612
- // watch for auto drop cancellation
11613
- createSubscription(this.state.callingState$, (callingState) => {
11638
+ // cancel auto-drop when call is
11639
+ createSubscription(this.state.session$, (session) => {
11614
11640
  if (!this.ringing)
11615
11641
  return;
11616
- if (callingState === CallingState.JOINED ||
11617
- callingState === CallingState.JOINING ||
11618
- callingState === CallingState.LEFT) {
11619
- clearTimeout(this.dropTimeout);
11620
- this.dropTimeout = undefined;
11642
+ const receiverId = this.clientStore.connectedUser?.id;
11643
+ if (!receiverId)
11644
+ return;
11645
+ const isAcceptedByMe = Boolean(session?.accepted_by[receiverId]);
11646
+ const isRejectedByMe = Boolean(session?.rejected_by[receiverId]);
11647
+ if (isAcceptedByMe || isRejectedByMe) {
11648
+ this.cancelAutoDrop();
11621
11649
  }
11622
11650
  }));
11623
11651
  this.leaveCallHooks.add(
@@ -12804,7 +12832,7 @@ class StreamClient {
12804
12832
  return await this.wsConnection.connect(this.defaultWSTimeout);
12805
12833
  };
12806
12834
  this.getUserAgent = () => {
12807
- const version = "1.12.2";
12835
+ const version = "1.12.4";
12808
12836
  return (this.userAgent ||
12809
12837
  `stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${version}`);
12810
12838
  };