@gcorevideo/player 2.22.29 → 2.22.31

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 (54) hide show
  1. package/assets/media-control/container.scss +2 -3
  2. package/assets/poster/poster.ejs +3 -1
  3. package/assets/poster/poster.scss +3 -3
  4. package/assets/skip-time/skip-time.ejs +4 -4
  5. package/assets/skip-time/style.scss +4 -4
  6. package/assets/style/main.scss +1 -1
  7. package/dist/core.js +1 -1
  8. package/dist/index.css +573 -574
  9. package/dist/index.js +225 -230
  10. package/dist/player.d.ts +63 -33
  11. package/docs/api/{player.seektime.bindevents.md → player.clapprstats.clearmetrics.md} +3 -3
  12. package/docs/api/player.clapprstats.md +14 -0
  13. package/docs/api/player.extendedevents.md +14 -0
  14. package/docs/api/player.md +13 -2
  15. package/docs/api/player.seektime.attributes.md +0 -1
  16. package/docs/api/player.seektime.md +6 -197
  17. package/docs/api/{player.seektime.render.md → player.seektimesettings.md} +7 -7
  18. package/docs/api/player.skiptime.md +3 -184
  19. package/lib/plugins/poster/Poster.d.ts +24 -14
  20. package/lib/plugins/poster/Poster.d.ts.map +1 -1
  21. package/lib/plugins/poster/Poster.js +67 -97
  22. package/lib/plugins/skip-time/SkipTime.d.ts +25 -11
  23. package/lib/plugins/skip-time/SkipTime.d.ts.map +1 -1
  24. package/lib/plugins/skip-time/SkipTime.js +43 -17
  25. package/lib/testUtils.d.ts +13 -39
  26. package/lib/testUtils.d.ts.map +1 -1
  27. package/lib/testUtils.js +14 -65
  28. package/package.json +1 -1
  29. package/src/plugins/poster/Poster.ts +91 -110
  30. package/src/plugins/poster/__tests__/Poster.test.ts +119 -0
  31. package/src/plugins/poster/__tests__/__snapshots__/Poster.test.ts.snap +8 -0
  32. package/src/plugins/skip-time/SkipTime.ts +52 -25
  33. package/src/plugins/source-controller/__tests__/SourceController.test.ts +1 -2
  34. package/src/testUtils.ts +14 -86
  35. package/temp/player.api.json +295 -829
  36. package/tsconfig.tsbuildinfo +1 -1
  37. package/docs/api/player.seektime.durationshown.md +0 -14
  38. package/docs/api/player.seektime.getseektime.md +0 -20
  39. package/docs/api/player.seektime.islivestreamwithdvr.md +0 -14
  40. package/docs/api/player.seektime.mediacontrol.md +0 -14
  41. package/docs/api/player.seektime.mediacontrolcontainer.md +0 -14
  42. package/docs/api/player.seektime.shouldbevisible.md +0 -18
  43. package/docs/api/player.seektime.template.md +0 -14
  44. package/docs/api/player.seektime.update.md +0 -18
  45. package/docs/api/player.skiptime.attributes.md +0 -17
  46. package/docs/api/player.skiptime.bindevents.md +0 -18
  47. package/docs/api/player.skiptime.events.md +0 -18
  48. package/docs/api/player.skiptime.handlerewindclicks.md +0 -18
  49. package/docs/api/player.skiptime.render.md +0 -18
  50. package/docs/api/player.skiptime.setback.md +0 -18
  51. package/docs/api/player.skiptime.setforward.md +0 -18
  52. package/docs/api/player.skiptime.setmidclick.md +0 -18
  53. package/docs/api/player.skiptime.template.md +0 -14
  54. package/docs/api/player.skiptime.togglefullscreen.md +0 -18
