senza-sdk 4.4.8 → 4.4.10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "senza-sdk",
3
- "version": "4.4.8",
3
+ "version": "4.4.10",
4
4
  "main": "./src/api.js",
5
5
  "description": "API for Senza application",
6
6
  "license": "MIT",
@@ -101,12 +101,6 @@ class Lifecycle extends LifecycleInterface {
101
101
  */
102
102
  this._backgroundTimestamp = Date.now();
103
103
 
104
- /**
105
- * Flag to track if suspend was triggered by timer
106
- * @type {boolean}
107
- * @private
108
- */
109
- this._isSuspendTriggeredByTimer = false;
110
104
 
111
105
  this._isInTransitionToSuspended = false;
112
106
 
@@ -321,7 +315,7 @@ class Lifecycle extends LifecycleInterface {
321
315
  if (this._isBackgroundTriggeredByTimer && (this.state === this.UiState.BACKGROUND ||
322
316
  this.state === this.UiState.IN_TRANSITION_TO_BACKGROUND)) {
323
317
  sdkLogger.log("Moving to foreground due to user interaction after auto background");
324
- this.moveToForeground();
318
+ this.moveToForeground(true);
325
319
  } else {
326
320
  this._startCountdown();
327
321
  }
@@ -602,25 +596,9 @@ class Lifecycle extends LifecycleInterface {
602
596
  // Only start countdown if delay is positive
603
597
  if (timeoutDelay > 0) {
604
598
  sdkLogger.debug("Starting countdown timeout", timeoutDelay, isPlaying ? "(video)" : "(UI)");
605
- this._countdown = setTimeout(async () => {
599
+ this._countdown = setTimeout(() => {
606
600
  sdkLogger.debug("Countdown timeout reached, moving to background");
607
-
608
- // Create the event with cancelable: true
609
- const event = new Event("beforestatechange", { cancelable: true });
610
- event.state = this.UiState.BACKGROUND;
611
- // Use the event manager to dispatch the event and wait for all listeners
612
- await this._eventManager.dispatch("beforestatechange", event);
613
- // Check if any listener called preventDefault()
614
- if (event.defaultPrevented) {
615
- sdkLogger.info("moveToBackground was prevented by a listener");
616
- // Restart the countdown since the move was cancelled
617
- if (this._isForegroundOrTransitioning()) {
618
- this._startCountdown();
619
- }
620
- } else {
621
- this.moveToBackground(true);
622
- }
623
-
601
+ this.moveToBackground(true);
624
602
  }, timeoutDelay * 1000);
625
603
  } else {
626
604
  sdkLogger.debug("Countdown not started - delay is negative or zero");
@@ -657,30 +635,14 @@ class Lifecycle extends LifecycleInterface {
657
635
  this._suspendCountdown = setTimeout(async () => {
658
636
  sdkLogger.debug("Suspend countdown timeout reached, moving to suspended");
659
637
  if (this._state === this.UiState.BACKGROUND) {
660
- // Create the event with cancelable: true
661
- const event = new Event("beforestatechange", { cancelable: true });
662
- event.state = this.UiState.SUSPENDED;
663
- // Use the event manager to dispatch the event and wait for all listeners
664
- await this._eventManager.dispatch("beforestatechange", event);
665
- // Check if any listener called preventDefault()
666
- if (event.defaultPrevented) {
667
- sdkLogger.info("moveToSuspended was prevented by a listener");
668
- // Restart the suspend countdown since the move was cancelled
669
- this._startSuspendCountdown();
670
- } else {
671
- try {
672
- // Set flag to indicate suspend was triggered by timer
673
- this._isSuspendTriggeredByTimer = true;
674
- await this.moveToSuspended();
675
- } catch (error) {
676
- sdkLogger.error("Failed to move to suspended:", error);
677
- }
638
+ try {
639
+ await this.moveToSuspended(true);
640
+ } catch (error) {
641
+ sdkLogger.error("Failed to move to suspended:", error);
678
642
  }
679
-
680
643
  } else {
681
644
  sdkLogger.warn("suspend timer was called while not in background");
682
645
  }
683
-
684
646
  }, timeoutDelay * 1000);
685
647
  } else {
686
648
  sdkLogger.debug("Suspend countdown not started - delay is zero or negative");
@@ -695,8 +657,6 @@ class Lifecycle extends LifecycleInterface {
695
657
  sdkLogger.debug("Stopping suspend countdown timer");
696
658
  clearTimeout(this._suspendCountdown);
697
659
  this._suspendCountdown = null;
698
- // Reset the timer flag when stopping countdown
699
- this._isSuspendTriggeredByTimer = false;
700
660
  }
701
661
  }
702
662
 
@@ -727,7 +687,7 @@ class Lifecycle extends LifecycleInterface {
727
687
  sdkLogger.warn("lifecycle getState is not supported if NOT running e2e");
728
688
  }
729
689
 
730
- moveToForeground() {
690
+ async moveToForeground(isSystemTriggered = false) {
731
691
  if (!_isUiReady()) {
732
692
  sdkLogger.warn("lifecycle moveToForeground: UI is not ready yet. Make sure to call senza.uiReady() before calling lifecycle.moveToForeground()");
733
693
  }
@@ -747,6 +707,19 @@ class Lifecycle extends LifecycleInterface {
747
707
  sdkLogger.warn(`lifecycle moveToForeground: No need to transition to foreground, state: ${this._state} transition: ${inTransition}`);
748
708
  return Promise.resolve(false);
749
709
  }
710
+
711
+ // Fire beforestatechange event
712
+ const event = new Event("beforestatechange", { cancelable: true });
713
+ event.state = this.UiState.FOREGROUND;
714
+ event.isSystemTriggered = isSystemTriggered;
715
+ await this._eventManager.dispatch("beforestatechange", event);
716
+
717
+ // Check if any listener called preventDefault()
718
+ if (event.defaultPrevented) {
719
+ sdkLogger.info("moveToForeground was prevented by a listener");
720
+ return Promise.resolve(false);
721
+ }
722
+
750
723
  this._inTransitionToForeground = true;
751
724
  bus.dispatchEvent(new Event(Events.LifecycleForeground));
752
725
  const FCID = getFCID();
@@ -918,13 +891,13 @@ class Lifecycle extends LifecycleInterface {
918
891
  return Promise.resolve(false);
919
892
  }
920
893
 
921
- moveToBackground(isTriggeredByTimer = false) {
894
+ async moveToBackground(isSystemTriggered = false) {
922
895
  if (this._isInTransitionToSuspended) {
923
896
  sdkLogger.error("lifecycle moveToBackground: Currently in transition to suspend, cannot move to background");
924
897
  return Promise.resolve(false);
925
898
  }
926
899
  // If the background transition is triggered by the auto background timer, set the flag
927
- this._isBackgroundTriggeredByTimer = isTriggeredByTimer;
900
+ this._isBackgroundTriggeredByTimer = isSystemTriggered;
928
901
 
929
902
  if (window.cefQuery) {
930
903
  const inTransition = this._isInTransition();
@@ -932,6 +905,24 @@ class Lifecycle extends LifecycleInterface {
932
905
  sdkLogger.warn(`lifecycle moveToBackground: No need to transition to background, state: ${this._state} transition: ${inTransition}`);
933
906
  return Promise.resolve(false);
934
907
  }
908
+
909
+ // Fire beforestatechange event
910
+ const event = new Event("beforestatechange", { cancelable: true });
911
+ event.state = this.UiState.BACKGROUND;
912
+ event.isSystemTriggered = isSystemTriggered;
913
+ await this._eventManager.dispatch("beforestatechange", event);
914
+
915
+ // Check if any listener called preventDefault()
916
+ if (event.defaultPrevented) {
917
+ sdkLogger.info("moveToBackground was prevented by a listener");
918
+ // Clear the timer flag if the move was prevented
919
+ this._isBackgroundTriggeredByTimer = false;
920
+ // Restart the countdown if it was triggered by timer
921
+ if (isSystemTriggered && this._isForegroundOrTransitioning()) {
922
+ this._startCountdown();
923
+ }
924
+ return Promise.resolve(false);
925
+ }
935
926
  if (remotePlayer._isSeekingByApplication) {
936
927
  remotePlayer._targetSeekPlayingState = TargetPlayingState.PLAYING_ABR;
937
928
  return Promise.resolve(true);
@@ -1076,7 +1067,7 @@ class Lifecycle extends LifecycleInterface {
1076
1067
  return Promise.reject("disconnect is not supported if NOT running e2e");
1077
1068
  }
1078
1069
 
1079
- moveToSuspended() {
1070
+ async moveToSuspended(isSystemTriggered = false) {
1080
1071
  // Check if the current state is BACKGROUND
1081
1072
  if (this._state !== this.UiState.BACKGROUND) {
1082
1073
  const errorMsg = `moveToSuspended can only be called from BACKGROUND state. Current state: ${this._state}`;
@@ -1084,20 +1075,35 @@ class Lifecycle extends LifecycleInterface {
1084
1075
  return Promise.reject(errorMsg);
1085
1076
  }
1086
1077
 
1078
+ // Fire beforestatechange event
1079
+ const event = new Event("beforestatechange", { cancelable: true });
1080
+ event.state = this.UiState.SUSPENDED;
1081
+ event.isSystemTriggered = isSystemTriggered;
1082
+ await this._eventManager.dispatch("beforestatechange", event);
1083
+
1084
+ // Check if any listener called preventDefault()
1085
+ if (event.defaultPrevented) {
1086
+ sdkLogger.info("moveToSuspended was prevented by a listener");
1087
+ // Restart the suspend countdown if it was triggered by timer
1088
+ if (isSystemTriggered && this._isAutoSuspendEnabled()) {
1089
+ this._startSuspendCountdown();
1090
+ }
1091
+ return Promise.resolve(false);
1092
+ }
1093
+
1087
1094
  this._isInTransitionToSuspended = true;
1088
1095
  // Report metrics for time between background and suspend
1089
1096
  const duration = (Date.now() - this._backgroundTimestamp) / 1000;
1090
1097
 
1091
1098
  sdkLogger.metrics({
1092
1099
  type: "suspendTransitions",
1093
- isAutoSuspend: this._isSuspendTriggeredByTimer,
1100
+ isAutoSuspend: isSystemTriggered,
1094
1101
  isPlaying: remotePlayer._isPlaying,
1095
1102
  duration
1096
1103
  });
1097
1104
 
1098
1105
  // Reset the timer flag after reporting metrics
1099
- const reason = this._isSuspendTriggeredByTimer ? "timer" : "appInitiated";
1100
- this._isSuspendTriggeredByTimer = false;
1106
+ const reason = isSystemTriggered ? "timer" : "appInitiated";
1101
1107
 
1102
1108
  if (window.cefQuery) {
1103
1109
  return new Promise((resolve, reject) => {
@@ -16,18 +16,32 @@ import {
16
16
  /**
17
17
  * @event Lifecycle#beforestatechange
18
18
  * @description Fired before transitioning to a new state. This event is cancelable.<br>
19
- * Currently only fired when transitioning to BACKGROUND and SUSPENDED state (e.g., from autoBackground feature).<br>
19
+ * Fired when transitioning to FOREGROUND, BACKGROUND, or SUSPENDED state.<br>
20
20
  * The actual state transition will occur after all event listeners have completed processing.
21
- * Can be used to prevent automatic transitions to background state when using autoBackground feature, or for suspneded from autoSuspended feature .
22
- * @property {UiState} state - Indicates the target state the lifecycle is trying to transition to.
21
+ * Can be used to prevent automatic transitions (e.g., from autoBackground or autoSuspend features) or
22
+ * to perform cleanup operations before state changes.
23
+ * @property {UiState} state - Indicates the target state the lifecycle is trying to transition to (FOREGROUND, BACKGROUND, or SUSPENDED).
24
+ * @property {boolean} isSystemTriggered - Indicates whether the transition was triggered by the system (e.g., auto background timer, auto suspend timer) or by the application.
23
25
  * @property {boolean} cancelable - true, indicating the event can be cancelled using preventDefault()
24
26
  * @example
27
+ * // Prevent automatic background transition when user is actively interacting
25
28
  * lifecycle.addEventListener("beforestatechange", (e) => {
26
- * if (e.state === lifecycle.UiState.BACKGROUND && userIsInteracting) {
27
- * // Prevent transition to background
29
+ * if (e.state === lifecycle.UiState.BACKGROUND && e.isSystemTriggered && userIsInteracting) {
30
+ * console.log("Preventing automatic background transition");
28
31
  * e.preventDefault();
29
32
  * }
30
33
  * });
34
+ *
35
+ * @example
36
+ * // Save application state before moving to suspended
37
+ * lifecycle.addEventListener("beforestatechange", async (e) => {
38
+ * if (e.state === lifecycle.UiState.SUSPENDED) {
39
+ * console.log("Saving application state before suspend");
40
+ * await saveApplicationState();
41
+ * }
42
+ * });
43
+ *
44
+
31
45
  */
32
46
 
33
47
  /**
@@ -1 +1 @@
1
- export const version = "4.4.8";
1
+ export const version = "4.4.10";