@gcorevideo/player 2.22.23 → 2.22.25

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 (34) hide show
  1. package/assets/clappr-nerd-stats/clappr-nerd-stats.scss +11 -0
  2. package/assets/subtitles/combobox.ejs +1 -1
  3. package/assets/subtitles/style.scss +0 -1
  4. package/dist/core.js +1 -1
  5. package/dist/index.css +1411 -1405
  6. package/dist/index.js +48 -31
  7. package/dist/plugins/index.css +516 -517
  8. package/dist/plugins/index.js +47 -29
  9. package/lib/plugins/audio-selector/AudioTracks.d.ts +2 -2
  10. package/lib/plugins/audio-selector/AudioTracks.d.ts.map +1 -1
  11. package/lib/plugins/audio-selector/AudioTracks.js +12 -7
  12. package/lib/plugins/bottom-gear/BottomGear.d.ts +1 -1
  13. package/lib/plugins/bottom-gear/BottomGear.d.ts.map +1 -1
  14. package/lib/plugins/bottom-gear/BottomGear.js +9 -5
  15. package/lib/plugins/subtitles/ClosedCaptions.d.ts +3 -3
  16. package/lib/plugins/subtitles/ClosedCaptions.d.ts.map +1 -1
  17. package/lib/plugins/subtitles/ClosedCaptions.js +27 -19
  18. package/lib/testUtils.d.ts.map +1 -1
  19. package/lib/testUtils.js +1 -0
  20. package/package.json +1 -1
  21. package/rollup.config.js +28 -28
  22. package/src/plugins/audio-selector/AudioTracks.ts +12 -7
  23. package/src/plugins/audio-selector/__tests__/AudioTracks.test.ts +18 -1
  24. package/src/plugins/audio-selector/__tests__/__snapshots__/AudioTracks.test.ts.snap +1 -1
  25. package/src/plugins/bottom-gear/BottomGear.ts +9 -5
  26. package/src/plugins/bottom-gear/__tests__/BottomGear.test.ts +19 -1
  27. package/src/plugins/subtitles/ClosedCaptions.ts +27 -20
  28. package/src/plugins/subtitles/__tests__/ClosedCaptions.test.ts +52 -13
  29. package/src/plugins/subtitles/__tests__/__snapshots__/ClosedCaptions.test.ts.snap +4 -4
  30. package/src/testUtils.ts +1 -0
  31. package/tsconfig.tsbuildinfo +1 -1
  32. package/assets/subtitles/combobox copy.ejs +0 -16
  33. /package/assets/{audio-selector → audio-tracks}/style.scss +0 -0
  34. /package/assets/{audio-selector/track-selector.ejs → audio-tracks/template.ejs} +0 -0
@@ -4,8 +4,8 @@ import assert from 'assert'
4
4
 
5
5
  import { CLAPPR_VERSION } from '../../build.js'
6
6
 
7
- import pluginHtml from '../../../assets/audio-selector/track-selector.ejs'
8
- import '../../../assets/audio-selector/style.scss'
7
+ import pluginHtml from '../../../assets/audio-tracks/template.ejs'
8
+ import '../../../assets/audio-tracks/style.scss'
9
9
  import audioArrow from '../../../assets/icons/old/quality-arrow.svg'
10
10
  import { ZeptoResult } from '../../types.js'
11
11
  import { ExtendedEvents, MediaControl } from '../media-control/MediaControl.js'
