senza-sdk 4.2.64-70c0747.0 → 4.2.65-90c49ac.0

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.
Files changed (26) hide show
  1. package/dist/bundle.js +1 -1
  2. package/package.json +7 -15
  3. package/src/{implementation/alarmManager.js → alarmManager.js} +52 -15
  4. package/src/api.js +350 -183
  5. package/src/{implementation/deviceManager.js → deviceManager.js} +65 -4
  6. package/src/{implementation/lifecycle.js → lifecycle.js} +215 -28
  7. package/src/{implementation/messageManager.js → messageManager.js} +6 -6
  8. package/src/{implementation/platformManager.js → platformManager.js} +4 -5
  9. package/src/{implementation/remotePlayer.js → remotePlayer.js} +22 -18
  10. package/src/{implementation/senzaShakaPlayer.js → senzaShakaPlayer.js} +28 -18
  11. package/src/{implementation/utils.js → utils.js} +6 -15
  12. package/src/implementation/api.js +0 -367
  13. package/src/interface/alarmManager.js +0 -69
  14. package/src/interface/api.js +0 -8
  15. package/src/interface/deviceManager.js +0 -133
  16. package/src/interface/lifecycle.js +0 -278
  17. package/src/interface/messageManager.js +0 -46
  18. package/src/interface/platformManager.js +0 -35
  19. package/src/interface/remotePlayer.js +0 -441
  20. package/src/interface/senzaShakaPlayer.js +0 -171
  21. package/src/interface/utils.js +0 -45
  22. /package/src/{implementation/SessionInfo.js → SessionInfo.js} +0 -0
  23. /package/src/{implementation/devHelper.js → devHelper.js} +0 -0
  24. /package/src/{interface/devSequence.js → devSequence.js} +0 -0
  25. /package/src/{implementation/eventListenersManager.js → eventListenersManager.js} +0 -0
  26. /package/src/{implementation/subtitlesUtils.js → subtitlesUtils.js} +0 -0
@@ -1,4 +1,3 @@
1
- import { DeviceManager as DeviceManagerInterface } from "../interface/deviceManager";
2
1
  import { getFCID, sdkLogger, getRestResponse } from "./utils";
3
2
  import { isRunningE2E } from "./api";
4
3
  import { sessionInfo } from "./SessionInfo";
@@ -36,7 +35,10 @@ async function getWifiStatus() {
36
35
  }
37
36
  }
38
37
 
