@npo/player 1.25.0 → 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 (127) 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 +12 -12
  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 +4 -4
  9. package/lib/js/playeractions/handlers/processsourceconfig.d.ts +1 -0
  10. package/lib/js/playeractions/handlers/processsourceconfig.js +4 -5
  11. package/lib/js/playeractions/handlers/processsourceconfig.test.js +25 -0
  12. package/lib/js/tracking/handlers/playertrackerstart.js +1 -1
  13. package/lib/lang/nl.json +1 -1
  14. package/lib/lang/subtitleLabels/nl.json +14 -0
  15. package/lib/npoplayer.d.ts +2 -3
  16. package/lib/npoplayer.js +24 -32
  17. package/lib/npoplayer.test.js +1 -1
  18. package/lib/package.json +2 -2
  19. package/lib/services/a11y/setup.js +2 -5
  20. package/lib/services/a11y/setup.test.js +2 -19
  21. package/lib/services/advertHandlers/discardAdBreak.js +4 -4
  22. package/lib/services/advertHandlers/discardAdBreak.test.js +25 -13
  23. package/lib/services/advertHandlers/handlePreRolls.js +19 -19
  24. package/lib/services/advertHandlers/handlePrerolls.test.js +4 -4
  25. package/lib/services/drmHandlers/decideprofile.js +1 -1
  26. package/lib/services/drmHandlers/decideprofile.test.js +1 -1
  27. package/lib/services/drmHandlers/verifydrm.js +6 -6
  28. package/lib/services/drmHandlers/verifydrm.test.js +5 -5
  29. package/lib/services/eventListenerHandlers/removeEventListeners.js +2 -2
  30. package/lib/services/eventListenerHandlers/removeEventListeners.test.js +9 -9
  31. package/lib/services/keyboardHandlers/resolvekeypress.js +5 -5
  32. package/lib/services/keyboardHandlers/resolvekeypress.test.js +1 -1
  33. package/lib/services/liveStreamHandlers/handleLiveStreamControls.js +2 -2
  34. package/lib/services/liveStreamHandlers/handleLiveStreamControls.test.js +2 -2
  35. package/lib/services/localStorageHandlers/localStorageHandlers.js +2 -2
  36. package/lib/services/localStorageHandlers/localStorageHandlers.test.js +2 -5
  37. package/lib/services/nicamHandlers/nicamhandler.d.ts +1 -2
  38. package/lib/services/nicamHandlers/nicamhandler.js +17 -16
  39. package/lib/services/nicamHandlers/nicamhandler.test.js +72 -9
  40. package/lib/services/npoPlayerAPI/npoPlayerAPI.d.ts +2 -2
  41. package/lib/services/npoPlayerAPI/npoPlayerAPI.js +16 -23
  42. package/lib/services/preferences/handlePreferences.d.ts +2 -0
  43. package/lib/services/preferences/handlePreferences.js +42 -0
  44. package/lib/services/preferences/handlePreferences.test.js +102 -0
  45. package/lib/services/segmentHandlers/addSegmentEventListeners.js +2 -2
  46. package/lib/services/segmentHandlers/addSegmentEventListeners.test.js +1 -1
  47. package/lib/services/services.d.ts +6 -2
  48. package/lib/services/services.js +21 -2
  49. package/lib/services/streamoptionsHandlers/{steamOptionsHandler.js → streamOptionsHandler.js} +11 -11
  50. package/lib/services/streamoptionsHandlers/streamOptionsHandler.test.js +20 -20
  51. package/lib/services/uiHandlers/uiVisiblityHandler.d.ts +3 -0
  52. package/lib/services/uiHandlers/uiVisiblityHandler.js +26 -0
  53. package/lib/services/uiHandlers/uiVisiblityHandler.test.d.ts +1 -0
  54. package/lib/services/uiHandlers/uiVisiblityHandler.test.js +62 -0
  55. package/lib/src/js/api/getstreamobject.d.ts +1 -1
  56. package/lib/src/js/playeractions/handlers/processplayerconfig.d.ts +1 -1
  57. package/lib/src/js/playeractions/handlers/processsourceconfig.d.ts +1 -0
  58. package/lib/src/js/playeractions/handlers/processsourceconfig.test.d.ts +1 -0
  59. package/lib/src/npoplayer.d.ts +2 -3
  60. package/lib/src/services/nicamHandlers/nicamhandler.d.ts +1 -2
  61. package/lib/src/services/npoPlayerAPI/npoPlayerAPI.d.ts +2 -2
  62. package/lib/src/services/preferences/handlePreferences.d.ts +2 -0
  63. package/lib/src/services/preferences/handlePreferences.test.d.ts +1 -0
  64. package/lib/src/services/services.d.ts +6 -2
  65. package/lib/src/services/uiHandlers/uiVisiblityHandler.d.ts +3 -0
  66. package/lib/src/services/uiHandlers/uiVisiblityHandler.test.d.ts +1 -0
  67. package/lib/src/types/classes.d.ts +6 -0
  68. package/lib/src/types/interfaces.d.ts +24 -3
  69. package/lib/src/ui/components/adbutton.d.ts +1 -1
  70. package/lib/src/ui/components/adlabel.d.ts +1 -1
  71. package/lib/src/ui/components/buttons.d.ts +6 -16
  72. package/lib/src/ui/components/controlbar.d.ts +2 -2
  73. package/lib/src/ui/components/ctabar.d.ts +1 -1
  74. package/lib/src/ui/components/playnext.d.ts +1 -4
  75. package/lib/src/ui/components/seekbar.d.ts +1 -1
  76. package/lib/src/ui/components/titlebar.d.ts +1 -1
  77. package/lib/src/ui/handlers/playnextscreen.test.d.ts +1 -0
  78. package/lib/src/ui/uicontainer.test.d.ts +1 -0
  79. package/lib/tests/mocks/mockLogEmitter.d.ts +2 -0
  80. package/lib/tests/mocks/mockLogEmitter.js +20 -0
  81. package/lib/tests/mocks/mockNpoplayer.js +1 -2
  82. package/lib/tests/mocks/playerContextMock.d.ts +5 -3
  83. package/lib/tests/mocks/playerContextMock.js +7 -5
  84. package/lib/types/classes.d.ts +6 -0
  85. package/lib/types/classes.js +12 -0
  86. package/lib/types/interfaces.d.ts +24 -3
  87. package/lib/types/interfaces.js +1 -0
  88. package/lib/ui/components/adbutton.d.ts +1 -1
  89. package/lib/ui/components/adbutton.js +3 -3
  90. package/lib/ui/components/adlabel.d.ts +1 -1
  91. package/lib/ui/components/adlabel.js +3 -3
  92. package/lib/ui/components/buttons.d.ts +6 -16
  93. package/lib/ui/components/buttons.js +27 -10
  94. package/lib/ui/components/controlbar.d.ts +2 -2
  95. package/lib/ui/components/controlbar.js +20 -37
  96. package/lib/ui/components/ctabar.d.ts +1 -1
  97. package/lib/ui/components/ctabar.js +4 -4
  98. package/lib/ui/components/nativemobile/topbar.js +2 -2
  99. package/lib/ui/components/playnext.d.ts +1 -4
  100. package/lib/ui/components/playnext.js +3 -3
  101. package/lib/ui/components/seekbar.d.ts +1 -1
  102. package/lib/ui/components/seekbar.js +5 -3
  103. package/lib/ui/components/settingspanel.js +9 -9
  104. package/lib/ui/components/titlebar.d.ts +1 -1
  105. package/lib/ui/components/titlebar.js +2 -2
  106. package/lib/ui/components/topbar.js +6 -20
  107. package/lib/ui/components/verticalvideo/controlbar.js +1 -1
  108. package/lib/ui/handlers/playnextscreen.test.d.ts +1 -0
  109. package/lib/ui/nativemobileuifactory.js +1 -1
  110. package/lib/ui/nativemobileuifactory.test.js +2 -1
  111. package/lib/ui/uicontainer.js +11 -30
  112. package/lib/ui/uicontainer.test.d.ts +1 -0
  113. package/lib/ui/uicontainer.test.js +80 -0
  114. package/package.json +2 -2
  115. package/src/style/components/_advert.scss +0 -9
  116. package/src/style/components/_nicam.scss +5 -4
  117. package/src/style/components/_settingspanel.scss +48 -17
  118. package/src/style/components/vertical-video/_settingspanel.scss +1 -1
  119. package/src/style/npoplayer.css +25 -20
  120. package/src/style/variants/_player-base.scss +4 -0
  121. package/src/style/variants/_player-large.scss +5 -1
  122. package/src/style/variants/_player-small.scss +11 -8
  123. /package/lib/{src/ui/handlers/playnextstreen.test.d.ts → js/playeractions/handlers/processsourceconfig.test.d.ts} +0 -0
  124. /package/lib/{ui/handlers/playnextstreen.test.d.ts → services/preferences/handlePreferences.test.d.ts} +0 -0
  125. /package/lib/services/streamoptionsHandlers/{steamOptionsHandler.d.ts → streamOptionsHandler.d.ts} +0 -0
  126. /package/lib/src/services/streamoptionsHandlers/{steamOptionsHandler.d.ts → streamOptionsHandler.d.ts} +0 -0
  127. /package/lib/ui/handlers/{playnextstreen.test.js → playnextscreen.test.js} +0 -0
