bitmovin-player-ui 4.2.0 → 4.3.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 (265) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/js/bitmovinplayer-ui.js +1 -1
  3. package/dist/js/bitmovinplayer-ui.js.map +1 -1
  4. package/dist/js/framework/UIFactory.js +1 -2
  5. package/dist/js/framework/components/Container.d.ts +1 -1
  6. package/dist/js/framework/components/UIContainer.d.ts +7 -1
  7. package/dist/js/framework/components/UIContainer.js +33 -2
  8. package/dist/js/framework/components/ads/AdMessageLabel.d.ts +22 -3
  9. package/dist/js/framework/components/ads/AdMessageLabel.js +40 -17
  10. package/dist/js/framework/components/overlays/DismissClickOverlay.js +7 -1
  11. package/dist/js/framework/components/settings/SettingsPanel.d.ts +28 -1
  12. package/dist/js/framework/components/settings/SettingsPanel.js +103 -7
  13. package/dist/js/framework/utils/StringUtils.d.ts +2 -2
  14. package/docs/assets/hierarchy.js +1 -1
  15. package/docs/assets/search.js +1 -1
  16. package/docs/classes/AdClickOverlay.html +28 -28
  17. package/docs/classes/AdControlBar.html +31 -31
  18. package/docs/classes/AdCounterLabel.html +31 -31
  19. package/docs/classes/AdMessageLabel.html +51 -32
  20. package/docs/classes/AdSkipButton.html +27 -27
  21. package/docs/classes/AdStatusOverlay.html +31 -31
  22. package/docs/classes/AirPlayToggleButton.html +35 -35
  23. package/docs/classes/AudioQualitySelectBox.html +38 -38
  24. package/docs/classes/AudioTrackListBox.html +40 -39
  25. package/docs/classes/AudioTrackSelectBox.html +38 -38
  26. package/docs/classes/BackgroundColorSelectBox.html +38 -38
  27. package/docs/classes/BackgroundOpacitySelectBox.html +38 -38
  28. package/docs/classes/BrowserUtils.html +2 -2
  29. package/docs/classes/BufferingOverlay.html +31 -31
  30. package/docs/classes/Button.html +27 -27
  31. package/docs/classes/CastStatusOverlay.html +31 -31
  32. package/docs/classes/CastToggleButton.html +35 -35
  33. package/docs/classes/CastUIContainer.html +31 -31
  34. package/docs/classes/CharacterEdgeSelectBox.html +38 -38
  35. package/docs/classes/ClickOverlay.html +28 -28
  36. package/docs/classes/CloseButton.html +27 -27
  37. package/docs/classes/Component.html +25 -25
  38. package/docs/classes/Container.html +31 -31
  39. package/docs/classes/ControlBar.html +31 -31
  40. package/docs/classes/DynamicSettingsPanelItem.html +33 -33
  41. package/docs/classes/ErrorMessageOverlay.html +31 -31
  42. package/docs/classes/FontColorSelectBox.html +38 -38
  43. package/docs/classes/FontFamilySelectBox.html +38 -38
  44. package/docs/classes/FontOpacitySelectBox.html +38 -38
  45. package/docs/classes/FontSizeSelectBox.html +38 -38
  46. package/docs/classes/FullscreenToggleButton.html +35 -35
  47. package/docs/classes/HugePlaybackToggleButton.html +35 -35
  48. package/docs/classes/HugeReplayButton.html +27 -27
  49. package/docs/classes/I18n.html +2 -2
  50. package/docs/classes/Icon.html +25 -25
  51. package/docs/classes/ItemSelectionList.html +38 -38
  52. package/docs/classes/Label.html +31 -31
  53. package/docs/classes/ListBox.html +40 -39
  54. package/docs/classes/ListSelector.html +38 -38
  55. package/docs/classes/MetadataLabel.html +31 -31
  56. package/docs/classes/NavigationGroup.html +10 -10
  57. package/docs/classes/PictureInPictureToggleButton.html +35 -35
  58. package/docs/classes/PlaybackSpeedSelectBox.html +38 -38
  59. package/docs/classes/PlaybackTimeLabel.html +32 -32
  60. package/docs/classes/PlaybackToggleButton.html +35 -35
  61. package/docs/classes/PlaybackToggleOverlay.html +31 -31
  62. package/docs/classes/PlayerUtils.LiveStreamDetector.html +2 -2
  63. package/docs/classes/PlayerUtils.TimeShiftAvailabilityDetector.html +2 -2
  64. package/docs/classes/PlayerWrapper.html +4 -4
  65. package/docs/classes/QuickSeekButton.html +27 -27
  66. package/docs/classes/RecommendationItem.html +25 -25
  67. package/docs/classes/RecommendationOverlay.html +31 -31
  68. package/docs/classes/ReplayButton.html +27 -27
  69. package/docs/classes/RootNavigationGroup.html +10 -10
  70. package/docs/classes/SeekBar.html +36 -36
  71. package/docs/classes/SeekBarLabel.html +35 -35
  72. package/docs/classes/SelectBox.html +38 -38
  73. package/docs/classes/SettingsPanel.html +40 -39
  74. package/docs/classes/SettingsPanelItem.html +33 -33
  75. package/docs/classes/SettingsPanelNavigationGroup.html +10 -10
  76. package/docs/classes/SettingsPanelNavigationGroupConfig.html +2 -2
  77. package/docs/classes/SettingsPanelPage.html +33 -33
  78. package/docs/classes/SettingsPanelPageBackButton.html +29 -29
  79. package/docs/classes/SettingsPanelPageOpenButton.html +29 -29
  80. package/docs/classes/SettingsToggleButton.html +35 -35
  81. package/docs/classes/Spacer.html +25 -25
  82. package/docs/classes/SpatialNavigation.html +4 -4
  83. package/docs/classes/SubtitleListBox.html +40 -39
  84. package/docs/classes/SubtitleOverlay.html +31 -31
  85. package/docs/classes/SubtitleSelectBox.html +38 -38
  86. package/docs/classes/SubtitleSettingSelectBox.html +38 -38
  87. package/docs/classes/SubtitleSettingsPanelPage.html +33 -33
  88. package/docs/classes/SubtitleSettingsResetButton.html +27 -27
  89. package/docs/classes/TitleBar.html +31 -31
  90. package/docs/classes/ToggleButton.html +35 -35
  91. package/docs/classes/UIContainer.html +31 -31
  92. package/docs/classes/UIInstanceManager.html +14 -14
  93. package/docs/classes/UIManager.html +14 -14
  94. package/docs/classes/VRToggleButton.html +35 -35
  95. package/docs/classes/VideoQualitySelectBox.html +39 -39
  96. package/docs/classes/VolumeControlButton.html +33 -33
  97. package/docs/classes/VolumeSlider.html +36 -36
  98. package/docs/classes/VolumeToggleButton.html +35 -35
  99. package/docs/classes/Watermark.html +28 -28
  100. package/docs/classes/WindowColorSelectBox.html +38 -38
  101. package/docs/classes/WindowOpacitySelectBox.html +38 -38
  102. package/docs/enums/ButtonStyle.html +5 -5
  103. package/docs/enums/LabelStyle.html +4 -4
  104. package/docs/enums/MetadataLabelContent.html +3 -3
  105. package/docs/enums/NavigationDirection.html +2 -2
  106. package/docs/enums/PlaybackTimeLabelMode.html +5 -5
  107. package/docs/enums/PlayerUtils.PlayerState.html +2 -2
  108. package/docs/enums/UIUtils.KeyCode.html +2 -2
  109. package/docs/enums/ViewMode.html +3 -3
  110. package/docs/functions/ArrayUtils.remove.html +1 -1
  111. package/docs/functions/ErrorUtils.defaultMobileV3ErrorMessageTranslator.html +1 -1
  112. package/docs/functions/PlayerUtils.clampValueToRange.html +1 -1
  113. package/docs/functions/PlayerUtils.getCurrentTimeRelativeToSeekableRange.html +1 -1
  114. package/docs/functions/PlayerUtils.getSeekableRangeRespectingLive.html +1 -1
  115. package/docs/functions/PlayerUtils.getSeekableRangeStart.html +1 -1
  116. package/docs/functions/PlayerUtils.getState.html +1 -1
  117. package/docs/functions/PlayerUtils.isTimeShiftAvailable.html +1 -1
  118. package/docs/functions/StorageUtils.getItem.html +1 -1
  119. package/docs/functions/StorageUtils.getObject.html +1 -1
  120. package/docs/functions/StorageUtils.setItem.html +1 -1
  121. package/docs/functions/StorageUtils.setObject.html +1 -1
  122. package/docs/functions/StorageUtils.setStorageApiDisabled.html +1 -1
  123. package/docs/functions/StringUtils.replaceAdMessagePlaceholders.html +1 -1
  124. package/docs/functions/StringUtils.secondsToText.html +1 -1
  125. package/docs/functions/StringUtils.secondsToTime.html +1 -1
  126. package/docs/functions/UIFactory.buildCastReceiverUI.html +1 -1
  127. package/docs/functions/UIFactory.buildSmallScreenUI.html +1 -1
  128. package/docs/functions/UIFactory.buildSubtitleUI.html +1 -1
  129. package/docs/functions/UIFactory.buildTvUI.html +1 -1
  130. package/docs/functions/UIFactory.buildUI.html +1 -1
  131. package/docs/functions/UIUtils.traverseTree.html +1 -1
  132. package/docs/hierarchy.html +1 -1
  133. package/docs/interfaces/ActiveUiChangedArgs.html +3 -3
  134. package/docs/interfaces/AdControlBarConfig.html +12 -12
  135. package/docs/interfaces/AdSkipButtonConfig.html +16 -16
  136. package/docs/interfaces/BufferingOverlayConfig.html +13 -13
  137. package/docs/interfaces/ButtonConfig.html +14 -14
  138. package/docs/interfaces/ClickOverlayConfig.html +15 -15
  139. package/docs/interfaces/CloseButtonConfig.html +15 -15
  140. package/docs/interfaces/ComponentConfig.html +11 -11
  141. package/docs/interfaces/ComponentFocusChangedEventArgs.html +2 -2
  142. package/docs/interfaces/ComponentHoverChangedEventArgs.html +2 -2
  143. package/docs/interfaces/ContainerConfig.html +12 -12
  144. package/docs/interfaces/ControlBarConfig.html +12 -12
  145. package/docs/interfaces/DynamicSettingsPanelItemConfig.html +19 -19
  146. package/docs/interfaces/ErrorMessageMap.html +1 -1
  147. package/docs/interfaces/ErrorMessageOverlayConfig.html +13 -13
  148. package/docs/interfaces/ErrorMessageTranslator.html +1 -1
  149. package/docs/interfaces/ExternalRecommendationLink.html +3 -3
  150. package/docs/interfaces/IconConfig.html +12 -12
  151. package/docs/interfaces/InternalUIConfig.html +15 -15
  152. package/docs/interfaces/LabelConfig.html +14 -14
  153. package/docs/interfaces/ListBoxConfig.html +22 -17
  154. package/docs/interfaces/ListItem.html +2 -2
  155. package/docs/interfaces/ListItemFilter.html +1 -1
  156. package/docs/interfaces/ListItemLabelTranslator.html +1 -1
  157. package/docs/interfaces/ListSelectorConfig.html +11 -11
  158. package/docs/interfaces/LocalizationConfig.html +3 -3
  159. package/docs/interfaces/MetadataLabelConfig.html +15 -15
  160. package/docs/interfaces/PlaybackTimeLabelConfig.html +16 -16
  161. package/docs/interfaces/PlaybackToggleButtonConfig.html +19 -19
  162. package/docs/interfaces/PlaybackToggleOverlayConfig.html +13 -13
  163. package/docs/interfaces/PlayerUtils.LiveStreamDetectorEventArgs.html +2 -2
  164. package/docs/interfaces/PlayerUtils.TimeShiftAvailabilityChangedArgs.html +2 -2
  165. package/docs/interfaces/QuickSeekButtonConfig.html +15 -15
  166. package/docs/interfaces/RecommendationConfig.html +4 -4
  167. package/docs/interfaces/RecommendationItemConfig.html +12 -12
  168. package/docs/interfaces/SeekBarConfig.html +19 -19
  169. package/docs/interfaces/SeekBarLabelConfig.html +12 -12
  170. package/docs/interfaces/SeekBarMarker.html +2 -2
  171. package/docs/interfaces/SeekPreviewArgs.html +3 -3
  172. package/docs/interfaces/SeekPreviewEventArgs.html +4 -4
  173. package/docs/interfaces/SettingsPanelConfig.html +20 -15
  174. package/docs/interfaces/SettingsPanelItemConfig.html +17 -17
  175. package/docs/interfaces/SettingsPanelPageConfig.html +13 -13
  176. package/docs/interfaces/SettingsToggleButtonConfig.html +20 -20
  177. package/docs/interfaces/SubtitleSettingSelectBoxConfig.html +11 -11
  178. package/docs/interfaces/SubtitleSettingsPanelPageConfig.html +13 -13
  179. package/docs/interfaces/TimelineMarker.html +6 -6
  180. package/docs/interfaces/TitleBarConfig.html +13 -13
  181. package/docs/interfaces/ToggleButtonConfig.html +18 -18
  182. package/docs/interfaces/UIConditionContext.html +10 -10
  183. package/docs/interfaces/UIConditionResolver.html +1 -1
  184. package/docs/interfaces/UIConfig.html +14 -14
  185. package/docs/interfaces/UIContainerConfig.html +20 -16
  186. package/docs/interfaces/UIUtils.TreeTraversalCallback.html +1 -1
  187. package/docs/interfaces/UIVariant.html +2 -2
  188. package/docs/interfaces/ViewModeChangedEventArgs.html +2 -2
  189. package/docs/interfaces/Vocabularies.html +1 -1
  190. package/docs/interfaces/Vocabulary.html +2 -2
  191. package/docs/interfaces/VolumeControlButtonConfig.html +14 -14
  192. package/docs/interfaces/VolumeSliderConfig.html +21 -21
  193. package/docs/interfaces/WatermarkConfig.html +15 -15
  194. package/docs/interfaces/WrappedPlayer.html +2 -2
  195. package/docs/media/CHANGELOG.md +20 -0
  196. package/docs/types/CustomVocabulary.html +1 -1
  197. package/docs/types/LocalizableText.html +1 -1
  198. package/docs/types/Localizer.html +1 -1
  199. package/docs/variables/ErrorUtils.defaultErrorMessages.html +1 -1
  200. package/docs/variables/ErrorUtils.defaultWebErrorMessageTranslator.html +1 -1
  201. package/docs/variables/StringUtils.FORMAT_HHMMSS.html +1 -1
  202. package/docs/variables/StringUtils.FORMAT_MMSS.html +1 -1
  203. package/docs/variables/i18n.html +1 -1
  204. package/docs/variables/version.html +1 -1
  205. package/package.json +1 -1
  206. package/src/ts/DOM.ts +18 -18
  207. package/src/ts/EventDispatcher.ts +5 -5
  208. package/src/ts/UIFactory.ts +8 -9
  209. package/src/ts/UIManager.ts +29 -29
  210. package/src/ts/components/CastUIContainer.ts +6 -6
  211. package/src/ts/components/Component.ts +3 -3
  212. package/src/ts/components/Container.ts +5 -5
  213. package/src/ts/components/RecommendationItem.ts +2 -2
  214. package/src/ts/components/TvNoiseCanvas.ts +3 -3
  215. package/src/ts/components/UIContainer.ts +57 -14
  216. package/src/ts/components/ads/AdClickOverlay.ts +2 -2
  217. package/src/ts/components/ads/AdMessageLabel.ts +47 -20
  218. package/src/ts/components/ads/AdSkipButton.ts +5 -5
  219. package/src/ts/components/buttons/Button.ts +1 -1
  220. package/src/ts/components/buttons/CastToggleButton.ts +1 -1
  221. package/src/ts/components/buttons/CloseButton.ts +1 -1
  222. package/src/ts/components/buttons/HugePlaybackToggleButton.ts +3 -3
  223. package/src/ts/components/buttons/PlaybackToggleButton.ts +3 -3
  224. package/src/ts/components/buttons/QuickSeekButton.ts +1 -1
  225. package/src/ts/components/buttons/SmallCenteredPlaybackToggleButton.ts +1 -1
  226. package/src/ts/components/buttons/VRToggleButton.ts +4 -4
  227. package/src/ts/components/buttons/VolumeControlButton.ts +2 -2
  228. package/src/ts/components/labels/Label.ts +1 -1
  229. package/src/ts/components/labels/MetadataLabel.ts +4 -4
  230. package/src/ts/components/labels/PlaybackTimeLabel.ts +13 -13
  231. package/src/ts/components/lists/ItemSelectionList.ts +3 -3
  232. package/src/ts/components/lists/ListSelector.ts +4 -4
  233. package/src/ts/components/overlays/CastStatusOverlay.ts +2 -2
  234. package/src/ts/components/overlays/ClickOverlay.ts +1 -1
  235. package/src/ts/components/overlays/DismissClickOverlay.ts +7 -2
  236. package/src/ts/components/overlays/ErrorMessageOverlay.ts +2 -2
  237. package/src/ts/components/overlays/RecommendationOverlay.ts +2 -2
  238. package/src/ts/components/overlays/SubtitleOverlay.ts +10 -10
  239. package/src/ts/components/seekbar/SeekBar.ts +37 -37
  240. package/src/ts/components/seekbar/SeekBarLabel.ts +15 -15
  241. package/src/ts/components/seekbar/VolumeSlider.ts +1 -1
  242. package/src/ts/components/settings/AudioQualitySelectBox.ts +4 -4
  243. package/src/ts/components/settings/DynamicSettingsPanelItem.ts +3 -3
  244. package/src/ts/components/settings/SelectBox.ts +3 -3
  245. package/src/ts/components/settings/SettingsPanel.ts +137 -10
  246. package/src/ts/components/settings/SettingsPanelItem.ts +1 -1
  247. package/src/ts/components/settings/SettingsPanelPage.ts +4 -4
  248. package/src/ts/components/settings/SettingsPanelSelectOption.ts +1 -1
  249. package/src/ts/components/settings/SettingsToggleButton.ts +3 -3
  250. package/src/ts/components/settings/VideoQualitySelectBox.ts +4 -4
  251. package/src/ts/components/settings/subtitlesettings/BackgroundColorSelectBox.ts +1 -1
  252. package/src/ts/components/settings/subtitlesettings/FontColorSelectBox.ts +1 -1
  253. package/src/ts/components/settings/subtitlesettings/WindowColorSelectBox.ts +1 -1
  254. package/src/ts/main.ts +2 -2
  255. package/src/ts/spatialnavigation/NavigationGroup.ts +2 -2
  256. package/src/ts/spatialnavigation/SettingsPanelNavigationGroup.ts +1 -1
  257. package/src/ts/utils/ArrayUtils.ts +1 -1
  258. package/src/ts/utils/AudioTrackUtils.ts +1 -1
  259. package/src/ts/utils/ImageLoader.ts +2 -2
  260. package/src/ts/utils/PlayerUtils.ts +4 -4
  261. package/src/ts/utils/StorageUtils.ts +3 -3
  262. package/src/ts/utils/StringUtils.ts +17 -17
  263. package/src/ts/utils/SubtitleSettingsManager.ts +3 -3
  264. package/src/ts/utils/SubtitleUtils.ts +1 -1
  265. package/src/ts/utils/UIUtils.ts +2 -2
