@gcorevideo/player 2.21.3 → 2.21.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/assets/audio-selector/style.scss +1 -1
  2. package/assets/audio-selector/track-selector.ejs +3 -3
  3. package/assets/bottom-gear/bottomgear.ejs +2 -2
  4. package/assets/media-control/container.scss +1 -1
  5. package/assets/media-control/media-control.ejs +1 -6
  6. package/assets/media-control/media-control.scss +6 -4
  7. package/assets/media-control/width270.scss +1 -1
  8. package/assets/media-control/width370.scss +4 -4
  9. package/assets/playback-rate/button.ejs +2 -2
  10. package/assets/playback-rate/list.ejs +4 -4
  11. package/assets/subtitles/combobox.ejs +5 -5
  12. package/assets/subtitles/string.ejs +1 -1
  13. package/assets/subtitles/style.scss +2 -2
  14. package/dist/core.js +2 -1
  15. package/dist/index.css +972 -967
  16. package/dist/index.js +126 -106
  17. package/dist/player.d.ts +141 -119
  18. package/dist/plugins/index.css +801 -796
  19. package/dist/plugins/index.js +119 -104
  20. package/docs/api/player.bottomgear.getelement.md +2 -2
  21. package/docs/api/player.bottomgear.md +1 -1
  22. package/docs/api/{player.subtitles.hide.md → player.closedcaptions.hide.md} +2 -2
  23. package/docs/api/{player.subtitles.md → player.closedcaptions.md} +11 -11
  24. package/docs/api/{player.subtitles.show.md → player.closedcaptions.show.md} +2 -2
  25. package/docs/api/player.closedcaptionspluginsettings.md +13 -0
  26. package/docs/api/player.gearitemelement.md +6 -4
  27. package/docs/api/player.gearoptionsitem.md +16 -0
  28. package/docs/api/player.md +48 -12
  29. package/docs/api/player.mediacontrol.putelement.md +2 -2
  30. package/docs/api/player.mediacontrolelement.md +1 -1
  31. package/docs/api/player.playbackrate.md +1 -1
  32. package/docs/api/player.subtitlespluginsettings.md +18 -0
  33. package/docs/api/player.texttrackitem.id.md +11 -0
  34. package/docs/api/player.texttrackitem.md +87 -0
  35. package/docs/api/player.texttrackitem.name.md +11 -0
  36. package/docs/api/player.texttrackitem.track.md +11 -0
  37. package/lib/index.d.ts +1 -1
  38. package/lib/index.js +1 -1
  39. package/lib/index.plugins.d.ts +2 -1
  40. package/lib/index.plugins.d.ts.map +1 -1
  41. package/lib/index.plugins.js +2 -1
  42. package/lib/playback/dash-playback/DashPlayback.d.ts.map +1 -1
  43. package/lib/playback/dash-playback/DashPlayback.js +1 -0
  44. package/lib/plugins/audio-selector/AudioSelector.d.ts +2 -3
  45. package/lib/plugins/audio-selector/AudioSelector.d.ts.map +1 -1
  46. package/lib/plugins/audio-selector/AudioSelector.js +6 -7
  47. package/lib/plugins/bottom-gear/BottomGear.d.ts +6 -2
  48. package/lib/plugins/bottom-gear/BottomGear.d.ts.map +1 -1
  49. package/lib/plugins/bottom-gear/BottomGear.js +2 -1
  50. package/lib/plugins/media-control/MediaControl.d.ts +5 -5
  51. package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
  52. package/lib/plugins/media-control/MediaControl.js +46 -39
  53. package/lib/plugins/picture-in-picture/PictureInPicture.d.ts +1 -0
  54. package/lib/plugins/picture-in-picture/PictureInPicture.d.ts.map +1 -1
  55. package/lib/plugins/picture-in-picture/PictureInPicture.js +4 -4
  56. package/lib/plugins/playback-rate/PlaybackRate.d.ts +0 -1
  57. package/lib/plugins/playback-rate/PlaybackRate.d.ts.map +1 -1
  58. package/lib/plugins/playback-rate/PlaybackRate.js +23 -14
  59. package/lib/plugins/subtitles/ClosedCaptions.d.ts +118 -0
  60. package/lib/plugins/subtitles/ClosedCaptions.d.ts.map +1 -0
  61. package/lib/plugins/subtitles/ClosedCaptions.js +348 -0
  62. package/lib/plugins/subtitles/Subtitles.d.ts +12 -9
  63. package/lib/plugins/subtitles/Subtitles.d.ts.map +1 -1
  64. package/lib/plugins/subtitles/Subtitles.js +31 -32
  65. package/lib/testUtils.d.ts +22 -18
  66. package/lib/testUtils.d.ts.map +1 -1
  67. package/lib/testUtils.js +22 -36
  68. package/package.json +1 -1
  69. package/src/index.plugins.ts +2 -1
  70. package/src/index.ts +1 -1
  71. package/src/playback/dash-playback/DashPlayback.ts +1 -0
  72. package/src/plugins/audio-selector/AudioSelector.ts +9 -8
  73. package/src/plugins/bottom-gear/BottomGear.ts +11 -4
  74. package/src/plugins/bottom-gear/__tests__/BottomGear.test.ts +1 -1
  75. package/src/plugins/bottom-gear/__tests__/__snapshots__/BottomGear.test.ts.snap +2 -2
  76. package/src/plugins/media-control/MediaControl.ts +53 -46
  77. package/src/plugins/media-control/__tests__/MediaControl.test.ts +43 -0
  78. package/src/plugins/media-control/__tests__/__snapshots__/MediaControl.test.ts.snap +175 -0
  79. package/src/plugins/picture-in-picture/PictureInPicture.ts +5 -5
  80. package/src/plugins/playback-rate/PlaybackRate.ts +142 -100
  81. package/src/plugins/playback-rate/__tests__/PlaybackRate.test.ts +65 -0
  82. package/src/plugins/playback-rate/__tests__/__snapshots__/PlaybackRate.test.ts.snap +11 -0
  83. package/src/plugins/subtitles/{Subtitles.ts → ClosedCaptions.ts} +42 -34
  84. package/src/plugins/subtitles/__tests__/ClosedCaptions.test.ts +58 -0
  85. package/src/plugins/subtitles/__tests__/__snapshots__/ClosedCaptions.test.ts.snap +25 -0
  86. package/src/testUtils.ts +22 -36
  87. package/temp/player.api.json +269 -89
  88. package/tsconfig.tsbuildinfo +1 -1
  89. package/src/plugins/index.ts +0 -39
