@gcorevideo/player 2.22.0 → 2.22.2

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 (125) hide show
  1. package/assets/bottom-gear/bottomgear copy.ejs +10 -0
  2. package/assets/bottom-gear/bottomgear.ejs +4 -8
  3. package/assets/bottom-gear/gear-sub-menu.scss +0 -1
  4. package/assets/bottom-gear/gear.scss +0 -1
  5. package/assets/clappr-nerd-stats/button.ejs +3 -3
  6. package/assets/level-selector/button.ejs +2 -4
  7. package/assets/level-selector/list.ejs +14 -10
  8. package/assets/level-selector/style.scss +9 -4
  9. package/assets/media-control/container.scss +1 -1
  10. package/assets/playback-rate/list.ejs +5 -5
  11. package/assets/spinner-three-bounce/spinner.scss +1 -1
  12. package/dist/core.js +1 -2
  13. package/dist/index.css +885 -884
  14. package/dist/index.js +3938 -3779
  15. package/dist/player.d.ts +246 -108
  16. package/dist/plugins/index.css +1230 -1229
  17. package/dist/plugins/index.js +4036 -3878
  18. package/docs/api/player.bottomgear.additem.md +95 -0
  19. package/docs/api/player.bottomgear.md +63 -19
  20. package/docs/api/player.bottomgear.refresh.md +5 -1
  21. package/docs/api/player.clapprnerdstats.md +0 -2
  22. package/docs/api/player.clicktopause.md +1 -1
  23. package/docs/api/player.closedcaptions.md +2 -2
  24. package/docs/api/player.closedcaptionspluginsettings.md +5 -0
  25. package/docs/api/player.errorscreen.md +18 -4
  26. package/docs/api/player.errorscreenpluginsettings.md +1 -4
  27. package/docs/api/player.errorscreensettings.md +15 -0
  28. package/docs/api/{player.mediacontrolevents.md → player.gearevents.md} +7 -7
  29. package/docs/api/player.levelselector.events.md +0 -1
  30. package/docs/api/player.levelselector.md +1 -1
  31. package/docs/api/player.md +33 -36
  32. package/docs/api/{player.bottomgear.setcontent.md → player.mediacontrol.handlecustomarea.md} +5 -9
  33. package/docs/api/player.mediacontrol.md +10 -24
  34. package/docs/api/player.mediacontrol.putelement.md +2 -2
  35. package/docs/api/{player.bottomgear.getelement.md → player.mediacontrol.toggleelement.md} +23 -9
  36. package/docs/api/player.mediacontrolelement.md +1 -1
  37. package/docs/api/player.playbackrate.md +22 -3
  38. package/docs/api/{player.gearoptionsitem.md → player.playbackrateoption.md} +6 -4
  39. package/docs/api/{player.mediacontrol.getcenterpanel.md → player.playbackratesettings.md} +8 -6
  40. package/docs/api/player.sourcecontroller._constructor_.md +49 -0
  41. package/docs/api/player.sourcecontroller.md +70 -7
  42. package/docs/api/player.spinnerevents.md +1 -4
  43. package/docs/api/player.spinnerthreebounce._constructor_.md +0 -3
  44. package/docs/api/player.spinnerthreebounce.hide.md +0 -3
  45. package/docs/api/player.spinnerthreebounce.md +5 -8
  46. package/docs/api/player.spinnerthreebounce.show.md +2 -5
  47. package/lib/internal.types.d.ts +5 -0
  48. package/lib/internal.types.d.ts.map +1 -1
  49. package/lib/playback/dash-playback/DashPlayback.d.ts.map +1 -1
  50. package/lib/playback/dash-playback/DashPlayback.js +0 -1
  51. package/lib/playback.types.d.ts +0 -5
  52. package/lib/playback.types.d.ts.map +1 -1
  53. package/lib/plugins/bottom-gear/BottomGear.d.ts +93 -20
  54. package/lib/plugins/bottom-gear/BottomGear.d.ts.map +1 -1
  55. package/lib/plugins/bottom-gear/BottomGear.js +145 -37
  56. package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.d.ts +2 -3
  57. package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.d.ts.map +1 -1
  58. package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.js +18 -15
  59. package/lib/plugins/click-to-pause/ClickToPause.d.ts +1 -1
  60. package/lib/plugins/click-to-pause/ClickToPause.d.ts.map +1 -1
  61. package/lib/plugins/click-to-pause/ClickToPause.js +3 -2
  62. package/lib/plugins/dvr-controls/DvrControls.js +1 -1
  63. package/lib/plugins/error-screen/ErrorScreen.d.ts +29 -4
  64. package/lib/plugins/error-screen/ErrorScreen.d.ts.map +1 -1
  65. package/lib/plugins/error-screen/ErrorScreen.js +17 -2
  66. package/lib/plugins/level-selector/LevelSelector.d.ts +8 -11
  67. package/lib/plugins/level-selector/LevelSelector.d.ts.map +1 -1
  68. package/lib/plugins/level-selector/LevelSelector.js +66 -102
  69. package/lib/plugins/media-control/MediaControl.d.ts +6 -15
  70. package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
  71. package/lib/plugins/media-control/MediaControl.js +36 -30
  72. package/lib/plugins/picture-in-picture/PictureInPicture.d.ts.map +1 -1
  73. package/lib/plugins/picture-in-picture/PictureInPicture.js +7 -2
  74. package/lib/plugins/playback-rate/PlaybackRate.d.ts +42 -14
  75. package/lib/plugins/playback-rate/PlaybackRate.d.ts.map +1 -1
  76. package/lib/plugins/playback-rate/PlaybackRate.js +101 -83
  77. package/lib/plugins/source-controller/SourceController.d.ts +40 -4
  78. package/lib/plugins/source-controller/SourceController.d.ts.map +1 -1
  79. package/lib/plugins/source-controller/SourceController.js +41 -4
  80. package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.d.ts +8 -6
  81. package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.d.ts.map +1 -1
  82. package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.js +10 -6
  83. package/lib/plugins/subtitles/ClosedCaptions.d.ts +7 -7
  84. package/lib/plugins/subtitles/ClosedCaptions.d.ts.map +1 -1
  85. package/lib/plugins/subtitles/ClosedCaptions.js +3 -3
  86. package/lib/testUtils.d.ts +1 -0
  87. package/lib/testUtils.d.ts.map +1 -1
  88. package/lib/testUtils.js +13 -0
  89. package/package.json +1 -1
  90. package/src/internal.types.ts +6 -0
  91. package/src/playback/dash-playback/DashPlayback.ts +0 -1
  92. package/src/playback.types.ts +0 -5
  93. package/src/plugins/bottom-gear/BottomGear.ts +186 -77
  94. package/src/plugins/bottom-gear/__tests__/BottomGear.test.ts +21 -5
  95. package/src/plugins/bottom-gear/__tests__/__snapshots__/BottomGear.test.ts.snap +5 -12
  96. package/src/plugins/clappr-nerd-stats/ClapprNerdStats.ts +27 -25
  97. package/src/plugins/click-to-pause/ClickToPause.ts +3 -2
  98. package/src/plugins/dvr-controls/DvrControls.ts +1 -1
  99. package/src/plugins/dvr-controls/__tests__/DvrControls.test.ts +1 -1
  100. package/src/plugins/error-screen/ErrorScreen.ts +30 -4
  101. package/src/plugins/level-selector/LevelSelector.ts +80 -120
  102. package/src/plugins/level-selector/__tests__/LevelSelector.test.ts +69 -79
  103. package/src/plugins/level-selector/__tests__/__snapshots__/LevelSelector.test.ts.snap +38 -71
  104. package/src/plugins/media-control/MediaControl.ts +50 -36
  105. package/src/plugins/media-control/__tests__/MediaControl.test.ts +4 -4
  106. package/src/plugins/picture-in-picture/PictureInPicture.ts +7 -2
  107. package/src/plugins/playback-rate/PlaybackRate.ts +136 -108
  108. package/src/plugins/playback-rate/__tests__/PlaybackRate.test.ts +84 -37
  109. package/src/plugins/playback-rate/__tests__/__snapshots__/PlaybackRate.test.ts.snap +55 -6
  110. package/src/plugins/source-controller/SourceController.ts +41 -4
  111. package/src/plugins/spinner-three-bounce/SpinnerThreeBounce.ts +10 -6
  112. package/src/plugins/subtitles/ClosedCaptions.ts +9 -10
  113. package/src/plugins/subtitles/__tests__/ClosedCaptions.test.ts +1 -1
  114. package/src/testUtils.ts +14 -0
  115. package/src/typings/vitest.d.ts +1 -0
  116. package/temp/player.api.json +303 -370
  117. package/tsconfig.tsbuildinfo +1 -1
  118. package/docs/api/player.gearitemelement.md +0 -18
  119. package/docs/api/player.mediacontrol.getleftpanel.md +0 -22
  120. package/docs/api/player.mediacontrol.getrightpanel.md +0 -22
  121. package/docs/api/player.subtitlespluginsettings.md +0 -18
  122. package/docs/api/player.texttrackitem.id.md +0 -11
  123. package/docs/api/player.texttrackitem.md +0 -87
  124. package/docs/api/player.texttrackitem.name.md +0 -11
  125. package/docs/api/player.texttrackitem.track.md +0 -11
