@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.
Files changed (98) 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/dvr-controls/dvr_controls.scss +7 -25
  5. package/assets/dvr-controls/index.ejs +2 -2
  6. package/assets/media-control/container.scss +1 -1
  7. package/assets/media-control/media-control.ejs +1 -6
  8. package/assets/media-control/media-control.scss +14 -7
  9. package/assets/media-control/width270.scss +1 -1
  10. package/assets/media-control/width370.scss +5 -5
  11. package/assets/playback-rate/button.ejs +2 -2
  12. package/assets/playback-rate/list.ejs +4 -4
  13. package/assets/style/theme.scss +1 -1
  14. package/assets/subtitles/combobox.ejs +5 -5
  15. package/assets/subtitles/string.ejs +1 -1
  16. package/assets/subtitles/style.scss +2 -2
  17. package/dist/core.js +2 -1
  18. package/dist/index.css +993 -993
  19. package/dist/index.js +199 -178
  20. package/dist/player.d.ts +141 -119
  21. package/dist/plugins/index.css +1118 -1118
  22. package/dist/plugins/index.js +191 -173
  23. package/docs/api/player.bottomgear.getelement.md +2 -2
  24. package/docs/api/player.bottomgear.md +1 -1
  25. package/docs/api/{player.subtitles.hide.md → player.closedcaptions.hide.md} +2 -2
  26. package/docs/api/{player.subtitles.md → player.closedcaptions.md} +11 -11
  27. package/docs/api/{player.subtitles.show.md → player.closedcaptions.show.md} +2 -2
  28. package/docs/api/player.closedcaptionspluginsettings.md +13 -0
  29. package/docs/api/player.gearitemelement.md +6 -4
  30. package/docs/api/player.gearoptionsitem.md +16 -0
  31. package/docs/api/player.md +48 -12
  32. package/docs/api/player.mediacontrol.putelement.md +2 -2
  33. package/docs/api/player.mediacontrolelement.md +1 -1
  34. package/docs/api/player.playbackrate.md +1 -1
  35. package/docs/api/player.subtitlespluginsettings.md +18 -0
  36. package/docs/api/player.texttrackitem.id.md +11 -0
  37. package/docs/api/player.texttrackitem.md +87 -0
  38. package/docs/api/player.texttrackitem.name.md +11 -0
  39. package/docs/api/player.texttrackitem.track.md +11 -0
  40. package/lib/index.d.ts +1 -1
  41. package/lib/index.js +1 -1
  42. package/lib/index.plugins.d.ts +2 -1
  43. package/lib/index.plugins.d.ts.map +1 -1
  44. package/lib/index.plugins.js +2 -1
  45. package/lib/playback/dash-playback/DashPlayback.d.ts.map +1 -1
  46. package/lib/playback/dash-playback/DashPlayback.js +1 -0
  47. package/lib/plugins/audio-selector/AudioSelector.d.ts +2 -3
  48. package/lib/plugins/audio-selector/AudioSelector.d.ts.map +1 -1
  49. package/lib/plugins/audio-selector/AudioSelector.js +6 -7
  50. package/lib/plugins/bottom-gear/BottomGear.d.ts +6 -2
  51. package/lib/plugins/bottom-gear/BottomGear.d.ts.map +1 -1
  52. package/lib/plugins/bottom-gear/BottomGear.js +2 -1
  53. package/lib/plugins/dvr-controls/DvrControls.d.ts +0 -3
  54. package/lib/plugins/dvr-controls/DvrControls.d.ts.map +1 -1
  55. package/lib/plugins/dvr-controls/DvrControls.js +13 -38
  56. package/lib/plugins/media-control/MediaControl.d.ts +14 -18
  57. package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
  58. package/lib/plugins/media-control/MediaControl.js +105 -72
  59. package/lib/plugins/picture-in-picture/PictureInPicture.d.ts +1 -0
  60. package/lib/plugins/picture-in-picture/PictureInPicture.d.ts.map +1 -1
  61. package/lib/plugins/picture-in-picture/PictureInPicture.js +4 -4
  62. package/lib/plugins/playback-rate/PlaybackRate.d.ts +0 -1
  63. package/lib/plugins/playback-rate/PlaybackRate.d.ts.map +1 -1
  64. package/lib/plugins/playback-rate/PlaybackRate.js +23 -14
  65. package/lib/plugins/subtitles/ClosedCaptions.d.ts +118 -0
  66. package/lib/plugins/subtitles/ClosedCaptions.d.ts.map +1 -0
  67. package/lib/plugins/subtitles/ClosedCaptions.js +348 -0
  68. package/lib/plugins/subtitles/Subtitles.d.ts +12 -9
  69. package/lib/plugins/subtitles/Subtitles.d.ts.map +1 -1
  70. package/lib/plugins/subtitles/Subtitles.js +31 -32
  71. package/lib/testUtils.d.ts +26 -19
  72. package/lib/testUtils.d.ts.map +1 -1
  73. package/lib/testUtils.js +30 -45
  74. package/package.json +1 -1
  75. package/src/index.plugins.ts +2 -1
  76. package/src/index.ts +1 -1
  77. package/src/playback/dash-playback/DashPlayback.ts +1 -0
  78. package/src/plugins/audio-selector/AudioSelector.ts +9 -8
  79. package/src/plugins/bottom-gear/BottomGear.ts +11 -4
  80. package/src/plugins/bottom-gear/__tests__/BottomGear.test.ts +1 -1
  81. package/src/plugins/bottom-gear/__tests__/__snapshots__/BottomGear.test.ts.snap +2 -2
  82. package/src/plugins/dvr-controls/DvrControls.ts +16 -44
  83. package/src/plugins/dvr-controls/__tests__/DvrControls.test.ts +18 -22
  84. package/src/plugins/dvr-controls/__tests__/__snapshots__/DvrControls.test.ts.snap +6 -30
  85. package/src/plugins/media-control/MediaControl.ts +130 -85
  86. package/src/plugins/media-control/__tests__/MediaControl.test.ts +132 -0
  87. package/src/plugins/media-control/__tests__/__snapshots__/MediaControl.test.ts.snap +299 -0
  88. package/src/plugins/picture-in-picture/PictureInPicture.ts +5 -5
  89. package/src/plugins/playback-rate/PlaybackRate.ts +142 -100
  90. package/src/plugins/playback-rate/__tests__/PlaybackRate.test.ts +65 -0
  91. package/src/plugins/playback-rate/__tests__/__snapshots__/PlaybackRate.test.ts.snap +11 -0
  92. package/src/plugins/subtitles/{Subtitles.ts → ClosedCaptions.ts} +42 -34
  93. package/src/plugins/subtitles/__tests__/ClosedCaptions.test.ts +58 -0
  94. package/src/plugins/subtitles/__tests__/__snapshots__/ClosedCaptions.test.ts.snap +25 -0
  95. package/src/testUtils.ts +30 -45
  96. package/temp/player.api.json +269 -89
  97. package/tsconfig.tsbuildinfo +1 -1
  98. package/src/plugins/index.ts +0 -39