@@ -641,7 +641,6 @@ function emptyStateUILayout() {
641
641
  function buildDefaultSettingsPanel(subtitleOverlay, hideDelay, enableEcoMode) {
642
642
  if (hideDelay === void 0) { hideDelay = undefined; }
643
643
  if (enableEcoMode === void 0) { enableEcoMode = false; }
644
- var mainSettingsPanelPage;
645
644
  var settingsPanelConfig = {
646
645
  components: [],
647
646
  hidden: true,
@@ -681,7 +680,7 @@ function buildDefaultSettingsPanel(subtitleOverlay, hideDelay, enableEcoMode) {
681
680
  });
682
681
  components.unshift(ecoModeContainer);
683
682
  }
684
- mainSettingsPanelPage = new SettingsPanelPage_1.SettingsPanelPage({
683
+ var mainSettingsPanelPage = new SettingsPanelPage_1.SettingsPanelPage({
685
684
  components: components,
686
685
  });
687
686
  settingsPanel.addComponent(mainSettingsPanelPage);
@@ -36,7 +36,7 @@ export declare class Container<Config extends ContainerConfig> extends Component
36
36
  /**
37
37
  * A reference to the inner element that contains the components of the container.
38
38
  */
39
- private innerContainerElement;
39
+ protected innerContainerElement: DOM;
40
40
  private componentsToAppend;
41
41
  private componentsToPrepend;
42
42
  private componentsToRemove;
@@ -32,6 +32,12 @@ export interface UIContainerConfig extends ContainerConfig {
32
32
  * Default: true
33
33
  */
34
34
  hideImmediatelyOnMouseLeave?: boolean;
35
+ /**
36
+ * When true, suspend the UIContainer's hide timer while a SettingsPanel is open,
37
+ * and resume it when the panel closes.
38
+ * Default: true
39
+ */
40
+ deferUiHideWhileSettingsOpen?: boolean;
35
41
  }
36
42
  /**
37
43
  * The base container that contains all of the UI. The UIContainer is passed to the {@link UIManager} to build and
@@ -51,7 +57,7 @@ export declare class UIContainer extends Container<UIContainerConfig> {
51
57
  private userInteractionEventSource;
52
58
  private userInteractionEvents;
53
59
  private hidingPrevented;
54
- hideUi: () => void;
60
+ hideUi: (force?: boolean) => void;
55
61
  showUi: () => void;
56
62
  toggleUiShown: () => void;
57
63
  constructor(config: UIContainerConfig);
@@ -24,6 +24,7 @@ var EventDispatcher_1 = require("../EventDispatcher");
24
24
  var i18n_1 = require("../localization/i18n");
25
25
  var Button_1 = require("./buttons/Button");
26
26
  var TouchControlOverlay_1 = require("./overlays/TouchControlOverlay");
27
+ var SettingsPanel_1 = require("./settings/SettingsPanel");
27
28
  /**
28
29
  * The base container that contains all of the UI. The UIContainer is passed to the {@link UIManager} to build and
29
30
  * setup the UI.
@@ -43,6 +44,7 @@ var UIContainer = /** @class */ (function (_super) {
43
44
  ariaLabel: i18n_1.i18n.getLocalizer('player'),
44
45
  hideDelay: 2000,
45
46
  hideImmediatelyOnMouseLeave: true,
47
+ deferUiHideWhileSettingsOpen: true,
46
48
  }, _this.config);
47
49
  _this.playerStateChange = new EventDispatcher_1.EventDispatcher();
48
50
  _this.hidingPrevented = function () { return false; };
@@ -64,6 +66,8 @@ var UIContainer = /** @class */ (function (_super) {
64
66
  var _this = this;
65
67
  var config = this.getConfig();
66
68
  var isUiShown = false;
69
+ var isSettingsPanelShown = false;
70
+ var isHideUiPending = false;
67
71
  uimanager.onConfigured.subscribe(function () {
68
72
  if (isUiShown) {
69
73
  uimanager.onControlsShow.dispatch(_this);
@@ -79,10 +83,27 @@ var UIContainer = /** @class */ (function (_super) {
79
83
  var isSeeking = false;
80
84
  var isFirstTouch = true;
81
85
  var playerState;
86
+ if (config.deferUiHideWhileSettingsOpen) {
87
+ uimanager.onComponentShow.subscribe(function (component) {
88
+ if (component instanceof SettingsPanel_1.SettingsPanel) {
89
+ isSettingsPanelShown = true;
90
+ }
91
+ });
92
+ uimanager.onComponentHide.subscribe(function (component) {
93
+ if (component instanceof SettingsPanel_1.SettingsPanel) {
94
+ isSettingsPanelShown = false;
95
+ if (isHideUiPending) {
96
+ _this.hideUi(true);
97
+ isHideUiPending = false;
98
+ }
99
+ }
100
+ });
101
+ }
82
102
  this.hidingPrevented = function () {
83
103
  return config.hidePlayerStateExceptions && config.hidePlayerStateExceptions.indexOf(playerState) > -1;
84
104
  };
85
105
  this.showUi = function () {
106
+ isHideUiPending = false;
86
107
  if (!isUiShown) {
87
108
  // Let subscribers know that they should reveal themselves
88
109
  uimanager.onControlsShow.dispatch(_this);
@@ -93,9 +114,19 @@ var UIContainer = /** @class */ (function (_super) {
93
114
  _this.uiHideTimeout.start();
94
115
  }
95
116
  };
96
- this.hideUi = function () {
117
+ this.hideUi = function (force) {
118
+ if (force === void 0) { force = false; }
97
119
  // Hide the UI only if it is shown, and if not casting
98
120
  if (isUiShown && !player.isCasting()) {
121
+ if (force) {
122
+ uimanager.onControlsHide.dispatch(_this);
123
+ isUiShown = false;
124
+ return;
125
+ }
126
+ if (config.deferUiHideWhileSettingsOpen && isSettingsPanelShown) {
127
+ isHideUiPending = true;
128
+ return;
129
+ }
99
130
  // Issue a preview event to check if we are good to hide the controls
100
131
  var previewHideEventArgs = {};
101
132
  uimanager.onPreviewControlsHide.dispatch(_this, previewHideEventArgs);
@@ -215,7 +246,7 @@ var UIContainer = /** @class */ (function (_super) {
215
246
  // hide the UI in such cases
216
247
  if (!isSeeking && !_this.hidingPrevented()) {
217
248
  if (_this.config.hideImmediatelyOnMouseLeave) {
218
- _this.hideUi();
249
+ _this.hideUi(true);
219
250
  }
220
251
  else {
221
252
  _this.uiHideTimeout.start();
@@ -1,8 +1,27 @@
1
- import { UIInstanceManager } from '../../UIManager';
2
- import { PlayerAPI } from 'bitmovin-player';
3
1
  import { Label, LabelConfig } from '../labels/Label';
2
+ import { PlayerAPI } from 'bitmovin-player';
3
+ import { UIInstanceManager } from '../../UIManager';
4
4
  /**
5
- * A label that displays a message regarding the ad that's currently being played.
5
+ * A label that displays a message about a running ad, optionally with a countdown.
6
+ *
7
+ * The message text supports placeholders that are dynamically replaced with ad timing information:
8
+ * - `{remainingTime[formatString]}` - Remaining time until the ad ends
9
+ * - `{playedTime[formatString]}` - Current playback time of the ad
10
+ * - `{adDuration[formatString]}` - Total duration of the current ad
11
+ * - `{adBreakRemainingTime[formatString]}` - Remaining time for the entire ad break (including all remaining ads)
12
+ *
13
+ * Format string options (optional):
14
+ * - `%d` - Integer (e.g., `{remainingTime%d}` → `100`)
15
+ * - `%0Nd` - Integer with N leading zeros (e.g., `{remainingTime%03d}` → `100`)
16
+ * - `%f` - Float (e.g., `{remainingTime%f}` → `100.0`)
17
+ * - `%0Nf` - Float with leading zeros (e.g., `{remainingTime%05f}` → `100.0`)
18
+ * - `%.Mf` - Float with M decimal places (e.g., `{remainingTime%.2f}` → `100.00`)
19
+ * - `%hh:mm:ss` - Time format with hours (e.g., `{remainingTime%hh:mm:ss}` → `00:01:40`)
20
+ * - `%mm:ss` - Time format without hours (e.g., `{remainingTime%mm:ss}` → `01:40`)
21
+ *
22
+ * Example: `{ text: 'Ad: {remainingTime%mm:ss}' }` displays "Ad: 01:40" for 100 seconds remaining.
23
+ *
24
+ * Note: If a LinearAd has a `uiConfig.message` property, it takes precedence over the configured `text`.
6
25
  *
7
26
  * @category Labels
8
27
  */
@@ -17,8 +17,29 @@ var __extends = (this && this.__extends) || (function () {
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.AdMessageLabel = void 0;
19
19
  var Label_1 = require("../labels/Label");
20
+ var i18n_1 = require("../../localization/i18n");
21
+ var StringUtils_1 = require("../../utils/StringUtils");
20
22
  /**
21
- * A label that displays a message regarding the ad that's currently being played.
23
+ * A label that displays a message about a running ad, optionally with a countdown.
24
+ *
25
+ * The message text supports placeholders that are dynamically replaced with ad timing information:
26
+ * - `{remainingTime[formatString]}` - Remaining time until the ad ends
27
+ * - `{playedTime[formatString]}` - Current playback time of the ad
28
+ * - `{adDuration[formatString]}` - Total duration of the current ad
29
+ * - `{adBreakRemainingTime[formatString]}` - Remaining time for the entire ad break (including all remaining ads)
30
+ *
31
+ * Format string options (optional):
32
+ * - `%d` - Integer (e.g., `{remainingTime%d}` → `100`)
33
+ * - `%0Nd` - Integer with N leading zeros (e.g., `{remainingTime%03d}` → `100`)
34
+ * - `%f` - Float (e.g., `{remainingTime%f}` → `100.0`)
35
+ * - `%0Nf` - Float with leading zeros (e.g., `{remainingTime%05f}` → `100.0`)
36
+ * - `%.Mf` - Float with M decimal places (e.g., `{remainingTime%.2f}` → `100.00`)
37
+ * - `%hh:mm:ss` - Time format with hours (e.g., `{remainingTime%hh:mm:ss}` → `00:01:40`)
38
+ * - `%mm:ss` - Time format without hours (e.g., `{remainingTime%mm:ss}` → `01:40`)
39
+ *
40
+ * Example: `{ text: 'Ad: {remainingTime%mm:ss}' }` displays "Ad: 01:40" for 100 seconds remaining.
41
+ *
42
+ * Note: If a LinearAd has a `uiConfig.message` property, it takes precedence over the configured `text`.
22
43
  *
23
44
  * @category Labels
24
45
  */
@@ -35,23 +56,25 @@ var AdMessageLabel = /** @class */ (function (_super) {
35
56
  AdMessageLabel.prototype.configure = function (player, uimanager) {
36
57
  var _this = this;
37
58
  _super.prototype.configure.call(this, player, uimanager);
38
- var clearText = function () {
39
- _this.setText('');
59
+ var config = this.getConfig();
60
+ var text = config.text;
61
+ var updateMessageHandler = function () {
62
+ _this.setText(StringUtils_1.StringUtils.replaceAdMessagePlaceholders(i18n_1.i18n.performLocalization(text), null, player));
63
+ };
64
+ var adStartHandler = function (event) {
65
+ var uiConfig = event.ad.uiConfig;
66
+ text = (uiConfig === null || uiConfig === void 0 ? void 0 : uiConfig.message) || config.text;
67
+ updateMessageHandler();
68
+ player.on(player.exports.PlayerEvent.TimeChanged, updateMessageHandler);
69
+ };
70
+ var adEndHandler = function () {
71
+ player.off(player.exports.PlayerEvent.TimeChanged, updateMessageHandler);
40
72
  };
41
- clearText();
42
- player.on(player.exports.PlayerEvent.SourceUnloaded, clearText);
43
- player.on(player.exports.PlayerEvent.AdError, clearText);
44
- player.on(player.exports.PlayerEvent.AdSkipped, clearText);
45
- player.on(player.exports.PlayerEvent.AdFinished, clearText);
46
- player.on(player.exports.PlayerEvent.AdStarted, function (event) {
47
- var _a, _b;
48
- var ad = event.ad;
49
- if (!ad.isLinear) {
50
- return;
51
- }
52
- var linearAd = ad;
53
- _this.setText((_b = (_a = linearAd.uiConfig) === null || _a === void 0 ? void 0 : _a.message) !== null && _b !== void 0 ? _b : '');
54
- });
73
+ player.on(player.exports.PlayerEvent.AdStarted, adStartHandler);
74
+ player.on(player.exports.PlayerEvent.AdSkipped, adEndHandler);
75
+ player.on(player.exports.PlayerEvent.AdError, adEndHandler);
76
+ player.on(player.exports.PlayerEvent.AdFinished, adEndHandler);
77
+ player.on(player.exports.PlayerEvent.SourceUnloaded, adEndHandler);
55
78
  };
56
79
  return AdMessageLabel;
57
80
  }(Label_1.Label));
@@ -17,6 +17,7 @@ var __extends = (this && this.__extends) || (function () {
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.DismissClickOverlay = void 0;
19
19
  var Container_1 = require("../Container");
20
+ var SettingsPanel_1 = require("../settings/SettingsPanel");
20
21
  var DismissClickOverlay = /** @class */ (function (_super) {
21
22
  __extends(DismissClickOverlay, _super);
22
23
  function DismissClickOverlay(config) {
@@ -38,7 +39,12 @@ var DismissClickOverlay = /** @class */ (function (_super) {
38
39
  });
39
40
  var element = this.getDomElement();
40
41
  element.on('click', function () {
41
- _this.config.target.hide();
42
+ if (_this.config.target instanceof SettingsPanel_1.SettingsPanel) {
43
+ _this.config.target.hideAndReset();
44
+ }
45
+ else {
46
+ _this.config.target.hide();
47
+ }
42
48
  });
43
49
  };
44
50
  return DismissClickOverlay;
@@ -13,7 +13,7 @@ export interface SettingsPanelConfig extends ContainerConfig {
13
13
  /**
14
14
  * The delay in milliseconds after which the settings panel will be hidden when there is no user interaction.
15
15
  * Set to -1 to disable automatic hiding.
16
- * Default: 3 seconds (3000)
16
+ * Default: 5 seconds (5000)
17
17
  */
18
18
  hideDelay?: number;
19
19
  /**
@@ -21,6 +21,22 @@ export interface SettingsPanelConfig extends ContainerConfig {
21
21
  * Default: true
22
22
  */
23
23
  pageTransitionAnimation?: boolean;
24
+ /**
25
+ * The delay in milliseconds after hiding the settings panel before its internal state
26
+ * (e.g., navigation stack and scroll position) is reset.
27
+ * Set to -1 to disable automatic state reset.
28
+ * Default: 5 seconds (5000)
29
+ */
30
+ stateResetDelay?: number;
31
+ }
32
+ /**
33
+ * State interface for preserving settings panel navigation and scroll position
34
+ */
35
+ export interface SettingsPanelState {
36
+ activePageIndex: number;
37
+ navigationStackIndices: number[];
38
+ scrollTop: number;
39
+ wrapperScrollTop: number;
24
40
  }
25
41
  export declare enum NavigationDirection {
26
42
  Forwards = 0,
@@ -55,6 +71,9 @@ export declare class SettingsPanel<Config extends SettingsPanelConfig> extends C
55
71
  private static readonly CLASS_ACTIVE_PAGE;
56
72
  private activePage;
57
73
  private navigationStack;
74
+ private currentState;
75
+ private resetStateTimerId;
76
+ private shouldResetStateImmediately;
58
77
  private settingsPanelEvents;
59
78
  private hideTimeout;
60
79
  constructor(config: Config);
@@ -105,6 +124,7 @@ export declare class SettingsPanel<Config extends SettingsPanelConfig> extends C
105
124
  getRootPage(): SettingsPanelPage;
106
125
  get onSettingsStateChanged(): Event<SettingsPanel<SettingsPanelConfig>, NoArgs>;
107
126
  get onActivePageChanged(): Event<SettingsPanel<SettingsPanelConfig>, NoArgs>;
127
+ hideAndReset(): void;
108
128
  release(): void;
109
129
  addComponent(component: Component<ComponentConfig>): void;
110
130
  addPage(page: SettingsPanelPage): void;
@@ -112,6 +132,13 @@ export declare class SettingsPanel<Config extends SettingsPanelConfig> extends C
112
132
  protected resumeHideTimeout(): void;
113
133
  private updateActivePageClass;
114
134
  private resetNavigation;
135
+ private get wrapperScrollTop();
136
+ private set wrapperScrollTop(value);
137
+ private resetState;
138
+ private buildCurrentState;
139
+ private isDefaultPanelState;
140
+ private maybeSaveCurrentState;
141
+ private restoreNavigationState;
115
142
  protected navigateToPage(targetPage: SettingsPanelPage, sourcePage: SettingsPanelPage, direction: NavigationDirection, skipAnimation: boolean): void;
116
143
  /**
117
144
  * @param targetPage
@@ -58,14 +58,18 @@ var SettingsPanel = /** @class */ (function (_super) {
58
58
  function SettingsPanel(config) {
59
59
  var _this = _super.call(this, config) || this;
60
60
  _this.navigationStack = [];
61
+ _this.currentState = null;
62
+ _this.resetStateTimerId = null;
63
+ _this.shouldResetStateImmediately = false;
61
64
  _this.settingsPanelEvents = {
62
65
  onSettingsStateChanged: new EventDispatcher_1.EventDispatcher(),
63
66
  onActivePageChanged: new EventDispatcher_1.EventDispatcher(),
64
67
  };
65
68
  _this.config = _this.mergeConfig(config, {
66
69
  cssClass: 'ui-settings-panel',
67
- hideDelay: 3000,
70
+ hideDelay: 5000,
68
71
  pageTransitionAnimation: true,
72
+ stateResetDelay: 5000,
69
73
  }, _this.config);
70
74
  _this.activePage = _this.getRootPage();
71
75
  _this.onActivePageChangedEvent();
@@ -86,10 +90,7 @@ var SettingsPanel = /** @class */ (function (_super) {
86
90
  _this.hideHoveredSelectBoxes();
87
91
  });
88
92
  this.getDomElement().on('mouseenter mousemove', function () {
89
- // On mouse enter and mouse move clear the timeout
90
- if (_this.hideTimeout.isActive()) {
91
- _this.hideTimeout.clear();
92
- }
93
+ _this.hideTimeout.reset();
93
94
  });
94
95
  this.getDomElement().on('mouseleave', function () {
95
96
  // On mouse leave activate the timeout
@@ -113,9 +114,27 @@ var SettingsPanel = /** @class */ (function (_super) {
113
114
  var action = (0, getKeyMapForPlatform_1.getKeyMapForPlatform)()[event.keyCode];
114
115
  if (action === types_1.Action.BACK) {
115
116
  _this.hide();
117
+ _this.resetState();
118
+ }
119
+ };
120
+ var scheduleResetState = function () {
121
+ if (_this.resetStateTimerId !== null) {
122
+ clearTimeout(_this.resetStateTimerId);
123
+ _this.resetStateTimerId = null;
124
+ }
125
+ if (config.stateResetDelay > -1) {
126
+ _this.resetStateTimerId = window.setTimeout(function () { return _this.resetState(); }, config.stateResetDelay);
116
127
  }
117
128
  };
118
129
  this.onHide.subscribe(function () {
130
+ if (_this.shouldResetStateImmediately) {
131
+ _this.currentState = null;
132
+ _this.shouldResetStateImmediately = false;
133
+ }
134
+ else {
135
+ _this.currentState = _this.maybeSaveCurrentState();
136
+ scheduleResetState();
137
+ }
119
138
  if (config.hideDelay > -1) {
120
139
  // Clear timeout when hidden from outside
121
140
  _this.hideTimeout.clear();
@@ -126,8 +145,17 @@ var SettingsPanel = /** @class */ (function (_super) {
126
145
  document.removeEventListener('keyup', maybeCloseSettingsPanel);
127
146
  });
128
147
  this.onShow.subscribe(function () {
129
- // Reset navigation when te panel gets visible to avoid a weird animation when hiding
130
- _this.resetNavigation(true);
148
+ if (_this.resetStateTimerId !== null) {
149
+ clearTimeout(_this.resetStateTimerId);
150
+ _this.resetStateTimerId = null;
151
+ }
152
+ if (_this.currentState !== null) {
153
+ _this.restoreNavigationState(_this.currentState);
154
+ }
155
+ else {
156
+ // No saved state (was reset), ensure visual classes are updated
157
+ _this.updateActivePageClass();
158
+ }
131
159
  // Since we don't need to navigate to the root page again we need to fire the onActive event when the settings
132
160
  // panel gets visible.
133
161
  _this.activePage.onActiveEvent();
@@ -144,6 +172,11 @@ var SettingsPanel = /** @class */ (function (_super) {
144
172
  uimanager.onControlsHide.subscribe(function () {
145
173
  _this.hide();
146
174
  });
175
+ uimanager.onControlsShow.subscribe(function () {
176
+ if (_this.currentState !== null) {
177
+ _this.show();
178
+ }
179
+ });
147
180
  this.updateActivePageClass();
148
181
  };
149
182
  /**
@@ -238,6 +271,11 @@ var SettingsPanel = /** @class */ (function (_super) {
238
271
  enumerable: false,
239
272
  configurable: true
240
273
  });
274
+ SettingsPanel.prototype.hideAndReset = function () {
275
+ this.shouldResetStateImmediately = true;
276
+ this.hide();
277
+ this.resetState();
278
+ };
241
279
  SettingsPanel.prototype.release = function () {
242
280
  _super.prototype.release.call(this);
243
281
  if (this.hideTimeout) {
@@ -288,6 +326,64 @@ var SettingsPanel = /** @class */ (function (_super) {
288
326
  this.updateActivePageClass();
289
327
  this.onActivePageChangedEvent();
290
328
  };
329
+ Object.defineProperty(SettingsPanel.prototype, "wrapperScrollTop", {
330
+ get: function () {
331
+ var _a, _b;
332
+ return (_b = (_a = this.innerContainerElement.get(0)) === null || _a === void 0 ? void 0 : _a.scrollTop) !== null && _b !== void 0 ? _b : 0;
333
+ },
334
+ set: function (value) {
335
+ var element = this.innerContainerElement.get(0);
336
+ if (element) {
337
+ element.scrollTop = value;
338
+ }
339
+ },
340
+ enumerable: false,
341
+ configurable: true
342
+ });
343
+ SettingsPanel.prototype.resetState = function () {
344
+ this.activePage = this.getRootPage();
345
+ this.navigationStack = [];
346
+ this.currentState = null;
347
+ this.resetStateTimerId = null;
348
+ if (this.isHidden()) {
349
+ // Clear dimensions only when hidden to avoid visible transition animation
350
+ this.getDomElement().css({ width: '', height: '' });
351
+ }
352
+ };
353
+ SettingsPanel.prototype.buildCurrentState = function () {
354
+ var pages = this.getPages();
355
+ var activePageIndex = pages.indexOf(this.getActivePage());
356
+ var navigationStackIndices = this.navigationStack.map(function (p) { return pages.indexOf(p); });
357
+ var panelElement = this.getDomElement().get(0);
358
+ return {
359
+ activePageIndex: activePageIndex,
360
+ navigationStackIndices: navigationStackIndices,
361
+ scrollTop: panelElement.scrollTop,
362
+ wrapperScrollTop: this.wrapperScrollTop,
363
+ };
364
+ };
365
+ SettingsPanel.prototype.isDefaultPanelState = function () {
366
+ var _a;
367
+ var panelElement = this.getDomElement().get(0);
368
+ var atRoot = this.getActivePage() === this.getRootPage();
369
+ var noNav = this.navigationStack.length === 0;
370
+ var noScroll = ((_a = panelElement === null || panelElement === void 0 ? void 0 : panelElement.scrollTop) !== null && _a !== void 0 ? _a : 0) === 0 && this.wrapperScrollTop === 0;
371
+ return atRoot && noNav && noScroll;
372
+ };
373
+ SettingsPanel.prototype.maybeSaveCurrentState = function () {
374
+ return this.isDefaultPanelState() ? null : this.buildCurrentState();
375
+ };
376
+ SettingsPanel.prototype.restoreNavigationState = function (state) {
377
+ var _a;
378
+ var pages = this.getPages();
379
+ this.activePage = (_a = pages[state.activePageIndex]) !== null && _a !== void 0 ? _a : this.getRootPage();
380
+ this.navigationStack = state.navigationStackIndices.map(function (i) { return pages[i]; }).filter(Boolean);
381
+ this.updateActivePageClass();
382
+ this.onActivePageChangedEvent();
383
+ this.activePage.onActiveEvent();
384
+ this.getDomElement().get(0).scrollTop = state.scrollTop;
385
+ this.wrapperScrollTop = state.wrapperScrollTop;
386
+ };
291
387
  SettingsPanel.prototype.navigateToPage = function (targetPage, sourcePage, direction, skipAnimation) {
292
388
  this.activePage = targetPage;
293
389
  if (direction === NavigationDirection.Forwards) {
@@ -3,8 +3,8 @@ import { PlayerAPI } from 'bitmovin-player';
3
3
  * @category Utils
4
4
  */
5
5
  export declare namespace StringUtils {
6
- let FORMAT_HHMMSS: string;
7
- let FORMAT_MMSS: string;
6
+ const FORMAT_HHMMSS: string;
7
+ const FORMAT_MMSS: string;
8
8
  /**
9
9
  * Formats a number of seconds into a time string with the pattern hh:mm:ss.
10
10
  *
@@ -1 +1 @@
1
- window.hierarchyData = "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"
1
+ window.hierarchyData = "eJydW0tz5DYO/i86IxvxTfo29s7sTlWymdjZ2UMqB0033aOyWnJJ6sl6U/PftyD5QUpqCexLV5f7Az8ABAkCpP/K2qbpu+zqd8msAMkdA2MUMJ6D5PIPyFp/X/ldXzZ1l139lSn8qIujz66yj3Xv27qo/v3xpqnvy0MG2UNZ77MrrjRkp7bKrrISMffFznc/TuF/+9ofqwyyXVV0XXaV9d3+B5T/4VUm+w4Z43lAeef9w6fWfyv9n+/aQ7fBOEETCCHbfS2rfevr7Op35pj74ztkkstABaK1CVZGpAoZjQn9/K/iW3kocAr+0Tanx1dixu0L8TC6736cQM+Sj3+IiK1gYLVBeitYQH/bNH2CCgvwDTWQUZtolvu+rA/dp6L2VQL1mty2Di53gQ7Xp75v6jW2EZHiYq6sAyVzB0pxDZoLDdowAdZJASwXAj+lyHESWM74TB9S6IXQ1PDjhhlQijFQmgvQluXAciXMqFIUGDdN3bdNdV20a256Q6W4SmkxrD3GpFykJHliCk9ejEaNhjOlAy0+nKqq27Xe1781h0Plt2NlWWI7JhmPdoJ/ng7+U1U8fSl2D1TqczIEcuFsQP46SHn0PxVffLXGOgMT6BSTa3SkGT8jRcw1SqglDYievsDLcb7hZtj9mVZmQ400X8wEie7QRk9y78Zaf4akGG1yM2531pk5GcnOCJu6xA1nduB3zC0fNN5/83Wfdtp4FSE62nEbceOJ67r577qrn0FJCcgIBUJrDcLmFqRzFnRuDVhpNXqB506EJ7zeH0eisql/Krt+TaMZeHvJcy7O5n1yok9xgMslG+yUUSaLxiPG3EwiNfIcc2bURboFXai7zhKe4Hmlt0iT/HDpHoNHokAPqtEXb7FMacBtHtDrwK3NgTvnQOZagnaKgeGSD9NimDmjGckzF3kkVlYrAzhRozpRbvpc7n3z66moyv6JtF8sChDixNqw/vrcVKejp87SHE0gdC4MiM+3ZLLbNCLBWLjp/qfofXss2oc1jlcQYXgeFa6vkqTYmaBpS0nwKEKGArQvytqvpuwAlrKQtNRD2hbCzorjcTR6lRziiabKfFqIbBp6kZlY8QBmKUDvgnAqBykYAynxmzYKpBUOFJM5KG4UaCzitLIanOIKWJ4LByw3XAzuUlFUpDkr3VWTvU9KwMQHOGkg8Zu03IDimoMSToGW0oA2eQ4ODwksZ1qNaouwFt08/VNO/LFuwllQRjtQzjjQlo+8WtopL8lVaUf/WBXFMBMIPSqgwyPwu9O+TNp1FwUIm4fN7ZT2t7bYPdBJYziB0qkoMouuv+uL/tT98s23VfG0urSm4G06zLcTOupGP8USyJgV0ao7Pja1r1dPs6+gtOOlA6yaADcowFUDUmkNRmiGbRTFgeV2bKZgr3VJKeJWEKGTYzxnHLDiAtyQAJcZSK2x+6SdBZY7PuooWKjj+7Zt2p991xUHTwiLBThhruKT+cIYJAedlaMlGNzewxao3zXHo6/3Qz+RYPqiAMF4FW038ShYX9E5EU0g1FqsEpKcfU6M6Gsd9bieq/nNHBPiCIZavtBeoCeUuQDROCuiOuv0pS/7irJ6JlCCiS5q173I07oJU/A2HR55wvoIxTfaQy8YwuBc84XBaYVXBKZNk4r7rGPh8tI9JtY5EZxgonAblCRrz8oRDZfRrcdNVe4eKBk/wKUkSCy6QFkzZBe8ZjjDTUuCM4HUPIhF2qgJj455+7uH8nF73kMcYcI1F2dISObOBYhTrKMt6N2edm8T4gjGmahnHQoTjbvgrmbg1bFxzzl/M33ESIKB1kwMJC6VGEkgcmY6XSe0mGBRiNwmwsbvwjXD3aP3e1LSWJYgEHMRrja8oLr1j1XxRLvMCrEEMiHCVXd9ur/3bVkfCDM3xRLIpDQrZMTb2yUh2mrArsykqiK2gSZQgqnK6oXoGQszgnMXBQi0Js+3aC+4HLvE14ZFRWXVdJTi9Q1GMNayfJmCmB8neKJhlocHk599X+yLvtjcfyIgwTgX7QKRNMm8BQmigU6F5453ZYvBQG0/LMC3jcVbztlh764q9+urMsQRSHjU0Q6FE46SoQDNn3hjEq7JctefWv+xfv5Cvj5fkSMYL3R0o/dY7NZ9OyIIA8soWq6L3cOhbU71/qapmpaUKM/JEMhVVNO9DfTLY7GjNiHPSxEUMDLcDG6+Fm2x6337fn+gVZbLEgRi68Kg+tBgr4vq8Dma8AQtj47JOMSH4lhWNB8vwAmULMqhOEbKvC7hCaTxgQgHuSv/R5vMGZhAJyMb3xoNw71xYnMilkl6ZiLxalc5CxjRgNEFOOOAcwDoE7BaOrDGDY1/q4UkqE3rHa0K0/ZYVC68TizrffMnfUEs4QlzZ5yekaZE6LIEgdhJcd773a3vfE94GXFejPIaVIbbPr5n2TD2GZJ0X8CZASfM8CYF34PMGWnXXSGWFlBIveBigp0TKMGVwkTnrdfrKQLZDEygUzzuJwcvdT4VB09+WITgpNm0dpzI+NJwNmb6A6M3qfSbnny8eUblVpYUzTvnhAiPO1EPCv8lO+oFThpVEktvoIbBti5bZmCKC5g+G5jku5YzUulxIZh8edMdZrq/P9XFsdxdpty6MHVa4gMKtTWU1hYantkHLL+eSrwu9w/bRBMohUtFzxwnA5A8uyhDdahSfJJYxlzcrBZIIS7pLYfjFvAh6RheOqpgwkHJqS0WSA11PMrBy2PL4SVO3IWnvnKYQCnzbqN5/7hbDyz8nTKq49NRaf9/tUuJm+/f/w8yEdEd"