@gcorevideo/player 2.21.6 → 2.22.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 (71) 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/media-control.ejs +1 -1
  10. package/assets/playback-rate/list.ejs +5 -5
  11. package/dist/core.js +1 -2
  12. package/dist/index.css +652 -651
  13. package/dist/index.js +3850 -3766
  14. package/dist/player.d.ts +10 -17
  15. package/dist/plugins/index.css +742 -741
  16. package/dist/plugins/index.js +3951 -3868
  17. package/docs/api/player.mediacontrol.md +8 -36
  18. package/docs/api/player.mediacontrol.toggleelement.md +72 -0
  19. package/docs/api/player.mediacontrolelement.md +1 -1
  20. package/lib/playback/dash-playback/DashPlayback.d.ts.map +1 -1
  21. package/lib/playback/dash-playback/DashPlayback.js +0 -1
  22. package/lib/plugins/bottom-gear/BottomGear.d.ts +65 -14
  23. package/lib/plugins/bottom-gear/BottomGear.d.ts.map +1 -1
  24. package/lib/plugins/bottom-gear/BottomGear.js +113 -37
  25. package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.d.ts +2 -3
  26. package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.d.ts.map +1 -1
  27. package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.js +18 -15
  28. package/lib/plugins/dvr-controls/DvrControls.js +1 -1
  29. package/lib/plugins/level-selector/LevelSelector.d.ts +8 -11
  30. package/lib/plugins/level-selector/LevelSelector.d.ts.map +1 -1
  31. package/lib/plugins/level-selector/LevelSelector.js +66 -102
  32. package/lib/plugins/media-control/MediaControl.d.ts +7 -5
  33. package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
  34. package/lib/plugins/media-control/MediaControl.js +40 -20
  35. package/lib/plugins/picture-in-picture/PictureInPicture.d.ts.map +1 -1
  36. package/lib/plugins/picture-in-picture/PictureInPicture.js +7 -2
  37. package/lib/plugins/playback-rate/PlaybackRate.d.ts +42 -14
  38. package/lib/plugins/playback-rate/PlaybackRate.d.ts.map +1 -1
  39. package/lib/plugins/playback-rate/PlaybackRate.js +101 -83
  40. package/lib/plugins/subtitles/ClosedCaptions.js +1 -1
  41. package/lib/testUtils.d.ts +1 -0
  42. package/lib/testUtils.d.ts.map +1 -1
  43. package/lib/testUtils.js +13 -0
  44. package/package.json +1 -1
  45. package/src/playback/dash-playback/DashPlayback.ts +0 -1
  46. package/src/plugins/bottom-gear/BottomGear.ts +162 -72
  47. package/src/plugins/bottom-gear/__tests__/BottomGear.test.ts +21 -5
  48. package/src/plugins/bottom-gear/__tests__/__snapshots__/BottomGear.test.ts.snap +5 -12
  49. package/src/plugins/clappr-nerd-stats/ClapprNerdStats.ts +27 -25
  50. package/src/plugins/dvr-controls/DvrControls.ts +1 -1
  51. package/src/plugins/dvr-controls/__tests__/DvrControls.test.ts +6 -4
  52. package/src/plugins/dvr-controls/__tests__/__snapshots__/DvrControls.test.ts.snap +2 -2
  53. package/src/plugins/level-selector/LevelSelector.ts +80 -120
  54. package/src/plugins/level-selector/__tests__/LevelSelector.test.ts +69 -79
  55. package/src/plugins/level-selector/__tests__/__snapshots__/LevelSelector.test.ts.snap +38 -71
  56. package/src/plugins/media-control/MediaControl.ts +54 -26
  57. package/src/plugins/media-control/__tests__/MediaControl.test.ts +4 -4
  58. package/src/plugins/media-control/__tests__/__snapshots__/MediaControl.test.ts.snap +4 -0
  59. package/src/plugins/picture-in-picture/PictureInPicture.ts +7 -2
  60. package/src/plugins/playback-rate/PlaybackRate.ts +136 -108
  61. package/src/plugins/playback-rate/__tests__/PlaybackRate.test.ts +84 -37
  62. package/src/plugins/playback-rate/__tests__/__snapshots__/PlaybackRate.test.ts.snap +55 -6
  63. package/src/plugins/subtitles/ClosedCaptions.ts +1 -1
  64. package/src/plugins/subtitles/__tests__/ClosedCaptions.test.ts +1 -1
  65. package/src/testUtils.ts +14 -0
  66. package/src/typings/vitest.d.ts +1 -0
  67. package/temp/player.api.json +66 -94
  68. package/tsconfig.tsbuildinfo +1 -1
  69. package/docs/api/player.mediacontrol.getcenterpanel.md +0 -18
  70. package/docs/api/player.mediacontrol.getleftpanel.md +0 -22
  71. package/docs/api/player.mediacontrol.getrightpanel.md +0 -22
