@gcorevideo/player 2.20.22 → 2.21.3

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 (89) 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 -25
  7. package/assets/media-control/media-control.scss +114 -34
  8. package/assets/media-control/width370.scss +35 -109
  9. package/assets/picture-in-picture/button.ejs +1 -1
  10. package/assets/picture-in-picture/button.scss +5 -4
  11. package/assets/subtitles/combobox.ejs +7 -9
  12. package/assets/subtitles/style.scss +8 -15
  13. package/dist/core.js +151 -23
  14. package/dist/index.css +897 -1000
  15. package/dist/index.js +416 -438
  16. package/dist/player.d.ts +19 -16
  17. package/dist/plugins/index.css +1454 -1557
  18. package/dist/plugins/index.js +826 -23550
  19. package/docs/api/player.audioselector.md +4 -59
  20. package/docs/api/player.md +1 -1
  21. package/docs/api/player.mediacontrol.getelement.md +5 -0
  22. package/docs/api/player.mediacontrol.md +14 -0
  23. package/docs/api/{player.audioselector.updatecurrenttrack.md → player.mediacontrol.putelement.md} +7 -7
  24. package/docs/api/player.mediacontrolelement.md +1 -1
  25. package/docs/api/{player.audioselector.starttrackswitch.md → player.pictureinpicture.attributes.md} +5 -7
  26. package/docs/api/player.pictureinpicture.md +45 -0
  27. package/lib/playback/BasePlayback.d.ts +1 -1
  28. package/lib/playback/BasePlayback.d.ts.map +1 -1
  29. package/lib/playback/BasePlayback.js +3 -1
  30. package/lib/playback/HTML5Video.d.ts +4 -0
  31. package/lib/playback/HTML5Video.d.ts.map +1 -1
  32. package/lib/playback/HTML5Video.js +53 -4
  33. package/lib/playback/dash-playback/DashPlayback.d.ts +5 -0
  34. package/lib/playback/dash-playback/DashPlayback.d.ts.map +1 -1
  35. package/lib/playback/dash-playback/DashPlayback.js +48 -4
  36. package/lib/playback/hls-playback/HlsPlayback.d.ts +31 -25
  37. package/lib/playback/hls-playback/HlsPlayback.d.ts.map +1 -1
  38. package/lib/playback/hls-playback/HlsPlayback.js +47 -14
  39. package/lib/playback.types.d.ts +5 -0
  40. package/lib/playback.types.d.ts.map +1 -1
  41. package/lib/plugins/audio-selector/AudioSelector.d.ts +12 -11
  42. package/lib/plugins/audio-selector/AudioSelector.d.ts.map +1 -1
  43. package/lib/plugins/audio-selector/AudioSelector.js +65 -185
  44. package/lib/plugins/bottom-gear/BottomGear.d.ts +2 -2
  45. package/lib/plugins/bottom-gear/BottomGear.d.ts.map +1 -1
  46. package/lib/plugins/bottom-gear/BottomGear.js +12 -10
  47. package/lib/plugins/level-selector/LevelSelector.js +1 -1
  48. package/lib/plugins/media-control/MediaControl.d.ts +3 -4
  49. package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
  50. package/lib/plugins/media-control/MediaControl.js +23 -13
  51. package/lib/plugins/picture-in-picture/PictureInPicture.d.ts +3 -0
  52. package/lib/plugins/picture-in-picture/PictureInPicture.d.ts.map +1 -1
  53. package/lib/plugins/picture-in-picture/PictureInPicture.js +6 -1
  54. package/lib/plugins/playback-rate/PlaybackRate.d.ts +1 -0
  55. package/lib/plugins/playback-rate/PlaybackRate.d.ts.map +1 -1
  56. package/lib/plugins/playback-rate/PlaybackRate.js +1 -0
  57. package/lib/plugins/source-controller/SourceController.d.ts.map +1 -1
  58. package/lib/plugins/source-controller/SourceController.js +0 -1
  59. package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.d.ts +0 -2
  60. package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.d.ts.map +1 -1
  61. package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.js +1 -18
  62. package/lib/plugins/subtitles/Subtitles.d.ts +21 -19
  63. package/lib/plugins/subtitles/Subtitles.d.ts.map +1 -1
  64. package/lib/plugins/subtitles/Subtitles.js +121 -151
  65. package/lib/testUtils.d.ts.map +1 -1
  66. package/lib/testUtils.js +2 -0
  67. package/package.json +1 -1
  68. package/src/playback/BasePlayback.ts +4 -1
  69. package/src/playback/HTML5Video.ts +57 -4
  70. package/src/playback/dash-playback/DashPlayback.ts +64 -6
  71. package/src/playback/hls-playback/HlsPlayback.ts +82 -40
  72. package/src/playback.types.ts +6 -0
  73. package/src/plugins/audio-selector/AudioSelector.ts +84 -278
  74. package/src/plugins/bottom-gear/BottomGear.ts +14 -11
  75. package/src/plugins/bottom-gear/__tests__/BottomGear.test.ts +1 -3
  76. package/src/plugins/bottom-gear/__tests__/__snapshots__/BottomGear.test.ts.snap +14 -37
  77. package/src/plugins/level-selector/LevelSelector.ts +1 -1
  78. package/src/plugins/media-control/MediaControl.ts +54 -32
  79. package/src/plugins/picture-in-picture/PictureInPicture.ts +7 -1
  80. package/src/plugins/playback-rate/PlaybackRate.ts +1 -0
  81. package/src/plugins/source-controller/SourceController.ts +0 -1
  82. package/src/plugins/spinner-three-bounce/SpinnerThreeBounce.ts +1 -20
  83. package/src/plugins/subtitles/Subtitles.ts +144 -179
  84. package/src/testUtils.ts +2 -0
  85. package/src/typings/globals.d.ts +19 -0
  86. package/temp/player.api.json +102 -143
  87. package/tsconfig.tsbuildinfo +1 -1
  88. package/assets/media-control/plugins.scss +0 -94
  89. package/docs/api/player.audioselector.highlightcurrenttrack.md +0 -18
