@gcorevideo/player 2.25.7 → 2.25.8
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-sub-menu.scss +4 -9
- package/assets/media-control/container.scss +0 -13
- package/assets/media-control/media-control.scss +14 -12
- package/assets/media-control/width270.scss +3 -0
- package/assets/media-control/width370.scss +4 -0
- package/assets/multi-camera/style.scss +0 -5
- package/assets/subtitles/combobox.ejs +27 -6
- package/assets/subtitles/string.ejs +1 -1
- package/assets/subtitles/style.scss +16 -69
- package/dist/core.js +1 -1
- package/dist/index.css +642 -696
- package/dist/index.embed.js +136 -98
- package/dist/index.js +77 -42
- package/lib/plugins/bottom-gear/BottomGear.d.ts +1 -1
- package/lib/plugins/bottom-gear/BottomGear.d.ts.map +1 -1
- package/lib/plugins/bottom-gear/BottomGear.js +3 -4
- package/lib/plugins/media-control/MediaControl.d.ts +4 -0
- package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
- package/lib/plugins/media-control/MediaControl.js +7 -0
- package/lib/plugins/subtitles/ClosedCaptions.d.ts +7 -4
- package/lib/plugins/subtitles/ClosedCaptions.d.ts.map +1 -1
- package/lib/plugins/subtitles/ClosedCaptions.js +64 -34
- package/lib/testUtils.d.ts.map +1 -1
- package/lib/testUtils.js +2 -0
- package/package.json +1 -1
- package/src/plugins/bottom-gear/BottomGear.ts +3 -4
- package/src/plugins/bottom-gear/__tests__/BottomGear.test.ts +1 -1
- package/src/plugins/media-control/MediaControl.ts +10 -0
- package/src/plugins/subtitles/ClosedCaptions.ts +66 -35
- package/src/plugins/subtitles/__tests__/ClosedCaptions.test.ts +220 -35
- package/src/plugins/subtitles/__tests__/__snapshots__/ClosedCaptions.test.ts.snap +8 -19
- package/src/testUtils.ts +2 -0
- package/tsconfig.tsbuildinfo +1 -1
package/lib/testUtils.d.ts.map
CHANGED
|
@@ -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;AAGlC,wBAAgB,cAAc,CAC5B,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACrC,SAAS,GAAE,GAAkC;;;;;;;;;;;;;;;;;EAsB9C;AAED,wBAAgB,gBAAgB;;;EAK/B;AAED,wBAAgB,mBAAmB;;;;;;EAKlC;AAED,wBAAgB,kBAAkB,CAChC,IAAI,SAAS,EACb,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqCtC;AAED,wBAAgB,mBAAmB,CACjC,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACrC,QAAQ,GAAE,GAAgD;;;;;;;;;;;;;;;;;;;;;;;;;EA8B3D;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,GAAG,
|
|
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;AAGlC,wBAAgB,cAAc,CAC5B,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACrC,SAAS,GAAE,GAAkC;;;;;;;;;;;;;;;;;EAsB9C;AAED,wBAAgB,gBAAgB;;;EAK/B;AAED,wBAAgB,mBAAmB;;;;;;EAKlC;AAED,wBAAgB,kBAAkB,CAChC,IAAI,SAAS,EACb,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqCtC;AAED,wBAAgB,mBAAmB,CACjC,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACrC,QAAQ,GAAE,GAAgD;;;;;;;;;;;;;;;;;;;;;;;;;EA8B3D;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,GAAG,gBAuB/C;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,GAAG,OAe7C"}
|
package/lib/testUtils.js
CHANGED
|
@@ -117,6 +117,8 @@ export function createMockMediaControl(core) {
|
|
|
117
117
|
// @ts-ignore
|
|
118
118
|
mediaControl.getAvailableHeight = vi.fn().mockReturnValue(300);
|
|
119
119
|
// @ts-ignore
|
|
120
|
+
mediaControl.getAvailablePopupHeight = vi.fn().mockReturnValue(286);
|
|
121
|
+
// @ts-ignore
|
|
120
122
|
mediaControl.toggleElement = vi.fn();
|
|
121
123
|
vi.spyOn(mediaControl, 'trigger');
|
|
122
124
|
core.$el.append(mediaControl.$el);
|
package/package.json
CHANGED
|
@@ -198,7 +198,7 @@ export class BottomGear extends UICorePlugin {
|
|
|
198
198
|
.appendTo(this.$el.find('#gear-options-wrapper'))
|
|
199
199
|
$item.on('click', (e: MouseEvent) => {
|
|
200
200
|
e.stopPropagation()
|
|
201
|
-
this.
|
|
201
|
+
this.clampPopup($subMenu)
|
|
202
202
|
$subMenu.show()
|
|
203
203
|
this.$el.find('#gear-options').hide()
|
|
204
204
|
})
|
|
@@ -323,10 +323,9 @@ export class BottomGear extends UICorePlugin {
|
|
|
323
323
|
mediaControl.slot('gear', this.$el)
|
|
324
324
|
}
|
|
325
325
|
|
|
326
|
-
private
|
|
326
|
+
private clampPopup($subMenu: ZeptoResult) {
|
|
327
327
|
const availableHeight =
|
|
328
|
-
this.core.getPlugin('media_control').
|
|
329
|
-
MENU_VMARGIN * 2
|
|
328
|
+
this.core.getPlugin('media_control').getAvailablePopupHeight()
|
|
330
329
|
$subMenu.css('max-height', `${availableHeight}px`)
|
|
331
330
|
$subMenu
|
|
332
331
|
.find('.gear-sub-menu')
|
|
@@ -110,7 +110,7 @@ describe('BottomGear', () => {
|
|
|
110
110
|
})
|
|
111
111
|
describe('when submenu is open', () => {
|
|
112
112
|
beforeEach(async () => {
|
|
113
|
-
mediaControl.
|
|
113
|
+
mediaControl.getAvailablePopupHeight.mockReturnValue(174)
|
|
114
114
|
bottomGear.$el.find('#gear-button').click()
|
|
115
115
|
await new Promise((resolve) => setTimeout(resolve, 0))
|
|
116
116
|
bottomGear.$el.find('#more-button').click()
|
|
@@ -49,6 +49,8 @@ const STANDARD_MEDIA_CONTROL_ELEMENTS: string[] = [
|
|
|
49
49
|
'volume',
|
|
50
50
|
]
|
|
51
51
|
|
|
52
|
+
const MENU_VMARGIN = 12
|
|
53
|
+
|
|
52
54
|
/**
|
|
53
55
|
* Built-in media control elements.
|
|
54
56
|
* @beta
|
|
@@ -562,6 +564,13 @@ export class MediaControl extends UICorePlugin {
|
|
|
562
564
|
)
|
|
563
565
|
}
|
|
564
566
|
|
|
567
|
+
/**
|
|
568
|
+
* @returns Vertical space available to render a popup menu
|
|
569
|
+
*/
|
|
570
|
+
getAvailablePopupHeight() {
|
|
571
|
+
return this.getAvailableHeight() - MENU_VMARGIN * 2
|
|
572
|
+
}
|
|
573
|
+
|
|
565
574
|
/**
|
|
566
575
|
* Set the initial volume, which is preserved when playback is interrupted by an advertisement
|
|
567
576
|
*/
|
|
@@ -681,6 +690,7 @@ export class MediaControl extends UICorePlugin {
|
|
|
681
690
|
const pos = offset
|
|
682
691
|
? Math.min(1, Math.max(offset / this.$seekBarContainer.width(), 0))
|
|
683
692
|
: 0
|
|
693
|
+
|
|
684
694
|
if (this.settings.seekEnabled) {
|
|
685
695
|
// TODO test that it works when the element does not exist
|
|
686
696
|
this.$seekBarHover.css({ left: hoverOffset })
|
|
@@ -64,6 +64,8 @@ export class ClosedCaptions extends UICorePlugin {
|
|
|
64
64
|
|
|
65
65
|
private active = false
|
|
66
66
|
|
|
67
|
+
private open = false
|
|
68
|
+
|
|
67
69
|
private track: TextTrackItem | null = null
|
|
68
70
|
|
|
69
71
|
private tracks: TextTrackItem[] = []
|
|
@@ -91,16 +93,16 @@ export class ClosedCaptions extends UICorePlugin {
|
|
|
91
93
|
return VERSION
|
|
92
94
|
}
|
|
93
95
|
|
|
94
|
-
private static readonly
|
|
96
|
+
private static readonly templateControl = template(comboboxHTML)
|
|
95
97
|
|
|
96
|
-
private static readonly
|
|
98
|
+
private static readonly templateLine = template(stringHTML)
|
|
97
99
|
|
|
98
100
|
/**
|
|
99
101
|
* @internal
|
|
100
102
|
*/
|
|
101
103
|
override get attributes() {
|
|
102
104
|
return {
|
|
103
|
-
class: 'media-control-cc',
|
|
105
|
+
class: 'media-control-cc media-control-dd__wrap',
|
|
104
106
|
}
|
|
105
107
|
}
|
|
106
108
|
|
|
@@ -109,8 +111,8 @@ export class ClosedCaptions extends UICorePlugin {
|
|
|
109
111
|
*/
|
|
110
112
|
override get events() {
|
|
111
113
|
return {
|
|
112
|
-
'click #cc-
|
|
113
|
-
'click #cc-button': 'toggleMenu',
|
|
114
|
+
'click #gplayer-cc-menu [data-item]': 'onItemSelect',
|
|
115
|
+
'click #gplayer-cc-button': 'toggleMenu',
|
|
114
116
|
}
|
|
115
117
|
}
|
|
116
118
|
|
|
@@ -136,10 +138,9 @@ export class ClosedCaptions extends UICorePlugin {
|
|
|
136
138
|
}
|
|
137
139
|
|
|
138
140
|
private onCoreReady() {
|
|
139
|
-
trace(`${T} onCoreReady`)
|
|
140
141
|
const mediaControl = this.core.getPlugin('media_control')
|
|
141
142
|
assert(mediaControl, 'media_control plugin is required')
|
|
142
|
-
this.listenTo(mediaControl, Events.MEDIACONTROL_RENDERED, this.
|
|
143
|
+
this.listenTo(mediaControl, Events.MEDIACONTROL_RENDERED, this.mount)
|
|
143
144
|
this.listenTo(mediaControl, Events.MEDIACONTROL_HIDE, () => {
|
|
144
145
|
this.hideMenu()
|
|
145
146
|
})
|
|
@@ -155,7 +156,6 @@ export class ClosedCaptions extends UICorePlugin {
|
|
|
155
156
|
}
|
|
156
157
|
|
|
157
158
|
private onContainerChanged() {
|
|
158
|
-
trace(`${T} onContainerChanged`)
|
|
159
159
|
this.listenTo(
|
|
160
160
|
this.core.activeContainer,
|
|
161
161
|
Events.CONTAINER_FULLSCREEN,
|
|
@@ -176,6 +176,10 @@ export class ClosedCaptions extends UICorePlugin {
|
|
|
176
176
|
Events.PLAYBACK_SUBTITLE_CHANGED,
|
|
177
177
|
this.onSubtitleChanged,
|
|
178
178
|
)
|
|
179
|
+
this.listenTo(this.core.activeContainer, Events.CONTAINER_CLICK, () => {
|
|
180
|
+
// TODO test
|
|
181
|
+
this.hideMenu()
|
|
182
|
+
})
|
|
179
183
|
|
|
180
184
|
// fix for iOS
|
|
181
185
|
const video = this.core.activePlayback.el
|
|
@@ -197,6 +201,7 @@ export class ClosedCaptions extends UICorePlugin {
|
|
|
197
201
|
private onSubtitleAvailable() {
|
|
198
202
|
trace(`${T} onSubtitleAvailable`)
|
|
199
203
|
this.applyTracks()
|
|
204
|
+
this.mount()
|
|
200
205
|
}
|
|
201
206
|
|
|
202
207
|
private onSubtitleChanged({ id }: { id: number }) {
|
|
@@ -276,6 +281,7 @@ export class ClosedCaptions extends UICorePlugin {
|
|
|
276
281
|
|
|
277
282
|
try {
|
|
278
283
|
this.resizeFont()
|
|
284
|
+
this.clampPopup()
|
|
279
285
|
} catch (error) {
|
|
280
286
|
reportError(error)
|
|
281
287
|
}
|
|
@@ -286,7 +292,10 @@ export class ClosedCaptions extends UICorePlugin {
|
|
|
286
292
|
*/
|
|
287
293
|
hide() {
|
|
288
294
|
this.active = false
|
|
295
|
+
this.open = false
|
|
289
296
|
this.renderIcon()
|
|
297
|
+
this.$el.find('#gplayer-cc-menu').hide()
|
|
298
|
+
this.$el.find('#gplayer-cc-button').attr('aria-expanded', 'false')
|
|
290
299
|
this.$line.hide()
|
|
291
300
|
if (this.tracks) {
|
|
292
301
|
for (const t of this.tracks) {
|
|
@@ -337,20 +346,21 @@ export class ClosedCaptions extends UICorePlugin {
|
|
|
337
346
|
return this
|
|
338
347
|
}
|
|
339
348
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
this.$el.find('#cc-
|
|
348
|
-
this.
|
|
349
|
-
this.$line
|
|
349
|
+
this.$el.html(
|
|
350
|
+
ClosedCaptions.templateControl({
|
|
351
|
+
tracks: this.tracks ?? [],
|
|
352
|
+
i18n: this.core.i18n,
|
|
353
|
+
current: this.track?.id ?? -1,
|
|
354
|
+
}),
|
|
355
|
+
)
|
|
356
|
+
this.$el.find('#gplayer-cc-menu').hide()
|
|
357
|
+
this.open = false
|
|
358
|
+
this.core.activeContainer.$el.find('#gplayer-cc-line').remove()
|
|
359
|
+
this.$line = $(ClosedCaptions.templateLine())
|
|
350
360
|
this.resizeFont()
|
|
361
|
+
this.clampPopup()
|
|
351
362
|
|
|
352
363
|
this.core.activeContainer.$el.append(this.$line)
|
|
353
|
-
mediaControl.slot('cc', this.$el)
|
|
354
364
|
|
|
355
365
|
this.updateSelection()
|
|
356
366
|
|
|
@@ -371,11 +381,12 @@ export class ClosedCaptions extends UICorePlugin {
|
|
|
371
381
|
}
|
|
372
382
|
|
|
373
383
|
private onItemSelect(event: MouseEvent) {
|
|
374
|
-
|
|
384
|
+
// event.target does not exist for some reason in tests
|
|
385
|
+
const id =
|
|
386
|
+
((event.target ?? event.currentTarget) as HTMLElement).dataset?.item ??
|
|
387
|
+
'-1'
|
|
375
388
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
localStorage.setItem(LOCAL_STORAGE_CC_ID, id)
|
|
389
|
+
localStorage.setItem(LOCAL_STORAGE_CC_ID, id) // TODO store language instead
|
|
379
390
|
this.selectItem(this.findById(Number(id)))
|
|
380
391
|
this.hideMenu()
|
|
381
392
|
return false
|
|
@@ -398,31 +409,37 @@ export class ClosedCaptions extends UICorePlugin {
|
|
|
398
409
|
}
|
|
399
410
|
|
|
400
411
|
private hideMenu() {
|
|
401
|
-
|
|
402
|
-
this.$el.find('#cc-
|
|
412
|
+
this.open = false
|
|
413
|
+
this.$el.find('#gplayer-cc-menu').hide()
|
|
414
|
+
this.$el.find('#gplayer-cc-button').attr('aria-expanded', 'false')
|
|
403
415
|
}
|
|
404
416
|
|
|
405
417
|
private toggleMenu() {
|
|
406
|
-
trace(`${T} toggleMenu`, {display: this.$el.find('#cc-select').css('display')})
|
|
407
418
|
this.core
|
|
408
419
|
.getPlugin('media_control')
|
|
409
420
|
.trigger(ExtendedEvents.MEDIACONTROL_MENU_COLLAPSE, this.name)
|
|
410
|
-
this
|
|
411
|
-
|
|
421
|
+
this.open = !this.open
|
|
422
|
+
if (this.open) {
|
|
423
|
+
this.$el.find('#gplayer-cc-menu').show()
|
|
424
|
+
} else {
|
|
425
|
+
this.$el.find('#gplayer-cc-menu').hide()
|
|
426
|
+
}
|
|
427
|
+
this.$el.find('#gplayer-cc-button').attr('aria-expanded', this.open)
|
|
412
428
|
}
|
|
413
429
|
|
|
414
430
|
private itemElement(id: number): ZeptoResult {
|
|
415
|
-
|
|
431
|
+
// TODO fix semantically
|
|
432
|
+
return this.$el.find(`#gplayer-cc-menu [data-item="${id}"]`).parent()
|
|
416
433
|
}
|
|
417
434
|
|
|
418
435
|
private allItemElements(): ZeptoResult {
|
|
419
|
-
return this.$('#cc-
|
|
436
|
+
return this.$el.find('#gplayer-cc-menu li') // TODO fix semantically
|
|
420
437
|
}
|
|
421
438
|
|
|
422
439
|
private selectSubtitles() {
|
|
423
440
|
const trackId = this.track ? this.track.id : -1
|
|
424
441
|
|
|
425
|
-
this.core.activePlayback.closedCaptionsTrackId = trackId
|
|
442
|
+
this.core.activePlayback.closedCaptionsTrackId = trackId // TODO test
|
|
426
443
|
}
|
|
427
444
|
|
|
428
445
|
private getSubtitleText(track: TextTrack) {
|
|
@@ -434,6 +451,7 @@ export class ClosedCaptions extends UICorePlugin {
|
|
|
434
451
|
for (const cue of cues) {
|
|
435
452
|
if (currentTime >= cue.startTime && currentTime <= cue.endTime) {
|
|
436
453
|
lines.push((cue as VTTCue).getCueAsHTML().textContent)
|
|
454
|
+
// TODO break?
|
|
437
455
|
}
|
|
438
456
|
}
|
|
439
457
|
}
|
|
@@ -464,10 +482,8 @@ export class ClosedCaptions extends UICorePlugin {
|
|
|
464
482
|
.removeClass('current')
|
|
465
483
|
.find('a')
|
|
466
484
|
.removeClass('gcore-skin-active')
|
|
485
|
+
.attr('aria-checked', 'false')
|
|
467
486
|
|
|
468
|
-
trace(`${T} highlightCurrentSubtitles`, {
|
|
469
|
-
track: this.track?.id,
|
|
470
|
-
})
|
|
471
487
|
const currentLevelElement = this.itemElement(
|
|
472
488
|
this.track ? this.track.id : -1,
|
|
473
489
|
)
|
|
@@ -475,11 +491,26 @@ export class ClosedCaptions extends UICorePlugin {
|
|
|
475
491
|
.addClass('current')
|
|
476
492
|
.find('a')
|
|
477
493
|
.addClass('gcore-skin-active')
|
|
494
|
+
.attr('aria-checked', 'true')
|
|
478
495
|
}
|
|
479
496
|
|
|
480
497
|
private renderIcon() {
|
|
498
|
+
// render both icons at once
|
|
481
499
|
const icon = this.active ? subtitlesOnIcon : subtitlesOffIcon
|
|
500
|
+
this.$el.find('#gplayer-cc-button').html(icon)
|
|
501
|
+
}
|
|
482
502
|
|
|
483
|
-
|
|
503
|
+
private clampPopup() {
|
|
504
|
+
const availableHeight = this.core
|
|
505
|
+
.getPlugin('media_control')
|
|
506
|
+
.getAvailablePopupHeight()
|
|
507
|
+
this.$el.find('#gplayer-cc-menu').css('max-height', `${availableHeight}px`)
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
private mount() {
|
|
511
|
+
if (this.shouldRender()) {
|
|
512
|
+
const mediaControl = this.core.getPlugin('media_control')
|
|
513
|
+
mediaControl.slot('cc', this.$el)
|
|
514
|
+
}
|
|
484
515
|
}
|
|
485
516
|
}
|
|
@@ -4,9 +4,9 @@ import { ClosedCaptions } from '../ClosedCaptions.js'
|
|
|
4
4
|
import { createMockCore, createMockMediaControl } from '../../../testUtils.js'
|
|
5
5
|
import { ExtendedEvents } from '../../media-control/MediaControl.js'
|
|
6
6
|
|
|
7
|
-
import { LogTracer, Logger, setTracer } from '@gcorevideo/utils'
|
|
8
7
|
import { Events } from '@clappr/core'
|
|
9
|
-
|
|
8
|
+
|
|
9
|
+
// import { LogTracer, Logger, setTracer } from '@gcorevideo/utils'
|
|
10
10
|
|
|
11
11
|
// Logger.enable('*')
|
|
12
12
|
// setTracer(new LogTracer('ClosedCaptions.test'))
|
|
@@ -18,6 +18,7 @@ describe('ClosedCaptions', () => {
|
|
|
18
18
|
beforeEach(() => {
|
|
19
19
|
core = createMockCore()
|
|
20
20
|
mediaControl = createMockMediaControl(core)
|
|
21
|
+
mediaControl.getAvailablePopupHeight = vi.fn().mockReturnValue(211)
|
|
21
22
|
core.getPlugin = vi.fn().mockImplementation((name) => {
|
|
22
23
|
if (name === 'media_control') {
|
|
23
24
|
return mediaControl
|
|
@@ -31,44 +32,60 @@ describe('ClosedCaptions', () => {
|
|
|
31
32
|
core.emit(Events.CORE_READY)
|
|
32
33
|
core.activePlayback.el = document.createElement('video')
|
|
33
34
|
core.emit(Events.CORE_ACTIVE_CONTAINER_CHANGED, core.activeContainer)
|
|
34
|
-
core.activePlayback.closedCaptionsTracks = [
|
|
35
|
-
{
|
|
36
|
-
id: 1,
|
|
37
|
-
name: 'English',
|
|
38
|
-
track: {
|
|
39
|
-
language: 'en',
|
|
40
|
-
kind: 'subtitles',
|
|
41
|
-
label: 'English',
|
|
42
|
-
mode: 'hidden',
|
|
43
|
-
cues: [],
|
|
44
|
-
},
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
id: 2,
|
|
48
|
-
name: 'Spanish',
|
|
49
|
-
track: {
|
|
50
|
-
language: 'es',
|
|
51
|
-
kind: 'subtitles',
|
|
52
|
-
label: 'Spanish',
|
|
53
|
-
mode: 'hidden',
|
|
54
|
-
cues: [],
|
|
55
|
-
},
|
|
56
|
-
},
|
|
57
|
-
]
|
|
58
|
-
core.activePlayback.emit(Events.PLAYBACK_SUBTITLE_AVAILABLE)
|
|
59
|
-
core.activeContainer.emit(Events.CONTAINER_SUBTITLE_AVAILABLE)
|
|
60
35
|
})
|
|
61
36
|
it('should render', () => {
|
|
62
37
|
expect(cc.el.innerHTML).toMatchSnapshot()
|
|
63
|
-
expect(cc.$el.find('#cc-button').length).toEqual(1)
|
|
64
|
-
expect(
|
|
38
|
+
expect(cc.$el.find('#gplayer-cc-button').length).toEqual(1)
|
|
39
|
+
expect(cc.$el.find('#gplayer-cc-menu').css('display')).toEqual('none')
|
|
40
|
+
expect(core.activeContainer.$el.find('#gplayer-cc-line').length).toEqual(
|
|
41
|
+
1,
|
|
42
|
+
)
|
|
43
|
+
})
|
|
44
|
+
it('should clamp popup to availableheight', () => {
|
|
45
|
+
expect(cc.$el.find('#gplayer-cc-menu').css('max-height')).toBe('211px')
|
|
46
|
+
})
|
|
47
|
+
describe('until subtitle tracks are available', () => {
|
|
48
|
+
it('should not mount', () => {
|
|
49
|
+
expect(mediaControl.slot).not.toHaveBeenCalledWith(
|
|
50
|
+
'cc',
|
|
51
|
+
expect.anything(),
|
|
52
|
+
)
|
|
53
|
+
emitSubtitleAvailable(core)
|
|
54
|
+
expect(mediaControl.slot).toHaveBeenCalledWith('cc', cc.$el)
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
describe('when viewport is resized', () => {
|
|
58
|
+
beforeEach(() => {
|
|
59
|
+
mediaControl.getAvailablePopupHeight = vi.fn().mockReturnValue(197)
|
|
60
|
+
core.activeContainer.emit(Events.CONTAINER_RESIZE, {
|
|
61
|
+
width: 320,
|
|
62
|
+
height: 260,
|
|
63
|
+
})
|
|
64
|
+
core.emit(Events.CORE_RESIZE, { width: 320, height: 260 })
|
|
65
|
+
})
|
|
66
|
+
it('should clamp popup height', () => {
|
|
67
|
+
expect(cc.$el.find('#gplayer-cc-menu').css('max-height')).toBe('197px')
|
|
68
|
+
})
|
|
69
|
+
})
|
|
70
|
+
describe('when media control is rerendered', () => {
|
|
71
|
+
beforeEach(() => {
|
|
72
|
+
emitSubtitleAvailable(core)
|
|
73
|
+
mediaControl.trigger(Events.MEDIACONTROL_RENDERED)
|
|
74
|
+
})
|
|
75
|
+
it('should mount', () => {
|
|
76
|
+
expect(mediaControl.slot).toHaveBeenCalledWith('cc', cc.$el)
|
|
77
|
+
})
|
|
65
78
|
})
|
|
66
79
|
describe('when button is clicked', () => {
|
|
67
80
|
beforeEach(() => {
|
|
68
|
-
|
|
81
|
+
emitSubtitleAvailable(core)
|
|
82
|
+
cc.$el.find('#gplayer-cc-button').click()
|
|
69
83
|
})
|
|
70
84
|
it('should open menu', () => {
|
|
71
|
-
expect(cc.$el.find('#cc-
|
|
85
|
+
expect(cc.$el.find('#gplayer-cc-menu').css('display')).not.toBe('none')
|
|
86
|
+
expect(cc.$el.find('#gplayer-cc-button').attr('aria-expanded')).toBe(
|
|
87
|
+
'true',
|
|
88
|
+
)
|
|
72
89
|
})
|
|
73
90
|
it('should collapse all other menus', () => {
|
|
74
91
|
expect(mediaControl.trigger).toHaveBeenCalledWith(
|
|
@@ -79,20 +96,188 @@ describe('ClosedCaptions', () => {
|
|
|
79
96
|
})
|
|
80
97
|
describe('when clicked twice', () => {
|
|
81
98
|
beforeEach(() => {
|
|
82
|
-
|
|
99
|
+
emitSubtitleAvailable(core)
|
|
100
|
+
cc.$el.find('#gplayer-cc-button').click().click()
|
|
83
101
|
})
|
|
84
102
|
it('should collapse the menu', () => {
|
|
85
|
-
expect(cc.$el.find('#cc-
|
|
103
|
+
expect(cc.$el.find('#gplayer-cc-menu').css('display')).toBe('none')
|
|
104
|
+
expect(cc.$el.find('#gplayer-cc-button').attr('aria-expanded')).toBe(
|
|
105
|
+
'false',
|
|
106
|
+
)
|
|
86
107
|
})
|
|
87
108
|
})
|
|
88
109
|
describe('when media control is hidden', () => {
|
|
89
110
|
beforeEach(() => {
|
|
111
|
+
emitSubtitleAvailable(core)
|
|
90
112
|
cc.$el.find('#cc-button').click()
|
|
91
113
|
mediaControl.trigger(Events.MEDIACONTROL_HIDE)
|
|
92
114
|
})
|
|
93
115
|
it('should hide menu', () => {
|
|
94
|
-
expect(cc.$el.find('#cc-
|
|
116
|
+
expect(cc.$el.find('#gplayer-cc-menu').css('display')).toBe('none')
|
|
117
|
+
})
|
|
118
|
+
})
|
|
119
|
+
describe('when container is clicked', () => {
|
|
120
|
+
beforeEach(() => {
|
|
121
|
+
emitSubtitleAvailable(core)
|
|
122
|
+
cc.$el.find('#gplayer-cc-button').click()
|
|
123
|
+
core.activeContainer.emit(Events.CONTAINER_CLICK)
|
|
124
|
+
})
|
|
125
|
+
it('should hide menu', () => {
|
|
126
|
+
expect(cc.$el.find('#gplayer-cc-menu').css('display')).toBe('none')
|
|
127
|
+
expect(cc.$el.find('#gplayer-cc-button').attr('aria-expanded')).toBe(
|
|
128
|
+
'false',
|
|
129
|
+
)
|
|
130
|
+
})
|
|
131
|
+
})
|
|
132
|
+
describe('when subtitle is changed', () => {
|
|
133
|
+
beforeEach(async () => {
|
|
134
|
+
emitSubtitleAvailable(core)
|
|
135
|
+
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
136
|
+
core.activePlayback.getCurrentTime = vi.fn().mockReturnValue(7)
|
|
137
|
+
core.activeContainer.getCurrentTime = vi.fn().mockReturnValue(7)
|
|
138
|
+
core.activePlayback.closedCaptionsTracks[1].track.cues = [
|
|
139
|
+
{
|
|
140
|
+
startTime: 0,
|
|
141
|
+
endTime: 5,
|
|
142
|
+
text: 'Alright this is me',
|
|
143
|
+
getCueAsHTML: vi
|
|
144
|
+
.fn()
|
|
145
|
+
.mockImplementation(() =>
|
|
146
|
+
document.createTextNode('Alright this is me'),
|
|
147
|
+
),
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
startTime: 5,
|
|
151
|
+
endTime: 10,
|
|
152
|
+
text: 'Welcome to my channel',
|
|
153
|
+
getCueAsHTML: vi
|
|
154
|
+
.fn()
|
|
155
|
+
.mockImplementation(() =>
|
|
156
|
+
document.createTextNode('Welcome to my channel'),
|
|
157
|
+
),
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
startTime: 10,
|
|
161
|
+
endTime: 15,
|
|
162
|
+
text: 'Thank you for watching',
|
|
163
|
+
getCueAsHTML: vi
|
|
164
|
+
.fn()
|
|
165
|
+
.mockImplementation(() =>
|
|
166
|
+
document.createTextNode('Thank you for watching'),
|
|
167
|
+
),
|
|
168
|
+
},
|
|
169
|
+
]
|
|
170
|
+
core.activePlayback.emit(Events.PLAYBACK_SUBTITLE_CHANGED, { id: 2 })
|
|
171
|
+
})
|
|
172
|
+
it('should activate subtitle track', () => {
|
|
173
|
+
expect(core.activePlayback.closedCaptionsTracks[1].track.mode).toBe(
|
|
174
|
+
'showing',
|
|
175
|
+
)
|
|
176
|
+
expect(core.activePlayback.closedCaptionsTracks[0].track.mode).toBe(
|
|
177
|
+
'hidden',
|
|
178
|
+
)
|
|
179
|
+
})
|
|
180
|
+
it('should show active subtitle text', () => {
|
|
181
|
+
expect(
|
|
182
|
+
core.activeContainer.$el.find('#gplayer-cc-line').text().trim(),
|
|
183
|
+
).toEqual('Welcome to my channel')
|
|
184
|
+
})
|
|
185
|
+
})
|
|
186
|
+
describe('when subtitle is selected from menu', () => {
|
|
187
|
+
beforeEach(() => {
|
|
188
|
+
emitSubtitleAvailable(core)
|
|
189
|
+
cc.$el.find('#gplayer-cc-menu li:nth-child(2) a').click()
|
|
190
|
+
})
|
|
191
|
+
it('should activate subtitle track', () => {
|
|
192
|
+
expect(core.activePlayback.closedCaptionsTrackId).toEqual(2)
|
|
193
|
+
})
|
|
194
|
+
it('should highlight selected menu item', () => {
|
|
195
|
+
expect(
|
|
196
|
+
cc.$el.find('#gplayer-cc-menu li:nth-child(2)').hasClass('current'),
|
|
197
|
+
).toBe(true)
|
|
198
|
+
expect(
|
|
199
|
+
cc.$el
|
|
200
|
+
.find('#gplayer-cc-menu li:nth-child(2) a')
|
|
201
|
+
.attr('aria-checked'),
|
|
202
|
+
).toBe('true')
|
|
203
|
+
expect(cc.$el.find('#gplayer-cc-menu li.current').length).toBe(1)
|
|
204
|
+
expect(
|
|
205
|
+
cc.$el.find('#gplayer-cc-menu li a[aria-checked="true"]').length,
|
|
206
|
+
).toBe(1)
|
|
207
|
+
})
|
|
208
|
+
it('should collapse menu', () => {
|
|
209
|
+
expect(cc.$el.find('#gplayer-cc-menu').css('display')).toBe('none')
|
|
210
|
+
})
|
|
211
|
+
})
|
|
212
|
+
describe('when user turns off subtitles', () => {
|
|
213
|
+
beforeEach(() => {
|
|
214
|
+
emitSubtitleAvailable(core)
|
|
215
|
+
core.activePlayback.closedCaptionsTracks[1].track.mode = 'showing'
|
|
216
|
+
core.activePlayback.closedCaptionsTrackId = 2
|
|
217
|
+
core.activePlayback.emit(Events.PLAYBACK_SUBTITLE_CHANGED, { id: 2 })
|
|
218
|
+
cc.$el.find('#gplayer-cc-button').click()
|
|
219
|
+
cc.$el.find('#gplayer-cc-menu li:nth-child(3) a').click() // off
|
|
220
|
+
})
|
|
221
|
+
it('should hide menu', () => {
|
|
222
|
+
expect(cc.$el.find('#gplayer-cc-menu').css('display')).toBe('none')
|
|
223
|
+
})
|
|
224
|
+
it('should hide subtitle text', () => {
|
|
225
|
+
expect(
|
|
226
|
+
core.activeContainer.$el.find('#gplayer-cc-line').text().trim(),
|
|
227
|
+
).toBe('')
|
|
228
|
+
})
|
|
229
|
+
it('should deactivate subtitle track', () => {
|
|
230
|
+
expect(core.activePlayback.closedCaptionsTrackId).toEqual(-1)
|
|
231
|
+
expect(core.activePlayback.closedCaptionsTracks[0].track.mode).toBe(
|
|
232
|
+
'hidden',
|
|
233
|
+
)
|
|
234
|
+
expect(core.activePlayback.closedCaptionsTracks[1].track.mode).toBe(
|
|
235
|
+
'hidden',
|
|
236
|
+
)
|
|
237
|
+
})
|
|
238
|
+
it('should select menu item', () => {
|
|
239
|
+
expect(
|
|
240
|
+
cc.$el.find('#gplayer-cc-menu li:nth-child(3)').hasClass('current'),
|
|
241
|
+
).toBe(true)
|
|
242
|
+
expect(
|
|
243
|
+
cc.$el
|
|
244
|
+
.find('#gplayer-cc-menu li:nth-child(3) a')
|
|
245
|
+
.attr('aria-checked'),
|
|
246
|
+
).toBe('true')
|
|
247
|
+
expect(cc.$el.find('#gplayer-cc-menu li.current').length).toBe(1)
|
|
248
|
+
expect(
|
|
249
|
+
cc.$el.find('#gplayer-cc-menu li a[aria-checked="true"]').length,
|
|
250
|
+
).toBe(1)
|
|
95
251
|
})
|
|
96
252
|
})
|
|
97
253
|
})
|
|
98
254
|
})
|
|
255
|
+
|
|
256
|
+
function emitSubtitleAvailable(core: any) {
|
|
257
|
+
core.activePlayback.closedCaptionsTracks = [
|
|
258
|
+
{
|
|
259
|
+
id: 1,
|
|
260
|
+
name: 'English',
|
|
261
|
+
track: {
|
|
262
|
+
language: 'en',
|
|
263
|
+
kind: 'subtitles',
|
|
264
|
+
label: 'English',
|
|
265
|
+
mode: 'hidden',
|
|
266
|
+
cues: [],
|
|
267
|
+
},
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
id: 2,
|
|
271
|
+
name: 'Spanish',
|
|
272
|
+
track: {
|
|
273
|
+
language: 'es',
|
|
274
|
+
kind: 'subtitles',
|
|
275
|
+
label: 'Spanish',
|
|
276
|
+
mode: 'hidden',
|
|
277
|
+
cues: [],
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
]
|
|
281
|
+
core.activePlayback.emit(Events.PLAYBACK_SUBTITLE_AVAILABLE)
|
|
282
|
+
core.activeContainer.emit(Events.CONTAINER_SUBTITLE_AVAILABLE)
|
|
283
|
+
}
|
|
@@ -1,25 +1,14 @@
|
|
|
1
1
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
2
|
|
|
3
3
|
exports[`ClosedCaptions > basically > should render 1`] = `
|
|
4
|
-
"<button
|
|
5
|
-
<span class="cc-text">/assets/icons/new/subtitles-off.svg</span>
|
|
6
|
-
</button>
|
|
4
|
+
"<button class="media-control-button media-control-icon gcore-skin-button-color media-control-dd" id="gplayer-cc-button" aria-haspopup="menu" aria-expanded="false" aria-controls="gplayer-cc-menu">/assets/icons/new/subtitles-off.svg</button>
|
|
7
5
|
|
|
8
|
-
<ul class="gcore-skin-bg-color" id="cc-
|
|
6
|
+
<ul class="gcore-skin-bg-color media-control-dd__popup" id="gplayer-cc-menu" role="menu" style="display: none; max-height: 211px;">
|
|
9
7
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
<li class="">
|
|
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
|
-
"
|
|
8
|
+
<li class="current">
|
|
9
|
+
<a href="#" class="gcore-skin-text-color gcore-skin-active" data-item="-1" role="menuitemradio" aria-checked="true">
|
|
10
|
+
off
|
|
11
|
+
</a>
|
|
12
|
+
</li>
|
|
13
|
+
</ul>"
|
|
25
14
|
`;
|
package/src/testUtils.ts
CHANGED
|
@@ -134,6 +134,8 @@ export function createMockMediaControl(core: any) {
|
|
|
134
134
|
// @ts-ignore
|
|
135
135
|
mediaControl.getAvailableHeight = vi.fn().mockReturnValue(300)
|
|
136
136
|
// @ts-ignore
|
|
137
|
+
mediaControl.getAvailablePopupHeight = vi.fn().mockReturnValue(286)
|
|
138
|
+
// @ts-ignore
|
|
137
139
|
mediaControl.toggleElement = vi.fn()
|
|
138
140
|
vi.spyOn(mediaControl, 'trigger')
|
|
139
141
|
core.$el.append(mediaControl.$el)
|