@gcorevideo/player 2.20.22 → 2.21.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.
Files changed (76) hide show
  1. package/assets/audio-selector/style.scss +48 -82
  2. package/assets/audio-selector/track-selector.ejs +3 -3
  3. package/assets/bottom-gear/bottomgear.ejs +10 -12
  4. package/assets/bottom-gear/gear-sub-menu.scss +0 -15
  5. package/assets/bottom-gear/gear.scss +3 -32
  6. package/assets/media-control/media-control.ejs +5 -20
  7. package/assets/media-control/media-control.scss +124 -34
  8. package/assets/media-control/width370.scss +32 -104
  9. package/assets/picture-in-picture/button.ejs +1 -1
  10. package/assets/picture-in-picture/button.scss +5 -4
  11. package/dist/core.js +148 -23
  12. package/dist/index.css +530 -616
  13. package/dist/index.js +284 -282
  14. package/dist/player.d.ts +19 -16
  15. package/dist/plugins/index.css +1009 -1095
  16. package/dist/plugins/index.js +709 -23402
  17. package/docs/api/player.audioselector.md +4 -59
  18. package/docs/api/player.md +1 -1
  19. package/docs/api/player.mediacontrol.getelement.md +5 -0
  20. package/docs/api/player.mediacontrol.md +14 -0
  21. package/docs/api/{player.audioselector.updatecurrenttrack.md → player.mediacontrol.putelement.md} +7 -7
  22. package/docs/api/player.mediacontrolelement.md +1 -1
  23. package/docs/api/{player.audioselector.starttrackswitch.md → player.pictureinpicture.attributes.md} +5 -7
  24. package/docs/api/player.pictureinpicture.md +45 -0
  25. package/lib/playback/BasePlayback.d.ts +0 -1
  26. package/lib/playback/BasePlayback.d.ts.map +1 -1
  27. package/lib/playback/BasePlayback.js +0 -1
  28. package/lib/playback/HTML5Video.d.ts +4 -0
  29. package/lib/playback/HTML5Video.d.ts.map +1 -1
  30. package/lib/playback/HTML5Video.js +53 -4
  31. package/lib/playback/dash-playback/DashPlayback.d.ts +5 -0
  32. package/lib/playback/dash-playback/DashPlayback.d.ts.map +1 -1
  33. package/lib/playback/dash-playback/DashPlayback.js +48 -4
  34. package/lib/playback/hls-playback/HlsPlayback.d.ts +31 -25
  35. package/lib/playback/hls-playback/HlsPlayback.d.ts.map +1 -1
  36. package/lib/playback/hls-playback/HlsPlayback.js +47 -14
  37. package/lib/plugins/audio-selector/AudioSelector.d.ts +12 -11
  38. package/lib/plugins/audio-selector/AudioSelector.d.ts.map +1 -1
  39. package/lib/plugins/audio-selector/AudioSelector.js +65 -185
  40. package/lib/plugins/bottom-gear/BottomGear.d.ts +1 -1
  41. package/lib/plugins/bottom-gear/BottomGear.d.ts.map +1 -1
  42. package/lib/plugins/bottom-gear/BottomGear.js +10 -9
  43. package/lib/plugins/level-selector/LevelSelector.js +1 -1
  44. package/lib/plugins/media-control/MediaControl.d.ts +3 -3
  45. package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
  46. package/lib/plugins/media-control/MediaControl.js +17 -9
  47. package/lib/plugins/picture-in-picture/PictureInPicture.d.ts +3 -0
  48. package/lib/plugins/picture-in-picture/PictureInPicture.d.ts.map +1 -1
  49. package/lib/plugins/picture-in-picture/PictureInPicture.js +6 -1
  50. package/lib/plugins/source-controller/SourceController.d.ts.map +1 -1
  51. package/lib/plugins/source-controller/SourceController.js +0 -1
  52. package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.d.ts +0 -2
  53. package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.d.ts.map +1 -1
  54. package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.js +1 -18
  55. package/lib/testUtils.d.ts.map +1 -1
  56. package/lib/testUtils.js +2 -0
  57. package/package.json +1 -1
  58. package/src/playback/BasePlayback.ts +0 -1
  59. package/src/playback/HTML5Video.ts +57 -4
  60. package/src/playback/dash-playback/DashPlayback.ts +64 -6
  61. package/src/playback/hls-playback/HlsPlayback.ts +82 -40
  62. package/src/plugins/audio-selector/AudioSelector.ts +84 -278
  63. package/src/plugins/bottom-gear/BottomGear.ts +11 -10
  64. package/src/plugins/bottom-gear/__tests__/BottomGear.test.ts +1 -3
  65. package/src/plugins/bottom-gear/__tests__/__snapshots__/BottomGear.test.ts.snap +14 -37
  66. package/src/plugins/level-selector/LevelSelector.ts +1 -1
  67. package/src/plugins/media-control/MediaControl.ts +18 -13
  68. package/src/plugins/picture-in-picture/PictureInPicture.ts +7 -1
  69. package/src/plugins/source-controller/SourceController.ts +0 -1
  70. package/src/plugins/spinner-three-bounce/SpinnerThreeBounce.ts +1 -20
  71. package/src/testUtils.ts +2 -0
  72. package/src/typings/globals.d.ts +19 -0
  73. package/temp/player.api.json +102 -143
  74. package/tsconfig.tsbuildinfo +1 -1
  75. package/assets/media-control/plugins.scss +0 -94
  76. package/docs/api/player.audioselector.highlightcurrenttrack.md +0 -18