@@ -1,14 +1,9 @@
1
- import {
2
- Events,
3
- UICorePlugin,
4
- Browser,
5
- template,
6
- $,
7
- } from '@clappr/core'
1
+ import { Events, UICorePlugin, Browser, template, $ } from '@clappr/core'
8
2
  import { reportError, trace } from '@gcorevideo/utils'
9
3
  import assert from 'assert'
10
4
 
11
5
  import { CLAPPR_VERSION } from '../../build.js'
6
+ import type { TextTrackItem } from '../../playback.types.js'
12
7
 
13
8
  import '../../../assets/subtitles/style.scss'
14
9
  import subtitlesOffIcon from '../../../assets/icons/new/subtitles-off.svg'
@@ -21,18 +16,17 @@ import type { ZeptoResult } from '../../types.js'
21
16
 
22
17
  const VERSION: string = '2.19.14'
23
18
 
24
- const LOCAL_STORAGE_SUBTITLES_ID =
25
- 'gplayer.plugins.subtitles.selected'
19
+ const LOCAL_STORAGE_SUBTITLES_ID = 'gplayer.plugins.subtitles.selected'
26
20
 
27
21
  const T = 'plugins.subtitles'
28
22
 
29
- type TextTrackInfo = {
30
- language: string
31
- mode?: 'showing' | 'hidden' | 'disabled'
23
+ export type SubtitlesPluginSettings = {
24
+ /**
25
+ * Initially selected subtitles language
26
+ */
27
+ language?: string
32
28
  }
33
29
 
34
- const NO_TRACK = { language: 'off' }
35
-
36
30
  /**
37
31
  * `PLUGIN` that provides a UI to select the subtitles when available.
38
32
  * @beta
@@ -42,10 +36,7 @@ const NO_TRACK = { language: 'off' }
42
36
  *
43
37
  * - {@link MediaControl}
44
38
  *
45
- * Configuration options:
46
- *
47
- * - subtitles.language - The language of the subtitles to select by default.
48
- *
39
+ * Configuration options - {@link SubtitlesPluginSettings}
49
40
  * @example
50
41
  * ```ts
51
42
  * import { Subtitles } from '@gcorevideo/player'
@@ -61,15 +52,13 @@ const NO_TRACK = { language: 'off' }
61
52
  * ```
62
53
  */
63
54
  export class Subtitles extends UICorePlugin {
64
- private currentLevel: TextTrackInfo | null = null
65
-
66
55
  private isPreselectedApplied = false
67
56
 
68
57
  private isShowing = false
69
58
 
70
- private track: TextTrackInfo = { ...NO_TRACK }
59
+ private track: TextTrackItem | null = null
71
60
 
72
- private tracks: TextTrackList | null = null
61
+ private tracks: TextTrackItem[] = []
73
62
 
74
63
  private $string: ZeptoResult | null = null
75
64
 
@@ -103,7 +92,7 @@ export class Subtitles extends UICorePlugin {
103
92
  */
104
93
  override get attributes() {
105
94
  return {
106
- class: this.name,
95
+ class: 'media-control-subtitles',
107
96
  'data-subtitles': '',
108
97
  }
109
98
  }
@@ -113,51 +102,62 @@ export class Subtitles extends UICorePlugin {
113
102
  */
114
103
  override get events() {
115
104
  return {
116
- 'click [data-subtitles-select]': 'onLevelSelect',
117
- 'click [data-subtitles-button]': 'onShowLevelSelectMenu',
105
+ 'click [data-subtitles-select]': 'onItemSelect',
106
+ 'click [data-subtitles-button]': 'toggleMenu',
118
107
  }
119
108
  }
120
109
 
121
110
  private get preselectedLanguage(): string {
122
- return this.core.options.subtitles?.language ?? 'off'
111
+ return this.core.options.subtitles?.language ?? ''
123
112
  }
124
113
 
125
114
  /**
126
115
  * @internal
127
116
  */
128
117
  override bindEvents() {
129
- const mediaControl = this.core.getPlugin('media_control')
130
- assert(mediaControl, 'media_control plugin is required')
118
+ this.listenTo(this.core, Events.CORE_READY, this.onCoreReady)
131
119
  this.listenTo(this.core, Events.CORE_RESIZE, this.playerResize)
132
120
  this.listenTo(
133
121
  this.core,
134
122
  Events.CORE_ACTIVE_CONTAINER_CHANGED,
135
- this.bindPlaybackEvents,
123
+ this.onContainerChanged,
136
124
  )
125
+ }
126
+
127
+ private onCoreReady() {
128
+ trace(`${T} onCoreReady`)
129
+ const mediaControl = this.core.getPlugin('media_control')
130
+ assert(mediaControl, 'media_control plugin is required')
137
131
  this.listenTo(mediaControl, Events.MEDIACONTROL_RENDERED, this.render)
138
132
  this.listenTo(
139
133
  mediaControl,
140
134
  Events.MEDIACONTROL_HIDE,
141
- this.hideSelectLevelMenu,
135
+ this.hideMenu,
142
136
  )
143
137
  }
144
138
 
145
- private bindPlaybackEvents() {
139
+ private onContainerChanged() {
140
+ trace(`${T} onContainerChanged`)
146
141
  this.listenTo(
147
142
  this.core.activeContainer,
148
143
  Events.CONTAINER_FULLSCREEN,
149
144
  this.playerResize,
150
145
  )
151
- this.listenToOnce(
152
- this.core.activePlayback,
153
- Events.PLAYBACK_PLAY,
154
- this.getTracks,
155
- )
156
146
  this.listenTo(
157
147
  this.core.activeContainer,
158
148
  'container:advertisement:start',
159
149
  this.onStartAd,
160
150
  )
151
+ this.listenTo(
152
+ this.core.activePlayback,
153
+ Events.PLAYBACK_SUBTITLE_AVAILABLE,
154
+ this.onSubtitleAvailable,
155
+ )
156
+ this.listenTo(
157
+ this.core.activePlayback,
158
+ Events.PLAYBACK_SUBTITLE_CHANGED,
159
+ this.onSubtitleChanged,
160
+ )
161
161
 
162
162
  // fix for iOS
163
163
  const video = this.core.activePlayback.el
@@ -176,20 +176,52 @@ export class Subtitles extends UICorePlugin {
176
176
  })
177
177
  }
178
178
 
179
- private getTracks() {
180
- if (this.core.activePlayback) {
181
- try {
182
- const tracks = (this.core.activePlayback.el as HTMLMediaElement)
183
- .textTracks
184
- if (tracks.length > 0) {
185
- this.setTracks(tracks)
179
+ private onSubtitleAvailable() {
180
+ trace(`${T} onSubtitleAvailable`)
181
+ this.applyTracks()
182
+ }
183
+
184
+ private onSubtitleChanged({ id }: { id: number }) {
185
+ trace(`${T} onSubtitleChanged`, { id })
186
+ if (id === -1) {
187
+ this.clearSubtitleText()
188
+ }
189
+ for (const track of this.tracks) {
190
+ if (track.id === id) {
191
+ track.track.mode = 'showing'
192
+
193
+ this.setSubtitleText(this.getSubtitleText(track.track))
194
+
195
+ track.track.oncuechange = (e) => {
196
+ try {
197
+ if (track.track.activeCues?.length) {
198
+ const html = (track.track.activeCues[0] as VTTCue).getCueAsHTML()
199
+
200
+ this.setSubtitleText(html)
201
+ } else {
202
+ this.clearSubtitleText()
203
+ }
204
+ } catch (error) {
205
+ reportError(error)
206
+ }
186
207
  }
187
- } catch (error) {
188
- reportError(error)
208
+ } else {
209
+ track.track.oncuechange = null
210
+ track.track.mode = 'hidden'
189
211
  }
190
212
  }
191
213
  }
192
214
 
215
+ private applyTracks() {
216
+ try {
217
+ this.tracks = this.core.activePlayback.closedCaptionsTracks
218
+ this.applyPreselectedSubtitles()
219
+ this.render()
220
+ } catch (error) {
221
+ reportError(error)
222
+ }
223
+ }
224
+
193
225
  private onStartAd() {
194
226
  if (this.isShowing && this.core.activeContainer) {
195
227
  this.hide()
@@ -211,11 +243,12 @@ export class Subtitles extends UICorePlugin {
211
243
  }
212
244
 
213
245
  private playerResize() {
246
+ trace(`${T} playerResize`)
214
247
  const shouldShow =
215
248
  this.core.activeContainer &&
216
249
  isFullscreen(this.core.activeContainer.el) &&
217
- this.currentLevel &&
218
- this.currentLevel.mode &&
250
+ this.track &&
251
+ this.track.track.mode &&
219
252
  Browser.isiOS &&
220
253
  this.isShowing
221
254
 
@@ -239,7 +272,7 @@ export class Subtitles extends UICorePlugin {
239
272
  this.$string.hide()
240
273
  if (this.tracks) {
241
274
  for (const t of this.tracks) {
242
- t.mode = 'hidden'
275
+ t.track.mode = 'hidden'
243
276
  }
244
277
  }
245
278
  }
@@ -253,26 +286,22 @@ export class Subtitles extends UICorePlugin {
253
286
  if (
254
287
  this.core.activeContainer &&
255
288
  isFullscreen(this.core.activeContainer.el) &&
256
- this.currentLevel &&
257
- this.currentLevel.mode &&
289
+ this.track &&
290
+ this.track.track.mode &&
258
291
  Browser.isiOS
259
292
  ) {
260
293
  this.$string.hide()
261
- this.currentLevel.mode = 'showing'
294
+ this.track.track.mode = 'showing'
262
295
  } else {
263
296
  this.$string.show()
264
297
  }
265
298
  }
266
299
 
267
300
  private shouldRender() {
268
- return !!(this.tracks && this.tracks.length > 0)
301
+ return this.tracks.length > 0
269
302
  }
270
303
 
271
304
  private resizeFont() {
272
- if (!this.core.activeContainer) {
273
- return
274
- }
275
-
276
305
  if (!this.$string) {
277
306
  return
278
307
  }
@@ -294,71 +323,42 @@ export class Subtitles extends UICorePlugin {
294
323
  return this
295
324
  }
296
325
 
297
- trace(`${T} render`, {
298
- tracks: this.tracks?.length,
299
- track: this.track?.language,
300
- })
301
-
302
326
  const mediaControl = this.core.getPlugin('media_control')
303
- assert(mediaControl, 'media_control plugin is required')
304
327
 
305
328
  this.$el.html(Subtitles.template({ tracks: this.tracks }))
306
329
  this.core.activeContainer.$el.find('.subtitle-string').remove()
307
330
  this.$string = $(Subtitles.templateString())
308
331
  this.resizeFont()
309
332
 
310
- this.core.activeContainer.$el.append(this.$string[0])
311
- const ss = mediaControl.getElement('subtitlesSelector')
312
- if (ss && ss.length > 0) {
313
- ss.append(this.el)
314
- } else {
315
- mediaControl.getRightPanel().append(this.el)
316
- }
317
-
318
- this.updateCurrentLevel(this.track)
319
- this.highlightCurrentSubtitles()
333
+ this.core.activeContainer.$el.append(this.$string)
334
+ mediaControl.putElement('subtitlesSelector', this.$el)
320
335
 
321
- this.applyPreselectedSubtitles()
336
+ this.updateSelection()
322
337
 
323
338
  this.renderIcon()
324
339
 
325
340
  return this
326
341
  }
327
342
 
328
- private setTracks(tracks: TextTrackList) {
329
- this.tracks = tracks
330
- this.render()
343
+ private findById(id: number) {
344
+ return this.tracks.find((track) => track.id === id) ?? null
331
345
  }
332
346
 
333
- private findLevelBy(id: string) {
334
- if (this.tracks) {
335
- for (const track of this.tracks) {
336
- if (track.language === id) {
337
- return track // TODO TrackInfo?
338
- }
339
- }
340
- }
341
- }
342
-
343
- private selectLevel(id: string) {
347
+ private selectItem(item: TextTrackItem | null) {
344
348
  this.clearSubtitleText()
345
- this.track = this.findLevelBy(id) || { ...NO_TRACK }
346
-
347
- this.hideSelectLevelMenu()
348
- if (!this.track) {
349
- this.track = { language: 'off' }
350
- }
349
+ this.track = item
351
350
 
352
- this.updateCurrentLevel(this.track)
351
+ this.hideMenu()
352
+ this.updateSelection()
353
353
  }
354
354
 
355
- private onLevelSelect(event: MouseEvent) {
356
- const id = (event.target as HTMLElement).dataset.subtitlesSelect
355
+ private onItemSelect(event: MouseEvent) {
356
+ const id = (event.target as HTMLElement).dataset.subtitlesSelect ?? '-1'
357
357
 
358
- if (id) {
359
- localStorage.setItem(LOCAL_STORAGE_SUBTITLES_ID, id)
360
- this.selectLevel(id)
361
- }
358
+ trace(`${T} onItemSelect`, { id })
359
+
360
+ localStorage.setItem(LOCAL_STORAGE_SUBTITLES_ID, id)
361
+ this.selectItem(this.findById(Number(id)))
362
362
 
363
363
  return false
364
364
  }
@@ -366,91 +366,57 @@ export class Subtitles extends UICorePlugin {
366
366
  private applyPreselectedSubtitles() {
367
367
  if (!this.isPreselectedApplied) {
368
368
  this.isPreselectedApplied = true
369
+ if (!this.preselectedLanguage) {
370
+ return
371
+ }
369
372
  setTimeout(() => {
370
- this.selectLevel(this.preselectedLanguage)
371
- }, 300)
373
+ this.selectItem(
374
+ this.tracks.find(
375
+ (t) => t.track.language === this.preselectedLanguage,
376
+ ) ?? null,
377
+ )
378
+ }, 300) // TODO why delay?
372
379
  }
373
380
  }
374
381
 
375
- private onShowLevelSelectMenu() {
376
- trace(`${T} onShowLevelSelectMenu`)
377
- this.toggleContextMenu()
378
- }
379
-
380
- private hideSelectLevelMenu() {
382
+ private hideMenu() {
381
383
  ;(this.$('[data-subtitles] ul') as ZeptoResult).hide()
382
384
  }
383
385
 
384
- private toggleContextMenu() {
385
- (this.$('[data-subtitles] ul') as ZeptoResult).toggle()
386
- }
387
-
388
- private buttonElement(): ZeptoResult {
389
- return this.$('[data-subtitles] button')
386
+ private toggleMenu() {
387
+ ;(this.$('[data-subtitles] ul') as ZeptoResult).toggle()
390
388
  }
391
389
 
392
- private levelElement(id?: string): ZeptoResult {
390
+ private itemElement(id: number): ZeptoResult {
393
391
  return (
394
- this.$(
395
- '[data-subtitles] ul a' + (id ? '[data-subtitles-select="' + id + '"]' : ''),
396
- ) as ZeptoResult
392
+ this.$(`ul li a[data-subtitles-select="${id}"]`) as ZeptoResult
397
393
  ).parent()
398
394
  }
399
395
 
400
- private startLevelSwitch() {
401
- this.buttonElement().addClass('changing')
402
- }
403
-
404
- private stopLevelSwitch() {
405
- this.buttonElement().removeClass('changing')
396
+ private allItemElements(): ZeptoResult {
397
+ return this.$('[data-subtitles] li')
406
398
  }
407
399
 
408
400
  private selectSubtitles() {
409
- if (!this.currentLevel) {
410
- return
411
- }
401
+ const trackId = this.track ? this.track.id : -1
412
402
 
413
- if (this.tracks) {
414
- for (let i = 0; i < this.tracks.length; i++) {
415
- const track = this.tracks[i]
416
- if (track.language === this.currentLevel.language) {
417
- track.mode = 'showing'
418
-
419
- const currentTime = this.core.activePlayback?.getCurrentTime() ?? 0
420
- const cues = track.cues
421
- let subtitleText = ''
422
-
423
- if (cues && cues.length) {
424
- for (const cue of cues) {
425
- if (currentTime >= cue.startTime && currentTime <= cue.endTime) {
426
- subtitleText +=
427
- (cue as VTTCue).getCueAsHTML().textContent + '\n'
428
- }
429
- }
430
- }
431
-
432
- this.setSubtitleText(subtitleText)
403
+ this.core.activePlayback.closedCaptionsTrackId = trackId
404
+ }
433
405
 
434
- track.oncuechange = (e) => {
435
- try {
436
- if (track.activeCues?.length) {
437
- const html = (track.activeCues[0] as VTTCue).getCueAsHTML()
406
+ private getSubtitleText(track: TextTrack) {
407
+ const currentTime = this.core.activePlayback?.getCurrentTime() ?? 0
408
+ const cues = track.cues
409
+ const lines = []
438
410
 
439
- this.setSubtitleText(html)
440
- } else {
441
- this.clearSubtitleText()
442
- }
443
- } catch (error) {
444
- // console.error(error);
445
- reportError(error)
446
- }
447
- }
448
- continue
411
+ if (cues && cues.length) {
412
+ for (const cue of cues) {
413
+ if (currentTime >= cue.startTime && currentTime <= cue.endTime) {
414
+ lines.push((cue as VTTCue).getCueAsHTML().textContent)
449
415
  }
450
- this.tracks[i].oncuechange = null
451
- this.tracks[i].mode = 'hidden'
452
416
  }
453
417
  }
418
+
419
+ return lines.join('\n')
454
420
  }
455
421
 
456
422
  private setSubtitleText(text: string | DocumentFragment) {
@@ -461,9 +427,8 @@ export class Subtitles extends UICorePlugin {
461
427
  this.setSubtitleText('')
462
428
  }
463
429
 
464
- private updateCurrentLevel(track: TextTrackInfo) {
465
- this.currentLevel = track
466
- if (track.language === 'off') {
430
+ private updateSelection() {
431
+ if (!this.track) {
467
432
  this.hide()
468
433
  } else {
469
434
  this.show()
@@ -473,24 +438,24 @@ export class Subtitles extends UICorePlugin {
473
438
  }
474
439
 
475
440
  private highlightCurrentSubtitles() {
476
- this.levelElement().removeClass('current')
477
- this.levelElement().find('a').removeClass('gcore-skin-active')
478
-
479
- if (this.currentLevel) {
480
- const currentLevelElement = this.levelElement(this.currentLevel.language)
441
+ this.allItemElements()
442
+ .removeClass('current')
443
+ .find('a')
444
+ .removeClass('gcore-skin-active')
481
445
 
482
- currentLevelElement.addClass('current')
483
- currentLevelElement.find('a').addClass('gcore-skin-active')
484
- }
446
+ trace(`${T} highlightCurrentSubtitles`, {
447
+ track: this.track?.id,
448
+ })
449
+ const currentLevelElement = this.itemElement(this.track ? this.track.id : -1)
450
+ currentLevelElement
451
+ .addClass('current')
452
+ .find('a')
453
+ .addClass('gcore-skin-active')
485
454
  }
486
455
 
487
456
  private renderIcon() {
488
457
  const icon = this.isShowing ? subtitlesOnIcon : subtitlesOffIcon
489
458
 
490
- this.core
491
- .getPlugin('media_control')
492
- .getElement('subtitlesSelector')
493
- ?.find('span.subtitle-text')
494
- .html(icon)
459
+ this.$el.find('span.subtitle-text').html(icon)
495
460
  }
496
461
  }
package/src/testUtils.ts CHANGED
@@ -199,6 +199,8 @@ export function createMockMediaControl(core: any) {
199
199
  // @ts-ignore
200
200
  mediaControl.getElement = vi.fn().mockImplementation((name) => elements[name])
201
201
  // @ts-ignore
202
+ mediaControl.putElement = vi.fn()
203
+ // @ts-ignore
202
204
  mediaControl.getLeftPanel = vi.fn().mockImplementation(() => mediaControl.$el.find('.media-control-left-panel'))
203
205
  // @ts-ignore
204
206
  mediaControl.getRightPanel = vi.fn().mockImplementation(() => mediaControl.$el.find('.media-control-right-panel'))
@@ -2,6 +2,25 @@ declare interface HTMLVideoElement {
2
2
  webkitDisplayingFullscreen?: boolean;
3
3
  }
4
4
 
5
+ declare interface HTMLMediaElement {
6
+ audioTracks?: AudioTrackList;
7
+ }
8
+
9
+ declare interface AudioTrackW3C {
10
+ readonly id: string;
11
+ enabled: boolean;
12
+ readonly kind: string;
13
+ readonly label: string;
14
+ readonly language: string;
15
+ readonly sourceBuffer: SourceBuffer | null;
16
+ }
17
+
18
+ declare interface AudioTrackList {
19
+ getTrackById(id: string): AudioTrackW3C | null;
20
+ length: number;
21
+ [index: number]: AudioTrackW3C;
22
+ }
23
+
5
24
  declare module "*.css";
6
25
  declare module "*.scss";
7
26
  declare module "*.svg";