@gcorevideo/player 2.22.17 → 2.22.20

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 (120) hide show
  1. package/assets/audio-selector/track-selector.ejs +3 -3
  2. package/assets/bottom-gear/bottomgear.ejs +3 -3
  3. package/assets/clappr-nerd-stats/clappr-nerd-stats.ejs +76 -78
  4. package/assets/clappr-nerd-stats/clappr-nerd-stats.scss +10 -7
  5. package/assets/dvr-controls/dvr_controls.scss +0 -12
  6. package/dist/core.js +5 -7
  7. package/dist/index.css +1245 -1251
  8. package/dist/index.js +425 -261
  9. package/dist/player.d.ts +121 -108
  10. package/dist/plugins/index.css +577 -583
  11. package/dist/plugins/index.js +355 -187
  12. package/docs/api/player.bitratetrackrecord.md +20 -0
  13. package/docs/api/player.clapprstats.exportmetrics.md +2 -2
  14. package/docs/api/player.clapprstats.md +0 -4
  15. package/docs/api/player.clapprstatschronograph.md +115 -0
  16. package/docs/api/player.clapprstatscounter.md +211 -0
  17. package/docs/api/player.clapprstatsevents.md +51 -0
  18. package/docs/api/player.clapprstatsmetrics.md +52 -0
  19. package/docs/api/player.clipspluginsettings.md +1 -1
  20. package/docs/api/player.md +57 -2
  21. package/docs/api/player.nerdstats.md +3 -3
  22. package/docs/api/player.playerconfig.md +1 -1
  23. package/docs/api/player.playerconfig.playbacktype.md +6 -1
  24. package/docs/api/player.timeupdate.md +6 -3
  25. package/lib/playback/dash-playback/DashPlayback.d.ts +0 -1
  26. package/lib/playback/dash-playback/DashPlayback.d.ts.map +1 -1
  27. package/lib/playback/dash-playback/DashPlayback.js +4 -5
  28. package/lib/playback/hls-playback/HlsPlayback.d.ts +1 -1
  29. package/lib/playback/hls-playback/HlsPlayback.d.ts.map +1 -1
  30. package/lib/playback/hls-playback/HlsPlayback.js +0 -1
  31. package/lib/playback.types.d.ts +2 -3
  32. package/lib/playback.types.d.ts.map +1 -1
  33. package/lib/plugins/audio-selector/AudioSelector.d.ts +1 -1
  34. package/lib/plugins/audio-selector/AudioSelector.d.ts.map +1 -1
  35. package/lib/plugins/audio-selector/AudioSelector.js +15 -8
  36. package/lib/plugins/bottom-gear/BottomGear.d.ts +1 -1
  37. package/lib/plugins/bottom-gear/BottomGear.js +2 -2
  38. package/lib/plugins/clappr-nerd-stats/NerdStats.d.ts +17 -14
  39. package/lib/plugins/clappr-nerd-stats/NerdStats.d.ts.map +1 -1
  40. package/lib/plugins/clappr-nerd-stats/NerdStats.js +175 -124
  41. package/lib/plugins/clappr-nerd-stats/formatter.d.ts +5 -0
  42. package/lib/plugins/clappr-nerd-stats/formatter.d.ts.map +1 -1
  43. package/lib/plugins/clappr-nerd-stats/formatter.js +56 -24
  44. package/lib/plugins/clappr-nerd-stats/speedtest/index.d.ts +2 -2
  45. package/lib/plugins/clappr-nerd-stats/speedtest/index.d.ts.map +1 -1
  46. package/lib/plugins/clappr-nerd-stats/speedtest/types.d.ts +1 -1
  47. package/lib/plugins/clappr-nerd-stats/speedtest/types.d.ts.map +1 -1
  48. package/lib/plugins/clappr-nerd-stats/types.d.ts +3 -0
  49. package/lib/plugins/clappr-nerd-stats/types.d.ts.map +1 -1
  50. package/lib/plugins/clappr-nerd-stats/utils.d.ts +7 -0
  51. package/lib/plugins/clappr-nerd-stats/utils.d.ts.map +1 -0
  52. package/lib/plugins/clappr-nerd-stats/utils.js +67 -0
  53. package/lib/plugins/clappr-stats/ClapprStats.d.ts +5 -2
  54. package/lib/plugins/clappr-stats/ClapprStats.d.ts.map +1 -1
  55. package/lib/plugins/clappr-stats/ClapprStats.js +31 -33
  56. package/lib/plugins/clappr-stats/types.d.ts +21 -22
  57. package/lib/plugins/clappr-stats/types.d.ts.map +1 -1
  58. package/lib/plugins/clappr-stats/types.js +22 -22
  59. package/lib/plugins/clappr-stats/utils.d.ts +2 -2
  60. package/lib/plugins/clappr-stats/utils.d.ts.map +1 -1
  61. package/lib/plugins/clappr-stats/utils.js +0 -1
  62. package/lib/plugins/click-to-pause/ClickToPause.js +1 -1
  63. package/lib/plugins/clips/Clips.d.ts +1 -1
  64. package/lib/plugins/dvr-controls/DvrControls.d.ts +6 -2
  65. package/lib/plugins/dvr-controls/DvrControls.d.ts.map +1 -1
  66. package/lib/plugins/dvr-controls/DvrControls.js +39 -27
  67. package/lib/plugins/media-control/MediaControl.d.ts +6 -2
  68. package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
  69. package/lib/plugins/media-control/MediaControl.js +20 -9
  70. package/lib/plugins/picture-in-picture/PictureInPicture.js +1 -1
  71. package/lib/plugins/seek-time/SeekTime.d.ts +1 -1
  72. package/lib/plugins/seek-time/SeekTime.d.ts.map +1 -1
  73. package/lib/plugins/seek-time/SeekTime.js +3 -4
  74. package/lib/plugins/subtitles/ClosedCaptions.js +1 -1
  75. package/lib/plugins/vast-ads/VastAds.js +1 -1
  76. package/lib/plugins/vast-ads/rollmanager.js +1 -1
  77. package/lib/testUtils.d.ts.map +1 -1
  78. package/lib/testUtils.js +7 -4
  79. package/lib/types.d.ts +1 -1
  80. package/package.json +3 -3
  81. package/src/playback/__tests__/HTML5Video.test.ts +2 -2
  82. package/src/playback/dash-playback/DashPlayback.ts +5 -7
  83. package/src/playback/hls-playback/HlsPlayback.ts +2 -4
  84. package/src/playback.types.ts +2 -3
  85. package/src/plugins/audio-selector/AudioSelector.ts +14 -7
  86. package/src/plugins/audio-selector/__tests__/AudioSelector.test.ts +8 -8
  87. package/src/plugins/audio-selector/__tests__/__snapshots__/AudioSelector.test.ts.snap +15 -15
  88. package/src/plugins/bottom-gear/BottomGear.ts +2 -2
  89. package/src/plugins/bottom-gear/__tests__/BottomGear.test.ts +8 -5
  90. package/src/plugins/bottom-gear/__tests__/__snapshots__/BottomGear.test.ts.snap +3 -3
  91. package/src/plugins/clappr-nerd-stats/NerdStats.ts +216 -143
  92. package/src/plugins/clappr-nerd-stats/formatter.ts +91 -47
  93. package/src/plugins/clappr-nerd-stats/speedtest/index.ts +2 -2
  94. package/src/plugins/clappr-nerd-stats/speedtest/types.ts +1 -1
  95. package/src/plugins/clappr-nerd-stats/types.ts +43 -3
  96. package/src/plugins/clappr-nerd-stats/utils.ts +75 -0
  97. package/src/plugins/clappr-stats/ClapprStats.ts +41 -40
  98. package/src/plugins/clappr-stats/__tests__/ClapprStats.test.ts +12 -12
  99. package/src/plugins/clappr-stats/types.ts +43 -44
  100. package/src/plugins/clappr-stats/utils.ts +4 -5
  101. package/src/plugins/click-to-pause/ClickToPause.ts +1 -1
  102. package/src/plugins/clips/Clips.ts +1 -1
  103. package/src/plugins/clips/__tests__/Clips.test.ts +1 -1
  104. package/src/plugins/clips/__tests__/__snapshots__/Clips.test.ts.snap +1 -1
  105. package/src/plugins/dvr-controls/DvrControls.ts +51 -37
  106. package/src/plugins/dvr-controls/__tests__/DvrControls.test.ts +84 -26
  107. package/src/plugins/dvr-controls/__tests__/__snapshots__/DvrControls.test.ts.snap +0 -12
  108. package/src/plugins/media-control/MediaControl.ts +21 -9
  109. package/src/plugins/media-control/__tests__/MediaControl.test.ts +8 -5
  110. package/src/plugins/media-control/__tests__/__snapshots__/MediaControl.test.ts.snap +20 -20
  111. package/src/plugins/picture-in-picture/PictureInPicture.ts +1 -1
  112. package/src/plugins/seek-time/SeekTime.ts +4 -5
  113. package/src/plugins/subtitles/ClosedCaptions.ts +1 -1
  114. package/src/plugins/subtitles/__tests__/ClosedCaptions.test.ts +1 -1
  115. package/src/plugins/vast-ads/VastAds.ts +1 -1
  116. package/src/plugins/vast-ads/rollmanager.ts +1 -1
  117. package/src/testUtils.ts +11 -5
  118. package/src/types.ts +1 -1
  119. package/temp/player.api.json +630 -12
  120. package/tsconfig.tsbuildinfo +1 -1
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @beta
3
3
  */