@@ -1,10 +1,7 @@
1
1
  import { Events, UICorePlugin, template } from '@clappr/core'
2
- import {
3
- AudioTrackLoadedData,
4
- AudioTrackSwitchedData,
5
- AudioTracksUpdatedData,
6
- Events as HlsEvents,
7
- } from 'hls.js'
2
+ import { AudioTrack } from '@clappr/core/types/base/playback/playback.js'
3
+ import { trace } from '@gcorevideo/utils'
4
+ import assert from 'assert'
8
5
 
9
6
  import { CLAPPR_VERSION } from '../../build.js'
10
7
 
@@ -12,48 +9,25 @@ import pluginHtml from '../../../assets/audio-selector/track-selector.ejs'
12
9
  import '../../../assets/audio-selector/style.scss'
13
10
  import audioArrow from '../../../assets/icons/old/quality-arrow.svg'
14
11
  import { ZeptoResult } from '../../types.js'
15
- import assert from 'assert'
16
12
 
17
13
  const VERSION: string = '0.0.1'
18
14
 
19
- // const T = 'plugins.audio_selector';
20
-
21
- const AUTO = 0
22
-
23
- type AudioTrackW3C = {
24
- enabled: boolean
25
- id: string
26
- kind: string
27
- label: string
28
- }
29
-
30
- type AudioTrackItem = {
31
- id: number
32
- label: string
33
- }
34
-
35
- type AudioTrackList = {
36
- length: number
37
- addEventListener(
38
- type: 'change' | 'addtrack' | 'removetrack',
39
- listener: EventListenerOrEventListenerObject,
40
- ): void
41
- getTrackById(id: string): AudioTrackW3C | null
42
- [Symbol.iterator](): IterableIterator<AudioTrackW3C>
43
- }
15
+ const T = 'plugins.audio_selector'
44
16
 
45
17
  /**
46
- * `PLUGIN` that adds an audio track selector to the media control UI.
18
+ * `PLUGIN` that makes possible to switch audio tracks via the media control UI.
47
19
  * @beta
20
+ * @remarks
21
+ * The plugin is activated when there are multiple audio tracks available.
22
+ * The plugin adds a button showing the current audio track and a dropdown to switch to another audio track.
23
+ * Depends on:
24
+ *
25
+ * - {@link MediaControl}
48
26
  */
