@gcorevideo/player 2.22.13 → 2.22.14

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 (31) hide show
  1. package/assets/bottom-gear/gear.scss +20 -13
  2. package/assets/clappr-nerd-stats/button.ejs +2 -2
  3. package/assets/clappr-nerd-stats/clappr-nerd-stats.scss +0 -43
  4. package/assets/level-selector/button.ejs +3 -3
  5. package/assets/level-selector/style.scss +0 -5
  6. package/assets/playback-rate/button.ejs +2 -2
  7. package/dist/core.js +22 -1
  8. package/dist/index.css +599 -630
  9. package/dist/index.js +56 -40
  10. package/dist/plugins/index.css +1485 -1516
  11. package/dist/plugins/index.js +35 -40
  12. package/lib/playback/hls-playback/HlsPlayback.d.ts.map +1 -1
  13. package/lib/playback/hls-playback/HlsPlayback.js +21 -0
  14. package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.d.ts.map +1 -1
  15. package/lib/plugins/media-control/MediaControl.d.ts +4 -1
  16. package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
  17. package/lib/plugins/media-control/MediaControl.js +30 -14
  18. package/lib/plugins/playback-rate/PlaybackRate.d.ts.map +1 -1
  19. package/lib/plugins/playback-rate/PlaybackRate.js +1 -22
  20. package/package.json +1 -1
  21. package/src/playback/hls-playback/HlsPlayback.ts +22 -0
  22. package/src/plugins/clappr-nerd-stats/ClapprNerdStats.ts +0 -1
  23. package/src/plugins/level-selector/__tests__/__snapshots__/QualityLevels.test.ts.snap +3 -3
  24. package/src/plugins/media-control/MediaControl.ts +36 -15
  25. package/src/plugins/media-control/__tests__/MediaControl.test.ts +43 -10
  26. package/src/plugins/media-control/__tests__/__snapshots__/MediaControl.test.ts.snap +20 -20
  27. package/src/plugins/playback-rate/PlaybackRate.ts +1 -24
  28. package/src/plugins/playback-rate/__tests__/PlaybackRate.test.ts +2 -1
  29. package/tsconfig.tsbuildinfo +1 -1
  30. package/assets/clappr-nerd-stats/options-list.ejs +0 -9
  31. package/assets/clappr-nerd-stats/settings.ejs +0 -12
@@ -50,8 +50,6 @@ export type MediaControlLeftElement =
50
50
  | 'playstop'
51
51
  | 'position'
52
52
  | 'volume'
53
- // | 'seekbar'
54
- // | 'seekBarContainer' // TODO rename seekbar
55
53
 
