@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.
- package/README.md +1 -1
- package/lib/js/api/getstreamobject.d.ts +1 -1
- package/lib/js/api/getstreamobject.js +4 -4
- package/lib/js/api/getstreamobject.test.js +13 -13
- package/lib/js/playeractions/handlers/handleoffsets.js +9 -7
- package/lib/js/playeractions/handlers/handleoffsets.test.js +1 -1
- package/lib/js/playeractions/handlers/processplayerconfig.d.ts +1 -1
- package/lib/js/playeractions/handlers/processplayerconfig.js +18 -4
- package/lib/js/playeractions/handlers/processplayerconfig.test.js +116 -0
- package/lib/js/playeractions/handlers/processsourceconfig.d.ts +3 -1
- package/lib/js/playeractions/handlers/processsourceconfig.js +20 -10
- package/lib/js/playeractions/handlers/processsourceconfig.test.js +25 -0
- package/lib/js/settings/localization.d.ts +76 -1
- package/lib/js/settings/localization.js +2 -2
- package/lib/js/tracking/handlers/eventbinding.js +25 -17
- package/lib/js/tracking/handlers/eventlogging.js +3 -8
- package/lib/js/tracking/handlers/playertrackerinit.d.ts +2 -2
- package/lib/js/tracking/handlers/playertrackerinit.js +8 -6
- package/lib/js/tracking/handlers/playertrackerinit.test.d.ts +1 -0
- package/lib/js/tracking/handlers/playertrackerinit.test.js +74 -0
- package/lib/js/tracking/handlers/playertrackerstart.js +1 -1
- package/lib/js/utilities/utilities.element.d.ts +6 -0
- package/lib/js/utilities/utilities.element.js +10 -0
- package/lib/js/utilities/utilities.element.test.js +18 -5
- package/lib/lang/nl.json +1 -1
- package/lib/lang/subtitleLabels/nl.json +14 -0
- package/lib/npoplayer.d.ts +15 -6
- package/lib/npoplayer.js +57 -50
- package/lib/npoplayer.test.js +12 -4
- package/lib/package.json +3 -3
- package/lib/services/a11y/setup.js +2 -5
- package/lib/services/a11y/setup.test.js +2 -19
- package/lib/services/advertHandlers/discardAdBreak.js +4 -4
- package/lib/services/advertHandlers/discardAdBreak.test.js +25 -13
- package/lib/services/advertHandlers/handlePreRolls.js +19 -19
- package/lib/services/advertHandlers/handlePrerolls.test.js +4 -4
- package/lib/services/cdnProviders/cdnProviders.js +4 -2
- package/lib/services/drmHandlers/decideprofile.js +1 -1
- package/lib/services/drmHandlers/decideprofile.test.js +1 -1
- package/lib/services/drmHandlers/verifydrm.js +6 -6
- package/lib/services/drmHandlers/verifydrm.test.js +5 -5
- package/lib/services/eventListenerHandlers/removeEventListeners.js +2 -2
- package/lib/services/eventListenerHandlers/removeEventListeners.test.js +9 -9
- package/lib/services/keyboardHandlers/resolvekeypress.js +5 -5
- package/lib/services/keyboardHandlers/resolvekeypress.test.js +1 -1
- package/lib/services/liveStreamHandlers/handleLiveStreamControls.js +2 -2
- package/lib/services/liveStreamHandlers/handleLiveStreamControls.test.js +2 -2
- package/lib/services/localStorageHandlers/localStorageHandlers.js +2 -2
- package/lib/services/localStorageHandlers/localStorageHandlers.test.js +2 -5
- package/lib/services/nicamHandlers/nicamhandler.d.ts +5 -0
- package/lib/{ui/handlers → services/nicamHandlers}/nicamhandler.js +24 -15
- package/lib/services/nicamHandlers/nicamhandler.test.js +132 -0
- package/lib/services/npoPlayerAPI/npoPlayerAPI.d.ts +3 -2
- package/lib/services/npoPlayerAPI/npoPlayerAPI.js +19 -23
- package/lib/services/preferences/handlePreferences.d.ts +2 -0
- package/lib/services/preferences/handlePreferences.js +42 -0
- package/lib/services/preferences/handlePreferences.test.d.ts +1 -0
- package/lib/services/preferences/handlePreferences.test.js +102 -0
- package/lib/services/segmentHandlers/addSegmentEventListeners.js +2 -2
- package/lib/services/segmentHandlers/addSegmentEventListeners.test.js +1 -1
- package/lib/services/segmentHandlers/setSegmentMarkers.js +1 -1
- package/lib/services/services.d.ts +7 -0
- package/lib/services/services.js +26 -0
- package/lib/services/streamoptionsHandlers/streamOptionsHandler.d.ts +6 -0
- package/lib/services/streamoptionsHandlers/streamOptionsHandler.js +78 -0
- package/lib/services/streamoptionsHandlers/streamOptionsHandler.test.js +187 -0
- package/lib/services/uiHandlers/uiVisiblityHandler.d.ts +3 -0
- package/lib/services/uiHandlers/uiVisiblityHandler.js +26 -0
- package/lib/services/uiHandlers/uiVisiblityHandler.test.d.ts +1 -0
- package/lib/services/uiHandlers/uiVisiblityHandler.test.js +62 -0
- package/lib/src/js/api/getstreamobject.d.ts +1 -1
- package/lib/src/js/playeractions/handlers/processplayerconfig.d.ts +1 -1
- package/lib/src/js/playeractions/handlers/processplayerconfig.test.d.ts +1 -0
- package/lib/src/js/playeractions/handlers/processsourceconfig.d.ts +3 -1
- package/lib/src/js/playeractions/handlers/processsourceconfig.test.d.ts +1 -0
- package/lib/src/js/settings/localization.d.ts +76 -1
- package/lib/src/js/tracking/handlers/playertrackerinit.d.ts +2 -2
- package/lib/src/js/tracking/handlers/playertrackerinit.test.d.ts +1 -0
- package/lib/src/js/utilities/utilities.element.d.ts +6 -0
- package/lib/src/npoplayer.d.ts +15 -6
- package/lib/src/services/nicamHandlers/nicamhandler.d.ts +5 -0
- package/lib/src/services/nicamHandlers/nicamhandler.test.d.ts +1 -0
- package/lib/src/services/npoPlayerAPI/npoPlayerAPI.d.ts +3 -2
- package/lib/src/services/preferences/handlePreferences.d.ts +2 -0
- package/lib/src/services/preferences/handlePreferences.test.d.ts +1 -0
- package/lib/src/services/services.d.ts +7 -0
- package/lib/src/services/streamoptionsHandlers/streamOptionsHandler.d.ts +6 -0
- package/lib/src/services/streamoptionsHandlers/streamOptionsHandler.test.d.ts +1 -0
- package/lib/src/services/uiHandlers/uiVisiblityHandler.d.ts +3 -0
- package/lib/src/services/uiHandlers/uiVisiblityHandler.test.d.ts +1 -0
- package/lib/src/types/classes.d.ts +6 -0
- package/lib/src/types/interfaces.d.ts +25 -3
- package/lib/src/ui/components/adbutton.d.ts +1 -1
- package/lib/src/ui/components/adlabel.d.ts +1 -1
- package/lib/src/ui/components/buttons.d.ts +10 -17
- package/lib/src/ui/components/controlbar.d.ts +2 -2
- package/lib/src/ui/components/ctabar.d.ts +1 -1
- package/lib/src/ui/components/nativemobile/buttons.d.ts +8 -0
- package/lib/src/ui/components/playnext.d.ts +1 -3
- package/lib/src/ui/components/seekbar.d.ts +1 -1
- package/lib/src/ui/components/titlebar.d.ts +1 -1
- package/lib/src/ui/components/topbar.d.ts +2 -2
- package/lib/src/ui/components/verticalvideo/controlbar.d.ts +2 -2
- package/lib/src/ui/handlers/playnextscreen.test.d.ts +1 -0
- package/lib/src/ui/handlers/timecontrolhandlers.d.ts +3 -3
- package/lib/src/ui/uicontainer.d.ts +2 -3
- package/lib/src/ui/uicontainer.test.d.ts +1 -0
- package/lib/tests/mocks/mockLogEmitter.d.ts +2 -0
- package/lib/tests/mocks/mockLogEmitter.js +20 -0
- package/lib/tests/mocks/mockNpoplayer.js +4 -2
- package/lib/tests/mocks/playerContextMock.d.ts +5 -3
- package/lib/tests/mocks/playerContextMock.js +8 -5
- package/lib/types/classes.d.ts +6 -0
- package/lib/types/classes.js +12 -0
- package/lib/types/interfaces.d.ts +25 -3
- package/lib/types/interfaces.js +1 -0
- package/lib/ui/components/adbutton.d.ts +1 -1
- package/lib/ui/components/adbutton.js +3 -3
- package/lib/ui/components/adlabel.d.ts +1 -1
- package/lib/ui/components/adlabel.js +3 -3
- package/lib/ui/components/buttons.d.ts +10 -17
- package/lib/ui/components/buttons.js +44 -27
- package/lib/ui/components/controlbar.d.ts +2 -2
- package/lib/ui/components/controlbar.js +20 -32
- package/lib/ui/components/ctabar.d.ts +1 -1
- package/lib/ui/components/ctabar.js +4 -4
- package/lib/ui/components/nativemobile/buttons.d.ts +8 -0
- package/lib/ui/components/nativemobile/buttons.js +41 -1
- package/lib/ui/components/nativemobile/controlbar.js +1 -2
- package/lib/ui/components/nativemobile/topbar.js +2 -2
- package/lib/ui/components/playnext.d.ts +1 -3
- package/lib/ui/components/playnext.js +3 -3
- package/lib/ui/components/seekbar.d.ts +1 -1
- package/lib/ui/components/seekbar.js +5 -3
- package/lib/ui/components/settingspanel.js +9 -9
- package/lib/ui/components/titlebar.d.ts +1 -1
- package/lib/ui/components/titlebar.js +2 -2
- package/lib/ui/components/topbar.d.ts +2 -2
- package/lib/ui/components/topbar.js +8 -17
- package/lib/ui/components/verticalvideo/controlbar.d.ts +2 -2
- package/lib/ui/components/verticalvideo/controlbar.js +4 -4
- package/lib/ui/handlers/playnextscreen.test.d.ts +1 -0
- package/lib/ui/handlers/timecontrolhandlers.d.ts +3 -3
- package/lib/ui/nativemobileuifactory.js +20 -24
- package/lib/ui/nativemobileuifactory.test.js +2 -6
- package/lib/ui/uicontainer.d.ts +2 -3
- package/lib/ui/uicontainer.js +13 -30
- package/lib/ui/uicontainer.test.d.ts +1 -0
- package/lib/ui/uicontainer.test.js +80 -0
- package/package.json +3 -3
- package/src/style/components/_advert.scss +0 -9
- package/src/style/components/_icons.scss +5 -0
- package/src/style/components/_nicam.scss +5 -4
- package/src/style/components/_settingspanel.scss +48 -17
- package/src/style/components/vertical-video/_settingspanel.scss +1 -1
- package/src/style/npoplayer.css +26 -20
- package/src/style/variants/_player-base.scss +4 -0
- package/src/style/variants/_player-large.scss +5 -1
- package/src/style/variants/_player-small.scss +11 -8
- package/lib/src/ui/handlers/nicamhandler.d.ts +0 -6
- package/lib/src/ui/handlers/streamhandler.d.ts +0 -2
- package/lib/ui/handlers/nicamhandler.d.ts +0 -6
- package/lib/ui/handlers/nicamhandler.test.js +0 -36
- package/lib/ui/handlers/streamhandler.d.ts +0 -2
- package/lib/ui/handlers/streamhandler.js +0 -60
- /package/lib/{src/ui/handlers/playnextstreen.test.d.ts → js/playeractions/handlers/processplayerconfig.test.d.ts} +0 -0
- /package/lib/{ui/handlers/playnextstreen.test.d.ts → js/playeractions/handlers/processsourceconfig.test.d.ts} +0 -0
- /package/lib/{src/ui/handlers → services/nicamHandlers}/nicamhandler.test.d.ts +0 -0
- /package/lib/{ui/handlers/nicamhandler.test.d.ts → services/streamoptionsHandlers/streamOptionsHandler.test.d.ts} +0 -0
- /package/lib/ui/handlers/{playnextstreen.test.js → playnextscreen.test.js} +0 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { processNicam, showNicamAfterUiDelay } from './nicamhandler';
|
|
2
|
+
import '@testing-library/jest-dom';
|
|
3
|
+
import { createMockNpoPlayer, createPlayerContextMock } from '../../../tests/mocks/playerContextMock';
|
|
4
|
+
import { NpoPlayerEvent } from '../../types/events';
|
|
5
|
+
describe('NICAM Processing', () => {
|
|
6
|
+
let mockElement;
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
mockElement = { innerHTML: '', appendChild: jest.fn() };
|
|
9
|
+
document.querySelector = jest.fn().mockReturnValue(mockElement);
|
|
10
|
+
});
|
|
11
|
+
it('processes NICAM from the streamObject', () => {
|
|
12
|
+
const mockElement = document.createElement('div');
|
|
13
|
+
const npoPlayerMock = createMockNpoPlayer({
|
|
14
|
+
streamObject: {
|
|
15
|
+
metadata: {
|
|
16
|
+
ageRating: '12',
|
|
17
|
+
nicam: ['GEWELD', 'ANGST', 'DRUGS_EN_ALCOHOL', 'GROF_TAALGEBRUIK']
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
const playerContextMock = createPlayerContextMock({
|
|
22
|
+
npoPlayer: npoPlayerMock
|
|
23
|
+
});
|
|
24
|
+
processNicam(playerContextMock, mockElement);
|
|
25
|
+
expect(mockElement.children).toHaveLength(5);
|
|
26
|
+
});
|
|
27
|
+
it('processes NICAM and age rating with streamOptions taking priority', () => {
|
|
28
|
+
const mockElement = document.createElement('div');
|
|
29
|
+
const npoPlayerMock = createMockNpoPlayer({
|
|
30
|
+
streamObject: {
|
|
31
|
+
metadata: {
|
|
32
|
+
ageRating: '12',
|
|
33
|
+
nicam: ['GEWELD', 'ANGST', 'GROF_TAALGEBRUIK']
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
streamOptions: {
|
|
37
|
+
ageRating: '16',
|
|
38
|
+
nicam: ['DRUGS_EN_ALCOHOL']
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
const playerContextMock = createPlayerContextMock({
|
|
42
|
+
npoPlayer: npoPlayerMock
|
|
43
|
+
});
|
|
44
|
+
processNicam(playerContextMock, mockElement);
|
|
45
|
+
expect(mockElement.children).toHaveLength(2);
|
|
46
|
+
});
|
|
47
|
+
it('does nothing if no NICAM element found', () => {
|
|
48
|
+
document.querySelector = jest.fn().mockReturnValue(undefined);
|
|
49
|
+
const npoPlayerMock = createMockNpoPlayer({
|
|
50
|
+
streamObject: {
|
|
51
|
+
metadata: {
|
|
52
|
+
ageRating: '12',
|
|
53
|
+
nicam: ['GEWELD', 'ANGST', 'GROF_TAALGEBRUIK']
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
const playerContextMock = createPlayerContextMock({
|
|
58
|
+
npoPlayer: npoPlayerMock
|
|
59
|
+
});
|
|
60
|
+
processNicam(playerContextMock, mockElement);
|
|
61
|
+
});
|
|
62
|
+
it('does nothing if no metadata and no streamOptions', () => {
|
|
63
|
+
const npoPlayerMock = createMockNpoPlayer({});
|
|
64
|
+
const playerContextMock = createPlayerContextMock({
|
|
65
|
+
npoPlayer: npoPlayerMock
|
|
66
|
+
});
|
|
67
|
+
processNicam(playerContextMock, mockElement);
|
|
68
|
+
expect(mockElement.appendChild).not.toHaveBeenCalled();
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
describe('NICAM Visibility Management', () => {
|
|
72
|
+
let mockPlayerContext;
|
|
73
|
+
let mockContainer;
|
|
74
|
+
let mockPlayer;
|
|
75
|
+
let mockUiManager;
|
|
76
|
+
beforeEach(() => {
|
|
77
|
+
mockContainer = document.createElement('div');
|
|
78
|
+
mockPlayer = {
|
|
79
|
+
getNpoPlayerElement: jest.fn().mockReturnValue(mockContainer),
|
|
80
|
+
off: jest.fn()
|
|
81
|
+
};
|
|
82
|
+
mockUiManager = {
|
|
83
|
+
activeUi: {
|
|
84
|
+
onControlsHide: {
|
|
85
|
+
subscribe: jest.fn(),
|
|
86
|
+
unsubscribe: jest.fn()
|
|
87
|
+
},
|
|
88
|
+
onControlsShow: {
|
|
89
|
+
subscribe: jest.fn(),
|
|
90
|
+
unsubscribe: jest.fn()
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
mockPlayerContext = createPlayerContextMock({
|
|
95
|
+
player: mockPlayer,
|
|
96
|
+
npoPlayer: {
|
|
97
|
+
uiManager: mockUiManager,
|
|
98
|
+
container: mockContainer
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
describe('showNicamAfterUiDelay', () => {
|
|
103
|
+
it('should add showNicam class when controls are hidden', () => {
|
|
104
|
+
jest.useFakeTimers();
|
|
105
|
+
const showNicamClass = 'bmpui-show-nicam';
|
|
106
|
+
showNicamAfterUiDelay(mockPlayerContext);
|
|
107
|
+
mockUiManager.activeUi.onControlsHide.subscribe.mock.calls[0][0]();
|
|
108
|
+
expect(mockContainer).toHaveClass(showNicamClass);
|
|
109
|
+
jest.advanceTimersByTime(3000);
|
|
110
|
+
expect(mockContainer).not.toHaveClass(showNicamClass);
|
|
111
|
+
jest.useRealTimers();
|
|
112
|
+
});
|
|
113
|
+
it('should remove showNicam class when controls are shown', () => {
|
|
114
|
+
showNicamAfterUiDelay(mockPlayerContext);
|
|
115
|
+
const showNicamClass = 'bmpui-show-nicam';
|
|
116
|
+
mockUiManager.activeUi.onControlsHide.subscribe.mock.calls[0][0]();
|
|
117
|
+
expect(mockContainer).toHaveClass(showNicamClass);
|
|
118
|
+
mockUiManager.activeUi.onControlsShow.subscribe.mock.calls[0][0]();
|
|
119
|
+
expect(mockContainer).not.toHaveClass(showNicamClass);
|
|
120
|
+
});
|
|
121
|
+
it('should not execute if player container or uiManager is undefined', () => {
|
|
122
|
+
mockPlayerContext.npoPlayer.uiManager = undefined;
|
|
123
|
+
showNicamAfterUiDelay(mockPlayerContext);
|
|
124
|
+
expect(mockUiManager.activeUi.onControlsHide.subscribe).not.toHaveBeenCalled();
|
|
125
|
+
expect(mockUiManager.activeUi.onControlsShow.subscribe).not.toHaveBeenCalled();
|
|
126
|
+
});
|
|
127
|
+
it('should clean up event listeners when the player is ready', () => {
|
|
128
|
+
showNicamAfterUiDelay(mockPlayerContext);
|
|
129
|
+
expect(mockPlayer.off).toHaveBeenCalledWith(NpoPlayerEvent.Ready, expect.any(Function));
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
});
|
|
@@ -17,7 +17,8 @@ export declare class NpoPlayerAPI {
|
|
|
17
17
|
setViewMode(viewMode: ViewMode): void;
|
|
18
18
|
getViewMode(): ViewMode;
|
|
19
19
|
areSubtitlesEnabled(): boolean;
|
|
20
|
-
|
|
20
|
+
getCurrentSubtitle(): string | undefined;
|
|
21
|
+
enableSubtitles(selectedLang?: string): void;
|
|
21
22
|
isPaused(): boolean;
|
|
22
23
|
isMuted(): boolean;
|
|
23
24
|
isLive(): boolean;
|
|
@@ -25,6 +26,7 @@ export declare class NpoPlayerAPI {
|
|
|
25
26
|
getSupportedTech(): Technology[];
|
|
26
27
|
off(eventType: NpoPlayerEvent, callback: NpoPlayerEventCallback): void;
|
|
27
28
|
on(eventType: NpoPlayerEvent, callback: NpoPlayerEventCallback): void;
|
|
29
|
+
isCastAvailable(): boolean;
|
|
28
30
|
seek(time: number): void;
|
|
29
31
|
timeShift(time: number): void;
|
|
30
32
|
getContainer(): HTMLElement;
|
|
@@ -37,7 +39,6 @@ export declare class NpoPlayerAPI {
|
|
|
37
39
|
getTimeShift(): number;
|
|
38
40
|
scheduleAds(adConfig: AdConfig): Promise<AdBreak[]>;
|
|
39
41
|
getActiveAdBreak(): AdBreak | null;
|
|
40
|
-
discardAdBreak(adBreakId: string): void;
|
|
41
42
|
getConfig(mergedConfig?: boolean): PlayerConfig;
|
|
42
43
|
createUIManager(playerContext: PlayerContext, variant: NpoPlayerUIVariants): Promise<void | UIManager>;
|
|
43
44
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { UIManager } from 'bitmovin-player-ui';
|
|
2
2
|
import { customSpecificErrorMessageOverlayConfig } from '../../js/playeractions/handlers/customerrors';
|
|
3
|
-
import { processStream } from '../../ui/handlers/streamhandler';
|
|
4
3
|
import { createUIContainer } from '../../ui/uicontainer';
|
|
5
4
|
import { playerEventMap } from '../../types/events';
|
|
6
5
|
import { VOLUME_MAX, VOLUME_MIN, VOLUME_STEP } from './contants';
|
|
@@ -46,23 +45,17 @@ export class NpoPlayerAPI {
|
|
|
46
45
|
return this.playerAPI.getViewMode();
|
|
47
46
|
}
|
|
48
47
|
areSubtitlesEnabled() {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
break;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return subsEnabled;
|
|
48
|
+
return this.playerAPI.subtitles.list().some((subtitle) => subtitle.enabled);
|
|
49
|
+
}
|
|
50
|
+
getCurrentSubtitle() {
|
|
51
|
+
const currentSubtitle = this.playerAPI.subtitles.list().find((subtitle) => subtitle.enabled);
|
|
52
|
+
return currentSubtitle ? currentSubtitle.lang : undefined;
|
|
58
53
|
}
|
|
59
|
-
enableSubtitles() {
|
|
54
|
+
enableSubtitles(selectedLang = 'nl') {
|
|
60
55
|
const subtitleTracks = this.playerAPI.subtitles.list();
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
break;
|
|
65
|
-
}
|
|
56
|
+
const subtitleToEnable = subtitleTracks.find((subtitle) => subtitle.lang === selectedLang);
|
|
57
|
+
if (subtitleToEnable && !subtitleToEnable.enabled) {
|
|
58
|
+
this.playerAPI.subtitles.enable(subtitleToEnable.id);
|
|
66
59
|
}
|
|
67
60
|
}
|
|
68
61
|
isPaused() {
|
|
@@ -99,6 +92,9 @@ export class NpoPlayerAPI {
|
|
|
99
92
|
}
|
|
100
93
|
this.playerAPI.on(externalEventType, externalCallback);
|
|
101
94
|
}
|
|
95
|
+
isCastAvailable() {
|
|
96
|
+
return this.playerAPI.isCastAvailable();
|
|
97
|
+
}
|
|
102
98
|
seek(time) {
|
|
103
99
|
this.playerAPI.seek(time);
|
|
104
100
|
}
|
|
@@ -135,22 +131,22 @@ export class NpoPlayerAPI {
|
|
|
135
131
|
getActiveAdBreak() {
|
|
136
132
|
return this.playerAPI.ads.getActiveAdBreak();
|
|
137
133
|
}
|
|
138
|
-
discardAdBreak(adBreakId) {
|
|
139
|
-
return this.playerAPI.ads.discardAdBreak(adBreakId);
|
|
140
|
-
}
|
|
141
134
|
getConfig(mergedConfig) {
|
|
142
135
|
return this.playerAPI.getConfig(mergedConfig);
|
|
143
136
|
}
|
|
144
137
|
async createUIManager(playerContext, variant) {
|
|
145
|
-
|
|
138
|
+
const { npoPlayerServices } = playerContext.npoPlayer;
|
|
139
|
+
npoPlayerServices.removeUivisiblityHandlers(playerContext);
|
|
140
|
+
if (playerContext.npoPlayer.uiManager === undefined || variant !== playerContext.npoPlayer.variant) {
|
|
146
141
|
const uiConfig = {
|
|
147
142
|
errorMessages: customSpecificErrorMessageOverlayConfig,
|
|
148
143
|
disableAutoHideWhenHovered: true,
|
|
149
144
|
seekbarSnappingEnabled: false
|
|
150
145
|
};
|
|
151
|
-
playerContext.
|
|
152
|
-
playerContext.
|
|
146
|
+
playerContext.npoPlayer.variant = variant;
|
|
147
|
+
const uiManager = new UIManager(this.playerAPI, createUIContainer(playerContext, this.playerAPI, variant), uiConfig);
|
|
148
|
+
playerContext.npoPlayer.uiManager = uiManager;
|
|
149
|
+
npoPlayerServices.addUivisiblityHandlers(playerContext);
|
|
153
150
|
}
|
|
154
|
-
processStream(playerContext);
|
|
155
151
|
}
|
|
156
152
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { NpoPlayerEvent } from '../../types/events';
|
|
2
|
+
import { LocalStorageValues } from '../../types/interfaces';
|
|
3
|
+
export function handlePreferences(playerContext) {
|
|
4
|
+
const { player, npoPlayer } = playerContext;
|
|
5
|
+
const { npoPlayerServices } = npoPlayer;
|
|
6
|
+
const handleSourceLoaded = () => {
|
|
7
|
+
const storedUserPrefs = npoPlayerServices.getStoredUserPrefs();
|
|
8
|
+
const subtitlesEnabledInPrefs = storedUserPrefs?.subtitles_enabled === 'true';
|
|
9
|
+
const preferredSubtitleLang = storedUserPrefs?.subtitles_language?.toString();
|
|
10
|
+
const shouldEnableSubtitles = npoPlayer.streamOptions.enableSubtitles || subtitlesEnabledInPrefs;
|
|
11
|
+
if (shouldEnableSubtitles) {
|
|
12
|
+
player.enableSubtitles(preferredSubtitleLang);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
const handleSubtitleEnabled = () => {
|
|
16
|
+
const currentSubtitleTrack = player.playerAPI.subtitles.list();
|
|
17
|
+
const enabledSubtitle = currentSubtitleTrack.find((subtitle) => subtitle.enabled);
|
|
18
|
+
if (enabledSubtitle) {
|
|
19
|
+
npoPlayerServices.setStoredUserPrefs(LocalStorageValues.SUBTITLES_LANGUAGE, enabledSubtitle.lang);
|
|
20
|
+
npoPlayerServices.setStoredUserPrefs(LocalStorageValues.SUBTITLES_ENABLED, 'true');
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
const handleSubtitleDisabled = () => {
|
|
24
|
+
npoPlayerServices.setStoredUserPrefs(LocalStorageValues.SUBTITLES_ENABLED, 'false');
|
|
25
|
+
};
|
|
26
|
+
const handleVolumeChanged = () => {
|
|
27
|
+
const volume = player.getVolume();
|
|
28
|
+
npoPlayerServices.setStoredUserPrefs(LocalStorageValues.VOLUME, volume);
|
|
29
|
+
};
|
|
30
|
+
const handleMuted = () => {
|
|
31
|
+
npoPlayerServices.setStoredUserPrefs(LocalStorageValues.IS_MUTED, 'true');
|
|
32
|
+
};
|
|
33
|
+
const handleUnmuted = () => {
|
|
34
|
+
npoPlayerServices.setStoredUserPrefs(LocalStorageValues.IS_MUTED, 'false');
|
|
35
|
+
};
|
|
36
|
+
player.on(NpoPlayerEvent.SourceLoaded, handleSourceLoaded);
|
|
37
|
+
player.on(NpoPlayerEvent.SubtitleEnabled, handleSubtitleEnabled);
|
|
38
|
+
player.on(NpoPlayerEvent.SubtitleDisabled, handleSubtitleDisabled);
|
|
39
|
+
player.on(NpoPlayerEvent.VolumeChanged, handleVolumeChanged);
|
|
40
|
+
player.on(NpoPlayerEvent.Muted, handleMuted);
|
|
41
|
+
player.on(NpoPlayerEvent.Unmuted, handleUnmuted);
|
|
42
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import createPlayerContextMock, { createMockNpoPlayer, createMockNpoPlayerAPI } from '../../../tests/mocks/playerContextMock';
|
|
2
|
+
import { handlePreferences } from './handlePreferences';
|
|
3
|
+
import { NpoPlayerEvent } from '../../types/events';
|
|
4
|
+
import { LocalStorageValues } from '../../types/interfaces';
|
|
5
|
+
describe('handlePreferences', () => {
|
|
6
|
+
let mockPlayerAPI;
|
|
7
|
+
let mockNpoPlayer;
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
mockPlayerAPI = createMockNpoPlayerAPI({
|
|
10
|
+
getVolume: jest.fn().mockReturnValue(50),
|
|
11
|
+
on: jest.fn(),
|
|
12
|
+
enableSubtitles: jest.fn(),
|
|
13
|
+
playerAPI: {
|
|
14
|
+
subtitles: {
|
|
15
|
+
list: jest.fn()
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
mockNpoPlayer = createMockNpoPlayer({
|
|
20
|
+
streamOptions: {
|
|
21
|
+
enableSubtitles: false
|
|
22
|
+
},
|
|
23
|
+
npoPlayerServices: {
|
|
24
|
+
getStoredUserPrefs: jest.fn().mockReturnValue({
|
|
25
|
+
subtitles_enabled: 'false',
|
|
26
|
+
subtitles_language: 'nl'
|
|
27
|
+
}),
|
|
28
|
+
setStoredUserPrefs: jest.fn()
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
const playerContextMock = createPlayerContextMock({
|
|
32
|
+
player: mockPlayerAPI,
|
|
33
|
+
npoPlayer: mockNpoPlayer
|
|
34
|
+
});
|
|
35
|
+
handlePreferences(playerContextMock);
|
|
36
|
+
});
|
|
37
|
+
test('should enable subtitles if streamOptions.enableSubtitles is true', () => {
|
|
38
|
+
mockNpoPlayer.streamOptions.enableSubtitles = true;
|
|
39
|
+
for (const [event, callback] of mockPlayerAPI.on.mock.calls) {
|
|
40
|
+
if (event === NpoPlayerEvent.SourceLoaded) {
|
|
41
|
+
callback(NpoPlayerEvent.SourceLoaded);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
expect(mockPlayerAPI.enableSubtitles).toHaveBeenCalledWith('nl');
|
|
45
|
+
});
|
|
46
|
+
test('should enable subtitles if subtitles_enabled in preferences is true', () => {
|
|
47
|
+
mockNpoPlayer.streamOptions.enableSubtitles = false;
|
|
48
|
+
mockNpoPlayer.npoPlayerServices.getStoredUserPrefs.mockReturnValueOnce({
|
|
49
|
+
subtitles_enabled: 'true',
|
|
50
|
+
subtitles_language: 'nl'
|
|
51
|
+
});
|
|
52
|
+
for (const [event, callback] of mockPlayerAPI.on.mock.calls) {
|
|
53
|
+
if (event === NpoPlayerEvent.SourceLoaded) {
|
|
54
|
+
callback(NpoPlayerEvent.SourceLoaded);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
expect(mockPlayerAPI.enableSubtitles).toHaveBeenCalledWith('nl');
|
|
58
|
+
});
|
|
59
|
+
test('should disable subtitles and set the preferences', () => {
|
|
60
|
+
;
|
|
61
|
+
mockPlayerAPI.playerAPI.subtitles.list.mockReturnValueOnce([{ lang: 'nl', enabled: true }]);
|
|
62
|
+
for (const [event, callback] of mockPlayerAPI.on.mock.calls) {
|
|
63
|
+
if (event === NpoPlayerEvent.SubtitleEnabled) {
|
|
64
|
+
callback(NpoPlayerEvent.SubtitleEnable);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
expect(mockNpoPlayer.npoPlayerServices.setStoredUserPrefs).toHaveBeenCalledWith(LocalStorageValues.SUBTITLES_LANGUAGE, 'nl');
|
|
68
|
+
expect(mockNpoPlayer.npoPlayerServices.setStoredUserPrefs).toHaveBeenCalledWith(LocalStorageValues.SUBTITLES_ENABLED, 'true');
|
|
69
|
+
});
|
|
70
|
+
test('should disable subtitles and set preferences to false', () => {
|
|
71
|
+
for (const [event, callback] of mockPlayerAPI.on.mock.calls) {
|
|
72
|
+
if (event === NpoPlayerEvent.SubtitleDisabled) {
|
|
73
|
+
callback(NpoPlayerEvent.SubtitleDisabled);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
expect(mockNpoPlayer.npoPlayerServices.setStoredUserPrefs).toHaveBeenCalledWith(LocalStorageValues.SUBTITLES_ENABLED, 'false');
|
|
77
|
+
});
|
|
78
|
+
test('should set volume preferences', () => {
|
|
79
|
+
for (const [event, callback] of mockPlayerAPI.on.mock.calls) {
|
|
80
|
+
if (event === NpoPlayerEvent.VolumeChanged) {
|
|
81
|
+
callback(NpoPlayerEvent.VolumeChanged);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
expect(mockNpoPlayer.npoPlayerServices.setStoredUserPrefs).toHaveBeenCalledWith(LocalStorageValues.VOLUME, 50);
|
|
85
|
+
});
|
|
86
|
+
test('should set muted preferences', () => {
|
|
87
|
+
for (const [event, callback] of mockPlayerAPI.on.mock.calls) {
|
|
88
|
+
if (event === NpoPlayerEvent.Muted) {
|
|
89
|
+
callback(NpoPlayerEvent.Muted);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
expect(mockNpoPlayer.npoPlayerServices.setStoredUserPrefs).toHaveBeenCalledWith(LocalStorageValues.IS_MUTED, 'true');
|
|
93
|
+
});
|
|
94
|
+
test('should set unmuted preferences', () => {
|
|
95
|
+
for (const [event, callback] of mockPlayerAPI.on.mock.calls) {
|
|
96
|
+
if (event === NpoPlayerEvent.Unmuted) {
|
|
97
|
+
callback(NpoPlayerEvent.Unmuted);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
expect(mockNpoPlayer.npoPlayerServices.setStoredUserPrefs).toHaveBeenCalledWith(LocalStorageValues.IS_MUTED, 'false');
|
|
101
|
+
});
|
|
102
|
+
});
|
|
@@ -4,10 +4,10 @@ import { handleSegmentSeek } from './handleSegmentSeek';
|
|
|
4
4
|
export const addSegmentEventListeners = (playerContext, segment) => {
|
|
5
5
|
const segmentHandleTimeChangedCallback = handleSegmentTimeChanged(playerContext, segment);
|
|
6
6
|
const segmentSeekFunctionCallback = handleSegmentSeek(playerContext, segment);
|
|
7
|
-
const { player,
|
|
7
|
+
const { player, npoPlayer } = playerContext;
|
|
8
8
|
player.on(NpoPlayerEvent.TimeChanged, segmentHandleTimeChangedCallback);
|
|
9
9
|
player.on(NpoPlayerEvent.Seek, segmentSeekFunctionCallback);
|
|
10
|
-
|
|
10
|
+
npoPlayer.eventListeners = {
|
|
11
11
|
segmentHandleTimeChangedCallback,
|
|
12
12
|
segmentSeekFunctionCallback
|
|
13
13
|
};
|
|
@@ -36,7 +36,7 @@ describe('addSegmentEventListeners', () => {
|
|
|
36
36
|
handleSegmentTimeChanged.mockReturnValue(segmentHandleTimeChangedCallback);
|
|
37
37
|
handleSegmentSeek.mockReturnValue(segmentSeekFunctionCallback);
|
|
38
38
|
addSegmentEventListeners(mockPlayerContext, segment);
|
|
39
|
-
expect(mockPlayerContext.
|
|
39
|
+
expect(mockPlayerContext.npoPlayer.eventListeners).toEqual({
|
|
40
40
|
segmentHandleTimeChangedCallback,
|
|
41
41
|
segmentSeekFunctionCallback
|
|
42
42
|
});
|
|
@@ -12,5 +12,12 @@ export declare class NpoPlayerServices {
|
|
|
12
12
|
handleUserPrefs(playerContext: PlayerContext): void;
|
|
13
13
|
setAccessibilityAttributes(playerContext: PlayerContext): void;
|
|
14
14
|
schedulePreRolls(playerContext: PlayerContext): Promise<void>;
|
|
15
|
+
discardAdBreak(playerContext: PlayerContext): void;
|
|
15
16
|
handleVerticalVideoControls(playerContext: PlayerContext, variant: NpoPlayerUIVariants): void;
|
|
17
|
+
showNicamAfterUiDelay(playerContext: PlayerContext | undefined): void;
|
|
18
|
+
setupNicamKijkwijzerIcons(playerContext: PlayerContext): void;
|
|
19
|
+
handlePreferences(playerContext: PlayerContext): void;
|
|
20
|
+
addUivisiblityHandlers(playerContext: PlayerContext): void;
|
|
21
|
+
removeUivisiblityHandlers(playerContext: PlayerContext): void;
|
|
22
|
+
handleStreamOptions(playerContext: PlayerContext): void;
|
|
16
23
|
}
|
package/lib/services/services.js
CHANGED
|
@@ -7,6 +7,11 @@ import { getLocalStorage, setLocalStorage, setValuesBasedOnLocalStorage } from '
|
|
|
7
7
|
import { getAVType } from './avTypeHandlers/getAVType';
|
|
8
8
|
import { handlePreRolls } from './advertHandlers/handlePreRolls';
|
|
9
9
|
import { handleVerticalVideoControls } from './verticalVideoHandlers/handleVerticalVideoControls';
|
|
10
|
+
import { setupNicamKijkwijzerIcons, showNicamAfterUiDelay } from './nicamHandlers/nicamhandler';
|
|
11
|
+
import { handlePreferences } from './preferences/handlePreferences';
|
|
12
|
+
import { addUivisiblityHandlers, removeUivisiblityHandlers } from './uiHandlers/uiVisiblityHandler';
|
|
13
|
+
import { discardAdBreak } from './advertHandlers/discardAdBreak';
|
|
14
|
+
import { handleStreamOptions } from './streamoptionsHandlers/streamOptionsHandler';
|
|
10
15
|
export class NpoPlayerServices {
|
|
11
16
|
getAVType(avType) {
|
|
12
17
|
return getAVType(avType);
|
|
@@ -49,7 +54,28 @@ export class NpoPlayerServices {
|
|
|
49
54
|
async schedulePreRolls(playerContext) {
|
|
50
55
|
await handlePreRolls(playerContext);
|
|
51
56
|
}
|
|
57
|
+
discardAdBreak(playerContext) {
|
|
58
|
+
discardAdBreak(playerContext);
|
|
59
|
+
}
|
|
52
60
|
handleVerticalVideoControls(playerContext, variant) {
|
|
53
61
|
return handleVerticalVideoControls(playerContext, variant);
|
|
54
62
|
}
|
|
63
|
+
showNicamAfterUiDelay(playerContext) {
|
|
64
|
+
return showNicamAfterUiDelay(playerContext);
|
|
65
|
+
}
|
|
66
|
+
setupNicamKijkwijzerIcons(playerContext) {
|
|
67
|
+
return setupNicamKijkwijzerIcons(playerContext);
|
|
68
|
+
}
|
|
69
|
+
handlePreferences(playerContext) {
|
|
70
|
+
handlePreferences(playerContext);
|
|
71
|
+
}
|
|
72
|
+
addUivisiblityHandlers(playerContext) {
|
|
73
|
+
addUivisiblityHandlers(playerContext);
|
|
74
|
+
}
|
|
75
|
+
removeUivisiblityHandlers(playerContext) {
|
|
76
|
+
removeUivisiblityHandlers(playerContext);
|
|
77
|
+
}
|
|
78
|
+
handleStreamOptions(playerContext) {
|
|
79
|
+
handleStreamOptions(playerContext);
|
|
80
|
+
}
|
|
55
81
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { PlayerContext } from '../../types/interfaces';
|
|
2
|
+
export declare function handleStreamOptions(playerContext: PlayerContext): void;
|
|
3
|
+
export declare function initializeFragment(playerContext: PlayerContext): void;
|
|
4
|
+
export declare function handleStartOffset(playerContext: PlayerContext): void;
|
|
5
|
+
export declare function updateStreamClasses(playerContext: PlayerContext): void;
|
|
6
|
+
export declare function setupAutoplay(playerContext: PlayerContext): void;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import * as playerAction from '../../js/playeractions/playeractions';
|
|
2
|
+
import { initSegment } from '../segmentHandlers/initSegment';
|
|
3
|
+
import { handleLiveStreamControls } from '../liveStreamHandlers/handleLiveStreamControls';
|
|
4
|
+
import { removeEventListeners } from '../eventListenerHandlers/removeEventListeners';
|
|
5
|
+
import { NpoPlayerEvent } from '../../types/events';
|
|
6
|
+
import { updateClassFromElementByQuery } from '../../js/utilities/utilities.element';
|
|
7
|
+
export function handleStreamOptions(playerContext) {
|
|
8
|
+
const { streamObject, uiManager } = playerContext.npoPlayer;
|
|
9
|
+
if (!streamObject || !uiManager)
|
|
10
|
+
return;
|
|
11
|
+
removeEventListeners(playerContext);
|
|
12
|
+
initializeFragment(playerContext);
|
|
13
|
+
handleStartOffset(playerContext);
|
|
14
|
+
updateStreamClasses(playerContext);
|
|
15
|
+
const isAutoplayEnabled = getAutoplayStatus(playerContext);
|
|
16
|
+
if (isAutoplayEnabled) {
|
|
17
|
+
setupAutoplay(playerContext);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export function initializeFragment(playerContext) {
|
|
21
|
+
const { streamObject, streamOptions } = playerContext.npoPlayer;
|
|
22
|
+
initSegment(playerContext, {
|
|
23
|
+
segment: streamObject.segment,
|
|
24
|
+
fragment: streamOptions?.fragments
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
export function handleStartOffset(playerContext) {
|
|
28
|
+
const streamOptions = playerContext.npoPlayer.streamOptions;
|
|
29
|
+
if (streamOptions?.startOffset) {
|
|
30
|
+
playerAction.handleStartOffset(playerContext, streamOptions.startOffset);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export function updateStreamClasses(playerContext) {
|
|
34
|
+
const { streamObject, container } = playerContext.npoPlayer;
|
|
35
|
+
const containerClassString = '.bmpui-ui-uicontainer';
|
|
36
|
+
const playerContainer = container;
|
|
37
|
+
const queries = [
|
|
38
|
+
{
|
|
39
|
+
container: playerContainer,
|
|
40
|
+
query: containerClassString,
|
|
41
|
+
className: 'livestream-no-dvr',
|
|
42
|
+
condition: !!(streamObject.stream.isLiveStream && !streamObject.stream.hasDvrWindow)
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
container: playerContainer,
|
|
46
|
+
query: containerClassString,
|
|
47
|
+
className: 'audio-only',
|
|
48
|
+
condition: !!(streamObject.stream.avType === 'aod' || streamObject.stream.avType === 'audio')
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
container: playerContainer,
|
|
52
|
+
query: '.bitmovinplayer-poster',
|
|
53
|
+
className: 'audio-only',
|
|
54
|
+
condition: !!(streamObject.stream.avType === 'aod' || streamObject.stream.avType === 'audio')
|
|
55
|
+
}
|
|
56
|
+
];
|
|
57
|
+
for (const query of queries)
|
|
58
|
+
updateClassFromElementByQuery(query);
|
|
59
|
+
if (streamObject.stream.isLiveStream && streamObject.stream.hasDvrWindow) {
|
|
60
|
+
handleLiveStreamControls(playerContext);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function getAutoplayStatus(playerContext) {
|
|
64
|
+
return (playerContext.npoPlayer.streamOptions?.autoplay ?? playerContext.player.getConfig()?.playback?.autoplay ?? false);
|
|
65
|
+
}
|
|
66
|
+
export function setupAutoplay(playerContext) {
|
|
67
|
+
const { player } = playerContext;
|
|
68
|
+
const handleAutoPlay = () => {
|
|
69
|
+
doAutoPlay().catch((error) => {
|
|
70
|
+
console.error('Error attempting to autoplay:', error);
|
|
71
|
+
});
|
|
72
|
+
};
|
|
73
|
+
const doAutoPlay = async () => {
|
|
74
|
+
player.off(NpoPlayerEvent.Ready, handleAutoPlay);
|
|
75
|
+
await player.play();
|
|
76
|
+
};
|
|
77
|
+
player.on(NpoPlayerEvent.Ready, handleAutoPlay);
|
|
78
|
+
}
|