@gcorevideo/player 2.21.1 → 2.21.4

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 (97) hide show
  1. package/assets/audio-selector/style.scss +1 -1
  2. package/assets/audio-selector/track-selector.ejs +3 -3
  3. package/assets/bottom-gear/bottomgear.ejs +2 -2
  4. package/assets/media-control/container.scss +1 -1
  5. package/assets/media-control/media-control.ejs +1 -11
  6. package/assets/media-control/media-control.scss +49 -57
  7. package/assets/media-control/width270.scss +1 -1
  8. package/assets/media-control/width370.scss +7 -9
  9. package/assets/playback-rate/button.ejs +2 -2
  10. package/assets/playback-rate/list.ejs +4 -4
  11. package/assets/subtitles/combobox.ejs +10 -12
  12. package/assets/subtitles/string.ejs +1 -1
  13. package/assets/subtitles/style.scss +9 -16
  14. package/dist/core.js +5 -1
  15. package/dist/index.css +782 -794
  16. package/dist/index.js +240 -244
  17. package/dist/player.d.ts +141 -119
  18. package/dist/plugins/index.css +862 -874
  19. package/dist/plugins/index.js +222 -238
  20. package/docs/api/player.bottomgear.getelement.md +2 -2
  21. package/docs/api/player.bottomgear.md +1 -1
  22. package/docs/api/{player.subtitles.hide.md → player.closedcaptions.hide.md} +2 -2
  23. package/docs/api/{player.subtitles.md → player.closedcaptions.md} +11 -11
  24. package/docs/api/{player.subtitles.show.md → player.closedcaptions.show.md} +2 -2
  25. package/docs/api/player.closedcaptionspluginsettings.md +13 -0
  26. package/docs/api/player.gearitemelement.md +6 -4
  27. package/docs/api/player.gearoptionsitem.md +16 -0
  28. package/docs/api/player.md +48 -12
  29. package/docs/api/player.mediacontrol.putelement.md +2 -2
  30. package/docs/api/player.mediacontrolelement.md +1 -1
  31. package/docs/api/player.playbackrate.md +1 -1
  32. package/docs/api/player.subtitlespluginsettings.md +18 -0
  33. package/docs/api/player.texttrackitem.id.md +11 -0
  34. package/docs/api/player.texttrackitem.md +87 -0
  35. package/docs/api/player.texttrackitem.name.md +11 -0
  36. package/docs/api/player.texttrackitem.track.md +11 -0
  37. package/lib/index.d.ts +1 -1
  38. package/lib/index.js +1 -1
  39. package/lib/index.plugins.d.ts +2 -1
  40. package/lib/index.plugins.d.ts.map +1 -1
  41. package/lib/index.plugins.js +2 -1
  42. package/lib/playback/BasePlayback.d.ts +1 -0
  43. package/lib/playback/BasePlayback.d.ts.map +1 -1
  44. package/lib/playback/BasePlayback.js +3 -0
  45. package/lib/playback/dash-playback/DashPlayback.d.ts.map +1 -1
  46. package/lib/playback/dash-playback/DashPlayback.js +1 -0
  47. package/lib/playback.types.d.ts +5 -0
  48. package/lib/playback.types.d.ts.map +1 -1
  49. package/lib/plugins/audio-selector/AudioSelector.d.ts +2 -3
  50. package/lib/plugins/audio-selector/AudioSelector.d.ts.map +1 -1
  51. package/lib/plugins/audio-selector/AudioSelector.js +6 -7
  52. package/lib/plugins/bottom-gear/BottomGear.d.ts +7 -3
  53. package/lib/plugins/bottom-gear/BottomGear.d.ts.map +1 -1
  54. package/lib/plugins/bottom-gear/BottomGear.js +4 -2
  55. package/lib/plugins/media-control/MediaControl.d.ts +5 -6
  56. package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
  57. package/lib/plugins/media-control/MediaControl.js +48 -39
  58. package/lib/plugins/picture-in-picture/PictureInPicture.d.ts +1 -0
  59. package/lib/plugins/picture-in-picture/PictureInPicture.d.ts.map +1 -1
  60. package/lib/plugins/picture-in-picture/PictureInPicture.js +4 -4
  61. package/lib/plugins/playback-rate/PlaybackRate.d.ts +1 -1
  62. package/lib/plugins/playback-rate/PlaybackRate.d.ts.map +1 -1
  63. package/lib/plugins/playback-rate/PlaybackRate.js +24 -14
  64. package/lib/plugins/subtitles/ClosedCaptions.d.ts +118 -0
  65. package/lib/plugins/subtitles/ClosedCaptions.d.ts.map +1 -0
  66. package/lib/plugins/subtitles/ClosedCaptions.js +348 -0
  67. package/lib/plugins/subtitles/Subtitles.d.ts +31 -26
  68. package/lib/plugins/subtitles/Subtitles.d.ts.map +1 -1
  69. package/lib/plugins/subtitles/Subtitles.js +138 -169
  70. package/lib/testUtils.d.ts +22 -18
  71. package/lib/testUtils.d.ts.map +1 -1
  72. package/lib/testUtils.js +22 -36
  73. package/package.json +1 -1
  74. package/src/index.plugins.ts +2 -1
  75. package/src/index.ts +1 -1
  76. package/src/playback/BasePlayback.ts +4 -0
  77. package/src/playback/dash-playback/DashPlayback.ts +1 -0
  78. package/src/playback.types.ts +6 -0
  79. package/src/plugins/audio-selector/AudioSelector.ts +9 -8
  80. package/src/plugins/bottom-gear/BottomGear.ts +14 -5
  81. package/src/plugins/bottom-gear/__tests__/BottomGear.test.ts +1 -1
  82. package/src/plugins/bottom-gear/__tests__/__snapshots__/BottomGear.test.ts.snap +2 -2
  83. package/src/plugins/media-control/MediaControl.ts +84 -60
  84. package/src/plugins/media-control/__tests__/MediaControl.test.ts +43 -0
  85. package/src/plugins/media-control/__tests__/__snapshots__/MediaControl.test.ts.snap +175 -0
  86. package/src/plugins/picture-in-picture/PictureInPicture.ts +5 -5
  87. package/src/plugins/playback-rate/PlaybackRate.ts +143 -100
  88. package/src/plugins/playback-rate/__tests__/PlaybackRate.test.ts +65 -0
  89. package/src/plugins/playback-rate/__tests__/__snapshots__/PlaybackRate.test.ts.snap +11 -0
  90. package/src/plugins/subtitles/ClosedCaptions.ts +469 -0
  91. package/src/plugins/subtitles/__tests__/ClosedCaptions.test.ts +58 -0
  92. package/src/plugins/subtitles/__tests__/__snapshots__/ClosedCaptions.test.ts.snap +25 -0
  93. package/src/testUtils.ts +22 -36
  94. package/temp/player.api.json +269 -89
  95. package/tsconfig.tsbuildinfo +1 -1
  96. package/src/plugins/index.ts +0 -39
  97. package/src/plugins/subtitles/Subtitles.ts +0 -496