39
- class DeviceManager extends DeviceManagerInterface {
38
+ /**
39
+ * DeviceManager is a singleton class that manages the device
40
+ */
41
+ class DeviceManager extends EventTarget {
40
42
 
41
43
  constructor() {
42
44
  super();
@@ -44,7 +46,15 @@ class DeviceManager extends DeviceManagerInterface {
44
46
  wifiInfo.quality = 0;
45
47
  wifiInfo.ssid = "unknown";
46
48
  wifiInfo.bssid = "unknown";
47
-
49
+ /**
50
+ * @deprecated Instead, call deviceManager.getWifiInfo() periodically
51
+ * @event DeviceManager#wifiInfoUpdated
52
+ * @example
53
+ * deviceManager.addEventListener("wifiInfoUpdated", () => {
54
+ * console.info("Wifi info has been updated to", deviceManager.wifiInfo);
55
+ * });
56
+ *
57
+ */
48
58
  typeof document !== "undefined" && document.addEventListener("wifiSignalReport", (e) => {
49
59
  wifiInfo.level = e.detail.level;
50
60
  wifiInfo.quality = e.detail.quality;
@@ -55,6 +65,17 @@ class DeviceManager extends DeviceManagerInterface {
55
65
 
56
66
  }
57
67
 
68
+ /**
69
+ * @property {object} DeviceInfo
70
+ * @property {string} DeviceInfo.deviceId
71
+ * @property {string} DeviceInfo.modelNumber
72
+ * @property {string} DeviceInfo.connectionId
73
+ * @property {string} DeviceInfo.community
74
+ * @property {string} DeviceInfo.tenant
75
+ * @property {string} DeviceInfo.clientIp
76
+ * @property {string} DeviceInfo.countryCode A 2-letter code as defined in ISO_3166-1
77
+ * @property {string} DeviceInfo.connectionType The type of device used during the current connection. Possible values are "device" which mean real device, "simulator" - simulated device - that used during development.
78
+ */
58
79
  get deviceInfo() {
59
80
  const sessionInfoObj = sessionInfo.sessionInfoObj;
60
81
  if (isRunningE2E() && sessionInfoObj) {
@@ -82,10 +103,23 @@ class DeviceManager extends DeviceManagerInterface {
82
103
  };
83
104
  }
84
105
 
106
+ /**
107
+ * @deprecated use deviceManager.getWifiInfo() instead
108
+ * @property {object} WifiInfo
109
+ * @property {number} WifiInfo.level
110
+ * @property {number} WifiInfo.quality
111
+ * @property {string} WifiInfo.ssid
112
+ * @property {string} WifiInfo.bssid
113
+ */
85
114
  get wifiInfo() {
86
115
  return wifiInfo;
87
116
  }
88
117
 
118
+ /**
119
+ * Reboot the device
120
+ * @return {Promise} Promise which is resolved when the reboot command has been successfully processed.
121
+ * Failure to process the reboot command will result in the promise being rejected.
122
+ */
89
123
  reboot() {
90
124
  return new Promise((resolve, reject) => {
91
125
  if (window.cefQuery) {
@@ -115,6 +149,11 @@ class DeviceManager extends DeviceManagerInterface {
115
149
  });
116
150
  }
117
151
 
152
+ /**
153
+ * Delete current wifi configuration and forget network
154
+ * @return {Promise} Promise which is resolved when the clearWifi command has been successfully processed.
155
+ * Failure to process the clearWifi command will result in the promise being rejected.
156
+ */
118
157
  clearWifi() {
119
158
  return new Promise((resolve, reject) => {
120
159
  const FCID = getFCID();
@@ -139,6 +178,16 @@ class DeviceManager extends DeviceManagerInterface {
139
178
  });
140
179
  }
141
180
 
181
+ /**
182
+ * Send raw data directly to a customer's device via the USB serial connection of a Senza device.
183
+ * This function is specifically designed for customers who have their devices connected to a Senza device.
184
+ * Using this API, these customers can transmit messages or data directly to their connected devices.
185
+ * The transmission occurs through the Senza device's USB serial interface, facilitating direct communication
186
+ * between the customer's web application and their device.
187
+ * @param {String} data raw data to be passed to the device
188
+ * @return {Promise} Promise which is resolved when the command has been successfully processed.
189
+ * Failure to process the command will result in the promise being rejected.
190
+ */
142
191
  sendDataToDevice(data) {
143
192
  if (typeof data !== "string") {
144
193
  throw new Error("data must be of type 'string'");
@@ -170,6 +219,12 @@ class DeviceManager extends DeviceManagerInterface {
170
219
  });
171
220
  }
172
221
 
222
+ /**
223
+ * Perform device factory reset.
224
+ * @param {Boolean} [reboot=true] a flag that is passed to the device to indicate whether it should reboot after the factory reset. defaults to true.
225
+ * @return {Promise} Promise which is resolved when factoryReset has been successfully performed
226
+ * Failure to factoryReset for any reason, result in the promise being rejected.
227
+ */
173
228
  async factoryReset(reboot = true) {
174
229
  if (typeof reboot !== "boolean") {
175
230
  throw new Error("reboot param must be of type 'boolean'");
@@ -227,6 +282,12 @@ class DeviceManager extends DeviceManagerInterface {
227
282
  * @property {number} quality a measure of the signal quality, in the range 0 to 100 (the higher, the better). The quality value is derived from the signal EVM.
228
283
  * */
229
284
 
285
+ /**
286
+ * Get Wi-Fi info - access point data and status (the status is cached for 5 seconds)
287
+ * @returns {WiFiInfo} An object containing the Wi-Fi info
288
+ * @alpha API has not yet been released
289
+ * */
290
+ // This api is part of epic HSDEV-4185
230
291
  async getWifiInfo() {
231
292
  await Promise.all([getWifiApData(), getWifiStatus()]);
232
293
  return { ...wifi_ap_data, ...wifi_status };
@@ -234,7 +295,7 @@ class DeviceManager extends DeviceManagerInterface {
234
295
  }
235
296
 
236
297
  /**
237
-
298
+ *
238
299
  * @module
239
300
  * @example
240
301
  * import { deviceManager } from "senza-sdk";
@@ -1,6 +1,4 @@
1
- import { Lifecycle as LifecycleInterface } from "../interface/lifecycle";
2
- import { getPlatformInfo } from "./api";
3
- import { alarmManager } from "./alarmManager";
1
+ import { alarmManager, getPlatformInfo } from "./api";
4
2
  import {
5
3
  getFCID,
6
4
  isAudioSyncConfigured,
@@ -26,7 +24,76 @@ const DEFAULT_AUTO_BACKGROUND_ENABLED = false;
26
24
  * @fires userinactivity
27
25
  * @fires userdisconnected
28
26
  */
29
- class Lifecycle extends LifecycleInterface {
27
+ class Lifecycle extends EventTarget {
28
+
29
+ /**
30
+ * @typedef {Object} ConnectReason - The reason the ui app has been loaded
31
+ * @property {string} UNKNOWN
32
+ * @property {string} INITIAL_CONNECTION - Indicates that ui app has been loaded for the first time
33
+ * @property {string} APPLICATION_RELOAD - Indicates that ui app has been reloaded (e.g. after HOME keypress)
34
+ * @property {string} UI_RELEASE - Indicates that ui app has been reloaded after ui release
35
+ * @property {string} UI_TERMINATION - Indicates that ui app has been reloaded due to ui termination
36
+ * @property {string} WEBRTC_ERROR - Indicates that ui app has been reloaded due to webrtc error
37
+ * @property {string} UI_WATCHDOG - Indicates that ui app has been reloaded due to ui watchdog not receiving ui frames
38
+ */
39
+ ConnectReason = Object.freeze({
40
+ UNKNOWN: "unknown",
41
+ INITIAL_CONNECTION: "initial_connection",
42
+ APPLICATION_RELOAD: "reload_app",
43
+ UI_RELEASE: "ui_release",
44
+ UI_TERMINATION: "ui_termination",
45
+ WEBRTC_ERROR: "webrtc_error",
46
+ UI_WATCHDOG: "ui_watchdog"
47
+ });
48
+
49
+ /**
50
+ * @typedef {Object} UiState - The ui lifecycle state
51
+ * @property {string} UNKNOWN - state is unknown at this time
52
+ * @property {string} FOREGROUND - ui is displayed
53
+ * @property {string} IN_TRANSITION_TO_FOREGROUND - ui is about to be displayed
54
+ * @property {string} BACKGROUND - remote player is playing (full screen playback is displayed)
55
+ * @property {string} IN_TRANSITION_TO_BACKGROUND - remote player is about to be playing
56
+ */
57
+ UiState = Object.freeze({
58
+ UNKNOWN: "unknown",
59
+ FOREGROUND: "foreground",
60
+ IN_TRANSITION_TO_FOREGROUND: "inTransitionToForeground",
61
+ BACKGROUND: "background",
62
+ IN_TRANSITION_TO_BACKGROUND: "inTransitionToBackground"
63
+ });
64
+
65
+ /**
66
+ * @event Lifecycle#onstatechange
67
+ * @description Fired after transition from one state to another.<br>
68
+ * The flow is: foreground --> inTransitionToBackground --> background --> inTransitionToForeground --> foreground
69
+ * @property {UiState} state - Indicates the new state.
70
+ * @example
71
+ * lifecycle.addEventListener("onstatechange", (e) => {
72
+ * console.log("new state is", e.state);
73
+ * });
74
+ */
75
+
76
+ /**
77
+ * @event Lifecycle#userinactivity
78
+ * @description Fired after the ui has been inactive (i.e. no key presses) for a configurable number of seconds.<br>
79
+ * @property {number} timeout - the number of seconds after which the application will be unloaded.
80
+ * @example
81
+ * lifecycle.addEventListener("userinactivity", (e) => {
82
+ * console.log(`Application will be unloaded in ${e.timeout} seconds`);
83
+ * });
84
+ * @alpha API has not yet been released
85
+ */
86
+
87
+ /**
88
+ * @event Lifecycle#userdisconnected
89
+ * @description Fired when the user session ends .
90
+ * This event is useful for cleaning up application state or saving data before the application closes. Event callback should return promise to ensure that the event is handled before the application is terminated
91
+ * @example
92
+ * lifecycle.addEventListener("userdisconnected", () => {
93
+ * console.log("User session ended, cleaning up application state");
94
+ * // Perform any necessary cleanup here
95
+ * });
96
+ */
30
97
  constructor() {
31
98
  super();
32
99
 
@@ -35,7 +102,9 @@ class Lifecycle extends LifecycleInterface {
35
102
  * @private
36
103
  */
37
104
  this._isInitialized = false;
38
- this._inTransition = false;
105
+ this._inTransitionToForeground = false;
106
+ this._inTransitionToBackground = false;
107
+ this._inTransitionToStandby = false;
39
108
 
40
109
  /**
41
110
  * Event listeners manager for the userdisconnected event
@@ -238,6 +307,15 @@ class Lifecycle extends LifecycleInterface {
238
307
  return this._autoBackgroundOnUIDelay;
239
308
  }
240
309
 
310
+ /**
311
+ * Configure lifecycle settings
312
+ * @param {Object} config - Configuration object
313
+ * @param {Object} [config.autoBackground] - Auto background settings
314
+ * @param {boolean} [config.autoBackground.enabled] - Enable/disable auto background
315
+ * @param {Object} [config.autoBackground.timeout] - Timeout settings
316
+ * @param {number|false} [config.autoBackground.timeout.playing=30] - Timeout in seconds when video is playing, false to disable
317
+ * @param {number|false} [config.autoBackground.timeout.idle=false] - Timeout in seconds when in UI mode, false to disable
318
+ */
241
319
  configure(config) {
242
320
  if (config?.autoBackground) {
243
321
  const { enabled, timeout } = config.autoBackground;
@@ -277,6 +355,15 @@ class Lifecycle extends LifecycleInterface {
277
355
  }
278
356
  }
279
357
 
358
+ /**
359
+ * Get the current configuration settings
360
+ * @returns {Object} The current configuration object
361
+ * @example
362
+ * const config = lifecycle.getConfiguration();
363
+ * console.log(config.autoBackground.enabled); // true/false
364
+ * console.log(config.autoBackground.timeout.playing); // 30
365
+ * console.log(config.autoBackground.timeout.idle); // false
366
+ */
280
367
  getConfiguration() {
281
368
  return {
282
369
  autoBackground: {
@@ -299,7 +386,7 @@ class Lifecycle extends LifecycleInterface {
299
386
  // This api is part of epic HSDEV-713
300
387
  _moveToUiStandby() {
301
388
  if (window.cefQuery) {
302
- this._inTransition = true;
389
+ this._inTransitionToStandby = true;
303
390
  return new Promise((resolve, reject) => {
304
391
  const FCID = getFCID();
305
392
  const request = { target: "TC", waitForResponse: false, internalAction: "uiExit", message: JSON.stringify({ type: "uiStandbyRequest", fcid: FCID }) };
@@ -310,12 +397,12 @@ class Lifecycle extends LifecycleInterface {
310
397
  persistent: false,
311
398
  onSuccess: () => {
312
399
  logger.log("[ moveToUiStandby ] moveToUiStandby successfully sent");
313
- this._inTransition = false;
400
+ this._inTransitionToStandby = false;
314
401
  resolve(true);
315
402
  },
316
403
  onFailure: (code, msg) => {
317
404
  logger.error(`[ moveToUiStandby ] moveToUiStandby failed: ${code} ${msg}`);
318
- this._inTransition = false;
405
+ this._inTransitionToStandby = false;
319
406
  reject(`moveToUiStandby failed: ${code} ${msg}`);
320
407
  }
321
408
  });
@@ -325,6 +412,10 @@ class Lifecycle extends LifecycleInterface {
325
412
  return Promise.resolve(true);
326
413
  }
327
414
 
415
+ /**
416
+ * Getter for returning the ui lifecycle state
417
+ * @returns {UiState} the current application lifecycle state
418
+ */
328
419
  get state() {
329
420
  if (!this._isInitialized) {
330
421
  this._state = this.UiState.UNKNOWN;
@@ -332,6 +423,10 @@ class Lifecycle extends LifecycleInterface {
332
423
  return this._state;
333
424
  }
334
425
 
426
+ /**
427
+ * Getter for returning the application connection reason
428
+ * @returns {ConnectReason} the application connection reason
429
+ */
335
430
  get connectReason() {
336
431
  if (!this._isInitialized) {
337
432
  this._connectReason = this.ConnectReason.UNKNOWN;
@@ -339,6 +434,11 @@ class Lifecycle extends LifecycleInterface {
339
434
  return this._connectReason;
340
435
  }
341
436
 
437
+ /**
438
+ * Getter for returning the event that triggered the reloading of the ui after ui has been released
439
+ * @returns {Object} trigger event
440
+ * @property {string} type - the type of the trigger event (e.g. keyPressEvent, videoPlaybackEvent)
441
+ * @property {object} data - data of the event, dependent on its type (e.g. keyPressEvent has data of keyValue) */
342
442
  get triggerEvent() {
343
443
  if (!this._isInitialized) {
344
444
  this._triggerEvent = {};
@@ -346,6 +446,14 @@ class Lifecycle extends LifecycleInterface {
346
446
  return this._triggerEvent;
347
447
  }
348
448
 
449
+ /**
450
+ * @deprecated Use `lifecycle.configure()` instead.
451
+ * Controls the autoBackground feature.<br>
452
+ * When enabled, the application will automatically move to the background state after a configurable
453
+ * period of inactivity. Use the `configure` method to set timeouts for video playback and UI states.
454
+ * @type {boolean}
455
+ * @see {@link Lifecycle#configure}
456
+ */
349
457
  set autoBackground(enabled) {
350
458
  this._autoBackground = enabled;
351
459
  if (this._isAutoBackgroundEnabled()) {
@@ -359,6 +467,14 @@ class Lifecycle extends LifecycleInterface {
359
467
  return this._autoBackground;
360
468
  }
361
469
 
470
+ /**
471
+ * @deprecated Use `lifecycle.configure()` instead.
472
+ * The number of seconds of user inactivity before the application moves to the background state while playing video.
473
+ * Use the `configure` method to set this timeout.
474
+ * @type {integer}
475
+ * @default 30
476
+ * @see {@link Lifecycle#configure}
477
+ */
362
478
  set autoBackgroundDelay(delay) {
363
479
  this._autoBackgroundOnVideoDelay = delay;
364
480
  if (this._isAutoBackgroundEnabled() && remotePlayer._isPlaying) {
@@ -370,6 +486,14 @@ class Lifecycle extends LifecycleInterface {
370
486
  return this._autoBackgroundOnVideoDelay;
371
487
  }
372
488
 
489
+ /**
490
+ * @deprecated Use `lifecycle.configure()` instead.
491
+ * The number of seconds of user inactivity before the application moves to the background state while in the UI (not playing).
492
+ * Use the `configure` method to set this timeout.
493
+ * @type {integer}
494
+ * @default -1
495
+ * @see {@link Lifecycle#configure}
496
+ */
373
497
  set autoBackgroundOnUIDelay(delay) {
374
498
  this._autoBackgroundOnUIDelay = delay;
375
499
  if (this._isAutoBackgroundEnabled() && !remotePlayer._isPlaying) {
@@ -412,6 +536,26 @@ class Lifecycle extends LifecycleInterface {
412
536
  this._countdown = null;
413
537
  }
414
538
 
539
+ /**
540
+ * @private
541
+ */
542
+ _isInTransition() {
543
+ return this._inTransitionToForeground || this._inTransitionToBackground || this._inTransitionToStandby;
544
+ }
545
+
546
+
547
+ /**
548
+ * @deprecated use lifecycle.state instead.
549
+ * Async function that returns the ui lifecycle state
550
+ * @returns {UiState} the current application lifecycle state
551
+ * @example
552
+ * try {
553
+ * const state = await lifecycle.getState();
554
+ * console.log("current state is", state);
555
+ * } catch (e) {
556
+ * console.error("getState failed", e);
557
+ * }
558
+ */
415
559
  getState() {
416
560
  if (window.cefQuery) {
417
561
  return new Promise((resolve, reject) => {
@@ -432,16 +576,29 @@ class Lifecycle extends LifecycleInterface {
432
576
  sdkLogger.warn("lifecycle getState is not supported if NOT running e2e");
433
577
  }
434
578
 
579
+ /**
580
+ * Once playback starts on the remote player,
581
+ * the application is moved from foreground to inTransitionToBackground and eventually to background.
582
+ * The application will need to call moveToForeground when it receives an event that needs the UI to be displayed again,
583
+ * for example a key press, a playback end-of-file or a playback error.
584
+ * @return {Promise} Promise which is resolved when the moveToForeground command has been successfully processed.
585
+ * Failure to process the moveToForeground command will result in the promise being rejected.
586
+ */
435
587
  moveToForeground() {
436
588
  if (window.cefQuery) {
437
- if (this._inTransition || this._state === this.UiState.FOREGROUND || this._state === this.UiState.IN_TRANSITION_TO_FOREGROUND) {
438
- sdkLogger.warn(`lifecycle moveToForeground: No need to transition to foreground, state: ${this._state} transition: ${this._inTransition}`);
589
+ const inTransition = this._isInTransition();
590
+ if (inTransition || this._state === this.UiState.FOREGROUND || this._state === this.UiState.IN_TRANSITION_TO_FOREGROUND) {
591
+ sdkLogger.warn(`lifecycle moveToForeground: No need to transition to foreground, state: ${this._state} transition: ${inTransition}`);
439
592
  return Promise.resolve(false);
440
593
  }
441
- this._inTransition = true;
594
+ this._inTransitionToForeground = true;
442
595
  alarmManager._moveToForegroundCalled();
443
596
  const FCID = getFCID();
444
597
  if (this._remotePlayerApiVersion >= 2) {
598
+ // Only update to playing UI if we started seeking in ABR. But, if we are seeking while already paused, keep the target seek state as is.
599
+ if (remotePlayer._isSeekingByApplication && remotePlayer._targetSeekPlayingState === TargetPlayingState.PLAYING_ABR) {
600
+ remotePlayer._targetSeekPlayingState = TargetPlayingState.PLAYING_UI;
601
+ }
445
602
  return new Promise((resolve, reject) => {
446
603
  const FCID = getFCID();
447
604
  const logger = sdkLogger.withFields({ FCID });
@@ -461,14 +618,14 @@ class Lifecycle extends LifecycleInterface {
461
618
  onSuccess: () => {
462
619
  const duration = Date.now() - timeBeforeSendingRequest;
463
620
  logger.withFields({ duration }).log(`stop completed successfully after ${duration} ms`);
464
- this._inTransition = false;
621
+ this._inTransitionToForeground = false;
465
622
  timerId = clearTimer(timerId);
466
623
  resolve(true);
467
624
  },
468
625
  onFailure: (code, msg) => {
469
626
  const duration = Date.now() - timeBeforeSendingRequest;
470
627
  logger.withFields({ duration }).log(`stop failed after ${duration} ms. Error code: ${code}, error message: ${msg}`);
471
- this._inTransition = false;
628
+ this._inTransitionToForeground = false;
472
629
  timerId = clearTimer(timerId);
473
630
  reject(new SenzaError(code, msg));
474
631
  }
@@ -477,7 +634,7 @@ class Lifecycle extends LifecycleInterface {
477
634
  const timeout = this._remotePlayerConfirmationTimeout + 1000;
478
635
  timerId = setTimeout(() => {
479
636
  logger.log(`stop reached timeout of ${timeout} ms, canceling query id ${queryId}`);
480
- this._inTransition = false;
637
+ this._inTransitionToForeground = false;
481
638
  window.cefQueryCancel(queryId);
482
639
  reject(new SenzaError(6000, `stop reached timeout of ${timeout} ms`));
483
640
  }, timeout, queryId);
@@ -492,11 +649,11 @@ class Lifecycle extends LifecycleInterface {
492
649
  persistent: false,
493
650
  onSuccess: () => {
494
651
  logger.log("uiActiveRequest successfully sent");
495
- this._inTransition = false;
652
+ this._inTransitionToForeground = false;
496
653
  resolve(true);
497
654
  },
498
655
  onFailure: (code, msg) => {
499
- this._inTransition = false;
656
+ this._inTransitionToForeground = false;
500
657
  logger.error(`uiActiveRequest failed: ${code} ${msg}`);
501
658
  reject(`uiActiveRequest failed: ${code} ${msg}`);
502
659
  }
@@ -509,10 +666,6 @@ class Lifecycle extends LifecycleInterface {
509
666
 
510
667
  _moveToBackground() {
511
668
  if (window.cefQuery) {
512
- if (this._inTransition || this._state === this.UiState.BACKGROUND || this._state === this.UiState.IN_TRANSITION_TO_BACKGROUND) {
513
- sdkLogger.warn(`lifecycle moveToBackground: No need to transition to background, state: ${this._state} transition: ${this._inTransition}`);
514
- return Promise.resolve(false);
515
- }
516
669
  // If audio sync is disabled, we only need to sync before remote player starts playing
517
670
  if (!isAudioSyncConfigured()) {
518
671
  remotePlayer._syncRemotePlayerWithLocalPlayer();
@@ -524,7 +677,7 @@ class Lifecycle extends LifecycleInterface {
524
677
  return this._moveToUiStandby();
525
678
  }
526
679
 
527
- this._inTransition = true;
680
+ this._inTransitionToBackground = true;
528
681
  return new Promise((resolve, reject) => {
529
682
  const FCID = getFCID();
530
683
  const logger = sdkLogger.withFields({ FCID });
@@ -565,14 +718,14 @@ class Lifecycle extends LifecycleInterface {
565
718
  onSuccess: () => {
566
719
  const duration = Date.now() - timeBeforeSendingRequest;
567
720
  logger.withFields({ duration }).log(`play completed successfully after ${duration} ms`);
568
- this._inTransition = false;
721
+ this._inTransitionToBackground = false;
569
722
  timerId = clearTimer(timerId);
570
723
  resolve();
571
724
  },
572
725
  onFailure: (code, msg) => {
573
726
  const duration = Date.now() - timeBeforeSendingRequest;
574
727
  logger.withFields({ duration }).log(`play failed after ${duration} ms. Error code: ${code}, error message: ${msg}`);
575
- this._inTransition = false;
728
+ this._inTransitionToBackground = false;
576
729
  timerId = clearTimer(timerId);
577
730
  reject(new SenzaError(code, msg));
578
731
  }
@@ -582,7 +735,7 @@ class Lifecycle extends LifecycleInterface {
582
735
  const timeout = this._remotePlayerConfirmationTimeout + 1000;
583
736
  timerId = setTimeout(() => {
584
737
  logger.log(`play reached timeout of ${timeout} ms, canceling query id ${queryId}`);
585
- this._inTransition = false;
738
+ this._inTransitionToBackground = false;
586
739
  window.cefQueryCancel(queryId);
587
740
  reject(new SenzaError(6000, `play reached timeout of ${timeout} ms`));
588
741
  }, timeout, queryId);
@@ -593,13 +746,24 @@ class Lifecycle extends LifecycleInterface {
593
746
  return Promise.resolve(false);
594
747
  }
595
748
 
749
+ /**
750
+ * This method moves the application to the background.
751
+ * It should be called after remotePlayer.play().
752
+ * As a consequence, remote player playback will be displayed in full screen.
753
+ * @example
754
+ * remotePlayer.load("https://example.com/video.mp4", 0);
755
+ * remotePlayer.play();
756
+ * lifecycle.moveToBackground();
757
+ * @return {Promise} Promise which is resolved when the moveToBackground command has been successfully processed.
758
+ * Failure to process the moveToBackground command will result in the promise being rejected.
759
+ */
596
760
  moveToBackground() {
597
761
  if (window.cefQuery) {
598
- if (this._inTransition || this._state === this.UiState.BACKGROUND || this._state === this.UiState.IN_TRANSITION_TO_BACKGROUND) {
599
- sdkLogger.warn(`lifecycle moveToBackground: No need to transition to background, state: ${this._state} transition: ${this._inTransition}`);
762
+ const inTransition = this._isInTransition();
763
+ if (inTransition || this._state === this.UiState.BACKGROUND || this._state === this.UiState.IN_TRANSITION_TO_BACKGROUND) {
764
+ sdkLogger.warn(`lifecycle moveToBackground: No need to transition to background, state: ${this._state} transition: ${inTransition}`);
600
765
  return Promise.resolve(false);
601
766
  }
602
-
603
767
  if (remotePlayer._isSeekingByApplication) {
604
768
  remotePlayer._targetSeekPlayingState = TargetPlayingState.PLAYING_ABR;
605
769
  return Promise.resolve(true);
@@ -616,6 +780,13 @@ class Lifecycle extends LifecycleInterface {
616
780
  return this._moveToBackground();
617
781
  }
618
782
 
783
+ /**
784
+ * Use this api to switch to another tenant (other than the home tenant) which will launch the application associated with the tenantId. The tenantId must be configured in the
785
+ * Senza platform. Switching to the home tenant should use the exitApplication().
786
+ * @param {string} tenantId The tenantId to switch
787
+ * @return {Promise} Promise which is resolved when the switchTenant command has been successfully processed.
788
+ * Failure to process the switchTenant command will result in the promise being rejected.
789
+ */
619
790
  switchTenant(tenantId) {
620
791
  if (tenantId && tenantId.length > 0) {
621
792
  if (tenantId === getPlatformInfo().sessionInfo?.tenantId) {
@@ -661,6 +832,11 @@ class Lifecycle extends LifecycleInterface {
661
832
  return Promise.reject("SwitchTenant requires a valid tenantId string parameter");
662
833
  }
663
834
 
835
+ /**
836
+ * Use this api to exit the application which will redirect the browser to the home tenant application.
837
+ * @return {Promise} Promise which is resolved when the exitApplication command has been successfully processed.
838
+ * Failure to process the exitApplication command will result in the promise being rejected.
839
+ */
664
840
  exitApplication() {
665
841
  if (window.cefQuery) {
666
842
  return new Promise((resolve, reject) => {
@@ -709,6 +885,12 @@ class Lifecycle extends LifecycleInterface {
709
885
  return Promise.reject("exitApplication is not supported if NOT running e2e");
710
886
  }
711
887
 
888
+ /**
889
+ * Add event listener for lifecycle events
890
+ * @param {string} type - The event type to listen for
891
+ * @param {Function} listener - The callback function. Listeners for 'userdisconnected' events should return a promise to ensure the event is processed before the application exits.
892
+ * @param {Object} options - Event listener options
893
+ */
712
894
  addEventListener(type, listener, options) {
713
895
  if (type === "userdisconnected") {
714
896
  // Use the event manager for userdisconnected events
@@ -719,7 +901,12 @@ class Lifecycle extends LifecycleInterface {
719
901
  }
720
902
  }
721
903
 
722
-
904
+ /**
905
+ * Remove event listener
906
+ * @param {string} type - The event type
907
+ * @param {Function} listener - The callback function to remove
908
+ * @param {Object} options - Event listener options
909
+ */
723
910
  removeEventListener(type, listener, options) {
724
911
  if (type === "userdisconnected") {
725
912
  // Use the event manager for userdisconnected events
@@ -1,12 +1,12 @@
1
- import { MessageManager as MessageManagerInterface } from "../interface/messageManager";
2
- import { getFCID, sdkLogger } from "./utils";
1
+
2
+ import {getFCID, sdkLogger} from "./utils";
3
3
 
4
4
  /**
5
5
  * MessageManager is a singleton class that manages the external messages received by the application. It fires custom events as "message" with the payload as the content
6
6
  * @fires MessageManager#message
7
7
  */
8
8
 
9
- class MessageManager extends MessageManagerInterface {
9
+ class MessageManager extends EventTarget {
10
10
 
11
11
  /**
12
12
  * @typedef {object} MessageDetails - object which contains the content of the message
@@ -34,7 +34,7 @@ class MessageManager extends MessageManagerInterface {
34
34
  super();
35
35
  typeof document !== "undefined" && document.addEventListener("hs/externalEvent", (e) => {
36
36
  sdkLogger.log("Got hs/externalEvent", JSON.stringify(e.detail));
37
- this.dispatchEvent(new CustomEvent("message", { detail: { eventName: e.detail.eventName, payload: e.detail.payload, fcid: e.detail.fcid } }));
37
+ this.dispatchEvent(new CustomEvent("message", {detail: {eventName: e.detail.eventName, payload: e.detail.payload, fcid: e.detail.fcid } }));
38
38
  });
39
39
  }
40
40
 
@@ -49,13 +49,13 @@ class MessageManager extends MessageManagerInterface {
49
49
  return new Promise((resolve, reject) => {
50
50
  if (window.cefQuery) {
51
51
  const FCID = getFCID();
52
- const logger = sdkLogger.withFields({ FCID });
52
+ const logger = sdkLogger.withFields({FCID});
53
53
  const message = {
54
54
  type: "registerGroupEvent",
55
55
  fcid: FCID,
56
56
  groups
57
57
  };
58
- const request = { target: "UI-Streamer", waitForResponse: false, message: JSON.stringify(message) };
58
+ const request = {target: "UI-Streamer", waitForResponse: false, message: JSON.stringify(message)};
59
59
  window.cefQuery({
60
60
  request: JSON.stringify(request),
61
61
  persistent: false,
@@ -1,12 +1,11 @@
1
- import { PlatformManager as PlatformManagerInterface } from "../interface/platformManager";
2
1
  import { sdkLogger } from "./utils";
3
- import { sessionInfo } from "./SessionInfo";
2
+ import {sessionInfo} from "./SessionInfo";
4
3
 
5
4
 
6
5
  /**
7
6
  * PlatformManager is a singleton class that manages the platform
8
7
  */
9
- class PlatformManager extends PlatformManagerInterface {
8
+ class PlatformManager extends EventTarget {
10
9
 
11
10
  constructor() {
12
11
  super();
@@ -23,7 +22,7 @@ class PlatformManager extends PlatformManagerInterface {
23
22
  get appConfig() {
24
23
  const sessionInfoObj = sessionInfo.sessionInfoObj;
25
24
  const appConfig = sessionInfoObj.homeSessionInfo?.["appConfig"] || {};
26
- sdkLogger.info("PlatformManager get appConfig: \n" + JSON.stringify(appConfig, null, 2));
25
+ sdkLogger.info("PlatformManager get appConfig: \n" + JSON.stringify(appConfig, null,2));
27
26
  return appConfig;
28
27
  }
29
28
 
@@ -36,7 +35,7 @@ class PlatformManager extends PlatformManagerInterface {
36
35
  */
37
36
  setTimezone(timezone) {
38
37
  if (window.cefQuery) {
39
- const request = { message: JSON.stringify({ type: "setTimeZone", timezone }), waitForResponse: false, target: "UI-Streamer" };
38
+ const request = {message: JSON.stringify({type: "setTimeZone", timezone}), waitForResponse: false, target: "UI-Streamer"};
40
39
  window.cefQuery({
41
40
  request: JSON.stringify(request),
42
41
  persistent: false,