@@ -0,0 +1,119 @@
1
+ import { Poster } from '../Poster'
2
+ import { describe, it, expect, beforeEach } from 'vitest'
3
+ import { createMockCore } from '../../../testUtils'
4
+ import { Events, PlayerError } from '@clappr/core'
5
+
6
+ describe('Poster', () => {
7
+ let core: any
8
+ let poster: Poster
9
+ describe('basically', () => {
10
+ beforeEach(() => {
11
+ core = createMockCore({
12
+ poster: {
13
+ url: 'https://via.placeholder.com/150.png',
14
+ },
15
+ })
16
+ poster = new Poster(core.activeContainer)
17
+ core.activeContainer.trigger(Events.CONTAINER_READY)
18
+ })
19
+ it('should render', () => {
20
+ expect(poster.el.innerHTML).toMatchSnapshot()
21
+ })
22
+ describe('when clicked', () => {
23
+ beforeEach(() => {
24
+ poster.el.click()
25
+ })
26
+ it('should start playback', () => {
27
+ expect(core.activeContainer.play).toHaveBeenCalled()
28
+ expect(core.activeContainer.playback.consent).not.toHaveBeenCalled()
29
+ })
30
+ it('should hide button', () => {
31
+ expect(poster.$el.find('#poster-play')[0].style.display).toBe('none')
32
+ })
33
+ it('should remove clickable class', () => {
34
+ expect(poster.el.classList.contains('clickable')).toBe(false)
35
+ })
36
+ })
37
+ describe('when playback is triggered', () => {
38
+ beforeEach(() => {
39
+ core.activeContainer.playback.trigger(Events.PLAYBACK_PLAY_INTENT)
40
+ })
41
+ it('should hide button', () => {
42
+ expect(poster.$el.find('#poster-play')[0].style.display).toBe('none')
43
+ })
44
+ })
45
+ describe('when playback is about to start', () => {
46
+ describe.each([
47
+ [
48
+ Events.CONTAINER_STATE_BUFFERING,
49
+ ], [
50
+ Events.CONTAINER_STATE_BUFFERFULL,
51
+ ]
52
+ ])("event %s", (event) => {
53
+ beforeEach(() => {
54
+ core.activeContainer.buffering = true
55
+ core.activeContainer.trigger(event)
56
+ })
57
+ it('should hide button', () => {
58
+ expect(poster.$el.find('#poster-play')[0].style.display).toBe('none')
59
+ })
60
+ })
61
+ })
62
+ describe('when playback is started', () => {
63
+ beforeEach(() => {
64
+ core.activeContainer.trigger(Events.CONTAINER_PLAY)
65
+ core.activeContainer.playback.trigger(Events.PLAYBACK_PLAY)
66
+ })
67
+ it('should hide poster', () => {
68
+ expect(poster.el.style.display).toBe('none')
69
+ })
70
+ })
71
+ describe('when playback is stopped', () => {
72
+ beforeEach(() => {
73
+ core.activeContainer.trigger(Events.CONTAINER_PLAY)
74
+ core.activeContainer.playback.trigger(Events.PLAYBACK_PLAY)
75
+ core.activeContainer.trigger(Events.CONTAINER_STOP)
76
+ })
77
+ it('should show poster', () => {
78
+ expect(poster.el.style.display).not.toBe('none')
79
+ })
80
+ it('should show button', () => {
81
+ expect(poster.$el.find('#poster-play')[0].style.display).not.toBe('none')
82
+ })
83
+ it('should add clickable class', () => {
84
+ expect(poster.el.classList.contains('clickable')).toBe(true)
85
+ })
86
+ })
87
+ })
88
+ describe('when autoplay is configured', () => {
89
+ beforeEach(() => {
90
+ core = createMockCore({
91
+ autoPlay: true,
92
+ })
93
+ poster = new Poster(core.activeContainer)
94
+ core.activeContainer.trigger(Events.CONTAINER_READY)
95
+ })
96
+ it('should hide button initially', () => {
97
+ expect(poster.$el.find('#poster-play')[0].style.display).toBe('none')
98
+ })
99
+ })
100
+ describe('when error occurs', () => {
101
+ beforeEach(() => {
102
+ core = createMockCore({
103
+ autoPlay: true,
104
+ })
105
+ poster = new Poster(core.activeContainer)
106
+ core.activeContainer.trigger(Events.CONTAINER_READY)
107
+ core.activeContainer.playback.trigger(Events.PLAYBACK_PLAY_INTENT)
108
+ core.activeContainer.trigger(Events.CONTAINER_ERROR, {
109
+ level: PlayerError.Levels.FATAL,
110
+ })
111
+ })
112
+ it('should show poster', () => {
113
+ expect(poster.el.style.display).not.toBe('none')
114
+ })
115
+ it('should hide button', () => {
116
+ expect(poster.$el.find('#poster-play')[0].style.display).toBe('none')
117
+ })
118
+ })
119
+ })
@@ -0,0 +1,8 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`Poster > basically > should render 1`] = `
4
+ "<div class="play-wrapper" id="gplayer-poster">
5
+ <div class="circle-poster gcore-skin-button-color gcore-skin-border-color" id="poster-play">/assets/icons/new/play.svg</div>
6
+ </div>
7
+ "
8
+ `;
@@ -1,4 +1,5 @@
1
1
  import { UICorePlugin, Browser, Playback, Events, template } from '@clappr/core'
2
+ import { trace } from '@gcorevideo/utils'
2
3
 
