@gcorevideo/player 2.20.9 → 2.20.12

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 (236) hide show
  1. package/assets/dvr-controls/dvr_controls.scss +0 -2
  2. package/dist/core.js +5 -5
  3. package/dist/index.css +1521 -1524
  4. package/dist/index.js +101 -106
  5. package/dist/player.d.ts +141 -100
  6. package/dist/plugins/index.css +1376 -1379
  7. package/dist/plugins/index.js +96 -102
  8. package/docs/api/player.audioselector.md +1 -1
  9. package/docs/api/player.bigmutebutton.md +1 -1
  10. package/docs/api/player.bottomgear.md +1 -1
  11. package/docs/api/player.clapprnerdstats.md +1 -1
  12. package/docs/api/player.clapprstats.md +1 -1
  13. package/docs/api/player.clicktopause.md +1 -1
  14. package/docs/api/player.clipsplugin.md +1 -1
  15. package/docs/api/player.containerpluginconstructor.md +3 -5
  16. package/docs/api/player.containersize.md +0 -3
  17. package/docs/api/player.contextmenu.md +1 -1
  18. package/docs/api/player.contextmenupluginsettings.md +1 -1
  19. package/docs/api/player.corepluginconstructor.md +3 -5
  20. package/docs/api/player.dashsettings.md +0 -3
  21. package/docs/api/player.dvrcontrols.md +2 -35
  22. package/docs/api/player.errorlevel.md +0 -3
  23. package/docs/api/player.errorscreen.md +1 -1
  24. package/docs/api/player.favicon.md +4 -174
  25. package/docs/api/{player.favicon.disable.md → player.faviconpluginsettings.faviconcolor.md} +5 -7
  26. package/docs/api/{player.dvrcontrols._constructor_.md → player.faviconpluginsettings.md} +17 -8
  27. package/docs/api/player.googleanalytics.md +1 -1
  28. package/docs/api/player.langtag.md +0 -3
  29. package/docs/api/player.levelselector.md +1 -1
  30. package/docs/api/player.logo.md +1 -1
  31. package/docs/api/player.md +82 -82
  32. package/docs/api/{player.favicon.configure.md → player.mediacontrol.getcenterpanel.md} +4 -4
  33. package/docs/api/{player.favicon.destroy.md → player.mediacontrol.getleftpanel.md} +8 -4
  34. package/docs/api/player.mediacontrol.md +30 -2
  35. package/docs/api/player.multicamera.md +1 -1
  36. package/docs/api/player.pictureinpicture.md +1 -1
  37. package/docs/api/player.playbackerror.code.md +0 -3
  38. package/docs/api/player.playbackerror.description.md +0 -3
  39. package/docs/api/player.playbackerror.level.md +0 -3
  40. package/docs/api/player.playbackerror.md +8 -11
  41. package/docs/api/player.playbackerror.message.md +0 -3
  42. package/docs/api/player.playbackerror.origin.md +0 -3
  43. package/docs/api/player.playbackerror.scope.md +0 -3
  44. package/docs/api/player.playbackerror.ui.md +1 -3
  45. package/docs/api/player.playbackerrorcode.md +3 -6
  46. package/docs/api/player.playbackmodule.md +0 -3
  47. package/docs/api/player.playbackrate.md +1 -1
  48. package/docs/api/player.playbacktype.md +1 -4
  49. package/docs/api/player.player._constructor_.md +0 -3
  50. package/docs/api/player.player.attachto.md +0 -3
  51. package/docs/api/player.player.configure.md +0 -3
  52. package/docs/api/player.player.destroy.md +0 -3
  53. package/docs/api/player.player.getcurrenttime.md +0 -3
  54. package/docs/api/player.player.getduration.md +0 -3
  55. package/docs/api/player.player.getvolume.md +0 -3
  56. package/docs/api/player.player.isdvrenabled.md +0 -3
  57. package/docs/api/player.player.isdvrinuse.md +0 -3
  58. package/docs/api/player.player.ismuted.md +0 -3
  59. package/docs/api/player.player.isplaying.md +0 -3
  60. package/docs/api/player.player.md +25 -28
  61. package/docs/api/player.player.mute.md +0 -3
  62. package/docs/api/player.player.off.md +0 -3
  63. package/docs/api/player.player.on.md +0 -3
  64. package/docs/api/player.player.pause.md +0 -3
  65. package/docs/api/player.player.play.md +0 -3
  66. package/docs/api/player.player.registerplugin.md +0 -3
  67. package/docs/api/player.player.resize.md +0 -3
  68. package/docs/api/player.player.seek.md +0 -3
  69. package/docs/api/player.player.setvolume.md +0 -3
  70. package/docs/api/player.player.stop.md +0 -3
  71. package/docs/api/player.player.unmute.md +0 -3
  72. package/docs/api/player.player.unregisterplugin.md +14 -7
  73. package/docs/api/player.playercomponenttype.md +0 -3
  74. package/docs/api/player.playerconfig.autoplay.md +0 -3
  75. package/docs/api/player.playerconfig.dash.md +0 -3
  76. package/docs/api/player.playerconfig.debug.md +0 -3
  77. package/docs/api/player.playerconfig.language.md +0 -3
  78. package/docs/api/player.playerconfig.loop.md +0 -3
  79. package/docs/api/player.playerconfig.md +10 -13
  80. package/docs/api/player.playerconfig.mute.md +0 -3
  81. package/docs/api/player.playerconfig.playbacktype.md +0 -3
  82. package/docs/api/player.playerconfig.prioritytransport.md +0 -3
  83. package/docs/api/player.playerconfig.sources.md +0 -3
  84. package/docs/api/player.playerconfig.strings.md +0 -3
  85. package/docs/api/player.playerdebugsettings.md +0 -3
  86. package/docs/api/player.playerdebugtag.md +0 -3
  87. package/docs/api/player.playerevent.md +11 -14
  88. package/docs/api/player.playereventhandler.md +0 -3
  89. package/docs/api/player.playereventparams.md +0 -3
  90. package/docs/api/player.playermediasource.md +0 -3
  91. package/docs/api/player.playermediasourcedesc.md +2 -5
  92. package/docs/api/player.playermediasourcedesc.mimetype.md +0 -3
  93. package/docs/api/player.playermediasourcedesc.source.md +0 -3
  94. package/docs/api/player.playerplugin.md +0 -4
  95. package/docs/api/player.playerpluginconstructor.md +0 -3
  96. package/docs/api/player.poster.md +1 -1
  97. package/docs/api/player.qualitylevel.bitrate.md +0 -3
  98. package/docs/api/player.qualitylevel.height.md +0 -3
  99. package/docs/api/player.qualitylevel.level.md +0 -3
  100. package/docs/api/player.qualitylevel.md +4 -7
  101. package/docs/api/player.qualitylevel.width.md +0 -3
  102. package/docs/api/player.seektime.md +1 -1
  103. package/docs/api/player.share.md +1 -1
  104. package/docs/api/player.skiptime.md +1 -1
  105. package/docs/api/player.sourcecontroller.md +1 -1
  106. package/docs/api/player.spinnerthreebounce.md +1 -1
  107. package/docs/api/player.subtitles.md +1 -1
  108. package/docs/api/player.telemetry.md +1 -1
  109. package/docs/api/player.thumbnails.md +1 -1
  110. package/docs/api/player.timeposition.current.md +0 -3
  111. package/docs/api/player.timeposition.md +2 -5
  112. package/docs/api/player.timeposition.total.md +0 -3
  113. package/docs/api/player.timevalue.md +0 -3
  114. package/docs/api/player.translationkey.md +0 -3
  115. package/docs/api/player.translationsettings.md +0 -3
  116. package/docs/api/player.transportpreference.md +2 -7
  117. package/docs/api/player.volumefade.md +1 -1
  118. package/lib/Player.d.ts +5 -5
  119. package/lib/Player.js +2 -2
  120. package/lib/index.d.ts +18 -1
  121. package/lib/index.d.ts.map +1 -1
  122. package/lib/index.js +18 -1
  123. package/lib/playback.types.d.ts +8 -7
  124. package/lib/playback.types.d.ts.map +1 -1
  125. package/lib/playback.types.js +1 -1
  126. package/lib/plugins/audio-selector/AudioSelector.d.ts +1 -1
  127. package/lib/plugins/audio-selector/AudioSelector.js +1 -1
  128. package/lib/plugins/big-mute-button/BigMuteButton.d.ts +1 -1
  129. package/lib/plugins/big-mute-button/BigMuteButton.d.ts.map +1 -1
  130. package/lib/plugins/big-mute-button/BigMuteButton.js +1 -2
  131. package/lib/plugins/bottom-gear/BottomGear.d.ts +1 -1
  132. package/lib/plugins/bottom-gear/BottomGear.js +1 -1
  133. package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.d.ts +1 -1
  134. package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.js +1 -1
  135. package/lib/plugins/clappr-stats/ClapprStats.d.ts +1 -1
  136. package/lib/plugins/clappr-stats/ClapprStats.js +1 -1
  137. package/lib/plugins/click-to-pause/ClickToPause.d.ts +1 -1
  138. package/lib/plugins/click-to-pause/ClickToPause.js +1 -1
  139. package/lib/plugins/clips/Clips.d.ts +1 -1
  140. package/lib/plugins/clips/Clips.js +1 -1
  141. package/lib/plugins/context-menu/ContextMenu.d.ts +2 -2
  142. package/lib/plugins/context-menu/ContextMenu.js +1 -1
  143. package/lib/plugins/dvr-controls/DvrControls.d.ts +6 -4
  144. package/lib/plugins/dvr-controls/DvrControls.d.ts.map +1 -1
  145. package/lib/plugins/dvr-controls/DvrControls.js +28 -36
  146. package/lib/plugins/error-screen/ErrorScreen.d.ts +1 -18
  147. package/lib/plugins/error-screen/ErrorScreen.d.ts.map +1 -1
  148. package/lib/plugins/error-screen/ErrorScreen.js +1 -2
  149. package/lib/plugins/favicon/Favicon.d.ts +30 -3
  150. package/lib/plugins/favicon/Favicon.d.ts.map +1 -1
  151. package/lib/plugins/favicon/Favicon.js +28 -35
  152. package/lib/plugins/google-analytics/GoogleAnalytics.d.ts +1 -1
  153. package/lib/plugins/google-analytics/GoogleAnalytics.js +1 -1
  154. package/lib/plugins/level-selector/LevelSelector.d.ts +1 -1
  155. package/lib/plugins/level-selector/LevelSelector.js +1 -1
  156. package/lib/plugins/logo/Logo.d.ts +1 -1
  157. package/lib/plugins/logo/Logo.js +1 -1
  158. package/lib/plugins/media-control/MediaControl.d.ts +8 -2
  159. package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
  160. package/lib/plugins/media-control/MediaControl.js +15 -3
  161. package/lib/plugins/multi-camera/MultiCamera.d.ts +1 -1
  162. package/lib/plugins/multi-camera/MultiCamera.js +1 -1
  163. package/lib/plugins/picture-in-picture/PictureInPicture.d.ts +1 -1
  164. package/lib/plugins/picture-in-picture/PictureInPicture.js +1 -1
  165. package/lib/plugins/playback-rate/PlaybackRate.d.ts +1 -1
  166. package/lib/plugins/playback-rate/PlaybackRate.js +1 -1
  167. package/lib/plugins/poster/Poster.d.ts +1 -1
  168. package/lib/plugins/poster/Poster.js +1 -1
  169. package/lib/plugins/seek-time/SeekTime.d.ts +1 -1
  170. package/lib/plugins/seek-time/SeekTime.js +1 -1
  171. package/lib/plugins/share/Share.d.ts +1 -1
  172. package/lib/plugins/share/Share.js +1 -1
  173. package/lib/plugins/skip-time/SkipTime.d.ts +1 -1
  174. package/lib/plugins/skip-time/SkipTime.js +1 -1
  175. package/lib/plugins/source-controller/SourceController.d.ts +1 -1
  176. package/lib/plugins/source-controller/SourceController.js +1 -1
  177. package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.d.ts +1 -1
  178. package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.js +1 -1
  179. package/lib/plugins/subtitles/Subtitles.d.ts +1 -1
  180. package/lib/plugins/subtitles/Subtitles.js +1 -1
  181. package/lib/plugins/telemetry/Telemetry.d.ts +1 -1
  182. package/lib/plugins/telemetry/Telemetry.js +1 -1
  183. package/lib/plugins/thumbnails/Thumbnails.d.ts +1 -1
  184. package/lib/plugins/thumbnails/Thumbnails.js +1 -1
  185. package/lib/plugins/volume-fade/VolumeFade.d.ts +1 -1
  186. package/lib/plugins/volume-fade/VolumeFade.js +1 -1
  187. package/lib/testUtils.d.ts +11 -2
  188. package/lib/testUtils.d.ts.map +1 -1
  189. package/lib/testUtils.js +22 -3
  190. package/lib/types.d.ts +20 -25
  191. package/lib/types.d.ts.map +1 -1
  192. package/lib/types.js +1 -1
  193. package/package.json +1 -1
  194. package/src/Player.ts +5 -5
  195. package/src/index.ts +18 -1
  196. package/src/playback.types.ts +8 -7
  197. package/src/plugins/audio-selector/AudioSelector.ts +1 -1
  198. package/src/plugins/big-mute-button/BigMuteButton.ts +1 -2
  199. package/src/plugins/bottom-gear/BottomGear.ts +1 -1
  200. package/src/plugins/clappr-nerd-stats/ClapprNerdStats.ts +1 -1
  201. package/src/plugins/clappr-stats/ClapprStats.ts +1 -1
  202. package/src/plugins/click-to-pause/ClickToPause.ts +1 -1
  203. package/src/plugins/clips/Clips.ts +1 -1
  204. package/src/plugins/context-menu/ContextMenu.ts +2 -2
  205. package/src/plugins/dvr-controls/DvrControls.ts +33 -45
  206. package/src/plugins/dvr-controls/__tests__/DvrControls.test.ts +91 -0
  207. package/src/plugins/dvr-controls/__tests__/__snapshots__/DvrControls.test.ts.snap +43 -0
  208. package/src/plugins/error-screen/ErrorScreen.ts +3 -22
  209. package/src/plugins/favicon/Favicon.ts +38 -41
  210. package/src/plugins/google-analytics/GoogleAnalytics.ts +1 -1
  211. package/src/plugins/level-selector/LevelSelector.ts +1 -1
  212. package/src/plugins/logo/Logo.ts +1 -1
  213. package/src/plugins/media-control/MediaControl.ts +17 -3
  214. package/src/plugins/multi-camera/MultiCamera.ts +1 -1
  215. package/src/plugins/picture-in-picture/PictureInPicture.ts +1 -1
  216. package/src/plugins/playback-rate/PlaybackRate.ts +1 -1
  217. package/src/plugins/poster/Poster.ts +1 -1
  218. package/src/plugins/seek-time/SeekTime.ts +1 -1
  219. package/src/plugins/share/Share.ts +1 -1
  220. package/src/plugins/skip-time/SkipTime.ts +1 -1
  221. package/src/plugins/source-controller/SourceController.ts +1 -1
  222. package/src/plugins/spinner-three-bounce/SpinnerThreeBounce.ts +1 -1
  223. package/src/plugins/subtitles/Subtitles.ts +1 -1
  224. package/src/plugins/telemetry/Telemetry.ts +1 -1
  225. package/src/plugins/thumbnails/Thumbnails.ts +1 -1
  226. package/src/plugins/volume-fade/VolumeFade.ts +1 -1
  227. package/src/testUtils.ts +28 -4
  228. package/src/types.ts +20 -26
  229. package/temp/player.api.json +274 -455
  230. package/tsconfig.tsbuildinfo +1 -1
  231. package/docs/api/player.errordesc.md +0 -28
  232. package/docs/api/player.favicon._constructor_.md +0 -50
  233. package/docs/api/player.favicon.bindevents.md +0 -18
  234. package/docs/api/player.favicon.name.md +0 -14
  235. package/docs/api/player.favicon.supportedversion.md +0 -16
  236. package/docs/api/player.mediatransport.md +0 -16