56
54
  /**
57
55
  * Media control elements that appear in main layer, spanning the entire width of the player.
@@ -197,10 +195,14 @@ export class MediaControl extends UICorePlugin {
197
195
  private lastMouseX = 0
198
196
  private lastMouseY = 0
199
197
 
200
- private needsUpdate = false
198
+ private metadataLoaded = false
199
+
200
+ private hasUpdate = false
201
201
 
202
202
  private persistConfig: boolean
203
203
 
204
+ private renderTimerId: ReturnType<typeof setTimeout> | null = null
205
+
204
206
  private rendered = false
205
207
 
206
208
  private settings: MediaControlSettings = INITIAL_SETTINGS
@@ -492,12 +494,18 @@ export class MediaControl extends UICorePlugin {
492
494
  Events.CONTAINER_OPTIONS_CHANGE,
493
495
  this.setInitialVolume,
494
496
  )
495
- // wait until the metadata has loaded and then check if fullscreen on video tag is supported
496
- this.listenToOnce(
497
+ this.listenTo(
497
498
  this.core.activeContainer,
498
499
  Events.CONTAINER_LOADEDMETADATA,
499
500
  this.onLoadedMetadata,
500
501
  )
502
+ this.listenTo(
503
+ this.core,
504
+ Events.CONTAINER_DESTROYED,
505
+ () => {
506
+ this.cancelRenderTimer()
507
+ },
508
+ )
501
509
  }
502
510
 
503
511
  /**
@@ -547,12 +555,16 @@ export class MediaControl extends UICorePlugin {
547
555
  // TODO sort out, use single utility function
548
556
  this.fullScreenOnVideoTagSupported = true
549
557
  }
550
- this.updateSettings()
551
- if (this.core.activeContainer.getPlaybackType() === Playback.LIVE) {
552
- this.$el.addClass('live')
553
- } else {
554
- this.$el.removeClass('live')
555
- }
558
+ this.renderTimerId = setTimeout(() => {
559
+ this.renderTimerId = null
560
+ this.metadataLoaded = true
561
+ this.render()
562
+ if (this.core.activeContainer.getPlaybackType() === Playback.LIVE) {
563
+ this.$el.addClass('live')
564
+ } else {
565
+ this.$el.removeClass('live')
566
+ }
567
+ }, 25)
556
568
  }
557
569
 
558
570
  private updateVolumeUI() {
@@ -822,6 +834,7 @@ export class MediaControl extends UICorePlugin {
822
834
 
823
835
  private onActiveContainerChanged() {
824
836
  this.fullScreenOnVideoTagSupported = false
837
+ this.metadataLoaded = false
825
838
  // set the new container to match the volume of the last one
826
839
  this.setInitialVolume()
827
840
  this.changeTogglePlay()
@@ -1113,7 +1126,7 @@ export class MediaControl extends UICorePlugin {
1113
1126
 
1114
1127
  if (settingsChanged) {
1115
1128
  this.settings = newSettings
1116
- this.needsUpdate = true
1129
+ this.hasUpdate = true
1117
1130
  this.render()
1118
1131
  }
1119
1132
  }
@@ -1390,6 +1403,7 @@ export class MediaControl extends UICorePlugin {
1390
1403
  * @internal
1391
1404
  */