3
4
  import { CLAPPR_VERSION } from '../../build.js'
4
5
 
@@ -7,8 +8,10 @@ import '../../../assets/skip-time/style.scss'
7
8
 
8
9
  type Position = 'mid' | 'left' | 'right'
9
10
 
11
+ const T = 'plugins.skip_time'
12
+
10
13
  /**
11
- * `PLUGIN` that adds skip controls to the media control UI.
14
+ * `PLUGIN` that allows skipping time by tapping on the left or right side of the video.
12
15
  * @beta
13
16
  */
14
17
  export class SkipTime extends UICorePlugin {
@@ -24,52 +27,70 @@ export class SkipTime extends UICorePlugin {
24
27
  return this.core && this.core.activeContainer
25
28
  }
26
29
 
27
- get template() {
28
- return template(pluginHtml)
29
- }
30
+ private static readonly template = template(pluginHtml)
30
31
 
32
+ /**
33
+ * @internal
34
+ */
31
35
  override get attributes() {
32
36
  return {
33
- class: this.name + '_plugin',
34
- 'data-skip-time': '',
37
+ class: 'mc-skip-time',
35
38
  }
36
39
  }
37
40
 
38
41
  private position: Position = 'mid'
39
42
 
43
+ /**
44
+ * @internal
45
+ */
40
46
  override get events() {
41
47
  return {
42
- 'click [data-skip-left]': 'setBack',
43
- 'click [data-skip-mid]': 'setMidClick',
44
- 'click [data-skip-right]': 'setForward',
48
+ 'click #mc-skip-left': 'setBack',
49
+ 'click #mc-skip-mid': 'setMidClick',
50
+ 'click #mc-skip-right': 'setForward',
45
51
  }
46
52
  }
47
53
 
54
+ /**
55
+ * @internal
56
+ */
48
57
  override bindEvents() {
49
58
  this.listenTo(this.core, Events.CORE_READY, this.render)
50
- if (!this.container) {
51
- return
52
- }
59
+ this.listenTo(this.core, Events.CORE_ACTIVE_CONTAINER_CHANGED, this.onContainerChanged)
60
+ }
61
+
62
+ private onContainerChanged() {
53
63
  this.listenTo(
54
64
  this.container,
55
65
  Events.CONTAINER_DBLCLICK,
56
66
  this.handleRewindClicks,
57
67
  )
68
+ this.mount()
58
69
  }
59
70
 
60
- setBack() {
71
+ private setBack() {
72
+ trace(`${T} setBack`)
61
73
  this.position = 'left'
62
74
  }
63
75
 
64
- handleRewindClicks() {
76
+ private handleRewindClicks() {
77
+ trace(`${T} handleRewindClicks`, {
78
+ position: this.position,
79
+ })
65
80
  if (
66
81
  this.core.getPlaybackType() === Playback.LIVE &&
67
82
  !this.container.isDvrEnabled()
68
83
  ) {
69
84
  this.toggleFullscreen()
70
-
71
85
  return
72
86
  }
87
+ this.handleSkip()
88
+ }
89
+
90
+ private handleSkip() {
91
+ trace(`${T} handleSkip`, {
92
+ position: this.position,
93
+ })
73
94
  if (Browser.isMobile) {
74
95
  if (this.position === 'left') {
75
96
  const seekPos = this.container.getCurrentTime() - 10
@@ -92,29 +113,35 @@ export class SkipTime extends UICorePlugin {
92
113
  }
93
114
  }
94
115
 
95
- setMidClick() {
116
+ private setMidClick() {
117
+ trace(`${T} setMidClick`)
96
118
  this.position = 'mid'
97
119
  }
98
120
 
99
- setForward() {
121
+ private setForward() {
122
+ trace(`${T} setForward`)
100
123
  this.position = 'right'
101
124
  }
102
125
 
103
- toggleFullscreen() {
126
+ private toggleFullscreen() {
127
+ trace(`${T} toggleFullscreen`)
104
128
  this.trigger(Events.MEDIACONTROL_FULLSCREEN, this.name)
105
129
  this.container.fullscreen()
106
130
  this.core.toggleFullscreen()
107
131
  }
108
132
 
133
+ /**
134
+ * @internal
135
+ */
109
136
  override render() {
110
- this.$el.html(template(pluginHtml))
111
-
112
- if (this.core.activeContainer) {
113
- this.core.activeContainer.$el.append(this.el)
114
- }
115
-
116
- this.bindEvents()
137
+ trace(`${T} render`)
138
+ this.$el.html(SkipTime.template())
117
139
 
118
140
  return this
119
141
  }
142
+
143
+ private mount() {
144
+ trace(`${T} mount`)
145
+ this.core.activeContainer.$el.append(this.el)
146
+ }
120
147
  }
@@ -5,7 +5,6 @@ import FakeTimers from '@sinonjs/fake-timers'
5
5
  import { SourceController } from '../SourceController'
6
6
  import { PlaybackErrorCode } from '../../../playback.types.js'
7
7
  import {
8
- _MockPlayback,
9
8
  createMockCore,
10
9
  createMockPlayback,
11
10
  createMockPlugin,
@@ -151,7 +150,7 @@ describe('SourceController', () => {
151
150
  core.activePlayback.emit('playback:error', {
152
151
  code: PlaybackErrorCode.MediaSourceUnavailable,
153
152
  })
154
- nextPlayback = new _MockPlayback({} as any, {} as any)
153
+ nextPlayback = createMockPlayback()
155
154
  vi.spyOn(nextPlayback, 'consent')
156
155
  vi.spyOn(nextPlayback, 'play')
157
156
  core.activePlayback = nextPlayback
package/src/testUtils.ts CHANGED
@@ -1,86 +1,6 @@
1
- import { $, Playback, UICorePlugin } from '@clappr/core'
1
+ import { $, UICorePlugin } from '@clappr/core'
2
2
  import Events from 'eventemitter3'
3
3
  import { vi } from 'vitest'
4
- /**
5
- * @internal
6
- * @deprecated
7
- * TODO use createMockPlayback() instead
8
- */
9
- export class _MockPlayback extends Events {
10
- constructor(
11
- protected options: any,
12
- readonly i18n: any,
13
- protected playerError?: any,
14
- ) {
15
- super()
16
- }
17
-
18
- get name() {
19
- return 'mock'
20
- }
21
-
22
- consent() {}
23
-
24
- play() {}
25
-
26
- pause() {}
27
-
28
- stop() {}
29
-
30
- destroy() {}
31
-
32
- seek() {}
33
-
34
- seekPercentage() {}
35
-
36
- getDuration() {
37
- return 100
38
- }
39
-
40
- enterPiP() {}
41
-
42
- exitPiP() {}
43
-
44
- getPlaybackType() {
45
- return Playback.LIVE
46
- }
47
-
48
- getStartTimeOffset() {
49
- return 0
50
- }
51
-
52
- getCurrentTime() {
53
- return 0
54
- }
55
-
56
- isHighDefinitionInUse() {
57
- return false
58
- }
59
-
60
- mute() {}
61
-
62
- unmute() {}
63
-
64
- volume() {}
65
-
66
- configure() {}
67
-
68
- attemptAutoPlay() {
69
- return true
70
- }
71
-
72
- canAutoPlay() {
73
- return true
74
- }
75
-
76
- onResize() {
77
- return true
78
- }
79
-
80
- trigger(event: string, ...args: any[]) {
81
- this.emit(event, ...args)
82
- }
83
- }
84
4
 
85
5
  export function createMockCore(
86
6
  options: Record<string, unknown> = {},
@@ -129,11 +49,12 @@ export function createMockPlayback(name = 'mock') {
129
49
  el: document.createElement('video'),
130
50
  dvrEnabled: false,
131
51
  dvrInUse: false,
52
+ isAudioOnly: false,
132
53
  levels: [],
133
- consent() {},
134
- play() {},
135
- pause() {},
136
- stop() {},
54
+ consent: vi.fn(),
55
+ play: vi.fn(),
56
+ pause: vi.fn(),
57
+ stop: vi.fn(),
137
58
  destroy: vi.fn(),
138
59
  seek: vi.fn(),
139
60
  seekPercentage: vi.fn(),
@@ -166,13 +87,20 @@ export function createMockContainer(
166
87
  return Object.assign(emitter, {
167
88
  el,
168
89
  playback,
169
- options,
90
+ options: {
91
+ ...options,
92
+ },
170
93
  $el: $(el),
94
+ disableMediaControl: vi.fn(),
95
+ enableMediaControl: vi.fn(),
96
+ enterPiP: vi.fn(),
97
+ exitPiP: vi.fn(),
171
98
  getDuration: vi.fn().mockReturnValue(0),
172
99
  getPlugin: vi.fn(),
173
100
  getPlaybackType: vi.fn(),
174
101
  isDvrInUse: vi.fn().mockReturnValue(false),
175
102
  isDvrEnabled: vi.fn().mockReturnValue(false),
103
+ isHighDefinitionInUse: vi.fn().mockReturnValue(false),
176
104
  isPlaying: vi.fn().mockReturnValue(false),
177
105
  play: vi.fn(),
178
106
  seek: vi.fn(),