@@ -6,11 +6,12 @@ import { CLAPPR_VERSION } from '../../build.js'
6
6
  import dvrHTML from '../../../assets/dvr-controls/index.ejs'
7
7
  import '../../../assets/dvr-controls/dvr_controls.scss'
8
8
  import { trace } from '@gcorevideo/utils'
9
+ import { MediaControl } from '../media-control/MediaControl.js'
9
10
 
10
11
  const T = 'plugins.dvr_controls'
11
12
 
12
13
  /**
13
- * PLUGIN that adds the DVR controls to the media control UI
14
+ * `PLUGIN` that adds the DVR controls to the media control UI
14
15
  *
15
16
  * @beta
16
17
  *
@@ -19,7 +20,9 @@ const T = 'plugins.dvr_controls'
19
20
  *
20
21
  * - {@link MediaControl}
21
22
  *
22
- * The plugin renders live stream indicator and the DVR seek bar, if DVR is enabled, in the media control UI.
23
+ * The plugin renders live stream indicator.
24
+ * If DVR is enabled, the indicator shows whether the current position is at the live edge of the stream or not.
25
+ * In the latter case, the indicator can be clicked to seek to the live edge.
23
26
  */
24
27
  export class DvrControls extends UICorePlugin {
25
28
  private static readonly template = template(dvrHTML)
@@ -57,15 +60,20 @@ export class DvrControls extends UICorePlugin {
57
60
  }
58
61
  }