@@ -16,42 +16,50 @@ import type { ZeptoResult } from '../../types.js'
16
16
 
17
17
  const VERSION: string = '2.19.14'
18
18
 
19
- const LOCAL_STORAGE_SUBTITLES_ID = 'gplayer.plugins.subtitles.selected'
19
+ const LOCAL_STORAGE_CC_ID = 'gplayer.plugins.cc.selected'
20
20
 
21
- const T = 'plugins.subtitles'
21
+ const T = 'plugins.cc'
22
22
 
23
- export type SubtitlesPluginSettings = {
23
+ export type ClosedCaptionsPluginSettings = {
24
24
  /**
25
25
  * Initially selected subtitles language
26
26
  */
27
27
  language?: string
28
28
  }
29
29
 
30
+ /**
31
+ * @deprecated Use {@link ClosedCaptionsPluginSettings} instead.
32
+ */
33
+ export type SubtitlesPluginSettings = ClosedCaptionsPluginSettings;
34
+
30
35
  /**
31
36
  * `PLUGIN` that provides a UI to select the subtitles when available.
32
37
  * @beta
33
38
  *
34
39
  * @remarks
40
+ * The plugin is activated when closed captions tracks are provided with the media source.
41
+ * It shows a familiar "CC" button with a dropdown menu to select the subtitles language.
42
+ *
35
43
  * Depends on:
36
44
  *
37
45
  * - {@link MediaControl}
38
46
  *
39
- * Configuration options - {@link SubtitlesPluginSettings}
47
+ * Configuration options - {@link ClosedCaptionsPluginSettings}
40
48
  * @example
41
49
  * ```ts
42
- * import { Subtitles } from '@gcorevideo/player'
50
+ * import { ClosedCaptions } from '@gcorevideo/player'
43
51
  *
44
- * Player.registerPlugin(Subtitles)
52
+ * Player.registerPlugin(ClosedCaptions)
45
53
  *
46
54
  * new Player({
47
55
  * ...
48
- * subtitles: {
56
+ * cc: {
49
57
  * language: 'en',
50
58
  * },
51
59
  * })
52
60
  * ```
53
61
  */
54
- export class Subtitles extends UICorePlugin {
62
+ export class ClosedCaptions extends UICorePlugin {
55
63
  private isPreselectedApplied = false
56
64
 
57
65
  private isShowing = false
@@ -60,13 +68,13 @@ export class Subtitles extends UICorePlugin {
60
68
 
61
69
  private tracks: TextTrackItem[] = []
62
70
 
63
- private $string: ZeptoResult | null = null
71
+ private $line: ZeptoResult | null = null
64
72
 
65
73
  /**
66
74
  * @internal
67
75
  */
68
76
  get name() {
69
- return 'subtitles'
77
+ return 'cc'
70
78
  }
71
79
 
72
80
  /**
@@ -92,8 +100,7 @@ export class Subtitles extends UICorePlugin {
92
100
  */
93
101
  override get attributes() {
94
102
  return {
95
- class: 'media-control-subtitles',
96
- 'data-subtitles': '',
103
+ class: 'media-control-cc',
97
104
  }
98
105
  }
99
106
 
@@ -102,13 +109,13 @@ export class Subtitles extends UICorePlugin {
102
109
  */
103
110
  override get events() {
104
111
  return {
105
- 'click [data-subtitles-select]': 'onItemSelect',
106
- 'click [data-subtitles-button]': 'toggleMenu',
112
+ 'click [data-cc-select]': 'onItemSelect',
113
+ 'click [data-cc-button]': 'toggleMenu',
107
114
  }
108
115
  }
109
116
 
110
117
  private get preselectedLanguage(): string {
111
- return this.core.options.subtitles?.language ?? ''
118
+ return this.core.options.cc?.language ?? this.core.options.subtitles?.language ?? ''
112
119
  }
113
120
 
114
121
  /**
@@ -269,7 +276,7 @@ export class Subtitles extends UICorePlugin {
269
276
  hide() {
270
277
  this.isShowing = false
271
278
  this.renderIcon()
272
- this.$string.hide()
279
+ this.$line.hide()
273
280
  if (this.tracks) {
274
281
  for (const t of this.tracks) {
275
282
  t.track.mode = 'hidden'
@@ -290,25 +297,25 @@ export class Subtitles extends UICorePlugin {
290
297
  this.track.track.mode &&
291
298
  Browser.isiOS
292
299
  ) {
293
- this.$string.hide()
300
+ this.$line.hide()
294
301
  this.track.track.mode = 'showing'
295
302
  } else {
296
- this.$string.show()
303
+ this.$line.show()
297
304
  }
298
305
  }
299
306
 
300
307
  private shouldRender() {
301
- return this.tracks.length > 0
308
+ return this.tracks?.length > 0
302
309
  }
303
310
 
304
311
  private resizeFont() {
305
- if (!this.$string) {
312
+ if (!this.$line) {
306
313
  return
307
314
  }
308
315
 
309
316
  const skinWidth = this.core.activeContainer.$el.width()
310
317
 
311
- this.$string.find('p').css('font-size', skinWidth * 0.03)
318
+ this.$line.find('p').css('font-size', skinWidth * 0.03)
312
319
  }
313
320
 
314
321
  /**
@@ -325,13 +332,13 @@ export class Subtitles extends UICorePlugin {
325
332
 
326
333
  const mediaControl = this.core.getPlugin('media_control')
327
334
 
328
- this.$el.html(Subtitles.template({ tracks: this.tracks }))
329
- this.core.activeContainer.$el.find('.subtitle-string').remove()
330
- this.$string = $(Subtitles.templateString())
335
+ this.$el.html(ClosedCaptions.template({ tracks: this.tracks }))
336
+ this.core.activeContainer.$el.find('#cc-line').remove()
337
+ this.$line = $(ClosedCaptions.templateString())
331
338
  this.resizeFont()
332
339
 
333
- this.core.activeContainer.$el.append(this.$string)
334
- mediaControl.putElement('subtitlesSelector', this.$el)
340
+ this.core.activeContainer.$el.append(this.$line)
341
+ mediaControl.putElement('cc', this.el)
335
342
 
336
343
  this.updateSelection()
337
344
 
@@ -353,11 +360,11 @@ export class Subtitles extends UICorePlugin {
353
360
  }
354
361
 
355
362
  private onItemSelect(event: MouseEvent) {
356
- const id = (event.target as HTMLElement).dataset.subtitlesSelect ?? '-1'
363
+ const id = (event.target as HTMLElement).dataset.ccSelect ?? '-1'
357
364
 
358
365
  trace(`${T} onItemSelect`, { id })
359
366
 
360
- localStorage.setItem(LOCAL_STORAGE_SUBTITLES_ID, id)
367
+ localStorage.setItem(LOCAL_STORAGE_CC_ID, id)
361
368
  this.selectItem(this.findById(Number(id)))
362
369
 
363
370
  return false
@@ -380,21 +387,22 @@ export class Subtitles extends UICorePlugin {
380
387
  }
381
388
 
382
389
  private hideMenu() {
383
- ;(this.$('[data-subtitles] ul') as ZeptoResult).hide()
390
+ ;(this.$('[data-cc] ul') as ZeptoResult).hide()
384
391
  }
385
392
 
386
393
  private toggleMenu() {
387
- ;(this.$('[data-subtitles] ul') as ZeptoResult).toggle()
394
+ trace(`${T} toggleMenu`)
395
+ ;(this.$('[data-cc] ul') as ZeptoResult).toggle()
388
396
  }
389
397
 
390
398
  private itemElement(id: number): ZeptoResult {
391
399
  return (
392
- this.$(`ul li a[data-subtitles-select="${id}"]`) as ZeptoResult
400
+ this.$(`ul li a[data-cc-select="${id}"]`) as ZeptoResult
393
401
  ).parent()
394
402
  }
395
403
 
396
404
  private allItemElements(): ZeptoResult {
397
- return this.$('[data-subtitles] li')
405
+ return this.$('[data-cc] li')
398
406
  }
399
407
 
400
408
  private selectSubtitles() {
@@ -420,7 +428,7 @@ export class Subtitles extends UICorePlugin {
420
428
  }
421
429
 
422
430
  private setSubtitleText(text: string | DocumentFragment) {
423
- this.$string.find('p').html(text)
431
+ this.$line.find('p').html(text)
424
432
  }
425
433
 
426
434
  private clearSubtitleText() {
@@ -456,6 +464,6 @@ export class Subtitles extends UICorePlugin {
456
464
  private renderIcon() {
457
465
  const icon = this.isShowing ? subtitlesOnIcon : subtitlesOffIcon
458
466
 
459
- this.$el.find('span.subtitle-text').html(icon)
467
+ this.$el.find('span.cc-text').html(icon)
460
468
  }
461
469
  }
@@ -0,0 +1,58 @@
1
+ import { beforeEach, describe, expect, it, vi } from 'vitest'
2
+ import { ClosedCaptions } from '../ClosedCaptions.js'
3
+ import { createMockCore, createMockMediaControl } from '../../../testUtils.js';
4
+
5
+ describe('ClosedCaptions', () => {
6
+ let core: any;
7
+ let mediaControl: any;
8
+ let cc: ClosedCaptions;
9
+ beforeEach(() => {
10
+ core = createMockCore()
11
+ mediaControl = createMockMediaControl(core)
12
+ core.getPlugin = vi.fn().mockImplementation((name) => {
13
+ if (name === 'media_control') {
14
+ return mediaControl
15
+ }
16
+ return null
17
+ })
18
+ cc = new ClosedCaptions(core)
19
+ })
20
+ describe('basically', () => {
21
+ beforeEach(() => {
22
+ core.emit('core:ready')
23
+ core.activePlayback.el = document.createElement('video')
24
+ core.emit('core:active:container:changed', core.activeContainer)
25
+ core.activePlayback.closedCaptionsTracks = [
26
+ {
27
+ id: 1,
28
+ name: 'English',
29
+ track: {
30
+ language: 'en',
31
+ kind: 'subtitles',
32
+ label: 'English',
33
+ mode: 'hidden',
34
+ cues: [],
35
+ }
36
+ },
37
+ {
38
+ id: 2,
39
+ name: 'Spanish',
40
+ track: {
41
+ language: 'es',
42
+ kind: 'subtitles',
43
+ label: 'Spanish',
44
+ mode: 'hidden',
45
+ cues: [],
46
+ }
47
+ }
48
+ ]
49
+ core.activePlayback.emit('playback:subtitle:available')
50
+ core.activeContainer.emit('container:subtitle:available')
51
+ })
52
+ it('should render', () => {
53
+ expect(cc.el.innerHTML).toMatchSnapshot()
54
+ expect(cc.$el.find('[data-cc-button]').length).toEqual(1)
55
+ expect(mediaControl.putElement).toHaveBeenCalledWith('cc', cc.el)
56
+ })
57
+ })
58
+ })
@@ -0,0 +1,25 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`ClosedCaptions > basically > should render 1`] = `
4
+ "<button data-cc-button="" class="media-control-button media-control-icon gcore-skin-button-color" id="cc-button">
5
+ <span class="cc-text">/assets/icons/new/subtitles-off.svg</span>
6
+ </button>
7
+
8
+ <ul class="gcore-skin-bg-color" id="cc-select">
9
+
10
+ <li>
11
+ <a href="#" class="gcore-skin-text-color" data-cc-select="1">
12
+ English
13
+ </a>
14
+ </li>
15
+
16
+ <li>
17
+ <a href="#" class="gcore-skin-text-color" data-cc-select="2">
18
+ Spanish
19
+ </a>
20
+ </li>
21
+
22
+ <li class="current"><a href="#" class="gcore-skin-text-color gcore-skin-active" data-cc-select="-1">Off</a></li>
23
+ </ul>
24
+ "
25
+ `;
package/src/testUtils.ts 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
  /**
@@ -42,7 +42,7 @@ export class _MockPlayback extends Events {
42
42
  exitPiP() {}
43
43
 
44
44
  getPlaybackType() {
45
- return 'live'
45
+ return Playback.LIVE
46
46
  }
47
47
 
48
48
  getStartTimeOffset() {
@@ -100,7 +100,7 @@ export function createMockCore(
100
100
  ...options,
101
101
  },
102
102
  configure: vi.fn(),
103
- getPlaybackType: vi.fn(),
103
+ getPlaybackType: vi.fn().mockReturnValue(Playback.LIVE),
104
104
  getPlugin: vi.fn(),
105
105
  load: vi.fn(),
106
106
  trigger: emitter.emit,
@@ -126,52 +126,38 @@ export function createMockPlayback(name = 'mock') {
126
126
  return Object.assign(emitter, {
127
127
  name,
128
128
  currentLevel: -1,
129
+ el: document.createElement('video'),
130
+ dvrEnabled: false,
131
+ dvrInUse: false,
129
132
  levels: [],
130
133
  consent() {},
131
134
  play() {},
132
135
  pause() {},
133
136
  stop() {},
134
- destroy() {},
135
- seek() {},
136
- seekPercentage() {},
137
- getDuration() {
138
- return 100
139
- },
140
- enterPiP() {},
141
- exitPiP() {},
142
- getPlaybackType() {
143
- return 'live'
144
- },
145
- getStartTimeOffset() {
146
- return 0
147
- },
148
- getCurrentTime() {
149
- return 0
150
- },
151
- isHighDefinitionInUse() {
152
- return false
153
- },
154
- mute() {},
155
- unmute() {},
156
- volume() {},
157
- configure() {},
158
- attemptAutoPlay() {
159
- return true
160
- },
161
- canAutoPlay() {
162
- return true
163
- },
164
- onResize() {
165
- return true
166
- },
167
- trigger(event: string, ...args: any[]) {
168
- emitter.emit(event, ...args)
169
- },
137
+ destroy: vi.fn(),
138
+ seek: vi.fn(),
139
+ seekPercentage: vi.fn(),
140
+ getDuration: vi.fn().mockImplementation(() => 100),
141
+ enterPiP: vi.fn(),
142
+ exitPiP: vi.fn(),
143
+ getPlaybackType: vi.fn().mockImplementation(() => Playback.LIVE),
144
+ getStartTimeOffset: vi.fn().mockImplementation(() => 0),
145
+ getCurrentTime: vi.fn().mockImplementation(() => 0),
146
+ isHighDefinitionInUse: vi.fn().mockImplementation(() => false),
147
+ mute: vi.fn(),
148
+ unmute: vi.fn(),
149
+ volume: vi.fn(),
150
+ configure: vi.fn(),
151
+ attemptAutoPlay: vi.fn().mockImplementation(() => true),
152
+ canAutoPlay: vi.fn().mockImplementation(() => true),
153
+ onResize: vi.fn().mockImplementation(() => true),
154
+ setPlaybackRate: vi.fn(),
155
+ trigger: emitter.emit,
170
156
  })
171
157
  }
172
158
 
173
159
  export function createMockContainer(playback: any = createMockPlayback()) {
174
- const el = document.createElement('div')
160
+ const el = playback.el
175
161
  const emitter = new Events()
176
162
  return Object.assign(emitter, {
177
163
  el,
@@ -179,6 +165,9 @@ export function createMockContainer(playback: any = createMockPlayback()) {
179
165
  $el: $(el),
180
166
  getDuration: vi.fn().mockReturnValue(0),
181
167
  getPlugin: vi.fn(),
168
+ getPlaybackType: vi.fn().mockReturnValue(Playback.LIVE),
169
+ isDvrInUse: vi.fn().mockReturnValue(false),
170
+ isDvrEnabled: vi.fn().mockReturnValue(false),
182
171
  isPlaying: vi.fn().mockReturnValue(false),
183
172
  play: vi.fn(),
184
173
  seek: vi.fn(),
@@ -201,10 +190,6 @@ export function createMockMediaControl(core: any) {
201
190
  // @ts-ignore
202
191
  mediaControl.putElement = vi.fn()
203
192
  // @ts-ignore
204
- mediaControl.getLeftPanel = vi.fn().mockImplementation(() => mediaControl.$el.find('.media-control-left-panel'))
205
- // @ts-ignore
206
- mediaControl.getRightPanel = vi.fn().mockImplementation(() => mediaControl.$el.find('.media-control-right-panel'))
207
- // @ts-ignore
208
- mediaControl.getCenterPanel = vi.fn().mockImplementation(() => mediaControl.$el.find('.media-control-center-panel'))
193
+ mediaControl.toggleElement = vi.fn()
209
194
  return mediaControl
210
195
  }