@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.
- 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 +12 -12
- 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 +4 -4
- package/lib/js/playeractions/handlers/processsourceconfig.d.ts +1 -0
- package/lib/js/playeractions/handlers/processsourceconfig.js +4 -5
- package/lib/js/playeractions/handlers/processsourceconfig.test.js +25 -0
- package/lib/js/tracking/handlers/playertrackerstart.js +1 -1
- package/lib/lang/nl.json +1 -1
- package/lib/lang/subtitleLabels/nl.json +14 -0
- package/lib/npoplayer.d.ts +2 -3
- package/lib/npoplayer.js +24 -32
- package/lib/npoplayer.test.js +1 -1
- package/lib/package.json +2 -2
- 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/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 +1 -2
- package/lib/services/nicamHandlers/nicamhandler.js +17 -16
- package/lib/services/nicamHandlers/nicamhandler.test.js +72 -9
- package/lib/services/npoPlayerAPI/npoPlayerAPI.d.ts +2 -2
- package/lib/services/npoPlayerAPI/npoPlayerAPI.js +16 -23
- package/lib/services/preferences/handlePreferences.d.ts +2 -0
- package/lib/services/preferences/handlePreferences.js +42 -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/services.d.ts +6 -2
- package/lib/services/services.js +21 -2
- package/lib/services/streamoptionsHandlers/{steamOptionsHandler.js → streamOptionsHandler.js} +11 -11
- package/lib/services/streamoptionsHandlers/streamOptionsHandler.test.js +20 -20
- 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/processsourceconfig.d.ts +1 -0
- package/lib/src/js/playeractions/handlers/processsourceconfig.test.d.ts +1 -0
- package/lib/src/npoplayer.d.ts +2 -3
- package/lib/src/services/nicamHandlers/nicamhandler.d.ts +1 -2
- package/lib/src/services/npoPlayerAPI/npoPlayerAPI.d.ts +2 -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 +6 -2
- 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 +24 -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 +6 -16
- 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/playnext.d.ts +1 -4
- package/lib/src/ui/components/seekbar.d.ts +1 -1
- package/lib/src/ui/components/titlebar.d.ts +1 -1
- package/lib/src/ui/handlers/playnextscreen.test.d.ts +1 -0
- 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 +1 -2
- package/lib/tests/mocks/playerContextMock.d.ts +5 -3
- package/lib/tests/mocks/playerContextMock.js +7 -5
- package/lib/types/classes.d.ts +6 -0
- package/lib/types/classes.js +12 -0
- package/lib/types/interfaces.d.ts +24 -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 +6 -16
- package/lib/ui/components/buttons.js +27 -10
- package/lib/ui/components/controlbar.d.ts +2 -2
- package/lib/ui/components/controlbar.js +20 -37
- package/lib/ui/components/ctabar.d.ts +1 -1
- package/lib/ui/components/ctabar.js +4 -4
- package/lib/ui/components/nativemobile/topbar.js +2 -2
- package/lib/ui/components/playnext.d.ts +1 -4
- 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.js +6 -20
- package/lib/ui/components/verticalvideo/controlbar.js +1 -1
- package/lib/ui/handlers/playnextscreen.test.d.ts +1 -0
- package/lib/ui/nativemobileuifactory.js +1 -1
- package/lib/ui/nativemobileuifactory.test.js +2 -1
- package/lib/ui/uicontainer.js +11 -30
- package/lib/ui/uicontainer.test.d.ts +1 -0
- package/lib/ui/uicontainer.test.js +80 -0
- package/package.json +2 -2
- package/src/style/components/_advert.scss +0 -9
- 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 +25 -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/playnextstreen.test.d.ts → js/playeractions/handlers/processsourceconfig.test.d.ts} +0 -0
- /package/lib/{ui/handlers/playnextstreen.test.d.ts → services/preferences/handlePreferences.test.d.ts} +0 -0
- /package/lib/services/streamoptionsHandlers/{steamOptionsHandler.d.ts → streamOptionsHandler.d.ts} +0 -0
- /package/lib/src/services/streamoptionsHandlers/{steamOptionsHandler.d.ts → streamOptionsHandler.d.ts} +0 -0
- /package/lib/ui/handlers/{playnextstreen.test.js → playnextscreen.test.js} +0 -0
|
@@ -3,12 +3,12 @@ import { NpoPlayerUIVariants } from '../../types/interfaces';
|
|
|
3
3
|
import { NpoPlayerEvent } from '../../types/events';
|
|
4
4
|
export async function handlePreRolls(playerContext) {
|
|
5
5
|
return new Promise((resolve) => {
|
|
6
|
-
if (playerContext.
|
|
7
|
-
playerContext.
|
|
6
|
+
if (playerContext.npoPlayer.streamObject.metadata.hasPreroll == 'false' ||
|
|
7
|
+
playerContext.npoPlayer.streamObject.assets.preroll == undefined) {
|
|
8
8
|
resolve();
|
|
9
9
|
return;
|
|
10
10
|
}
|
|
11
|
-
const prerollUrl = playerContext.
|
|
11
|
+
const prerollUrl = playerContext.npoPlayer.streamObject.assets.preroll;
|
|
12
12
|
let adIndex = 0;
|
|
13
13
|
let totalAds = 0;
|
|
14
14
|
let currentClickListener;
|
|
@@ -35,13 +35,13 @@ export async function handlePreRolls(playerContext) {
|
|
|
35
35
|
const activeAdBreak = playerContext.player.getActiveAdBreak();
|
|
36
36
|
if (!activeAdBreak || !activeAdBreak.ads)
|
|
37
37
|
return false;
|
|
38
|
-
playerContext.
|
|
39
|
-
playerContext.
|
|
40
|
-
if (playerContext.
|
|
41
|
-
playerContext.player.createUIManager(playerContext, NpoPlayerUIVariants.AD);
|
|
38
|
+
playerContext.npoPlayer.uiManager?.release();
|
|
39
|
+
playerContext.npoPlayer.uiManager = undefined;
|
|
40
|
+
if (playerContext.npoPlayer.playerContext) {
|
|
41
|
+
void playerContext.player.createUIManager(playerContext, NpoPlayerUIVariants.AD);
|
|
42
42
|
}
|
|
43
43
|
adUiSet = true;
|
|
44
|
-
const adButton = playerContext.
|
|
44
|
+
const adButton = playerContext.npoPlayer.uiComponents.adbutton;
|
|
45
45
|
const currentAd = activeAdBreak.ads[0];
|
|
46
46
|
adIndex = 1;
|
|
47
47
|
totalAds = activeAdBreak.ads.length;
|
|
@@ -49,7 +49,7 @@ export async function handlePreRolls(playerContext) {
|
|
|
49
49
|
adButton.show();
|
|
50
50
|
adClickHandler(currentAd, adButton);
|
|
51
51
|
}
|
|
52
|
-
playerContext.
|
|
52
|
+
playerContext.npoPlayer.uiComponents.adlabel?.setText(`Advertentie 1 van ${activeAdBreak.ads.length}`);
|
|
53
53
|
return true;
|
|
54
54
|
}
|
|
55
55
|
function attemptSetAdUi(attemptsLeft = 10) {
|
|
@@ -71,7 +71,7 @@ export async function handlePreRolls(playerContext) {
|
|
|
71
71
|
}
|
|
72
72
|
if (!adUiSet)
|
|
73
73
|
attemptSetAdUi();
|
|
74
|
-
playerContext.
|
|
74
|
+
playerContext.npoPlayer.adBreakActive = true;
|
|
75
75
|
}
|
|
76
76
|
playerContext.player.on(NpoPlayerEvent.AdStarted, handleAdStarted);
|
|
77
77
|
function adClickHandler(ad, button) {
|
|
@@ -102,26 +102,26 @@ export async function handlePreRolls(playerContext) {
|
|
|
102
102
|
handleAdBreakFinished();
|
|
103
103
|
return;
|
|
104
104
|
}
|
|
105
|
-
const adButton = playerContext.
|
|
105
|
+
const adButton = playerContext.npoPlayer.uiComponents.adbutton;
|
|
106
106
|
const nextAd = activeAdBreak.ads[adIndex];
|
|
107
107
|
adIndex += 1;
|
|
108
108
|
if (adButton) {
|
|
109
109
|
adButton.show();
|
|
110
110
|
adClickHandler(nextAd, adButton);
|
|
111
111
|
}
|
|
112
|
-
playerContext.
|
|
112
|
+
playerContext.npoPlayer.uiComponents.adlabel?.setText(`Advertentie ${adIndex} van ${activeAdBreak.ads.length}`);
|
|
113
113
|
}
|
|
114
114
|
playerContext.player.on(NpoPlayerEvent.AdFinished, handleAdFinished);
|
|
115
115
|
function handleAdBreakFinished() {
|
|
116
116
|
playerContext.player.off(NpoPlayerEvent.AdBreakFinished, handleAdBreakFinished);
|
|
117
117
|
playerContext.player.off(NpoPlayerEvent.AdError, handleAdBreakFinished);
|
|
118
|
-
playerContext.
|
|
119
|
-
playerContext.
|
|
120
|
-
playerContext.
|
|
121
|
-
playerContext.
|
|
122
|
-
playerContext.
|
|
123
|
-
if (playerContext.
|
|
124
|
-
playerContext.player.createUIManager(playerContext, NpoPlayerUIVariants.DEFAULT);
|
|
118
|
+
playerContext.npoPlayer.adBreakActive = false;
|
|
119
|
+
playerContext.npoPlayer.uiComponents.adbutton?.hide();
|
|
120
|
+
playerContext.npoPlayer.uiComponents.adlabel?.hide();
|
|
121
|
+
playerContext.npoPlayer.uiManager?.release();
|
|
122
|
+
playerContext.npoPlayer.uiManager = undefined;
|
|
123
|
+
if (playerContext.npoPlayer.playerContext) {
|
|
124
|
+
void playerContext.player.createUIManager(playerContext, NpoPlayerUIVariants.DEFAULT);
|
|
125
125
|
}
|
|
126
126
|
adUiSet = false;
|
|
127
127
|
resolve();
|
|
@@ -15,7 +15,7 @@ describe('handlePreRolls', () => {
|
|
|
15
15
|
};
|
|
16
16
|
});
|
|
17
17
|
it('should not schedule ads when hasPreroll is false', async () => {
|
|
18
|
-
const
|
|
18
|
+
const npoPlayerMock = createMockNpoPlayer({
|
|
19
19
|
streamObject: {
|
|
20
20
|
metadata: {
|
|
21
21
|
hasPreroll: 'false'
|
|
@@ -26,13 +26,13 @@ describe('handlePreRolls', () => {
|
|
|
26
26
|
}
|
|
27
27
|
});
|
|
28
28
|
const playerContextMock = createPlayerContextMock({
|
|
29
|
-
|
|
29
|
+
npoPlayer: npoPlayerMock
|
|
30
30
|
});
|
|
31
31
|
await handlePreRolls(playerContextMock);
|
|
32
32
|
expect(mockPlayerAPI.ads.schedule).not.toHaveBeenCalled();
|
|
33
33
|
});
|
|
34
34
|
it('should not schedule ads if preroll URL is missing', async () => {
|
|
35
|
-
const
|
|
35
|
+
const npoPlayerMock = createMockNpoPlayer({
|
|
36
36
|
streamObject: {
|
|
37
37
|
metadata: {
|
|
38
38
|
hasPreroll: 'true'
|
|
@@ -41,7 +41,7 @@ describe('handlePreRolls', () => {
|
|
|
41
41
|
}
|
|
42
42
|
});
|
|
43
43
|
const playerContextMock = createPlayerContextMock({
|
|
44
|
-
|
|
44
|
+
npoPlayer: npoPlayerMock
|
|
45
45
|
});
|
|
46
46
|
await handlePreRolls(playerContextMock);
|
|
47
47
|
expect(mockPlayerAPI.ads.schedule).not.toHaveBeenCalled();
|
|
@@ -5,7 +5,7 @@ export async function decideProfile(playerContext, preferredDRM = '') {
|
|
|
5
5
|
console.error('No player detected');
|
|
6
6
|
return { profileName: '', drm: '' };
|
|
7
7
|
}
|
|
8
|
-
const player = playerContext
|
|
8
|
+
const { player } = playerContext;
|
|
9
9
|
const supportedTech = player.getSupportedTech();
|
|
10
10
|
const supportedDRM = await player.getSupportedDRM();
|
|
11
11
|
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
|
@@ -13,7 +13,7 @@ describe('decideProfile', () => {
|
|
|
13
13
|
.fn()
|
|
14
14
|
.mockResolvedValue(['com.widevine.alpha', 'com.microsoft.playready', 'com.apple.fps.1_0'])
|
|
15
15
|
};
|
|
16
|
-
mockPlayerContext = { player: mockPlayer,
|
|
16
|
+
mockPlayerContext = { player: mockPlayer, npoPlayer: mockNpoplayer };
|
|
17
17
|
});
|
|
18
18
|
afterEach(() => {
|
|
19
19
|
jest.clearAllMocks();
|
|
@@ -2,7 +2,7 @@ import { convertJwtToBase64, convertBase64ToObject } from '../../js/utilities/ut
|
|
|
2
2
|
import { getStreamObject } from '../../js/api/getstreamobject';
|
|
3
3
|
export async function verifyDRM(playerContext, payload) {
|
|
4
4
|
try {
|
|
5
|
-
const { player,
|
|
5
|
+
const { player, npoPlayer: { streamObject, sourceConfig } } = playerContext;
|
|
6
6
|
const { stream } = streamObject;
|
|
7
7
|
if (stream.drmToken) {
|
|
8
8
|
const drmJsonTimestamp = getDRMTokenTimestamp(stream.drmToken);
|
|
@@ -29,12 +29,12 @@ function getDRMTokenTimestamp(drmToken) {
|
|
|
29
29
|
return convertBase64ToObject(drmBase64).iat;
|
|
30
30
|
}
|
|
31
31
|
async function refreshDRMToken(playerContext, payload) {
|
|
32
|
-
const backupStreamObject = await getStreamObject(playerContext.
|
|
32
|
+
const backupStreamObject = await getStreamObject(playerContext.npoPlayer, payload);
|
|
33
33
|
const newDrmToken = backupStreamObject.stream.drmToken;
|
|
34
34
|
const clonedStreamObject = {
|
|
35
|
-
...playerContext.
|
|
36
|
-
stream: { ...playerContext.
|
|
35
|
+
...playerContext.npoPlayer.streamObject,
|
|
36
|
+
stream: { ...playerContext.npoPlayer.streamObject.stream, drmToken: newDrmToken }
|
|
37
37
|
};
|
|
38
|
-
playerContext.
|
|
39
|
-
await loadPlayer(playerContext, playerContext.
|
|
38
|
+
playerContext.npoPlayer.streamObject = clonedStreamObject;
|
|
39
|
+
await loadPlayer(playerContext, playerContext.npoPlayer.sourceConfig);
|
|
40
40
|
}
|
|
@@ -18,7 +18,7 @@ beforeEach(() => {
|
|
|
18
18
|
streamObject: { stream: { drmToken: undefined } },
|
|
19
19
|
load: jest.fn()
|
|
20
20
|
};
|
|
21
|
-
mockPlayerContext = { player: mockPlayer,
|
|
21
|
+
mockPlayerContext = { player: mockPlayer, npoPlayer: mockNpoplayer };
|
|
22
22
|
});
|
|
23
23
|
afterEach(() => {
|
|
24
24
|
jest.clearAllMocks();
|
|
@@ -42,7 +42,7 @@ describe('Test DRM verification', () => {
|
|
|
42
42
|
streamURL: '',
|
|
43
43
|
drmToken: drmToken
|
|
44
44
|
};
|
|
45
|
-
mockPlayerContext.
|
|
45
|
+
mockPlayerContext.npoPlayer.sourceConfig = sourceConfig;
|
|
46
46
|
jest.spyOn(global.Date, 'now').mockImplementation(() => currentTime * 1000);
|
|
47
47
|
convertJwtToBase64.mockReturnValue(JSON.stringify({ iat: drmJsonTimestamp }));
|
|
48
48
|
convertBase64ToObject.mockReturnValue({ iat: drmJsonTimestamp });
|
|
@@ -62,14 +62,14 @@ describe('Test DRM verification', () => {
|
|
|
62
62
|
streamURL: '',
|
|
63
63
|
drmToken: drmToken
|
|
64
64
|
};
|
|
65
|
-
mockPlayerContext.
|
|
65
|
+
mockPlayerContext.npoPlayer.sourceConfig = sourceConfig;
|
|
66
66
|
jest.spyOn(global.Date, 'now').mockImplementation(() => currentTime * 1000);
|
|
67
67
|
convertJwtToBase64.mockReturnValue(JSON.stringify({ iat: drmJsonTimestamp }));
|
|
68
68
|
convertBase64ToObject.mockReturnValue({ iat: drmJsonTimestamp });
|
|
69
69
|
getStreamObject.mockResolvedValue({ stream: { drmToken: 'newToken' } });
|
|
70
70
|
jest.spyOn(mockPlayerContext.player, 'load').mockResolvedValue(undefined);
|
|
71
71
|
await verifyDRM(mockPlayerContext, payload);
|
|
72
|
-
expect(getStreamObject).toHaveBeenCalledWith(mockPlayerContext.
|
|
72
|
+
expect(getStreamObject).toHaveBeenCalledWith(mockPlayerContext.npoPlayer, payload);
|
|
73
73
|
expect(mockPlayerContext.player.load).toHaveBeenCalledWith(sourceConfig);
|
|
74
74
|
});
|
|
75
75
|
it('should call loadPlayer when the drmToken is null', async () => {
|
|
@@ -82,7 +82,7 @@ describe('Test DRM verification', () => {
|
|
|
82
82
|
streamURL: '',
|
|
83
83
|
drmToken: undefined
|
|
84
84
|
};
|
|
85
|
-
mockPlayerContext.
|
|
85
|
+
mockPlayerContext.npoPlayer.sourceConfig = sourceConfig;
|
|
86
86
|
await verifyDRM(mockPlayerContext, payload);
|
|
87
87
|
expect(mockPlayerContext.player.load).toHaveBeenCalledWith(sourceConfig);
|
|
88
88
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NpoPlayerEvent } from '../../types/events';
|
|
2
2
|
export const removeEventListeners = (playerContext) => {
|
|
3
|
-
const { eventListeners } = playerContext.
|
|
3
|
+
const { eventListeners } = playerContext.npoPlayer;
|
|
4
4
|
if (eventListeners) {
|
|
5
5
|
const { segmentHandleTimeChangedCallback, segmentSeekFunctionCallback, liveStreamHandleTimeChangedCallback } = eventListeners;
|
|
6
6
|
const eventMapping = [
|
|
@@ -13,6 +13,6 @@ export const removeEventListeners = (playerContext) => {
|
|
|
13
13
|
playerContext.player.off(event, callback);
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
|
-
playerContext.
|
|
16
|
+
playerContext.npoPlayer.eventListeners = undefined;
|
|
17
17
|
}
|
|
18
18
|
};
|
|
@@ -8,35 +8,35 @@ describe('removeEventListeners', () => {
|
|
|
8
8
|
mockPlayerContext = createPlayerContextMock();
|
|
9
9
|
});
|
|
10
10
|
it('should remove TimeChanged event listener if exists', () => {
|
|
11
|
-
mockPlayerContext.
|
|
11
|
+
mockPlayerContext.npoPlayer.eventListeners = {
|
|
12
12
|
segmentHandleTimeChangedCallback: jest.fn(),
|
|
13
13
|
liveStreamHandleTimeChangedCallback: jest.fn(),
|
|
14
14
|
segmentSeekFunctionCallback: jest.fn()
|
|
15
15
|
};
|
|
16
16
|
removeEventListeners(mockPlayerContext);
|
|
17
|
-
if (mockPlayerContext.
|
|
18
|
-
expect(mockPlayerContext.player.off).toHaveBeenCalledWith(NpoPlayerEvent.TimeChanged, mockPlayerContext.
|
|
19
|
-
expect(mockPlayerContext.player.off).toHaveBeenCalledWith(NpoPlayerEvent.TimeChanged, mockPlayerContext.
|
|
17
|
+
if (mockPlayerContext.npoPlayer.eventListeners) {
|
|
18
|
+
expect(mockPlayerContext.player.off).toHaveBeenCalledWith(NpoPlayerEvent.TimeChanged, mockPlayerContext.npoPlayer.eventListeners.segmentHandleTimeChangedCallback);
|
|
19
|
+
expect(mockPlayerContext.player.off).toHaveBeenCalledWith(NpoPlayerEvent.TimeChanged, mockPlayerContext.npoPlayer.eventListeners.liveStreamHandleTimeChangedCallback);
|
|
20
20
|
}
|
|
21
21
|
});
|
|
22
22
|
it('should remove Seek event listener if exists', () => {
|
|
23
|
-
mockPlayerContext.
|
|
23
|
+
mockPlayerContext.npoPlayer.eventListeners = {
|
|
24
24
|
segmentHandleTimeChangedCallback: jest.fn(),
|
|
25
25
|
liveStreamHandleTimeChangedCallback: jest.fn(),
|
|
26
26
|
segmentSeekFunctionCallback: jest.fn()
|
|
27
27
|
};
|
|
28
28
|
removeEventListeners(mockPlayerContext);
|
|
29
|
-
if (mockPlayerContext.
|
|
30
|
-
expect(mockPlayerContext.player.off).toHaveBeenCalledWith(NpoPlayerEvent.Seek, mockPlayerContext.
|
|
29
|
+
if (mockPlayerContext.npoPlayer.eventListeners) {
|
|
30
|
+
expect(mockPlayerContext.player.off).toHaveBeenCalledWith(NpoPlayerEvent.Seek, mockPlayerContext.npoPlayer.eventListeners.segmentSeekFunctionCallback);
|
|
31
31
|
}
|
|
32
32
|
});
|
|
33
33
|
it('should reset EventListeners in playerContext', () => {
|
|
34
|
-
mockPlayerContext.
|
|
34
|
+
mockPlayerContext.npoPlayer.eventListeners = {
|
|
35
35
|
segmentHandleTimeChangedCallback: jest.fn(),
|
|
36
36
|
liveStreamHandleTimeChangedCallback: jest.fn(),
|
|
37
37
|
segmentSeekFunctionCallback: jest.fn()
|
|
38
38
|
};
|
|
39
39
|
removeEventListeners(mockPlayerContext);
|
|
40
|
-
expect(mockPlayerContext.
|
|
40
|
+
expect(mockPlayerContext.npoPlayer.eventListeners).toBeUndefined();
|
|
41
41
|
});
|
|
42
42
|
});
|
|
@@ -23,17 +23,17 @@ export function resolveKeyPress(playerContext, e) {
|
|
|
23
23
|
ArrowUp: () => {
|
|
24
24
|
if (isMuted)
|
|
25
25
|
playerContext.player.unmute();
|
|
26
|
-
playerContext.
|
|
26
|
+
playerContext.npoPlayer.increaseVolume();
|
|
27
27
|
},
|
|
28
28
|
ArrowDown: () => {
|
|
29
29
|
if (isMuted)
|
|
30
30
|
playerContext.player.unmute();
|
|
31
|
-
playerContext.
|
|
31
|
+
playerContext.npoPlayer.decreaseVolume();
|
|
32
32
|
},
|
|
33
|
-
ArrowLeft: () => playerContext.
|
|
34
|
-
ArrowRight: () => playerContext.
|
|
33
|
+
ArrowLeft: () => playerContext.npoPlayer.goBackwards(10),
|
|
34
|
+
ArrowRight: () => playerContext.npoPlayer.goForward(10),
|
|
35
35
|
Escape: () => {
|
|
36
|
-
const { settingsPanels } = playerContext.
|
|
36
|
+
const { settingsPanels } = playerContext.npoPlayer.uiComponents;
|
|
37
37
|
if (settingsPanels && settingsPanels.length > 0) {
|
|
38
38
|
for (const panel of settingsPanels) {
|
|
39
39
|
if (panel.isShown()) {
|
|
@@ -32,7 +32,7 @@ describe('resolveKeyPress', () => {
|
|
|
32
32
|
})
|
|
33
33
|
};
|
|
34
34
|
e = new KeyboardEvent('keydown');
|
|
35
|
-
mockPlayerContext = { player: mockPlayer,
|
|
35
|
+
mockPlayerContext = { player: mockPlayer, npoPlayer: mockNpoplayer };
|
|
36
36
|
});
|
|
37
37
|
it('should mute/unmute the player when "KeyM" is pressed', () => {
|
|
38
38
|
mockPlayer.isMuted.mockReturnValue(true);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { NpoPlayerEvent } from '../../types/events';
|
|
2
2
|
export const handleLiveStreamControls = (playerContext) => {
|
|
3
3
|
const liveStreamHandleTimeChangedCallback = () => updateForwardButtonState(playerContext.player);
|
|
4
|
-
const { player,
|
|
4
|
+
const { player, npoPlayer } = playerContext;
|
|
5
5
|
player.on(NpoPlayerEvent.TimeChanged, liveStreamHandleTimeChangedCallback);
|
|
6
|
-
|
|
6
|
+
npoPlayer.eventListeners = {
|
|
7
7
|
liveStreamHandleTimeChangedCallback
|
|
8
8
|
};
|
|
9
9
|
};
|
|
@@ -11,8 +11,8 @@ describe('handleLiveStreamControls', () => {
|
|
|
11
11
|
});
|
|
12
12
|
it('should add TimeChanged event listener and store it in eventListeners', () => {
|
|
13
13
|
handleLiveStreamControls(mockPlayerContext);
|
|
14
|
-
expect(mockPlayerContext.player.on).toHaveBeenCalledWith(NpoPlayerEvent.TimeChanged, mockPlayerContext.
|
|
15
|
-
expect(mockPlayerContext.
|
|
14
|
+
expect(mockPlayerContext.player.on).toHaveBeenCalledWith(NpoPlayerEvent.TimeChanged, mockPlayerContext.npoPlayer.eventListeners?.liveStreamHandleTimeChangedCallback);
|
|
15
|
+
expect(mockPlayerContext.npoPlayer.eventListeners?.liveStreamHandleTimeChangedCallback).toBeDefined();
|
|
16
16
|
});
|
|
17
17
|
});
|
|
18
18
|
describe('updateForwardButtonState', () => {
|
|
@@ -18,7 +18,7 @@ export function getLocalStorage() {
|
|
|
18
18
|
}
|
|
19
19
|
export function setValuesBasedOnLocalStorage(playerContext) {
|
|
20
20
|
const localStorageData = getLocalStorage();
|
|
21
|
-
const player = playerContext
|
|
21
|
+
const { player } = playerContext;
|
|
22
22
|
if (!player) {
|
|
23
23
|
console.error('Player is undefined in playerContext');
|
|
24
24
|
return;
|
|
@@ -28,6 +28,6 @@ export function setValuesBasedOnLocalStorage(playerContext) {
|
|
|
28
28
|
player.mute();
|
|
29
29
|
}
|
|
30
30
|
if (localStorageData.subtitles_enabled === 'true') {
|
|
31
|
-
playerContext.
|
|
31
|
+
playerContext.npoPlayer.streamOptions.enableSubtitles = true;
|
|
32
32
|
}
|
|
33
33
|
}
|
|
@@ -54,14 +54,11 @@ describe('localStorageHandler', () => {
|
|
|
54
54
|
};
|
|
55
55
|
playerContext = {
|
|
56
56
|
player: mockPlayerAPI,
|
|
57
|
-
|
|
57
|
+
npoPlayer: {
|
|
58
58
|
...mockNpoPlayer,
|
|
59
59
|
streamOptions: {
|
|
60
60
|
enableSubtitles: false
|
|
61
61
|
},
|
|
62
|
-
userPreferences: {
|
|
63
|
-
subtitles_enabled: 'false'
|
|
64
|
-
},
|
|
65
62
|
container: document.createElement('div'),
|
|
66
63
|
streamObject: {},
|
|
67
64
|
playerConfig: {},
|
|
@@ -102,7 +99,7 @@ describe('localStorageHandler', () => {
|
|
|
102
99
|
it('should enable subtitles if localStorage subtitles_enabled is true', () => {
|
|
103
100
|
localStorage.setItem('npoplayer-subtitles_enabled', JSON.stringify('true'));
|
|
104
101
|
setValuesBasedOnLocalStorage(playerContext);
|
|
105
|
-
expect(playerContext.
|
|
102
|
+
expect(playerContext.npoPlayer.streamOptions.enableSubtitles).toBe(true);
|
|
106
103
|
});
|
|
107
104
|
});
|
|
108
105
|
});
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { UIManager } from 'bitmovin-player-ui';
|
|
2
1
|
import { PlayerContext } from '../../types/interfaces';
|
|
3
2
|
export declare function processNicam(playerContext: PlayerContext, nicamElement: HTMLElement | undefined): void;
|
|
4
3
|
export declare function addNicamIcon(character: string, nicamElement: Element): void;
|
|
5
|
-
export declare function showNicamAfterUiDelay(playerContext: PlayerContext
|
|
4
|
+
export declare function showNicamAfterUiDelay(playerContext: PlayerContext): void;
|
|
6
5
|
export declare function setupNicamKijkwijzerIcons(playerContext: PlayerContext): void;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { NpoPlayerEvent } from '../../types/events';
|
|
2
2
|
export function processNicam(playerContext, nicamElement) {
|
|
3
|
-
const streamOptions = playerContext.
|
|
4
|
-
const metadata = playerContext?.
|
|
3
|
+
const streamOptions = playerContext.npoPlayer.streamOptions;
|
|
4
|
+
const metadata = playerContext?.npoPlayer?.streamObject?.metadata ?? {};
|
|
5
5
|
const effectiveMetadata = { ...metadata, ...streamOptions };
|
|
6
6
|
if (nicamElement) {
|
|
7
7
|
nicamElement.innerHTML = '';
|
|
@@ -45,27 +45,28 @@ export function addNicamIcon(character, nicamElement) {
|
|
|
45
45
|
span.classList.add('nicam-icon', iconClass);
|
|
46
46
|
nicamElement.appendChild(span);
|
|
47
47
|
}
|
|
48
|
-
export function showNicamAfterUiDelay(playerContext
|
|
49
|
-
const player = playerContext
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
export function showNicamAfterUiDelay(playerContext) {
|
|
49
|
+
const { player, npoPlayer } = playerContext;
|
|
50
|
+
const { uiManager } = npoPlayer;
|
|
51
|
+
const showNicamClassName = 'bmpui-show-nicam';
|
|
52
|
+
const playerContainer = player.getNpoPlayerElement();
|
|
53
|
+
player.off(NpoPlayerEvent.Ready, () => {
|
|
54
|
+
npoPlayer.npoPlayerServices.showNicamAfterUiDelay(playerContext);
|
|
52
55
|
});
|
|
53
|
-
if (
|
|
56
|
+
if (!playerContainer || !uiManager)
|
|
54
57
|
return;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if (!playerContainer)
|
|
58
|
-
return;
|
|
59
|
-
uiManager?.activeUi.onControlsHide.subscribeOnce(() => {
|
|
60
|
-
const className = 'bmpui-show-nicam';
|
|
61
|
-
playerContainer.classList.add(className);
|
|
58
|
+
uiManager.activeUi.onControlsHide.subscribe(() => {
|
|
59
|
+
playerContainer.classList.add(showNicamClassName);
|
|
62
60
|
setTimeout(() => {
|
|
63
|
-
playerContainer.classList.remove(
|
|
61
|
+
playerContainer.classList.remove(showNicamClassName);
|
|
64
62
|
}, 3000);
|
|
65
63
|
});
|
|
64
|
+
uiManager?.activeUi.onControlsShow.subscribe(() => {
|
|
65
|
+
playerContainer.classList.remove(showNicamClassName);
|
|
66
|
+
});
|
|
66
67
|
}
|
|
67
68
|
export function setupNicamKijkwijzerIcons(playerContext) {
|
|
68
|
-
const { container } = playerContext.
|
|
69
|
+
const { container } = playerContext.npoPlayer;
|
|
69
70
|
const nicamElement = container.querySelector('.bmpui-nicam');
|
|
70
71
|
processNicam(playerContext, nicamElement);
|
|
71
72
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { processNicam } from './nicamhandler';
|
|
1
|
+
import { processNicam, showNicamAfterUiDelay } from './nicamhandler';
|
|
2
2
|
import '@testing-library/jest-dom';
|
|
3
3
|
import { createMockNpoPlayer, createPlayerContextMock } from '../../../tests/mocks/playerContextMock';
|
|
4
|
+
import { NpoPlayerEvent } from '../../types/events';
|
|
4
5
|
describe('NICAM Processing', () => {
|
|
5
6
|
let mockElement;
|
|
6
7
|
beforeEach(() => {
|
|
@@ -9,7 +10,7 @@ describe('NICAM Processing', () => {
|
|
|
9
10
|
});
|
|
10
11
|
it('processes NICAM from the streamObject', () => {
|
|
11
12
|
const mockElement = document.createElement('div');
|
|
12
|
-
const
|
|
13
|
+
const npoPlayerMock = createMockNpoPlayer({
|
|
13
14
|
streamObject: {
|
|
14
15
|
metadata: {
|
|
15
16
|
ageRating: '12',
|
|
@@ -18,14 +19,14 @@ describe('NICAM Processing', () => {
|
|
|
18
19
|
}
|
|
19
20
|
});
|
|
20
21
|
const playerContextMock = createPlayerContextMock({
|
|
21
|
-
|
|
22
|
+
npoPlayer: npoPlayerMock
|
|
22
23
|
});
|
|
23
24
|
processNicam(playerContextMock, mockElement);
|
|
24
25
|
expect(mockElement.children).toHaveLength(5);
|
|
25
26
|
});
|
|
26
27
|
it('processes NICAM and age rating with streamOptions taking priority', () => {
|
|
27
28
|
const mockElement = document.createElement('div');
|
|
28
|
-
const
|
|
29
|
+
const npoPlayerMock = createMockNpoPlayer({
|
|
29
30
|
streamObject: {
|
|
30
31
|
metadata: {
|
|
31
32
|
ageRating: '12',
|
|
@@ -38,14 +39,14 @@ describe('NICAM Processing', () => {
|
|
|
38
39
|
}
|
|
39
40
|
});
|
|
40
41
|
const playerContextMock = createPlayerContextMock({
|
|
41
|
-
|
|
42
|
+
npoPlayer: npoPlayerMock
|
|
42
43
|
});
|
|
43
44
|
processNicam(playerContextMock, mockElement);
|
|
44
45
|
expect(mockElement.children).toHaveLength(2);
|
|
45
46
|
});
|
|
46
47
|
it('does nothing if no NICAM element found', () => {
|
|
47
48
|
document.querySelector = jest.fn().mockReturnValue(undefined);
|
|
48
|
-
const
|
|
49
|
+
const npoPlayerMock = createMockNpoPlayer({
|
|
49
50
|
streamObject: {
|
|
50
51
|
metadata: {
|
|
51
52
|
ageRating: '12',
|
|
@@ -54,16 +55,78 @@ describe('NICAM Processing', () => {
|
|
|
54
55
|
}
|
|
55
56
|
});
|
|
56
57
|
const playerContextMock = createPlayerContextMock({
|
|
57
|
-
|
|
58
|
+
npoPlayer: npoPlayerMock
|
|
58
59
|
});
|
|
59
60
|
processNicam(playerContextMock, mockElement);
|
|
60
61
|
});
|
|
61
62
|
it('does nothing if no metadata and no streamOptions', () => {
|
|
62
|
-
const
|
|
63
|
+
const npoPlayerMock = createMockNpoPlayer({});
|
|
63
64
|
const playerContextMock = createPlayerContextMock({
|
|
64
|
-
|
|
65
|
+
npoPlayer: npoPlayerMock
|
|
65
66
|
});
|
|
66
67
|
processNicam(playerContextMock, mockElement);
|
|
67
68
|
expect(mockElement.appendChild).not.toHaveBeenCalled();
|
|
68
69
|
});
|
|
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;
|
|
@@ -38,7 +39,6 @@ export declare class NpoPlayerAPI {
|
|
|
38
39
|
getTimeShift(): number;
|
|
39
40
|
scheduleAds(adConfig: AdConfig): Promise<AdBreak[]>;
|
|
40
41
|
getActiveAdBreak(): AdBreak | null;
|
|
41
|
-
discardAdBreak(adBreakId: string): void;
|
|
42
42
|
getConfig(mergedConfig?: boolean): PlayerConfig;
|
|
43
43
|
createUIManager(playerContext: PlayerContext, variant: NpoPlayerUIVariants): Promise<void | UIManager>;
|
|
44
44
|
}
|