@@ -1,5 +1,6 @@
1
- import { Button, PlaybackToggleButton, ControlBar } from 'bitmovin-player-ui';
1
+ import { Button, PlaybackToggleButton, ControlBar, CastToggleButton } from 'bitmovin-player-ui';
2
2
  import { rewind, forward } from '../handlers/timecontrolhandlers';
3
+ import { NpoPlayerEvent } from '../../types/events';
3
4
  export function createMiddleButtons(playerContext) {
4
5
  const bigPlayToggleButton = new PlaybackToggleButton({
5
6
  cssClass: 'ui-playbacktogglebutton'
@@ -33,7 +34,7 @@ export function createForwardButton(playerContext) {
33
34
  });
34
35
  return forwardButton;
35
36
  }
36
- export function createPlayNextButton(player, npoplayer) {
37
+ export function createPlayNextButton(player, npoPlayer) {
37
38
  const playNextButton = new Button({
38
39
  cssClass: 'ui-textbutton ui-playNextButton bmpui-ui-button',
39
40
  text: '<span class="bmpui-ui-textbutton-icon bmpui-ui-textbutton-icon-play"></span> Volgende aflevering',
@@ -43,12 +44,12 @@ export function createPlayNextButton(player, npoplayer) {
43
44
  });
44
45
  playNextButton.onClick.subscribe(() => {
45
46
  if (player != undefined) {
46
- npoplayer.doPlayNext();
47
+ npoPlayer.doPlayNext();
47
48
  }
48
49
  });
49
50
  return playNextButton;
50
51
  }
51
- export function createCancelPlayNextButton(player, npoplayer) {
52
+ export function createCancelPlayNextButton(player, npoPlayer) {
52
53
  const cancelPlayNextButton = new Button({
53
54
  cssClass: 'ui-textbutton ui-cancelPlayNextButton bmpui-ui-button',
54
55
  text: 'Annuleer',
@@ -58,7 +59,7 @@ export function createCancelPlayNextButton(player, npoplayer) {
58
59
  });
59
60
  cancelPlayNextButton.onClick.subscribe(() => {
60
61
  if (player != undefined) {
61
- npoplayer.cancelPlayNextScreen();
62
+ npoPlayer.cancelPlayNextScreen();
62
63
  }
63
64
  });
64
65
  return cancelPlayNextButton;
@@ -91,7 +92,7 @@ export function createGoBackLiveButton(player) {
91
92
  });
92
93
  return goBackLiveButton;
93
94
  }
94
- export function createWatchFromStartButton(player, npoplayer) {
95
+ export function createWatchFromStartButton(player, npoPlayer) {
95
96
  const watchFromStartButton = new Button({
96
97
  cssClass: 'ui-textbutton ui-watchfromstartbutton bmpui-ui-button',
97
98
  text: 'Kijk vanaf het begin',
@@ -100,10 +101,26 @@ export function createWatchFromStartButton(player, npoplayer) {
100
101
  });
101
102
  watchFromStartButton.onClick.subscribe(() => {
102
103
  if (player.isLive() ?? false)
103
- npoplayer.watchFromStart();
104
- if (npoplayer.uiComponents.watchFromStartButton)
105
- npoplayer.uiComponents.watchFromStartButton.hide();
104
+ npoPlayer.watchFromStart();
105
+ if (npoPlayer.uiComponents.watchFromStartButton)
106
+ npoPlayer.uiComponents.watchFromStartButton.hide();
106
107
  });
107
- npoplayer.uiComponents.watchFromStartButton = watchFromStartButton;
108
+ npoPlayer.uiComponents.watchFromStartButton = watchFromStartButton;
108
109
  return watchFromStartButton;
109
110
  }
111
+ export function createChromecastButton(player, npoPlayer) {
112
+ const chromeCastButton = new CastToggleButton({
113
+ disabled: true
114
+ });
115
+ const handleCastAvailable = () => {
116
+ const remoteControlConfig = npoPlayer.playerConfig?.remotecontrol;
117
+ if (player?.isCastAvailable() && remoteControlConfig.customReceiverConfig?.enable !== 'false') {
118
+ chromeCastButton.enable();
119
+ }
120
+ else {
121
+ chromeCastButton.disable();
122
+ }
123
+ };
124
+ player?.on(NpoPlayerEvent.CastAvailable, handleCastAvailable);
125
+ return chromeCastButton;
126
+ }
@@ -1,3 +1,3 @@
1
1
  import { ControlBar } from 'bitmovin-player-ui';
2
- import { PlayerContext } from '../../types/interfaces';
3
- export declare function createControlBar(playerContext: PlayerContext): ControlBar;
2
+ import { NpoPlayerUIVariants, PlayerContext } from '../../types/interfaces';
3
+ export declare function createControlBar(playerContext: PlayerContext, variant: NpoPlayerUIVariants): ControlBar;
@@ -1,48 +1,31 @@
1
- import { ControlBar, Container, SeekBar, SeekBarLabel, PlaybackToggleButton, VolumeToggleButton, VolumeSlider, Spacer, PictureInPictureToggleButton, AirPlayToggleButton, CastToggleButton, SettingsToggleButton, FullscreenToggleButton } from 'bitmovin-player-ui';
2
- 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';
3
3
  import { createSeekBar } from './seekbar';
4
4
  import { createSettingsPanel } from './settingspanel';
5
- import { NpoPlayerEvent } from '../../types/events';
6
- export function createControlBar(playerContext) {
7
- const npoPlayer = playerContext.npoplayer;
8
- const player = playerContext.player;
9
- const rewindButton = createRewindButton(playerContext);
10
- const forwardButton = createForwardButton(playerContext);
5
+ import { NpoPlayerUIVariants } from '../../types/interfaces';
6
+ export function createControlBar(playerContext, variant) {
7
+ const { npoPlayer, player } = playerContext;
11
8
  const seekBar = new SeekBar({ label: new SeekBarLabel() });
12
9
  npoPlayer.uiComponents.seekBar = seekBar;
13
- const chromeCastButton = new CastToggleButton({
14
- disabled: true
15
- });
16
- const handleCastAvailable = () => {
17
- player?.off(NpoPlayerEvent.CastAvailable, handleCastAvailable);
18
- const remoteControlConfig = npoPlayer.playerConfig?.remotecontrol;
19
- if (player?.isCastAvailable() && remoteControlConfig.customReceiverConfig?.enable !== 'false') {
20
- chromeCastButton.enable();
21
- }
22
- else {
23
- chromeCastButton.disable();
24
- }
25
- };
26
- player?.on(NpoPlayerEvent.CastAvailable, handleCastAvailable);
27
- 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());
28
24
  const controlBar = new ControlBar({
29
25
  components: [
30
26
  createSeekBar(npoPlayer),
31
27
  new Container({
32
- components: [
33
- new PlaybackToggleButton(),
34
- new VolumeToggleButton(),
35
- new VolumeSlider(),
36
- rewindButton,
37
- forwardButton,
38
- new Spacer(),
39
- new PictureInPictureToggleButton(),
40
- new AirPlayToggleButton(),
41
- chromeCastButton,
42
- new SettingsToggleButton({ settingsPanel }),
43
- settingsPanel,
44
- new FullscreenToggleButton()
45
- ],
28
+ components: [...controlComponents],
46
29
  cssClasses: ['controlbar-bottom']
47
30
  })
48
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
  }
@@ -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,13 +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
- acceptsTouchWithUiHidden: true;
11
8
  }>[];
12
9
  cssClasses: string[];
13
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,24 +1,10 @@
1
- import { NpoPlayerEvent } from '../../types/events';
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';
3
+ import { createChromecastButton } from './buttons';
4
4
  export function createTopBar(playerContext) {
5
- const npoPlayer = playerContext.npoplayer;
6
- const player = playerContext.player;
7
- const chromeCastButton = new CastToggleButton({
8
- disabled: true
9
- });
10
- const handleCastAvailable = () => {
11
- player?.off(NpoPlayerEvent.CastAvailable, handleCastAvailable);
12
- const remoteControlConfig = npoPlayer.playerConfig?.remotecontrol;
13
- if (player?.isCastAvailable() && remoteControlConfig.customReceiverConfig?.enable !== 'false') {
14
- chromeCastButton.enable();
15
- }
16
- else {
17
- chromeCastButton.disable();
18
- }
19
- };
20
- player?.on(NpoPlayerEvent.CastAvailable, handleCastAvailable);
5
+ const { npoPlayer, player } = playerContext;
21
6
  const settingsPanel = createSettingsPanel(npoPlayer);
7
+ const chromeCastButton = createChromecastButton(player, npoPlayer);
22
8
  return new TitleBar({
23
9
  components: [
24
10
  new Container({
@@ -28,10 +14,10 @@ export function createTopBar(playerContext) {
28
14
  chromeCastButton,
29
15
  new SettingsToggleButton({ settingsPanel }),
30
16
  settingsPanel,
31
- new FullscreenToggleButton(),
32
17
  new VolumeControlButton({
33
18
  vertical: true
34
- })
19
+ }),
20
+ new FullscreenToggleButton()
35
21
  ],
36
22
  cssClasses: ['controlbar-top', 'controlbar-small']
37
23
  })
@@ -3,7 +3,7 @@ import { createForwardButton, createRewindButton } from '../buttons';
3
3
  import { createSeekBar } from '../seekbar';
4
4
  import { createSettingsPanel } from '../settingspanel';
5
5
  export function createVerticalVideoControlBar(playerContext) {
6
- const npoPlayer = playerContext.npoplayer;
6
+ const { npoPlayer } = playerContext;
7
7
  const rewindButton = createRewindButton(playerContext);
8
8
  const forwardButton = createForwardButton(playerContext);
9
9
  const seekBar = new SeekBar({ label: new SeekBarLabel() });
@@ -0,0 +1 @@
1
+ export {};
@@ -35,7 +35,7 @@ export function nativeMobileUiFactory(player, config = {}) {
35
35
  }
36
36
  if (_webData.metadata?.ageRating || _webData.metadata?.nicam) {
37
37
  const webDataPlayerContext = {
38
- npoplayer: {
38
+ npoPlayer: {
39
39
  streamObject: {
40
40
  metadata: {
41
41
  ageRating: _webData.metadata.ageRating,
@@ -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) {
@@ -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';
@@ -14,69 +13,51 @@ import { createVerticalVideoControlBar } from './components/verticalvideo/contro
14
13
  import { DEFAULT_UI_DELAY, PREVENT_UI_DELAY } from '../services/npoPlayerAPI/contants';
15
14
  export function createUIContainer(playerContext, player, variant) {
16
15
  const cssClassArray = ['npo-player'];
17
- const npoPlayer = playerContext.npoplayer;
16
+ const hidePlayerStateExceptions = [PlayerUtils.PlayerState.Paused, PlayerUtils.PlayerState.Prepared];
17
+ const { npoPlayer } = playerContext;
18
18
  const container = npoPlayer.container;
19
19
  let uiDelay = DEFAULT_UI_DELAY;
20
20
  container.dataset.npoPlayerVersion = npoPlayer.version;
21
21
  container.classList.remove('bitmovinplayer-audio-container');
22
+ const components = [];
22
23
  switch (variant) {
23
24
  case NpoPlayerUIVariants.DEFAULT: {
24
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));
25
27
  break;
26
28
  }
27
29
  case NpoPlayerUIVariants.AD: {
28
30
  uiDelay = PREVENT_UI_DELAY;
29
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));
30
34
  break;
31
35
  }
32
36
  case NpoPlayerUIVariants.AUDIO: {
33
37
  uiDelay = PREVENT_UI_DELAY;
34
38
  container.classList.add('bitmovinplayer-audio-container');
35
39
  cssClassArray.push('audio');
40
+ components.push(new PlaybackToggleButton(), createAudioControlBar(npoPlayer), createTitleBar(npoPlayer));
36
41
  break;
37
42
  }
38
43
  case NpoPlayerUIVariants.VERTICAL: {
39
44
  uiDelay = DEFAULT_UI_DELAY;
40
45
  cssClassArray.push('vertical-video');
41
46
  npoPlayer.player?.setAspectRatio('9:16');
47
+ components.push(new SubtitleOverlay(), new BufferingOverlay(), createVerticalVideoControlBar(playerContext), createTitleBar(npoPlayer));
42
48
  break;
43
49
  }
44
50
  }
45
- const middleButtons = createMiddleButtons(playerContext);
46
- const playNextScreen = createPlayNextScreen(player, npoPlayer);
47
- const settingsPanel = createSettingsPanel(npoPlayer);
48
- const ctaBar = createCTABar(player, npoPlayer, variant);
49
- const topBar = createTopBar(playerContext);
50
- const controlBar = createControlBar(playerContext);
51
- const titleBar = createTitleBar(npoPlayer);
52
- const playbackToggleOverlay = new PlaybackToggleOverlay();
53
- const audioControlbar = createAudioControlBar(npoPlayer);
54
- const bufferingOverlay = new BufferingOverlay();
55
- const verticalVideoControlBar = createVerticalVideoControlBar(playerContext);
56
51
  const errorMessageOverlay = new ErrorMessageOverlay();
57
- const castStatusOverlay = new CastStatusOverlay();
58
52
  npoPlayer.uiComponents.errorMessageOverlay = errorMessageOverlay;
59
- const defaultVideoComponents = [settingsPanel, new SubtitleOverlay(), bufferingOverlay, playbackToggleOverlay];
60
- const components = [];
61
- if (variant === NpoPlayerUIVariants.DEFAULT) {
62
- components.push(...defaultVideoComponents, castStatusOverlay, middleButtons, playNextScreen, controlBar, ctaBar, titleBar, topBar);
63
- }
64
- if (variant === NpoPlayerUIVariants.VERTICAL) {
65
- components.push(...defaultVideoComponents, verticalVideoControlBar, titleBar);
66
- }
67
- if (variant === NpoPlayerUIVariants.AUDIO) {
68
- components.push(new PlaybackToggleButton(), audioControlbar, titleBar);
69
- }
70
- if (variant === NpoPlayerUIVariants.AD) {
71
- components.push(...defaultVideoComponents, castStatusOverlay, middleButtons, controlBar, ctaBar);
72
- }
53
+ components.push(errorMessageOverlay);
73
54
  UIManager.setLocalizationConfig(localizationConfig);
74
55
  const ariaLabelKey = variant === NpoPlayerUIVariants.AUDIO ? 'audioPlayer' : 'videoPlayer';
75
56
  return new UIContainer({
76
- components: [...components, errorMessageOverlay],
57
+ components,
77
58
  cssClasses: cssClassArray,
78
59
  ariaLabel: localizeKey(ariaLabelKey),
79
60
  hideDelay: uiDelay,
80
- hidePlayerStateExceptions: [PlayerUtils.PlayerState.Paused]
61
+ hidePlayerStateExceptions
81
62
  });
82
63
  }
@@ -0,0 +1 @@
1
+ import '@testing-library/jest-dom';
@@ -0,0 +1,80 @@
1
+ import '@testing-library/jest-dom';
2
+ import { createPlayerContextMock } from '../../tests/mocks/playerContextMock';
3
+ import { NpoPlayerUIVariants } from '../types/interfaces';
4
+ import { DEFAULT_UI_DELAY, PREVENT_UI_DELAY } from '../services/npoPlayerAPI/contants';
5
+ import { createUIContainer } from './uicontainer';
6
+ import { mockPlayerAPI } from '../../tests/mocks/mockPlayerAPI';
7
+ import { BufferingOverlay, CastStatusOverlay, Container, ControlBar, ErrorMessageOverlay, PlaybackToggleButton, PlaybackToggleOverlay, SubtitleOverlay, TitleBar } from 'bitmovin-player-ui';
8
+ describe('createUIContainer', () => {
9
+ let playerContextMock;
10
+ let playerMock;
11
+ beforeEach(() => {
12
+ playerMock = mockPlayerAPI;
13
+ playerContextMock = createPlayerContextMock({
14
+ npoPlayer: {
15
+ container: document.createElement('div'),
16
+ version: '1.0.0',
17
+ player: playerMock,
18
+ uiComponents: []
19
+ }
20
+ });
21
+ });
22
+ afterEach(() => {
23
+ jest.resetAllMocks();
24
+ });
25
+ it('should create the default UI container with the correct components', () => {
26
+ const uiContainer = createUIContainer(playerContextMock, playerMock, NpoPlayerUIVariants.DEFAULT);
27
+ expect(uiContainer.getComponents()).toEqual([
28
+ expect.any(SubtitleOverlay),
29
+ expect.any(BufferingOverlay),
30
+ expect.any(PlaybackToggleOverlay),
31
+ expect.any(CastStatusOverlay),
32
+ expect.any(ControlBar),
33
+ expect.any(Container),
34
+ expect.any(ControlBar),
35
+ expect.any(Container),
36
+ expect.any(TitleBar),
37
+ expect.any(TitleBar),
38
+ expect.any(ErrorMessageOverlay)
39
+ ]);
40
+ expect(uiContainer.getConfig().hideDelay).toBe(DEFAULT_UI_DELAY);
41
+ expect(uiContainer.getDomElement().hasClass('bmpui-npo-player')).toBe(true);
42
+ });
43
+ it('should create the AD variant with the correct components and prevent UI delay', () => {
44
+ const uiContainer = createUIContainer(playerContextMock, playerMock, NpoPlayerUIVariants.AD);
45
+ expect(uiContainer.getComponents()).toEqual([
46
+ expect.any(PlaybackToggleOverlay),
47
+ expect.any(CastStatusOverlay),
48
+ expect.any(ControlBar),
49
+ expect.any(Container),
50
+ expect.any(ErrorMessageOverlay)
51
+ ]);
52
+ expect(uiContainer.getConfig().hideDelay).toBe(PREVENT_UI_DELAY);
53
+ expect(uiContainer.getDomElement().hasClass('bmpui-ster-ad')).toBe(true);
54
+ });
55
+ it('should create the AUDIO variant with the correct components and no video-specific classes', () => {
56
+ const uiContainer = createUIContainer(playerContextMock, playerMock, NpoPlayerUIVariants.AUDIO);
57
+ expect(uiContainer.getComponents()).toEqual([
58
+ expect.any(PlaybackToggleButton),
59
+ expect.any(ControlBar),
60
+ expect.any(TitleBar),
61
+ expect.any(ErrorMessageOverlay)
62
+ ]);
63
+ expect(uiContainer.getConfig().hideDelay).toBe(PREVENT_UI_DELAY);
64
+ expect(uiContainer.getDomElement().hasClass('bmpui-audio')).toBe(true);
65
+ });
66
+ it('should create the VERTICAL variant with the correct aspect ratio and components', () => {
67
+ playerMock.setAspectRatio = jest.fn();
68
+ const uiContainer = createUIContainer(playerContextMock, playerMock, NpoPlayerUIVariants.VERTICAL);
69
+ expect(playerMock.setAspectRatio).toHaveBeenCalledWith('9:16');
70
+ expect(uiContainer.getComponents()).toEqual([
71
+ expect.any(SubtitleOverlay),
72
+ expect.any(BufferingOverlay),
73
+ expect.any(ControlBar),
74
+ expect.any(TitleBar),
75
+ expect.any(ErrorMessageOverlay)
76
+ ]);
77
+ expect(uiContainer.getConfig().hideDelay).toBe(DEFAULT_UI_DELAY);
78
+ expect(uiContainer.getDomElement().hasClass('bmpui-vertical-video')).toBe(true);
79
+ });
80
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@npo/player",
3
- "version": "1.25.0",
3
+ "version": "1.26.0",
4
4
  "description": "NPO Player",
5
5
  "author": "Publieke Omroep <player@npo.nl>",
6
6
  "contributors": [
@@ -89,7 +89,7 @@
89
89
  "webpack-dev-server": "^4.11.1"
90
90
  },
91
91
  "dependencies": {
92
- "@npotag/tag": "3.2.1",
92
+ "@npotag/tag": "3.2.4",
93
93
  "bitmovin-player": "^8.166.0",
94
94
  "bitmovin-player-ui": "3.67.0"
95
95
  },
@@ -4,15 +4,6 @@
4
4
  display: none;
5
5
  }
6
6
 
7
- .bmpui-ui-controlbar {
8
- &.bmpui-controlbar-middle,
9
- .bmpui-ui-rewindbutton,
10
- .bmpui-ui-forwardbutton,
11
- .bmpui-ui-settingstogglebutton {
12
- display: none;
13
- }
14
- }
15
-
16
7
  .bmpui-ui-seekbar {
17
8
  .bmpui-seekbar {
18
9
  .bmpui-seekbar-bufferlevel {
@@ -79,12 +79,13 @@
79
79
  }
80
80
  }
81
81
 
82
- // show nicam on default state
82
+ // show nicam on initial state and after UI hide
83
83
  &.bmpui-player-state-prepared,
84
84
  &.bmpui-player-state-prepared.bmpui-layout-max-width-400,
85
85
  &.bmpui-player-state-prepared.bmpui-layout-max-width-600,
86
- &.bmpui-show-nicam:not(.bmpui-player-state-paused).bmpui-layout-max-width-400,
87
- &.bmpui-show-nicam:not(.bmpui-player-state-paused).bmpui-layout-max-width-600 {
86
+ &.bmpui-player-state-prepared.bmpui-layout-max-width-800,
87
+ &.bmpui-player-state-prepared.bmpui-layout-max-width-1200,
88
+ &.bmpui-show-nicam {
88
89
  .bmpui-metadata,
89
90
  .bmpui-metadata.bmpui-title-bar {
90
91
  display: block;
@@ -94,7 +95,7 @@
94
95
 
95
96
  .bmpui-label-metadata-title,
96
97
  .bmpui-label-metadata-description {
97
- display: none;
98
+ opacity: 0;
98
99
  }
99
100
  }
100
101