49
27
  export class AudioSelector extends UICorePlugin {
50
- // TODO
51
-
52
- private selectedTrackId: number | undefined
28
+ private currentTrack: AudioTrack | null = null
53
29
 
54
- private currentTrack: AudioTrackItem | null = null
55
-
56
- private tracks: AudioTrackItem[] = []
30
+ private tracks: AudioTrack[] = []
57
31
 
58
32
  /**
59
33
  * @internal
@@ -83,7 +57,7 @@ export class AudioSelector extends UICorePlugin {
83
57
  */
84
58
  override get attributes() {
85
59
  return {
86
- class: this.name,
60
+ class: 'media-control-audio-tracks',
87
61
  'data-track-selector': '',
88
62
  }
89
63
  }
@@ -102,148 +76,73 @@ export class AudioSelector extends UICorePlugin {
102
76
  * @internal
103
77
  */
104
78
  override bindEvents() {
105
- this.listenTo(this.core, Events.CORE_READY, this.bindPlaybackEvents)
106
- // TODO CORE_ACTIVE_CONTAINER_CHANGED
79
+ this.listenTo(this.core, Events.CORE_READY, this.onCoreReady)
107
80
  this.listenTo(
108
- this.core.mediaControl,
109
- Events.MEDIACONTROL_CONTAINERCHANGED,
110
- this.reload,
111
- )
112
- this.listenTo(
113
- this.core.mediaControl,
114
- Events.MEDIACONTROL_RENDERED,
115
- this.render,
81
+ this.core,
82
+ Events.CORE_ACTIVE_CONTAINER_CHANGED,
83
+ this.onActiveContainerChanged,
116
84
  )
85
+ }
86
+
87
+ private onCoreReady() {
88
+ trace(`${T} onCoreReady`)
89
+ const mediaControl = this.core.getPlugin('media_control')
90
+ assert(mediaControl, 'media_control plugin is required')
91
+ this.listenTo(mediaControl, Events.MEDIACONTROL_RENDERED, this.render)
117
92
  this.listenTo(
118
- this.core.mediaControl,
93
+ mediaControl,
119
94
  Events.MEDIACONTROL_HIDE,
120
95
  this.hideSelectTrackMenu,
121
96
  )
122
97
  }
123
98
 
124
- private unBindEvents() {
125
- // @ts-ignore
126
- this.stopListening(this.core, Events.CORE_READY)
127
- // @ts-ignore
128
- this.stopListening(
129
- this.core.mediaControl,
130
- Events.MEDIACONTROL_CONTAINERCHANGED,
131
- )
132
- // @ts-ignore
133
- this.stopListening(this.core.mediaControl, Events.MEDIACONTROL_RENDERED)
134
- // @ts-ignore
135
- this.stopListening(this.core.mediaControl, Events.MEDIACONTROL_HIDE)
136
- }
137
-
138
99
  private bindPlaybackEvents() {
139
- // this.currentTrack = {};
140
- // this.removeAuto = false;
141
- this.selectedTrackId = undefined
142
- const currentPlayback = this.core.activePlayback
143
-
144
- this.listenTo(currentPlayback, Events.PLAYBACK_STOP, this.onStop)
100
+ trace(`${T} bindPlaybackEvents`)
101
+ this.currentTrack = null
102
+ this.listenTo(this.core.activePlayback, Events.PLAYBACK_STOP, this.onStop)
145
103
  this.setupAudioTrackListeners()
146
104
  }
147
105
 
148
106
  private setupAudioTrackListeners() {
149
- const currentPlayback = this.core.activePlayback
150
-
151
- // TODO no-crutch:currentPlayback._hls
152
- if (currentPlayback._hls) {
153
- // TODO AUDIO_TRACKS_UPDATED
154
- // currentPlayback._hls.on('hlsAudioTracksUpdated', (e, data) => {
155
- currentPlayback._hls.on(
156
- HlsEvents.AUDIO_TRACKS_UPDATED,
157
- (e: HlsEvents.AUDIO_TRACKS_UPDATED, data: AudioTracksUpdatedData) => {
158
- // let id = -1;
159
- // for (const audioTrack of data.audioTracks) {
160
- // if (audioTrack.default) {
161
- // id = audioTrack.id;
162
- // this.currentTrack = audioTrack;
163
- // }
164
- // }
165
- const defaultTrack = data.audioTracks.find((track) => track.default)
166
- if (defaultTrack) {
167
- this.currentTrack = {
168
- id: defaultTrack.id,
169
- label: defaultTrack.name,
170
- }
171
- }
172
- this.fillTracks(
173
- data.audioTracks.map((p) => ({
174
- id: p.id,
175
- label: p.name,
176
- })),
177
- defaultTrack?.id,
178
- )
179
- },
180
- )
181
- currentPlayback._hls.on(
182
- HlsEvents.AUDIO_TRACK_SWITCHING,
183
- this.startTrackSwitch.bind(this),
184
- )
185
- currentPlayback._hls.on(
186
- HlsEvents.AUDIO_TRACK_SWITCHED,
187
- this.updateCurrentTrack.bind(this),
188
- )
189
- currentPlayback._hls.on(
190
- HlsEvents.AUDIO_TRACK_LOADED,
191
- this.updateCurrentTrack.bind(this),
192
- )
193
- } else {
194
- this.listenToOnce(currentPlayback, Events.PLAYBACK_PLAY, () => {
195
- const mediaElement = currentPlayback.$el.get(0)
196
- // const { audioTracks } = currentPlayback.$el.get(0);
197
- const audioTracks: AudioTrackList = mediaElement.audioTracks
198
-
199
- if (audioTracks && audioTracks.length) {
200
- let index = 0
201
- const trackItems: AudioTrackItem[] = []
202
- for (const audioTrack of audioTracks) {
203
- if (audioTrack.enabled) {
204
- const t = {
205
- id: index,
206
- label: audioTrack.label,
207
- }
208
- this.currentTrack = t
209
- trackItems.push(t)
210
- index++
211
- }
212
- }
213
-
214
- audioTracks.addEventListener('change', () =>
215
- this.updateCurrentTrackW3C(),
216
- )
217
-
218
- this.fillTracks(trackItems, trackItems[0].id)
219
- }
220
- })
221
- }
107
+ this.listenTo(
108
+ this.core.activePlayback,
109
+ Events.PLAYBACK_AUDIO_AVAILABLE,
110
+ (tracks: AudioTrack[]) => {
111
+ trace(`${T} on PLAYBACK_AUDIO_AVAILABLE`, { audioTracks: tracks })
112
+ this.currentTrack =
113
+ tracks.find((track) => track.kind === 'main') ?? null
114
+ this.fillTracks(tracks)
115
+ },
116
+ )
117
+
118
+ this.listenTo(
119
+ this.core.activePlayback,
120
+ Events.PLAYBACK_AUDIO_CHANGED,
121
+ (track: AudioTrack) => {
122
+ trace(`${T} PLAYBACK_AUDIO_CHANGED`, { audioTrack: track })
123
+ this.currentTrack = track
124
+ this.highlightCurrentTrack()
125
+ this.buttonElement().removeClass('changing')
126
+ this.updateText()
127
+ },
128
+ )
222
129
  }
223
130
 
224
- private onStop() {}
131
+ private onStop() {
132
+ trace(`${T} onStop`)
133
+ }
225
134
 
226
- private reload() {
227
- this.unBindEvents()
228
- this.bindEvents()
135
+ private onActiveContainerChanged() {
136
+ trace(`${T} onActiveContainerChanged`)
229
137
  this.bindPlaybackEvents()
230
138
  }
231
139
 
232
140
  private shouldRender() {
233
- if (!this.core.activeContainer) {
234
- return false
235
- }
236
-
237
- const currentPlayback = this.core.activePlayback
238
-
239
- if (!currentPlayback) {
141
+ if (!this.core.activePlayback) {
240
142
  return false
241
143
  }
242
144
 
243
- const { audioTracks } =
244
- currentPlayback.activePlayback._hls || currentPlayback.$el.get(0)
245
-
246
- this.tracks = audioTracks
145
+ this.tracks = this.core.activePlayback.audioTracks
247
146
 
248
147
  // Only care if we have at least 2 to choose from
249
148
  return this.tracks && this.tracks.length > 1
@@ -258,76 +157,41 @@ export class AudioSelector extends UICorePlugin {
258
157
  }
259
158
 
260
159
  const mediaControl = this.core.getPlugin('media_control')
261
- assert(mediaControl, 'media_control plugin is required')
262
160
  this.$el.html(
263
161
  AudioSelector.template({ tracks: this.tracks, title: this.getTitle() }),
264
162
  )
163
+ this.$('.audio-arrow').append(audioArrow)
164
+ mediaControl.putElement('audioTracksSelector', this.$el)
265
165
 
266
- const ats = mediaControl.getElement('audioTracksSelector')
267
- if (!(ats && ats.length > 0)) {
268
- return this
269
- }
270
- ats.append(this.el)
271
-
166
+ this.updateText()
272
167
  this.highlightCurrentTrack()
273
168
 
274
- const aa = ats.find('audioArrow')
275
- if (aa.length > 0) {
276
- aa.append(audioArrow)
277
- }
278
-
279
169
  return this
280
170
  }
281
171
 
282
- private fillTracks(tracks: AudioTrackItem[], selected = AUTO) {
283
- if (this.selectedTrackId === undefined) {
284
- this.selectedTrackId = selected
285
- }
286
- // this.tracks = levels.audioTracks;
287
- // for (let i = 0; i < this.tracks.length; i++) {
288
- // if (this.tracks[i].name && !this.tracks[i].label) {
289
- // this.tracks[i].label = this.tracks[i].name;
290
- // }
291
- // }
172
+ private fillTracks(tracks: AudioTrack[]) {
292
173
  this.tracks = tracks
293
-
294
- // Player.player.trigger('tracks', this.tracks);
295
- // this.core.trigger('tracks', this.tracks);
296
174
  this.render()
297
175
  }
298
176
 
299
- private findTrackBy(id: number) {
177
+ private findTrackBy(id: string) {
300
178
  return this.tracks.find((track) => track.id === id)
301
179
  }
302
180
 
303
181
  private onTrackSelect(event: MouseEvent) {
304
- // this.selectedTrackId = parseInt(event.target.dataset.levelSelectorSelect, 10)
305
182
  const id = (event.target as HTMLElement)?.dataset?.trackSelectorSelect
306
183
  if (id) {
307
- this.setIndexTrack(Number(id))
184
+ this.selectAudioTrack(id)
308
185
  }
309
186
  this.toggleContextMenu()
310
187
  event.stopPropagation()
311
188
  return false
312
189
  }
313
190
 
314
- private setIndexTrack(index: number) {
315
- this.selectedTrackId = index
316
- if (this.core.activePlayback._hls) {
317
- if (
318
- this.core.activePlayback._hls.audioTrack.id === this.selectedTrackId
319
- ) {
320
- return
321
- }
322
- this.core.activePlayback._hls.audioTrack = this.selectedTrackId
323
- } else {
324
- const { audioTracks } = this.core.activePlayback.$el.get(0)
325
-
326
- for (const track of audioTracks) {
327
- track.enabled = track.id === this.selectedTrackId
328
- }
329
- }
330
- this.updateText(this.selectedTrackId)
191
+ private selectAudioTrack(id: string) {
192
+ this.startTrackSwitch()
193
+ this.core.activePlayback.switchAudioTrack(id)
194
+ this.updateText()
331
195
  }
332
196
 
333
197
  private onShowLevelSelectMenu() {
@@ -335,112 +199,54 @@ export class AudioSelector extends UICorePlugin {
335
199
  }
336
200
 
337
201
  private hideSelectTrackMenu() {
338
- ;(this.$('.audio_selector ul') as ZeptoResult).hide()
202
+ ;(this.$('ul') as ZeptoResult).hide()
339
203
  }
340
204
 
341
205
  private toggleContextMenu() {
342
- ;(this.$('.audio_selector ul') as ZeptoResult).toggle()
206
+ ;(this.$('ul') as ZeptoResult).toggle()
343
207
  }
344
208
 
345
209
  private buttonElement(): ZeptoResult {
346
- return this.$('.audio_selector button')
210
+ return this.$('button')
347
211
  }
348
212
 
349
213
  private buttonElementText(): ZeptoResult {
350
- return this.$('.audio_selector button .audio-text')
214
+ return this.$('button .audio-text')
351
215
  }
352
216
 
353
- private trackElement(id?: number): ZeptoResult {
217
+ private trackElement(id?: string): ZeptoResult {
354
218
  return (
355
219
  this.$(
356
- '.audio_selector ul a' +
220
+ 'ul a' +
357
221
  (id !== undefined ? '[data-track-selector-select="' + id + '"]' : ''),
358
222
  ) as ZeptoResult
359
223
  ).parent()
360
224
  }
361
225
 
362
226
  private getTitle(): string {
363
- if (!this.tracks) {
364
- return ''
365
- }
366
-
367
- const selectedTrackId = this.selectedTrackId || 0
368
-
369
- const selectedTrack = this.tracks[selectedTrackId]
370
-
371
- return selectedTrack?.label || ''
227
+ return this.currentTrack?.label || ''
372
228
  }
373
229
 
374
- startTrackSwitch() {
230
+ private startTrackSwitch() {
375
231
  this.buttonElement().addClass('changing')
376
232
  }
377
233
 
378
- private updateText(trackId: number | undefined) {
379
- if (trackId === undefined) {
234
+ private updateText() {
235
+ if (!this.currentTrack) {
380
236
  return
381
237
  }
382
-
383
- const track = this.findTrackBy(trackId)
384
-
385
- if (track) {
386
- this.buttonElementText().text(track.label)
387
- }
238
+ this.buttonElementText().text(this.currentTrack.label)
388
239
  }
389
240
 
390
- updateCurrentTrack(
391
- e: HlsEvents.AUDIO_TRACK_SWITCHED,
392
- info: AudioTrackSwitchedData | AudioTrackLoadedData,
393
- ) {
394
- // if (!info) {
395
- // const { audioTracks } = this.core.activePlayback.$el.get(0);
396
-
397
- // for (const track of audioTracks) {
398
- // if (track.enabled) {
399
- // info = track;
400
- // }
401
- // }
402
- // }
403
- // if (!info) {
404
- // return;
405
- // }
406
-
407
- // const track = this.findTrackBy(info.id);
408
-
409
- // this.currentTrack = track ? track : null;
410
- // this.selectedTrackId = track?.id;
411
- // this.highlightCurrentTrack();
412
- // this.buttonElement().removeClass('changing');
413
- this.setCurrentTrack(info.id)
414
- }
415
-
416
- private updateCurrentTrackW3C() {
417
- const { audioTracks } = this.core.activePlayback.$el.get(0)
418
- const index = audioTracks.findIndex((track: AudioTrackW3C) => track.enabled)
419
- if (index >= 0) {
420
- this.setCurrentTrack(index)
421
- }
422
- }
423
-
424
- private setCurrentTrack(index: number) {
425
- const track = this.findTrackBy(index)
426
-
427
- this.currentTrack = track ?? null
428
- this.selectedTrackId = index
429
- this.highlightCurrentTrack()
430
- this.buttonElement().removeClass('changing')
431
- }
432
-
433
- highlightCurrentTrack() {
241
+ private highlightCurrentTrack() {
434
242
  this.trackElement().removeClass('current')
435
243
  this.trackElement().find('a').removeClass('gcore-skin-active')
436
244
 
437
245
  if (this.currentTrack) {
438
- const currentTrackElement = this.trackElement(this.currentTrack.id)
439
-
440
- currentTrackElement.addClass('current')
441
- currentTrackElement.find('a').addClass('gcore-skin-active')
246
+ this.trackElement(this.currentTrack.id)
247
+ .addClass('current')
248
+ .find('a')
249
+ .addClass('gcore-skin-active')
442
250
  }
443
-
444
- this.updateText(this.selectedTrackId)
445
251
  }
446
252
  }
@@ -63,8 +63,7 @@ export class BottomGear extends UICorePlugin {
63
63
  */
64
64
  override get attributes() {
65
65
  return {
66
- 'class': this.name,
67
- 'data-track-selector': ''
66
+ 'class': 'media-control-gear',
68
67
  };
69
68
  }
70
69
 
@@ -81,12 +80,8 @@ export class BottomGear extends UICorePlugin {
81
80
  * @internal
82
81
  */
83
82
  override bindEvents() {
84
- const mediaControl = this.core.getPlugin('media_control');
85
- assert(mediaControl, 'media_control plugin is required');
86
-
83
+ this.listenTo(this.core, ClapprEvents.CORE_READY, this.onCoreReady)
87
84
  this.listenTo(this.core, ClapprEvents.CORE_ACTIVE_CONTAINER_CHANGED, this.onActiveContainerChanged);
88
- this.listenTo(mediaControl, ClapprEvents.MEDIACONTROL_RENDERED, this.render);
89
- this.listenTo(mediaControl, ClapprEvents.MEDIACONTROL_HIDE, this.hide); // TODO mediacontrol show as well
90
85
  }
91
86
 
92
87
  /**
@@ -94,7 +89,7 @@ export class BottomGear extends UICorePlugin {
94
89
  * @returns Zepto result of the element
95
90
  */
96
91
  getElement(name: GearItemElement): ZeptoResult | null {
97
- return this.core.getPlugin('media_control')?.getElement('gear')?.find(`.gear-options-list [data-${name}]`);
92
+ return this.$el.find(`.gear-options-list [data-${name}]`);
98
93
  }
99
94
 
100
95
  /**
@@ -126,7 +121,6 @@ export class BottomGear extends UICorePlugin {
126
121
  */
127
122
  override render() {
128
123
  const mediaControl = this.core.getPlugin('media_control');
129
- assert(mediaControl, 'media_control plugin is required');
130
124
 
131
125
  // TODO use options.mediaControl.gear.items
132
126
  const items: GearItemElement[] = [
@@ -137,7 +131,7 @@ export class BottomGear extends UICorePlugin {
137
131
  const icon = this.isHd ? gearHdIcon : gearIcon;
138
132
  this.$el.html(BottomGear.template({ icon, items }));
139
133
 
140
- mediaControl.getElement('gear')?.html(this.el);
134
+ mediaControl.putElement('gear', this.$el);
141
135
  mediaControl.trigger(MediaControlEvents.MEDIACONTROL_GEAR_RENDERED);
142
136
  return this;
143
137
  }
@@ -159,4 +153,11 @@ export class BottomGear extends UICorePlugin {
159
153
  private hide() {
160
154
  this.$el.find('.gear-wrapper').hide();
161
155
  }
156
+
157
+ private onCoreReady() {
158
+ const mediaControl = this.core.getPlugin('media_control');
159
+ assert(mediaControl, 'media_control plugin is required');
160
+ this.listenTo(mediaControl, ClapprEvents.MEDIACONTROL_RENDERED, this.render);
161
+ this.listenTo(mediaControl, ClapprEvents.MEDIACONTROL_HIDE, this.hide); // TODO mediacontrol show as well
162
+ }
162
163
  }
@@ -26,9 +26,7 @@ describe('BottomGear', () => {
26
26
  expect(bottomGear.el.innerHTML).toMatchSnapshot()
27
27
  })
28
28
  it('should attach to media control', () => {
29
- const gearElement = mediaControl.getElement('gear')
30
- expect(gearElement[0].innerHTML).not.toEqual('')
31
- expect(gearElement[0].innerHTML).toMatchSnapshot()
29
+ expect(mediaControl.putElement).toHaveBeenCalledWith('gear', bottomGear.$el)
32
30
  })
33
31
  it('should emit event', () => {
34
32
  expect(onGearRendered).toHaveBeenCalled()
@@ -1,41 +1,18 @@
1
1
  // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
2
 
3
- exports[`BottomGear > should attach to media control 1`] = `
4
- "<div class="bottom_gear" data-track-selector=""><div class="media-control-gear" data-="">
5
- <button type="button" class="button-gear gplayer-lite-btn gcore-skin-button-color" data-gear-button="-1">
6
- <span class="gear-icon">/assets/icons/new/gear.svg</span>
7
- </button>
8
- <div class="gear-wrapper gcore-skin-bg-color">
9
- <ul class="gear-options-list">
10
-
11
- <li data-quality=""></li>
12
-
13
- <li data-rate=""></li>
14
-
15
- <li data-nerd=""></li>
16
-
17
- </ul>
18
- </div>
19
- </div>
20
- </div>"
21
- `;
22
-
23
3
  exports[`BottomGear > should render 1`] = `
24
- "<div class="media-control-gear" data-="">
25
- <button type="button" class="button-gear gplayer-lite-btn gcore-skin-button-color" data-gear-button="-1">
26
- <span class="gear-icon">/assets/icons/new/gear.svg</span>
27
- </button>
28
- <div class="gear-wrapper gcore-skin-bg-color">
29
- <ul class="gear-options-list">
30
-
31
- <li data-quality=""></li>
32
-
33
- <li data-rate=""></li>
34
-
35
- <li data-nerd=""></li>
36
-
37
- </ul>
38
- </div>
39
- </div>
40
- "
4
+ "<button type="button" class="button-gear media-control-button gplayer-lite-btn gcore-skin-button-color gear-icon" data-gear-button="-1">
5
+ /assets/icons/new/gear.svg
6
+ </button>
7
+ <div class="gear-wrapper gcore-skin-bg-color">
8
+ <ul class="gear-options-list">
9
+
10
+ <li data-quality=""></li>
11
+
12
+ <li data-rate=""></li>
13
+
14
+ <li data-nerd=""></li>
15
+
16
+ </ul>
17
+ </div>"
41
18
  `;
@@ -106,7 +106,7 @@ export class LevelSelector extends UICorePlugin {
106
106
  */
107
107
  override get attributes() {
108
108
  return {
109
- class: this.name,
109
+ class: 'level-selector',
110
110
  'data-level-selector': '',
111
111
  }
112
112
  }