@@ -130,3 +130,9 @@ export interface PlaybackError {
130
130
  icon?: string
131
131
  }
132
132
  }
133
+
134
+ export interface TextTrackItem {
135
+ id: number
136
+ name: string
137
+ track: TextTrack
138
+ }
@@ -9,6 +9,7 @@ import pluginHtml from '../../../assets/audio-selector/track-selector.ejs'
9
9
  import '../../../assets/audio-selector/style.scss'
10
10
  import audioArrow from '../../../assets/icons/old/quality-arrow.svg'
11
11
  import { ZeptoResult } from '../../types.js'
12
+ import { MediaControl } from '../media-control/MediaControl.js'
12
13
 
13
14
  const VERSION: string = '0.0.1'
14
15
 
@@ -57,8 +58,8 @@ export class AudioSelector extends UICorePlugin {
57
58
  */
58
59
  override get attributes() {
59
60
  return {
60
- class: 'media-control-audio-tracks',
61
- 'data-track-selector': '',
61
+ class: 'media-control-audiotracks',
62
+
62
63
  }
63
64
  }
64
65
 
@@ -67,8 +68,8 @@ export class AudioSelector extends UICorePlugin {
67
68
  */
68
69
  override get events() {
69
70
  return {
70
- 'click [data-track-selector-select]': 'onTrackSelect',
71
- 'click [data-track-selector-button]': 'onShowLevelSelectMenu',
71
+ 'click [data-audiotracks-select]': 'onTrackSelect',
72
+ 'click [data-audiotracks-button]': 'onShowLevelSelectMenu',
72
73
  }
73
74
  }
74
75
 
@@ -156,12 +157,12 @@ export class AudioSelector extends UICorePlugin {
156
157
  return this
157
158
  }
158
159
 
159
- const mediaControl = this.core.getPlugin('media_control')
160
+ const mediaControl = this.core.getPlugin('media_control') as MediaControl
160
161
  this.$el.html(
161
162
  AudioSelector.template({ tracks: this.tracks, title: this.getTitle() }),
162
163
  )
163
164
  this.$('.audio-arrow').append(audioArrow)
164
- mediaControl.putElement('audioTracksSelector', this.$el)
165
+ mediaControl.putElement('audiotracks', this.el)
165
166
 
166
167
  this.updateText()
167
168
  this.highlightCurrentTrack()
@@ -179,7 +180,7 @@ export class AudioSelector extends UICorePlugin {
179
180
  }
180
181
 
181
182
  private onTrackSelect(event: MouseEvent) {
182
- const id = (event.target as HTMLElement)?.dataset?.trackSelectorSelect
183
+ const id = (event.target as HTMLElement)?.dataset?.audiotracksSelect
183
184
  if (id) {
184
185
  this.selectAudioTrack(id)
185
186
  }
@@ -218,7 +219,7 @@ export class AudioSelector extends UICorePlugin {
218
219
  return (
219
220
  this.$(
220
221
  'ul a' +
221
- (id !== undefined ? '[data-track-selector-select="' + id + '"]' : ''),
222
+ (id !== undefined ? '[data-audiotracks-select="' + id + '"]' : ''),
222
223
  ) as ZeptoResult
223
224
  ).parent()
224
225
  }
@@ -20,7 +20,14 @@ const T = 'plugins.bottom_gear';
20
20
  * An element inside the gear menu
21
21
  * @beta
22
22
  */
23
- export type GearItemElement = 'quality' | 'rate' | 'nerd';
23
+ export type GearOptionsItem = 'quality' | 'rate' | 'nerd';
24
+
25
+ /**
26
+ * @deprecated Use {@link GearOptionsItem} instead
27
+ */
28
+ export type GearItemElement = GearOptionsItem;
29
+
30
+ // TODO disabled if no items added
24
31
 
25
32
  /**
26
33
  * `PLUGIN` that adds the gear button with an extra options menu on the right side of the {@link MediaControl | media control} UI
@@ -30,7 +37,7 @@ export type GearItemElement = 'quality' | 'rate' | 'nerd';
30
37
  *
31
38
  * Depends on:
32
39
  *
33
- * - {@link MediaControl | media_control}
40
+ * - {@link MediaControl}
34
41
  */
35
42
  export class BottomGear extends UICorePlugin {
36
43
  private isHd = false;
@@ -88,10 +95,12 @@ export class BottomGear extends UICorePlugin {
88
95
  * @param name - Name of a gear menu placeholder item to attach custom UI
89
96
  * @returns Zepto result of the element
90
97
  */
91
- getElement(name: GearItemElement): ZeptoResult | null {
98
+ getElement(name: GearOptionsItem): ZeptoResult | null {
92
99
  return this.$el.find(`.gear-options-list [data-${name}]`);
93
100
  }
94
101
 
102
+ // TODO implement putElement/addElement method
103
+
95
104
  /**
96
105
  * Replaces the content of the gear menu
97
106
  * @param content - Zepto result of the element
@@ -123,7 +132,7 @@ export class BottomGear extends UICorePlugin {
123
132
  const mediaControl = this.core.getPlugin('media_control');
124
133
 
125
134
  // TODO use options.mediaControl.gear.items
126
- const items: GearItemElement[] = [
135
+ const items: GearOptionsItem[] = [
127
136
  'quality',
128
137
  'rate',
129
138
  'nerd',
@@ -131,7 +140,7 @@ export class BottomGear extends UICorePlugin {
131
140
  const icon = this.isHd ? gearHdIcon : gearIcon;
132
141
  this.$el.html(BottomGear.template({ icon, items }));
133
142
 
134
- mediaControl.putElement('gear', this.$el);
143
+ mediaControl.putElement('gear', this.el);
135
144
  mediaControl.trigger(MediaControlEvents.MEDIACONTROL_GEAR_RENDERED);
136
145
  return this;
137
146
  }
@@ -26,7 +26,7 @@ describe('BottomGear', () => {
26
26
  expect(bottomGear.el.innerHTML).toMatchSnapshot()
27
27
  })
28
28
  it('should attach to media control', () => {
29
- expect(mediaControl.putElement).toHaveBeenCalledWith('gear', bottomGear.$el)
29
+ expect(mediaControl.putElement).toHaveBeenCalledWith('gear', bottomGear.el)
30
30
  })
31
31
  it('should emit event', () => {
32
32
  expect(onGearRendered).toHaveBeenCalled()
@@ -1,11 +1,11 @@
1
1
  // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
2
 
3
3
  exports[`BottomGear > should render 1`] = `
4
- "<button type="button" class="button-gear media-control-button gplayer-lite-btn gcore-skin-button-color gear-icon" data-gear-button="-1">
4
+ "<button type="button" class="button-gear media-control-button gplayer-lite-btn gcore-skin-button-color gear-icon" data-gear-button="-1" id="gear-button">
5
5
  /assets/icons/new/gear.svg
6
6
  </button>
7
7
  <div class="gear-wrapper gcore-skin-bg-color">
8
- <ul class="gear-options-list">
8
+ <ul class="gear-options-list" id="gear-options">
9
9
 
10
10
  <li data-quality=""></li>
11
11
 
@@ -42,13 +42,13 @@ import fullscreenOnIcon from '../../../assets/icons/new/fullscreen-on.svg'
42
42
  * @beta
43
43
  */
44
44
  export type MediaControlElement =
45
- | 'audioTracksSelector'
45
+ | 'audiotracks'
46
46
  | 'clipText'
47
47
  | 'gear'
48
48
  | 'pip'
49
49
  | 'playbackRate'
50
50
  | 'seekBarContainer'
51
- | 'subtitlesSelector'
51
+ | 'cc'
52
52
 
53
53
  /**
54
54
  * Custom events emitted by the plugins to communicate with one another
@@ -95,7 +95,7 @@ type DisabledClickable = {
95
95
  * The methods exposed are to be used by the other plugins that extend the media control UI.
96
96
  */
97
97
  export class MediaControl extends UICorePlugin {
98
- private advertisementPlaying = false
98
+ // private advertisementPlaying = false
99
99
 
100
100
  private buttonsColor: string | null = null
101
101
 
@@ -131,7 +131,7 @@ export class MediaControl extends UICorePlugin {
131
131
 
132
132
  private rendered = false
133
133
 
134
- private settings: Record<string, unknown> = {}
134
+ private settings: Record<string, MediaControlElement[]> = {} // TODO & seekEnabled: boolean, ...
135
135
 
136
136
  private userDisabled = false
137
137
 
@@ -171,8 +171,6 @@ export class MediaControl extends UICorePlugin {
171
171
 
172
172
  private $seekBarScrubber: ZeptoResult | null = null
173
173
 
174
- private $subtitlesSelector: ZeptoResult | null = null
175
-
176
174
  private $volumeBarContainer: ZeptoResult | null = null
177
175
 
178
176
  private $volumeBarBackground: ZeptoResult | null = null
@@ -203,7 +201,8 @@ export class MediaControl extends UICorePlugin {
203
201
 
204
202
  private get disabled() {
205
203
  const playbackIsNOOP =
206
- this.core.activeContainer && this.core.activeContainer.getPlaybackType() === Playback.NO_OP
204
+ this.core.activeContainer &&
205
+ this.core.activeContainer.getPlaybackType() === Playback.NO_OP
207
206
 
208
207
  return this.userDisabled || playbackIsNOOP
209
208
  }
@@ -296,9 +295,7 @@ export class MediaControl extends UICorePlugin {
296
295
  this.bindKeyEvents()
297
296
 
298
297
  this.userDisabled = false
299
- if (
300
- this.options.chromeless
301
- ) {
298
+ if (this.options.chromeless) {
302
299
  this.disable()
303
300
  }
304
301
 
@@ -364,9 +361,21 @@ export class MediaControl extends UICorePlugin {
364
361
  }
365
362
 
366
363
  private bindContainerEvents() {
367
- this.listenTo(this.core.activeContainer, Events.CONTAINER_PLAY, this.changeTogglePlay)
368
- this.listenTo(this.core.activeContainer, Events.CONTAINER_PAUSE, this.changeTogglePlay)
369
- this.listenTo(this.core.activeContainer, Events.CONTAINER_STOP, this.changeTogglePlay)
364
+ this.listenTo(
365
+ this.core.activeContainer,
366
+ Events.CONTAINER_PLAY,
367
+ this.changeTogglePlay,
368
+ )
369
+ this.listenTo(
370
+ this.core.activeContainer,
371
+ Events.CONTAINER_PAUSE,
372
+ this.changeTogglePlay,
373
+ )
374
+ this.listenTo(
375
+ this.core.activeContainer,
376
+ Events.CONTAINER_STOP,
377
+ this.changeTogglePlay,
378
+ )
370
379
  this.listenTo(
371
380
  this.core.activeContainer,
372
381
  Events.CONTAINER_DBLCLICK,
@@ -385,12 +394,12 @@ export class MediaControl extends UICorePlugin {
385
394
  this.listenTo(
386
395
  this.core.activeContainer,
387
396
  Events.CONTAINER_SETTINGSUPDATE,
388
- this.settingsUpdate,
397
+ this.updateSettings,
389
398
  )
390
399
  this.listenTo(
391
400
  this.core.activeContainer,
392
401
  Events.CONTAINER_PLAYBACKDVRSTATECHANGED,
393
- this.settingsUpdate,
402
+ this.updateSettings,
394
403
  )
395
404
  this.listenTo(
396
405
  this.core.activeContainer,
@@ -408,20 +417,22 @@ export class MediaControl extends UICorePlugin {
408
417
  this.enable,
409
418
  )
410
419
  this.listenTo(this.core.activeContainer, Events.CONTAINER_ENDED, this.ended)
411
- this.listenTo(this.core.activeContainer, Events.CONTAINER_VOLUME, this.onVolumeChanged)
420
+ this.listenTo(
421
+ this.core.activeContainer,
422
+ Events.CONTAINER_VOLUME,
423
+ this.onVolumeChanged,
424
+ )
412
425
  this.listenTo(
413
426
  this.core.activeContainer,
414
427
  Events.CONTAINER_OPTIONS_CHANGE,
415
428
  this.setInitialVolume,
416
429
  )
417
- if (this.core.activePlayback.el.nodeName.toLowerCase() === 'video') {
418
- // wait until the metadata has loaded and then check if fullscreen on video tag is supported
419
- this.listenToOnce(
420
- this.core.activeContainer,
421
- Events.CONTAINER_LOADEDMETADATA,
422
- this.onLoadedMetadataOnVideoTag,
423
- )
424
- }
430
+ // wait until the metadata has loaded and then check if fullscreen on video tag is supported
431
+ this.listenToOnce(
432
+ this.core.activeContainer,
433
+ Events.CONTAINER_LOADEDMETADATA,
434
+ this.onLoadedMetadata,
435
+ )
425
436
  }
426
437
 
427
438
  /**
@@ -462,14 +473,14 @@ export class MediaControl extends UICorePlugin {
462
473
  this.updateVolumeUI()
463
474
  }
464
475
 
465
- private onLoadedMetadataOnVideoTag(event: any) {
476
+ private onLoadedMetadata() {
466
477
  const video = this.core.activePlayback?.el
467
478
 
468
479
  // video.webkitSupportsFullscreen is deprecated but iOS appears to only use this
469
480
  // see https://github.com/clappr/clappr/issues/1127
470
481
  if (!Fullscreen.fullscreenEnabled() && video.webkitSupportsFullscreen) {
471
482
  this.fullScreenOnVideoTagSupported = true
472
- this.settingsUpdate()
483
+ this.updateSettings()
473
484
  }
474
485
  }
475
486
 
@@ -741,7 +752,7 @@ export class MediaControl extends UICorePlugin {
741
752
  this.setInitialVolume()
742
753
  this.changeTogglePlay()
743
754
  this.bindContainerEvents()
744
- this.settingsUpdate()
755
+ this.updateSettings()
745
756
  this.core.activeContainer.trigger(
746
757
  Events.CONTAINER_PLAYBACKDVRSTATECHANGED,
747
758
  this.core.activeContainer.isDvrInUse(),
@@ -976,23 +987,28 @@ export class MediaControl extends UICorePlugin {
976
987
  }
977
988
  }
978
989
 
979
- private settingsUpdate() {
980
- const newSettings = $.extend(true, {
981
- left: [],
982
- default: [],
983
- right: [],
984
- }, this.core.activeContainer?.settings)
990
+ private updateSettings() {
991
+ const newSettings = $.extend(
992
+ true,
993
+ {
994
+ left: [],
995
+ default: [],
996
+ right: [],
997
+ },
998
+ this.core.activeContainer.settings,
999
+ )
985
1000
 
986
1001
  newSettings.left = orderByOrderPattern(
987
1002
  [...newSettings.left, 'clipsText', 'volume'],
988
1003
  LEFT_ORDER,
989
1004
  )
990
1005
 
1006
+ // actual order of the items appear rendered is controlled by CSS
991
1007
  newSettings.right = [
992
1008
  'fullscreen',
993
1009
  'pip',
994
- 'bottomgear',
995
- 'subtitles',
1010
+ 'gear',
1011
+ 'cc',
996
1012
  'multicamera',
997
1013
  'playbackrate',
998
1014
  'vr',
@@ -1004,7 +1020,7 @@ export class MediaControl extends UICorePlugin {
1004
1020
  !Fullscreen.fullscreenEnabled()) ||
1005
1021
  this.options.fullscreenDisable
1006
1022
  ) {
1007
- // remove fullscreen from settings if it is present
1023
+ // remove fullscreen from settings if it is not available
1008
1024
  removeArrayItem(newSettings.default, 'fullscreen')
1009
1025
  removeArrayItem(newSettings.left, 'fullscreen')
1010
1026
  removeArrayItem(newSettings.right, 'fullscreen')
@@ -1055,16 +1071,13 @@ export class MediaControl extends UICorePlugin {
1055
1071
  this.$volumeBarBackground = this.$el.find('.bar-background[data-volume]')
1056
1072
  this.$volumeBarFill = this.$el.find('.bar-fill-1[data-volume]')
1057
1073
  this.$volumeBarScrubber = this.$el.find('.bar-scrubber[data-volume]')
1058
- this.$subtitlesSelector = this.$el.find(
1059
- '.media-control-subtitles[data-subtitles]',
1060
- )
1061
1074
  this.$playbackRate = this.$el.find(
1062
1075
  '.media-control-playbackrate[data-playbackrate]',
1063
1076
  )
1064
1077
  this.$multiCameraSelector = this.$el.find(
1065
1078
  '.media-control-multicamera[data-multicamera]',
1066
1079
  )
1067
- this.$clipText = this.$el.find('.media-clip-text[data-clipstext]')
1080
+ this.$clipText = this.$el.find('.media-clip-text[data-clipstext]') // TODO
1068
1081
  this.$clipTextContainer = this.$el.find(
1069
1082
  '.media-clip-container[data-clipstext]',
1070
1083
  )
@@ -1094,34 +1107,32 @@ export class MediaControl extends UICorePlugin {
1094
1107
  */
1095
1108
  getElement(name: MediaControlElement): ZeptoResult | null {
1096
1109
  switch (name) {
1097
- case 'audioTracksSelector':
1110
+ case 'audiotracks':
1098
1111
  return null
1099
1112
  case 'clipText':
1100
1113
  return this.$clipText
1101
- case 'gear':
1102
- return null
1103
- case 'pip':
1104
- return null
1105
1114
  case 'playbackRate':
1106
1115
  return this.$playbackRate
1107
1116
  case 'seekBarContainer':
1108
1117
  return this.$seekBarContainer
1109
- case 'subtitlesSelector':
1110
- return this.$subtitlesSelector
1111
1118
  }
1112
1119
  }
1113
1120
 
1114
- putElement(name: MediaControlElement, element: ZeptoResult) {
1115
- switch (name) {
1116
- case 'audioTracksSelector':
1117
- this.getRightPanel().append(element)
1118
- break
1119
- case 'pip':
1120
- this.getRightPanel().append(element)
1121
- break
1122
- case 'gear':
1123
- this.getRightPanel().append(element)
1124
- break
1121
+ putElement(name: MediaControlElement, element: HTMLElement) {
1122
+ const panel = this.getElementLocation(name);
1123
+ trace(`${T} putElement`, { name, panel: !!panel })
1124
+ if (panel) {
1125
+ const current = panel.find(`[data-${name}]`)
1126
+ element.setAttribute(`data-${name}`, "")
1127
+ // TODO test
1128
+ if (current.length) {
1129
+ if (current[0] === element) {
1130
+ return
1131
+ }
1132
+ current.replaceWith(element)
1133
+ } else {
1134
+ panel.append(element)
1135
+ }
1125
1136
  }
1126
1137
  }
1127
1138
 
@@ -1407,13 +1418,13 @@ export class MediaControl extends UICorePlugin {
1407
1418
 
1408
1419
  // TODO manage by the ads plugin
1409
1420
  private onStartAd() {
1410
- this.advertisementPlaying = true
1421
+ // this.advertisementPlaying = true
1411
1422
  this.disable()
1412
1423
  }
1413
1424
 
1414
1425
  // TODO manage by the ads plugin
1415
1426
  private onFinishAd() {
1416
- this.advertisementPlaying = false
1427
+ // this.advertisementPlaying = false
1417
1428
  this.enable()
1418
1429
  }
1419
1430
 
@@ -1470,6 +1481,19 @@ export class MediaControl extends UICorePlugin {
1470
1481
 
1471
1482
  return isFinite(this.core.activePlayback.getDuration())
1472
1483
  }
1484
+
1485
+ private getElementLocation(name: MediaControlElement) {
1486
+ if (this.settings.right?.includes(name)) {
1487
+ return this.getRightPanel();
1488
+ }
1489
+ if (this.settings.left?.includes(name)) {
1490
+ return this.getLeftPanel();
1491
+ }
1492
+ if (this.settings.default?.includes(name)) {
1493
+ return this.getCenterPanel();
1494
+ }
1495
+ return null;
1496
+ }
1473
1497
  }
1474
1498
 
1475
1499
  MediaControl.extend = function (properties) {
@@ -0,0 +1,43 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest'
2
+ import { MediaControl, MediaControlElement } from '../MediaControl'
3
+ import { createMockCore } from '../../../testUtils'
4
+ import { LogTracer, Logger, setTracer } from '@gcorevideo/utils'
5
+
6
+ Logger.enable('*')
7
+ setTracer(new LogTracer('MediaControl.test'))
8
+
9
+ describe('MediaControl', () => {
10
+ let core: any
11
+ let mediaControl: MediaControl
12
+
13
+ beforeEach(() => {
14
+ core = createMockCore()
15
+ })
16
+ describe('putElement', () => {
17
+ beforeEach(() => {
18
+ mediaControl = new MediaControl(core)
19
+ core.emit('core:ready')
20
+ core.activeContainer.settings = {}
21
+ core.emit('core:active:container:changed', core.activeContainer)
22
+ })
23
+ describe.each([
24
+ ['pip' as MediaControlElement],
25
+ ['gear' as MediaControlElement],
26
+ ['cc' as MediaControlElement],
27
+ // ['multicamera' as MediaControlElement],
28
+ // ['playbackrate' as MediaControlElement],
29
+ // ['vr' as MediaControlElement],
30
+ // ['audiotracks' as MediaControlElement],
31
+ ])('%s', (mcName) => {
32
+ it('should put the element in the right panel', () => {
33
+ const element = document.createElement('div')
34
+ element.className = 'my-media-control'
35
+ element.textContent = 'test'
36
+ mediaControl.putElement(mcName, element)
37
+
38
+ expect(mediaControl.el.innerHTML).toMatchSnapshot()
39
+ expect(mediaControl.$el.find('.media-control-right-panel .my-media-control').length).toEqual(1)
40
+ })
41
+ })
42
+ })
43
+ })
@@ -0,0 +1,175 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`MediaControl > putElement > cc > should put the element in the right panel 1`] = `
4
+ "<div class="media-control-background" data-background=""></div>
5
+
6
+ <div class="media-control-layer gcore-skin-bg-color" data-controls="">
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+ <div class="media-control-left-panel" data-media-control="">
21
+
22
+ <div class="drawer-container" data-volume="">
23
+ <div class="drawer-icon-container" data-volume="">
24
+ <div class="drawer-icon media-control-icon gcore-skin-button-color" data-volume="">/assets/icons/new/volume-max.svg</div>
25
+ <span class="drawer-text" data-volume=""></span>
26
+ </div>
27
+
28
+ <div class="bar-container" data-volume="">
29
+ <div class="bar-background" data-volume="">
30
+ <div class="bar-fill-1 gcore-skin-main-color" data-volume="" style=""></div>
31
+ </div>
32
+ <div class="bar-scrubber" data-volume="" style="">
33
+ <div class="bar-scrubber-icon gcore-skin-main-color" data-volume=""></div>
34
+ </div>
35
+ </div>
36
+
37
+ </div>
38
+
39
+
40
+ <div class="media-clip-container gcore-skin-text-color" data-clipstext="">
41
+ <div class="media-clip-point gcore-skin-text-color" data-clipstext="">•</div>
42
+ <div class="media-clip-text gcore-skin-text-color" data-clipstext=""></div>
43
+ </div>
44
+
45
+ </div>
46
+
47
+
48
+
49
+ <div class="media-control-right-panel" data-media-control="">
50
+
51
+ <div class="media-control-multicamera" data-multicamera=""></div>
52
+
53
+ <div class="media-control-vr" data-vr=""></div>
54
+
55
+ <div class="my-media-control" data-cc="">test</div></div>
56
+
57
+ </div>
58
+ <style>:root {}</style>"
59
+ `;
60
+
61
+ exports[`MediaControl > putElement > gear > should put the element in the right panel 1`] = `
62
+ "<div class="media-control-background" data-background=""></div>
63
+
64
+ <div class="media-control-layer gcore-skin-bg-color" data-controls="">
65
+
66
+
67
+
68
+
69
+
70
+
71
+
72
+
73
+
74
+
75
+
76
+
77
+
78
+ <div class="media-control-left-panel" data-media-control="">
79
+
80
+ <div class="drawer-container" data-volume="">
81
+ <div class="drawer-icon-container" data-volume="">
82
+ <div class="drawer-icon media-control-icon gcore-skin-button-color" data-volume="">/assets/icons/new/volume-max.svg</div>
83
+ <span class="drawer-text" data-volume=""></span>
84
+ </div>
85
+
86
+ <div class="bar-container" data-volume="">
87
+ <div class="bar-background" data-volume="">
88
+ <div class="bar-fill-1 gcore-skin-main-color" data-volume="" style=""></div>
89
+ </div>
90
+ <div class="bar-scrubber" data-volume="" style="">
91
+ <div class="bar-scrubber-icon gcore-skin-main-color" data-volume=""></div>
92
+ </div>
93
+ </div>
94
+
95
+ </div>
96
+
97
+
98
+ <div class="media-clip-container gcore-skin-text-color" data-clipstext="">
99
+ <div class="media-clip-point gcore-skin-text-color" data-clipstext="">•</div>
100
+ <div class="media-clip-text gcore-skin-text-color" data-clipstext=""></div>
101
+ </div>
102
+
103
+ </div>
104
+
105
+
106
+
107
+ <div class="media-control-right-panel" data-media-control="">
108
+
109
+ <div class="media-control-multicamera" data-multicamera=""></div>
110
+
111
+ <div class="media-control-vr" data-vr=""></div>
112
+
113
+ <div class="my-media-control" data-gear="">test</div></div>
114
+
115
+ </div>
116
+ <style>:root {}</style>"
117
+ `;
118
+
119
+ exports[`MediaControl > putElement > pip > should put the element in the right panel 1`] = `
120
+ "<div class="media-control-background" data-background=""></div>
121
+
122
+ <div class="media-control-layer gcore-skin-bg-color" data-controls="">
123
+
124
+
125
+
126
+
127
+
128
+
129
+
130
+
131
+
132
+
133
+
134
+
135
+
136
+ <div class="media-control-left-panel" data-media-control="">
137
+
138
+ <div class="drawer-container" data-volume="">
139
+ <div class="drawer-icon-container" data-volume="">
140
+ <div class="drawer-icon media-control-icon gcore-skin-button-color" data-volume="">/assets/icons/new/volume-max.svg</div>
141
+ <span class="drawer-text" data-volume=""></span>
142
+ </div>
143
+
144
+ <div class="bar-container" data-volume="">
145
+ <div class="bar-background" data-volume="">
146
+ <div class="bar-fill-1 gcore-skin-main-color" data-volume="" style=""></div>
147
+ </div>
148
+ <div class="bar-scrubber" data-volume="" style="">
149
+ <div class="bar-scrubber-icon gcore-skin-main-color" data-volume=""></div>
150
+ </div>
151
+ </div>
152
+
153
+ </div>
154
+
155
+
156
+ <div class="media-clip-container gcore-skin-text-color" data-clipstext="">
157
+ <div class="media-clip-point gcore-skin-text-color" data-clipstext="">•</div>
158
+ <div class="media-clip-text gcore-skin-text-color" data-clipstext=""></div>
159
+ </div>
160
+
161
+ </div>
162
+
163
+
164
+
165
+ <div class="media-control-right-panel" data-media-control="">
166
+
167
+ <div class="media-control-multicamera" data-multicamera=""></div>
168
+
169
+ <div class="media-control-vr" data-vr=""></div>
170
+
171
+ <div class="my-media-control" data-pip="">test</div></div>
172
+
173
+ </div>
174
+ <style>:root {}</style>"
175
+ `;