@@ -0,0 +1,348 @@
1
+ import { Events, UICorePlugin, Browser, template, $ } from '@clappr/core';
2
+ import { reportError, trace } from '@gcorevideo/utils';
3
+ import assert from 'assert';
4
+ import { CLAPPR_VERSION } from '../../build.js';
5
+ import '../../../assets/subtitles/style.scss';
6
+ import subtitlesOffIcon from '../../../assets/icons/new/subtitles-off.svg';
7
+ import subtitlesOnIcon from '../../../assets/icons/new/subtitles-on.svg';
8
+ import comboboxHTML from '../../../assets/subtitles/combobox.ejs';
9
+ import stringHTML from '../../../assets/subtitles/string.ejs';
10
+ import { isFullscreen } from '../utils.js';
11
+ const VERSION = '2.19.14';
12
+ const LOCAL_STORAGE_CC_ID = 'gplayer.plugins.cc.selected';
13
+ const T = 'plugins.cc';
14
+ /**
15
+ * `PLUGIN` that provides a UI to select the subtitles when available.
16
+ * @beta
17
+ *
18
+ * @remarks
19
+ * The plugin is activated when closed captions tracks are provided with the media source.
20
+ * It shows a familiar "CC" button with a dropdown menu to select the subtitles language.
21
+ *
22
+ * Depends on:
23
+ *
24
+ * - {@link MediaControl}
25
+ *
26
+ * Configuration options - {@link ClosedCaptionsPluginSettings}
27
+ * @example
28
+ * ```ts
29
+ * import { ClosedCaptions } from '@gcorevideo/player'
30
+ *
31
+ * Player.registerPlugin(ClosedCaptions)
32
+ *
33
+ * new Player({
34
+ * ...
35
+ * cc: {
36
+ * language: 'en',
37
+ * },
38
+ * })
39
+ * ```
40
+ */
41
+ export class ClosedCaptions extends UICorePlugin {
42
+ isPreselectedApplied = false;
43
+ isShowing = false;
44
+ track = null;
45
+ tracks = [];
46
+ $line = null;
47
+ /**
48
+ * @internal
49
+ */
50
+ get name() {
51
+ return 'cc';
52
+ }
53
+ /**
54
+ * @internal
55
+ */
56
+ get supportedVersion() {
57
+ return { min: CLAPPR_VERSION };
58
+ }
59
+ /**
60
+ * @internal
61
+ */
62
+ static get version() {
63
+ return VERSION;
64
+ }
65
+ static template = template(comboboxHTML);
66
+ static templateString = template(stringHTML);
67
+ /**
68
+ * @internal
69
+ */
70
+ get attributes() {
71
+ return {
72
+ class: 'media-control-cc',
73
+ };
74
+ }
75
+ /**
76
+ * @internal
77
+ */
78
+ get events() {
79
+ return {
80
+ 'click [data-cc-select]': 'onItemSelect',
81
+ 'click [data-cc-button]': 'toggleMenu',
82
+ };
83
+ }
84
+ get preselectedLanguage() {
85
+ return this.core.options.cc?.language ?? this.core.options.subtitles?.language ?? '';
86
+ }
87
+ /**
88
+ * @internal
89
+ */
90
+ bindEvents() {
91
+ this.listenTo(this.core, Events.CORE_READY, this.onCoreReady);
92
+ this.listenTo(this.core, Events.CORE_RESIZE, this.playerResize);
93
+ this.listenTo(this.core, Events.CORE_ACTIVE_CONTAINER_CHANGED, this.onContainerChanged);
94
+ }
95
+ onCoreReady() {
96
+ trace(`${T} onCoreReady`);
97
+ const mediaControl = this.core.getPlugin('media_control');
98
+ assert(mediaControl, 'media_control plugin is required');
99
+ this.listenTo(mediaControl, Events.MEDIACONTROL_RENDERED, this.render);
100
+ this.listenTo(mediaControl, Events.MEDIACONTROL_HIDE, this.hideMenu);
101
+ }
102
+ onContainerChanged() {
103
+ trace(`${T} onContainerChanged`);
104
+ this.listenTo(this.core.activeContainer, Events.CONTAINER_FULLSCREEN, this.playerResize);
105
+ this.listenTo(this.core.activeContainer, 'container:advertisement:start', this.onStartAd);
106
+ this.listenTo(this.core.activePlayback, Events.PLAYBACK_SUBTITLE_AVAILABLE, this.onSubtitleAvailable);
107
+ this.listenTo(this.core.activePlayback, Events.PLAYBACK_SUBTITLE_CHANGED, this.onSubtitleChanged);
108
+ // fix for iOS
109
+ const video = this.core.activePlayback.el;
110
+ assert(video, 'video element is required');
111
+ video.addEventListener('webkitbeginfullscreen', () => {
112
+ if (Browser.isiOS) {
113
+ video.classList.add('ios-fullscreen');
114
+ }
115
+ });
116
+ video.addEventListener('webkitendfullscreen', () => {
117
+ if (Browser.isiOS) {
118
+ video.classList.remove('ios-fullscreen');
119
+ }
120
+ });
121
+ }
122
+ onSubtitleAvailable() {
123
+ trace(`${T} onSubtitleAvailable`);
124
+ this.applyTracks();
125
+ }
126
+ onSubtitleChanged({ id }) {
127
+ trace(`${T} onSubtitleChanged`, { id });
128
+ if (id === -1) {
129
+ this.clearSubtitleText();
130
+ }
131
+ for (const track of this.tracks) {
132
+ if (track.id === id) {
133
+ track.track.mode = 'showing';
134
+ this.setSubtitleText(this.getSubtitleText(track.track));
135
+ track.track.oncuechange = (e) => {
136
+ try {
137
+ if (track.track.activeCues?.length) {
138
+ const html = track.track.activeCues[0].getCueAsHTML();
139
+ this.setSubtitleText(html);
140
+ }
141
+ else {
142
+ this.clearSubtitleText();
143
+ }
144
+ }
145
+ catch (error) {
146
+ reportError(error);
147
+ }
148
+ };
149
+ }
150
+ else {
151
+ track.track.oncuechange = null;
152
+ track.track.mode = 'hidden';
153
+ }
154
+ }
155
+ }
156
+ applyTracks() {
157
+ try {
158
+ this.tracks = this.core.activePlayback.closedCaptionsTracks;
159
+ this.applyPreselectedSubtitles();
160
+ this.render();
161
+ }
162
+ catch (error) {
163
+ reportError(error);
164
+ }
165
+ }
166
+ onStartAd() {
167
+ if (this.isShowing && this.core.activeContainer) {
168
+ this.hide();
169
+ this.listenTo(this.core.activeContainer, 'container:advertisement:finish', this.onFinishAd);
170
+ }
171
+ }
172
+ onFinishAd() {
173
+ this.show();
174
+ this.stopListening(this.core.activeContainer, 'container:advertisement:finish', this.onFinishAd);
175
+ }
176
+ playerResize() {
177
+ trace(`${T} playerResize`);
178
+ const shouldShow = this.core.activeContainer &&
179
+ isFullscreen(this.core.activeContainer.el) &&
180
+ this.track &&
181
+ this.track.track.mode &&
182
+ Browser.isiOS &&
183
+ this.isShowing;
184
+ if (shouldShow) {
185
+ this.show();
186
+ }
187
+ try {
188
+ this.resizeFont();
189
+ }
190
+ catch (error) {
191
+ reportError(error);
192
+ }
193
+ }
194
+ /**
195
+ * Hides the subtitles menu and the subtitles.
196
+ */
197
+ hide() {
198
+ this.isShowing = false;
199
+ this.renderIcon();
200
+ this.$line.hide();
201
+ if (this.tracks) {
202
+ for (const t of this.tracks) {
203
+ t.track.mode = 'hidden';
204
+ }
205
+ }
206
+ }
207
+ /**
208
+ * Shows the subtitles menu and the subtitles.
209
+ */
210
+ show() {
211
+ this.isShowing = true;
212
+ this.renderIcon();
213
+ if (this.core.activeContainer &&
214
+ isFullscreen(this.core.activeContainer.el) &&
215
+ this.track &&
216
+ this.track.track.mode &&
217
+ Browser.isiOS) {
218
+ this.$line.hide();
219
+ this.track.track.mode = 'showing';
220
+ }
221
+ else {
222
+ this.$line.show();
223
+ }
224
+ }
225
+ shouldRender() {
226
+ return this.tracks?.length > 0;
227
+ }
228
+ resizeFont() {
229
+ if (!this.$line) {
230
+ return;
231
+ }
232
+ const skinWidth = this.core.activeContainer.$el.width();
233
+ this.$line.find('p').css('font-size', skinWidth * 0.03);
234
+ }
235
+ /**
236
+ * @internal
237
+ */
238
+ render() {
239
+ if (!this.core.activeContainer) {
240
+ return this;
241
+ }
242
+ if (!this.shouldRender()) {
243
+ return this;
244
+ }
245
+ const mediaControl = this.core.getPlugin('media_control');
246
+ this.$el.html(ClosedCaptions.template({ tracks: this.tracks }));
247
+ this.core.activeContainer.$el.find('#cc-line').remove();
248
+ this.$line = $(ClosedCaptions.templateString());
249
+ this.resizeFont();
250
+ this.core.activeContainer.$el.append(this.$line);
251
+ mediaControl.putElement('cc', this.el);
252
+ this.updateSelection();
253
+ this.renderIcon();
254
+ return this;
255
+ }
256
+ findById(id) {
257
+ return this.tracks.find((track) => track.id === id) ?? null;
258
+ }
259
+ selectItem(item) {
260
+ this.clearSubtitleText();
261
+ this.track = item;
262
+ this.hideMenu();
263
+ this.updateSelection();
264
+ }
265
+ onItemSelect(event) {
266
+ const id = event.target.dataset.ccSelect ?? '-1';
267
+ trace(`${T} onItemSelect`, { id });
268
+ localStorage.setItem(LOCAL_STORAGE_CC_ID, id);
269
+ this.selectItem(this.findById(Number(id)));
270
+ return false;
271
+ }
272
+ applyPreselectedSubtitles() {
273
+ if (!this.isPreselectedApplied) {
274
+ this.isPreselectedApplied = true;
275
+ if (!this.preselectedLanguage) {
276
+ return;
277
+ }
278
+ setTimeout(() => {
279
+ this.selectItem(this.tracks.find((t) => t.track.language === this.preselectedLanguage) ?? null);
280
+ }, 300); // TODO why delay?
281
+ }
282
+ }
283
+ hideMenu() {
284
+ ;
285
+ this.$('[data-cc] ul').hide();
286
+ }
287
+ toggleMenu() {
288
+ trace(`${T} toggleMenu`);
289
+ this.$('[data-cc] ul').toggle();
290
+ }
291
+ itemElement(id) {
292
+ return this.$(`ul li a[data-cc-select="${id}"]`).parent();
293
+ }
294
+ allItemElements() {
295
+ return this.$('[data-cc] li');
296
+ }
297
+ selectSubtitles() {
298
+ const trackId = this.track ? this.track.id : -1;
299
+ this.core.activePlayback.closedCaptionsTrackId = trackId;
300
+ }
301
+ getSubtitleText(track) {
302
+ const currentTime = this.core.activePlayback?.getCurrentTime() ?? 0;
303
+ const cues = track.cues;
304
+ const lines = [];
305
+ if (cues && cues.length) {
306
+ for (const cue of cues) {
307
+ if (currentTime >= cue.startTime && currentTime <= cue.endTime) {
308
+ lines.push(cue.getCueAsHTML().textContent);
309
+ }
310
+ }
311
+ }
312
+ return lines.join('\n');
313
+ }
314
+ setSubtitleText(text) {
315
+ this.$line.find('p').html(text);
316
+ }
317
+ clearSubtitleText() {
318
+ this.setSubtitleText('');
319
+ }
320
+ updateSelection() {
321
+ if (!this.track) {
322
+ this.hide();
323
+ }
324
+ else {
325
+ this.show();
326
+ }
327
+ this.selectSubtitles();
328
+ this.highlightCurrentSubtitles();
329
+ }
330
+ highlightCurrentSubtitles() {
331
+ this.allItemElements()
332
+ .removeClass('current')
333
+ .find('a')
334
+ .removeClass('gcore-skin-active');
335
+ trace(`${T} highlightCurrentSubtitles`, {
336
+ track: this.track?.id,
337
+ });
338
+ const currentLevelElement = this.itemElement(this.track ? this.track.id : -1);
339
+ currentLevelElement
340
+ .addClass('current')
341
+ .find('a')
342
+ .addClass('gcore-skin-active');
343
+ }
344
+ renderIcon() {
345
+ const icon = this.isShowing ? subtitlesOnIcon : subtitlesOffIcon;
346
+ this.$el.find('span.cc-text').html(icon);
347
+ }
348
+ }
@@ -1,11 +1,15 @@
1
1
  import { UICorePlugin } from '@clappr/core';