@@ -1,17 +1,16 @@
1
1
  import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
2
- import { $, UICorePlugin } from '@clappr/core'
3
- import FakeTimers from '@sinonjs/fake-timers'
4
- import { Logger, LogTracer, setTracer } from '@gcorevideo/utils'
2
+ import { Events } from '@clappr/core'
5
3
  import { LevelSelector } from '../LevelSelector.js'
6
4
  import {
5
+ createMockBottomGear,
7
6
  createMockCore,
8
7
  createMockMediaControl,
9
- createMockPlayback,
10
8
  } from '../../../testUtils.js'
11
- import { MediaControlEvents } from '../../media-control/MediaControl.js'
9
+ import { GearEvents } from '../../bottom-gear/BottomGear.js'
10
+ // import { Logger, LogTracer, setTracer } from '@gcorevideo/utils'
12
11
 
13
- setTracer(new LogTracer('LevelSelector.test'))
14
- Logger.enable('*')
12
+ // setTracer(new LogTracer('LevelSelector.test'))
13
+ // Logger.enable('*')
15
14
 
16
15
  const LEVELS = [
17
16
  {
@@ -33,28 +32,20 @@ const LEVELS = [
33
32
  bitrate: 250000,
34
33
  },
35
34
  ]
35
+
36
36
  describe('LevelSelector', () => {
37
- let clock: FakeTimers.InstalledClock
38
37
  let core: any
39
38
  let levelSelector: LevelSelector
40
- let activePlayback: any
41
- let mediaControl: UICorePlugin
42
- let bottomGear: UICorePlugin | null
43
- beforeEach(() => {
44
- clock = FakeTimers.install()
45
- })
46
- afterEach(() => {
47
- clock.uninstall()
48
- })
39
+ let mediaControl: any
40
+ let bottomGear: any
49
41
  describe('basically', () => {
50
42
  beforeEach(() => {
51
43
  core = createMockCore({
52
44
  levelSelector: {
53
45
  // restrictResolution: 360,
54
- labels: { 360: '360p', 720: 'HD' },
46
+ labels: { 720: 'HD', 1080: 'Full HD' },
55
47
  },
56
48
  })
57
- activePlayback = core.activePlayback
58
49
  core.getPlugin.mockImplementation((name: string) => {
59
50
  if (name === 'media_control') {
60
51
  return mediaControl
@@ -65,43 +56,45 @@ describe('LevelSelector', () => {
65
56
  return null
66
57
  })
67
58
  mediaControl = createMockMediaControl(core)
68
- bottomGear = createBottomGear(core)
59
+ bottomGear = createMockBottomGear(core)
69
60
  levelSelector = new LevelSelector(core)
70
61
  })
71
62
  describe('initially', () => {
72
- beforeEach(async () => {
73
- core.emit('core:active:container:changed')
74
- await clock.tickAsync(1)
75
- activePlayback.emit('playback:levels:available', LEVELS)
76
- await clock.tickAsync(1)
63
+ beforeEach(() => {
64
+ core.emit(Events.CORE_READY)
65
+ core.emit(Events.CORE_ACTIVE_CONTAINER_CHANGED)
66
+ bottomGear.trigger(GearEvents.RENDERED)
67
+ core.activePlayback.emit(Events.PLAYBACK_LEVELS_AVAILABLE, LEVELS)
77
68
  })
78
69
  it('should render proper level label', () => {
79
- // @ts-ignore
80
- expect(levelSelector.el.textContent).toMatchQualityLevelLabel('Auto')
70
+ expect(
71
+ bottomGear.$el.find('[data-quality]').text(),
72
+ // @ts-ignore
73
+ ).toMatchQualityLevelLabel('auto')
81
74
  })
82
75
  })
83
76
  describe.each([
84
- ['auto', LEVELS, -1, 'Auto'],
77
+ ['auto', LEVELS, -1, 'auto'],
85
78
  ['standard label', LEVELS, 0, '360p'],
86
79
  ['custom label', LEVELS, 1, 'HD'],
87
80
  ])('%s', (_, levels, current, label) => {
88
- beforeEach(async () => {
89
- core.emit('core:active:container:changed')
90
- await clock.tickAsync(1)
91
- // activePlayback.currentLevel = current
92
- activePlayback.emit('playback:levels:available', levels)
93
- await clock.tickAsync(1)
94
- levelSelector.$el.find('.gear-option').click()
95
- await clock.tickAsync(1)
81
+ beforeEach(() => {
82
+ core.emit(Events.CORE_READY)
83
+ core.emit(Events.CORE_ACTIVE_CONTAINER_CHANGED)
84
+ bottomGear.trigger(GearEvents.RENDERED)
85
+ core.activePlayback.emit(Events.PLAYBACK_LEVELS_AVAILABLE, levels)
96
86
  levelSelector.$el
97
- .find(`.gear-sub-menu_btn[data-id="${current}"]`)
87
+ .find(`#level-selector-menu [data-id="${current}"]`)
98
88
  .click()
99
- await clock.tickAsync(1)
100
89
  })
101
- it('should render the proper level labels', () => {
102
- expect(levelSelector.el.innerHTML).toMatchSnapshot()
90
+ it('should render the proper level label', () => {
91
+ expect(
92
+ bottomGear.$el.find('[data-quality]').text(),
93
+ // @ts-ignore
94
+ ).toMatchQualityLevelLabel(label)
103
95
  })
104
96
  it('should render the selected level', () => {
97
+ expect(levelSelector.el.innerHTML).toMatchSnapshot()
105
98
  expect(
106
99
  levelSelector.$el.find('ul.gear-sub-menu .current')[0].textContent,
107
100
  // @ts-ignore
@@ -111,15 +104,14 @@ describe('LevelSelector', () => {
111
104
  })
112
105
  describe('options.restrictResolution', () => {
113
106
  beforeEach(() => {
114
- let mediaControl: UICorePlugin | null = null
115
- let bottomGear: UICorePlugin | null = null
116
107
  core = createMockCore({
117
108
  levelSelector: {
118
109
  restrictResolution: 360,
119
- labels: { 360: '360p', 720: '720p' },
110
+ labels: { 360: '360p', 720: '720p', 1080: '1080p' },
120
111
  },
121
112
  })
122
- activePlayback = core.activePlayback
113
+ mediaControl = createMockMediaControl(core)
114
+ bottomGear = createMockBottomGear(core)
123
115
  core.getPlugin.mockImplementation((name: string) => {
124
116
  if (name === 'media_control') {
125
117
  return mediaControl
@@ -130,30 +122,31 @@ describe('LevelSelector', () => {
130
122
  return null
131
123
  })
132
124
  mediaControl = createMockMediaControl(core)
133
- bottomGear = createBottomGear(core)
125
+ bottomGear = createMockBottomGear(core)
134
126
  levelSelector = new LevelSelector(core)
127
+ core.emit(Events.CORE_READY)
128
+ core.emit(Events.CORE_ACTIVE_CONTAINER_CHANGED, core.activeContainer)
129
+ bottomGear.trigger(GearEvents.RENDERED)
135
130
  })
136
- describe('basically', () => {
131
+ describe('initially', () => {
137
132
  beforeEach(async () => {
138
- core.emit('core:active:container:changed')
139
- await clock.tickAsync(1)
140
- activePlayback.emit('playback:levels:available', LEVELS)
141
- await clock.tickAsync(1)
133
+ core.activePlayback.emit(Events.PLAYBACK_LEVELS_AVAILABLE, LEVELS)
142
134
  })
143
135
  it('should render the restricted quality level label', () => {
136
+ expect(bottomGear.$el.find('[data-quality]').html()).toMatchSnapshot()
144
137
  expect(
145
- levelSelector.el.textContent,
138
+ bottomGear.$el.find('[data-quality]').text(),
146
139
  // @ts-ignore
147
140
  ).toMatchQualityLevelLabel('360p')
148
-
149
- expect(levelSelector.el.innerHTML).toMatchSnapshot()
141
+ expect(
142
+ levelSelector.$el.find('#level-selector-menu .current').text(),
143
+ // @ts-ignore
144
+ ).toMatchQualityLevelOption('360p')
150
145
  })
151
146
  })
152
147
  describe('given vertical video format levels', () => {
153
- beforeEach(async () => {
154
- core.emit('core:active:container:changed')
155
- await clock.tickAsync(1)
156
- activePlayback.emit('playback:levels:available', [
148
+ beforeEach(() => {
149
+ core.activePlayback.emit(Events.PLAYBACK_LEVELS_AVAILABLE, [
157
150
  {
158
151
  level: 0,
159
152
  width: 360,
@@ -168,22 +161,31 @@ describe('LevelSelector', () => {
168
161
  },
169
162
  {
170
163
  level: 2,
171
- width: 1920,
172
- height: 1080,
164
+ width: 1080,
165
+ height: 1920,
173
166
  bitrate: 250000,
174
167
  },
175
168
  ])
176
- await clock.tickAsync(1)
177
- levelSelector.$el.find('.gear-option').click()
178
- await clock.tickAsync(1)
179
169
  })
180
170
  it('should recognize vertical orientation', () => {
181
171
  expect(levelSelector.el.innerHTML).toMatchSnapshot()
182
- expect(levelSelector.el.innerHTML).toMatchSnapshot()
172
+ expect(
173
+ levelSelector.$el.find('#level-selector-menu [data-id]:eq(0)').text(),
174
+ // @ts-ignore
175
+ ).toMatchQualityLevelOption('1080p')
176
+ expect(
177
+ levelSelector.$el.find('#level-selector-menu [data-id]:eq(1)').text(),
178
+ // @ts-ignore
179
+ ).toMatchQualityLevelOption('720p')
180
+ expect(
181
+ levelSelector.$el.find('#level-selector-menu [data-id]:eq(2)').text(),
182
+ // @ts-ignore
183
+ ).toMatchQualityLevelOption('360p')
183
184
  })
184
185
  it('should properly apply the restriction', () => {
185
186
  expect(
186
- levelSelector.$el.find('li:not(.level-disabled)')[0].textContent,
187
+ levelSelector.$el.find('#level-selector-menu li:not(.disabled)')[0]
188
+ .textContent,
187
189
  // @ts-ignore
188
190
  ).toMatchQualityLevelOption('360p')
189
191
  })
@@ -195,11 +197,11 @@ expect.extend({
195
197
  toMatchQualityLevelLabel(received, expected) {
196
198
  const { isNot } = this
197
199
  const rendered = received
198
- .replace('/assets/icons/new/arrow-right.svg', '')
200
+ .replace(/\/assets\/.*\.svg/g, '')
199
201
  .replace(/\s+/g, ' ')
200
202
  .trim()
201
203
  return {
202
- pass: rendered.includes(`Quality ${expected}`),
204
+ pass: rendered.includes(`quality ${expected}`),
203
205
  message: () =>
204
206
  `Quality label must${
205
207
  isNot ? ' not' : ''
@@ -209,7 +211,7 @@ expect.extend({
209
211
  toMatchQualityLevelOption(received, expected) {
210
212
  const { isNot } = this
211
213
  const rendered = received
212
- .replace('/assets/icons/new/check.svg', '')
214
+ .replace(/\/assets\/.*\.svg/g, '')
213
215
  .replace(/\s+/g, ' ')
214
216
  .trim()
215
217
  return {
@@ -221,15 +223,3 @@ expect.extend({
221
223
  }
222
224
  },
223
225
  })
224
-
225
- function createBottomGear(core: any) {
226
- const bottomGear = new UICorePlugin(core)
227
- const elemets = {
228
- quality: $(document.createElement('div')),
229
- }
230
- // @ts-ignore
231
- bottomGear.getElement = vi.fn().mockImplementation((name) => elemets[name])
232
- // @ts-ignore
233
- bottomGear.setContent = vi.fn()
234
- return bottomGear
235
- }
@@ -1,24 +1,24 @@
1
1
  // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
2
 
3
- exports[`LevelSelector > basically > auto > should render the proper level labels 1`] = `
4
- "<button class="gplayer-lite-btn go-back gcore-skin-text-color">
3
+ exports[`LevelSelector > basically > auto > should render the selected level 1`] = `
4
+ "<button class="gplayer-lite-btn go-back gcore-skin-text-color" id="level-selector-back-button">
5
5
  <span class="arrow-left-icon">/assets/icons/new/arrow-left.svg</span>
6
- Quality
6
+ quality
7
7
  </button>
8
- <ul class="gear-sub-menu">
8
+ <ul class="gear-sub-menu" id="level-selector-menu">
9
9
 
10
10
  <li class="current">
11
11
  <a href="#" class="gear-sub-menu_btn gcore-skin-text-color gcore-skin-active" data-id="-1" id="level_selector_auto">
12
12
  <span class="check-icon">/assets/icons/new/check.svg</span>
13
- Auto
14
- </a>
15
- </li>
13
+ auto
14
+ </a>
15
+ </li>
16
16
 
17
17
 
18
18
  <li class="">
19
19
  <a href="#" class="gear-sub-menu_btn gcore-skin-text-color" data-id="2" id="level_selector_1080">
20
20
  <span class="check-icon">/assets/icons/new/check.svg</span>
21
- 1080p
21
+ Full HD
22
22
  </a>
23
23
  </li>
24
24
 
@@ -40,25 +40,25 @@ exports[`LevelSelector > basically > auto > should render the proper level label
40
40
  "
41
41
  `;
42
42
 
43
- exports[`LevelSelector > basically > custom label > should render the proper level labels 1`] = `
44
- "<button class="gplayer-lite-btn go-back gcore-skin-text-color">
43
+ exports[`LevelSelector > basically > custom label > should render the selected level 1`] = `
44
+ "<button class="gplayer-lite-btn go-back gcore-skin-text-color" id="level-selector-back-button">
45
45
  <span class="arrow-left-icon">/assets/icons/new/arrow-left.svg</span>
46
- Quality
46
+ quality
47
47
  </button>
48
- <ul class="gear-sub-menu">
48
+ <ul class="gear-sub-menu" id="level-selector-menu">
49
49
 
50
50
  <li class="">
51
51
  <a href="#" class="gear-sub-menu_btn gcore-skin-text-color" data-id="-1" id="level_selector_auto">
52
52
  <span class="check-icon">/assets/icons/new/check.svg</span>
53
- Auto
54
- </a>
55
- </li>
53
+ auto
54
+ </a>
55
+ </li>
56
56
 
57
57
 
58
58
  <li class="">
59
59
  <a href="#" class="gear-sub-menu_btn gcore-skin-text-color" data-id="2" id="level_selector_1080">
60
60
  <span class="check-icon">/assets/icons/new/check.svg</span>
61
- 1080p
61
+ Full HD
62
62
  </a>
63
63
  </li>
64
64
 
@@ -80,25 +80,25 @@ exports[`LevelSelector > basically > custom label > should render the proper lev
80
80
  "
81
81
  `;
82
82
 
83
- exports[`LevelSelector > basically > standard label > should render the proper level labels 1`] = `
84
- "<button class="gplayer-lite-btn go-back gcore-skin-text-color">
83
+ exports[`LevelSelector > basically > standard label > should render the selected level 1`] = `
84
+ "<button class="gplayer-lite-btn go-back gcore-skin-text-color" id="level-selector-back-button">
85
85
  <span class="arrow-left-icon">/assets/icons/new/arrow-left.svg</span>
86
- Quality
86
+ quality
87
87
  </button>
88
- <ul class="gear-sub-menu">
88
+ <ul class="gear-sub-menu" id="level-selector-menu">
89
89
 
90
90
  <li class="">
91
91
  <a href="#" class="gear-sub-menu_btn gcore-skin-text-color" data-id="-1" id="level_selector_auto">
92
92
  <span class="check-icon">/assets/icons/new/check.svg</span>
93
- Auto
94
- </a>
95
- </li>
93
+ auto
94
+ </a>
95
+ </li>
96
96
 
97
97
 
98
98
  <li class="">
99
99
  <a href="#" class="gear-sub-menu_btn gcore-skin-text-color" data-id="2" id="level_selector_1080">
100
100
  <span class="check-icon">/assets/icons/new/check.svg</span>
101
- 1080p
101
+ Full HD
102
102
  </a>
103
103
  </li>
104
104
 
@@ -120,40 +120,30 @@ exports[`LevelSelector > basically > standard label > should render the proper l
120
120
  "
121
121
  `;
122
122
 
123
- exports[`LevelSelector > options.restrictResolution > basically > should render the restricted quality level label 1`] = `
124
- "<button class="gplayer-lite-btn gcore-skin-text-color gear-option">
125
-
126
- <span>Quality</span>
127
- <span class="gear-option_arrow-right-icon">/assets/icons/new/arrow-right.svg</span>
128
- <span class="gear-option_value">360p</span>
129
- </button>
130
- "
131
- `;
132
-
133
123
  exports[`LevelSelector > options.restrictResolution > given vertical video format levels > should recognize vertical orientation 1`] = `
134
- "<button class="gplayer-lite-btn go-back gcore-skin-text-color">
124
+ "<button class="gplayer-lite-btn go-back gcore-skin-text-color" id="level-selector-back-button">
135
125
  <span class="arrow-left-icon">/assets/icons/new/arrow-left.svg</span>
136
- Quality
126
+ quality
137
127
  </button>
138
- <ul class="gear-sub-menu">
128
+ <ul class="gear-sub-menu" id="level-selector-menu">
139
129
 
140
130
 
141
- <li class="level-disabled">
131
+ <li class="disabled ">
142
132
  <a href="#" class="gear-sub-menu_btn gcore-skin-text-color" data-id="2" id="level_selector_1080">
143
133
  <span class="check-icon">/assets/icons/new/check.svg</span>
144
134
  1080p
145
135
  </a>
146
136
  </li>
147
137
 
148
- <li class="level-disabled">
149
- <a href="#" class="gear-sub-menu_btn gcore-skin-text-color" data-id="1" id="level_selector_1280">
138
+ <li class="disabled ">
139
+ <a href="#" class="gear-sub-menu_btn gcore-skin-text-color" data-id="1" id="level_selector_720">
150
140
  <span class="check-icon">/assets/icons/new/check.svg</span>
151
141
  720p
152
142
  </a>
153
143
  </li>
154
144
 
155
- <li class="current">
156
- <a href="#" class="gear-sub-menu_btn gcore-skin-text-color gcore-skin-active" data-id="0" id="level_selector_640">
145
+ <li class="current ">
146
+ <a href="#" class="gear-sub-menu_btn gcore-skin-text-color gcore-skin-active" data-id="0" id="level_selector_360">
157
147
  <span class="check-icon">/assets/icons/new/check.svg</span>
158
148
  360p
159
149
  </a>
@@ -163,35 +153,12 @@ exports[`LevelSelector > options.restrictResolution > given vertical video forma
163
153
  "
164
154
  `;
165
155
 
166
- exports[`LevelSelector > options.restrictResolution > given vertical video format levels > should recognize vertical orientation 2`] = `
167
- "<button class="gplayer-lite-btn go-back gcore-skin-text-color">
168
- <span class="arrow-left-icon">/assets/icons/new/arrow-left.svg</span>
169
- Quality
156
+ exports[`LevelSelector > options.restrictResolution > initially > should render the restricted quality level label 1`] = `
157
+ "<button class="gplayer-lite-btn gcore-skin-text-color gear-option">
158
+ <span class="gear-option_hd-icon hidden">/assets/icons/new/hd.svg</span>
159
+ <span>quality</span>
160
+ <span class="gear-option_arrow-right-icon">/assets/icons/new/arrow-right.svg</span>
161
+ <span class="gear-option_value">360p</span>
170
162
  </button>
171
- <ul class="gear-sub-menu">
172
-
173
-
174
- <li class="level-disabled">
175
- <a href="#" class="gear-sub-menu_btn gcore-skin-text-color" data-id="2" id="level_selector_1080">
176
- <span class="check-icon">/assets/icons/new/check.svg</span>
177
- 1080p
178
- </a>
179
- </li>
180
-
181
- <li class="level-disabled">
182
- <a href="#" class="gear-sub-menu_btn gcore-skin-text-color" data-id="1" id="level_selector_1280">
183
- <span class="check-icon">/assets/icons/new/check.svg</span>
184
- 720p
185
- </a>
186
- </li>
187
-
188
- <li class="current">
189
- <a href="#" class="gear-sub-menu_btn gcore-skin-text-color gcore-skin-active" data-id="0" id="level_selector_640">
190
- <span class="check-icon">/assets/icons/new/check.svg</span>
191
- 360p
192
- </a>
193
- </li>
194
-
195
- </ul>
196
163
  "
197
164
  `;
@@ -47,11 +47,15 @@ export type MediaControlElement =
47
47
  | 'clipText'
48
48
  | 'dvr'
49
49
  | 'duration'
50
+ | 'fullscreen'
50
51
  | 'gear'
52
+ | 'multicamera'
51
53
  | 'pip'
52
54
  | 'playbackRate'
53
55
  | 'position'
54
56
  | 'seekBarContainer'
57
+ | 'vr'
58
+ | 'volume'
55
59
 
56
60
  type MediaControlSettings = {
57
61
  left: MediaControlElement[]
@@ -62,28 +66,25 @@ type MediaControlSettings = {
62
66
 
63
67
  const DEFAULT_SETTINGS: MediaControlSettings = {
64
68
  left: [],
65
- right: [],
69
+ right: [
70
+ 'fullscreen',
71
+ 'pip',
72
+ 'gear',
73
+ 'cc',
74
+ 'multicamera',
75
+ // 'playbackrate',
76
+ 'vr',
77
+ 'audiotracks',
78
+ ],
66
79
  default: [],
67
80
  seekEnabled: true,
68
81
  }
69
82
 
70
- /**
71
- * Custom events emitted by the plugins to communicate with one another
72
- * @beta
73
- */
74
- export enum MediaControlEvents {
75
- /**
76
- * Emitted when the gear menu is rendered
77
- */
78
- MEDIACONTROL_GEAR_RENDERED = 'mediacontrol:gear:rendered',
79
- }
80
-
81
83
  const T = 'plugins.media_control'
82
84
 
83
85
  const LEFT_ORDER = [
84
86
  'playpause',
85
87
  'playstop',
86
- // 'live',
87
88
  'dvr',
88
89
  'volume',
89
90
  'position',
@@ -115,6 +116,9 @@ type DisabledClickable = {
115
116
  export class MediaControl extends UICorePlugin {
116
117
  // private advertisementPlaying = false
117
118
 
119
+ private customAreaElements: Record<string, HTMLElement> = {}
120
+ private customAreaHandler?: (name: string, element: HTMLElement) => void
121
+
118
122
  private buttonsColor: string | null = null
119
123
 
120
124
  private currentDurationValue: number = 0
@@ -155,8 +159,6 @@ export class MediaControl extends UICorePlugin {
155
159
 
156
160
  private verticalVolume = false
157
161
 
158
- private $audioTracksSelector: ZeptoResult | null = null
159
-
160
162
  private $clipText: ZeptoResult | null = null
161
163
 
162
164
  private $clipTextContainer: ZeptoResult | null = null
@@ -167,8 +169,6 @@ export class MediaControl extends UICorePlugin {
167
169
 
168
170
  private $multiCameraSelector: ZeptoResult | null = null
169
171
 
170
- private $pip: ZeptoResult | null = null
171
-
172
172
  private $playPauseToggle: ZeptoResult | null = null
173
173
 
174
174
  private $playStopToggle: ZeptoResult | null = null
@@ -740,9 +740,13 @@ export class MediaControl extends UICorePlugin {
740
740
  if (this.core.activeContainer && this.core.activeContainer.isReady) {
741
741
  this.core.activeContainer.setVolume(value)
742
742
  } else {
743
- this.listenToOnce(this.core.activeContainer, Events.CONTAINER_READY, () => {
744
- this.core.activeContainer.setVolume(value)
745
- })
743
+ this.listenToOnce(
744
+ this.core.activeContainer,
745
+ Events.CONTAINER_READY,
746
+ () => {
747
+ this.core.activeContainer.setVolume(value)
748
+ },
749
+ )
746
750
  }
747
751
  }
748
752
 
@@ -815,10 +819,12 @@ export class MediaControl extends UICorePlugin {
815
819
  if (!this.$volumeBarContainer) {
816
820
  return
817
821
  }
822
+ if (this.hideVolumeId) {
823
+ clearTimeout(this.hideVolumeId)
824
+ }
818
825
  if (this.draggingVolumeBar) {
819
826
  this.hideVolumeId = setTimeout(() => this.hideVolumeBar(), timeout)
820
827
  } else {
821
- this.hideVolumeId && clearTimeout(this.hideVolumeId)
822
828
  this.hideVolumeId = setTimeout(
823
829
  () => this.$volumeBarContainer?.addClass('volume-bar-hide'),
824
830
  timeout,
@@ -1025,16 +1031,7 @@ export class MediaControl extends UICorePlugin {
1025
1031
  }
1026
1032
 
1027
1033
  // actual order of the items appear rendered is controlled by CSS
1028
- newSettings.right = [
1029
- 'fullscreen',
1030
- 'pip',
1031
- 'gear',
1032
- 'cc',
1033
- 'multicamera',
1034
- 'playbackrate',
1035
- 'vr',
1036
- 'audiotracks',
1037
- ]
1034
+ newSettings.right = DEFAULT_SETTINGS.right
1038
1035
 
1039
1036
  if (
1040
1037
  (!this.fullScreenOnVideoTagSupported &&
@@ -1140,31 +1137,40 @@ export class MediaControl extends UICorePlugin {
1140
1137
  }
1141
1138
  }
1142
1139
 
1143
- putElement(name: MediaControlElement, element: HTMLElement) {
1140
+ putElement(name: MediaControlElement, element: ZeptoResult) {
1144
1141
  const panel = this.getElementLocation(name)
1145
1142
  trace(`${T} putElement`, { name, panel: !!panel })
1146
1143
  if (panel) {
1147
1144
  const current = panel.find(`[data-${name}]`)
1148
- element.setAttribute(`data-${name}`, '')
1145
+ element.attr(`data-${name}`, '')
1149
1146
  // TODO test
1150
1147
  if (current.length) {
1151
- if (current[0] === element) {
1148
+ if (current[0] === element[0]) {
1152
1149
  return
1153
1150
  }
1154
1151
  current.replaceWith(element)
1155
1152
  } else {
1156
1153
  panel.append(element)
1157
1154
  }
1155
+ return
1158
1156
  }
1159
1157
  }
1160
1158
 
1159
+ handleCustomArea(handler: (name: string, content: HTMLElement) => void) {
1160
+ this.customAreaHandler = handler
1161
+ Object.entries(this.customAreaElements).forEach(([name, element]) => {
1162
+ handler(name, element)
1163
+ })
1164
+ this.customAreaElements = {}
1165
+ }
1166
+
1161
1167
  /**
1162
1168
  * Toggle the visibility of a media control element
1163
1169
  * @param name - The name of the media control element
1164
1170
  * @param show - Whether to show or hide the element
1165
1171
  */
1166
- toggleElement(name: MediaControlElement, show: boolean) {
1167
- this.$el.find(`[data-${name}]`).toggle(show)
1172
+ toggleElement(area: MediaControlElement, show: boolean) {
1173
+ this.$el.find(`[data-${area}]`).toggle(show)
1168
1174
  }
1169
1175
 
1170
1176
  private getRightPanel() {
@@ -1356,6 +1362,7 @@ export class MediaControl extends UICorePlugin {
1356
1362
  * @internal
1357
1363
  */
1358
1364
  override render() {
1365
+ trace(`${T} render`)
1359
1366
  const timeout = this.options.hideMediaControlDelay || 2000
1360
1367
 
1361
1368
  const html = MediaControl.template({ settings: this.settings ?? {} })
@@ -1417,6 +1424,7 @@ export class MediaControl extends UICorePlugin {
1417
1424
 
1418
1425
  this.rendered = true
1419
1426
  this.updateVolumeUI()
1427
+ // TODO setTimeout
1420
1428
  this.trigger(Events.MEDIACONTROL_RENDERED)
1421
1429
 
1422
1430
  return this
@@ -1505,6 +1513,12 @@ export class MediaControl extends UICorePlugin {
1505
1513
  }
1506
1514
 
1507
1515
  private getElementLocation(name: MediaControlElement) {
1516
+ trace(`${T} getElementLocation`, {
1517
+ name,
1518
+ right: this.settings.right,
1519
+ left: this.settings.left,
1520
+ default: this.settings.default,
1521
+ })
1508
1522
  if (this.settings.right?.includes(name)) {
1509
1523
  return this.getRightPanel()
1510
1524
  }