@gcorevideo/player 2.22.0 → 2.22.1
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/bottomgear copy.ejs +10 -0
- package/assets/bottom-gear/bottomgear.ejs +4 -8
- package/assets/bottom-gear/gear-sub-menu.scss +0 -1
- package/assets/bottom-gear/gear.scss +0 -1
- package/assets/clappr-nerd-stats/button.ejs +3 -3
- package/assets/level-selector/button.ejs +2 -4
- package/assets/level-selector/list.ejs +14 -10
- package/assets/level-selector/style.scss +9 -4
- package/assets/playback-rate/list.ejs +5 -5
- package/dist/core.js +1 -2
- package/dist/index.css +1104 -1103
- package/dist/index.js +3849 -3767
- package/dist/player.d.ts +10 -17
- package/dist/plugins/index.css +1541 -1540
- package/dist/plugins/index.js +3949 -3868
- package/docs/api/player.mediacontrol.md +8 -36
- package/docs/api/player.mediacontrol.toggleelement.md +72 -0
- package/docs/api/player.mediacontrolelement.md +1 -1
- package/lib/playback/dash-playback/DashPlayback.d.ts.map +1 -1
- package/lib/playback/dash-playback/DashPlayback.js +0 -1
- package/lib/plugins/bottom-gear/BottomGear.d.ts +65 -14
- package/lib/plugins/bottom-gear/BottomGear.d.ts.map +1 -1
- package/lib/plugins/bottom-gear/BottomGear.js +113 -37
- package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.d.ts +2 -3
- package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.d.ts.map +1 -1
- package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.js +18 -15
- package/lib/plugins/dvr-controls/DvrControls.js +1 -1
- package/lib/plugins/level-selector/LevelSelector.d.ts +8 -11
- package/lib/plugins/level-selector/LevelSelector.d.ts.map +1 -1
- package/lib/plugins/level-selector/LevelSelector.js +66 -102
- package/lib/plugins/media-control/MediaControl.d.ts +7 -5
- package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
- package/lib/plugins/media-control/MediaControl.js +37 -19
- package/lib/plugins/picture-in-picture/PictureInPicture.d.ts.map +1 -1
- package/lib/plugins/picture-in-picture/PictureInPicture.js +7 -2
- package/lib/plugins/playback-rate/PlaybackRate.d.ts +42 -14
- package/lib/plugins/playback-rate/PlaybackRate.d.ts.map +1 -1
- package/lib/plugins/playback-rate/PlaybackRate.js +101 -83
- package/lib/plugins/subtitles/ClosedCaptions.js +1 -1
- package/lib/testUtils.d.ts +1 -0
- package/lib/testUtils.d.ts.map +1 -1
- package/lib/testUtils.js +13 -0
- package/package.json +1 -1
- package/src/playback/dash-playback/DashPlayback.ts +0 -1
- package/src/plugins/bottom-gear/BottomGear.ts +162 -72
- package/src/plugins/bottom-gear/__tests__/BottomGear.test.ts +21 -5
- package/src/plugins/bottom-gear/__tests__/__snapshots__/BottomGear.test.ts.snap +5 -12
- package/src/plugins/clappr-nerd-stats/ClapprNerdStats.ts +27 -25
- package/src/plugins/dvr-controls/DvrControls.ts +1 -1
- package/src/plugins/dvr-controls/__tests__/DvrControls.test.ts +1 -1
- package/src/plugins/level-selector/LevelSelector.ts +80 -120
- package/src/plugins/level-selector/__tests__/LevelSelector.test.ts +69 -79
- package/src/plugins/level-selector/__tests__/__snapshots__/LevelSelector.test.ts.snap +38 -71
- package/src/plugins/media-control/MediaControl.ts +51 -25
- package/src/plugins/media-control/__tests__/MediaControl.test.ts +4 -4
- package/src/plugins/picture-in-picture/PictureInPicture.ts +7 -2
- package/src/plugins/playback-rate/PlaybackRate.ts +136 -108
- package/src/plugins/playback-rate/__tests__/PlaybackRate.test.ts +84 -37
- package/src/plugins/playback-rate/__tests__/__snapshots__/PlaybackRate.test.ts.snap +55 -6
- package/src/plugins/subtitles/ClosedCaptions.ts +1 -1
- package/src/plugins/subtitles/__tests__/ClosedCaptions.test.ts +1 -1
- package/src/testUtils.ts +14 -0
- package/src/typings/vitest.d.ts +1 -0
- package/temp/player.api.json +66 -94
- package/tsconfig.tsbuildinfo +1 -1
- package/docs/api/player.mediacontrol.getcenterpanel.md +0 -18
- package/docs/api/player.mediacontrol.getleftpanel.md +0 -22
- package/docs/api/player.mediacontrol.getrightpanel.md +0 -22
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Events, UICorePlugin, Playback, template, Core } from '@clappr/core'
|
|
1
|
+
import { Events, UICorePlugin, Playback, template, Core, $ } from '@clappr/core'
|
|
2
2
|
import { trace } from '@gcorevideo/utils'
|
|
3
3
|
import assert from 'assert'
|
|
4
4
|
|
|
@@ -11,29 +11,37 @@ import speedIcon from '../../../assets/icons/new/speed.svg'
|
|
|
11
11
|
import arrowRightIcon from '../../../assets/icons/new/arrow-right.svg'
|
|
12
12
|
import arrowLeftIcon from '../../../assets/icons/new/arrow-left.svg'
|
|
13
13
|
import checkIcon from '../../../assets/icons/new/check.svg'
|
|
14
|
-
import { BottomGear } from '../bottom-gear/BottomGear.js'
|
|
14
|
+
import { BottomGear, GearEvents } from '../bottom-gear/BottomGear.js'
|
|
15
15
|
import { PlaybackEvents } from '../../playback/types.js'
|
|
16
|
-
import {
|
|
17
|
-
MediaControl,
|
|
18
|
-
MediaControlEvents,
|
|
19
|
-
} from '../media-control/MediaControl.js'
|
|
16
|
+
import { MediaControl } from '../media-control/MediaControl.js'
|
|
20
17
|
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
/**
|
|
19
|
+
* @beta
|
|
20
|
+
*/
|
|
21
|
+
export type PlaybackRateOption = {
|
|
22
|
+
value: number
|
|
23
23
|
label: string
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
/**
|
|
27
|
+
* @beta
|
|
28
|
+
*/
|
|
29
|
+
export type PlaybackRateSettings = {
|
|
30
|
+
options?: PlaybackRateOption[]
|
|
31
|
+
defaultValue?: number
|
|
32
|
+
}
|
|
33
|
+
|
|
26
34
|
const DEFAULT_PLAYBACK_RATES = [
|
|
27
|
-
{ value:
|
|
28
|
-
{ value:
|
|
29
|
-
{ value:
|
|
30
|
-
{ value:
|
|
31
|
-
{ value:
|
|
32
|
-
{ value:
|
|
33
|
-
{ value:
|
|
35
|
+
{ value: 0.5, label: '0.5x' },
|
|
36
|
+
{ value: 0.75, label: '0.75x' },
|
|
37
|
+
{ value: 1.0, label: '1x' },
|
|
38
|
+
{ value: 1.25, label: '1.25x' },
|
|
39
|
+
{ value: 1.5, label: '1.5x' },
|
|
40
|
+
{ value: 1.75, label: '1.75x' },
|
|
41
|
+
{ value: 2.0, label: '2x' },
|
|
34
42
|
]
|
|
35
43
|
|
|
36
|
-
const DEFAULT_PLAYBACK_RATE =
|
|
44
|
+
const DEFAULT_PLAYBACK_RATE = 1
|
|
37
45
|
|
|
38
46
|
const T = 'plugins.playback_rate'
|
|
39
47
|
|
|
@@ -44,22 +52,37 @@ const T = 'plugins.playback_rate'
|
|
|
44
52
|
* @remarks
|
|
45
53
|
* Depends on:
|
|
46
54
|
*
|
|
47
|
-
* - {@link MediaControl
|
|
55
|
+
* - {@link MediaControl}
|
|
56
|
+
*
|
|
57
|
+
* - {@link BottomGear}
|
|
48
58
|
*
|
|
49
|
-
*
|
|
59
|
+
* It renders an option in the gear menu, which opens a dropdown with the options to change the playback rate.
|
|
60
|
+
* Note that the playback rate change is supported only for VOD or DVR-enabled live streams.
|
|
50
61
|
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
62
|
+
* Plugin settings - {@link PlaybackRateSettings}
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```ts
|
|
66
|
+
* import { Player, PlaybackRateSettings } from '@gcorevideo/player'
|
|
67
|
+
* Player.registerPlugin(PlaybackRate)
|
|
68
|
+
* const player = new Player({
|
|
69
|
+
* playbackRate: {
|
|
70
|
+
* options: [
|
|
71
|
+
* { value: 0.5, label: '0.5x' },
|
|
72
|
+
* { value: 1, label: '1x' },
|
|
73
|
+
* ],
|
|
74
|
+
* defaultValue: 1,
|
|
75
|
+
* } as PlaybackRateSettings,
|
|
76
|
+
* })
|
|
77
|
+
* ```
|
|
53
78
|
*/
|
|
54
79
|
export class PlaybackRate extends UICorePlugin {
|
|
55
80
|
private playbackRates: PlaybackRateOption[] = DEFAULT_PLAYBACK_RATES
|
|
56
81
|
|
|
57
82
|
// Saved when an ad starts to restore after it finishes
|
|
58
|
-
private prevSelectedRate: string | undefined
|
|
59
|
-
|
|
60
|
-
private rendered = false
|
|
83
|
+
// private prevSelectedRate: string | undefined
|
|
61
84
|
|
|
62
|
-
private selectedRate
|
|
85
|
+
private selectedRate = DEFAULT_PLAYBACK_RATE
|
|
63
86
|
|
|
64
87
|
/**
|
|
65
88
|
* @internal
|
|
@@ -101,9 +124,8 @@ export class PlaybackRate extends UICorePlugin {
|
|
|
101
124
|
*/
|
|
102
125
|
override get events() {
|
|
103
126
|
return {
|
|
104
|
-
'click
|
|
105
|
-
'click
|
|
106
|
-
'click .go-back': 'goBack',
|
|
127
|
+
'click [data-rate]': 'onSelect',
|
|
128
|
+
'click #playback-rate-back-button': 'goBack',
|
|
107
129
|
}
|
|
108
130
|
}
|
|
109
131
|
|
|
@@ -111,7 +133,7 @@ export class PlaybackRate extends UICorePlugin {
|
|
|
111
133
|
* @internal
|
|
112
134
|
*/
|
|
113
135
|
override bindEvents() {
|
|
114
|
-
this.
|
|
136
|
+
this.listenToOnce(this.core, Events.CORE_READY, this.onCoreReady)
|
|
115
137
|
this.listenTo(
|
|
116
138
|
this.core,
|
|
117
139
|
Events.CORE_ACTIVE_CONTAINER_CHANGED,
|
|
@@ -125,11 +147,13 @@ export class PlaybackRate extends UICorePlugin {
|
|
|
125
147
|
assert(mediaControl, 'media_control plugin is required')
|
|
126
148
|
const gear = this.core.getPlugin('bottom_gear') as BottomGear
|
|
127
149
|
assert(gear, 'bottom_gear plugin is required')
|
|
150
|
+
|
|
128
151
|
this.listenTo(
|
|
129
152
|
mediaControl,
|
|
130
|
-
|
|
131
|
-
this.
|
|
153
|
+
Events.MEDIACONTROL_RENDERED,
|
|
154
|
+
this.onMediaControlRendered,
|
|
132
155
|
)
|
|
156
|
+
this.listenTo(gear, GearEvents.RENDERED, this.onGearRendered)
|
|
133
157
|
}
|
|
134
158
|
|
|
135
159
|
private onActiveContainerChange() {
|
|
@@ -143,47 +167,65 @@ export class PlaybackRate extends UICorePlugin {
|
|
|
143
167
|
)
|
|
144
168
|
this.listenTo(
|
|
145
169
|
this.core.activeContainer,
|
|
146
|
-
Events.
|
|
147
|
-
this.
|
|
170
|
+
Events.CONTAINER_LOADEDMETADATA,
|
|
171
|
+
this.onMetaDataLoaded,
|
|
148
172
|
)
|
|
149
173
|
}
|
|
150
174
|
|
|
151
|
-
private
|
|
152
|
-
trace(`${T}
|
|
153
|
-
rendered: this.rendered,
|
|
154
|
-
})
|
|
155
|
-
this.rendered = false
|
|
175
|
+
private onMediaControlRendered() {
|
|
176
|
+
trace(`${T} onMediaControlRendered`)
|
|
156
177
|
this.render()
|
|
157
178
|
}
|
|
158
179
|
|
|
159
|
-
private
|
|
160
|
-
trace(`${T}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}
|
|
180
|
+
private onGearRendered() {
|
|
181
|
+
trace(`${T} onGearRendered`)
|
|
182
|
+
this.addGearItem()
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
private addGearItem() {
|
|
186
|
+
trace(`${T} addGearItem`)
|
|
187
|
+
this.core
|
|
188
|
+
.getPlugin('bottom_gear')
|
|
189
|
+
?.addItem('rate', this.$el)
|
|
190
|
+
.html(
|
|
191
|
+
$(
|
|
192
|
+
PlaybackRate.buttonTemplate({
|
|
193
|
+
title: this.getTitle(),
|
|
194
|
+
speedIcon,
|
|
195
|
+
arrowRightIcon,
|
|
196
|
+
i18n: this.core.i18n,
|
|
197
|
+
}),
|
|
198
|
+
),
|
|
199
|
+
)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
private onMetaDataLoaded() {
|
|
203
|
+
trace(`${T} onMetaDataLoaded`)
|
|
204
|
+
this.render()
|
|
166
205
|
}
|
|
167
206
|
|
|
168
207
|
private allRateElements(): ZeptoResult {
|
|
169
|
-
return this.$('
|
|
208
|
+
return this.$el.find('#playback-rate-menu li')
|
|
170
209
|
}
|
|
171
210
|
|
|
172
|
-
private rateElement(rate
|
|
211
|
+
private rateElement(rate: number): ZeptoResult {
|
|
173
212
|
return (
|
|
174
|
-
this.$(
|
|
213
|
+
this.$el.find(`#playback-rate-menu a[data-rate="${rate}"]`) as ZeptoResult
|
|
175
214
|
).parent()
|
|
176
215
|
}
|
|
177
216
|
|
|
178
217
|
private onPlaybackRateChange(playbackRate: number) {
|
|
179
|
-
const selectedRate = parseInt(this.selectedRate, 10)
|
|
180
218
|
// TODO check it doesn't interfere with the DASH.js or HLS.js playback live catchup
|
|
181
|
-
if (Math.abs(playbackRate - selectedRate) > 0.1) {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
219
|
+
if (Math.abs(playbackRate - this.selectedRate) > 0.1) {
|
|
220
|
+
this.core.activePlayback?.setPlaybackRate(this.selectedRate)
|
|
221
|
+
} else {
|
|
222
|
+
trace(
|
|
223
|
+
`${T} onPlaybackRateChange not steering to the selected rate, it is seemingly a catchup algorithm working`,
|
|
224
|
+
{
|
|
225
|
+
playbackRate,
|
|
226
|
+
selectedRate: this.selectedRate,
|
|
227
|
+
},
|
|
228
|
+
)
|
|
187
229
|
}
|
|
188
230
|
}
|
|
189
231
|
|
|
@@ -207,7 +249,6 @@ export class PlaybackRate extends UICorePlugin {
|
|
|
207
249
|
*/
|
|
208
250
|
override render() {
|
|
209
251
|
trace(`${T} render`, {
|
|
210
|
-
rendered: this.rendered,
|
|
211
252
|
shouldRender: this.shouldRender(),
|
|
212
253
|
})
|
|
213
254
|
|
|
@@ -215,43 +256,36 @@ export class PlaybackRate extends UICorePlugin {
|
|
|
215
256
|
return this
|
|
216
257
|
}
|
|
217
258
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
})
|
|
228
|
-
|
|
229
|
-
this.$el.html(button)
|
|
230
|
-
|
|
231
|
-
;(this.core.getPlugin('bottom_gear') as BottomGear)
|
|
232
|
-
?.getElement('rate')
|
|
233
|
-
?.html(this.el)
|
|
259
|
+
this.$el.html(
|
|
260
|
+
PlaybackRate.listTemplate({
|
|
261
|
+
arrowLeftIcon,
|
|
262
|
+
checkIcon,
|
|
263
|
+
current: this.selectedRate,
|
|
264
|
+
i18n: this.core.i18n,
|
|
265
|
+
playbackRates: this.playbackRates,
|
|
266
|
+
}),
|
|
267
|
+
)
|
|
234
268
|
|
|
235
|
-
this.
|
|
269
|
+
this.addGearItem()
|
|
236
270
|
|
|
237
271
|
return this
|
|
238
272
|
}
|
|
239
273
|
|
|
240
|
-
private onStartAd() {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
private onFinishAd() {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
}
|
|
274
|
+
// private onStartAd() {
|
|
275
|
+
// this.prevSelectedRate = this.selectedRate
|
|
276
|
+
// this.resetPlaybackRate()
|
|
277
|
+
// this.listenToOnce(
|
|
278
|
+
// this.core.activePlayback,
|
|
279
|
+
// Events.PLAYBACK_PLAY,
|
|
280
|
+
// this.onFinishAd,
|
|
281
|
+
// )
|
|
282
|
+
// }
|
|
283
|
+
|
|
284
|
+
// private onFinishAd() {
|
|
285
|
+
// if (this.prevSelectedRate) {
|
|
286
|
+
// this.setSelectedRate(this.prevSelectedRate)
|
|
287
|
+
// }
|
|
288
|
+
// }
|
|
255
289
|
|
|
256
290
|
private onPlay() {
|
|
257
291
|
if (
|
|
@@ -270,38 +304,27 @@ export class PlaybackRate extends UICorePlugin {
|
|
|
270
304
|
|
|
271
305
|
private onStop() {}
|
|
272
306
|
|
|
273
|
-
private
|
|
307
|
+
private onSelect(event: MouseEvent) {
|
|
274
308
|
event.stopPropagation()
|
|
275
|
-
const rate = (
|
|
309
|
+
const rate = parseFloat(
|
|
310
|
+
(event.currentTarget as HTMLElement).dataset.rate || '',
|
|
311
|
+
)
|
|
276
312
|
if (rate) {
|
|
277
313
|
this.setSelectedRate(rate)
|
|
278
314
|
this.highlightCurrentRate()
|
|
315
|
+
this.updateGearOptionLabel()
|
|
279
316
|
}
|
|
280
317
|
|
|
281
318
|
return false
|
|
282
319
|
}
|
|
283
320
|
|
|
284
|
-
private onShowMenu() {
|
|
285
|
-
this.$el.html(
|
|
286
|
-
PlaybackRate.listTemplate({
|
|
287
|
-
playbackRates: this.playbackRates,
|
|
288
|
-
arrowLeftIcon,
|
|
289
|
-
checkIcon,
|
|
290
|
-
i18n: this.core.i18n,
|
|
291
|
-
}),
|
|
292
|
-
)
|
|
293
|
-
;(this.core.getPlugin('bottom_gear') as BottomGear)?.setContent(this.el)
|
|
294
|
-
this.highlightCurrentRate()
|
|
295
|
-
}
|
|
296
|
-
|
|
297
321
|
private goBack() {
|
|
298
322
|
setTimeout(() => {
|
|
299
323
|
this.core.getPlugin('bottom_gear').refresh()
|
|
300
324
|
}, 0)
|
|
301
325
|
}
|
|
302
326
|
|
|
303
|
-
private setSelectedRate(rate:
|
|
304
|
-
// Set <video playbackRate="..."
|
|
327
|
+
private setSelectedRate(rate: number) {
|
|
305
328
|
this.core.activePlayback?.setPlaybackRate(rate)
|
|
306
329
|
this.selectedRate = rate
|
|
307
330
|
}
|
|
@@ -309,7 +332,7 @@ export class PlaybackRate extends UICorePlugin {
|
|
|
309
332
|
private getTitle() {
|
|
310
333
|
return (
|
|
311
334
|
this.playbackRates.find((r) => r.value === this.selectedRate)?.label ||
|
|
312
|
-
this.selectedRate
|
|
335
|
+
`x${this.selectedRate}`
|
|
313
336
|
)
|
|
314
337
|
}
|
|
315
338
|
|
|
@@ -317,9 +340,14 @@ export class PlaybackRate extends UICorePlugin {
|
|
|
317
340
|
this.allRateElements().removeClass('current')
|
|
318
341
|
this.allRateElements().find('a').removeClass('gcore-skin-active')
|
|
319
342
|
|
|
320
|
-
|
|
343
|
+
this.rateElement(this.selectedRate)
|
|
344
|
+
.addClass('current')
|
|
345
|
+
.find('a')
|
|
346
|
+
.addClass('gcore-skin-active')
|
|
347
|
+
}
|
|
321
348
|
|
|
322
|
-
|
|
323
|
-
|
|
349
|
+
private updateGearOptionLabel() {
|
|
350
|
+
trace(`${T} updateGearOptionLabel`)
|
|
351
|
+
this.addGearItem()
|
|
324
352
|
}
|
|
325
353
|
}
|
|
@@ -1,23 +1,26 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, vi } from 'vitest'
|
|
1
|
+
import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest'
|
|
2
2
|
import { PlaybackRate } from '../PlaybackRate'
|
|
3
3
|
import {
|
|
4
|
+
createMockBottomGear,
|
|
4
5
|
createMockCore,
|
|
5
6
|
createMockMediaControl,
|
|
6
|
-
createMockPlugin,
|
|
7
7
|
} from '../../../testUtils'
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
8
|
+
import { Events } from '@clappr/core'
|
|
9
|
+
import { GearEvents } from '../../bottom-gear/BottomGear'
|
|
10
|
+
// import { Logger, LogTracer, setTracer } from '@gcorevideo/utils'
|
|
10
11
|
|
|
11
|
-
Logger.enable('*')
|
|
12
|
-
setTracer(new LogTracer('PlaybackRate.test'))
|
|
12
|
+
// Logger.enable('*')
|
|
13
|
+
// setTracer(new LogTracer('PlaybackRate.test'))
|
|
13
14
|
|
|
14
15
|
describe('PlaybackRate', () => {
|
|
15
16
|
let core: any
|
|
16
17
|
let bottomGear: any
|
|
18
|
+
let mediaControl: any
|
|
19
|
+
let playbackRate: PlaybackRate
|
|
17
20
|
beforeEach(() => {
|
|
18
21
|
core = createMockCore()
|
|
19
|
-
|
|
20
|
-
bottomGear =
|
|
22
|
+
mediaControl = createMockMediaControl(core)
|
|
23
|
+
bottomGear = createMockBottomGear(core)
|
|
21
24
|
core.getPlugin.mockImplementation((name: string) => {
|
|
22
25
|
if (name === 'bottom_gear') {
|
|
23
26
|
return bottomGear
|
|
@@ -27,39 +30,83 @@ describe('PlaybackRate', () => {
|
|
|
27
30
|
}
|
|
28
31
|
return null
|
|
29
32
|
})
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const playbackRate = new PlaybackRate(core)
|
|
33
|
-
core.emit('core:ready')
|
|
33
|
+
playbackRate = new PlaybackRate(core)
|
|
34
|
+
core.emit(Events.CORE_READY)
|
|
34
35
|
core.activePlayback.getPlaybackType.mockReturnValue('live')
|
|
35
|
-
core.
|
|
36
|
+
core.activeContainer.getPlaybackType.mockReturnValue('live')
|
|
37
|
+
core.getPlaybackType.mockReturnValue('live')
|
|
38
|
+
core.emit(Events.CORE_ACTIVE_CONTAINER_CHANGED)
|
|
36
39
|
core.activePlayback.dvrEnabled = true
|
|
37
|
-
core.activeContainer.
|
|
40
|
+
core.activeContainer.isDvrEnabled.mockReturnValue(true)
|
|
41
|
+
core.activeContainer.emit(Events.CONTAINER_LOADEDMETADATA)
|
|
42
|
+
bottomGear.trigger(GearEvents.RENDERED)
|
|
43
|
+
})
|
|
44
|
+
it('should render', () => {
|
|
38
45
|
expect(playbackRate.el.innerHTML).toMatchSnapshot()
|
|
39
|
-
expect(bottomGear.
|
|
46
|
+
expect(bottomGear.addItem).toHaveBeenCalledWith('rate', playbackRate.$el)
|
|
47
|
+
expect(
|
|
48
|
+
bottomGear.$el.find('li[data-rate]').text(),
|
|
49
|
+
// @ts-ignore
|
|
50
|
+
).toMatchPlaybackRateLabel('playback_rate 1x')
|
|
51
|
+
})
|
|
52
|
+
it('should have normal rate initially', () => {
|
|
53
|
+
expect(
|
|
54
|
+
playbackRate.$el.find('[data-rate="1"]').parent().hasClass('current'),
|
|
55
|
+
).toBe(true)
|
|
40
56
|
expect(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
57
|
+
playbackRate.$el.find('[data-rate="1"]').hasClass('gcore-skin-active'),
|
|
58
|
+
).toBe(true)
|
|
59
|
+
})
|
|
60
|
+
describe('on playback rate select', () => {
|
|
61
|
+
describe.each([[2], [1.5], [1.25], [1], [0.75], [0.5]])('%s', (rate) => {
|
|
62
|
+
beforeEach(() => {
|
|
63
|
+
playbackRate.$el.find(`[data-rate="${rate}"]`).click()
|
|
64
|
+
})
|
|
65
|
+
it('should set the selected rate', () => {
|
|
66
|
+
expect(core.activePlayback.setPlaybackRate).toHaveBeenCalledWith(rate)
|
|
67
|
+
})
|
|
68
|
+
it('should highlight the selected rate', () => {
|
|
69
|
+
expect(
|
|
70
|
+
playbackRate.$el
|
|
71
|
+
.find(`[data-rate="${rate}"]`)
|
|
72
|
+
.parent()
|
|
73
|
+
.hasClass('current'),
|
|
74
|
+
).toBe(true)
|
|
75
|
+
expect(
|
|
76
|
+
playbackRate.$el
|
|
77
|
+
.find(`[data-rate="${rate}"]`)
|
|
78
|
+
.hasClass('gcore-skin-active'),
|
|
79
|
+
).toBe(true)
|
|
80
|
+
})
|
|
81
|
+
it('should update the gear box option label', () => {
|
|
82
|
+
expect(
|
|
83
|
+
bottomGear.$el.find('#playback-rate-button').text(),
|
|
84
|
+
// @ts-ignore
|
|
85
|
+
).toMatchPlaybackRateLabel(`playback_rate ${rate}x`)
|
|
86
|
+
})
|
|
87
|
+
})
|
|
88
|
+
})
|
|
89
|
+
describe('on go back', () => {
|
|
90
|
+
beforeEach(async () => {
|
|
91
|
+
playbackRate.$el.find('#playback-rate-back-button').click()
|
|
92
|
+
return new Promise((resolve) => setTimeout(resolve, 0))
|
|
93
|
+
})
|
|
94
|
+
it('should refresh the bottom gear', () => {
|
|
95
|
+
expect(bottomGear.refresh).toHaveBeenCalled()
|
|
96
|
+
})
|
|
48
97
|
})
|
|
49
98
|
})
|
|
50
99
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
return plugin
|
|
65
|
-
}
|
|
100
|
+
expect.extend({
|
|
101
|
+
toMatchPlaybackRateLabel(received, expected) {
|
|
102
|
+
const { isNot } = this
|
|
103
|
+
return {
|
|
104
|
+
pass:
|
|
105
|
+
received
|
|
106
|
+
.replace(/\/assets.*\.svg/g, '')
|
|
107
|
+
.replace(/\s+/g, ' ')
|
|
108
|
+
.trim().includes(expected),
|
|
109
|
+
message: () => `${received} does${isNot ? '' : ' not'} match ${expected}`,
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
})
|
|
@@ -1,11 +1,60 @@
|
|
|
1
1
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
2
|
|
|
3
3
|
exports[`PlaybackRate > should render 1`] = `
|
|
4
|
-
"<button class="gplayer-lite-btn gcore-skin-text-color
|
|
5
|
-
<span class="
|
|
6
|
-
|
|
7
|
-
<span class="gear-option_arrow-right-icon">/assets/icons/new/arrow-right.svg</span>
|
|
8
|
-
<span class="gear-option_value">1x</span>
|
|
4
|
+
"<button class="gplayer-lite-btn go-back gcore-skin-text-color" id="playback-rate-back-button">
|
|
5
|
+
<span class="arrow-left-icon">/assets/icons/new/arrow-left.svg</span>
|
|
6
|
+
playback_rate
|
|
9
7
|
</button>
|
|
10
|
-
"
|
|
8
|
+
<ul class="gear-sub-menu" id="playback-rate-menu">
|
|
9
|
+
|
|
10
|
+
<li>
|
|
11
|
+
<a href="#" class="gear-sub-menu_btn gcore-skin-text-color" data-rate="0.5">
|
|
12
|
+
<span class="check-icon">/assets/icons/new/check.svg</span>
|
|
13
|
+
0.5x
|
|
14
|
+
</a>
|
|
15
|
+
</li>
|
|
16
|
+
|
|
17
|
+
<li>
|
|
18
|
+
<a href="#" class="gear-sub-menu_btn gcore-skin-text-color" data-rate="0.75">
|
|
19
|
+
<span class="check-icon">/assets/icons/new/check.svg</span>
|
|
20
|
+
0.75x
|
|
21
|
+
</a>
|
|
22
|
+
</li>
|
|
23
|
+
|
|
24
|
+
<li class="current">
|
|
25
|
+
<a href="#" class="gear-sub-menu_btn gcore-skin-text-color gcore-skin-active" data-rate="1">
|
|
26
|
+
<span class="check-icon">/assets/icons/new/check.svg</span>
|
|
27
|
+
1x
|
|
28
|
+
</a>
|
|
29
|
+
</li>
|
|
30
|
+
|
|
31
|
+
<li>
|
|
32
|
+
<a href="#" class="gear-sub-menu_btn gcore-skin-text-color" data-rate="1.25">
|
|
33
|
+
<span class="check-icon">/assets/icons/new/check.svg</span>
|
|
34
|
+
1.25x
|
|
35
|
+
</a>
|
|
36
|
+
</li>
|
|
37
|
+
|
|
38
|
+
<li>
|
|
39
|
+
<a href="#" class="gear-sub-menu_btn gcore-skin-text-color" data-rate="1.5">
|
|
40
|
+
<span class="check-icon">/assets/icons/new/check.svg</span>
|
|
41
|
+
1.5x
|
|
42
|
+
</a>
|
|
43
|
+
</li>
|
|
44
|
+
|
|
45
|
+
<li>
|
|
46
|
+
<a href="#" class="gear-sub-menu_btn gcore-skin-text-color" data-rate="1.75">
|
|
47
|
+
<span class="check-icon">/assets/icons/new/check.svg</span>
|
|
48
|
+
1.75x
|
|
49
|
+
</a>
|
|
50
|
+
</li>
|
|
51
|
+
|
|
52
|
+
<li>
|
|
53
|
+
<a href="#" class="gear-sub-menu_btn gcore-skin-text-color" data-rate="2">
|
|
54
|
+
<span class="check-icon">/assets/icons/new/check.svg</span>
|
|
55
|
+
2x
|
|
56
|
+
</a>
|
|
57
|
+
</li>
|
|
58
|
+
|
|
59
|
+
</ul>"
|
|
11
60
|
`;
|
|
@@ -52,7 +52,7 @@ describe('ClosedCaptions', () => {
|
|
|
52
52
|
it('should render', () => {
|
|
53
53
|
expect(cc.el.innerHTML).toMatchSnapshot()
|
|
54
54
|
expect(cc.$el.find('[data-cc-button]').length).toEqual(1)
|
|
55
|
-
expect(mediaControl.putElement).toHaveBeenCalledWith('cc', cc
|
|
55
|
+
expect(mediaControl.putElement).toHaveBeenCalledWith('cc', cc.$el)
|
|
56
56
|
})
|
|
57
57
|
})
|
|
58
58
|
})
|
package/src/testUtils.ts
CHANGED
|
@@ -193,3 +193,17 @@ export function createMockMediaControl(core: any) {
|
|
|
193
193
|
mediaControl.toggleElement = vi.fn()
|
|
194
194
|
return mediaControl
|
|
195
195
|
}
|
|
196
|
+
|
|
197
|
+
export function createMockBottomGear(core: any) {
|
|
198
|
+
const plugin: any = new UICorePlugin(core)
|
|
199
|
+
plugin.getItem = vi.fn()
|
|
200
|
+
plugin.addItem = vi.fn().mockImplementation((name: string, $el: any) => {
|
|
201
|
+
const existing = plugin.$el.find(`[data-${name}]`)
|
|
202
|
+
if (existing.length) {
|
|
203
|
+
return existing
|
|
204
|
+
}
|
|
205
|
+
return $('<li></li>').attr(`data-${name}`, '').append($el).appendTo(plugin.$el)
|
|
206
|
+
})
|
|
207
|
+
plugin.refresh = vi.fn()
|
|
208
|
+
return plugin
|
|
209
|
+
}
|