59
62
 
60
- constructor(core: Core) {
61
- super(core)
62
- this.settingsUpdate()
63
- }
64
-
65
63
  /**
66
64
  * @internal
67
65
  */
68
66
  override bindEvents() {
67
+ this.listenTo(this.core, Events.CORE_READY, this.onCoreReady)
68
+ this.listenTo(this.core, Events.CORE_OPTIONS_CHANGE, this.render)
69
+ this.listenTo(
70
+ this.core,
71
+ Events.CORE_ACTIVE_CONTAINER_CHANGED,
72
+ this.bindContainerEvents,
73
+ )
74
+ }
75
+
76
+ private onCoreReady() {
69
77
  const mediaControl = this.core.getPlugin('media_control')
70
78
  assert(mediaControl, 'media_control plugin is required')
71
79
  this.listenTo(
@@ -73,12 +81,7 @@ export class DvrControls extends UICorePlugin {
73
81
  Events.MEDIACONTROL_RENDERED,
74
82
  this.settingsUpdate,
75
83
  )
76
- this.listenTo(this.core, Events.CORE_OPTIONS_CHANGE, this.render)
77
- this.listenTo(
78
- this.core,
79
- Events.CORE_ACTIVE_CONTAINER_CHANGED,
80
- this.bindContainerEvents,
81
- )
84
+ this.settingsUpdate()
82
85
  }
83
86
 
84
87
  private bindContainerEvents() {
@@ -94,57 +97,45 @@ export class DvrControls extends UICorePlugin {
94
97
  )
95
98
  }
96
99
 
97
- private onDvrChanged(dvrEnabled: boolean) {
100
+ private onDvrChanged(dvrInUse: boolean) {
98
101
  trace(`${T} onDvrChanged`, {
99
- dvrEnabled,
102
+ dvrInUse,
100
103
  })
101
104
  if (this.core.getPlaybackType() !== Playback.LIVE) {
102
105
  return
103
106
  }
104
- this.settingsUpdate()
105
- this.core.mediaControl.$el.addClass('live')
106
- if (dvrEnabled) {
107
- // TODO
108
- this.core.mediaControl.$el
107
+ this.render()
108
+ const mediaControl = this.core.getPlugin('media_control')
109
+ mediaControl.$el.addClass('live')
110
+ if (dvrInUse) {
111
+ mediaControl.$el
109
112
  .addClass('dvr')
110
113
  .find(
114
+ // TODO add API, test
111
115
  '.media-control-indicator[data-position], .media-control-indicator[data-duration]',
112
116
  )
113
117
  .hide()
114
118
  } else {
115
- this.core.mediaControl.$el.removeClass('dvr')
119
+ mediaControl.$el.removeClass('dvr')
116
120
  }
117
121
  }
118
122
 
119
123
  private click() {
120
- const mediaControl = this.core.getPlugin('media_control')
121
124
  const container = this.core.activeContainer
122
-
123
125
  if (!container.isPlaying()) {
124
126
  container.play()
125
127
  }
126
-
127
- if (mediaControl.$el.hasClass('dvr')) {
128
- container.seek(container.getDuration())
129
- }
128
+ container.seek(container.getDuration())
130
129
  }
131
130
 
132
131
  private settingsUpdate() {
133
- // @ts-ignore
134
- this.stopListening() // TODO sort out
135
- this.core.getPlugin('media_control').$el.removeClass('live') // TODO don't access directly
136
- if (this.shouldRender()) {
137
- this.render()
138
- this.$el.click(() => this.click())
139
- }
140
- this.bindEvents()
132
+ trace(`${T} settingsUpdate`)
133
+ this.core.getPlugin('media_control').$el.removeClass('live')
134
+ this.render()
141
135
  }
142
136
 
143
137
  private shouldRender() {
144
- const useDvrControls =
145
- this.core.options.useDvrControls === undefined ||
146
- !!this.core.options.useDvrControls
147
-
138
+ const useDvrControls = this.core.options.useDvrControls !== false
148
139
  return useDvrControls && this.core.getPlaybackType() === Playback.LIVE
149
140
  }
150
141
 
@@ -154,6 +145,7 @@ export class DvrControls extends UICorePlugin {
154
145
  override render() {
155
146
  trace(`${T} render`, {
156
147
  dvrEnabled: this.core.activePlayback?.dvrEnabled,
148
+ playbackType: this.core.getPlaybackType(),
157
149
  })
158
150
  if (!this.shouldRender()) {
159
151
  return this
@@ -164,13 +156,9 @@ export class DvrControls extends UICorePlugin {
164
156
  backToLive: this.core.i18n.t('back_to_live'),
165
157
  }),
166
158
  )
167
- const mediaControl = this.core.getPlugin('media_control')
168
- assert(mediaControl, 'media_control plugin is required')
169
- // TODO don't tap into the $el directly
159
+ const mediaControl = this.core.getPlugin('media_control') as MediaControl
170
160
  mediaControl.$el.addClass('live')
171
- mediaControl
172
- .$('.media-control-left-panel[data-media-control]')
173
- .append(this.$el)
161
+ mediaControl.getLeftPanel().append(this.$el)
174
162
 
175
163
  return this
176
164
  }
@@ -0,0 +1,91 @@
1
+ import { beforeEach, describe, expect, it, vi } from 'vitest'
2
+ import { DvrControls } from '../DvrControls.js'
3
+ import { createMockCore, createMockMediaControl } from '../../../testUtils.js'
4
+ // import { LogTracer, Logger, setTracer } from '@gcorevideo/utils'
5
+
6
+ // setTracer(new LogTracer('DvrControls.test'))
7
+ // Logger.enable('*')
8
+
9
+ describe('DvrControls', () => {
10
+ let core: any
11
+ let mediaControl: any
12
+ let plugins: Record<string, any> = {}
13
+ let dvrControls: DvrControls
14
+ beforeEach(() => {
15
+ core = createMockCore()
16
+ mediaControl = createMockMediaControl(core)
17
+ plugins = {
18
+ media_control: mediaControl,
19
+ }
20
+ core.getPlugin.mockImplementation((name: string) => plugins[name])
21
+ dvrControls = new DvrControls(core)
22
+ plugins.dvr_controls = dvrControls
23
+ })
24
+ describe('live stream', () => {
25
+ beforeEach(() => {
26
+ core.getPlaybackType.mockReturnValue('live')
27
+ })
28
+ describe.each([
29
+ ['no DVR', false, false, false],
30
+ ['DVR at live edge', true, false, false],
31
+ ['DVR behind live edge', true, true, true],
32
+ ])('%s', (_, dvrEnabled, dvrInUse, indicateDvr) => {
33
+ beforeEach(() => {
34
+ core.activePlayback.dvrEnabled = dvrEnabled
35
+ core.trigger('core:ready')
36
+ core.trigger('core:active:container:changed')
37
+ if (dvrInUse) {
38
+ core.activeContainer.trigger('container:dvr', true)
39
+ }
40
+ })
41
+ it('should render', () => {
42
+ expect(dvrControls.el.textContent).toBeTruthy()
43
+ expect(dvrControls.el.innerHTML).toMatchSnapshot()
44
+ })
45
+ it('should render to the media control left panel', () => {
46
+ expect(mediaControl.$el.find('.media-control-left-panel').text()).toContain('live')
47
+ expect(mediaControl.el.innerHTML).toMatchSnapshot()
48
+ })
49
+ it('should indicate live streaming mode', () => {
50
+ expect(mediaControl.$el.hasClass('live')).toBe(true)
51
+ })
52
+ if (indicateDvr) {
53
+ it('should indicate DVR mode', () => {
54
+ expect(mediaControl.$el.hasClass('dvr')).toBe(true)
55
+ })
56
+ } else {
57
+ it('should not indicate DVR mode', () => {
58
+ expect(mediaControl.$el.hasClass('dvr')).toBe(false)
59
+ })
60
+ }
61
+ })
62
+ describe('when back_to_live button is clicked', () => {
63
+ beforeEach(() => {
64
+ core.activePlayback.dvrEnabled = true
65
+ core.trigger('core:ready')
66
+ core.trigger('core:active:container:changed')
67
+ core.activeContainer.getDuration.mockReturnValue(180)
68
+ core.activeContainer.trigger('container:dvr', true)
69
+ dvrControls.$el.find('.live-button').click()
70
+ })
71
+ it('should call active container play', () => {
72
+ expect(core.activeContainer.play).toHaveBeenCalled()
73
+ })
74
+ it('should seek to live edge', () => {
75
+ expect(core.activeContainer.seek).toHaveBeenCalledWith(180)
76
+ })
77
+ })
78
+ })
79
+ describe('VOD stream', () => {
80
+ beforeEach(() => {
81
+ core.getPlaybackType.mockReturnValue('vod')
82
+ })
83
+ beforeEach(() => {
84
+ core.trigger('core:ready')
85
+ core.trigger('core:active:container:changed')
86
+ })
87
+ it('should not render', () => {
88
+ expect(dvrControls.el.textContent).toBeFalsy()
89
+ })
90
+ })
91
+ })
@@ -0,0 +1,43 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`DvrControls > live stream > DVR at live edge > should render 1`] = `
4
+ "<div class="live-info">live</div>
5
+ <button type="button" class="live-button" aria-label="back_to_live">back_to_live</button>
6
+ "
7
+ `;
8
+
9
+ exports[`DvrControls > live stream > DVR at live edge > should render to the media control left panel 1`] = `
10
+ "<div class="media-control-left-panel" data-media-control=""><div class="dvr-controls" data-dvr-controls=""><div class="live-info">live</div>
11
+ <button type="button" class="live-button" aria-label="back_to_live">back_to_live</button>
12
+ </div></div>
13
+ <div class="media-control-right-panel" data-media-control=""></div>
14
+ <div class="media-control-center-panel" data-media-control=""></div>"
15
+ `;
16
+
17
+ exports[`DvrControls > live stream > DVR behind live edge > should render 1`] = `
18
+ "<div class="live-info">live</div>
19
+ <button type="button" class="live-button" aria-label="back_to_live">back_to_live</button>
20
+ "
21
+ `;
22
+
23
+ exports[`DvrControls > live stream > DVR behind live edge > should render to the media control left panel 1`] = `
24
+ "<div class="media-control-left-panel" data-media-control=""><div class="dvr-controls" data-dvr-controls=""><div class="live-info">live</div>
25
+ <button type="button" class="live-button" aria-label="back_to_live">back_to_live</button>
26
+ </div></div>
27
+ <div class="media-control-right-panel" data-media-control=""></div>
28
+ <div class="media-control-center-panel" data-media-control=""></div>"
29
+ `;
30
+
31
+ exports[`DvrControls > live stream > no DVR > should render 1`] = `
32
+ "<div class="live-info">live</div>
33
+ <button type="button" class="live-button" aria-label="back_to_live">back_to_live</button>
34
+ "
35
+ `;
36
+
37
+ exports[`DvrControls > live stream > no DVR > should render to the media control left panel 1`] = `
38
+ "<div class="media-control-left-panel" data-media-control=""><div class="dvr-controls" data-dvr-controls=""><div class="live-info">live</div>
39
+ <button type="button" class="live-button" aria-label="back_to_live">back_to_live</button>
40
+ </div></div>
41
+ <div class="media-control-right-panel" data-media-control=""></div>
42
+ <div class="media-control-center-panel" data-media-control=""></div>"
43
+ `;
@@ -6,25 +6,7 @@ import { CLAPPR_VERSION } from '../../build.js'
6
6
  import reloadIcon from '../../../assets/icons/old/reload.svg'
7
7
  import templateHtml from '../../../assets/error-screen/error_screen.ejs'
8
8
  import '../../../assets/error-screen/error_screen.scss'
9
- import { PlaybackErrorCode } from '../../playback.types.js'
10
-
11
- /**
12
- * An error fired in the player and plugins code to be handled in the UI
13
- * @beta
14
- */
15
- export type ErrorDesc = {
16
- description: string
17
- level: string
18
- code: string
19
- origin: string
20
- scope: string
21
- raw?: string
22
- UI?: {
23
- icon?: string
24
- title: string
25
- message: string
26
- }
27
- }
9
+ import { PlaybackError } from '../../playback.types.js'
28
10
 
29
11
  type ErrorScreenDesc = {
30
12
  title: string
@@ -47,7 +29,7 @@ export type ErrorScreenPluginSettings = {
47
29
  const T = 'plugins.error_screen'
48
30
 
49
31
  /**
50
- * PLUGIN that displays errors nicely in the overlay on top of the player.
32
+ * `PLUGIN` that displays errors nicely in the overlay on top of the player.
51
33
  * @beta
52
34
  */
53
35
  export class ErrorScreen extends UICorePlugin {
@@ -142,7 +124,7 @@ export class ErrorScreen extends UICorePlugin {
142
124
  }
143
125
  }
144
126
 
145
- private onError(err: ErrorDesc) {
127
+ private onError(err: PlaybackError) {
146
128
  trace(`${T} onError`, { err })
147
129
  if (err.UI) {
148
130
  if (this.err) {
@@ -172,7 +154,6 @@ export class ErrorScreen extends UICorePlugin {
172
154
  }),
173
155
  )
174
156
 
175
- // TODO append to container instead of core?
176
157
  if (!this.el.parentElement) {
177
158
  this.core.$el.append(this.el)
178
159
  }
@@ -10,15 +10,23 @@ import stopIcon from '../../../assets/icons/new/stop.svg';
10
10
  const FAVICON_COLOR = '#567';
11
11
  const FAVICON_SELECTOR = 'link[rel="shortcut icon"]';
12
12
 
13
- // const oldIcon = $(FAVICON_SELECTOR);
13
+ /**
14
+ * @beta
15
+ */
16
+ export interface FaviconPluginSettings {
17
+ /**
18
+ * CSS color of the favicon.
19
+ */
20
+ faviconColor?: string;
21
+ }
14
22
 
15
23
  /**
16
- * The plugin adds custom favicon to the player's tab.
24
+ * `PLUGIN` that changes the favicon according to the player's state.
17
25
  * @beta
26
+ * @remarks
27
+ * There are three states: stopped, playing and paused.
18
28
  */
19
29
  export class Favicon extends CorePlugin {
20
- private _container: Container | null = null;
21
-
22
30
  private oldIcon: ZeptoResult;
23
31
 
24
32
  private playIcon: ZeptoResult | null = null;
@@ -27,18 +35,23 @@ export class Favicon extends CorePlugin {
27
35
 
28
36
  private stopIcon: ZeptoResult | null = null;
29
37
 
38
+ /**
39
+ * @internal
40
+ */
30
41
  get name() {
31
42
  return 'favicon';
32
43
  }
33
44
 
45
+ /**
46
+ * @internal
47
+ */
34
48
  get supportedVersion() {
35
49
  return { min: CLAPPR_VERSION };
36
50
  }
37
51
 
38
- // get oldIcon() {
39
- // return oldIcon;
40
- // }
41
-
52
+ /**
53
+ * @internal
54
+ */
42
55
  constructor(core: Core) {
43
56
  super(core);
44
57
  this.oldIcon = $(FAVICON_SELECTOR);
@@ -46,45 +59,35 @@ export class Favicon extends CorePlugin {
46
59
  this.stopIcon = this.createIcon(stopIcon);
47
60
  this.changeIcon(this.stopIcon);
48
61
  }
49
- this.configure();
50
- }
51
-
52
- configure() {
53
- if (this.core.options.changeFavicon) {
54
- if (!this.enabled) {
55
- // @ts-ignore
56
- this.stopListening(this.core, Events.CORE_OPTIONS_CHANGE);
57
- this.enable();
58
- }
59
- } else if (this.enabled) {
60
- this.disable();
61
- this.listenTo(this.core, Events.CORE_OPTIONS_CHANGE, this.configure);
62
- }
63
62
  }
64
63
 
64
+ /**
65
+ * @internal
66
+ */
65
67
  override bindEvents() {
66
- this.listenTo(this.core, Events.CORE_OPTIONS_CHANGE, this.configure);
67
68
  this.listenTo(this.core, Events.CORE_ACTIVE_CONTAINER_CHANGED, this.containerChanged);
68
- this.core.activeContainer && this.containerChanged();
69
69
  }
70
70
 
71
71
  private containerChanged() {
72
- // @ts-ignore
73
- this._container && this.stopListening(this._container);
74
- this._container = this.core.activeContainer;
75
- this.listenTo(this._container, Events.CONTAINER_PLAY, this.setPlayIcon);
76
- this.listenTo(this._container, Events.CONTAINER_PAUSE, this.setPauseIcon);
77
- this.listenTo(this._container, Events.CONTAINER_STOP, this.resetIcon);
78
- this.listenTo(this._container, Events.CONTAINER_ENDED, this.resetIcon);
79
- this.listenTo(this._container, Events.CONTAINER_ERROR, this.resetIcon);
72
+ this.listenTo(this.core.activeContainer, Events.CONTAINER_PLAY, this.setPlayIcon);
73
+ this.listenTo(this.core.activeContainer, Events.CONTAINER_PAUSE, this.setPauseIcon);
74
+ this.listenTo(this.core.activeContainer, Events.CONTAINER_STOP, this.resetIcon);
75
+ this.listenTo(this.core.activeContainer, Events.CONTAINER_ENDED, this.resetIcon);
76
+ this.listenTo(this.core.activeContainer, Events.CONTAINER_ERROR, this.resetIcon);
80
77
  this.resetIcon();
81
78
  }
82
79
 
80
+ /**
81
+ * @internal
82
+ */
83
83
  override disable() {
84
84
  super.disable();
85
85
  this.resetIcon();
86
86
  }
87
87
 
88
+ /**
89
+ * @internal
90
+ */
88
91
  override destroy() {
89
92
  super.destroy();
90
93
  this.resetIcon();
@@ -113,7 +116,6 @@ export class Favicon extends CorePlugin {
113
116
  if (!this.playIcon) {
114
117
  this.playIcon = this.createIcon(playIcon);
115
118
  }
116
-
117
119
  this.changeIcon(this.playIcon);
118
120
  }
119
121
 
@@ -121,21 +123,16 @@ export class Favicon extends CorePlugin {
121
123
  if (!this.pauseIcon) {
122
124
  this.pauseIcon = this.createIcon(pauseIcon);
123
125
  }
124
-
125
126
  this.changeIcon(this.pauseIcon);
126
127
  }
127
128
 
128
129
  private resetIcon() {
129
- $(FAVICON_SELECTOR).remove();
130
130
  const icon = this.oldIcon.length > 0 ? this.oldIcon : this.stopIcon;
131
-
132
131
  this.changeIcon(icon);
133
132
  }
134
133
 
135
- private changeIcon(icon: ZeptoResult | null) {
136
- if (icon) {
137
- $('link[rel="shortcut icon"]').remove();
138
- $('head').append(icon);
139
- }
134
+ private changeIcon(icon: ZeptoResult) {
135
+ $('link[rel="shortcut icon"]').remove();
136
+ $('head').append(icon);
140
137
  }
141
138
  }
@@ -11,7 +11,7 @@ declare const _gaq: {
11
11
  };
12
12
 
13
13
  /**
14
- * An example Google Analytics integration plugin
14
+ * `PLUGIN` that integrates with Google Analytics
15
15
  * @beta
16
16
  */
17
17
  export class GoogleAnalytics extends ContainerPlugin {
@@ -40,7 +40,7 @@ export interface LevelSelectorPluginSettings {
40
40
  }
41
41
 
42
42
  /**
43
- * PLUGIN that provides a UI to select the desired quality level of the playback.
43
+ * `PLUGIN` that provides a UI to select the desired quality level of the playback.
44
44
  * @beta
45
45
  *
46
46
  * @remarks
@@ -21,7 +21,7 @@ type LogoOptions = {
21
21
  };
22
22
 
23
23
  /**
24
- * The plugin adds custom logo to the player.
24
+ * `PLUGIN` that adds custom logo to the player.
25
25
  * @beta
26
26
  */
27
27
  export class Logo extends UIContainerPlugin {
@@ -1,6 +1,8 @@
1
+ // This is a derived work from the {@link https://github.com/clappr/clappr-plugins/tree/ffaa9d27005fa5a8a7c243ffc47eb5655b84b371/src/plugins/media_control | Clappr MediaControl plugin}
2
+ // It is redistributed under the terms of the {@link ../../../../../LICENSE | Apache 2.0} license.
1
3
  // Copyright 2014 Globo.com Player authors. All rights reserved.
2
4
  // Use of this source code is governed by a BSD-style
3
- // license that can be found in the LICENSE file.
5
+ // license that can be found in the {@link https://github.com/clappr/clappr-plugins/blob/master/LICENSE | LICENSE}.
4
6
 
5
7
  import assert from 'assert'
6
8
  import {
@@ -88,11 +90,11 @@ type DisabledClickable = {
88
90
  }
89
91
 
90
92
  /**
91
- * PLUGIN that provides a foundation for developing custom media controls UI.
93
+ * `PLUGIN` that provides a foundation for developing custom media controls UI.
92
94
  * @beta
93
95
  * @remarks
94
96
  * The methods exposed are to be used by the other plugins that extend the media control UI.
95
- * The plugin registration should be arranged so that MediaControl is initialized before every other plugin that depends on it.
97
+ * The plugin registration should be arranged so that MediaControl is initialized before every other `PLUGIN` that depends on it.
96
98
  * @example
97
99
  * ```ts
98
100
  * Player.registerPlugin(MediaControl) // <--- This must go first
@@ -1132,6 +1134,18 @@ export class MediaControl extends UICorePlugin {
1132
1134
  return this.$el.find('.media-control-right-panel')
1133
1135
  }
1134
1136
 
1137
+ /**
1138
+ * Get the left panel area to append custom elements to
1139
+ * @returns ZeptoSelector of the left panel element
1140
+ */
1141
+ getLeftPanel() {
1142
+ return this.$el.find('.media-control-left-panel')
1143
+ }
1144
+
1145
+ getCenterPanel() {
1146
+ return this.$el.find('.media-control-center-panel')
1147
+ }
1148
+
1135
1149
  private resetIndicators() {
1136
1150
  assert.ok(
1137
1151
  this.$duration && this.$position,
@@ -26,7 +26,7 @@ const VERSION = '0.0.1';
26
26
  const T = 'plugins.multicamera';
27
27
 
28
28
  /**
29
- * PLUGIN that adds support for loading multiple streams and switching between them using the media control UI.
29
+ * `PLUGIN` that adds support for loading multiple streams and switching between them using the media control UI.
30
30
  * @beta
31
31
  */
32
32
  export class MultiCamera extends UICorePlugin {
@@ -12,7 +12,7 @@ const VERSION = '0.0.1';
12
12
  const T = `plugins.pip`;
13
13
 
14
14
  /**
15
- * Enables picture in picture mode.
15
+ * `PLUGIN` that enables picture in picture mode.
16
16
  * @beta
17
17
  * @remarks
18
18
  * Depends on:
@@ -35,7 +35,7 @@ const DEFAULT_PLAYBACK_RATE = '1.0';
35
35
  const T = 'plugins.playback_rate';
36
36
 
37
37
  /**
38
- * PLUGIN that allows changing the playback speed of the video.
38
+ * `PLUGIN` that allows changing the playback speed of the video.
39
39
  * @beta
40
40
  *
41
41
  * @remarks
@@ -24,7 +24,7 @@ import { PlaybackError } from '../../playback.types.js'
24
24
  const T = 'plugins.poster'
25
25
 
26
26
  /**
27
- * Displays a poster image in the background and a big play button on top when playback is stopped
27
+ * `PLUGIN` that displays a poster image in the background and a big play button on top when playback is stopped
28
28
  * @beta
29
29
  * @remarks
30
30
  * When the playback is stopped, media control UI is disabled.
@@ -14,7 +14,7 @@ import { ZeptoResult } from '../../types.js';
14
14
  const { formatTime } = Utils;
15
15
 
16
16
  /**
17
- * The plugin adds a seek time indicator to the media control UI.
17
+ * `PLUGIN` that adds a seek time indicator to the media control UI.
18
18
  * @beta
19
19
  */
20
20
  export class SeekTime extends UICorePlugin {
@@ -10,7 +10,7 @@ import fbIcon from '../../../assets/icons/old/fb.svg';
10
10
  import twIcon from '../../../assets/icons/old/twitter.svg';
11
11
 
12
12
  /**
13
- * PLUGIN that adds a share button to the media control UI.
13
+ * `PLUGIN` that adds a share button to the media control UI.
14
14
  * @beta
15
15
  */
16
16
  export class Share extends UICorePlugin {
@@ -8,7 +8,7 @@ import '../../../assets/skip-time/style.scss';
8
8
  type Position = 'mid' | 'left' | 'right';
9
9
 
10
10
  /**
11
- * PLUGIN that adds skip controls to the media control UI.
11
+ * `PLUGIN` that adds skip controls to the media control UI.
12
12
  * @beta
13
13
  */
14
14
  export class SkipTime extends UICorePluginOriginal {
@@ -27,7 +27,7 @@ function noSync(cb: () => void) {
27
27
  }
28
28
 
29
29
  /**
30
- * This plugin is responsible for managing the automatic failover between sources.
30
+ * `PLUGIN` that is responsible for managing the automatic failover between sources.
31
31
  * @beta
32
32
  * @remarks
33
33
  * Have a look at the {@link https://miro.com/app/board/uXjVLiN15tY=/?share_link_id=390327585787 | source failover diagram} for the details
@@ -31,7 +31,7 @@ export enum SpinnerEvents {
31
31
  }
32
32
 
33
33
  /**
34
- * PLUGIN that shows a pending operation indicator when playback is buffering or in a similar state
34
+ * `PLUGIN` that shows a pending operation indicator when playback is buffering or in a similar state
35
35
  * @beta
36
36
  * @remarks
37
37
  * Events emitted- {@link SpinnerEvents}
@@ -34,7 +34,7 @@ type TextTrackInfo = {
34
34
  const NO_TRACK = { language: 'off' }
35
35
 
36
36
  /**
37
- * A {@link MediaControl | media control} plugin that provides a UI to select the subtitles when available.
37
+ * `PLUGIN` that provides a UI to select the subtitles when available.
38
38
  * @beta
39
39
  *
40
40
  * @remarks