@gcorevideo/player 2.21.4 → 2.21.6
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/assets/dvr-controls/dvr_controls.scss +7 -25
- package/assets/dvr-controls/index.ejs +2 -2
- package/assets/media-control/media-control.scss +8 -3
- package/assets/media-control/width370.scss +1 -1
- package/assets/style/theme.scss +1 -1
- package/dist/core.js +1 -1
- package/dist/index.css +603 -608
- package/dist/index.js +78 -77
- package/dist/plugins/index.css +1073 -1078
- package/dist/plugins/index.js +77 -74
- package/lib/plugins/dvr-controls/DvrControls.d.ts +0 -3
- package/lib/plugins/dvr-controls/DvrControls.d.ts.map +1 -1
- package/lib/plugins/dvr-controls/DvrControls.js +13 -38
- package/lib/plugins/media-control/MediaControl.d.ts +10 -14
- package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
- package/lib/plugins/media-control/MediaControl.js +63 -37
- package/lib/testUtils.d.ts +4 -1
- package/lib/testUtils.d.ts.map +1 -1
- package/lib/testUtils.js +10 -11
- package/package.json +1 -1
- package/src/plugins/dvr-controls/DvrControls.ts +16 -44
- package/src/plugins/dvr-controls/__tests__/DvrControls.test.ts +18 -22
- package/src/plugins/dvr-controls/__tests__/__snapshots__/DvrControls.test.ts.snap +6 -30
- package/src/plugins/media-control/MediaControl.ts +88 -50
- package/src/plugins/media-control/__tests__/MediaControl.test.ts +89 -0
- package/src/plugins/media-control/__tests__/__snapshots__/MediaControl.test.ts.snap +124 -0
- package/src/testUtils.ts +10 -11
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -19,6 +19,12 @@ import volumeMaxIcon from '../../../assets/icons/new/volume-max.svg';
|
|
|
19
19
|
import volumeOffIcon from '../../../assets/icons/new/volume-off.svg';
|
|
20
20
|
import fullscreenOffIcon from '../../../assets/icons/new/fullscreen-off.svg';
|
|
21
21
|
import fullscreenOnIcon from '../../../assets/icons/new/fullscreen-on.svg';
|
|
22
|
+
const DEFAULT_SETTINGS = {
|
|
23
|
+
left: [],
|
|
24
|
+
right: [],
|
|
25
|
+
default: [],
|
|
26
|
+
seekEnabled: true,
|
|
27
|
+
};
|
|
22
28
|
/**
|
|
23
29
|
* Custom events emitted by the plugins to communicate with one another
|
|
24
30
|
* @beta
|
|
@@ -34,7 +40,8 @@ const T = 'plugins.media_control';
|
|
|
34
40
|
const LEFT_ORDER = [
|
|
35
41
|
'playpause',
|
|
36
42
|
'playstop',
|
|
37
|
-
'live',
|
|
43
|
+
// 'live',
|
|
44
|
+
'dvr',
|
|
38
45
|
'volume',
|
|
39
46
|
'position',
|
|
40
47
|
'duration',
|
|
@@ -68,14 +75,13 @@ export class MediaControl extends UICorePlugin {
|
|
|
68
75
|
hideId = null;
|
|
69
76
|
hideVolumeId = null;
|
|
70
77
|
intendedVolume = 100;
|
|
71
|
-
isHD = false;
|
|
72
78
|
keepVisible = false;
|
|
73
79
|
kibo;
|
|
74
80
|
lastMouseX = 0;
|
|
75
81
|
lastMouseY = 0;
|
|
76
82
|
persistConfig;
|
|
77
83
|
rendered = false;
|
|
78
|
-
settings =
|
|
84
|
+
settings = DEFAULT_SETTINGS;
|
|
79
85
|
userDisabled = false;
|
|
80
86
|
userKeepVisible = false;
|
|
81
87
|
verticalVolume = false;
|
|
@@ -219,8 +225,6 @@ export class MediaControl extends UICorePlugin {
|
|
|
219
225
|
* @internal
|
|
220
226
|
*/
|
|
221
227
|
bindEvents() {
|
|
222
|
-
// @ts-ignore
|
|
223
|
-
this.stopListening();
|
|
224
228
|
this.listenTo(this.core, Events.CORE_ACTIVE_CONTAINER_CHANGED, this.onActiveContainerChanged);
|
|
225
229
|
this.listenTo(this.core, Events.CORE_MOUSE_MOVE, this.show);
|
|
226
230
|
this.listenTo(this.core, Events.CORE_MOUSE_LEAVE, () => this.hide(this.options.hideMediaControlDelay));
|
|
@@ -257,8 +261,8 @@ export class MediaControl extends UICorePlugin {
|
|
|
257
261
|
this.listenTo(this.core.activeContainer, Events.CONTAINER_TIMEUPDATE, this.onTimeUpdate);
|
|
258
262
|
this.listenTo(this.core.activeContainer, Events.CONTAINER_PROGRESS, this.updateProgressBar);
|
|
259
263
|
this.listenTo(this.core.activeContainer, Events.CONTAINER_SETTINGSUPDATE, this.updateSettings);
|
|
260
|
-
this.listenTo(this.core.activeContainer, Events.CONTAINER_PLAYBACKDVRSTATECHANGED, this.
|
|
261
|
-
this.listenTo(this.core.activeContainer, Events.CONTAINER_HIGHDEFINITIONUPDATE, this.
|
|
264
|
+
this.listenTo(this.core.activeContainer, Events.CONTAINER_PLAYBACKDVRSTATECHANGED, this.onDvrStateChanged);
|
|
265
|
+
this.listenTo(this.core.activeContainer, Events.CONTAINER_HIGHDEFINITIONUPDATE, this.onHdUpdate);
|
|
262
266
|
this.listenTo(this.core.activeContainer, Events.CONTAINER_MEDIACONTROL_DISABLE, this.disable);
|
|
263
267
|
this.listenTo(this.core.activeContainer, Events.CONTAINER_MEDIACONTROL_ENABLE, this.enable);
|
|
264
268
|
this.listenTo(this.core.activeContainer, Events.CONTAINER_ENDED, this.ended);
|
|
@@ -306,7 +310,13 @@ export class MediaControl extends UICorePlugin {
|
|
|
306
310
|
// see https://github.com/clappr/clappr/issues/1127
|
|
307
311
|
if (!Fullscreen.fullscreenEnabled() && video.webkitSupportsFullscreen) {
|
|
308
312
|
this.fullScreenOnVideoTagSupported = true;
|
|
309
|
-
|
|
313
|
+
}
|
|
314
|
+
this.updateSettings();
|
|
315
|
+
if (this.core.activeContainer.getPlaybackType() === Playback.LIVE) {
|
|
316
|
+
this.$el.addClass('live');
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
this.$el.removeClass('live');
|
|
310
320
|
}
|
|
311
321
|
}
|
|
312
322
|
updateVolumeUI() {
|
|
@@ -315,8 +325,6 @@ export class MediaControl extends UICorePlugin {
|
|
|
315
325
|
return;
|
|
316
326
|
}
|
|
317
327
|
assert.ok(this.$volumeBarContainer, 'volume bar container must be present');
|
|
318
|
-
// update volume bar scrubber/fill on bar mode
|
|
319
|
-
// this.$volumeBarContainer.find('.bar-fill-2').css({});
|
|
320
328
|
const containerWidth = this.$volumeBarContainer.width();
|
|
321
329
|
assert.ok(this.$volumeBarBackground, 'volume bar background must be present');
|
|
322
330
|
const barWidth = this.$volumeBarBackground.width();
|
|
@@ -505,17 +513,18 @@ export class MediaControl extends UICorePlugin {
|
|
|
505
513
|
// if the container is not ready etc
|
|
506
514
|
this.intendedVolume = value;
|
|
507
515
|
this.persistConfig && !isInitialVolume && Config.persist('volume', value);
|
|
516
|
+
// TODO
|
|
508
517
|
const setWhenContainerReady = () => {
|
|
509
|
-
if (this.
|
|
510
|
-
this.
|
|
518
|
+
if (this.core.activeContainer && this.core.activeContainer.isReady) {
|
|
519
|
+
this.core.activeContainer.setVolume(value);
|
|
511
520
|
}
|
|
512
521
|
else {
|
|
513
|
-
this.listenToOnce(this.
|
|
514
|
-
this.
|
|
522
|
+
this.listenToOnce(this.core.activeContainer, Events.CONTAINER_READY, () => {
|
|
523
|
+
this.core.activeContainer.setVolume(value);
|
|
515
524
|
});
|
|
516
525
|
}
|
|
517
526
|
};
|
|
518
|
-
if (!this.
|
|
527
|
+
if (!this.core.activeContainer) {
|
|
519
528
|
this.listenToOnce(this, Events.MEDIACONTROL_CONTAINERCHANGED, () => setWhenContainerReady());
|
|
520
529
|
}
|
|
521
530
|
else {
|
|
@@ -525,7 +534,7 @@ export class MediaControl extends UICorePlugin {
|
|
|
525
534
|
toggleFullscreen() {
|
|
526
535
|
if (!Browser.isMobile) {
|
|
527
536
|
this.trigger(Events.MEDIACONTROL_FULLSCREEN, this.name);
|
|
528
|
-
this.
|
|
537
|
+
this.core.activeContainer.fullscreen();
|
|
529
538
|
this.core.toggleFullscreen();
|
|
530
539
|
this.resetUserKeepVisible();
|
|
531
540
|
}
|
|
@@ -537,6 +546,7 @@ export class MediaControl extends UICorePlugin {
|
|
|
537
546
|
this.changeTogglePlay();
|
|
538
547
|
this.bindContainerEvents();
|
|
539
548
|
this.updateSettings();
|
|
549
|
+
// TODO remove
|
|
540
550
|
this.core.activeContainer.trigger(Events.CONTAINER_PLAYBACKDVRSTATECHANGED, this.core.activeContainer.isDvrInUse());
|
|
541
551
|
// TODO test
|
|
542
552
|
if (this.core.activeContainer.mediaControlDisabled) {
|
|
@@ -607,9 +617,9 @@ export class MediaControl extends UICorePlugin {
|
|
|
607
617
|
}
|
|
608
618
|
// default to 100%
|
|
609
619
|
this.currentSeekBarPercentage = 100;
|
|
610
|
-
if (this.
|
|
611
|
-
(this.
|
|
612
|
-
this.
|
|
620
|
+
if (this.core.activeContainer &&
|
|
621
|
+
(this.core.activeContainer.getPlaybackType() !== Playback.LIVE ||
|
|
622
|
+
this.core.activeContainer.isDvrInUse())) {
|
|
613
623
|
this.currentSeekBarPercentage =
|
|
614
624
|
(this.currentPositionValue / this.currentDurationValue) * 100;
|
|
615
625
|
}
|
|
@@ -636,16 +646,10 @@ export class MediaControl extends UICorePlugin {
|
|
|
636
646
|
const offsetX = MediaControl.getPageX(event) - this.$seekBarContainer.offset().left;
|
|
637
647
|
let pos = (offsetX / this.$seekBarContainer.width()) * 100;
|
|
638
648
|
pos = Math.min(100, Math.max(pos, 0));
|
|
639
|
-
this.
|
|
649
|
+
this.core.activeContainer && this.core.activeContainer.seekPercentage(pos);
|
|
640
650
|
this.setSeekPercentage(pos);
|
|
641
651
|
return false;
|
|
642
652
|
}
|
|
643
|
-
setKeepVisible() {
|
|
644
|
-
this.keepVisible = true;
|
|
645
|
-
}
|
|
646
|
-
resetKeepVisible() {
|
|
647
|
-
this.keepVisible = false;
|
|
648
|
-
}
|
|
649
653
|
setUserKeepVisible() {
|
|
650
654
|
this.userKeepVisible = true;
|
|
651
655
|
}
|
|
@@ -723,7 +727,12 @@ export class MediaControl extends UICorePlugin {
|
|
|
723
727
|
default: [],
|
|
724
728
|
right: [],
|
|
725
729
|
}, this.core.activeContainer.settings);
|
|
730
|
+
// TODO make order controlled via CSS
|
|
726
731
|
newSettings.left = orderByOrderPattern([...newSettings.left, 'clipsText', 'volume'], LEFT_ORDER);
|
|
732
|
+
if (this.core.activePlayback.getPlaybackType() === Playback.LIVE &&
|
|
733
|
+
this.core.activePlayback.dvrEnabled) {
|
|
734
|
+
newSettings.left.push('dvr');
|
|
735
|
+
}
|
|
727
736
|
// actual order of the items appear rendered is controlled by CSS
|
|
728
737
|
newSettings.right = [
|
|
729
738
|
'fullscreen',
|
|
@@ -745,17 +754,18 @@ export class MediaControl extends UICorePlugin {
|
|
|
745
754
|
}
|
|
746
755
|
removeArrayItem(newSettings.default, 'hd-indicator');
|
|
747
756
|
removeArrayItem(newSettings.left, 'hd-indicator');
|
|
757
|
+
// TODO get from container's settings
|
|
748
758
|
if (this.core.activePlayback.name === 'html5_video') {
|
|
749
759
|
newSettings.seekEnabled = this.isSeekEnabledForHtml5Playback();
|
|
750
760
|
}
|
|
751
|
-
const settingsChanged =
|
|
761
|
+
const settingsChanged = serializeSettings(this.settings) !== serializeSettings(newSettings);
|
|
752
762
|
if (settingsChanged) {
|
|
753
763
|
this.settings = newSettings;
|
|
754
764
|
this.render();
|
|
755
765
|
}
|
|
756
766
|
}
|
|
757
|
-
|
|
758
|
-
|
|
767
|
+
onHdUpdate(isHD) {
|
|
768
|
+
// TODO render?
|
|
759
769
|
}
|
|
760
770
|
createCachedElements() {
|
|
761
771
|
const $layer = this.$el.find('.media-control-layer');
|
|
@@ -818,7 +828,7 @@ export class MediaControl extends UICorePlugin {
|
|
|
818
828
|
trace(`${T} putElement`, { name, panel: !!panel });
|
|
819
829
|
if (panel) {
|
|
820
830
|
const current = panel.find(`[data-${name}]`);
|
|
821
|
-
element.setAttribute(`data-${name}`,
|
|
831
|
+
element.setAttribute(`data-${name}`, '');
|
|
822
832
|
// TODO test
|
|
823
833
|
if (current.length) {
|
|
824
834
|
if (current[0] === element) {
|
|
@@ -832,16 +842,16 @@ export class MediaControl extends UICorePlugin {
|
|
|
832
842
|
}
|
|
833
843
|
}
|
|
834
844
|
/**
|
|
835
|
-
*
|
|
836
|
-
* @
|
|
845
|
+
* Toggle the visibility of a media control element
|
|
846
|
+
* @param name - The name of the media control element
|
|
847
|
+
* @param show - Whether to show or hide the element
|
|
837
848
|
*/
|
|
849
|
+
toggleElement(name, show) {
|
|
850
|
+
this.$el.find(`[data-${name}]`).toggle(show);
|
|
851
|
+
}
|
|
838
852
|
getRightPanel() {
|
|
839
853
|
return this.$el.find('.media-control-right-panel');
|
|
840
854
|
}
|
|
841
|
-
/**
|
|
842
|
-
* Get the left panel area to append custom elements to
|
|
843
|
-
* @returns ZeptoSelector of the left panel element
|
|
844
|
-
*/
|
|
845
855
|
getLeftPanel() {
|
|
846
856
|
return this.$el.find('.media-control-left-panel');
|
|
847
857
|
}
|
|
@@ -1040,7 +1050,6 @@ export class MediaControl extends UICorePlugin {
|
|
|
1040
1050
|
this.hideVolumeBar(0);
|
|
1041
1051
|
}, 0);
|
|
1042
1052
|
this.parseColors();
|
|
1043
|
-
this.highDefinitionUpdate(this.isHD);
|
|
1044
1053
|
this.core.$el.append(this.el);
|
|
1045
1054
|
this.rendered = true;
|
|
1046
1055
|
this.updateVolumeUI();
|
|
@@ -1127,7 +1136,24 @@ export class MediaControl extends UICorePlugin {
|
|
|
1127
1136
|
}
|
|
1128
1137
|
return null;
|
|
1129
1138
|
}
|
|
1139
|
+
onDvrStateChanged(dvrInUse) {
|
|
1140
|
+
if (dvrInUse) {
|
|
1141
|
+
this.$el.addClass('dvr');
|
|
1142
|
+
}
|
|
1143
|
+
else {
|
|
1144
|
+
this.$el.removeClass('dvr');
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1130
1147
|
}
|
|
1131
1148
|
MediaControl.extend = function (properties) {
|
|
1132
1149
|
return extend(MediaControl, properties);
|
|
1133
1150
|
};
|
|
1151
|
+
function serializeSettings(s) {
|
|
1152
|
+
return s.left
|
|
1153
|
+
.slice()
|
|
1154
|
+
.sort()
|
|
1155
|
+
.concat(s.right.slice().sort())
|
|
1156
|
+
.concat(s.default.slice().sort())
|
|
1157
|
+
.concat([s.seekEnabled])
|
|
1158
|
+
.join(',');
|
|
1159
|
+
}
|
package/lib/testUtils.d.ts
CHANGED
|
@@ -65,7 +65,9 @@ export declare function createSpinnerPlugin(): Events<string | symbol, any> & {
|
|
|
65
65
|
export declare function createMockPlayback(name?: string): Events<string | symbol, any> & {
|
|
66
66
|
name: string;
|
|
67
67
|
currentLevel: number;
|
|
68
|
+
el: HTMLVideoElement;
|
|
68
69
|
dvrEnabled: boolean;
|
|
70
|
+
dvrInUse: boolean;
|
|
69
71
|
levels: never[];
|
|
70
72
|
consent(): void;
|
|
71
73
|
play(): void;
|
|
@@ -92,13 +94,14 @@ export declare function createMockPlayback(name?: string): Events<string | symbo
|
|
|
92
94
|
trigger: <T extends string | symbol>(event: T, ...args: any[]) => boolean;
|
|
93
95
|
};
|
|
94
96
|
export declare function createMockContainer(playback?: any): Events<string | symbol, any> & {
|
|
95
|
-
el:
|
|
97
|
+
el: any;
|
|
96
98
|
playback: any;
|
|
97
99
|
$el: any;
|
|
98
100
|
getDuration: import("vitest").Mock<(...args: any[]) => any>;
|
|
99
101
|
getPlugin: import("vitest").Mock<(...args: any[]) => any>;
|
|
100
102
|
getPlaybackType: import("vitest").Mock<(...args: any[]) => any>;
|
|
101
103
|
isDvrInUse: import("vitest").Mock<(...args: any[]) => any>;
|
|
104
|
+
isDvrEnabled: import("vitest").Mock<(...args: any[]) => any>;
|
|
102
105
|
isPlaying: import("vitest").Mock<(...args: any[]) => any>;
|
|
103
106
|
play: import("vitest").Mock<(...args: any[]) => any>;
|
|
104
107
|
seek: import("vitest").Mock<(...args: any[]) => any>;
|
package/lib/testUtils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testUtils.d.ts","sourceRoot":"","sources":["../src/testUtils.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"testUtils.d.ts","sourceRoot":"","sources":["../src/testUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,YAAY,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,MAAM,MAAM,eAAe,CAAA;AAElC;;;;GAIG;AACH,qBAAa,aAAc,SAAQ,MAAM;IAErC,SAAS,CAAC,OAAO,EAAE,GAAG;IACtB,QAAQ,CAAC,IAAI,EAAE,GAAG;IAClB,SAAS,CAAC,WAAW,CAAC,EAAE,GAAG;gBAFjB,OAAO,EAAE,GAAG,EACb,IAAI,EAAE,GAAG,EACR,WAAW,CAAC,EAAE,GAAG,YAAA;IAK7B,IAAI,IAAI,WAEP;IAED,OAAO;IAEP,IAAI;IAEJ,KAAK;IAEL,IAAI;IAEJ,OAAO;IAEP,IAAI;IAEJ,cAAc;IAEd,WAAW;IAIX,QAAQ;IAER,OAAO;IAEP,eAAe;IAIf,kBAAkB;IAIlB,cAAc;IAId,qBAAqB;IAIrB,IAAI;IAEJ,MAAM;IAEN,MAAM;IAEN,SAAS;IAET,eAAe;IAIf,WAAW;IAIX,QAAQ;IAIR,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE;CAGtC;AAED,wBAAgB,cAAc,CAC5B,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACrC,SAAS,GAAE,GAA2B;;;;;;;;;;;;;;;;EAqBvC;AAED,wBAAgB,gBAAgB;;;EAK/B;AAED,wBAAgB,mBAAmB;;;;;;EAKlC;AAED,wBAAgB,kBAAkB,CAAC,IAAI,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiC/C;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,GAAE,GAA0B;;;;;;;;;;;;;EAiBvE;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,GAAG,gBAiB/C"}
|
package/lib/testUtils.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $, UICorePlugin } from '@clappr/core';
|
|
1
|
+
import { $, Playback, UICorePlugin } from '@clappr/core';
|
|
2
2
|
import Events from 'eventemitter3';
|
|
3
3
|
import { vi } from 'vitest';
|
|
4
4
|
/**
|
|
@@ -32,7 +32,7 @@ export class _MockPlayback extends Events {
|
|
|
32
32
|
enterPiP() { }
|
|
33
33
|
exitPiP() { }
|
|
34
34
|
getPlaybackType() {
|
|
35
|
-
return
|
|
35
|
+
return Playback.LIVE;
|
|
36
36
|
}
|
|
37
37
|
getStartTimeOffset() {
|
|
38
38
|
return 0;
|
|
@@ -75,7 +75,7 @@ export function createMockCore(options = {}, container = createMockContainer())
|
|
|
75
75
|
...options,
|
|
76
76
|
},
|
|
77
77
|
configure: vi.fn(),
|
|
78
|
-
getPlaybackType: vi.fn(),
|
|
78
|
+
getPlaybackType: vi.fn().mockReturnValue(Playback.LIVE),
|
|
79
79
|
getPlugin: vi.fn(),
|
|
80
80
|
load: vi.fn(),
|
|
81
81
|
trigger: emitter.emit,
|
|
@@ -98,7 +98,9 @@ export function createMockPlayback(name = 'mock') {
|
|
|
98
98
|
return Object.assign(emitter, {
|
|
99
99
|
name,
|
|
100
100
|
currentLevel: -1,
|
|
101
|
+
el: document.createElement('video'),
|
|
101
102
|
dvrEnabled: false,
|
|
103
|
+
dvrInUse: false,
|
|
102
104
|
levels: [],
|
|
103
105
|
consent() { },
|
|
104
106
|
play() { },
|
|
@@ -110,7 +112,7 @@ export function createMockPlayback(name = 'mock') {
|
|
|
110
112
|
getDuration: vi.fn().mockImplementation(() => 100),
|
|
111
113
|
enterPiP: vi.fn(),
|
|
112
114
|
exitPiP: vi.fn(),
|
|
113
|
-
getPlaybackType: vi.fn().mockImplementation(() =>
|
|
115
|
+
getPlaybackType: vi.fn().mockImplementation(() => Playback.LIVE),
|
|
114
116
|
getStartTimeOffset: vi.fn().mockImplementation(() => 0),
|
|
115
117
|
getCurrentTime: vi.fn().mockImplementation(() => 0),
|
|
116
118
|
isHighDefinitionInUse: vi.fn().mockImplementation(() => false),
|
|
@@ -126,7 +128,7 @@ export function createMockPlayback(name = 'mock') {
|
|
|
126
128
|
});
|
|
127
129
|
}
|
|
128
130
|
export function createMockContainer(playback = createMockPlayback()) {
|
|
129
|
-
const el =
|
|
131
|
+
const el = playback.el;
|
|
130
132
|
const emitter = new Events();
|
|
131
133
|
return Object.assign(emitter, {
|
|
132
134
|
el,
|
|
@@ -134,8 +136,9 @@ export function createMockContainer(playback = createMockPlayback()) {
|
|
|
134
136
|
$el: $(el),
|
|
135
137
|
getDuration: vi.fn().mockReturnValue(0),
|
|
136
138
|
getPlugin: vi.fn(),
|
|
137
|
-
getPlaybackType: vi.fn().mockReturnValue(
|
|
139
|
+
getPlaybackType: vi.fn().mockReturnValue(Playback.LIVE),
|
|
138
140
|
isDvrInUse: vi.fn().mockReturnValue(false),
|
|
141
|
+
isDvrEnabled: vi.fn().mockReturnValue(false),
|
|
139
142
|
isPlaying: vi.fn().mockReturnValue(false),
|
|
140
143
|
play: vi.fn(),
|
|
141
144
|
seek: vi.fn(),
|
|
@@ -155,10 +158,6 @@ export function createMockMediaControl(core) {
|
|
|
155
158
|
// @ts-ignore
|
|
156
159
|
mediaControl.putElement = vi.fn();
|
|
157
160
|
// @ts-ignore
|
|
158
|
-
mediaControl.
|
|
159
|
-
// @ts-ignore
|
|
160
|
-
mediaControl.getRightPanel = vi.fn().mockImplementation(() => mediaControl.$el.find('.media-control-right-panel'));
|
|
161
|
-
// @ts-ignore
|
|
162
|
-
mediaControl.getCenterPanel = vi.fn().mockImplementation(() => mediaControl.$el.find('.media-control-center-panel'));
|
|
161
|
+
mediaControl.toggleElement = vi.fn();
|
|
163
162
|
return mediaControl;
|
|
164
163
|
}
|
package/package.json
CHANGED
|
@@ -56,7 +56,6 @@ export class DvrControls extends UICorePlugin {
|
|
|
56
56
|
override get attributes() {
|
|
57
57
|
return {
|
|
58
58
|
class: 'dvr-controls',
|
|
59
|
-
'data-dvr-controls': '',
|
|
60
59
|
}
|
|
61
60
|
}
|
|
62
61
|
|
|
@@ -65,7 +64,6 @@ export class DvrControls extends UICorePlugin {
|
|
|
65
64
|
*/
|
|
66
65
|
override bindEvents() {
|
|
67
66
|
this.listenTo(this.core, Events.CORE_READY, this.onCoreReady)
|
|
68
|
-
this.listenTo(this.core, Events.CORE_OPTIONS_CHANGE, this.render)
|
|
69
67
|
this.listenTo(
|
|
70
68
|
this.core,
|
|
71
69
|
Events.CORE_ACTIVE_CONTAINER_CHANGED,
|
|
@@ -76,48 +74,23 @@ export class DvrControls extends UICorePlugin {
|
|
|
76
74
|
private onCoreReady() {
|
|
77
75
|
const mediaControl = this.core.getPlugin('media_control')
|
|
78
76
|
assert(mediaControl, 'media_control plugin is required')
|
|
77
|
+
|
|
79
78
|
this.listenTo(
|
|
80
79
|
mediaControl,
|
|
81
80
|
Events.MEDIACONTROL_RENDERED,
|
|
82
|
-
this.
|
|
81
|
+
this.render,
|
|
83
82
|
)
|
|
84
|
-
|
|
83
|
+
// MediaControl has been rendered
|
|
84
|
+
this.render()
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
private bindContainerEvents() {
|
|
88
|
+
trace(`${T} bindContainerEvents`)
|
|
88
89
|
this.listenToOnce(
|
|
89
90
|
this.core.activeContainer,
|
|
90
91
|
Events.CONTAINER_TIMEUPDATE,
|
|
91
92
|
this.render,
|
|
92
93
|
)
|
|
93
|
-
this.listenTo(
|
|
94
|
-
this.core.activeContainer,
|
|
95
|
-
Events.CONTAINER_PLAYBACKDVRSTATECHANGED,
|
|
96
|
-
this.onDvrChanged,
|
|
97
|
-
)
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
private onDvrChanged(dvrInUse: boolean) {
|
|
101
|
-
trace(`${T} onDvrChanged`, {
|
|
102
|
-
dvrInUse,
|
|
103
|
-
})
|
|
104
|
-
if (this.core.getPlaybackType() !== Playback.LIVE) {
|
|
105
|
-
return
|
|
106
|
-
}
|
|
107
|
-
this.render()
|
|
108
|
-
const mediaControl = this.core.getPlugin('media_control')
|
|
109
|
-
mediaControl.$el.addClass('live')
|
|
110
|
-
if (dvrInUse) {
|
|
111
|
-
mediaControl.$el
|
|
112
|
-
.addClass('dvr')
|
|
113
|
-
.find(
|
|
114
|
-
// TODO add API, test
|
|
115
|
-
'.media-control-indicator[data-position], .media-control-indicator[data-duration]',
|
|
116
|
-
)
|
|
117
|
-
.hide()
|
|
118
|
-
} else {
|
|
119
|
-
mediaControl.$el.removeClass('dvr')
|
|
120
|
-
}
|
|
121
94
|
}
|
|
122
95
|
|
|
123
96
|
private click() {
|
|
@@ -128,14 +101,8 @@ export class DvrControls extends UICorePlugin {
|
|
|
128
101
|
container.seek(container.getDuration())
|
|
129
102
|
}
|
|
130
103
|
|
|
131
|
-
private settingsUpdate() {
|
|
132
|
-
this.core.getPlugin('media_control').$el.removeClass('live')
|
|
133
|
-
this.render()
|
|
134
|
-
}
|
|
135
|
-
|
|
136
104
|
private shouldRender() {
|
|
137
|
-
|
|
138
|
-
return useDvrControls && this.core.getPlaybackType() === Playback.LIVE
|
|
105
|
+
return this.core.getPlaybackType() === Playback.LIVE
|
|
139
106
|
}
|
|
140
107
|
|
|
141
108
|
/**
|
|
@@ -146,18 +113,23 @@ export class DvrControls extends UICorePlugin {
|
|
|
146
113
|
dvrEnabled: this.core.activePlayback?.dvrEnabled,
|
|
147
114
|
playbackType: this.core.getPlaybackType(),
|
|
148
115
|
})
|
|
116
|
+
const mediaControl = this.core.getPlugin('media_control') as MediaControl
|
|
117
|
+
if (!mediaControl) {
|
|
118
|
+
return this
|
|
119
|
+
}
|
|
149
120
|
if (!this.shouldRender()) {
|
|
150
121
|
return this
|
|
151
122
|
}
|
|
123
|
+
|
|
124
|
+
mediaControl.toggleElement('duration', false)
|
|
125
|
+
mediaControl.toggleElement('position', false)
|
|
126
|
+
|
|
152
127
|
this.$el.html(
|
|
153
128
|
DvrControls.template({
|
|
154
|
-
|
|
155
|
-
backToLive: this.core.i18n.t('back_to_live'),
|
|
129
|
+
i18n: this.core.i18n,
|
|
156
130
|
}),
|
|
157
131
|
)
|
|
158
|
-
|
|
159
|
-
mediaControl.$el.addClass('live')
|
|
160
|
-
mediaControl.getLeftPanel().append(this.$el)
|
|
132
|
+
mediaControl.putElement('dvr', this.el)
|
|
161
133
|
|
|
162
134
|
return this
|
|
163
135
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
2
2
|
import { DvrControls } from '../DvrControls.js'
|
|
3
3
|
import { createMockCore, createMockMediaControl } from '../../../testUtils.js'
|
|
4
|
+
import { Events, Playback } from '@clappr/core'
|
|
4
5
|
// import { LogTracer, Logger, setTracer } from '@gcorevideo/utils'
|
|
5
6
|
|
|
6
7
|
// setTracer(new LogTracer('DvrControls.test'))
|
|
@@ -28,36 +29,29 @@ describe('DvrControls', () => {
|
|
|
28
29
|
describe.each([
|
|
29
30
|
['no DVR', false, false, false],
|
|
30
31
|
['DVR at live edge', true, false, false],
|
|
31
|
-
|
|
32
|
-
])('%s', (_, dvrEnabled, dvrInUse, indicateDvr) => {
|
|
32
|
+
])('%s', (_, dvrEnabled, dvrInUse) => {
|
|
33
33
|
beforeEach(() => {
|
|
34
34
|
core.activePlayback.dvrEnabled = dvrEnabled
|
|
35
|
-
core.
|
|
36
|
-
core.trigger(
|
|
35
|
+
core.activeContainer.isDvrEnabled.mockReturnValue(dvrEnabled)
|
|
36
|
+
core.trigger(Events.CORE_READY)
|
|
37
|
+
core.trigger(Events.CORE_ACTIVE_CONTAINER_CHANGED, core.activeContainer)
|
|
37
38
|
if (dvrInUse) {
|
|
38
|
-
core.
|
|
39
|
+
core.activePlayback.dvrInUse = true
|
|
40
|
+
core.activeContainer.isDvrInUse.mockReturnValue(true)
|
|
41
|
+
core.activeContainer.emit(Events.CONTAINER_PLAYBACKDVRSTATECHANGED, true)
|
|
39
42
|
}
|
|
40
43
|
})
|
|
41
44
|
it('should render', () => {
|
|
42
45
|
expect(dvrControls.el.textContent).toBeTruthy()
|
|
43
46
|
expect(dvrControls.el.innerHTML).toMatchSnapshot()
|
|
44
47
|
})
|
|
45
|
-
it('should
|
|
46
|
-
expect(mediaControl
|
|
47
|
-
expect(mediaControl.
|
|
48
|
+
it('should hide duration and position indicators', () => {
|
|
49
|
+
expect(mediaControl.toggleElement).toHaveBeenCalledWith('duration', false)
|
|
50
|
+
expect(mediaControl.toggleElement).toHaveBeenCalledWith('position', false)
|
|
48
51
|
})
|
|
49
|
-
it('should
|
|
50
|
-
expect(mediaControl
|
|
52
|
+
it('should render to the media control', () => {
|
|
53
|
+
expect(mediaControl.putElement).toHaveBeenCalledWith('dvr', dvrControls.el)
|
|
51
54
|
})
|
|
52
|
-
if (indicateDvr) {
|
|
53
|
-
it('should indicate DVR mode', () => {
|
|
54
|
-
expect(mediaControl.$el.hasClass('dvr')).toBe(true)
|
|
55
|
-
})
|
|
56
|
-
} else {
|
|
57
|
-
it('should not indicate DVR mode', () => {
|
|
58
|
-
expect(mediaControl.$el.hasClass('dvr')).toBe(false)
|
|
59
|
-
})
|
|
60
|
-
}
|
|
61
55
|
})
|
|
62
56
|
describe('when back_to_live button is clicked', () => {
|
|
63
57
|
beforeEach(() => {
|
|
@@ -78,11 +72,13 @@ describe('DvrControls', () => {
|
|
|
78
72
|
})
|
|
79
73
|
describe('VOD stream', () => {
|
|
80
74
|
beforeEach(() => {
|
|
81
|
-
core.getPlaybackType.mockReturnValue(
|
|
75
|
+
core.getPlaybackType.mockReturnValue(Playback.VOD)
|
|
76
|
+
core.activeContainer.getPlaybackType.mockReturnValue(Playback.VOD)
|
|
77
|
+
core.activePlayback.getPlaybackType.mockReturnValue(Playback.VOD)
|
|
82
78
|
})
|
|
83
79
|
beforeEach(() => {
|
|
84
|
-
core.trigger(
|
|
85
|
-
core.trigger(
|
|
80
|
+
core.trigger(Events.CORE_READY)
|
|
81
|
+
core.trigger(Events.CORE_ACTIVE_CONTAINER_CHANGED, core.activeContainer)
|
|
86
82
|
})
|
|
87
83
|
it('should not render', () => {
|
|
88
84
|
expect(dvrControls.el.textContent).toBeFalsy()
|
|
@@ -1,43 +1,19 @@
|
|
|
1
1
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
2
|
|
|
3
3
|
exports[`DvrControls > live stream > DVR at live edge > should render 1`] = `
|
|
4
|
-
"<div class="live-info">live</div>
|
|
5
|
-
<button type="button" class="live-button" aria-label="back_to_live">back_to_live</button>
|
|
4
|
+
"<div class="live-info" id="media-control-live">live</div>
|
|
5
|
+
<button type="button" class="live-button" aria-label="back_to_live" id="media-control-back-to-live">back_to_live</button>
|
|
6
6
|
"
|
|
7
7
|
`;
|
|
8
8
|
|
|
9
|
-
exports[`DvrControls > live stream > DVR at live edge > should render to the media control left panel 1`] = `
|
|
10
|
-
"<div class="media-control-left-panel" data-media-control=""><div class="dvr-controls" data-dvr-controls=""><div class="live-info">live</div>
|
|
11
|
-
<button type="button" class="live-button" aria-label="back_to_live">back_to_live</button>
|
|
12
|
-
</div></div>
|
|
13
|
-
<div class="media-control-right-panel" data-media-control=""></div>
|
|
14
|
-
<div class="media-control-center-panel" data-media-control=""></div>"
|
|
15
|
-
`;
|
|
16
|
-
|
|
17
9
|
exports[`DvrControls > live stream > DVR behind live edge > should render 1`] = `
|
|
18
|
-
"<div class="live-info">live</div>
|
|
19
|
-
<button type="button" class="live-button" aria-label="back_to_live">back_to_live</button>
|
|
10
|
+
"<div class="live-info" id="media-control-live">live</div>
|
|
11
|
+
<button type="button" class="live-button" aria-label="back_to_live" id="media-control-back-to-live">back_to_live</button>
|
|
20
12
|
"
|
|
21
13
|
`;
|
|
22
14
|
|
|
23
|
-
exports[`DvrControls > live stream > DVR behind live edge > should render to the media control left panel 1`] = `
|
|
24
|
-
"<div class="media-control-left-panel" data-media-control=""><div class="dvr-controls" data-dvr-controls=""><div class="live-info">live</div>
|
|
25
|
-
<button type="button" class="live-button" aria-label="back_to_live">back_to_live</button>
|
|
26
|
-
</div></div>
|
|
27
|
-
<div class="media-control-right-panel" data-media-control=""></div>
|
|
28
|
-
<div class="media-control-center-panel" data-media-control=""></div>"
|
|
29
|
-
`;
|
|
30
|
-
|
|
31
15
|
exports[`DvrControls > live stream > no DVR > should render 1`] = `
|
|
32
|
-
"<div class="live-info">live</div>
|
|
33
|
-
<button type="button" class="live-button" aria-label="back_to_live">back_to_live</button>
|
|
16
|
+
"<div class="live-info" id="media-control-live">live</div>
|
|
17
|
+
<button type="button" class="live-button" aria-label="back_to_live" id="media-control-back-to-live">back_to_live</button>
|
|
34
18
|
"
|
|
35
19
|
`;
|
|
36
|
-
|
|
37
|
-
exports[`DvrControls > live stream > no DVR > should render to the media control left panel 1`] = `
|
|
38
|
-
"<div class="media-control-left-panel" data-media-control=""><div class="dvr-controls" data-dvr-controls=""><div class="live-info">live</div>
|
|
39
|
-
<button type="button" class="live-button" aria-label="back_to_live">back_to_live</button>
|
|
40
|
-
</div></div>
|
|
41
|
-
<div class="media-control-right-panel" data-media-control=""></div>
|
|
42
|
-
<div class="media-control-center-panel" data-media-control=""></div>"
|
|
43
|
-
`;
|