@npo/player 1.24.7 → 1.26.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 (170) hide show
  1. package/README.md +1 -1
  2. package/lib/js/api/getstreamobject.d.ts +1 -1
  3. package/lib/js/api/getstreamobject.js +4 -4
  4. package/lib/js/api/getstreamobject.test.js +13 -13
  5. package/lib/js/playeractions/handlers/handleoffsets.js +9 -7
  6. package/lib/js/playeractions/handlers/handleoffsets.test.js +1 -1
  7. package/lib/js/playeractions/handlers/processplayerconfig.d.ts +1 -1
  8. package/lib/js/playeractions/handlers/processplayerconfig.js +18 -4
  9. package/lib/js/playeractions/handlers/processplayerconfig.test.js +116 -0
  10. package/lib/js/playeractions/handlers/processsourceconfig.d.ts +3 -1
  11. package/lib/js/playeractions/handlers/processsourceconfig.js +20 -10
  12. package/lib/js/playeractions/handlers/processsourceconfig.test.js +25 -0
  13. package/lib/js/settings/localization.d.ts +76 -1
  14. package/lib/js/settings/localization.js +2 -2
  15. package/lib/js/tracking/handlers/eventbinding.js +25 -17
  16. package/lib/js/tracking/handlers/eventlogging.js +3 -8
  17. package/lib/js/tracking/handlers/playertrackerinit.d.ts +2 -2
  18. package/lib/js/tracking/handlers/playertrackerinit.js +8 -6
  19. package/lib/js/tracking/handlers/playertrackerinit.test.d.ts +1 -0
  20. package/lib/js/tracking/handlers/playertrackerinit.test.js +74 -0
  21. package/lib/js/tracking/handlers/playertrackerstart.js +1 -1
  22. package/lib/js/utilities/utilities.element.d.ts +6 -0
  23. package/lib/js/utilities/utilities.element.js +10 -0
  24. package/lib/js/utilities/utilities.element.test.js +18 -5
  25. package/lib/lang/nl.json +1 -1
  26. package/lib/lang/subtitleLabels/nl.json +14 -0
  27. package/lib/npoplayer.d.ts +15 -6
  28. package/lib/npoplayer.js +57 -50
  29. package/lib/npoplayer.test.js +12 -4
  30. package/lib/package.json +3 -3
  31. package/lib/services/a11y/setup.js +2 -5
  32. package/lib/services/a11y/setup.test.js +2 -19
  33. package/lib/services/advertHandlers/discardAdBreak.js +4 -4
  34. package/lib/services/advertHandlers/discardAdBreak.test.js +25 -13
  35. package/lib/services/advertHandlers/handlePreRolls.js +19 -19
  36. package/lib/services/advertHandlers/handlePrerolls.test.js +4 -4
  37. package/lib/services/cdnProviders/cdnProviders.js +4 -2
  38. package/lib/services/drmHandlers/decideprofile.js +1 -1
  39. package/lib/services/drmHandlers/decideprofile.test.js +1 -1
  40. package/lib/services/drmHandlers/verifydrm.js +6 -6
  41. package/lib/services/drmHandlers/verifydrm.test.js +5 -5
  42. package/lib/services/eventListenerHandlers/removeEventListeners.js +2 -2
  43. package/lib/services/eventListenerHandlers/removeEventListeners.test.js +9 -9
  44. package/lib/services/keyboardHandlers/resolvekeypress.js +5 -5
  45. package/lib/services/keyboardHandlers/resolvekeypress.test.js +1 -1
  46. package/lib/services/liveStreamHandlers/handleLiveStreamControls.js +2 -2
  47. package/lib/services/liveStreamHandlers/handleLiveStreamControls.test.js +2 -2
  48. package/lib/services/localStorageHandlers/localStorageHandlers.js +2 -2
  49. package/lib/services/localStorageHandlers/localStorageHandlers.test.js +2 -5
  50. package/lib/services/nicamHandlers/nicamhandler.d.ts +5 -0
  51. package/lib/{ui/handlers → services/nicamHandlers}/nicamhandler.js +24 -15
  52. package/lib/services/nicamHandlers/nicamhandler.test.js +132 -0
  53. package/lib/services/npoPlayerAPI/npoPlayerAPI.d.ts +3 -2
  54. package/lib/services/npoPlayerAPI/npoPlayerAPI.js +19 -23
  55. package/lib/services/preferences/handlePreferences.d.ts +2 -0
  56. package/lib/services/preferences/handlePreferences.js +42 -0
  57. package/lib/services/preferences/handlePreferences.test.d.ts +1 -0
  58. package/lib/services/preferences/handlePreferences.test.js +102 -0
  59. package/lib/services/segmentHandlers/addSegmentEventListeners.js +2 -2
  60. package/lib/services/segmentHandlers/addSegmentEventListeners.test.js +1 -1
  61. package/lib/services/segmentHandlers/setSegmentMarkers.js +1 -1
  62. package/lib/services/services.d.ts +7 -0
  63. package/lib/services/services.js +26 -0
  64. package/lib/services/streamoptionsHandlers/streamOptionsHandler.d.ts +6 -0
  65. package/lib/services/streamoptionsHandlers/streamOptionsHandler.js +78 -0
  66. package/lib/services/streamoptionsHandlers/streamOptionsHandler.test.js +187 -0
  67. package/lib/services/uiHandlers/uiVisiblityHandler.d.ts +3 -0
  68. package/lib/services/uiHandlers/uiVisiblityHandler.js +26 -0
  69. package/lib/services/uiHandlers/uiVisiblityHandler.test.d.ts +1 -0
  70. package/lib/services/uiHandlers/uiVisiblityHandler.test.js +62 -0
  71. package/lib/src/js/api/getstreamobject.d.ts +1 -1
  72. package/lib/src/js/playeractions/handlers/processplayerconfig.d.ts +1 -1
  73. package/lib/src/js/playeractions/handlers/processplayerconfig.test.d.ts +1 -0
  74. package/lib/src/js/playeractions/handlers/processsourceconfig.d.ts +3 -1
  75. package/lib/src/js/playeractions/handlers/processsourceconfig.test.d.ts +1 -0
  76. package/lib/src/js/settings/localization.d.ts +76 -1
  77. package/lib/src/js/tracking/handlers/playertrackerinit.d.ts +2 -2
  78. package/lib/src/js/tracking/handlers/playertrackerinit.test.d.ts +1 -0
  79. package/lib/src/js/utilities/utilities.element.d.ts +6 -0
  80. package/lib/src/npoplayer.d.ts +15 -6
  81. package/lib/src/services/nicamHandlers/nicamhandler.d.ts +5 -0
  82. package/lib/src/services/nicamHandlers/nicamhandler.test.d.ts +1 -0
  83. package/lib/src/services/npoPlayerAPI/npoPlayerAPI.d.ts +3 -2
  84. package/lib/src/services/preferences/handlePreferences.d.ts +2 -0
  85. package/lib/src/services/preferences/handlePreferences.test.d.ts +1 -0
  86. package/lib/src/services/services.d.ts +7 -0
  87. package/lib/src/services/streamoptionsHandlers/streamOptionsHandler.d.ts +6 -0
  88. package/lib/src/services/streamoptionsHandlers/streamOptionsHandler.test.d.ts +1 -0
  89. package/lib/src/services/uiHandlers/uiVisiblityHandler.d.ts +3 -0
  90. package/lib/src/services/uiHandlers/uiVisiblityHandler.test.d.ts +1 -0
  91. package/lib/src/types/classes.d.ts +6 -0
  92. package/lib/src/types/interfaces.d.ts +25 -3
  93. package/lib/src/ui/components/adbutton.d.ts +1 -1
  94. package/lib/src/ui/components/adlabel.d.ts +1 -1
  95. package/lib/src/ui/components/buttons.d.ts +10 -17
  96. package/lib/src/ui/components/controlbar.d.ts +2 -2
  97. package/lib/src/ui/components/ctabar.d.ts +1 -1
  98. package/lib/src/ui/components/nativemobile/buttons.d.ts +8 -0
  99. package/lib/src/ui/components/playnext.d.ts +1 -3
  100. package/lib/src/ui/components/seekbar.d.ts +1 -1
  101. package/lib/src/ui/components/titlebar.d.ts +1 -1
  102. package/lib/src/ui/components/topbar.d.ts +2 -2
  103. package/lib/src/ui/components/verticalvideo/controlbar.d.ts +2 -2
  104. package/lib/src/ui/handlers/playnextscreen.test.d.ts +1 -0
  105. package/lib/src/ui/handlers/timecontrolhandlers.d.ts +3 -3
  106. package/lib/src/ui/uicontainer.d.ts +2 -3
  107. package/lib/src/ui/uicontainer.test.d.ts +1 -0
  108. package/lib/tests/mocks/mockLogEmitter.d.ts +2 -0
  109. package/lib/tests/mocks/mockLogEmitter.js +20 -0
  110. package/lib/tests/mocks/mockNpoplayer.js +4 -2
  111. package/lib/tests/mocks/playerContextMock.d.ts +5 -3
  112. package/lib/tests/mocks/playerContextMock.js +8 -5
  113. package/lib/types/classes.d.ts +6 -0
  114. package/lib/types/classes.js +12 -0
  115. package/lib/types/interfaces.d.ts +25 -3
  116. package/lib/types/interfaces.js +1 -0
  117. package/lib/ui/components/adbutton.d.ts +1 -1
  118. package/lib/ui/components/adbutton.js +3 -3
  119. package/lib/ui/components/adlabel.d.ts +1 -1
  120. package/lib/ui/components/adlabel.js +3 -3
  121. package/lib/ui/components/buttons.d.ts +10 -17
  122. package/lib/ui/components/buttons.js +44 -27
  123. package/lib/ui/components/controlbar.d.ts +2 -2
  124. package/lib/ui/components/controlbar.js +20 -32
  125. package/lib/ui/components/ctabar.d.ts +1 -1
  126. package/lib/ui/components/ctabar.js +4 -4
  127. package/lib/ui/components/nativemobile/buttons.d.ts +8 -0
  128. package/lib/ui/components/nativemobile/buttons.js +41 -1
  129. package/lib/ui/components/nativemobile/controlbar.js +1 -2
  130. package/lib/ui/components/nativemobile/topbar.js +2 -2
  131. package/lib/ui/components/playnext.d.ts +1 -3
  132. package/lib/ui/components/playnext.js +3 -3
  133. package/lib/ui/components/seekbar.d.ts +1 -1
  134. package/lib/ui/components/seekbar.js +5 -3
  135. package/lib/ui/components/settingspanel.js +9 -9
  136. package/lib/ui/components/titlebar.d.ts +1 -1
  137. package/lib/ui/components/titlebar.js +2 -2
  138. package/lib/ui/components/topbar.d.ts +2 -2
  139. package/lib/ui/components/topbar.js +8 -17
  140. package/lib/ui/components/verticalvideo/controlbar.d.ts +2 -2
  141. package/lib/ui/components/verticalvideo/controlbar.js +4 -4
  142. package/lib/ui/handlers/playnextscreen.test.d.ts +1 -0
  143. package/lib/ui/handlers/timecontrolhandlers.d.ts +3 -3
  144. package/lib/ui/nativemobileuifactory.js +20 -24
  145. package/lib/ui/nativemobileuifactory.test.js +2 -6
  146. package/lib/ui/uicontainer.d.ts +2 -3
  147. package/lib/ui/uicontainer.js +13 -30
  148. package/lib/ui/uicontainer.test.d.ts +1 -0
  149. package/lib/ui/uicontainer.test.js +80 -0
  150. package/package.json +3 -3
  151. package/src/style/components/_advert.scss +0 -9
  152. package/src/style/components/_icons.scss +5 -0
  153. package/src/style/components/_nicam.scss +5 -4
  154. package/src/style/components/_settingspanel.scss +48 -17
  155. package/src/style/components/vertical-video/_settingspanel.scss +1 -1
  156. package/src/style/npoplayer.css +26 -20
  157. package/src/style/variants/_player-base.scss +4 -0
  158. package/src/style/variants/_player-large.scss +5 -1
  159. package/src/style/variants/_player-small.scss +11 -8
  160. package/lib/src/ui/handlers/nicamhandler.d.ts +0 -6
  161. package/lib/src/ui/handlers/streamhandler.d.ts +0 -2
  162. package/lib/ui/handlers/nicamhandler.d.ts +0 -6
  163. package/lib/ui/handlers/nicamhandler.test.js +0 -36
  164. package/lib/ui/handlers/streamhandler.d.ts +0 -2
  165. package/lib/ui/handlers/streamhandler.js +0 -60
  166. /package/lib/{src/ui/handlers/playnextstreen.test.d.ts → js/playeractions/handlers/processplayerconfig.test.d.ts} +0 -0
  167. /package/lib/{ui/handlers/playnextstreen.test.d.ts → js/playeractions/handlers/processsourceconfig.test.d.ts} +0 -0
  168. /package/lib/{src/ui/handlers → services/nicamHandlers}/nicamhandler.test.d.ts +0 -0
  169. /package/lib/{ui/handlers/nicamhandler.test.d.ts → services/streamoptionsHandlers/streamOptionsHandler.test.d.ts} +0 -0
  170. /package/lib/ui/handlers/{playnextstreen.test.js → playnextscreen.test.js} +0 -0
