@gcorevideo/player 2.21.3 → 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/audio-selector/style.scss +1 -1
- package/assets/audio-selector/track-selector.ejs +3 -3
- package/assets/bottom-gear/bottomgear.ejs +2 -2
- package/assets/dvr-controls/dvr_controls.scss +7 -25
- package/assets/dvr-controls/index.ejs +2 -2
- package/assets/media-control/container.scss +1 -1
- package/assets/media-control/media-control.ejs +1 -6
- package/assets/media-control/media-control.scss +14 -7
- package/assets/media-control/width270.scss +1 -1
- package/assets/media-control/width370.scss +5 -5
- package/assets/playback-rate/button.ejs +2 -2
- package/assets/playback-rate/list.ejs +4 -4
- package/assets/style/theme.scss +1 -1
- package/assets/subtitles/combobox.ejs +5 -5
- package/assets/subtitles/string.ejs +1 -1
- package/assets/subtitles/style.scss +2 -2
- package/dist/core.js +2 -1
- package/dist/index.css +993 -993
- package/dist/index.js +199 -178
- package/dist/player.d.ts +141 -119
- package/dist/plugins/index.css +1118 -1118
- package/dist/plugins/index.js +191 -173
- package/docs/api/player.bottomgear.getelement.md +2 -2
- package/docs/api/player.bottomgear.md +1 -1
- package/docs/api/{player.subtitles.hide.md → player.closedcaptions.hide.md} +2 -2
- package/docs/api/{player.subtitles.md → player.closedcaptions.md} +11 -11
- package/docs/api/{player.subtitles.show.md → player.closedcaptions.show.md} +2 -2
- package/docs/api/player.closedcaptionspluginsettings.md +13 -0
- package/docs/api/player.gearitemelement.md +6 -4
- package/docs/api/player.gearoptionsitem.md +16 -0
- package/docs/api/player.md +48 -12
- package/docs/api/player.mediacontrol.putelement.md +2 -2
- package/docs/api/player.mediacontrolelement.md +1 -1
- package/docs/api/player.playbackrate.md +1 -1
- package/docs/api/player.subtitlespluginsettings.md +18 -0
- package/docs/api/player.texttrackitem.id.md +11 -0
- package/docs/api/player.texttrackitem.md +87 -0
- package/docs/api/player.texttrackitem.name.md +11 -0
- package/docs/api/player.texttrackitem.track.md +11 -0
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/index.plugins.d.ts +2 -1
- package/lib/index.plugins.d.ts.map +1 -1
- package/lib/index.plugins.js +2 -1
- package/lib/playback/dash-playback/DashPlayback.d.ts.map +1 -1
- package/lib/playback/dash-playback/DashPlayback.js +1 -0
- package/lib/plugins/audio-selector/AudioSelector.d.ts +2 -3
- package/lib/plugins/audio-selector/AudioSelector.d.ts.map +1 -1
- package/lib/plugins/audio-selector/AudioSelector.js +6 -7
- package/lib/plugins/bottom-gear/BottomGear.d.ts +6 -2
- package/lib/plugins/bottom-gear/BottomGear.d.ts.map +1 -1
- package/lib/plugins/bottom-gear/BottomGear.js +2 -1
- 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 +14 -18
- package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
- package/lib/plugins/media-control/MediaControl.js +105 -72
- package/lib/plugins/picture-in-picture/PictureInPicture.d.ts +1 -0
- package/lib/plugins/picture-in-picture/PictureInPicture.d.ts.map +1 -1
- package/lib/plugins/picture-in-picture/PictureInPicture.js +4 -4
- package/lib/plugins/playback-rate/PlaybackRate.d.ts +0 -1
- package/lib/plugins/playback-rate/PlaybackRate.d.ts.map +1 -1
- package/lib/plugins/playback-rate/PlaybackRate.js +23 -14
- package/lib/plugins/subtitles/ClosedCaptions.d.ts +118 -0
- package/lib/plugins/subtitles/ClosedCaptions.d.ts.map +1 -0
- package/lib/plugins/subtitles/ClosedCaptions.js +348 -0
- package/lib/plugins/subtitles/Subtitles.d.ts +12 -9
- package/lib/plugins/subtitles/Subtitles.d.ts.map +1 -1
- package/lib/plugins/subtitles/Subtitles.js +31 -32
- package/lib/testUtils.d.ts +26 -19
- package/lib/testUtils.d.ts.map +1 -1
- package/lib/testUtils.js +30 -45
- package/package.json +1 -1
- package/src/index.plugins.ts +2 -1
- package/src/index.ts +1 -1
- package/src/playback/dash-playback/DashPlayback.ts +1 -0
- package/src/plugins/audio-selector/AudioSelector.ts +9 -8
- package/src/plugins/bottom-gear/BottomGear.ts +11 -4
- package/src/plugins/bottom-gear/__tests__/BottomGear.test.ts +1 -1
- package/src/plugins/bottom-gear/__tests__/__snapshots__/BottomGear.test.ts.snap +2 -2
- 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 +130 -85
- package/src/plugins/media-control/__tests__/MediaControl.test.ts +132 -0
- package/src/plugins/media-control/__tests__/__snapshots__/MediaControl.test.ts.snap +299 -0
- package/src/plugins/picture-in-picture/PictureInPicture.ts +5 -5
- package/src/plugins/playback-rate/PlaybackRate.ts +142 -100
- package/src/plugins/playback-rate/__tests__/PlaybackRate.test.ts +65 -0
- package/src/plugins/playback-rate/__tests__/__snapshots__/PlaybackRate.test.ts.snap +11 -0
- package/src/plugins/subtitles/{Subtitles.ts → ClosedCaptions.ts} +42 -34
- package/src/plugins/subtitles/__tests__/ClosedCaptions.test.ts +58 -0
- package/src/plugins/subtitles/__tests__/__snapshots__/ClosedCaptions.test.ts.snap +25 -0
- package/src/testUtils.ts +30 -45
- package/temp/player.api.json +269 -89
- package/tsconfig.tsbuildinfo +1 -1
- package/src/plugins/index.ts +0 -39
|
@@ -9,8 +9,8 @@ import comboboxHTML from '../../../assets/subtitles/combobox.ejs';
|
|
|
9
9
|
import stringHTML from '../../../assets/subtitles/string.ejs';
|
|
10
10
|
import { isFullscreen } from '../utils.js';
|
|
11
11
|
const VERSION = '2.19.14';
|
|
12
|
-
const
|
|
13
|
-
const T = 'plugins.
|
|
12
|
+
const LOCAL_STORAGE_CC_ID = 'gplayer.plugins.cc.selected';
|
|
13
|
+
const T = 'plugins.cc';
|
|
14
14
|
/**
|
|
15
15
|
* `PLUGIN` that provides a UI to select the subtitles when available.
|
|
16
16
|
* @beta
|
|
@@ -20,16 +20,16 @@ const T = 'plugins.subtitles';
|
|
|
20
20
|
*
|
|
21
21
|
* - {@link MediaControl}
|
|
22
22
|
*
|
|
23
|
-
* Configuration options - {@link
|
|
23
|
+
* Configuration options - {@link ClosedCaptionsPluginSettings}
|
|
24
24
|
* @example
|
|
25
25
|
* ```ts
|
|
26
|
-
* import {
|
|
26
|
+
* import { ClosedCaptions } from '@gcorevideo/player'
|
|
27
27
|
*
|
|
28
|
-
* Player.registerPlugin(
|
|
28
|
+
* Player.registerPlugin(ClosedCaptions)
|
|
29
29
|
*
|
|
30
30
|
* new Player({
|
|
31
31
|
* ...
|
|
32
|
-
*
|
|
32
|
+
* cc: {
|
|
33
33
|
* language: 'en',
|
|
34
34
|
* },
|
|
35
35
|
* })
|
|
@@ -40,12 +40,12 @@ export class Subtitles extends UICorePlugin {
|
|
|
40
40
|
isShowing = false;
|
|
41
41
|
track = null;
|
|
42
42
|
tracks = [];
|
|
43
|
-
$
|
|
43
|
+
$line = null;
|
|
44
44
|
/**
|
|
45
45
|
* @internal
|
|
46
46
|
*/
|
|
47
47
|
get name() {
|
|
48
|
-
return 'subtitles';
|
|
48
|
+
return 'subtitles'; // TODO rename to 'cc'
|
|
49
49
|
}
|
|
50
50
|
/**
|
|
51
51
|
* @internal
|
|
@@ -66,8 +66,7 @@ export class Subtitles extends UICorePlugin {
|
|
|
66
66
|
*/
|
|
67
67
|
get attributes() {
|
|
68
68
|
return {
|
|
69
|
-
class: 'media-control-
|
|
70
|
-
'data-subtitles': '',
|
|
69
|
+
class: 'media-control-cc',
|
|
71
70
|
};
|
|
72
71
|
}
|
|
73
72
|
/**
|
|
@@ -75,12 +74,12 @@ export class Subtitles extends UICorePlugin {
|
|
|
75
74
|
*/
|
|
76
75
|
get events() {
|
|
77
76
|
return {
|
|
78
|
-
'click [data-
|
|
79
|
-
'click [data-
|
|
77
|
+
'click [data-cc-select]': 'onItemSelect',
|
|
78
|
+
'click [data-cc-button]': 'toggleMenu',
|
|
80
79
|
};
|
|
81
80
|
}
|
|
82
81
|
get preselectedLanguage() {
|
|
83
|
-
return this.core.options.subtitles?.language ?? '';
|
|
82
|
+
return this.core.options.cc?.language ?? this.core.options.subtitles?.language ?? '';
|
|
84
83
|
}
|
|
85
84
|
/**
|
|
86
85
|
* @internal
|
|
@@ -195,7 +194,7 @@ export class Subtitles extends UICorePlugin {
|
|
|
195
194
|
hide() {
|
|
196
195
|
this.isShowing = false;
|
|
197
196
|
this.renderIcon();
|
|
198
|
-
this.$
|
|
197
|
+
this.$line.hide();
|
|
199
198
|
if (this.tracks) {
|
|
200
199
|
for (const t of this.tracks) {
|
|
201
200
|
t.track.mode = 'hidden';
|
|
@@ -213,22 +212,22 @@ export class Subtitles extends UICorePlugin {
|
|
|
213
212
|
this.track &&
|
|
214
213
|
this.track.track.mode &&
|
|
215
214
|
Browser.isiOS) {
|
|
216
|
-
this.$
|
|
215
|
+
this.$line.hide();
|
|
217
216
|
this.track.track.mode = 'showing';
|
|
218
217
|
}
|
|
219
218
|
else {
|
|
220
|
-
this.$
|
|
219
|
+
this.$line.show();
|
|
221
220
|
}
|
|
222
221
|
}
|
|
223
222
|
shouldRender() {
|
|
224
|
-
return this.tracks
|
|
223
|
+
return this.tracks?.length > 0;
|
|
225
224
|
}
|
|
226
225
|
resizeFont() {
|
|
227
|
-
if (!this.$
|
|
226
|
+
if (!this.$line) {
|
|
228
227
|
return;
|
|
229
228
|
}
|
|
230
229
|
const skinWidth = this.core.activeContainer.$el.width();
|
|
231
|
-
this.$
|
|
230
|
+
this.$line.find('p').css('font-size', skinWidth * 0.03);
|
|
232
231
|
}
|
|
233
232
|
/**
|
|
234
233
|
* @internal
|
|
@@ -242,11 +241,11 @@ export class Subtitles extends UICorePlugin {
|
|
|
242
241
|
}
|
|
243
242
|
const mediaControl = this.core.getPlugin('media_control');
|
|
244
243
|
this.$el.html(Subtitles.template({ tracks: this.tracks }));
|
|
245
|
-
this.core.activeContainer.$el.find('
|
|
246
|
-
this.$
|
|
244
|
+
this.core.activeContainer.$el.find('#cc-line').remove();
|
|
245
|
+
this.$line = $(Subtitles.templateString());
|
|
247
246
|
this.resizeFont();
|
|
248
|
-
this.core.activeContainer.$el.append(this.$
|
|
249
|
-
mediaControl.putElement('
|
|
247
|
+
this.core.activeContainer.$el.append(this.$line);
|
|
248
|
+
mediaControl.putElement('cc', this.el);
|
|
250
249
|
this.updateSelection();
|
|
251
250
|
this.renderIcon();
|
|
252
251
|
return this;
|
|
@@ -261,9 +260,9 @@ export class Subtitles extends UICorePlugin {
|
|
|
261
260
|
this.updateSelection();
|
|
262
261
|
}
|
|
263
262
|
onItemSelect(event) {
|
|
264
|
-
const id = event.target.dataset.
|
|
263
|
+
const id = event.target.dataset.ccSelect ?? '-1';
|
|
265
264
|
trace(`${T} onItemSelect`, { id });
|
|
266
|
-
localStorage.setItem(
|
|
265
|
+
localStorage.setItem(LOCAL_STORAGE_CC_ID, id);
|
|
267
266
|
this.selectItem(this.findById(Number(id)));
|
|
268
267
|
return false;
|
|
269
268
|
}
|
|
@@ -280,17 +279,17 @@ export class Subtitles extends UICorePlugin {
|
|
|
280
279
|
}
|
|
281
280
|
hideMenu() {
|
|
282
281
|
;
|
|
283
|
-
this.$('[data-
|
|
282
|
+
this.$('[data-cc] ul').hide();
|
|
284
283
|
}
|
|
285
284
|
toggleMenu() {
|
|
286
|
-
;
|
|
287
|
-
this.$('[data-
|
|
285
|
+
trace(`${T} toggleMenu`);
|
|
286
|
+
this.$('[data-cc] ul').toggle();
|
|
288
287
|
}
|
|
289
288
|
itemElement(id) {
|
|
290
|
-
return this.$(`ul li a[data-
|
|
289
|
+
return this.$(`ul li a[data-cc-select="${id}"]`).parent();
|
|
291
290
|
}
|
|
292
291
|
allItemElements() {
|
|
293
|
-
return this.$('[data-
|
|
292
|
+
return this.$('[data-cc] li');
|
|
294
293
|
}
|
|
295
294
|
selectSubtitles() {
|
|
296
295
|
const trackId = this.track ? this.track.id : -1;
|
|
@@ -310,7 +309,7 @@ export class Subtitles extends UICorePlugin {
|
|
|
310
309
|
return lines.join('\n');
|
|
311
310
|
}
|
|
312
311
|
setSubtitleText(text) {
|
|
313
|
-
this.$
|
|
312
|
+
this.$line.find('p').html(text);
|
|
314
313
|
}
|
|
315
314
|
clearSubtitleText() {
|
|
316
315
|
this.setSubtitleText('');
|
|
@@ -341,6 +340,6 @@ export class Subtitles extends UICorePlugin {
|
|
|
341
340
|
}
|
|
342
341
|
renderIcon() {
|
|
343
342
|
const icon = this.isShowing ? subtitlesOnIcon : subtitlesOffIcon;
|
|
344
|
-
this.$el.find('span.
|
|
343
|
+
this.$el.find('span.cc-text').html(icon);
|
|
345
344
|
}
|
|
346
345
|
}
|
package/lib/testUtils.d.ts
CHANGED
|
@@ -65,36 +65,43 @@ 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;
|
|
69
|
+
dvrEnabled: boolean;
|
|
70
|
+
dvrInUse: boolean;
|
|
68
71
|
levels: never[];
|
|
69
72
|
consent(): void;
|
|
70
73
|
play(): void;
|
|
71
74
|
pause(): void;
|
|
72
75
|
stop(): void;
|
|
73
|
-
destroy():
|
|
74
|
-
seek():
|
|
75
|
-
seekPercentage():
|
|
76
|
-
getDuration():
|
|
77
|
-
enterPiP():
|
|
78
|
-
exitPiP():
|
|
79
|
-
getPlaybackType():
|
|
80
|
-
getStartTimeOffset():
|
|
81
|
-
getCurrentTime():
|
|
82
|
-
isHighDefinitionInUse():
|
|
83
|
-
mute():
|
|
84
|
-
unmute():
|
|
85
|
-
volume():
|
|
86
|
-
configure():
|
|
87
|
-
attemptAutoPlay():
|
|
88
|
-
canAutoPlay():
|
|
89
|
-
onResize():
|
|
90
|
-
|
|
76
|
+
destroy: import("vitest").Mock<(...args: any[]) => any>;
|
|
77
|
+
seek: import("vitest").Mock<(...args: any[]) => any>;
|
|
78
|
+
seekPercentage: import("vitest").Mock<(...args: any[]) => any>;
|
|
79
|
+
getDuration: import("vitest").Mock<(...args: any[]) => any>;
|
|
80
|
+
enterPiP: import("vitest").Mock<(...args: any[]) => any>;
|
|
81
|
+
exitPiP: import("vitest").Mock<(...args: any[]) => any>;
|
|
82
|
+
getPlaybackType: import("vitest").Mock<(...args: any[]) => any>;
|
|
83
|
+
getStartTimeOffset: import("vitest").Mock<(...args: any[]) => any>;
|
|
84
|
+
getCurrentTime: import("vitest").Mock<(...args: any[]) => any>;
|
|
85
|
+
isHighDefinitionInUse: import("vitest").Mock<(...args: any[]) => any>;
|
|
86
|
+
mute: import("vitest").Mock<(...args: any[]) => any>;
|
|
87
|
+
unmute: import("vitest").Mock<(...args: any[]) => any>;
|
|
88
|
+
volume: import("vitest").Mock<(...args: any[]) => any>;
|
|
89
|
+
configure: import("vitest").Mock<(...args: any[]) => any>;
|
|
90
|
+
attemptAutoPlay: import("vitest").Mock<(...args: any[]) => any>;
|
|
91
|
+
canAutoPlay: import("vitest").Mock<(...args: any[]) => any>;
|
|
92
|
+
onResize: import("vitest").Mock<(...args: any[]) => any>;
|
|
93
|
+
setPlaybackRate: import("vitest").Mock<(...args: any[]) => any>;
|
|
94
|
+
trigger: <T extends string | symbol>(event: T, ...args: any[]) => boolean;
|
|
91
95
|
};
|
|
92
96
|
export declare function createMockContainer(playback?: any): Events<string | symbol, any> & {
|
|
93
|
-
el:
|
|
97
|
+
el: any;
|
|
94
98
|
playback: any;
|
|
95
99
|
$el: any;
|
|
96
100
|
getDuration: import("vitest").Mock<(...args: any[]) => any>;
|
|
97
101
|
getPlugin: import("vitest").Mock<(...args: any[]) => any>;
|
|
102
|
+
getPlaybackType: import("vitest").Mock<(...args: any[]) => any>;
|
|
103
|
+
isDvrInUse: import("vitest").Mock<(...args: any[]) => any>;
|
|
104
|
+
isDvrEnabled: import("vitest").Mock<(...args: any[]) => any>;
|
|
98
105
|
isPlaying: import("vitest").Mock<(...args: any[]) => any>;
|
|
99
106
|
play: import("vitest").Mock<(...args: any[]) => any>;
|
|
100
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,51 +98,37 @@ export function createMockPlayback(name = 'mock') {
|
|
|
98
98
|
return Object.assign(emitter, {
|
|
99
99
|
name,
|
|
100
100
|
currentLevel: -1,
|
|
101
|
+
el: document.createElement('video'),
|
|
102
|
+
dvrEnabled: false,
|
|
103
|
+
dvrInUse: false,
|
|
101
104
|
levels: [],
|
|
102
105
|
consent() { },
|
|
103
106
|
play() { },
|
|
104
107
|
pause() { },
|
|
105
108
|
stop() { },
|
|
106
|
-
destroy()
|
|
107
|
-
seek()
|
|
108
|
-
seekPercentage()
|
|
109
|
-
getDuration()
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
},
|
|
126
|
-
mute() { },
|
|
127
|
-
unmute() { },
|
|
128
|
-
volume() { },
|
|
129
|
-
configure() { },
|
|
130
|
-
attemptAutoPlay() {
|
|
131
|
-
return true;
|
|
132
|
-
},
|
|
133
|
-
canAutoPlay() {
|
|
134
|
-
return true;
|
|
135
|
-
},
|
|
136
|
-
onResize() {
|
|
137
|
-
return true;
|
|
138
|
-
},
|
|
139
|
-
trigger(event, ...args) {
|
|
140
|
-
emitter.emit(event, ...args);
|
|
141
|
-
},
|
|
109
|
+
destroy: vi.fn(),
|
|
110
|
+
seek: vi.fn(),
|
|
111
|
+
seekPercentage: vi.fn(),
|
|
112
|
+
getDuration: vi.fn().mockImplementation(() => 100),
|
|
113
|
+
enterPiP: vi.fn(),
|
|
114
|
+
exitPiP: vi.fn(),
|
|
115
|
+
getPlaybackType: vi.fn().mockImplementation(() => Playback.LIVE),
|
|
116
|
+
getStartTimeOffset: vi.fn().mockImplementation(() => 0),
|
|
117
|
+
getCurrentTime: vi.fn().mockImplementation(() => 0),
|
|
118
|
+
isHighDefinitionInUse: vi.fn().mockImplementation(() => false),
|
|
119
|
+
mute: vi.fn(),
|
|
120
|
+
unmute: vi.fn(),
|
|
121
|
+
volume: vi.fn(),
|
|
122
|
+
configure: vi.fn(),
|
|
123
|
+
attemptAutoPlay: vi.fn().mockImplementation(() => true),
|
|
124
|
+
canAutoPlay: vi.fn().mockImplementation(() => true),
|
|
125
|
+
onResize: vi.fn().mockImplementation(() => true),
|
|
126
|
+
setPlaybackRate: vi.fn(),
|
|
127
|
+
trigger: emitter.emit,
|
|
142
128
|
});
|
|
143
129
|
}
|
|
144
130
|
export function createMockContainer(playback = createMockPlayback()) {
|
|
145
|
-
const el =
|
|
131
|
+
const el = playback.el;
|
|
146
132
|
const emitter = new Events();
|
|
147
133
|
return Object.assign(emitter, {
|
|
148
134
|
el,
|
|
@@ -150,6 +136,9 @@ export function createMockContainer(playback = createMockPlayback()) {
|
|
|
150
136
|
$el: $(el),
|
|
151
137
|
getDuration: vi.fn().mockReturnValue(0),
|
|
152
138
|
getPlugin: vi.fn(),
|
|
139
|
+
getPlaybackType: vi.fn().mockReturnValue(Playback.LIVE),
|
|
140
|
+
isDvrInUse: vi.fn().mockReturnValue(false),
|
|
141
|
+
isDvrEnabled: vi.fn().mockReturnValue(false),
|
|
153
142
|
isPlaying: vi.fn().mockReturnValue(false),
|
|
154
143
|
play: vi.fn(),
|
|
155
144
|
seek: vi.fn(),
|
|
@@ -169,10 +158,6 @@ export function createMockMediaControl(core) {
|
|
|
169
158
|
// @ts-ignore
|
|
170
159
|
mediaControl.putElement = vi.fn();
|
|
171
160
|
// @ts-ignore
|
|
172
|
-
mediaControl.
|
|
173
|
-
// @ts-ignore
|
|
174
|
-
mediaControl.getRightPanel = vi.fn().mockImplementation(() => mediaControl.$el.find('.media-control-right-panel'));
|
|
175
|
-
// @ts-ignore
|
|
176
|
-
mediaControl.getCenterPanel = vi.fn().mockImplementation(() => mediaControl.$el.find('.media-control-center-panel'));
|
|
161
|
+
mediaControl.toggleElement = vi.fn();
|
|
177
162
|
return mediaControl;
|
|
178
163
|
}
|
package/package.json
CHANGED
package/src/index.plugins.ts
CHANGED
|
@@ -25,7 +25,8 @@ export * from "./plugins/share/Share.js";
|
|
|
25
25
|
export * from "./plugins/skip-time/SkipTime.js";
|
|
26
26
|
export * from "./plugins/spinner-three-bounce/SpinnerThreeBounce.js";
|
|
27
27
|
export * from "./plugins/source-controller/SourceController.js";
|
|
28
|
-
export * from "./plugins/subtitles/
|
|
28
|
+
export * from "./plugins/subtitles/ClosedCaptions.js";
|
|
29
|
+
export { ClosedCaptions as Subtitles } from "./plugins/subtitles/ClosedCaptions.js"; // TODO remove in future versions
|
|
29
30
|
export * from "./plugins/telemetry/Telemetry.js";
|
|
30
31
|
export * from "./plugins/thumbnails/Thumbnails.js";
|
|
31
32
|
// _ vast-ads
|
package/src/index.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* It is built on top of the {@link https://github.com/clappr/clappr | Clappr} library and provides a framework for building custom integrations.
|
|
7
7
|
* Start with {@link Player} for more information.
|
|
8
8
|
*
|
|
9
|
-
* Various plugins (marked with `PLUGIN` keyword) are available to extend the
|
|
9
|
+
* Various plugins (marked with `PLUGIN` keyword) are available to extend the core functionality with additional features.
|
|
10
10
|
* @example
|
|
11
11
|
* ```ts
|
|
12
12
|
* import { Player, MediaControl, ErrorScreen } from '@gcorevideo/player'
|
|
@@ -416,6 +416,7 @@ export default class DashPlayback extends BasePlayback {
|
|
|
416
416
|
this.trigger(Events.PLAYBACK_STATS_ADD, { dvr: status })
|
|
417
417
|
}
|
|
418
418
|
|
|
419
|
+
// TODO move to the base class
|
|
419
420
|
override _updateSettings() {
|
|
420
421
|
if (this._playbackType === Playback.VOD) {
|
|
421
422
|
// @ts-expect-error
|
|
@@ -9,6 +9,7 @@ import pluginHtml from '../../../assets/audio-selector/track-selector.ejs'
|
|
|
9
9
|
import '../../../assets/audio-selector/style.scss'
|
|
10
10
|
import audioArrow from '../../../assets/icons/old/quality-arrow.svg'
|
|
11
11
|
import { ZeptoResult } from '../../types.js'
|
|
12
|
+
import { MediaControl } from '../media-control/MediaControl.js'
|
|
12
13
|
|
|
13
14
|
const VERSION: string = '0.0.1'
|
|
14
15
|
|
|
@@ -57,8 +58,8 @@ export class AudioSelector extends UICorePlugin {
|
|
|
57
58
|
*/
|
|
58
59
|
override get attributes() {
|
|
59
60
|
return {
|
|
60
|
-
class: 'media-control-
|
|
61
|
-
|
|
61
|
+
class: 'media-control-audiotracks',
|
|
62
|
+
|
|
62
63
|
}
|
|
63
64
|
}
|
|
64
65
|
|
|
@@ -67,8 +68,8 @@ export class AudioSelector extends UICorePlugin {
|
|
|
67
68
|
*/
|
|
68
69
|
override get events() {
|
|
69
70
|
return {
|
|
70
|
-
'click [data-
|
|
71
|
-
'click [data-
|
|
71
|
+
'click [data-audiotracks-select]': 'onTrackSelect',
|
|
72
|
+
'click [data-audiotracks-button]': 'onShowLevelSelectMenu',
|
|
72
73
|
}
|
|
73
74
|
}
|
|
74
75
|
|
|
@@ -156,12 +157,12 @@ export class AudioSelector extends UICorePlugin {
|
|
|
156
157
|
return this
|
|
157
158
|
}
|
|
158
159
|
|
|
159
|
-
const mediaControl = this.core.getPlugin('media_control')
|
|
160
|
+
const mediaControl = this.core.getPlugin('media_control') as MediaControl
|
|
160
161
|
this.$el.html(
|
|
161
162
|
AudioSelector.template({ tracks: this.tracks, title: this.getTitle() }),
|
|
162
163
|
)
|
|
163
164
|
this.$('.audio-arrow').append(audioArrow)
|
|
164
|
-
mediaControl.putElement('
|
|
165
|
+
mediaControl.putElement('audiotracks', this.el)
|
|
165
166
|
|
|
166
167
|
this.updateText()
|
|
167
168
|
this.highlightCurrentTrack()
|
|
@@ -179,7 +180,7 @@ export class AudioSelector extends UICorePlugin {
|
|
|
179
180
|
}
|
|
180
181
|
|
|
181
182
|
private onTrackSelect(event: MouseEvent) {
|
|
182
|
-
const id = (event.target as HTMLElement)?.dataset?.
|
|
183
|
+
const id = (event.target as HTMLElement)?.dataset?.audiotracksSelect
|
|
183
184
|
if (id) {
|
|
184
185
|
this.selectAudioTrack(id)
|
|
185
186
|
}
|
|
@@ -218,7 +219,7 @@ export class AudioSelector extends UICorePlugin {
|
|
|
218
219
|
return (
|
|
219
220
|
this.$(
|
|
220
221
|
'ul a' +
|
|
221
|
-
(id !== undefined ? '[data-
|
|
222
|
+
(id !== undefined ? '[data-audiotracks-select="' + id + '"]' : ''),
|
|
222
223
|
) as ZeptoResult
|
|
223
224
|
).parent()
|
|
224
225
|
}
|
|
@@ -20,7 +20,12 @@ const T = 'plugins.bottom_gear';
|
|
|
20
20
|
* An element inside the gear menu
|
|
21
21
|
* @beta
|
|
22
22
|
*/
|
|
23
|
-
export type
|
|
23
|
+
export type GearOptionsItem = 'quality' | 'rate' | 'nerd';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @deprecated Use {@link GearOptionsItem} instead
|
|
27
|
+
*/
|
|
28
|
+
export type GearItemElement = GearOptionsItem;
|
|
24
29
|
|
|
25
30
|
// TODO disabled if no items added
|
|
26
31
|
|
|
@@ -90,10 +95,12 @@ export class BottomGear extends UICorePlugin {
|
|
|
90
95
|
* @param name - Name of a gear menu placeholder item to attach custom UI
|
|
91
96
|
* @returns Zepto result of the element
|
|
92
97
|
*/
|
|
93
|
-
getElement(name:
|
|
98
|
+
getElement(name: GearOptionsItem): ZeptoResult | null {
|
|
94
99
|
return this.$el.find(`.gear-options-list [data-${name}]`);
|
|
95
100
|
}
|
|
96
101
|
|
|
102
|
+
// TODO implement putElement/addElement method
|
|
103
|
+
|
|
97
104
|
/**
|
|
98
105
|
* Replaces the content of the gear menu
|
|
99
106
|
* @param content - Zepto result of the element
|
|
@@ -125,7 +132,7 @@ export class BottomGear extends UICorePlugin {
|
|
|
125
132
|
const mediaControl = this.core.getPlugin('media_control');
|
|
126
133
|
|
|
127
134
|
// TODO use options.mediaControl.gear.items
|
|
128
|
-
const items:
|
|
135
|
+
const items: GearOptionsItem[] = [
|
|
129
136
|
'quality',
|
|
130
137
|
'rate',
|
|
131
138
|
'nerd',
|
|
@@ -133,7 +140,7 @@ export class BottomGear extends UICorePlugin {
|
|
|
133
140
|
const icon = this.isHd ? gearHdIcon : gearIcon;
|
|
134
141
|
this.$el.html(BottomGear.template({ icon, items }));
|
|
135
142
|
|
|
136
|
-
mediaControl.putElement('gear', this
|
|
143
|
+
mediaControl.putElement('gear', this.el);
|
|
137
144
|
mediaControl.trigger(MediaControlEvents.MEDIACONTROL_GEAR_RENDERED);
|
|
138
145
|
return this;
|
|
139
146
|
}
|
|
@@ -26,7 +26,7 @@ describe('BottomGear', () => {
|
|
|
26
26
|
expect(bottomGear.el.innerHTML).toMatchSnapshot()
|
|
27
27
|
})
|
|
28
28
|
it('should attach to media control', () => {
|
|
29
|
-
expect(mediaControl.putElement).toHaveBeenCalledWith('gear', bottomGear
|
|
29
|
+
expect(mediaControl.putElement).toHaveBeenCalledWith('gear', bottomGear.el)
|
|
30
30
|
})
|
|
31
31
|
it('should emit event', () => {
|
|
32
32
|
expect(onGearRendered).toHaveBeenCalled()
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
2
|
|
|
3
3
|
exports[`BottomGear > should render 1`] = `
|
|
4
|
-
"<button type="button" class="button-gear media-control-button gplayer-lite-btn gcore-skin-button-color gear-icon" data-gear-button="-1">
|
|
4
|
+
"<button type="button" class="button-gear media-control-button gplayer-lite-btn gcore-skin-button-color gear-icon" data-gear-button="-1" id="gear-button">
|
|
5
5
|
/assets/icons/new/gear.svg
|
|
6
6
|
</button>
|
|
7
7
|
<div class="gear-wrapper gcore-skin-bg-color">
|
|
8
|
-
<ul class="gear-options-list">
|
|
8
|
+
<ul class="gear-options-list" id="gear-options">
|
|
9
9
|
|
|
10
10
|
<li data-quality=""></li>
|
|
11
11
|
|
|
@@ -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
|
}
|