1392
1405
  override destroy() {
1406
+ this.cancelRenderTimer()
1393
1407
  $(document).unbind('mouseup', this.stopDrag)
1394
1408
  $(document).unbind('mousemove', this.updateDrag)
1395
1409
  $(document).unbind('touchend', this.stopDrag)
@@ -1398,6 +1412,13 @@ export class MediaControl extends UICorePlugin {
1398
1412
  return super.destroy()
1399
1413
  }
1400
1414
 
1415
+ private cancelRenderTimer() {
1416
+ if (this.renderTimerId) {
1417
+ clearTimeout(this.renderTimerId)
1418
+ this.renderTimerId = null
1419
+ }
1420
+ }
1421
+
1401
1422
  private configure() {
1402
1423
  this.trigger(Events.MEDIACONTROL_OPTIONS_CHANGE)
1403
1424
  }
@@ -1406,8 +1427,8 @@ export class MediaControl extends UICorePlugin {
1406
1427
  * @internal
1407
1428
  */
1408
1429
  override render() {
1409
- trace(`${T} render`, { needsUpdate: this.needsUpdate })
1410
- if (!this.needsUpdate) {
1430
+ trace(`${T} render`, { needsUpdate: this.hasUpdate, metadataLoaded: this.metadataLoaded })
1431
+ if (!this.hasUpdate || !this.metadataLoaded) {
1411
1432
  return this
1412
1433
  }
1413
1434
  const timeout = this.options.hideMediaControlDelay || 2000
@@ -1471,7 +1492,7 @@ export class MediaControl extends UICorePlugin {
1471
1492
  this.rendered = true
1472
1493
  this.updateVolumeUI()
1473
1494
 
1474
- this.needsUpdate = false
1495
+ this.hasUpdate = false
1475
1496
  // TODO setTimeout?
1476
1497
  this.trigger(Events.MEDIACONTROL_RENDERED)
1477
1498
 
@@ -32,21 +32,57 @@ describe('MediaControl', () => {
32
32
  expect(mediaControl.el.innerHTML).toBe('')
33
33
  })
34
34
  })
35
- describe('when container settings update', () => {
35
+ describe('rendering timing', () => {
36
36
  beforeEach(() => {
37
+ mediaControl = new MediaControl(core)
38
+ core.emit(Events.CORE_READY)
39
+ core.emit(Events.CORE_ACTIVE_CONTAINER_CHANGED, core.activeContainer)
40
+ core.activeContainer.settings = {
41
+ left: ['playpause', 'position', 'duration', 'volume'],
42
+ default: ['seekbar'],
43
+ right: ['fullscreen', 'hd-indicator'],
44
+ seekEnabled: true,
45
+ } as MediaControlSettings
46
+ core.activePlayback.emit(Events.PLAYBACK_SETTINGSUPDATE)
47
+ core.activeContainer.emit(Events.CONTAINER_SETTINGSUPDATE)
48
+ })
49
+ describe('until metadata is loaded', () => {
50
+ it('should not render', () => {
51
+ expect(mediaControl.el.innerHTML).toBe('')
52
+ })
53
+ })
54
+ describe('once metadata is loaded', () => {
55
+ beforeEach(() => {
56
+ core.activePlayback.emit(Events.PLAYBACK_LOADEDMETADATA)
57
+ core.activeContainer.emit(Events.CONTAINER_LOADEDMETADATA)
58
+ })
59
+ it('should wait a delay before rendering anything', async () => {
60
+ expect(mediaControl.el.innerHTML).toBe('')
61
+ await new Promise((resolve) => setTimeout(resolve, 35))
62
+ expect(mediaControl.el.innerHTML).toMatchSnapshot()
63
+ expect(mediaControl.$el.find('.media-control-left-panel [data-playpause]').length).toBeGreaterThan(0)
64
+ expect(mediaControl.$el.find('.media-control-left-panel [data-volume]').length).toBeGreaterThan(0)
65
+ expect(mediaControl.$el.find('.media-control-center-panel [data-seekbar]').length).toBeGreaterThan(0)
66
+ expect(mediaControl.$el.find('.media-control-right-panel [data-fullscreen]').length).toBeGreaterThan(0)
67
+ })
68
+ })
69
+ })
70
+ describe('when container settings update', () => {
71
+ beforeEach(async () => {
37
72
  mediaControl = new MediaControl(core)
38
73
  core.emit(Events.CORE_READY)
39
74
  core.emit(Events.CORE_ACTIVE_CONTAINER_CHANGED, core.activeContainer)
40
75
  core.activePlayback.emit(Events.PLAYBACK_LOADEDMETADATA)
41
76
  core.activeContainer.emit(Events.CONTAINER_LOADEDMETADATA)
77
+ await new Promise((resolve) => setTimeout(resolve, 25))
42
78
  })
43
79
  describe.each([
44
80
  [
45
81
  'vod',
46
82
  {
47
- left: ['playpause', 'position', 'duration'],
83
+ left: ['playpause', 'position', 'duration', 'volume'],
48
84
  default: ['seekbar'],
49
- right: ['fullscreen', 'volume', 'hd-indicator'],
85
+ right: ['fullscreen', 'hd-indicator'],
50
86
  seekEnabled: true,
51
87
  } as MediaControlSettings,
52
88
  ],
@@ -56,17 +92,14 @@ describe('MediaControl', () => {
56
92
  core.activePlayback.emit(Events.PLAYBACK_SETTINGSUPDATE)
57
93
  core.activeContainer.emit(Events.CONTAINER_SETTINGSUPDATE)
58
94
  })
59
- it('should render', () => {
60
- expect(mediaControl.el.innerHTML).toMatchSnapshot()
61
- })
62
95
  it.each(
63
96
  settings.left
64
97
  )("should render %s control", (element) => {
65
98
  const el = mediaControl.$el.find(`.media-control-left-panel [data-${element}]`)
66
- expect(el.length).toEqual(1)
99
+ expect(el.length).toBeGreaterThan(0)
67
100
  })
68
101
  it.each(
69
- arraySubtract(['playpause', 'playstop', 'position', 'duration'], settings.left)
102
+ arraySubtract(['playpause', 'playstop', 'position', 'duration', 'volume'], settings.left)
70
103
  )("should not render %s control", (element) => {
71
104
  const el = mediaControl.$el.find(`.media-control-left-panel [data-${element}]`)
72
105
  expect(el.length).toEqual(0)
@@ -80,9 +113,9 @@ describe('MediaControl', () => {
80
113
  expect(seekbar.hasClass('seek-disabled')).toBe(true)
81
114
  }
82
115
  })
83
- it(`should ${settings.right.includes('volume') ? '' : 'not '}render the volume control`, () => {
116
+ it(`should ${settings.left.includes('volume') ? '' : 'not '}render the volume control`, () => {
84
117
  const volume = mediaControl.$el.find('.drawer-container[data-volume]')
85
- if (settings.right.includes('volume')) {
118
+ if (settings.left.includes('volume')) {
86
119
  expect(volume.length).toEqual(1)
87
120
  } else {
88
121
  expect(volume.length).toEqual(0)
@@ -236,7 +236,7 @@ exports[`MediaControl > putElement > pip > should put the element in the right p
236
236
  <style>:root {}</style>"
237
237
  `;
238
238
 
239
- exports[`MediaControl > updateSettings > dvr > when disabled > should disable DVR controls 1`] = `
239
+ exports[`MediaControl > rendering timing > once metadata is loaded > should wait a delay before rendering anything 1`] = `
240
240
  "<div class="media-control-background" data-background=""></div>
241
241
 
242
242
  <div class="media-control-layer gcore-skin-bg-color" data-controls="">
@@ -286,6 +286,21 @@ exports[`MediaControl > updateSettings > dvr > when disabled > should disable DV
286
286
  </div>
287
287
 
288
288
 
289
+ <div class="media-control-center-panel" data-media-control="">
290
+
291
+ <div class="bar-container" data-seekbar="">
292
+ <div class="bar-background" data-seekbar="">
293
+ <div class="bar-fill-1" data-seekbar=""></div>
294
+ <div class="bar-fill-2 gcore-skin-main-color" data-seekbar="" style=""></div>
295
+ <div class="bar-hover" data-seekbar=""></div>
296
+ </div>
297
+ </div>
298
+ <div class="bar-scrubber" data-seekbar="" style="">
299
+ <div class="bar-scrubber-icon gcore-skin-main-color" data-seekbar=""></div>
300
+ </div>
301
+
302
+ </div>
303
+
289
304
 
290
305
  <div class="media-control-right-panel" data-media-control="">
291
306
 
@@ -301,7 +316,7 @@ exports[`MediaControl > updateSettings > dvr > when disabled > should disable DV
301
316
  <style>:root {}</style>"
302
317
  `;
303
318
 
304
- exports[`MediaControl > updateSettings > dvr > when enabled > should enable DVR controls 1`] = `
319
+ exports[`MediaControl > updateSettings > dvr > when disabled > should disable DVR controls 1`] = `
305
320
  "<div class="media-control-background" data-background=""></div>
306
321
 
307
322
  <div class="media-control-layer gcore-skin-bg-color" data-controls="">
@@ -348,7 +363,7 @@ exports[`MediaControl > updateSettings > dvr > when enabled > should enable DVR
348
363
  <div class="media-clip-text gcore-skin-text-color" data-clipstext=""></div>
349
364
  </div>
350
365
 
351
- <div class="my-dvr-controls" data-dvr="">live</div></div>
366
+ </div>
352
367
 
353
368
 
354
369
 
@@ -366,7 +381,7 @@ exports[`MediaControl > updateSettings > dvr > when enabled > should enable DVR
366
381
  <style>:root {}</style>"
367
382
  `;
368
383
 
369
- exports[`MediaControl > when container settings update > vod > should render 1`] = `
384
+ exports[`MediaControl > updateSettings > dvr > when enabled > should enable DVR controls 1`] = `
370
385
  "<div class="media-control-background" data-background=""></div>
371
386
 
372
387
  <div class="media-control-layer gcore-skin-bg-color" data-controls="">
@@ -413,23 +428,8 @@ exports[`MediaControl > when container settings update > vod > should render 1`]
413
428
  <div class="media-clip-text gcore-skin-text-color" data-clipstext=""></div>
414
429
  </div>
415
430
 
416
- </div>
417
-
418
-
419
- <div class="media-control-center-panel" data-media-control="">
420
-
421
- <div class="bar-container" data-seekbar="">
422
- <div class="bar-background" data-seekbar="">
423
- <div class="bar-fill-1" data-seekbar=""></div>
424
- <div class="bar-fill-2 gcore-skin-main-color" data-seekbar="" style=""></div>
425
- <div class="bar-hover" data-seekbar=""></div>
426
- </div>
427
- </div>
428
- <div class="bar-scrubber" data-seekbar="" style="">
429
- <div class="bar-scrubber-icon gcore-skin-main-color" data-seekbar=""></div>
430
- </div>
431
+ <div class="my-dvr-controls" data-dvr="">live</div></div>
431
432
 
432
- </div>
433
433
 
434
434
 
435
435
  <div class="media-control-right-panel" data-media-control="">
@@ -85,8 +85,6 @@ export class PlaybackRate extends UICorePlugin {
85
85
 
86
86
  private metadataLoaded = false
87
87
 
88
- // private playbackSettingsUpdateReceived = false
89
-
90
88
  private mountTimerId: TimerId | null = null
91
89
 
92
90
  /**
@@ -167,14 +165,8 @@ export class PlaybackRate extends UICorePlugin {
167
165
  private onActiveContainerChange() {
168
166
  trace(`${T} onActiveContainerChange`)
169
167
  this.metadataLoaded = false
170
- // this.playbackSettingsUpdateReceived = false
171
168
  this.listenTo(this.core.activePlayback, Events.PLAYBACK_STOP, this.onStop)
172
169
  this.listenTo(this.core.activePlayback, Events.PLAYBACK_PLAY, this.onPlay)
173
- // this.listenTo(
174
- // this.core.activePlayback,
175
- // Events.PLAYBACK_SETTINGSUPDATE,
176
- // this.onSettingsUpdate,
177
- // )
178
170
  this.listenTo(
179
171
  this.core.activePlayback,
180
172
  PlaybackEvents.PLAYBACK_RATE_CHANGED,
@@ -219,28 +211,13 @@ export class PlaybackRate extends UICorePlugin {
219
211
  )
220
212
  }
221
213
 
222
- // private onSettingsUpdate() {
223
- // trace(`${T} onSettingsUpdate`, {
224
- // playbackType: this.core.activePlayback.getPlaybackType(),
225
- // dvrEnabled: this.core.activePlayback.dvrEnabled,
226
- // })
227
- // this.playbackSettingsUpdateReceived = true
228
- // if (this.metadataLoaded) {
229
- // if (this.mountTimerId) {
230
- // clearTimeout(this.mountTimerId)
231
- // this.mountTimerId = null
232
- // }
233
- // this.mount()
234
- // }
235
- // }
236
-
237
214
  private onMetaDataLoaded() {
238
215
  trace(`${T} onMetaDataLoaded`, {
239
216
  playbackType: this.core.activePlayback.getPlaybackType(),
240
217
  dvrEnabled: this.core.activePlayback.dvrEnabled,
241
218
  })
242
- this.metadataLoaded = true
243
219
  this.mountTimerId = setTimeout(() => {
220
+ this.metadataLoaded = true
244
221
  this.mountTimerId = null
245
222
  this.mount()
246
223
  }, 25)
@@ -89,11 +89,12 @@ describe('PlaybackRate', () => {
89
89
  })
90
90
  });
91
91
  describe('on playback rate select', () => {
92
- beforeEach(() => {
92
+ beforeEach(async () => {
93
93
  core.activePlayback.dvrEnabled = true
94
94
  core.activeContainer.isDvrEnabled.mockReturnValue(true)
95
95
  core.activePlayback.emit(Events.PLAYBACK_LOADEDMETADATA)
96
96
  core.activeContainer.emit(Events.CONTAINER_LOADEDMETADATA)
97
+ await new Promise((resolve) => setTimeout(resolve, 25))
97
98
  })
98
99
  describe.each([[2], [1.5], [1.25], [0.75], [0.5]])('%s', (rate) => {
99
100
  beforeEach(() => {