2
2
  import '../../../assets/subtitles/style.scss';
3
- export type SubtitlesPluginSettings = {
3
+ export type ClosedCaptionsPluginSettings = {
4
4
  /**
5
5
  * Initially selected subtitles language
6
6
  */
7
7
  language?: string;
8
8
  };
9
+ /**
10
+ * @deprecated Use {@link ClosedCaptionsPluginSettings} instead.
11
+ */
12
+ export type SubtitlesPluginSettings = ClosedCaptionsPluginSettings;
9
13
  /**
10
14
  * `PLUGIN` that provides a UI to select the subtitles when available.
11
15
  * @beta
@@ -15,16 +19,16 @@ export type SubtitlesPluginSettings = {
15
19
  *
16
20
  * - {@link MediaControl}
17
21
  *
18
- * Configuration options - {@link SubtitlesPluginSettings}
22
+ * Configuration options - {@link ClosedCaptionsPluginSettings}
19
23
  * @example
20
24
  * ```ts
21
- * import { Subtitles } from '@gcorevideo/player'
25
+ * import { ClosedCaptions } from '@gcorevideo/player'
22
26
  *
23
- * Player.registerPlugin(Subtitles)
27
+ * Player.registerPlugin(ClosedCaptions)
24
28
  *
25
29
  * new Player({
26
30
  * ...
27
- * subtitles: {
31
+ * cc: {
28
32
  * language: 'en',
29
33
  * },
30
34
  * })
@@ -35,7 +39,7 @@ export declare class Subtitles extends UICorePlugin {
35
39
  private isShowing;
36
40
  private track;
37
41
  private tracks;
38
- private $string;
42
+ private $line;
39
43
  /**
40
44
  * @internal
41
45
  */
@@ -57,14 +61,13 @@ export declare class Subtitles extends UICorePlugin {
57
61
  */
58
62
  get attributes(): {
59
63
  class: string;
60
- 'data-subtitles': string;
61
64
  };
62
65
  /**
63
66
  * @internal
64
67
  */
65
68
  get events(): {
66
- 'click [data-subtitles-select]': string;
67
- 'click [data-subtitles-button]': string;
69
+ 'click [data-cc-select]': string;
70
+ 'click [data-cc-button]': string;
68
71
  };
69
72
  private get preselectedLanguage();
70
73
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"Subtitles.d.ts","sourceRoot":"","sources":["../../../src/plugins/subtitles/Subtitles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,YAAY,EAAwB,MAAM,cAAc,CAAA;AAOzE,OAAO,sCAAsC,CAAA;AAe7C,MAAM,MAAM,uBAAuB,GAAG;IACpC;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,SAAU,SAAQ,YAAY;IACzC,OAAO,CAAC,oBAAoB,CAAQ;IAEpC,OAAO,CAAC,SAAS,CAAQ;IAEzB,OAAO,CAAC,KAAK,CAA6B;IAE1C,OAAO,CAAC,MAAM,CAAsB;IAEpC,OAAO,CAAC,OAAO,CAA2B;IAE1C;;OAEG;IACH,IAAI,IAAI,WAEP;IAED;;OAEG;IACH,IAAI,gBAAgB;;MAEnB;IAED;;OAEG;IACH,MAAM,KAAK,OAAO,WAEjB;IAED,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAyB;IAEzD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAuB;IAE7D;;OAEG;IACH,IAAa,UAAU;;;MAKtB;IAED;;OAEG;IACH,IAAa,MAAM;;;MAKlB;IAED,OAAO,KAAK,mBAAmB,GAE9B;IAED;;OAEG;IACM,UAAU;IAUnB,OAAO,CAAC,WAAW;IAYnB,OAAO,CAAC,kBAAkB;IAwC1B,OAAO,CAAC,mBAAmB;IAK3B,OAAO,CAAC,iBAAiB;IA+BzB,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,SAAS;IAWjB,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,YAAY;IAqBpB;;OAEG;IACH,IAAI;IAWJ;;OAEG;IACH,IAAI;IAiBJ,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,UAAU;IAUlB;;OAEG;IACM,MAAM;IA0Bf,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,yBAAyB;IAgBjC,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,eAAe;IAgBvB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,yBAAyB;IAgBjC,OAAO,CAAC,UAAU;CAKnB"}
1
+ {"version":3,"file":"Subtitles.d.ts","sourceRoot":"","sources":["../../../src/plugins/subtitles/Subtitles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,YAAY,EAAwB,MAAM,cAAc,CAAA;AAOzE,OAAO,sCAAsC,CAAA;AAe7C,MAAM,MAAM,4BAA4B,GAAG;IACzC;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG,4BAA4B,CAAC;AAEnE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,SAAU,SAAQ,YAAY;IACzC,OAAO,CAAC,oBAAoB,CAAQ;IAEpC,OAAO,CAAC,SAAS,CAAQ;IAEzB,OAAO,CAAC,KAAK,CAA6B;IAE1C,OAAO,CAAC,MAAM,CAAsB;IAEpC,OAAO,CAAC,KAAK,CAA2B;IAExC;;OAEG;IACH,IAAI,IAAI,WAEP;IAED;;OAEG;IACH,IAAI,gBAAgB;;MAEnB;IAED;;OAEG;IACH,MAAM,KAAK,OAAO,WAEjB;IAED,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAyB;IAEzD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAuB;IAE7D;;OAEG;IACH,IAAa,UAAU;;MAItB;IAED;;OAEG;IACH,IAAa,MAAM;;;MAKlB;IAED,OAAO,KAAK,mBAAmB,GAE9B;IAED;;OAEG;IACM,UAAU;IAUnB,OAAO,CAAC,WAAW;IAYnB,OAAO,CAAC,kBAAkB;IAwC1B,OAAO,CAAC,mBAAmB;IAK3B,OAAO,CAAC,iBAAiB;IA+BzB,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,SAAS;IAWjB,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,YAAY;IAqBpB;;OAEG;IACH,IAAI;IAWJ;;OAEG;IACH,IAAI;IAiBJ,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,UAAU;IAUlB;;OAEG;IACM,MAAM;IA0Bf,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,yBAAyB;IAgBjC,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,eAAe;IAgBvB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,yBAAyB;IAgBjC,OAAO,CAAC,UAAU;CAKnB"}
@@ -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 LOCAL_STORAGE_SUBTITLES_ID = 'gplayer.plugins.subtitles.selected';
13
- const T = 'plugins.subtitles';
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 SubtitlesPluginSettings}
23
+ * Configuration options - {@link ClosedCaptionsPluginSettings}
24
24
  * @example
25
25
  * ```ts
26
- * import { Subtitles } from '@gcorevideo/player'
26
+ * import { ClosedCaptions } from '@gcorevideo/player'
27
27
  *
28
- * Player.registerPlugin(Subtitles)
28
+ * Player.registerPlugin(ClosedCaptions)
29
29
  *
30
30
  * new Player({
31
31
  * ...
32
- * subtitles: {
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
- $string = null;
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-subtitles',
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-subtitles-select]': 'onItemSelect',
79
- 'click [data-subtitles-button]': 'toggleMenu',
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.$string.hide();
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.$string.hide();
215
+ this.$line.hide();
217
216
  this.track.track.mode = 'showing';
218
217
  }
219
218
  else {
220
- this.$string.show();
219
+ this.$line.show();
221
220
  }
222
221
  }
223
222
  shouldRender() {
224
- return this.tracks.length > 0;
223
+ return this.tracks?.length > 0;
225
224
  }
226
225
  resizeFont() {
227
- if (!this.$string) {
226
+ if (!this.$line) {
228
227
  return;
229
228
  }
230
229
  const skinWidth = this.core.activeContainer.$el.width();
231
- this.$string.find('p').css('font-size', skinWidth * 0.03);
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('.subtitle-string').remove();
246
- this.$string = $(Subtitles.templateString());
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.$string);
249
- mediaControl.putElement('subtitlesSelector', this.$el);
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.subtitlesSelect ?? '-1';
263
+ const id = event.target.dataset.ccSelect ?? '-1';
265
264
  trace(`${T} onItemSelect`, { id });
266
- localStorage.setItem(LOCAL_STORAGE_SUBTITLES_ID, id);
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-subtitles] ul').hide();
282
+ this.$('[data-cc] ul').hide();
284
283
  }
285
284
  toggleMenu() {
286
- ;
287
- this.$('[data-subtitles] ul').toggle();
285
+ trace(`${T} toggleMenu`);
286
+ this.$('[data-cc] ul').toggle();
288
287
  }
289
288
  itemElement(id) {
290
- return this.$(`ul li a[data-subtitles-select="${id}"]`).parent();
289
+ return this.$(`ul li a[data-cc-select="${id}"]`).parent();
291
290
  }
292
291
  allItemElements() {
293
- return this.$('[data-subtitles] li');
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.$string.find('p').html(text);
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.subtitle-text').html(icon);
343
+ this.$el.find('span.cc-text').html(icon);
345
344
  }
346
345
  }
@@ -65,29 +65,31 @@ 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
+ dvrEnabled: boolean;
68
69
  levels: never[];
69
70
  consent(): void;
70
71
  play(): void;
71
72
  pause(): void;
72
73
  stop(): void;
73
- destroy(): void;
74
- seek(): void;
75
- seekPercentage(): void;
76
- getDuration(): 100;
77
- enterPiP(): void;
78
- exitPiP(): void;
79
- getPlaybackType(): "live";
80
- getStartTimeOffset(): 0;
81
- getCurrentTime(): 0;
82
- isHighDefinitionInUse(): false;
83
- mute(): void;
84
- unmute(): void;
85
- volume(): void;
86
- configure(): void;
87
- attemptAutoPlay(): true;
88
- canAutoPlay(): true;
89
- onResize(): true;
90
- trigger(event: string, ...args: any[]): void;
74
+ destroy: import("vitest").Mock<(...args: any[]) => any>;
75
+ seek: import("vitest").Mock<(...args: any[]) => any>;
76
+ seekPercentage: import("vitest").Mock<(...args: any[]) => any>;
77
+ getDuration: import("vitest").Mock<(...args: any[]) => any>;
78
+ enterPiP: import("vitest").Mock<(...args: any[]) => any>;
79
+ exitPiP: import("vitest").Mock<(...args: any[]) => any>;
80
+ getPlaybackType: import("vitest").Mock<(...args: any[]) => any>;
81
+ getStartTimeOffset: import("vitest").Mock<(...args: any[]) => any>;
82
+ getCurrentTime: import("vitest").Mock<(...args: any[]) => any>;
83
+ isHighDefinitionInUse: import("vitest").Mock<(...args: any[]) => any>;
84
+ mute: import("vitest").Mock<(...args: any[]) => any>;
85
+ unmute: import("vitest").Mock<(...args: any[]) => any>;
86
+ volume: import("vitest").Mock<(...args: any[]) => any>;
87
+ configure: import("vitest").Mock<(...args: any[]) => any>;
88
+ attemptAutoPlay: import("vitest").Mock<(...args: any[]) => any>;
89
+ canAutoPlay: import("vitest").Mock<(...args: any[]) => any>;
90
+ onResize: import("vitest").Mock<(...args: any[]) => any>;
91
+ setPlaybackRate: import("vitest").Mock<(...args: any[]) => any>;
92
+ trigger: <T extends string | symbol>(event: T, ...args: any[]) => boolean;
91
93
  };
92
94
  export declare function createMockContainer(playback?: any): Events<string | symbol, any> & {
93
95
  el: HTMLDivElement;
@@ -95,6 +97,8 @@ export declare function createMockContainer(playback?: any): Events<string | sym
95
97
  $el: any;
96
98
  getDuration: import("vitest").Mock<(...args: any[]) => any>;
97
99
  getPlugin: import("vitest").Mock<(...args: any[]) => any>;
100
+ getPlaybackType: import("vitest").Mock<(...args: any[]) => any>;
101
+ isDvrInUse: import("vitest").Mock<(...args: any[]) => any>;
98
102
  isPlaying: import("vitest").Mock<(...args: any[]) => any>;
99
103
  play: import("vitest").Mock<(...args: any[]) => any>;
100
104
  seek: import("vitest").Mock<(...args: any[]) => any>;
@@ -1 +1 @@
1
- {"version":3,"file":"testUtils.d.ts","sourceRoot":"","sources":["../src/testUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAK,YAAY,EAAE,MAAM,cAAc,CAAA;AAC9C,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;;;;;;;;;;;;;;;;;;;;;;;;;mBA2C7B,MAAM,WAAW,GAAG,EAAE;EAIxC;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,GAAE,GAA0B;;;;;;;;;;EAcvE;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,GAAG,gBAqB/C"}
1
+ {"version":3,"file":"testUtils.d.ts","sourceRoot":"","sources":["../src/testUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAK,YAAY,EAAE,MAAM,cAAc,CAAA;AAC9C,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;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+B/C;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,GAAE,GAA0B;;;;;;;;;;;;EAgBvE;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,GAAG,gBAqB/C"}