@@ -1,43 +1,31 @@
1
- import { ControlBar, Container, SeekBar, SeekBarLabel, PlaybackToggleButton, VolumeToggleButton, VolumeSlider, Spacer, PictureInPictureToggleButton, AirPlayToggleButton, CastToggleButton, SettingsToggleButton, FullscreenToggleButton } from 'bitmovin-player-ui';
2
- import { PlayerEvent } from 'bitmovin-player';
3
- import { createForwardButton, createRewindButton } from './buttons';
1
+ import { ControlBar, Container, SeekBar, SeekBarLabel, PlaybackToggleButton, VolumeToggleButton, VolumeSlider, Spacer, PictureInPictureToggleButton, AirPlayToggleButton, SettingsToggleButton, FullscreenToggleButton } from 'bitmovin-player-ui';
2
+ import { createChromecastButton, createForwardButton, createRewindButton } from './buttons';
4
3
  import { createSeekBar } from './seekbar';
5
4
  import { createSettingsPanel } from './settingspanel';
6
- export function createControlBar(npoPlayer) {
7
- const player = npoPlayer.player;
8
- const rewindButton = createRewindButton(player);
9
- const forwardButton = createForwardButton(player);
5
+ import { NpoPlayerUIVariants } from '../../types/interfaces';
6
+ export function createControlBar(playerContext, variant) {
7
+ const { npoPlayer, player } = playerContext;
10
8
  const seekBar = new SeekBar({ label: new SeekBarLabel() });
11
9
  npoPlayer.uiComponents.seekBar = seekBar;
12
- const chromeCastButton = new CastToggleButton({
13
- hidden: true
14
- });
15
- const handleCastAvailable = () => {
16
- player?.off(PlayerEvent.CastAvailable, handleCastAvailable);
17
- if (player?.isCastAvailable()) {
18
- chromeCastButton.show();
19
- }
20
- };
21
- player?.on(PlayerEvent.CastAvailable, handleCastAvailable);
22
- const settingsPanel = createSettingsPanel(npoPlayer);
10
+ const controlComponents = [];
11
+ controlComponents.push(new PlaybackToggleButton(), new VolumeToggleButton(), new VolumeSlider());
12
+ if (variant === NpoPlayerUIVariants.DEFAULT) {
13
+ const rewindButton = createRewindButton(playerContext);
14
+ const forwardButton = createForwardButton(playerContext);
15
+ controlComponents.push(rewindButton, forwardButton);
16
+ }
17
+ const chromeCastButton = createChromecastButton(player, npoPlayer);
18
+ controlComponents.push(new Spacer(), new PictureInPictureToggleButton(), new AirPlayToggleButton(), chromeCastButton);
19
+ if (variant === NpoPlayerUIVariants.DEFAULT) {
20
+ const settingsPanel = createSettingsPanel(npoPlayer);
21
+ controlComponents.push(new SettingsToggleButton({ settingsPanel }), settingsPanel);
22
+ }
23
+ controlComponents.push(new FullscreenToggleButton());
23
24
  const controlBar = new ControlBar({
24
25
  components: [
25
26
  createSeekBar(npoPlayer),
26
27
  new Container({
27
- components: [
28
- new PlaybackToggleButton(),
29
- new VolumeToggleButton(),
30
- new VolumeSlider(),
31
- rewindButton,
32
- forwardButton,
33
- new Spacer(),
34
- new PictureInPictureToggleButton(),
35
- new AirPlayToggleButton(),
36
- chromeCastButton,
37
- new SettingsToggleButton({ settingsPanel }),
38
- settingsPanel,
39
- new FullscreenToggleButton()
40
- ],
28
+ components: [...controlComponents],
41
29
  cssClasses: ['controlbar-bottom']
42
30
  })
43
31
  ],
@@ -4,7 +4,7 @@ import { type PlayerAPI } from 'bitmovin-player';
4
4
  import { ButtonConfig } from 'bitmovin-player-ui/dist/js/framework/components/button';
5
5
  import { LabelConfig } from 'bitmovin-player-ui/dist/js/framework/components/label';
6
6
  import { NpoPlayerUIVariants } from '../../types/interfaces';
7
- export declare function createCTABar(player: PlayerAPI, npoplayer: NpoPlayer, variant: NpoPlayerUIVariants): Container<{
7
+ export declare function createCTABar(player: PlayerAPI, npoPlayer: NpoPlayer, variant: NpoPlayerUIVariants): Container<{
8
8
  components: (Button<ButtonConfig> | Label<LabelConfig>)[];
9
9
  cssClasses: string[];
10
10
  }>;
@@ -3,16 +3,16 @@ import { createGoBackLiveButton, createWatchFromStartButton } from './buttons';
3
3
  import { createAdButton } from './adbutton';
4
4
  import { createAdLabel } from './adlabel';
5
5
  import { NpoPlayerUIVariants } from '../../types/interfaces';
6
- export function createCTABar(player, npoplayer, variant) {
6
+ export function createCTABar(player, npoPlayer, variant) {
7
7
  const barComponents = [];
8
8
  if (variant === NpoPlayerUIVariants.DEFAULT) {
9
9
  const goBackLiveButton = createGoBackLiveButton(player);
10
- const watchFromStartButton = createWatchFromStartButton(player, npoplayer);
10
+ const watchFromStartButton = createWatchFromStartButton(player, npoPlayer);
11
11
  barComponents.push(watchFromStartButton, goBackLiveButton);
12
12
  }
13
13
  if (variant === NpoPlayerUIVariants.AD) {
14
- const adLabel = createAdLabel(npoplayer);
15
- const adButton = createAdButton(npoplayer);
14
+ const adLabel = createAdLabel(npoPlayer);
15
+ const adButton = createAdButton(npoPlayer);
16
16
  barComponents.push(adLabel, adButton);
17
17
  adLabel.hide();
18
18
  }
@@ -1,5 +1,13 @@
1
1
  import { AirPlayToggleButton, Button, CastToggleButton, ControlBar, FullscreenToggleButton, PictureInPictureToggleButton, PlaybackToggleButton, SettingsPanel, SettingsToggleButton, VolumeToggleButton } from 'bitmovin-player-ui';
2
2
  import { PlayerAPI } from 'bitmovin-player';
3
+ export declare function createForwardButton(player: PlayerAPI | undefined): Button<{
4
+ cssClass: string;
5
+ ariaLabel: string;
6
+ }>;
7
+ export declare function createRewindButton(player: PlayerAPI | undefined): Button<{
8
+ cssClass: string;
9
+ ariaLabel: string;
10
+ }>;
3
11
  export declare function createMiddleButtons(player: PlayerAPI): ControlBar;
4
12
  export declare function createWatchFromStartButton(): Button<{
5
13
  cssClass: string;
@@ -2,7 +2,23 @@ import { AirPlayToggleButton, Button, CastToggleButton, ControlBar, FullscreenTo
2
2
  import { sendCustomMessage } from '../../nativemobileuicontainer';
3
3
  import { CustomMessages } from '../../../types/interfaces';
4
4
  import { ViewMode } from 'bitmovin-player';
5
- import { createForwardButton, createRewindButton } from '../buttons';
5
+ const interval = 10;
6
+ function rewind(player) {
7
+ if (player.isLive()) {
8
+ player.timeShift(player.getTimeShift() - interval);
9
+ }
10
+ else {
11
+ player.seek(Math.max(0, player.getCurrentTime() - interval));
12
+ }
13
+ }
14
+ function forward(player) {
15
+ if (player.isLive()) {
16
+ player.timeShift(Math.min(0, player.getTimeShift() + interval));
17
+ }
18
+ else {
19
+ player.seek(Math.min(player.getDuration(), player.getCurrentTime() + interval));
20
+ }
21
+ }
6
22
  const watchFromStartButtonClickHandler = () => {
7
23
  sendCustomMessage(CustomMessages.CLICK_WATCH_FROM_START);
8
24
  };
@@ -23,6 +39,30 @@ function createBigPlayToggleButton() {
23
39
  });
24
40
  return bigPlayToggleButton;
25
41
  }
42
+ export function createForwardButton(player) {
43
+ const forwardButton = new Button({
44
+ cssClass: 'ui-forwardbutton bmpui-ui-button',
45
+ ariaLabel: 'Spoel 10 seconden vooruit'
46
+ });
47
+ if (player) {
48
+ forwardButton.onClick.subscribe(() => {
49
+ forward(player);
50
+ });
51
+ }
52
+ return forwardButton;
53
+ }
54
+ export function createRewindButton(player) {
55
+ const rewindButton = new Button({
56
+ cssClass: 'ui-rewindbutton bmpui-ui-button',
57
+ ariaLabel: 'Spoel 10 seconden terug'
58
+ });
59
+ if (player) {
60
+ rewindButton.onClick.subscribe(() => {
61
+ rewind(player);
62
+ });
63
+ }
64
+ return rewindButton;
65
+ }
26
66
  export function createMiddleButtons(player) {
27
67
  const bigPlayToggleButton = createBigPlayToggleButton();
28
68
  const bigRewindButton = createRewindButton(player);
@@ -1,6 +1,5 @@
1
1
  import { ControlBar, Container, PlaybackTimeLabel, PlaybackTimeLabelMode, SeekBar, SeekBarLabel, Spacer } from 'bitmovin-player-ui';
2
- import { createForwardButton, createRewindButton } from '../buttons';
3
- import { createAirPlayToggleButton, createCastToggleButton, createFullscreenToggleButton, createPictureInPictureToggleButton, createPlaybackToggleButton, createSettingsButton, createVolumeToggleButton } from './buttons';
2
+ import { createForwardButton, createRewindButton, createAirPlayToggleButton, createCastToggleButton, createFullscreenToggleButton, createPictureInPictureToggleButton, createPlaybackToggleButton, createSettingsButton, createVolumeToggleButton } from './buttons';
4
3
  import { createSettingsPanel } from '../settingspanel';
5
4
  export function createControlBar(player) {
6
5
  const rewindButton = createRewindButton(player);
@@ -12,8 +12,8 @@ export function createTopBar(player) {
12
12
  createSettingsButton(settingsPanel),
13
13
  settingsPanel,
14
14
  createPictureInPictureToggleButton(player),
15
- createFullscreenToggleButton(player),
16
- createVolumeToggleButton(player)
15
+ createVolumeToggleButton(player),
16
+ createFullscreenToggleButton(player)
17
17
  ],
18
18
  cssClasses: ['controlbar-top', 'controlbar-small']
19
19
  })
@@ -1,12 +1,10 @@
1
1
  import { Container } from 'bitmovin-player-ui';
2
2
  import { type PlayerAPI } from 'bitmovin-player';
3
3
  import type NpoPlayer from '../../npoplayer';
4
- export declare function createPlayNextScreen(player: PlayerAPI, npoplayer: NpoPlayer): Container<{
4
+ export declare function createPlayNextScreen(player: PlayerAPI, npoPlayer: NpoPlayer): Container<{
5
5
  components: import("bitmovin-player-ui").Button<{
6
6
  cssClass: string;
7
- text: string;
8
7
  ariaLabel: string;
9
- hidden: false;
10
8
  }>[];
11
9
  cssClasses: string[];
12
10
  }>;
@@ -1,8 +1,8 @@
1
1
  import { Container } from 'bitmovin-player-ui';
2
2
  import { createPlayNextButton, createCancelPlayNextButton } from './buttons';
3
- export function createPlayNextScreen(player, npoplayer) {
4
- const playNextButton = createPlayNextButton(player, npoplayer);
5
- const cancelButton = createCancelPlayNextButton(player, npoplayer);
3
+ export function createPlayNextScreen(player, npoPlayer) {
4
+ const playNextButton = createPlayNextButton(player, npoPlayer);
5
+ const cancelButton = createCancelPlayNextButton(player, npoPlayer);
6
6
  return new Container({
7
7
  components: [cancelButton, playNextButton],
8
8
  cssClasses: ['overlay-playnext']
@@ -1,6 +1,6 @@
1
1
  import { Container, PlaybackTimeLabel, SeekBar } from 'bitmovin-player-ui';
2
2
  import type NpoPlayer from '../../npoplayer';
3
- export declare function createSeekBar(npoplayer: NpoPlayer): Container<{
3
+ export declare function createSeekBar(npoPlayer: NpoPlayer): Container<{
4
4
  components: (SeekBar | PlaybackTimeLabel)[];
5
5
  cssClasses: string[];
6
6
  }>;
@@ -1,7 +1,9 @@
1
1
  import { Container, PlaybackTimeLabel, PlaybackTimeLabelMode, SeekBar, SeekBarLabel } from 'bitmovin-player-ui';
2
- export function createSeekBar(npoplayer) {
2
+ import { NpoPlayerUIVariants } from '../../npoplayer';
3
+ export function createSeekBar(npoPlayer) {
3
4
  const seekBar = new SeekBar({ label: new SeekBarLabel() });
4
- npoplayer.uiComponents.seekBar = seekBar;
5
+ npoPlayer.uiComponents.seekBar = seekBar;
6
+ const isAdUi = npoPlayer.variant === NpoPlayerUIVariants.AD || false;
5
7
  return new Container({
6
8
  components: [
7
9
  new PlaybackTimeLabel({
@@ -11,7 +13,7 @@ export function createSeekBar(npoplayer) {
11
13
  }),
12
14
  seekBar,
13
15
  new PlaybackTimeLabel({
14
- timeLabelMode: PlaybackTimeLabelMode.TotalTime,
16
+ timeLabelMode: isAdUi ? PlaybackTimeLabelMode.RemainingTime : PlaybackTimeLabelMode.TotalTime,
15
17
  cssClasses: ['total-time']
16
18
  })
17
19
  ],
@@ -49,11 +49,6 @@ export function createSettingsPanel(npoPlayer) {
49
49
  new SettingsPanelItem(audioqualityLabel, new AudioQualitySelectBox()),
50
50
  new SettingsPanelItem(audiotrackLabel, new AudioTrackSelectBox())
51
51
  ], ['main-panel']);
52
- const onSourceLoaded = () => {
53
- player?.off(PlayerEvent.SourceLoaded, onSourceLoaded);
54
- checkQualities();
55
- checkSubtitles();
56
- };
57
52
  const settingsPanel = new SettingsPanel({
58
53
  components: [mainSettingsPage, subtitlePanelPage, speedPanelPage, qualityPanelPage],
59
54
  hidden: true,
@@ -84,7 +79,6 @@ export function createSettingsPanel(npoPlayer) {
84
79
  panelPage.addComponent(createSettingsPanelPageBackButton(mainSettingsPage, settingsPanel, labels[index], [
85
80
  settingsBackButtonClass
86
81
  ]));
87
- panelPage.addComponent(new SettingsToggleButton({ settingsPanel }));
88
82
  }
89
83
  if ('uiComponents' in npoPlayer) {
90
84
  npoPlayer.uiComponents.subtitlesButton = subtitlesPanelItem;
@@ -113,8 +107,7 @@ export function createSettingsPanel(npoPlayer) {
113
107
  }
114
108
  };
115
109
  const checkQualities = () => {
116
- const availableVideoQualities = player?.getAvailableVideoQualities();
117
- qualityListBox.clearItems();
110
+ const availableVideoQualities = player?.getAvailableVideoQualities() || [];
118
111
  if (availableVideoQualities?.length) {
119
112
  for (const quality of availableVideoQualities)
120
113
  qualityListBox.addItem(quality.id, quality.label ?? 'test');
@@ -126,12 +119,19 @@ export function createSettingsPanel(npoPlayer) {
126
119
  qualityPanelItem.hide();
127
120
  }
128
121
  };
129
- player?.on(PlayerEvent.SourceLoaded, onSourceLoaded);
130
122
  settingsPanel.onHide.subscribe(() => {
131
123
  player?.getContainer().querySelector('.bmpui-npo-player')?.classList.remove('bmpui-settings-panel-shown');
132
124
  });
133
125
  settingsPanel.onShow.subscribe(() => {
134
126
  player?.getContainer().querySelector('.bmpui-npo-player')?.classList.add('bmpui-settings-panel-shown');
135
127
  });
128
+ const onSourceLoaded = () => {
129
+ player?.off(PlayerEvent.SourceLoaded, onSourceLoaded);
130
+ player?.off(PlayerEvent.Ready, onSourceLoaded);
131
+ checkQualities();
132
+ checkSubtitles();
133
+ };
134
+ player?.on(PlayerEvent.SourceLoaded, onSourceLoaded);
135
+ player?.on(PlayerEvent.Ready, onSourceLoaded);
136
136
  return settingsPanel;
137
137
  }
@@ -1,3 +1,3 @@
1
1
  import { TitleBar } from 'bitmovin-player-ui';
2
2
  import type NpoPlayer from '../../npoplayer';
3
- export declare function createTitleBar(npoplayer: NpoPlayer): TitleBar;
3
+ export declare function createTitleBar(npoPlayer: NpoPlayer): TitleBar;
@@ -1,8 +1,8 @@
1
1
  import { Label, TitleBar } from 'bitmovin-player-ui';
2
- export function createTitleBar(npoplayer) {
2
+ export function createTitleBar(npoPlayer) {
3
3
  const nicam = new Label({ text: '', cssClass: 'nicam' });
4
4
  const titleBar = new TitleBar({ cssClasses: ['metadata'] });
5
5
  titleBar.addComponent(nicam);
6
- npoplayer.uiComponents.nicam = nicam;
6
+ npoPlayer.uiComponents.nicam = nicam;
7
7
  return titleBar;
8
8
  }
@@ -1,3 +1,3 @@
1
1
  import { TitleBar } from 'bitmovin-player-ui';
2
- import NpoPlayer from 'npoplayer';
3
- export declare function createTopBar(npoplayer: NpoPlayer): TitleBar;
2
+ import { PlayerContext } from '../../types/interfaces';
3
+ export declare function createTopBar(playerContext: PlayerContext): TitleBar;
@@ -1,19 +1,10 @@
1
- import { PlayerEvent } from 'bitmovin-player';
2
- import { Container, TitleBar, PictureInPictureToggleButton, AirPlayToggleButton, CastToggleButton, SettingsToggleButton, FullscreenToggleButton, VolumeControlButton } from 'bitmovin-player-ui';
1
+ import { Container, TitleBar, PictureInPictureToggleButton, AirPlayToggleButton, SettingsToggleButton, FullscreenToggleButton, VolumeControlButton } from 'bitmovin-player-ui';
3
2
  import { createSettingsPanel } from './settingspanel';
4
- export function createTopBar(npoplayer) {
5
- const player = npoplayer.player;
6
- const chromeCastButton = new CastToggleButton({
7
- hidden: true
8
- });
9
- const handleCastAvailable = () => {
10
- player?.off(PlayerEvent.CastAvailable, handleCastAvailable);
11
- if (player?.isCastAvailable()) {
12
- chromeCastButton.show();
13
- }
14
- };
15
- player?.on(PlayerEvent.CastAvailable, handleCastAvailable);
16
- const settingsPanel = createSettingsPanel(npoplayer);
3
+ import { createChromecastButton } from './buttons';
4
+ export function createTopBar(playerContext) {
5
+ const { npoPlayer, player } = playerContext;
6
+ const settingsPanel = createSettingsPanel(npoPlayer);
7
+ const chromeCastButton = createChromecastButton(player, npoPlayer);
17
8
  return new TitleBar({
18
9
  components: [
19
10
  new Container({
@@ -23,10 +14,10 @@ export function createTopBar(npoplayer) {
23
14
  chromeCastButton,
24
15
  new SettingsToggleButton({ settingsPanel }),
25
16
  settingsPanel,
26
- new FullscreenToggleButton(),
27
17
  new VolumeControlButton({
28
18
  vertical: true
29
- })
19
+ }),
20
+ new FullscreenToggleButton()
30
21
  ],
31
22
  cssClasses: ['controlbar-top', 'controlbar-small']
32
23
  })
@@ -1,3 +1,3 @@
1
1
  import { ControlBar } from 'bitmovin-player-ui';
2
- import type NpoPlayer from '../../../npoplayer';
3
- export declare function createVerticalVideoControlBar(npoPlayer: NpoPlayer): ControlBar;
2
+ import { PlayerContext } from 'types/interfaces';
3
+ export declare function createVerticalVideoControlBar(playerContext: PlayerContext): ControlBar;
@@ -2,10 +2,10 @@ import { ControlBar, Container, SeekBar, SeekBarLabel, PlaybackToggleButton, Set
2
2
  import { createForwardButton, createRewindButton } from '../buttons';
3
3
  import { createSeekBar } from '../seekbar';
4
4
  import { createSettingsPanel } from '../settingspanel';
5
- export function createVerticalVideoControlBar(npoPlayer) {
6
- const player = npoPlayer.player;
7
- const rewindButton = createRewindButton(player);
8
- const forwardButton = createForwardButton(player);
5
+ export function createVerticalVideoControlBar(playerContext) {
6
+ const { npoPlayer } = playerContext;
7
+ const rewindButton = createRewindButton(playerContext);
8
+ const forwardButton = createForwardButton(playerContext);
9
9
  const seekBar = new SeekBar({ label: new SeekBarLabel() });
10
10
  npoPlayer.uiComponents.seekBar = seekBar;
11
11
  const settingsPanel = createSettingsPanel(npoPlayer);
@@ -0,0 +1 @@
1
+ export {};
@@ -1,3 +1,3 @@
1
- import { type PlayerAPI } from 'bitmovin-player';
2
- export declare function rewind(player: PlayerAPI): void;
3
- export declare function forward(player: PlayerAPI): void;
1
+ import { NpoPlayerAPI } from '../../services/npoPlayerAPI/npoPlayerAPI';
2
+ export declare function rewind(player: NpoPlayerAPI): void;
3
+ export declare function forward(player: NpoPlayerAPI): void;
@@ -4,13 +4,14 @@ import { customSpecificErrorMessageOverlayConfig } from '../js/playeractions/han
4
4
  import { localizationConfig } from '../js/settings/localization';
5
5
  import { nativeMobileUIContainer, sendCustomMessage } from './nativemobileuicontainer';
6
6
  import { CustomMessages } from '../types/interfaces';
7
- import { processNicam } from './handlers/nicamhandler';
8
- import { getElementByQuery, removeClassFromElementByQuery } from '../js/utilities/utilities.element';
7
+ import { getElementByQuery } from '../js/utilities/utilities.element';
9
8
  import { handleLiveStreamNoDvr } from './handlers/domhandlers';
10
9
  import { removeReplayClass } from '../js/playeractions/handlers/removereplayclass';
10
+ import { processNicam } from '../services/nicamHandlers/nicamhandler';
11
11
  let adBreakActive = false;
12
12
  export function nativeMobileUiFactory(player, config = {}) {
13
13
  UIManager.setLocalizationConfig(localizationConfig);
14
+ const nicamClass = '.bmpui-nicam';
14
15
  const uiConfig = {
15
16
  ...config,
16
17
  errorMessages: customSpecificErrorMessageOverlayConfig,
@@ -22,25 +23,7 @@ export function nativeMobileUiFactory(player, config = {}) {
22
23
  player.off(PlayerEvent.Seek, removeFinishedClass);
23
24
  removeReplayClass(player);
24
25
  };
25
- const clearUI = () => {
26
- adBreakActive = false;
27
- const nicamElement = getElementByQuery({ container: player.getContainer(), query: '.bmpui-nicam' });
28
- if (nicamElement)
29
- nicamElement.innerHTML = '';
30
- const seekbarTitleElement = getElementByQuery({
31
- container: player.getContainer(),
32
- query: '.bmpui-seekbar-label-title'
33
- });
34
- if (seekbarTitleElement)
35
- seekbarTitleElement.textContent = '';
36
- removeClassFromElementByQuery({
37
- className: 'livestream-no-dvr',
38
- container: player.getContainer(),
39
- query: '.bmpui-npo-player'
40
- });
41
- };
42
26
  const updateUI = () => {
43
- const nicamElement = getElementByQuery({ container: player.getContainer(), query: '.bmpui-nicam' });
44
27
  const seekbarTitleElement = getElementByQuery({
45
28
  container: player.getContainer(),
46
29
  query: '.bmpui-seekbar-label-title'
@@ -51,7 +34,18 @@ export function nativeMobileUiFactory(player, config = {}) {
51
34
  player.on(PlayerEvent.AdError, setAdBreakActiveToFalse);
52
35
  }
53
36
  if (_webData.metadata?.ageRating || _webData.metadata?.nicam) {
54
- processNicam(_webData, nicamElement, undefined);
37
+ const webDataPlayerContext = {
38
+ npoPlayer: {
39
+ streamObject: {
40
+ metadata: {
41
+ ageRating: _webData.metadata.ageRating,
42
+ nicam: _webData.metadata.nicam
43
+ }
44
+ }
45
+ }
46
+ };
47
+ const nicamElement = getElementByQuery({ container: player.getContainer(), query: nicamClass });
48
+ processNicam(webDataPlayerContext, nicamElement);
55
49
  }
56
50
  if (seekbarTitleElement)
57
51
  seekbarTitleElement.textContent = _webData.title || '';
@@ -64,10 +58,12 @@ export function nativeMobileUiFactory(player, config = {}) {
64
58
  };
65
59
  if (window.bitmovin?.customMessageHandler) {
66
60
  const handleData = (data) => {
67
- clearUI();
68
61
  if (data) {
69
- _webData = JSON.parse(data);
70
- updateUI();
62
+ const newData = JSON.parse(data);
63
+ if (data !== _webData.toString()) {
64
+ _webData = newData;
65
+ updateUI();
66
+ }
71
67
  }
72
68
  };
73
69
  window.bitmovin.customMessageHandler.on(CustomMessages.SET_STREAM_LINK, handleData);
@@ -24,7 +24,8 @@ describe('nativeMobileUiFactory', () => {
24
24
  on: jest.fn(),
25
25
  off: jest.fn(),
26
26
  getContainer: () => containerElement,
27
- getVolume: jest.fn().mockReturnValue(50)
27
+ getVolume: jest.fn().mockReturnValue(50),
28
+ getAvailableVideoQualities: jest.fn()
28
29
  };
29
30
  storedCallbacks = {};
30
31
  if (storedCallbacks) {
@@ -41,10 +42,6 @@ describe('nativeMobileUiFactory', () => {
41
42
  test('should update the DOM correctly when sendSynchronous is called with setstreamlink', () => {
42
43
  const mockData = {
43
44
  title: title,
44
- metadata: {
45
- ageRating: '12',
46
- nicam: ['GEWELD', 'ANGST', 'GROF_TAALGEBRUIK']
47
- },
48
45
  stream: {
49
46
  isLiveStream: true,
50
47
  hasDvrWindow: false
@@ -57,7 +54,6 @@ describe('nativeMobileUiFactory', () => {
57
54
  storedCallbacks[CustomMessages.SET_STREAM_LINK](JSON.stringify(mockData));
58
55
  }
59
56
  const container = mockPlayer.getContainer();
60
- expect(container.querySelector('.bmpui-nicam')?.innerHTML).not.toBe('');
61
57
  expect(container.querySelector('.bmpui-seekbar-label-title')?.textContent).toBe(title);
62
58
  expect(container.querySelector('.bmpui-npo-player')?.classList.contains('livestream-no-dvr')).toBeTruthy();
63
59
  });
@@ -1,5 +1,4 @@
1
- import NpoPlayer from '../npoplayer';
2
1
  import { UIContainer } from 'bitmovin-player-ui';
3
2
  import { PlayerAPI } from 'bitmovin-player';
4
- import { NpoPlayerUIVariants } from '../types/interfaces';
5
- export declare function createUIContainer(npoPlayer: NpoPlayer, player: PlayerAPI, variant: NpoPlayerUIVariants, container: HTMLElement): UIContainer;
3
+ import { NpoPlayerUIVariants, PlayerContext } from '../types/interfaces';
4
+ export declare function createUIContainer(playerContext: PlayerContext, player: PlayerAPI, variant: NpoPlayerUIVariants): UIContainer;
@@ -1,7 +1,6 @@
1
1
  import { UIContainer, PlaybackToggleOverlay, BufferingOverlay, CastStatusOverlay, SubtitleOverlay, ErrorMessageOverlay, UIManager, PlaybackToggleButton, PlayerUtils } from 'bitmovin-player-ui';
2
2
  import { createMiddleButtons } from './components/buttons';
3
3
  import { createPlayNextScreen } from './components/playnext';
4
- import { createSettingsPanel } from './components/settingspanel';
5
4
  import { createCTABar } from './components/ctabar';
6
5
  import { createTopBar } from './components/topbar';
7
6
  import { createControlBar } from './components/controlbar';
@@ -12,69 +11,53 @@ import { localizationConfig } from '../js/settings/localization';
12
11
  import { NpoPlayerUIVariants } from '../types/interfaces';
13
12
  import { createVerticalVideoControlBar } from './components/verticalvideo/controlbar';
14
13
  import { DEFAULT_UI_DELAY, PREVENT_UI_DELAY } from '../services/npoPlayerAPI/contants';
15
- export function createUIContainer(npoPlayer, player, variant, container) {
14
+ export function createUIContainer(playerContext, player, variant) {
16
15
  const cssClassArray = ['npo-player'];
16
+ const hidePlayerStateExceptions = [PlayerUtils.PlayerState.Paused, PlayerUtils.PlayerState.Prepared];
17
+ const { npoPlayer } = playerContext;
18
+ const container = npoPlayer.container;
17
19
  let uiDelay = DEFAULT_UI_DELAY;
18
20
  container.dataset.npoPlayerVersion = npoPlayer.version;
19
21
  container.classList.remove('bitmovinplayer-audio-container');
22
+ const components = [];
20
23
  switch (variant) {
21
24
  case NpoPlayerUIVariants.DEFAULT: {
22
25
  uiDelay = DEFAULT_UI_DELAY;
26
+ components.push(new SubtitleOverlay(), new BufferingOverlay(), new PlaybackToggleOverlay(), new CastStatusOverlay(), createMiddleButtons(playerContext), createPlayNextScreen(player, npoPlayer), createControlBar(playerContext, variant), createCTABar(player, npoPlayer, variant), createTitleBar(npoPlayer), createTopBar(playerContext));
23
27
  break;
24
28
  }
25
29
  case NpoPlayerUIVariants.AD: {
26
30
  uiDelay = PREVENT_UI_DELAY;
27
31
  cssClassArray.push('ster-ad');
32
+ hidePlayerStateExceptions.push(PlayerUtils.PlayerState.Playing);
33
+ components.push(new PlaybackToggleOverlay(), new CastStatusOverlay(), createControlBar(playerContext, variant), createCTABar(player, npoPlayer, variant));
28
34
  break;
29
35
  }
30
36
  case NpoPlayerUIVariants.AUDIO: {
31
37
  uiDelay = PREVENT_UI_DELAY;
32
38
  container.classList.add('bitmovinplayer-audio-container');
33
39
  cssClassArray.push('audio');
40
+ components.push(new PlaybackToggleButton(), createAudioControlBar(npoPlayer), createTitleBar(npoPlayer));
34
41
  break;
35
42
  }
36
43
  case NpoPlayerUIVariants.VERTICAL: {
37
44
  uiDelay = DEFAULT_UI_DELAY;
38
45
  cssClassArray.push('vertical-video');
39
46
  npoPlayer.player?.setAspectRatio('9:16');
47
+ components.push(new SubtitleOverlay(), new BufferingOverlay(), createVerticalVideoControlBar(playerContext), createTitleBar(npoPlayer));
40
48
  break;
41
49
  }
42
50
  }
43
- const middleButtons = createMiddleButtons(player);
44
- const playNextScreen = createPlayNextScreen(player, npoPlayer);
45
- const settingsPanel = createSettingsPanel(npoPlayer);
46
- const ctaBar = createCTABar(player, npoPlayer, variant);
47
- const topBar = createTopBar(npoPlayer);
48
- const controlBar = createControlBar(npoPlayer);
49
- const titleBar = createTitleBar(npoPlayer);
50
- const playbackToggleOverlay = new PlaybackToggleOverlay();
51
- const audioControlbar = createAudioControlBar(npoPlayer);
52
- const bufferingOverlay = new BufferingOverlay();
53
- const verticalVideoControlBar = createVerticalVideoControlBar(npoPlayer);
54
51
  const errorMessageOverlay = new ErrorMessageOverlay();
55
- const castStatusOverlay = new CastStatusOverlay();
56
52
  npoPlayer.uiComponents.errorMessageOverlay = errorMessageOverlay;
57
- const defaultVideoComponents = [settingsPanel, new SubtitleOverlay(), bufferingOverlay, playbackToggleOverlay];
58
- const components = [];
59
- if (variant === NpoPlayerUIVariants.DEFAULT) {
60
- components.push(...defaultVideoComponents, castStatusOverlay, middleButtons, playNextScreen, controlBar, ctaBar, titleBar, topBar);
61
- }
62
- if (variant === NpoPlayerUIVariants.VERTICAL) {
63
- components.push(...defaultVideoComponents, verticalVideoControlBar, titleBar);
64
- }
65
- if (variant === NpoPlayerUIVariants.AUDIO) {
66
- components.push(new PlaybackToggleButton(), audioControlbar, titleBar);
67
- }
68
- if (variant === NpoPlayerUIVariants.AD) {
69
- components.push(...defaultVideoComponents, castStatusOverlay, middleButtons, controlBar, ctaBar);
70
- }
53
+ components.push(errorMessageOverlay);
71
54
  UIManager.setLocalizationConfig(localizationConfig);
72
55
  const ariaLabelKey = variant === NpoPlayerUIVariants.AUDIO ? 'audioPlayer' : 'videoPlayer';
73
56
  return new UIContainer({
74
- components: [...components, errorMessageOverlay],
57
+ components,
75
58
  cssClasses: cssClassArray,
76
59
  ariaLabel: localizeKey(ariaLabelKey),
77
60
  hideDelay: uiDelay,
78
- hidePlayerStateExceptions: [PlayerUtils.PlayerState.Paused]
61
+ hidePlayerStateExceptions
79
62
  });
80
63
  }
@@ -0,0 +1 @@
1
+ import '@testing-library/jest-dom';