@@ -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,7 +66,16 @@ 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
  }
@@ -70,6 +83,7 @@ const DEFAULT_SETTINGS: MediaControlSettings = {
70
83
  /**
71
84
  * Custom events emitted by the plugins to communicate with one another
72
85
  * @beta
86
+ * @deprecated
73
87
  */
74
88
  export enum MediaControlEvents {
75
89
  /**
@@ -83,7 +97,6 @@ const T = 'plugins.media_control'
83
97
  const LEFT_ORDER = [
84
98
  'playpause',
85
99
  'playstop',
86
- // 'live',
87
100
  'dvr',
88
101
  'volume',
89
102
  'position',
@@ -115,6 +128,9 @@ type DisabledClickable = {
115
128
  export class MediaControl extends UICorePlugin {
116
129
  // private advertisementPlaying = false
117
130
 
131
+ private customAreaElements: Record<string, HTMLElement> = {}
132
+ private customAreaHandler?: (name: string, element: HTMLElement) => void
133
+
118
134
  private buttonsColor: string | null = null
119
135
 
120
136
  private currentDurationValue: number = 0
@@ -155,8 +171,6 @@ export class MediaControl extends UICorePlugin {
155
171
 
156
172
  private verticalVolume = false
157
173
 
158
- private $audioTracksSelector: ZeptoResult | null = null
159
-
160
174
  private $clipText: ZeptoResult | null = null
161
175
 
162
176
  private $clipTextContainer: ZeptoResult | null = null
@@ -167,8 +181,6 @@ export class MediaControl extends UICorePlugin {
167
181
 
168
182
  private $multiCameraSelector: ZeptoResult | null = null
169
183
 
170
- private $pip: ZeptoResult | null = null
171
-
172
184
  private $playPauseToggle: ZeptoResult | null = null
173
185
 
174
186
  private $playStopToggle: ZeptoResult | null = null
@@ -740,9 +752,13 @@ export class MediaControl extends UICorePlugin {
740
752
  if (this.core.activeContainer && this.core.activeContainer.isReady) {
741
753
  this.core.activeContainer.setVolume(value)
742
754
  } else {
743
- this.listenToOnce(this.core.activeContainer, Events.CONTAINER_READY, () => {
744
- this.core.activeContainer.setVolume(value)
745
- })
755
+ this.listenToOnce(
756
+ this.core.activeContainer,
757
+ Events.CONTAINER_READY,
758
+ () => {
759
+ this.core.activeContainer.setVolume(value)
760
+ },
761
+ )
746
762
  }
747
763
  }
748
764
 
@@ -805,7 +821,9 @@ export class MediaControl extends UICorePlugin {
805
821
  }
806
822
 
807
823
  private showVolumeBar() {
808
- this.hideVolumeId && clearTimeout(this.hideVolumeId)
824
+ if (this.hideVolumeId) {
825
+ clearTimeout(this.hideVolumeId)
826
+ }
809
827
  this.$volumeBarContainer?.removeClass('volume-bar-hide')
810
828
  }
811
829
 
@@ -813,10 +831,12 @@ export class MediaControl extends UICorePlugin {
813
831
  if (!this.$volumeBarContainer) {
814
832
  return
815
833
  }
834
+ if (this.hideVolumeId) {
835
+ clearTimeout(this.hideVolumeId)
836
+ }
816
837
  if (this.draggingVolumeBar) {
817
838
  this.hideVolumeId = setTimeout(() => this.hideVolumeBar(), timeout)
818
839
  } else {
819
- this.hideVolumeId && clearTimeout(this.hideVolumeId)
820
840
  this.hideVolumeId = setTimeout(
821
841
  () => this.$volumeBarContainer?.addClass('volume-bar-hide'),
822
842
  timeout,
@@ -1023,16 +1043,7 @@ export class MediaControl extends UICorePlugin {
1023
1043
  }
1024
1044
 
1025
1045
  // actual order of the items appear rendered is controlled by CSS
1026
- newSettings.right = [
1027
- 'fullscreen',
1028
- 'pip',
1029
- 'gear',
1030
- 'cc',
1031
- 'multicamera',
1032
- 'playbackrate',
1033
- 'vr',
1034
- 'audiotracks',
1035
- ]
1046
+ newSettings.right = DEFAULT_SETTINGS.right
1036
1047
 
1037
1048
  if (
1038
1049
  (!this.fullScreenOnVideoTagSupported &&
@@ -1138,31 +1149,40 @@ export class MediaControl extends UICorePlugin {
1138
1149
  }
1139
1150
  }
1140
1151
 
1141
- putElement(name: MediaControlElement, element: HTMLElement) {
1152
+ putElement(name: MediaControlElement, element: ZeptoResult) {
1142
1153
  const panel = this.getElementLocation(name)
1143
1154
  trace(`${T} putElement`, { name, panel: !!panel })
1144
1155
  if (panel) {
1145
1156
  const current = panel.find(`[data-${name}]`)
1146
- element.setAttribute(`data-${name}`, '')
1157
+ element.attr(`data-${name}`, '')
1147
1158
  // TODO test
1148
1159
  if (current.length) {
1149
- if (current[0] === element) {
1160
+ if (current[0] === element[0]) {
1150
1161
  return
1151
1162
  }
1152
1163
  current.replaceWith(element)
1153
1164
  } else {
1154
1165
  panel.append(element)
1155
1166
  }
1167
+ return
1156
1168
  }
1157
1169
  }
1158
1170
 
1171
+ handleCustomArea(handler: (name: string, content: HTMLElement) => void) {
1172
+ this.customAreaHandler = handler
1173
+ Object.entries(this.customAreaElements).forEach(([name, element]) => {
1174
+ handler(name, element)
1175
+ })
1176
+ this.customAreaElements = {}
1177
+ }
1178
+
1159
1179
  /**
1160
1180
  * Toggle the visibility of a media control element
1161
1181
  * @param name - The name of the media control element
1162
1182
  * @param show - Whether to show or hide the element
1163
1183
  */
1164
- toggleElement(name: MediaControlElement, show: boolean) {
1165
- this.$el.find(`[data-${name}]`).toggle(show)
1184
+ toggleElement(area: MediaControlElement, show: boolean) {
1185
+ this.$el.find(`[data-${area}]`).toggle(show)
1166
1186
  }
1167
1187
 
1168
1188
  private getRightPanel() {
@@ -1354,6 +1374,7 @@ export class MediaControl extends UICorePlugin {
1354
1374
  * @internal
1355
1375
  */
1356
1376
  override render() {
1377
+ trace(`${T} render`)
1357
1378
  const timeout = this.options.hideMediaControlDelay || 2000
1358
1379
 
1359
1380
  const html = MediaControl.template({ settings: this.settings ?? {} })
@@ -1415,6 +1436,7 @@ export class MediaControl extends UICorePlugin {
1415
1436
 
1416
1437
  this.rendered = true
1417
1438
  this.updateVolumeUI()
1439
+ // TODO setTimeout
1418
1440
  this.trigger(Events.MEDIACONTROL_RENDERED)
1419
1441
 
1420
1442
  return this
@@ -1503,6 +1525,12 @@ export class MediaControl extends UICorePlugin {
1503
1525
  }
1504
1526
 
1505
1527
  private getElementLocation(name: MediaControlElement) {
1528
+ trace(`${T} getElementLocation`, {
1529
+ name,
1530
+ right: this.settings.right,
1531
+ left: this.settings.left,
1532
+ default: this.settings.default,
1533
+ })
1506
1534
  if (this.settings.right?.includes(name)) {
1507
1535
  return this.getRightPanel()
1508
1536
  }
@@ -2,7 +2,7 @@ import { describe, it, expect, vi, beforeEach } from 'vitest'
2
2
  import { MediaControl, MediaControlElement } from '../MediaControl'
3
3
  import { createMockCore } from '../../../testUtils'
4
4
  import { LogTracer, Logger, setTracer } from '@gcorevideo/utils'
5
- import { Events, Playback } from '@clappr/core'
5
+ import { $, Events, Playback } from '@clappr/core'
6
6
 
7
7
  Logger.enable('*')
8
8
  setTracer(new LogTracer('MediaControl.test'))
@@ -60,7 +60,7 @@ describe('MediaControl', () => {
60
60
  const element = document.createElement('div')
61
61
  element.className = 'my-media-control'
62
62
  element.textContent = 'test'
63
- mediaControl.putElement(mcName, element)
63
+ mediaControl.putElement(mcName, $(element))
64
64
 
65
65
  expect(mediaControl.el.innerHTML).toMatchSnapshot()
66
66
  expect(mediaControl.$el.find('.media-control-right-panel .my-media-control').length).toEqual(1)
@@ -90,7 +90,7 @@ describe('MediaControl', () => {
90
90
  const element = document.createElement('div')
91
91
  element.className = 'my-dvr-controls'
92
92
  element.textContent = 'live'
93
- mediaControl.putElement('dvr', element)
93
+ mediaControl.putElement('dvr', $(element))
94
94
  expect(mediaControl.el.innerHTML).toMatchSnapshot()
95
95
  expect(mediaControl.$el.find('.media-control-left-panel .my-dvr-controls').length).toEqual(1)
96
96
  })
@@ -100,7 +100,7 @@ describe('MediaControl', () => {
100
100
  const element = document.createElement('div')
101
101
  element.className = 'my-dvr-controls'
102
102
  element.textContent = 'live'
103
- mediaControl.putElement('dvr', element)
103
+ mediaControl.putElement('dvr', $(element))
104
104
  expect(mediaControl.el.innerHTML).toMatchSnapshot()
105
105
  expect(mediaControl.$el.find('.media-control-left-panel .my-dvr-controls').length).toEqual(0)
106
106
  })
@@ -193,6 +193,8 @@ exports[`MediaControl > updateSettings > dvr > when disabled > should disable DV
193
193
 
194
194
  <div class="media-control-left-panel" data-media-control="">
195
195
 
196
+ <button type="button" class="media-control-button media-control-icon gcore-skin-button-color paused" data-playpause="" aria-label="playpause">/assets/icons/new/play.svg</button>
197
+
196
198
  <div class="drawer-container" data-volume="">
197
199
  <div class="drawer-icon-container" data-volume="">
198
200
  <div class="drawer-icon media-control-icon gcore-skin-button-color" data-volume="">/assets/icons/new/volume-max.svg</div>
@@ -255,6 +257,8 @@ exports[`MediaControl > updateSettings > dvr > when enabled > should enable DVR
255
257
 
256
258
  <div class="media-control-left-panel" data-media-control="">
257
259
 
260
+ <button type="button" class="media-control-button media-control-icon gcore-skin-button-color paused" data-playpause="" aria-label="playpause">/assets/icons/new/play.svg</button>
261
+
258
262
  <div class="drawer-container" data-volume="">
259
263
  <div class="drawer-icon-container" data-volume="">
260
264
  <div class="drawer-icon media-control-icon gcore-skin-button-color" data-volume="">/assets/icons/new/volume-max.svg</div>
@@ -6,6 +6,7 @@ import { CLAPPR_VERSION } from '../../build.js';
6
6
  import pipIcon from '../../../assets/icons/new/pip.svg';
7
7
  import buttonHtml from '../../../assets/picture-in-picture/button.ejs';
8
8
  import '../../../assets/picture-in-picture/button.scss';
9
+ import assert from 'assert';
9
10
 
10
11
  const VERSION = '0.0.1';
11
12
 
@@ -68,7 +69,11 @@ export class PictureInPicture extends UICorePlugin {
68
69
  * @internal
69
70
  */
70
71
  override bindEvents() {
71
- this.listenTo(this.core.mediaControl, Events.MEDIACONTROL_RENDERED, this.render);
72
+ this.listenToOnce(this.core, Events.CORE_READY, () => {
73
+ const mediaControl = this.core.getPlugin('media_control');
74
+ assert(mediaControl, 'media_control plugin is required');
75
+ this.listenTo(mediaControl, Events.MEDIACONTROL_RENDERED, this.render);
76
+ });
72
77
  }
73
78
 
74
79
  private isPiPSupported() {
@@ -92,7 +97,7 @@ export class PictureInPicture extends UICorePlugin {
92
97
 
93
98
  const mediaControl = this.core.getPlugin('media_control');
94
99
  if (mediaControl) {
95
- mediaControl.putElement('pip', this.el);
100
+ mediaControl.putElement('pip', this.$el);
96
101
  }
97
102
 
98
103
  return this;