@@ -34,7 +34,7 @@ export class AudioTracks extends UICorePlugin {
34
34
  * @internal
35
35
  */
36
36
  get name() {
37
- return 'audio_selector' // TODO rename to audiotracks
37
+ return 'audio_tracks'
38
38
  }
39
39
 
40
40
  /**
@@ -68,7 +68,7 @@ export class AudioTracks extends UICorePlugin {
68
68
  override get events() {
69
69
  return {
70
70
  'click [data-audiotracks-select]': 'onTrackSelect',
71
- 'click #audiotracks-button': 'toggleContextMenu',
71
+ 'click #audiotracks-button': 'toggleMenu',
72
72
  }
73
73
  }
74
74
 
@@ -91,7 +91,11 @@ export class AudioTracks extends UICorePlugin {
91
91
  mediaControl.mount('audiotracks', this.$el)
92
92
  })
93
93
  this.listenTo(mediaControl, Events.MEDIACONTROL_HIDE, this.hideMenu)
94
- this.listenTo(mediaControl, ExtendedEvents.MEDIACONTROL_MENU_COLLAPSE, this.hideMenu)
94
+ this.listenTo(mediaControl, ExtendedEvents.MEDIACONTROL_MENU_COLLAPSE, (from: string) => {
95
+ if (from !== this.name) {
96
+ this.hideMenu()
97
+ }
98
+ })
95
99
  }
96
100
 
97
101
  private onActiveContainerChanged() {
@@ -165,10 +169,11 @@ export class AudioTracks extends UICorePlugin {
165
169
  private hideMenu() {
166
170
  trace(`${T} hideMenu`)
167
171
  this.$el.find('#audiotracks-select').addClass('hidden')
172
+ this.$el.find('#audiotracks-button').attr('aria-expanded', 'false')
168
173
  }
169
174
 
170
- private toggleContextMenu() {
171
- this.core.getPlugin('media_control').trigger(ExtendedEvents.MEDIACONTROL_MENU_COLLAPSE)
175
+ private toggleMenu() {
176
+ this.core.getPlugin('media_control').trigger(ExtendedEvents.MEDIACONTROL_MENU_COLLAPSE, this.name)
172
177
  this.$el.find('#audiotracks-select').toggleClass('hidden') // TODO use plain CSS display: none
173
178
  const open = !this.$el.find('#audiotracks-select').hasClass('hidden') // TODO hold state
174
179
  this.$el.find('#audiotracks-button').attr('aria-expanded', open)
@@ -1,6 +1,6 @@
1
1
  import { beforeEach, describe, expect, it, vi } from 'vitest'
2
2
  import { Events } from '@clappr/core'
3
-
3
+ import { ExtendedEvents } from '../../media-control/MediaControl'
4
4
  import { AudioTracks } from '../AudioTracks'
5
5
 
6
6
  import { createMockCore, createMockMediaControl } from '../../../testUtils'
@@ -78,6 +78,12 @@ describe('AudioTracks', () => {
78
78
  audioTracks.$el.find('#audiotracks-select').hasClass('hidden'),
79
79
  ).toBe(false)
80
80
  })
81
+ it('should collapse all other menus', () => {
82
+ expect(mediaControl.trigger).toHaveBeenCalledWith(
83
+ ExtendedEvents.MEDIACONTROL_MENU_COLLAPSE,
84
+ 'audio_tracks',
85
+ )
86
+ })
81
87
  describe('when audio track is selected', () => {
82
88
  beforeEach(() => {
83
89
  audioTracks.$el
@@ -94,6 +100,7 @@ describe('AudioTracks', () => {
94
100
  expect(
95
101
  audioTracks.$el.find('#audiotracks-select').hasClass('hidden'),
96
102
  ).toBe(true)
103
+ expect(audioTracks.$el.find('#audiotracks-button').attr('aria-expanded')).toBe('false')
97
104
  })
98
105
  it('should add changing class to the button', () => {
99
106
  expect(
@@ -153,6 +160,16 @@ describe('AudioTracks', () => {
153
160
  })
154
161
  })
155
162
  })
163
+ describe('when button is clicked twice', () => {
164
+ beforeEach(() => {
165
+ audioTracks.$el.find('#audiotracks-button').click()
166
+ audioTracks.$el.find('#audiotracks-button').click()
167
+ })
168
+ it('should collapse the menu', () => {
169
+ expect(audioTracks.$el.find('#audiotracks-select').hasClass('hidden')).toBe(true)
170
+ expect(audioTracks.$el.find('#audiotracks-button').attr('aria-expanded')).toBe('false')
171
+ })
172
+ })
156
173
  })
157
174
  describe('when audio tracks are not available', () => {
158
175
  it('should not render the button', () => {
@@ -45,7 +45,7 @@ exports[`AudioTracks > given that audio tracks are available > when button is cl
45
45
  `;
46
46
 
47
47
  exports[`AudioTracks > given that audio tracks are available > when button is clicked > when audio track is selected > should hide the menu 1`] = `
48
- "<button data-audiotracks-button="" class="gcore-skin-button-color changing" id="audiotracks-button" aria-haspopup="menu" aria-expanded="true">
48
+ "<button data-audiotracks-button="" class="gcore-skin-button-color changing" id="audiotracks-button" aria-haspopup="menu" aria-expanded="false">
49
49
  <span class="audio-text"></span> <span class="audio-arrow">/assets/icons/old/quality-arrow.svg</span>
50
50
  </button>
51
51
  <ul class="gcore-skin-bg-color menu hidden" id="audiotracks-select" role="menu">
@@ -98,7 +98,7 @@ export enum GearEvents {
98
98
  * ```
99
99
  */
100
100
  export class BottomGear extends UICorePlugin {
101
- private isHd = false
101
+ private hd = false
102
102
 
103
103
  /**
104
104
  * @internal
@@ -216,7 +216,7 @@ export class BottomGear extends UICorePlugin {
216
216
 
217
217
  private highDefinitionUpdate(isHd: boolean) {
218
218
  trace(`${T} highDefinitionUpdate`, { isHd })
219
- this.isHd = isHd
219
+ this.hd = isHd
220
220
  this.$el.find('.gear-icon').html(isHd ? gearHdIcon : gearIcon)
221
221
  }
222
222
 
@@ -229,7 +229,7 @@ export class BottomGear extends UICorePlugin {
229
229
  if (!mediaControl) {
230
230
  return this // TODO test
231
231
  }
232
- const icon = this.isHd ? gearHdIcon : gearIcon
232
+ const icon = this.hd ? gearHdIcon : gearIcon
233
233
  this.$el
234
234
  .html(BottomGear.template({ icon }))
235
235
  .find('#gear-sub-menu-wrapper')
@@ -257,7 +257,7 @@ export class BottomGear extends UICorePlugin {
257
257
  private toggleGearMenu() {
258
258
  this.core
259
259
  .getPlugin('media_control')
260
- .trigger(ExtendedEvents.MEDIACONTROL_MENU_COLLAPSE)
260
+ .trigger(ExtendedEvents.MEDIACONTROL_MENU_COLLAPSE, this.name)
261
261
  this.$el.find('#gear-options-wrapper').toggle()
262
262
  }
263
263
 
@@ -279,7 +279,11 @@ export class BottomGear extends UICorePlugin {
279
279
  this.listenTo(
280
280
  mediaControl,
281
281
  ExtendedEvents.MEDIACONTROL_MENU_COLLAPSE,
282
- this.hide,
282
+ (from: string) => {
283
+ if (from !== this.name) {
284
+ this.hide()
285
+ }
286
+ },
283
287
  )
284
288
  }
285
289
 
@@ -3,6 +3,7 @@ import { MockedFunction, beforeEach, describe, expect, it, vi } from 'vitest'
3
3
  import { BottomGear, GearEvents } from '../BottomGear'
4
4
  import { createMockCore, createMockMediaControl } from '../../../testUtils'
5
5
  import { Events } from '@clappr/core'
6
+ import { ExtendedEvents } from '../../media-control/MediaControl'
6
7
 
7
8
  describe('BottomGear', () => {
8
9
  let mediaControl: any
@@ -56,10 +57,27 @@ describe('BottomGear', () => {
56
57
  beforeEach(() => {
57
58
  bottomGear.$el.find('#gear-button').click()
58
59
  })
59
- it('should toggle the gear menu', () => {
60
+ it('should open the gear menu', () => {
60
61
  expect(
61
62
  bottomGear.$el.find('#gear-options-wrapper').css('display'),
62
63
  ).not.toBe('none')
63
64
  })
65
+ it('should trigger media control menu collapse', () => {
66
+ expect(mediaControl.trigger).toHaveBeenCalledWith(
67
+ ExtendedEvents.MEDIACONTROL_MENU_COLLAPSE,
68
+ 'bottom_gear',
69
+ )
70
+ })
71
+ })
72
+ describe('when clicked twice', () => {
73
+ beforeEach(() => {
74
+ bottomGear.$el.find('#gear-button').click()
75
+ bottomGear.$el.find('#gear-button').click()
76
+ })
77
+ it('should collapse the gear menu', () => {
78
+ expect(bottomGear.$el.find('#gear-options-wrapper').css('display')).toBe(
79
+ 'none',
80
+ )
81
+ })
64
82
  })
65
83
  })
@@ -62,7 +62,7 @@ export type ClosedCaptionsPluginSettings = {
62
62
  export class ClosedCaptions extends UICorePlugin {
63
63
  private isPreselectedApplied = false
64
64
 
65
- private isShowing = false
65
+ private active = false
66
66
 
67
67
  private track: TextTrackItem | null = null
68
68
 
@@ -109,8 +109,8 @@ export class ClosedCaptions extends UICorePlugin {
109
109
  */
110
110
  override get events() {
111
111
  return {
112
- 'click [data-cc-select]': 'onItemSelect',
113
- 'click [data-cc-button]': 'toggleMenu',
112
+ 'click #cc-select li a': 'onItemSelect',
113
+ 'click #cc-button': 'toggleMenu',
114
114
  }
115
115
  }
116
116
 
@@ -139,12 +139,18 @@ export class ClosedCaptions extends UICorePlugin {
139
139
  trace(`${T} onCoreReady`)
140
140
  const mediaControl = this.core.getPlugin('media_control')
141
141
  assert(mediaControl, 'media_control plugin is required')
142
- this.listenTo(mediaControl, Events.MEDIACONTROL_RENDERED, this.render)
143
- this.listenTo(mediaControl, Events.MEDIACONTROL_HIDE, this.hideMenu)
142
+ this.listenTo(mediaControl, Events.MEDIACONTROL_RENDERED, this.render) // TODO mount to media control
143
+ this.listenTo(mediaControl, Events.MEDIACONTROL_HIDE, () => {
144
+ this.hideMenu()
145
+ })
144
146
  this.listenTo(
145
147
  mediaControl,
146
148
  ExtendedEvents.MEDIACONTROL_MENU_COLLAPSE,
147
- this.hideMenu,
149
+ (from: string) => {
150
+ if (from !== this.name) {
151
+ this.hideMenu()
152
+ }
153
+ },
148
154
  )
149
155
  }
150
156
 
@@ -235,7 +241,7 @@ export class ClosedCaptions extends UICorePlugin {
235
241
  }
236
242
 
237
243
  private onStartAd() {
238
- if (this.isShowing && this.core.activeContainer) {
244
+ if (this.active && this.core.activeContainer) {
239
245
  this.hide()
240
246
  this.listenTo(
241
247
  this.core.activeContainer,
@@ -262,7 +268,7 @@ export class ClosedCaptions extends UICorePlugin {
262
268
  this.track &&
263
269
  this.track.track.mode &&
264
270
  Browser.isiOS &&
265
- this.isShowing
271
+ this.active
266
272
 
267
273
  if (shouldShow) {
268
274
  this.show()
@@ -279,7 +285,7 @@ export class ClosedCaptions extends UICorePlugin {
279
285
  * Hides the subtitles menu and the subtitles.
280
286
  */
281
287
  hide() {
282
- this.isShowing = false
288
+ this.active = false
283
289
  this.renderIcon()
284
290
  this.$line.hide()
285
291
  if (this.tracks) {
@@ -293,7 +299,7 @@ export class ClosedCaptions extends UICorePlugin {
293
299
  * Shows the subtitles menu and the subtitles.
294
300
  */
295
301
  show() {
296
- this.isShowing = true
302
+ this.active = true
297
303
  this.renderIcon()
298
304
  if (
299
305
  this.core.activeContainer &&
@@ -337,7 +343,8 @@ export class ClosedCaptions extends UICorePlugin {
337
343
 
338
344
  const mediaControl = this.core.getPlugin('media_control')
339
345
 
340
- this.$el.html(ClosedCaptions.template({ tracks: this.tracks }))
346
+ this.$el.html(ClosedCaptions.template({ tracks: this.tracks, i18n: this.core.i18n }))
347
+ this.$el.find('#cc-select').hide()
341
348
  this.core.activeContainer.$el.find('#cc-line').remove()
342
349
  this.$line = $(ClosedCaptions.templateString())
343
350
  this.resizeFont()
@@ -360,7 +367,6 @@ export class ClosedCaptions extends UICorePlugin {
360
367
  this.clearSubtitleText()
361
368
  this.track = item
362
369
 
363
- this.hideMenu()
364
370
  this.updateSelection()
365
371
  }
366
372
 
@@ -371,7 +377,7 @@ export class ClosedCaptions extends UICorePlugin {
371
377
 
372
378
  localStorage.setItem(LOCAL_STORAGE_CC_ID, id)
373
379
  this.selectItem(this.findById(Number(id)))
374
-
380
+ this.hideMenu()
375
381
  return false
376
382
  }
377
383
 
@@ -393,23 +399,24 @@ export class ClosedCaptions extends UICorePlugin {
393
399
 
394
400
  private hideMenu() {
395
401
  trace(`${T} hideMenu`)
396
- ;(this.$('[data-cc] ul') as ZeptoResult).hide()
402
+ this.$el.find('#cc-select').hide()
397
403
  }
398
404
 
399
405
  private toggleMenu() {
400
- trace(`${T} toggleMenu`)
406
+ trace(`${T} toggleMenu`, {display: this.$el.find('#cc-select').css('display')})
401
407
  this.core
402
408
  .getPlugin('media_control')
403
- .trigger(ExtendedEvents.MEDIACONTROL_MENU_COLLAPSE)
404
- this.$el.find('[data-cc] ul').toggle()
409
+ .trigger(ExtendedEvents.MEDIACONTROL_MENU_COLLAPSE, this.name)
410
+ this.$el.find('#cc-select').toggle()
411
+ // TODO hold state, add aria-expanded to the button, add active state to the button
405
412
  }
406
413
 
407
414
  private itemElement(id: number): ZeptoResult {
408
- return (this.$(`ul li a[data-cc-select="${id}"]`) as ZeptoResult).parent()
415
+ return this.$el.find(`#cc-select li a[data-cc-select="${id}"]`).parent()
409
416
  }
410
417
 
411
418
  private allItemElements(): ZeptoResult {
412
- return this.$('[data-cc] li')
419
+ return this.$('#cc-select li')
413
420
  }
414
421
 
415
422
  private selectSubtitles() {
@@ -471,7 +478,7 @@ export class ClosedCaptions extends UICorePlugin {
471
478
  }
472
479
 
473
480
  private renderIcon() {
474
- const icon = this.isShowing ? subtitlesOnIcon : subtitlesOffIcon
481
+ const icon = this.active ? subtitlesOnIcon : subtitlesOffIcon
475
482
 
476
483
  this.$el.find('span.cc-text').html(icon)
477
484
  }
@@ -1,12 +1,20 @@
1
1
  import { beforeEach, describe, expect, it, vi } from 'vitest'
2
2
 
3
3
  import { ClosedCaptions } from '../ClosedCaptions.js'
4
- import { createMockCore, createMockMediaControl } from '../../../testUtils.js';
4
+ import { createMockCore, createMockMediaControl } from '../../../testUtils.js'
5
+ import { ExtendedEvents } from '../../media-control/MediaControl.js'
6
+
7
+ import { LogTracer, Logger, setTracer } from '@gcorevideo/utils'
8
+ import { Events } from '@clappr/core'
9
+ // import { Events } from '@clappr/core';
10
+
11
+ // Logger.enable('*')
12
+ // setTracer(new LogTracer('ClosedCaptions.test'))
5
13
 
6
14
  describe('ClosedCaptions', () => {
7
- let core: any;
8
- let mediaControl: any;
9
- let cc: ClosedCaptions;
15
+ let core: any
16
+ let mediaControl: any
17
+ let cc: ClosedCaptions
10
18
  beforeEach(() => {
11
19
  core = createMockCore()
12
20
  mediaControl = createMockMediaControl(core)
@@ -20,9 +28,9 @@ describe('ClosedCaptions', () => {
20
28
  })
21
29
  describe('basically', () => {
22
30
  beforeEach(() => {
23
- core.emit('core:ready')
31
+ core.emit(Events.CORE_READY)
24
32
  core.activePlayback.el = document.createElement('video')
25
- core.emit('core:active:container:changed', core.activeContainer)
33
+ core.emit(Events.CORE_ACTIVE_CONTAINER_CHANGED, core.activeContainer)
26
34
  core.activePlayback.closedCaptionsTracks = [
27
35
  {
28
36
  id: 1,
@@ -33,7 +41,7 @@ describe('ClosedCaptions', () => {
33
41
  label: 'English',
34
42
  mode: 'hidden',
35
43
  cues: [],
36
- }
44
+ },
37
45
  },
38
46
  {
39
47
  id: 2,
@@ -44,16 +52,47 @@ describe('ClosedCaptions', () => {
44
52
  label: 'Spanish',
45
53
  mode: 'hidden',
46
54
  cues: [],
47
- }
48
- }
55
+ },
56
+ },
49
57
  ]
50
- core.activePlayback.emit('playback:subtitle:available')
51
- core.activeContainer.emit('container:subtitle:available')
58
+ core.activePlayback.emit(Events.PLAYBACK_SUBTITLE_AVAILABLE)
59
+ core.activeContainer.emit(Events.CONTAINER_SUBTITLE_AVAILABLE)
52
60
  })
53
61
  it('should render', () => {
54
62
  expect(cc.el.innerHTML).toMatchSnapshot()
55
- expect(cc.$el.find('[data-cc-button]').length).toEqual(1)
63
+ expect(cc.$el.find('#cc-button').length).toEqual(1)
56
64
  expect(mediaControl.mount).toHaveBeenCalledWith('cc', cc.$el)
57
65
  })
66
+ describe('when button is clicked', () => {
67
+ beforeEach(() => {
68
+ cc.$el.find('#cc-button').click()
69
+ })
70
+ it('should open menu', () => {
71
+ expect(cc.$el.find('#cc-select').css('display')).not.toBe('none')
72
+ })
73
+ it('should collapse all other menus', () => {
74
+ expect(mediaControl.trigger).toHaveBeenCalledWith(
75
+ ExtendedEvents.MEDIACONTROL_MENU_COLLAPSE,
76
+ 'cc',
77
+ )
78
+ })
79
+ })
80
+ describe('when clicked twice', () => {
81
+ beforeEach(() => {
82
+ cc.$el.find('#cc-button').click().click()
83
+ })
84
+ it('should collapse the menu', () => {
85
+ expect(cc.$el.find('#cc-select').css('display')).toBe('none')
86
+ })
87
+ })
88
+ describe('when media control is hidden', () => {
89
+ beforeEach(() => {
90
+ cc.$el.find('#cc-button').click()
91
+ mediaControl.trigger(Events.MEDIACONTROL_HIDE)
92
+ })
93
+ it('should hide menu', () => {
94
+ expect(cc.$el.find('#cc-select').css('display')).toBe('none')
95
+ })
96
+ })
58
97
  })
59
- })
98
+ })
@@ -5,21 +5,21 @@ exports[`ClosedCaptions > basically > should render 1`] = `
5
5
  <span class="cc-text">/assets/icons/new/subtitles-off.svg</span>
6
6
  </button>
7
7
 
8
- <ul class="gcore-skin-bg-color" id="cc-select">
8
+ <ul class="gcore-skin-bg-color" id="cc-select" style="display: none;">
9
9
 
10
- <li>
10
+ <li class="">
11
11
  <a href="#" class="gcore-skin-text-color" data-cc-select="1">
12
12
  English
13
13
  </a>
14
14
  </li>
15
15
 
16
- <li>
16
+ <li class="">
17
17
  <a href="#" class="gcore-skin-text-color" data-cc-select="2">
18
18
  Spanish
19
19
  </a>
20
20
  </li>
21
21
 
22
- <li class="current"><a href="#" class="gcore-skin-text-color gcore-skin-active" data-cc-select="-1">Off</a></li>
22
+ <li class="current"><a href="#" class="gcore-skin-text-color gcore-skin-active" data-cc-select="-1">off</a></li>
23
23
  </ul>
24
24
  "
25
25
  `;
package/src/testUtils.ts CHANGED
@@ -194,6 +194,7 @@ export function createMockMediaControl(core: any) {
194
194
  mediaControl.mount = vi.fn()
195
195
  // @ts-ignore
196
196
  mediaControl.toggleElement = vi.fn()
197
+ vi.spyOn(mediaControl, 'trigger')
197
198
  return mediaControl
198
199
  }
199
200