4
- export enum Chronograph {
4
+ export enum ClapprStatsChronograph {
5
5
  Startup = 'startup',
6
6
  Watch = 'watch',
7
7
  Pause = 'pause',
@@ -13,7 +13,7 @@ export enum Chronograph {
13
13
  /**
14
14
  * @beta
15
15
  */
16
- export enum Counter {
16
+ export enum ClapprStatsCounter {
17
17
  Play = 'play',
18
18
  Pause = 'pause',
19
19
  Error = 'error',
@@ -30,26 +30,26 @@ export enum Counter {
30
30
  /**
31
31
  * @beta
32
32
  */
33
- export type Metrics = {
33
+ export type ClapprStatsMetrics = {
34
34
  /**
35
35
  * Events count counters
36
36
  */
37
37
  counters: {
38
38
  /**
39
- *
39
+ *
40
40
  */
41
- [Counter.Play]: number;
42
- [Counter.Pause]: number;
43
- [Counter.Error]: number;
44
- [Counter.Buffering]: number;
45
- [Counter.DecodedFrames]: number;
46
- [Counter.DroppedFrames]: number;
47
- [Counter.Fps]: number;
48
- [Counter.ChangeLevel]: number;
49
- [Counter.Seek]: number;
50
- [Counter.Fullscreen]: number;
51
- [Counter.DvrUsage]: number;
52
- };
41
+ [ClapprStatsCounter.Play]: number
42
+ [ClapprStatsCounter.Pause]: number
43
+ [ClapprStatsCounter.Error]: number
44
+ [ClapprStatsCounter.Buffering]: number
45
+ [ClapprStatsCounter.DecodedFrames]: number
46
+ [ClapprStatsCounter.DroppedFrames]: number
47
+ [ClapprStatsCounter.Fps]: number
48
+ [ClapprStatsCounter.ChangeLevel]: number
49
+ [ClapprStatsCounter.Seek]: number
50
+ [ClapprStatsCounter.Fullscreen]: number
51
+ [ClapprStatsCounter.DvrUsage]: number
52
+ }
53
53
  /**
54
54
  * Time measurements - accumulated duration of time-based activities
55
55
  */
@@ -57,44 +57,43 @@ export type Metrics = {
57
57
  /**
58
58
  * Time spent in the startup phase
59
59
  */
60
- [Chronograph.Startup]: number;
60
+ [ClapprStatsChronograph.Startup]: number
61
61
  /**
62
62
  * Total time spent in the watch phase
63
63
  */
64
- [Chronograph.Watch]: number;
64
+ [ClapprStatsChronograph.Watch]: number
65
65
  /**
66
- *
66
+ *
67
67
  */
68
- [Chronograph.Pause]: number;
69
- [Chronograph.Buffering]: number;
70
- [Chronograph.Session]: number;
68
+ [ClapprStatsChronograph.Pause]: number
69
+ [ClapprStatsChronograph.Buffering]: number
70
+ [ClapprStatsChronograph.Session]: number
71
71
  // [Chronograph.Latency]: number;
72
- };
72
+ }
73
73
  extra: {
74
- playbackName: string;
75
- playbackType: string;
76
- bitratesHistory: BitrateTrackRecord[];
77
- bitrateWeightedMean: number;
78
- bitrateMostUsed: number;
79
- buffersize: number;
80
- watchHistory: Array<[number, number]>;
81
- watchedPercentage: number;
82
- bufferingPercentage: number;
83
- bandwidth: number;
84
- duration: number;
85
- currentTime: number;
86
- };
87
- custom: Record<string, unknown>;
88
- };
74
+ playbackName: string
75
+ playbackType: string
76
+ bitratesHistory: ClapprStatsBitrateTrack[]
77
+ bitrateWeightedMean: number
78
+ bitrateMostUsed: number
79
+ buffersize: number
80
+ watchHistory: Array<[number, number]>
81
+ watchedPercentage: number
82
+ bufferingPercentage: number
83
+ bandwidth: number
84
+ duration: number
85
+ currentTime: number
86
+ }
87
+ }
89
88
 
90
89
  /**
91
90
  * @beta
92
91
  */
93
- export type BitrateTrackRecord = {
94
- start: number;
95
- end?: number;
96
- time?: number;
97
- bitrate: number;
92
+ export type ClapprStatsBitrateTrack = {
93
+ start: number
94
+ end?: number
95
+ time?: number
96
+ bitrate: number
98
97
  }
99
98
 
100
99
  /**
@@ -109,4 +108,4 @@ export enum ClapprStatsEvents {
109
108
  * Emitted when the playback reaches a certain percentage of the total duration.
110
109
  */
111
110
  // PERCENTAGE = 'clappr:stats:percentage',
112
- }
111
+ }
@@ -1,6 +1,6 @@
1
- import type { Metrics } from "./types";
1
+ import type { ClapprStatsMetrics } from './types'
2
2
 
3
- export function newMetrics(): Metrics {
3
+ export function newMetrics(): ClapprStatsMetrics {
4
4
  return {
5
5
  counters: {
6
6
  play: 0,
@@ -36,6 +36,5 @@ export function newMetrics(): Metrics {
36
36
  duration: 0,
37
37
  currentTime: 0,
38
38
  },
39
- custom: {},
40
- };
41
- }
39
+ }
40
+ }
@@ -25,7 +25,7 @@ export class ClickToPause extends ContainerPlugin {
25
25
  * @internal
26
26
  */
27
27
  get name() {
28
- return 'click_to_pause_custom'
28
+ return 'click_to_pause'
29
29
  }
30
30
 
31
31
  /**
@@ -12,7 +12,7 @@ import clipsHTML from '../../../assets/clips/clips.ejs'
12
12
  const T = 'plugins.clips'
13
13
 
14
14
  /**
15
- * Configuration options for the {@link ClipsPlugin} plugin.
15
+ * Configuration options for the {@link Clips} plugin.
16
16
  * @beta
17
17
  */
18
18
  export interface ClipsPluginSettings {
@@ -8,7 +8,7 @@ import { Events } from '@clappr/core'
8
8
  // Logger.enable('*')
9
9
  // setTracer(new LogTracer('Clips.text'))
10
10
 
11
- describe('ClipsPlugin', () => {
11
+ describe('Clips', () => {
12
12
  let core: any
13
13
  let mediaControl: any
14
14
  let clips: Clips
@@ -1,6 +1,6 @@
1
1
  // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
2
 
3
- exports[`ClipsPlugin > should render indicator 1`] = `
3
+ exports[`Clips > should render indicator 1`] = `
4
4
  "<div class="media-clip-text" id="clips-text">Introduction</div><svg width="0" height="0">
5
5
  <defs>
6
6
  <clipPath id="myClip">
@@ -1,14 +1,14 @@
1
- import { Core, Events, Playback, UICorePlugin, template } from '@clappr/core'
1
+ import { Events, Playback, UICorePlugin, template } from '@clappr/core'
2
2
  import assert from 'assert'
3
3
 
4
4
  import { CLAPPR_VERSION } from '../../build.js'
5
5
 
6
6
  import dvrHTML from '../../../assets/dvr-controls/index.ejs'
7
7
  import '../../../assets/dvr-controls/dvr_controls.scss'
8
- import { trace } from '@gcorevideo/utils'
8
+ // import { trace } from '@gcorevideo/utils'
9
9
  import { MediaControl } from '../media-control/MediaControl.js'
10
10
 
11
- const T = 'plugins.dvr_controls'
11
+ // const T = 'plugins.dvr_controls'
12
12
 
13
13
  /**
14
14
  * `PLUGIN` that adds the DVR controls to the media control UI
@@ -63,11 +63,11 @@ export class DvrControls extends UICorePlugin {
63
63
  * @internal
64
64
  */
65
65
  override bindEvents() {
66
- this.listenTo(this.core, Events.CORE_READY, this.onCoreReady)
66
+ this.listenToOnce(this.core, Events.CORE_READY, this.onCoreReady)
67
67
  this.listenTo(
68
68
  this.core,
69
69
  Events.CORE_ACTIVE_CONTAINER_CHANGED,
70
- this.bindContainerEvents,
70
+ this.onActiveContainerChanged,
71
71
  )
72
72
  }
73
73
 
@@ -75,21 +75,19 @@ export class DvrControls extends UICorePlugin {
75
75
  const mediaControl = this.core.getPlugin('media_control')
76
76
  assert(mediaControl, 'media_control plugin is required')
77
77
 
78
- this.listenTo(
79
- mediaControl,
80
- Events.MEDIACONTROL_RENDERED,
81
- this.render,
82
- )
83
- // MediaControl has been rendered
84
- this.render()
78
+ this.listenTo(mediaControl, Events.MEDIACONTROL_RENDERED, this.mount)
85
79
  }
86
80
 
87
- private bindContainerEvents() {
88
- trace(`${T} bindContainerEvents`)
89
- this.listenToOnce(
81
+ private onActiveContainerChanged() {
82
+ this.listenTo(
90
83
  this.core.activeContainer,
91
- Events.CONTAINER_TIMEUPDATE,
92
- this.render,
84
+ Events.CONTAINER_LOADEDMETADATA,
85
+ this.onMetadataLoaded,
86
+ )
87
+ this.listenTo(
88
+ this.core.activeContainer,
89
+ Events.CONTAINER_PLAYBACKDVRSTATECHANGED,
90
+ this.onDvrStateChanged,
93
91
  )
94
92
  }
95
93
 
@@ -101,36 +99,52 @@ export class DvrControls extends UICorePlugin {
101
99
  container.seek(container.getDuration())
102
100
  }
103
101
 
104
- private shouldRender() {
105
- return this.core.getPlaybackType() === Playback.LIVE
106
- }
107
-
108
102
  /**
109
103
  * @internal
110
104
  */
111
105
  override render() {
112
- trace(`${T} render`, {
113
- dvrEnabled: this.core.activePlayback?.dvrEnabled,
114
- playbackType: this.core.getPlaybackType(),
115
- })
116
- const mediaControl = this.core.getPlugin('media_control') as MediaControl
117
- if (!mediaControl) {
118
- return this
119
- }
120
- if (!this.shouldRender()) {
121
- return this
122
- }
123
-
124
- mediaControl.toggleElement('duration', false)
125
- mediaControl.toggleElement('position', false)
126
-
127
106
  this.$el.html(
128
107
  DvrControls.template({
129
108
  i18n: this.core.i18n,
130
109
  }),
131
110
  )
132
- mediaControl.putElement('dvr', this.$el)
133
111
 
134
112
  return this
135
113
  }
114
+
115
+ private onMediacontrolRendered() {
116
+ this.render()
117
+ }
118
+
119
+ private onMetadataLoaded() {
120
+ this.mount()
121
+ this.toggleState(this.core.activeContainer.isDvrInUse())
122
+ }
123
+
124
+ private mount() {
125
+ // TODO move mount point management logic to MediaControl
126
+ if (this.core.getPlaybackType() !== Playback.LIVE) {
127
+ return
128
+ }
129
+ const mediaControl = this.core.getPlugin('media_control') as MediaControl
130
+ assert(mediaControl, 'media_control plugin is required')
131
+ // TODO -> to MediaControl
132
+ mediaControl.toggleElement('duration', false)
133
+ mediaControl.toggleElement('position', false)
134
+ mediaControl.mount('dvr', this.$el)
135
+ }
136
+
137
+ private onDvrStateChanged(dvrInUse: boolean) {
138
+ this.toggleState(dvrInUse)
139
+ }
140
+
141
+ private toggleState(dvrInUse: boolean) {
142
+ if (dvrInUse) {
143
+ this.$el.find('#media-control-back-to-live').show()
144
+ this.$el.find('#media-control-live').hide()
145
+ } else {
146
+ this.$el.find('#media-control-back-to-live').hide()
147
+ this.$el.find('#media-control-live').show()
148
+ }
149
+ }
136
150
  }
@@ -20,11 +20,30 @@ describe('DvrControls', () => {
20
20
  }
21
21
  core.getPlugin.mockImplementation((name: string) => plugins[name])
22
22
  dvrControls = new DvrControls(core)
23
- plugins.dvr_controls = dvrControls
23
+ core.emit(Events.CORE_READY)
24
+ mediaControl.trigger(Events.MEDIACONTROL_RENDERED)
25
+ core.trigger(Events.CORE_ACTIVE_CONTAINER_CHANGED, core.activeContainer)
26
+ })
27
+ describe('basically', () => {
28
+ it('should render', () => {
29
+ expect(dvrControls.el.innerHTML).toMatchSnapshot()
30
+ expect(dvrControls.el.textContent).toMatch(/\blive\b/)
31
+ expect(dvrControls.el.textContent).toMatch(/\bback_to_live\b/)
32
+ })
33
+ })
34
+ describe('while playback type is unknown', () => {
35
+ it('should not mount', () => {
36
+ expect(mediaControl.mount).not.toHaveBeenCalledWith(
37
+ 'dvr',
38
+ dvrControls.$el,
39
+ )
40
+ })
24
41
  })
25
42
  describe('live stream', () => {
26
43
  beforeEach(() => {
27
44
  core.getPlaybackType.mockReturnValue('live')
45
+ core.activeContainer.getPlaybackType.mockReturnValue('live')
46
+ core.activePlayback.getPlaybackType.mockReturnValue('live')
28
47
  })
29
48
  describe.each([
30
49
  ['no DVR', false, false, false],
@@ -33,36 +52,75 @@ describe('DvrControls', () => {
33
52
  beforeEach(() => {
34
53
  core.activePlayback.dvrEnabled = dvrEnabled
35
54
  core.activeContainer.isDvrEnabled.mockReturnValue(dvrEnabled)
36
- core.trigger(Events.CORE_READY)
37
- core.trigger(Events.CORE_ACTIVE_CONTAINER_CHANGED, core.activeContainer)
55
+ core.activePlayback.emit(Events.PLAYBACK_LOADEDMETADATA)
56
+ core.activeContainer.emit(Events.CONTAINER_LOADEDMETADATA)
38
57
  if (dvrInUse) {
39
58
  core.activePlayback.dvrInUse = true
40
59
  core.activeContainer.isDvrInUse.mockReturnValue(true)
41
- core.activeContainer.emit(Events.CONTAINER_PLAYBACKDVRSTATECHANGED, true)
60
+ core.activeContainer.emit(
61
+ Events.CONTAINER_PLAYBACKDVRSTATECHANGED,
62
+ true,
63
+ )
42
64
  }
43
65
  })
44
- it('should render', () => {
45
- expect(dvrControls.el.textContent).toBeTruthy()
46
- expect(dvrControls.el.innerHTML).toMatchSnapshot()
47
- })
66
+ // TODO let the media control itself handle this
48
67
  it('should hide duration and position indicators', () => {
49
- expect(mediaControl.toggleElement).toHaveBeenCalledWith('duration', false)
50
- expect(mediaControl.toggleElement).toHaveBeenCalledWith('position', false)
68
+ expect(mediaControl.toggleElement).toHaveBeenCalledWith(
69
+ 'duration',
70
+ false,
71
+ )
72
+ expect(mediaControl.toggleElement).toHaveBeenCalledWith(
73
+ 'position',
74
+ false,
75
+ )
51
76
  })
52
- it('should render to the media control', () => {
53
- expect(mediaControl.putElement).toHaveBeenCalledWith('dvr', dvrControls.$el)
77
+ it('should mount to the media control', () => {
78
+ expect(mediaControl.mount).toHaveBeenCalledWith('dvr', dvrControls.$el)
54
79
  })
80
+ if (dvrEnabled) {
81
+ if (dvrInUse) {
82
+ it('should show back_to_live button', () => {
83
+ expect(
84
+ dvrControls.$el
85
+ .find('#media-control-back-to-live')
86
+ .css('display'),
87
+ ).not.toBe('none')
88
+ })
89
+ it('should hide live inficator', () => {
90
+ expect(
91
+ dvrControls.$el.find('#media-control-live').css('display'),
92
+ ).toBe('none')
93
+ })
94
+ } else {
95
+ it('should show live inficator', () => {
96
+ expect(
97
+ dvrControls.$el.find('#media-control-live').css('display'),
98
+ ).not.toBe('none')
99
+ })
100
+ it('should hide back_to_live button', () => {
101
+ expect(
102
+ dvrControls.$el
103
+ .find('#media-control-back-to-live')
104
+ .css('display'),
105
+ ).toBe('none')
106
+ })
107
+ }
108
+ }
55
109
  })
56
110
  describe('when back_to_live button is clicked', () => {
57
111
  beforeEach(() => {
58
112
  core.activePlayback.dvrEnabled = true
59
- core.trigger('core:ready')
60
- core.trigger('core:active:container:changed')
113
+ core.activeContainer.isDvrEnabled.mockReturnValue(true)
114
+ core.activePlayback.emit(Events.PLAYBACK_LOADEDMETADATA)
115
+ core.activeContainer.emit(Events.CONTAINER_LOADEDMETADATA)
61
116
  core.activeContainer.getDuration.mockReturnValue(180)
62
- core.activeContainer.trigger('container:dvr', true)
63
- dvrControls.$el.find('.live-button').click()
117
+ core.activeContainer.emit(
118
+ Events.CONTAINER_PLAYBACKDVRSTATECHANGED,
119
+ true,
120
+ )
121
+ dvrControls.$el.find('#media-control-back-to-live').click()
64
122
  })
65
- it('should call active container play', () => {
123
+ it('should play stream', () => {
66
124
  expect(core.activeContainer.play).toHaveBeenCalled()
67
125
  })
68
126
  it('should seek to live edge', () => {
@@ -70,20 +128,20 @@ describe('DvrControls', () => {
70
128
  })
71
129
  })
72
130
  })
73
- describe('basically', () => {
131
+ describe('VOD stream', () => {
74
132
  beforeEach(() => {
75
133
  core.getPlaybackType.mockReturnValue(Playback.VOD)
76
134
  core.activeContainer.getPlaybackType.mockReturnValue(Playback.VOD)
77
135
  core.activePlayback.getPlaybackType.mockReturnValue(Playback.VOD)
136
+ core.activePlayback.emit(Events.PLAYBACK_LOADEDMETADATA)
137
+ core.activeContainer.emit(Events.CONTAINER_LOADEDMETADATA)
78
138
  })
79
- beforeEach(() => {
80
- core.trigger(Events.CORE_READY)
81
- core.trigger(Events.CORE_ACTIVE_CONTAINER_CHANGED, core.activeContainer)
82
- })
83
- it('should render', () => {
84
- expect(dvrControls.el.innerHTML).toMatchSnapshot()
85
- expect(dvrControls.el.textContent).toContain('live')
86
- expect(dvrControls.el.textContent).toContain('back_to_live')
139
+ // TODO handle mount points in MediaControl
140
+ it('should not mount', () => {
141
+ expect(mediaControl.mount).not.toHaveBeenCalledWith(
142
+ 'dvr',
143
+ expect.anything(),
144
+ )
87
145
  })
88
146
  })
89
147
  })
@@ -5,15 +5,3 @@ exports[`DvrControls > basically > should render 1`] = `
5
5
  <button type="button" class="live-button" aria-label="back_to_live" id="media-control-back-to-live">back_to_live</button>
6
6
  "
7
7
  `;
8
-
9
- exports[`DvrControls > live stream > DVR at live edge > should render 1`] = `
10
- "<div class="live-info" id="media-control-live">live</div>
11
- <button type="button" class="live-button" aria-label="back_to_live" id="media-control-back-to-live">back_to_live</button>
12
- "
13
- `;
14
-
15
- exports[`DvrControls > live stream > no DVR > should render 1`] = `
16
- "<div class="live-info" id="media-control-live">live</div>
17
- <button type="button" class="live-button" aria-label="back_to_live" id="media-control-back-to-live">back_to_live</button>
18
- "
19
- `;
@@ -81,6 +81,16 @@ export type MediaControlElement =
81
81
  | MediaControlLayerElement
82
82
  | MediaControlRightElement
83
83
 
84
+ const MANAGED_ELEMENTS: MediaControlElement[] = [
85
+ 'dvr',
86
+ 'duration',
87
+ 'fullscreen',
88
+ 'hd-indicator',
89
+ 'position',
90
+ 'seekbar',
91
+ 'volume',
92
+ ]
93
+
84
94
  /**
85
95
  * Specifies the allowed media control elements in each area.
86
96
  * Can be used to restrict rendered media control elements.
@@ -99,8 +109,6 @@ const DEFAULT_SETTINGS: MediaControlSettings = {
99
109
  right: [
100
110
  'audiotracks',
101
111
  'cc',
102
- // 'dvr',
103
- // 'duration',
104
112
  'fullscreen',
105
113
  'gear',
106
114
  'multicamera',
@@ -122,10 +130,10 @@ const T = 'plugins.media_control'
122
130
  const LEFT_ORDER = [
123
131
  'playpause',
124
132
  'playstop',
125
- 'dvr',
126
133
  'volume',
127
134
  'position',
128
135
  'duration',
136
+ 'dvr',
129
137
  ]
130
138
 
131
139
  const { Config, Fullscreen, formatTime, extend, removeArrayItem } = Utils
@@ -996,8 +1004,7 @@ export class MediaControl extends UICorePlugin {
996
1004
  }
997
1005
  this.$el.show()
998
1006
  this.trigger(Events.MEDIACONTROL_SHOW, this.name)
999
- this.container &&
1000
- this.container.trigger(Events.CONTAINER_MEDIACONTROL_SHOW, this.name)
1007
+ this.core.activeContainer?.trigger(Events.CONTAINER_MEDIACONTROL_SHOW, this.name)
1001
1008
  this.$el.removeClass('media-control-hide')
1002
1009
  this.hideId = setTimeout(() => this.hide(), timeout)
1003
1010
  if (event) {
@@ -1066,7 +1073,7 @@ export class MediaControl extends UICorePlugin {
1066
1073
  )
1067
1074
  trace(`${T} updateSettings`, { newSettings })
1068
1075
 
1069
- newSettings.left.push('clips') // TODO
1076
+ newSettings.left.push('clips') // TODO settings
1070
1077
  // TODO make order controlled via CSS
1071
1078
  newSettings.left = orderByOrderPattern(
1072
1079
  [...newSettings.left, 'volume', 'clips'],
@@ -1155,7 +1162,6 @@ export class MediaControl extends UICorePlugin {
1155
1162
  * Get a media control element DOM node
1156
1163
  * @param name - The name of the media control element
1157
1164
  * @returns The DOM node to render to or extend
1158
- * @deprecated Use {@link MediaControl.putElement} instead
1159
1165
  * @remarks
1160
1166
  * Use this method to render custom media control UI in a plugin
1161
1167
  * @example
@@ -1171,7 +1177,7 @@ export class MediaControl extends UICorePlugin {
1171
1177
  */
1172
1178
  mount(name: MediaControlElement, element: ZeptoResult) {
1173
1179
  const panel = this.getElementLocation(name)
1174
- trace(`${T} putElement`, { name, panel: !!panel })
1180
+ trace(`${T} mount`, { name, panel: !!panel })
1175
1181
  if (panel) {
1176
1182
  const current = panel.find(`[data-${name}]`)
1177
1183
  element.attr(`data-${name}`, '')
@@ -1188,6 +1194,11 @@ export class MediaControl extends UICorePlugin {
1188
1194
  }
1189
1195
  }
1190
1196
 
1197
+ /**
1198
+ * @deprecated Use {@link MediaControl.mount} instead
1199
+ * @param name
1200
+ * @param element
1201
+ */
1191
1202
  putElement(name: MediaControlElement, element: ZeptoResult) {
1192
1203
  this.mount(name, element)
1193
1204
  }
@@ -1195,7 +1206,7 @@ export class MediaControl extends UICorePlugin {
1195
1206
  /**
1196
1207
  * Toggle the visibility of a media control element
1197
1208
  * @param name - The name of the media control element
1198
- * @param show - Whether to show or hide the element
1209
+ * @param show - Visibility state
1199
1210
  */
1200
1211
  toggleElement(area: MediaControlElement, show: boolean) {
1201
1212
  this.$el.find(`[data-${area}]`).toggle(show)
@@ -1456,6 +1467,7 @@ export class MediaControl extends UICorePlugin {
1456
1467
  width: this.options.width,
1457
1468
  height: this.options.height,
1458
1469
  })
1470
+ // TODO check out
1459
1471
  this.hideVolumeBar(0)
1460
1472
  }, 0)
1461
1473
 
@@ -189,7 +189,7 @@ describe('MediaControl', () => {
189
189
  })
190
190
  })
191
191
  })
192
- describe('putElement', () => {
192
+ describe('mount', () => {
193
193
  beforeEach(async () => {
194
194
  mediaControl = new MediaControl(core)
195
195
  core.emit(Events.CORE_READY)
@@ -212,7 +212,7 @@ describe('MediaControl', () => {
212
212
  const element = document.createElement('div')
213
213
  element.className = 'my-media-control'
214
214
  element.textContent = 'test'
215
- mediaControl.putElement(mcName, $(element))
215
+ mediaControl.mount(mcName, $(element))
216
216
 
217
217
  expect(mediaControl.el.innerHTML).toMatchSnapshot()
218
218
  expect(
@@ -234,19 +234,22 @@ describe('MediaControl', () => {
234
234
  seekEnabled: true,
235
235
  }
236
236
  core.emit(Events.CORE_ACTIVE_CONTAINER_CHANGED, core.activeContainer)
237
+ core.activePlayback.getPlaybackType.mockReturnValue(Playback.LIVE)
238
+ core.activeContainer.getPlaybackType.mockReturnValue(Playback.LIVE)
239
+ core.getPlaybackType.mockReturnValue(Playback.LIVE)
237
240
  await runMetadataLoaded(core)
238
241
  })
239
242
  describe('when enabled', () => {
240
243
  beforeEach(() => {
241
244
  core.activePlayback.dvrEnabled = true
242
245
  core.activeContainer.isDvrEnabled.mockReturnValue(true)
243
- core.activeContainer.emit(Events.CONTAINER_SETTINGSUPDATE, true)
246
+ core.activeContainer.emit(Events.CONTAINER_SETTINGSUPDATE)
244
247
  })
245
248
  it('should enable DVR controls', () => {
246
249
  const element = document.createElement('div')
247
250
  element.className = 'my-dvr-controls'
248
251
  element.textContent = 'live'
249
- mediaControl.putElement('dvr', $(element))
252
+ mediaControl.mount('dvr', $(element))
250
253
  expect(mediaControl.el.innerHTML).toMatchSnapshot()
251
254
  expect(
252
255
  mediaControl.$el.find('.media-control-left-panel .my-dvr-controls')
@@ -259,7 +262,7 @@ describe('MediaControl', () => {
259
262
  const element = document.createElement('div')
260
263
  element.className = 'my-dvr-controls'
261
264
  element.textContent = 'live'
262
- mediaControl.putElement('dvr', $(element))
265
+ mediaControl.mount('dvr', $(element))
263
266
  expect(mediaControl.el.innerHTML).toMatchSnapshot()
264
267
  expect(
265
268
  mediaControl.$el.find('.media-control-left-panel .my-dvr-controls')