@stream-io/video-client 1.12.3 → 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.
@@ -540,6 +540,10 @@ export declare class Call {
540
540
  * Applicable only for ringing calls.
541
541
  */
542
542
  private scheduleAutoDrop;
543
+ /**
544
+ * Cancels a scheduled auto-drop timeout.
545
+ */
546
+ private cancelAutoDrop;
543
547
  /**
544
548
  * Retrieves the list of recordings for the current call or call session.
545
549
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stream-io/video-client",
3
- "version": "1.12.3",
3
+ "version": "1.12.4",
4
4
  "packageManager": "yarn@3.2.4",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.es.js",
@@ -13,7 +13,7 @@
13
13
  "start": "rollup -w -c",
14
14
  "build": "yarn clean && rollup -c",
15
15
  "test": "vitest",
16
- "test-ci": "vitest --coverage",
16
+ "test-ci": "vitest run --coverage",
17
17
  "generate:open-api": "./generate-openapi.sh protocol",
18
18
  "generate:open-api:dev": "./generate-openapi.sh chat",
19
19
  "generate:timer-worker": "./generate-timer-worker.sh"
@@ -45,7 +45,7 @@
45
45
  "@stream-io/node-sdk": "^0.4.3",
46
46
  "@types/sdp-transform": "^2.4.7",
47
47
  "@types/ua-parser-js": "^0.7.37",
48
- "@vitest/coverage-v8": "^2.1.4",
48
+ "@vitest/coverage-v8": "^2.1.8",
49
49
  "dotenv": "^16.3.1",
50
50
  "happy-dom": "^11.0.2",
51
51
  "prettier": "^3.3.2",
@@ -53,7 +53,7 @@
53
53
  "rollup": "^4.22.0",
54
54
  "typescript": "^5.5.2",
55
55
  "vite": "^5.4.6",
56
- "vitest": "^2.1.4",
56
+ "vitest": "^2.1.8",
57
57
  "vitest-mock-extended": "^2.0.2"
58
58
  }
59
59
  }
package/src/Call.ts CHANGED
@@ -342,16 +342,18 @@ export class Call {
342
342
  );
343
343
 
344
344
  this.leaveCallHooks.add(
345
- // watch for auto drop cancellation
346
- createSubscription(this.state.callingState$, (callingState) => {
345
+ // cancel auto-drop when call is
346
+ createSubscription(this.state.session$, (session) => {
347
347
  if (!this.ringing) return;
348
- if (
349
- callingState === CallingState.JOINED ||
350
- callingState === CallingState.JOINING ||
351
- callingState === CallingState.LEFT
352
- ) {
353
- clearTimeout(this.dropTimeout);
354
- this.dropTimeout = undefined;
348
+
349
+ const receiverId = this.clientStore.connectedUser?.id;
350
+ if (!receiverId) return;
351
+
352
+ const isAcceptedByMe = Boolean(session?.accepted_by[receiverId]);
353
+ const isRejectedByMe = Boolean(session?.rejected_by[receiverId]);
354
+
355
+ if (isAcceptedByMe || isRejectedByMe) {
356
+ this.cancelAutoDrop();
355
357
  }
356
358
  }),
357
359
  );
@@ -2004,28 +2006,36 @@ export class Call {
2004
2006
  * Applicable only for ringing calls.
2005
2007
  */
2006
2008
  private scheduleAutoDrop = () => {
2007
- clearTimeout(this.dropTimeout);
2008
- this.leaveCallHooks.add(
2009
- createSubscription(this.state.settings$, (settings) => {
2010
- if (!settings) return;
2011
- // ignore if the call is not ringing
2012
- if (this.state.callingState !== CallingState.RINGING) return;
2013
-
2014
- const timeoutInMs = this.isCreatedByMe
2015
- ? settings.ring.auto_cancel_timeout_ms
2016
- : settings.ring.incoming_call_timeout_ms;
2017
-
2018
- // 0 means no auto-drop
2019
- if (timeoutInMs <= 0) return;
2009
+ this.cancelAutoDrop();
2010
+
2011
+ const settings = this.state.settings;
2012
+ if (!settings) return;
2013
+ // ignore if the call is not ringing
2014
+ if (this.state.callingState !== CallingState.RINGING) return;
2015
+
2016
+ const timeoutInMs = this.isCreatedByMe
2017
+ ? settings.ring.auto_cancel_timeout_ms
2018
+ : settings.ring.incoming_call_timeout_ms;
2019
+
2020
+ // 0 means no auto-drop
2021
+ if (timeoutInMs <= 0) return;
2022
+
2023
+ this.dropTimeout = setTimeout(() => {
2024
+ // the call might have stopped ringing by this point,
2025
+ // e.g. it was already accepted and joined
2026
+ if (this.state.callingState !== CallingState.RINGING) return;
2027
+ this.leave({ reject: true, reason: 'timeout' }).catch((err) => {
2028
+ this.logger('error', 'Failed to drop call', err);
2029
+ });
2030
+ }, timeoutInMs);
2031
+ };
2020
2032
 
2021
- clearTimeout(this.dropTimeout);
2022
- this.dropTimeout = setTimeout(() => {
2023
- this.leave({ reject: true, reason: 'timeout' }).catch((err) => {
2024
- this.logger('error', 'Failed to drop call', err);
2025
- });
2026
- }, timeoutInMs);
2027
- }),
2028
- );
2033
+ /**
2034
+ * Cancels a scheduled auto-drop timeout.
2035
+ */
2036
+ private cancelAutoDrop = () => {
2037
+ clearTimeout(this.dropTimeout);
2038
+ this.dropTimeout = undefined;
2029
2039
  };
2030
2040
 
2031
2041
  /**
@@ -371,11 +371,14 @@ export class DynascaleManager {
371
371
  });
372
372
  });
373
373
 
374
- let lastDimensions: string | undefined;
374
+ let lastDimensions: VideoDimension | undefined;
375
375
  const resizeObserver = boundParticipant.isLocalParticipant
376
376
  ? null
377
377
  : new ResizeObserver(() => {
378
- const currentDimensions = `${videoElement.clientWidth},${videoElement.clientHeight}`;
378
+ const currentDimensions = {
379
+ width: videoElement.clientWidth,
380
+ height: videoElement.clientHeight,
381
+ };
379
382
 
380
383
  // skip initial trigger
381
384
  if (!lastDimensions) {
@@ -384,13 +387,24 @@ export class DynascaleManager {
384
387
  }
385
388
 
386
389
  if (
387
- lastDimensions === currentDimensions ||
390
+ (lastDimensions.width === currentDimensions.width &&
391
+ lastDimensions.height === currentDimensions.height) ||
388
392
  viewportVisibilityState === VisibilityState.INVISIBLE
389
393
  ) {
390
394
  return;
391
395
  }
392
396
 
393
- requestTrackWithDimensions(DebounceType.SLOW, {
397
+ const relativeDelta = Math.max(
398
+ currentDimensions.width / lastDimensions.width,
399
+ currentDimensions.height / lastDimensions.height,
400
+ );
401
+ // Low quality video in an upscaled video element is very noticable.
402
+ // We try to upscale faster, and downscale slower. We also update debounce
403
+ // more if the size change is not significant, gurading against fast-firing
404
+ // resize events.
405
+ const debounceType =
406
+ relativeDelta > 1.2 ? DebounceType.IMMEDIATE : DebounceType.MEDIUM;
407
+ requestTrackWithDimensions(debounceType, {
394
408
  width: videoElement.clientWidth,
395
409
  height: videoElement.clientHeight,
396
410
  });
@@ -413,7 +427,7 @@ export class DynascaleManager {
413
427
  .subscribe((isPublishing) => {
414
428
  if (isPublishing) {
415
429
  // the participant just started to publish a track
416
- requestTrackWithDimensions(DebounceType.FAST, {
430
+ requestTrackWithDimensions(DebounceType.IMMEDIATE, {
417
431
  width: videoElement.clientWidth,
418
432
  height: videoElement.clientHeight,
419
433
  });