@gcorevideo/player 2.28.29 → 2.28.35
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/dist/core.js +1 -1
- package/dist/index.css +400 -400
- package/dist/index.embed.js +92 -74
- package/dist/index.js +150 -134
- package/docs/api/player.closedcaptionspluginsettings.md +1 -0
- package/docs/api/player.md +9 -0
- package/docs/api/player.mediacontrol.md +16 -0
- package/docs/api/player.thumbnails.md +1 -1
- package/lib/Player.d.ts.map +1 -1
- package/lib/plugins/media-control/MediaControl.d.ts +5 -6
- package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
- package/lib/plugins/media-control/MediaControl.js +40 -38
- package/lib/plugins/subtitles/ClosedCaptions.d.ts +6 -2
- package/lib/plugins/subtitles/ClosedCaptions.d.ts.map +1 -1
- package/lib/plugins/subtitles/ClosedCaptions.js +37 -23
- package/lib/plugins/utils/mobile.d.ts +2 -0
- package/lib/plugins/utils/mobile.d.ts.map +1 -0
- package/lib/plugins/utils/mobile.js +4 -0
- package/lib/testUtils.d.ts +1 -0
- package/lib/testUtils.d.ts.map +1 -1
- package/lib/testUtils.js +1 -0
- package/package.json +4 -1
- package/src/Player.ts +12 -12
- package/src/plugins/media-control/MediaControl.ts +45 -43
- package/src/plugins/media-control/__tests__/MediaControl.test.ts +63 -35
- package/src/plugins/subtitles/ClosedCaptions.ts +42 -28
- package/src/plugins/subtitles/__tests__/ClosedCaptions.test.ts +293 -6
- package/src/plugins/utils/mobile.ts +5 -0
- package/src/testUtils.ts +1 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
1
|
+
import { beforeEach, describe, expect, it, vi, afterEach } from 'vitest'
|
|
2
2
|
|
|
3
3
|
import { ClosedCaptions } from '../ClosedCaptions.js'
|
|
4
|
-
import { createMockCore, createMockMediaControl } from '../../../testUtils.js'
|
|
4
|
+
import { createMockContainer, createMockCore, createMockMediaControl } from '../../../testUtils.js'
|
|
5
5
|
import { ExtendedEvents } from '../../media-control/MediaControl.js'
|
|
6
6
|
|
|
7
7
|
import { Events } from '@clappr/core'
|
|
@@ -254,10 +254,297 @@ describe('ClosedCaptions', () => {
|
|
|
254
254
|
})
|
|
255
255
|
})
|
|
256
256
|
})
|
|
257
|
+
describe('when language is configured', () => {
|
|
258
|
+
describe("and is set to 'none'", () => {
|
|
259
|
+
beforeEach(() => {
|
|
260
|
+
vi.useFakeTimers()
|
|
261
|
+
core.options.cc = { language: 'none' }
|
|
262
|
+
emitSubtitleAvailable(core)
|
|
263
|
+
vi.advanceTimersByTime(1)
|
|
264
|
+
})
|
|
265
|
+
it('should disable subtitles', () => {
|
|
266
|
+
expect(core.activePlayback.closedCaptionsTrackId).toEqual(-1)
|
|
267
|
+
expect(
|
|
268
|
+
core.activeContainer.$el.find('#gplayer-cc-line').text().trim(),
|
|
269
|
+
).toBe('')
|
|
270
|
+
})
|
|
271
|
+
it('should have all tracks disabled', () => {
|
|
272
|
+
expect(core.activePlayback.closedCaptionsTracks[0].track.mode).toBe(
|
|
273
|
+
'disabled',
|
|
274
|
+
)
|
|
275
|
+
expect(core.activePlayback.closedCaptionsTracks[1].track.mode).toBe(
|
|
276
|
+
'disabled',
|
|
277
|
+
)
|
|
278
|
+
})
|
|
279
|
+
it('should hide subtitles', () => {
|
|
280
|
+
expect(cc.$el.find('#gplayer-cc-menu').css('display')).toBe('none')
|
|
281
|
+
})
|
|
282
|
+
})
|
|
283
|
+
describe('when language is undefined', () => {
|
|
284
|
+
// let spyClosedCaptionsTrackId: any // TODO
|
|
285
|
+
beforeEach(() => {
|
|
286
|
+
// spyClosedCaptionsTrackId = vi.spyOn(core.activePlayback, 'closedCaptionsTrackId')
|
|
287
|
+
core.options.cc = {}
|
|
288
|
+
core.activePlayback.closedCaptionsTrackId = undefined
|
|
289
|
+
emitSubtitleAvailable(core, 1)
|
|
290
|
+
})
|
|
291
|
+
// The native engine will decide
|
|
292
|
+
it('should not automatically select any track', () => {
|
|
293
|
+
expect(core.activePlayback.closedCaptionsTrackId).toEqual(undefined)
|
|
294
|
+
})
|
|
295
|
+
it('should not activate any tracks', () => {
|
|
296
|
+
expect(core.activePlayback.closedCaptionsTracks[0].track.mode).toBe(
|
|
297
|
+
'hidden', // showing is reset to hidden since the plugin manages rendition
|
|
298
|
+
)
|
|
299
|
+
expect(core.activePlayback.closedCaptionsTracks[1].track.mode).toBe(
|
|
300
|
+
'hidden',
|
|
301
|
+
)
|
|
302
|
+
})
|
|
303
|
+
})
|
|
304
|
+
describe('when language matches a track', () => {
|
|
305
|
+
beforeEach(() => {
|
|
306
|
+
vi.useFakeTimers()
|
|
307
|
+
core.options.cc = { language: 'en' }
|
|
308
|
+
emitSubtitleAvailable(core)
|
|
309
|
+
vi.advanceTimersByTime(1)
|
|
310
|
+
})
|
|
311
|
+
// afterEach(() => {
|
|
312
|
+
// vi.useRealTimers()
|
|
313
|
+
// })
|
|
314
|
+
it('should activate the matching track', () => {
|
|
315
|
+
expect(core.activePlayback.closedCaptionsTrackId).toEqual(1)
|
|
316
|
+
})
|
|
317
|
+
it('should set the matching track mode appropriately', () => {
|
|
318
|
+
// The matching track should be activated
|
|
319
|
+
expect(core.activePlayback.closedCaptionsTracks[0].track.mode).toBe(
|
|
320
|
+
'hidden',
|
|
321
|
+
)
|
|
322
|
+
expect(core.activePlayback.closedCaptionsTracks[1].track.mode).toBe(
|
|
323
|
+
'disabled',
|
|
324
|
+
)
|
|
325
|
+
})
|
|
326
|
+
it('should highlight the matching track in menu', () => {
|
|
327
|
+
expect(
|
|
328
|
+
cc.$el.find('#gplayer-cc-menu li:nth-child(1)').hasClass('current'),
|
|
329
|
+
).toBe(true)
|
|
330
|
+
})
|
|
331
|
+
})
|
|
332
|
+
describe('when language does not match any track', () => {
|
|
333
|
+
beforeEach(() => {
|
|
334
|
+
vi.useFakeTimers()
|
|
335
|
+
core.options.cc = { language: 'fr' }
|
|
336
|
+
cc = new ClosedCaptions(core)
|
|
337
|
+
core.emit(Events.CORE_READY)
|
|
338
|
+
core.activePlayback.el = document.createElement('video')
|
|
339
|
+
core.emit(Events.CORE_ACTIVE_CONTAINER_CHANGED, core.activeContainer)
|
|
340
|
+
emitSubtitleAvailable(core)
|
|
341
|
+
vi.advanceTimersByTime(1)
|
|
342
|
+
})
|
|
343
|
+
afterEach(() => {
|
|
344
|
+
vi.useRealTimers()
|
|
345
|
+
})
|
|
346
|
+
it('should disable subtitles', () => {
|
|
347
|
+
expect(core.activePlayback.closedCaptionsTrackId).toEqual(-1)
|
|
348
|
+
})
|
|
349
|
+
it('should have all tracks disabled', () => {
|
|
350
|
+
expect(core.activePlayback.closedCaptionsTracks[0].track.mode).toBe(
|
|
351
|
+
'disabled',
|
|
352
|
+
)
|
|
353
|
+
expect(core.activePlayback.closedCaptionsTracks[1].track.mode).toBe(
|
|
354
|
+
'disabled',
|
|
355
|
+
)
|
|
356
|
+
})
|
|
357
|
+
it('should hide subtitle text', () => {
|
|
358
|
+
expect(
|
|
359
|
+
core.activeContainer.$el.find('#gplayer-cc-line').text().trim(),
|
|
360
|
+
).toBe('')
|
|
361
|
+
})
|
|
362
|
+
})
|
|
363
|
+
})
|
|
364
|
+
describe('when subtitle available event occurs after user selection', () => {
|
|
365
|
+
describe('if user selected track before event', () => {
|
|
366
|
+
beforeEach(() => {
|
|
367
|
+
vi.useFakeTimers()
|
|
368
|
+
core.options.cc = { language: 'en' }
|
|
369
|
+
// First subtitle available event
|
|
370
|
+
emitSubtitleAvailable(core)
|
|
371
|
+
vi.advanceTimersByTime(1)
|
|
372
|
+
cc.$el.find('#gplayer-cc-button').click()
|
|
373
|
+
vi.advanceTimersByTime(1)
|
|
374
|
+
// User manually selects Spanish track
|
|
375
|
+
cc.$el.find('#gplayer-cc-menu li:nth-child(2) a').click()
|
|
376
|
+
vi.advanceTimersByTime(1)
|
|
377
|
+
|
|
378
|
+
core.activeContainer = createMockContainer()
|
|
379
|
+
// Reset isPreselectedApplied by emitting container changed
|
|
380
|
+
core.emit(Events.CORE_ACTIVE_CONTAINER_CHANGED, core.activeContainer)
|
|
381
|
+
// Second subtitle available event (e.g., after source switch)
|
|
382
|
+
emitSubtitleAvailable(core)
|
|
383
|
+
vi.advanceTimersByTime(1)
|
|
384
|
+
})
|
|
385
|
+
afterEach(() => {
|
|
386
|
+
vi.useRealTimers()
|
|
387
|
+
})
|
|
388
|
+
it('should run preselected language matching algorithm', () => {
|
|
389
|
+
// Should activate track selected by user
|
|
390
|
+
expect(core.activePlayback.closedCaptionsTrackId).toEqual(2)
|
|
391
|
+
})
|
|
392
|
+
it('should select track based on configured language', () => {
|
|
393
|
+
expect(
|
|
394
|
+
cc.$el.find('#gplayer-cc-menu li:nth-child(2)').hasClass('current'),
|
|
395
|
+
).toBe(true)
|
|
396
|
+
})
|
|
397
|
+
it('should activate the track matching the selected', () => {
|
|
398
|
+
expect(core.activePlayback.closedCaptionsTracks[0].track.mode).toBe(
|
|
399
|
+
'disabled',
|
|
400
|
+
)
|
|
401
|
+
// not 'showing' because the plugin manages the subtitles rendition
|
|
402
|
+
expect(core.activePlayback.closedCaptionsTracks[1].track.mode).toBe(
|
|
403
|
+
'hidden',
|
|
404
|
+
)
|
|
405
|
+
})
|
|
406
|
+
})
|
|
407
|
+
describe('when multiple subtitle available events occur', () => {
|
|
408
|
+
beforeEach(() => {
|
|
409
|
+
vi.useFakeTimers()
|
|
410
|
+
core.options.cc = { language: 'en' }
|
|
411
|
+
// cc = new ClosedCaptions(core)
|
|
412
|
+
// core.emit(Events.CORE_READY)
|
|
413
|
+
// core.activePlayback.el = document.createElement('video')
|
|
414
|
+
// core.emit(Events.CORE_ACTIVE_CONTAINER_CHANGED, core.activeContainer)
|
|
415
|
+
// First subtitle available event
|
|
416
|
+
emitSubtitleAvailable(core)
|
|
417
|
+
vi.advanceTimersByTime(1)
|
|
418
|
+
// User changes selection
|
|
419
|
+
// cc.$el.find('#gplayer-cc-menu li:nth-child(2) a').click()
|
|
420
|
+
// Container changed (simulating source switch)
|
|
421
|
+
core.emit(Events.CORE_ACTIVE_CONTAINER_CHANGED, core.activeContainer)
|
|
422
|
+
vi.advanceTimersByTime(1)
|
|
423
|
+
core.activePlayback.closedCaptionsTrackId = undefined
|
|
424
|
+
// Second subtitle available event
|
|
425
|
+
emitSubtitleAvailable(core)
|
|
426
|
+
vi.advanceTimersByTime(1)
|
|
427
|
+
})
|
|
428
|
+
afterEach(() => {
|
|
429
|
+
vi.useRealTimers()
|
|
430
|
+
})
|
|
431
|
+
it('should reapply preselected language matching', () => {
|
|
432
|
+
expect(core.activePlayback.closedCaptionsTrackId).toEqual(1)
|
|
433
|
+
// Should select English track based on configured language
|
|
434
|
+
expect(
|
|
435
|
+
cc.$el.find('#gplayer-cc-menu li:nth-child(1)').hasClass('current'),
|
|
436
|
+
).toBe(true)
|
|
437
|
+
})
|
|
438
|
+
it('should activate the matching track', () => {
|
|
439
|
+
expect(core.activePlayback.closedCaptionsTracks[0].track.mode).toBe(
|
|
440
|
+
'hidden',
|
|
441
|
+
)
|
|
442
|
+
expect(core.activePlayback.closedCaptionsTracks[1].track.mode).toBe(
|
|
443
|
+
'disabled',
|
|
444
|
+
)
|
|
445
|
+
})
|
|
446
|
+
})
|
|
447
|
+
})
|
|
448
|
+
describe.each(['dash', 'hls'] as const)(
|
|
449
|
+
'when playback engine is %s',
|
|
450
|
+
(playbackEngine) => {
|
|
451
|
+
beforeEach(() => {
|
|
452
|
+
// core.emit(Events.CORE_READY)
|
|
453
|
+
core.activePlayback.el = document.createElement('video')
|
|
454
|
+
core.activePlayback.name = playbackEngine
|
|
455
|
+
core.activePlayback.setTextTrack = vi.fn()
|
|
456
|
+
// core.emit(Events.CORE_ACTIVE_CONTAINER_CHANGED, core.activeContainer)
|
|
457
|
+
})
|
|
458
|
+
describe('when language is configured and matches a track', () => {
|
|
459
|
+
beforeEach(() => {
|
|
460
|
+
vi.useFakeTimers()
|
|
461
|
+
core.options.cc = { language: 'en' }
|
|
462
|
+
// cc = new ClosedCaptions(core)
|
|
463
|
+
// core.emit(Events.CORE_READY)
|
|
464
|
+
// core.activePlayback.el = document.createElement('video')
|
|
465
|
+
// core.activePlayback.name = playbackEngine
|
|
466
|
+
// core.activePlayback.setTextTrack = vi.fn()
|
|
467
|
+
// core.emit(Events.CORE_ACTIVE_CONTAINER_CHANGED, core.activeContainer)
|
|
468
|
+
emitSubtitleAvailable(core)
|
|
469
|
+
vi.advanceTimersByTime(1)
|
|
470
|
+
})
|
|
471
|
+
afterEach(() => {
|
|
472
|
+
vi.useRealTimers()
|
|
473
|
+
})
|
|
474
|
+
it('should call setTextTrack with matching track id', () => {
|
|
475
|
+
expect(core.activePlayback.setTextTrack).toHaveBeenCalledWith(1)
|
|
476
|
+
})
|
|
477
|
+
it('should set closedCaptionsTrackId to matching track id', () => {
|
|
478
|
+
expect(core.activePlayback.closedCaptionsTrackId).toEqual(1)
|
|
479
|
+
})
|
|
480
|
+
it('should not touch native tracks', () => {
|
|
481
|
+
expect(core.activePlayback.closedCaptionsTracks[0].track.mode).toBe('hidden')
|
|
482
|
+
expect(core.activePlayback.closedCaptionsTracks[1].track.mode).toBe('hidden')
|
|
483
|
+
})
|
|
484
|
+
})
|
|
485
|
+
describe('when language is configured but does not match any track', () => {
|
|
486
|
+
beforeEach(() => {
|
|
487
|
+
vi.useFakeTimers()
|
|
488
|
+
core.options.cc = { language: 'fr' }
|
|
489
|
+
cc = new ClosedCaptions(core)
|
|
490
|
+
core.emit(Events.CORE_READY)
|
|
491
|
+
core.activePlayback.el = document.createElement('video')
|
|
492
|
+
core.activePlayback.name = playbackEngine
|
|
493
|
+
core.activePlayback.setTextTrack = vi.fn()
|
|
494
|
+
core.emit(Events.CORE_ACTIVE_CONTAINER_CHANGED, core.activeContainer)
|
|
495
|
+
emitSubtitleAvailable(core)
|
|
496
|
+
vi.advanceTimersByTime(1)
|
|
497
|
+
})
|
|
498
|
+
afterEach(() => {
|
|
499
|
+
vi.useRealTimers()
|
|
500
|
+
})
|
|
501
|
+
it('should disable subtitles', () => {
|
|
502
|
+
expect(core.activePlayback.setTextTrack).toHaveBeenCalledWith(-1)
|
|
503
|
+
expect(core.activePlayback.closedCaptionsTrackId).toEqual(-1)
|
|
504
|
+
})
|
|
505
|
+
})
|
|
506
|
+
describe('when user selects a track from menu', () => {
|
|
507
|
+
beforeEach(() => {
|
|
508
|
+
core.activePlayback.setTextTrack = vi.fn()
|
|
509
|
+
emitSubtitleAvailable(core)
|
|
510
|
+
cc.$el.find('#gplayer-cc-menu li:nth-child(2) a').click()
|
|
511
|
+
})
|
|
512
|
+
it('should call setTextTrack with selected track id', () => {
|
|
513
|
+
// TODO: Implement assertion
|
|
514
|
+
// expect(core.activePlayback.setTextTrack).toHaveBeenCalledWith(2)
|
|
515
|
+
})
|
|
516
|
+
it('should update closedCaptionsTrackId', () => {
|
|
517
|
+
// TODO: Implement assertion
|
|
518
|
+
// expect(core.activePlayback.closedCaptionsTrackId).toEqual(2)
|
|
519
|
+
})
|
|
520
|
+
})
|
|
521
|
+
describe('when language is set to none', () => {
|
|
522
|
+
beforeEach(() => {
|
|
523
|
+
vi.useFakeTimers()
|
|
524
|
+
core.options.cc = { language: 'none' }
|
|
525
|
+
cc = new ClosedCaptions(core)
|
|
526
|
+
core.emit(Events.CORE_READY)
|
|
527
|
+
core.activePlayback.el = document.createElement('video')
|
|
528
|
+
core.activePlayback.name = playbackEngine
|
|
529
|
+
core.activePlayback.setTextTrack = vi.fn()
|
|
530
|
+
core.emit(Events.CORE_ACTIVE_CONTAINER_CHANGED, core.activeContainer)
|
|
531
|
+
emitSubtitleAvailable(core)
|
|
532
|
+
vi.advanceTimersByTime(1)
|
|
533
|
+
})
|
|
534
|
+
afterEach(() => {
|
|
535
|
+
vi.useRealTimers()
|
|
536
|
+
})
|
|
537
|
+
it('should call setTextTrack with -1 to disable subtitles', () => {
|
|
538
|
+
// TODO: Implement assertion
|
|
539
|
+
// expect(core.activePlayback.setTextTrack).toHaveBeenCalledWith(-1)
|
|
540
|
+
})
|
|
541
|
+
})
|
|
542
|
+
},
|
|
543
|
+
)
|
|
257
544
|
})
|
|
258
545
|
})
|
|
259
546
|
|
|
260
|
-
function emitSubtitleAvailable(core: any) {
|
|
547
|
+
function emitSubtitleAvailable(core: any, selectedTrackId?: number) {
|
|
261
548
|
core.activePlayback.closedCaptionsTracks = [
|
|
262
549
|
{
|
|
263
550
|
id: 1,
|
|
@@ -266,7 +553,7 @@ function emitSubtitleAvailable(core: any) {
|
|
|
266
553
|
language: 'en',
|
|
267
554
|
kind: 'subtitles',
|
|
268
555
|
label: 'English',
|
|
269
|
-
mode: 'hidden',
|
|
556
|
+
mode: selectedTrackId === 1 ? 'showing' : 'hidden',
|
|
270
557
|
cues: [],
|
|
271
558
|
},
|
|
272
559
|
},
|
|
@@ -276,8 +563,8 @@ function emitSubtitleAvailable(core: any) {
|
|
|
276
563
|
track: {
|
|
277
564
|
language: 'es',
|
|
278
565
|
kind: 'subtitles',
|
|
279
|
-
label: '
|
|
280
|
-
mode: 'hidden',
|
|
566
|
+
label: 'Español',
|
|
567
|
+
mode: selectedTrackId === 2 ? 'showing' : 'hidden',
|
|
281
568
|
cues: [],
|
|
282
569
|
},
|
|
283
570
|
},
|