@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.
- package/assets/bottom-gear/gear.scss +20 -13
- package/assets/clappr-nerd-stats/button.ejs +2 -2
- package/assets/clappr-nerd-stats/clappr-nerd-stats.scss +0 -43
- package/assets/level-selector/button.ejs +3 -3
- package/assets/level-selector/style.scss +0 -5
- package/assets/playback-rate/button.ejs +2 -2
- package/dist/core.js +22 -1
- package/dist/index.css +599 -630
- package/dist/index.js +56 -40
- package/dist/plugins/index.css +1485 -1516
- package/dist/plugins/index.js +35 -40
- package/lib/playback/hls-playback/HlsPlayback.d.ts.map +1 -1
- package/lib/playback/hls-playback/HlsPlayback.js +21 -0
- package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.d.ts.map +1 -1
- package/lib/plugins/media-control/MediaControl.d.ts +4 -1
- package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
- package/lib/plugins/media-control/MediaControl.js +30 -14
- package/lib/plugins/playback-rate/PlaybackRate.d.ts.map +1 -1
- package/lib/plugins/playback-rate/PlaybackRate.js +1 -22
- package/package.json +1 -1
- package/src/playback/hls-playback/HlsPlayback.ts +22 -0
- package/src/plugins/clappr-nerd-stats/ClapprNerdStats.ts +0 -1
- package/src/plugins/level-selector/__tests__/__snapshots__/QualityLevels.test.ts.snap +3 -3
- package/src/plugins/media-control/MediaControl.ts +36 -15
- package/src/plugins/media-control/__tests__/MediaControl.test.ts +43 -10
- package/src/plugins/media-control/__tests__/__snapshots__/MediaControl.test.ts.snap +20 -20
- package/src/plugins/playback-rate/PlaybackRate.ts +1 -24
- package/src/plugins/playback-rate/__tests__/PlaybackRate.test.ts +2 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/assets/clappr-nerd-stats/options-list.ejs +0 -9
- 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
|
|
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
|
-
|
|
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.
|
|
551
|
-
|
|
552
|
-
this
|
|
553
|
-
|
|
554
|
-
this
|
|
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.
|
|
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.
|
|
1410
|
-
if (!this.
|
|
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.
|
|
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('
|
|
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', '
|
|
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).
|
|
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.
|
|
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.
|
|
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 >
|
|
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
|
|
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
|
-
|
|
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 >
|
|
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(() => {
|