@gcorevideo/player 2.20.6 → 2.20.8

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 (65) hide show
  1. package/dist/core.js +37 -13
  2. package/dist/index.css +1163 -1163
  3. package/dist/index.js +2557 -2513
  4. package/dist/plugins/index.css +470 -470
  5. package/dist/plugins/index.js +5230 -5217
  6. package/lib/playback/BasePlayback.d.ts +5 -0
  7. package/lib/playback/BasePlayback.d.ts.map +1 -1
  8. package/lib/playback/BasePlayback.js +8 -0
  9. package/lib/playback/HTML5Video.d.ts +4 -0
  10. package/lib/playback/HTML5Video.d.ts.map +1 -0
  11. package/lib/playback/HTML5Video.js +3 -0
  12. package/lib/playback/dash-playback/DashPlayback.d.ts +1 -0
  13. package/lib/playback/dash-playback/DashPlayback.d.ts.map +1 -1
  14. package/lib/playback/dash-playback/DashPlayback.js +6 -2
  15. package/lib/playback/index.d.ts.map +1 -1
  16. package/lib/playback/index.js +2 -0
  17. package/lib/playback/types.d.ts +9 -0
  18. package/lib/playback/types.d.ts.map +1 -0
  19. package/lib/playback/types.js +9 -0
  20. package/lib/plugins/bottom-gear/BottomGear.d.ts +6 -11
  21. package/lib/plugins/bottom-gear/BottomGear.d.ts.map +1 -1
  22. package/lib/plugins/bottom-gear/BottomGear.js +9 -21
  23. package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.js +2 -2
  24. package/lib/plugins/dvr-controls/DvrControls.d.ts +1 -1
  25. package/lib/plugins/dvr-controls/DvrControls.d.ts.map +1 -1
  26. package/lib/plugins/dvr-controls/DvrControls.js +27 -16
  27. package/lib/plugins/level-selector/LevelSelector.d.ts +17 -5
  28. package/lib/plugins/level-selector/LevelSelector.d.ts.map +1 -1
  29. package/lib/plugins/level-selector/LevelSelector.js +35 -24
  30. package/lib/plugins/media-control/MediaControl.d.ts +11 -0
  31. package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
  32. package/lib/plugins/media-control/MediaControl.js +16 -3
  33. package/lib/plugins/playback-rate/PlaybackRate.d.ts +11 -10
  34. package/lib/plugins/playback-rate/PlaybackRate.d.ts.map +1 -1
  35. package/lib/plugins/playback-rate/PlaybackRate.js +83 -91
  36. package/lib/plugins/source-controller/SourceController.d.ts +1 -0
  37. package/lib/plugins/source-controller/SourceController.d.ts.map +1 -1
  38. package/lib/plugins/source-controller/SourceController.js +8 -4
  39. package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.d.ts +7 -3
  40. package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.d.ts.map +1 -1
  41. package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.js +35 -27
  42. package/lib/testUtils.d.ts +5 -8
  43. package/lib/testUtils.d.ts.map +1 -1
  44. package/lib/testUtils.js +15 -9
  45. package/package.json +1 -1
  46. package/src/playback/BasePlayback.ts +12 -4
  47. package/src/playback/HTML5Video.ts +3 -0
  48. package/src/playback/dash-playback/DashPlayback.ts +15 -11
  49. package/src/playback/index.ts +2 -1
  50. package/src/playback/types.ts +9 -0
  51. package/src/plugins/bottom-gear/BottomGear.ts +10 -21
  52. package/src/plugins/bottom-gear/__tests__/BottomGear.test.ts +36 -0
  53. package/src/plugins/bottom-gear/__tests__/__snapshots__/BottomGear.test.ts.snap +41 -0
  54. package/src/plugins/clappr-nerd-stats/ClapprNerdStats.ts +3 -3
  55. package/src/plugins/dvr-controls/DvrControls.ts +87 -54
  56. package/src/plugins/level-selector/LevelSelector.ts +64 -31
  57. package/src/plugins/level-selector/__tests__/LevelSelector.test.ts +15 -16
  58. package/src/plugins/media-control/MediaControl.ts +20 -6
  59. package/src/plugins/playback-rate/PlaybackRate.ts +89 -105
  60. package/src/plugins/source-controller/SourceController.ts +9 -4
  61. package/src/plugins/source-controller/__tests__/SourceController.test.ts +35 -1
  62. package/src/plugins/spinner-three-bounce/SpinnerThreeBounce.ts +80 -57
  63. package/src/testUtils.ts +16 -9
  64. package/tsconfig.tsbuildinfo +1 -1
  65. package/assets/playback-rate/playback-rate-selector.ejs +0 -9
@@ -1,3 +1,4 @@
1
+ import { UICorePlugin } from '@clappr/core';
1
2
  import Events from 'eventemitter3';
2
3
  /**
3
4
  * @internal
@@ -35,10 +36,7 @@ export declare class _MockPlayback extends Events {
35
36
  }
36
37
  export declare function createMockCore(options?: Record<string, unknown>, container?: any): Events<string | symbol, any> & {
37
38
  el: HTMLDivElement;
38
- $el: {
39
- 0: HTMLDivElement;
40
- append: import("vitest").Mock<(...args: any[]) => any>;
41
- };
39
+ $el: any;
42
40
  activePlayback: any;
43
41
  activeContainer: any;
44
42
  options: {
@@ -47,6 +45,7 @@ export declare function createMockCore(options?: Record<string, unknown>, contai
47
45
  configure: import("vitest").Mock<(...args: any[]) => any>;
48
46
  getPlugin: import("vitest").Mock<(...args: any[]) => any>;
49
47
  load: import("vitest").Mock<(...args: any[]) => any>;
48
+ trigger: <T extends string | symbol>(event: T, ...args: any[]) => boolean;
50
49
  };
51
50
  export declare function createMockPlugin(): Events<string | symbol, any> & {
52
51
  enable: import("vitest").Mock<(...args: any[]) => any>;
@@ -87,12 +86,10 @@ export declare function createMockPlayback(name?: string): Events<string | symbo
87
86
  trigger(event: string, ...args: any[]): void;
88
87
  };
89
88
  export declare function createMockContainer(playback?: any): Events<string | symbol, any> & {
90
- $el: {
91
- html: import("vitest").Mock<(...args: any[]) => any>;
92
- 0: HTMLDivElement;
93
- };
89
+ $el: any;
94
90
  el: HTMLDivElement;
95
91
  getPlugin: import("vitest").Mock<(...args: any[]) => any>;
96
92
  playback: any;
97
93
  };
94
+ export declare function createMockMediaControl(core: any): UICorePlugin;
98
95
  //# sourceMappingURL=testUtils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"testUtils.d.ts","sourceRoot":"","sources":["../src/testUtils.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,eAAe,CAAA;AAElC;;;;GAIG;AACH,qBAAa,aAAc,SAAQ,MAAM;IAErC,SAAS,CAAC,OAAO,EAAE,GAAG;IACtB,QAAQ,CAAC,IAAI,EAAE,GAAG;IAClB,SAAS,CAAC,WAAW,CAAC,EAAE,GAAG;gBAFjB,OAAO,EAAE,GAAG,EACb,IAAI,EAAE,GAAG,EACR,WAAW,CAAC,EAAE,GAAG,YAAA;IAK7B,IAAI,IAAI,WAEP;IAED,OAAO;IAEP,IAAI;IAEJ,KAAK;IAEL,IAAI;IAEJ,OAAO;IAEP,IAAI;IAEJ,cAAc;IAEd,WAAW;IAIX,QAAQ;IAER,OAAO;IAEP,eAAe;IAIf,kBAAkB;IAIlB,cAAc;IAId,qBAAqB;IAIrB,IAAI;IAEJ,MAAM;IAEN,MAAM;IAEN,SAAS;IAET,eAAe;IAIf,WAAW;IAIX,QAAQ;IAIR,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE;CAGtC;AAED,wBAAgB,cAAc,CAAC,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EAAE,SAAS,GAAE,GAA2B;;;;;;;;;;;;;;EAiB3G;AAED,wBAAgB,gBAAgB;;;EAK/B;AAED,wBAAgB,mBAAmB;;;;;;EAKlC;AAED,wBAAgB,kBAAkB,CAAC,IAAI,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;mBA2C7B,MAAM,WAAW,GAAG,EAAE;EAIxC;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,GAAE,GAA0B;;;;;;;;EAWvE"}
1
+ {"version":3,"file":"testUtils.d.ts","sourceRoot":"","sources":["../src/testUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAK,YAAY,EAAE,MAAM,cAAc,CAAA;AAC9C,OAAO,MAAM,MAAM,eAAe,CAAA;AAElC;;;;GAIG;AACH,qBAAa,aAAc,SAAQ,MAAM;IAErC,SAAS,CAAC,OAAO,EAAE,GAAG;IACtB,QAAQ,CAAC,IAAI,EAAE,GAAG;IAClB,SAAS,CAAC,WAAW,CAAC,EAAE,GAAG;gBAFjB,OAAO,EAAE,GAAG,EACb,IAAI,EAAE,GAAG,EACR,WAAW,CAAC,EAAE,GAAG,YAAA;IAK7B,IAAI,IAAI,WAEP;IAED,OAAO;IAEP,IAAI;IAEJ,KAAK;IAEL,IAAI;IAEJ,OAAO;IAEP,IAAI;IAEJ,cAAc;IAEd,WAAW;IAIX,QAAQ;IAER,OAAO;IAEP,eAAe;IAIf,kBAAkB;IAIlB,cAAc;IAId,qBAAqB;IAIrB,IAAI;IAEJ,MAAM;IAEN,MAAM;IAEN,SAAS;IAET,eAAe;IAIf,WAAW;IAIX,QAAQ;IAIR,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE;CAGtC;AAED,wBAAgB,cAAc,CAAC,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EAAE,SAAS,GAAE,GAA2B;;;;;;;;;;;;EAgB3G;AAED,wBAAgB,gBAAgB;;;EAK/B;AAED,wBAAgB,mBAAmB;;;;;;EAKlC;AAED,wBAAgB,kBAAkB,CAAC,IAAI,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;mBA2C7B,MAAM,WAAW,GAAG,EAAE;EAIxC;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,GAAE,GAA0B;;;;;EAQvE;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,GAAG,gBAQ/C"}
package/lib/testUtils.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { $, UICorePlugin } from '@clappr/core';
1
2
  import Events from 'eventemitter3';
2
3
  import { vi } from 'vitest';
3
4
  /**
@@ -61,12 +62,10 @@ export class _MockPlayback extends Events {
61
62
  }
62
63
  export function createMockCore(options = {}, container = createMockContainer()) {
63
64
  const el = document.createElement('div');
64
- return Object.assign(new Events(), {
65
+ const emitter = new Events();
66
+ return Object.assign(emitter, {
65
67
  el,
66
- $el: {
67
- [0]: el,
68
- append: vi.fn(),
69
- },
68
+ $el: $(el),
70
69
  activePlayback: container.playback,
71
70
  activeContainer: container,
72
71
  options: {
@@ -75,6 +74,7 @@ export function createMockCore(options = {}, container = createMockContainer())
75
74
  configure: vi.fn(),
76
75
  getPlugin: vi.fn(),
77
76
  load: vi.fn(),
77
+ trigger: emitter.emit,
78
78
  });
79
79
  }
80
80
  export function createMockPlugin() {
@@ -140,12 +140,18 @@ export function createMockPlayback(name = 'mock') {
140
140
  export function createMockContainer(playback = createMockPlayback()) {
141
141
  const el = document.createElement('div');
142
142
  return Object.assign(new Events(), {
143
- $el: {
144
- html: vi.fn(),
145
- [0]: el,
146
- },
143
+ $el: $(el),
147
144
  el,
148
145
  getPlugin: vi.fn(),
149
146
  playback,
150
147
  });
151
148
  }
149
+ export function createMockMediaControl(core) {
150
+ const mediaControl = new UICorePlugin(core);
151
+ const elements = {
152
+ gear: $(document.createElement('div')),
153
+ };
154
+ // @ts-ignore
155
+ mediaControl.getElement = vi.fn().mockImplementation((name) => elements[name]);
156
+ return mediaControl;
157
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gcorevideo/player",
3
- "version": "2.20.6",
3
+ "version": "2.20.8",
4
4
  "description": "Gcore JavaScript video player",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -11,10 +11,10 @@ export class BasePlayback extends HTML5Video {
11
11
  createError(errorData: any, options?: ErrorOptions) {
12
12
  const i18n =
13
13
  this.i18n ||
14
- // @ts-ignore
15
- (this.core && this.core.i18n) ||
16
- // @ts-ignore
17
- (this.container && this.container.i18n)
14
+ // @ts-ignore
15
+ (this.core && this.core.i18n) ||
16
+ // @ts-ignore
17
+ (this.container && this.container.i18n)
18
18
 
19
19
  if (
20
20
  i18n &&
@@ -34,6 +34,14 @@ export class BasePlayback extends HTML5Video {
34
34
  return super.createError(errorData, options)
35
35
  }
36
36
 
37
+ /**
38
+ * Sets the playback rate.
39
+ * @param rate - The playback rate to set.
40
+ */
41
+ setPlaybackRate(rate: number) {
42
+ ;(this.el as HTMLMediaElement).playbackRate = rate
43
+ }
44
+
37
45
  override _onPlaying() {
38
46
  super._onPlaying()
39
47
  this.trigger(Events.PLAYBACK_MEDIACONTROL_ENABLE)
@@ -0,0 +1,3 @@
1
+ import { BasePlayback } from './BasePlayback.js'
2
+
3
+ export default class HTML5Video extends BasePlayback {}
@@ -17,7 +17,6 @@ import DASHJS, {
17
17
  import {
18
18
  PlaybackError,
19
19
  PlaybackErrorCode,
20
- PlayerComponentType,
21
20
  QualityLevel,
22
21
  TimePosition,
23
22
  TimeUpdate,
@@ -25,6 +24,7 @@ import {
25
24
  } from '../../playback.types.js'
26
25
  import { isDashSource } from '../../utils/mediaSources.js'
27
26
  import { BasePlayback } from '../BasePlayback.js'
27
+ import { PlaybackEvents } from '../types.js'
28
28
 
29
29
  const AUTO = -1
30
30
 
@@ -300,8 +300,8 @@ export default class DashPlayback extends BasePlayback {
300
300
  },
301
301
  )
302
302
 
303
- this._dash.on(DASHJS.MediaPlayer.events.PLAYBACK_RATE_CHANGED, () => {
304
- this.trigger('dash:playback-rate-changed')
303
+ this._dash.on(DASHJS.MediaPlayer.events.PLAYBACK_RATE_CHANGED, (e: DASHJS.PlaybackRateChangedEvent) => {
304
+ this.trigger(PlaybackEvents.PLAYBACK_RATE_CHANGED, e.playbackRate)
305
305
  })
306
306
  }
307
307
 
@@ -361,7 +361,7 @@ export default class DashPlayback extends BasePlayback {
361
361
  return this._startTime
362
362
  }
363
363
 
364
- seekPercentage(percentage: number) {
364
+ override seekPercentage(percentage: number) {
365
365
  let seekTo = this._duration
366
366
 
367
367
  if (percentage > 0) {
@@ -376,7 +376,7 @@ export default class DashPlayback extends BasePlayback {
376
376
  this.seek(seekTo)
377
377
  }
378
378
 
379
- seek(time: TimeValue) {
379
+ override seek(time: TimeValue) {
380
380
  if (time < 0) {
381
381
  // eslint-disable-next-line max-len
382
382
  Log.warn(
@@ -478,7 +478,7 @@ export default class DashPlayback extends BasePlayback {
478
478
  }, 10)
479
479
  }
480
480
 
481
- _onTimeUpdate() {
481
+ override _onTimeUpdate() {
482
482
  if (this.startChangeQuality) {
483
483
  return
484
484
  }
@@ -499,7 +499,7 @@ export default class DashPlayback extends BasePlayback {
499
499
  this.trigger(Events.PLAYBACK_TIMEUPDATE, update, this.name)
500
500
  }
501
501
 
502
- _onDurationChange() {
502
+ override _onDurationChange() {
503
503
  const duration = this.getDuration()
504
504
 
505
505
  if (this._lastDuration === duration) {
@@ -540,7 +540,7 @@ export default class DashPlayback extends BasePlayback {
540
540
  this.trigger(Events.PLAYBACK_PROGRESS, progress, {})
541
541
  }
542
542
 
543
- play() {
543
+ override play() {
544
544
  trace(`${T} play`, { dash: !!this._dash })
545
545
  if (!this._dash) {
546
546
  this._setup()
@@ -550,7 +550,7 @@ export default class DashPlayback extends BasePlayback {
550
550
  this._startTimeUpdateTimer()
551
551
  }
552
552
 
553
- pause() {
553
+ override pause() {
554
554
  if (!this._dash) {
555
555
  return
556
556
  }
@@ -560,7 +560,7 @@ export default class DashPlayback extends BasePlayback {
560
560
  }
561
561
  }
562
562
 
563
- stop() {
563
+ override stop() {
564
564
  if (this._dash) {
565
565
  this._stopTimeUpdateTimer()
566
566
  this._dash.reset()
@@ -569,7 +569,7 @@ export default class DashPlayback extends BasePlayback {
569
569
  }
570
570
  }
571
571
 
572
- destroy() {
572
+ override destroy() {
573
573
  this._stopTimeUpdateTimer()
574
574
  if (this._dash) {
575
575
  this._dash.off(DASHJS.MediaPlayer.events.ERROR, this._onDASHJSSError)
@@ -638,6 +638,10 @@ export default class DashPlayback extends BasePlayback {
638
638
  assert.ok(ret, 'Invalid quality level')
639
639
  return ret
640
640
  }
641
+
642
+ setPlaybackRate(rate: number) {
643
+ this._dash?.setPlaybackRate(rate)
644
+ }
641
645
  }
642
646
 
643
647
  DashPlayback.canPlay = function (resource, mimeType) {
@@ -2,9 +2,10 @@ import { Loader } from '@clappr/core'
2
2
 
3
3
  import DashPlayback from './dash-playback/DashPlayback.js'
4
4
  import HlsPlayback from './hls-playback/HlsPlayback.js'
5
-
5
+ import HTML5Video from './HTML5Video.js'
6
6
  // TODO consider allowing the variation of the order of playback modules
7
7
  export function registerPlaybacks() {
8
+ Loader.registerPlayback(HTML5Video) // TODO check it overrides the default HTML5Video
8
9
  Loader.registerPlayback(HlsPlayback)
9
10
  Loader.registerPlayback(DashPlayback)
10
11
  }
@@ -0,0 +1,9 @@
1
+
2
+ export enum PlaybackEvents {
3
+ /**
4
+ * Emitted when the playback rate changes.
5
+ * Payload:
6
+ * - playbackRate number
7
+ */
8
+ PLAYBACK_RATE_CHANGED = 'playback:rate-changed',
9
+ }
@@ -10,22 +10,12 @@ import '../../../assets/bottom-gear/gear-sub-menu.scss';
10
10
  import gearIcon from '../../../assets/icons/new/gear.svg';
11
11
  import gearHdIcon from '../../../assets/icons/new/gear-hd.svg';
12
12
  import { ZeptoResult } from '../../utils/types.js';
13
+ import { MediaControlEvents } from '../media-control/MediaControl';
13
14
 
14
15
  const VERSION = '2.19.12';
15
16
 
16
17
  const T = 'plugins.bottom_gear';
17
18
 
18
- /**
19
- * Custom events emitted by the plugin
20
- * @beta
21
- */
22
- export enum GearEvents {
23
- /**
24
- * Emitted when the gear menu is rendered
25
- */
26
- MEDIACONTROL_GEAR_RENDERED = 'mediacontrol:gear:rendered',
27
- }
28
-
29
19
  /**
30
20
  * An element inside the gear menu
31
21
  * @beta
@@ -95,7 +85,6 @@ export class BottomGear extends UICorePlugin {
95
85
  assert(mediaControl, 'media_control plugin is required');
96
86
 
97
87
  this.listenTo(this.core, ClapprEvents.CORE_ACTIVE_CONTAINER_CHANGED, this.onActiveContainerChanged);
98
- this.listenTo(this.core, 'gear:refresh', this.refresh); // TODO use direct plugin method call
99
88
  this.listenTo(mediaControl, ClapprEvents.MEDIACONTROL_RENDERED, this.render);
100
89
  this.listenTo(mediaControl, ClapprEvents.MEDIACONTROL_HIDE, this.hide); // TODO mediacontrol show as well
101
90
  }
@@ -127,13 +116,9 @@ export class BottomGear extends UICorePlugin {
127
116
  }
128
117
 
129
118
  private highDefinitionUpdate(isHd: boolean) {
130
- trace(`${this.name} highDefinitionUpdate`, { isHd });
119
+ trace(`${T} highDefinitionUpdate`, { isHd });
131
120
  this.isHd = isHd;
132
- if (isHd) {
133
- this.$el.find('.gear-icon').html(gearHdIcon);
134
- } else {
135
- this.$el.find('.gear-icon').html(gearIcon);
136
- }
121
+ this.$el.find('.gear-icon').html(isHd ? gearHdIcon : gearIcon);
137
122
  }
138
123
 
139
124
  /**
@@ -153,12 +138,16 @@ export class BottomGear extends UICorePlugin {
153
138
  this.$el.html(BottomGear.template({ icon, items }));
154
139
 
155
140
  mediaControl.getElement('gear')?.html(this.el);
156
- this.core.trigger('gear:rendered'); // @deprecated
157
- mediaControl.trigger(GearEvents.MEDIACONTROL_GEAR_RENDERED);
141
+ mediaControl.trigger(MediaControlEvents.MEDIACONTROL_GEAR_RENDERED);
158
142
  return this;
159
143
  }
160
144
 
161
- private refresh() {
145
+ /**
146
+ * Re-renders the gear menu.
147
+ * It fires the {@link MediaControlEvents.MEDIACONTROL_GEAR_RENDERED | MEDIACONTROL_GEAR_RENDERED} event,
148
+ * which the plugins that attach to the gear menu can listen to to re-render themselves.
149
+ */
150
+ refresh() {
162
151
  this.render();
163
152
  this.$el.find('.gear-wrapper').show();
164
153
  }
@@ -0,0 +1,36 @@
1
+ import { MockedFunction, beforeEach, describe, expect, it, vi } from 'vitest'
2
+
3
+ import { BottomGear } from '../BottomGear'
4
+ import { createMockCore, createMockMediaControl } from '../../../testUtils'
5
+ import { MediaControlEvents } from '../../media-control/MediaControl'
6
+
7
+ describe('BottomGear', () => {
8
+ let mediaControl: any
9
+ let core: any
10
+ let bottomGear: BottomGear
11
+ let onGearRendered: MockedFunction<() => void>
12
+ beforeEach(() => {
13
+ core = createMockCore()
14
+ mediaControl = createMockMediaControl(core)
15
+ core.getPlugin = vi
16
+ .fn()
17
+ .mockImplementation((name) =>
18
+ name === 'media_control' ? mediaControl : null,
19
+ )
20
+ bottomGear = new BottomGear(core)
21
+ onGearRendered = vi.fn()
22
+ mediaControl.on(MediaControlEvents.MEDIACONTROL_GEAR_RENDERED, onGearRendered, null)
23
+ bottomGear.render()
24
+ })
25
+ it('should render', () => {
26
+ expect(bottomGear.el.innerHTML).toMatchSnapshot()
27
+ })
28
+ it('should attach to media control', () => {
29
+ const gearElement = mediaControl.getElement('gear')
30
+ expect(gearElement[0].innerHTML).not.toEqual('')
31
+ expect(gearElement[0].innerHTML).toMatchSnapshot()
32
+ })
33
+ it('should emit event', () => {
34
+ expect(onGearRendered).toHaveBeenCalled()
35
+ })
36
+ })
@@ -0,0 +1,41 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`BottomGear > should attach to media control 1`] = `
4
+ "<div class="bottom_gear" data-track-selector=""><div class="media-control-gear" data-="">
5
+ <button type="button" class="button-gear gplayer-lite-btn gcore-skin-button-color" data-gear-button="-1">
6
+ <span class="gear-icon">/assets/icons/new/gear.svg</span>
7
+ </button>
8
+ <div class="gear-wrapper gcore-skin-bg-color">
9
+ <ul class="gear-options-list">
10
+
11
+ <li data-quality=""></li>
12
+
13
+ <li data-rate=""></li>
14
+
15
+ <li data-nerd=""></li>
16
+
17
+ </ul>
18
+ </div>
19
+ </div>
20
+ </div>"
21
+ `;
22
+
23
+ exports[`BottomGear > should render 1`] = `
24
+ "<div class="media-control-gear" data-="">
25
+ <button type="button" class="button-gear gplayer-lite-btn gcore-skin-button-color" data-gear-button="-1">
26
+ <span class="gear-icon">/assets/icons/new/gear.svg</span>
27
+ </button>
28
+ <div class="gear-wrapper gcore-skin-bg-color">
29
+ <ul class="gear-options-list">
30
+
31
+ <li data-quality=""></li>
32
+
33
+ <li data-rate=""></li>
34
+
35
+ <li data-nerd=""></li>
36
+
37
+ </ul>
38
+ </div>
39
+ </div>
40
+ "
41
+ `;
@@ -24,8 +24,8 @@ import '../../../assets/clappr-nerd-stats/clappr-nerd-stats.scss'
24
24
  import pluginHtml from '../../../assets/clappr-nerd-stats/clappr-nerd-stats.ejs'
25
25
  import buttonHtml from '../../../assets/clappr-nerd-stats/button.ejs'
26
26
  import statsIcon from '../../../assets/icons/new/stats.svg'
27
- import { BottomGear, GearEvents } from '../bottom-gear/BottomGear.js'
28
- import { MediaControl } from '../media-control/MediaControl.js'
27
+ import { BottomGear } from '../bottom-gear/BottomGear.js'
28
+ import { MediaControl, MediaControlEvents } from '../media-control/MediaControl.js'
29
29
  import assert from 'assert'
30
30
 
31
31
  const qualityClasses = [
@@ -229,7 +229,7 @@ export class ClapprNerdStats extends UICorePlugin {
229
229
  this.listenToOnce(this.core, Events.CORE_READY, this.init)
230
230
  this.listenTo(
231
231
  mediaControl,
232
- GearEvents.MEDIACONTROL_GEAR_RENDERED,
232
+ MediaControlEvents.MEDIACONTROL_GEAR_RENDERED,
233
233
  this.addToBottomGear,
234
234
  )
235
235
  }
@@ -1,10 +1,13 @@
1
- import { Core, Events, Playback, UICorePlugin, template } from '@clappr/core';
2
- import assert from 'assert';
1
+ import { Core, Events, Playback, UICorePlugin, template } from '@clappr/core'
2
+ import assert from 'assert'
3
3
 
4
- import { CLAPPR_VERSION } from '../../build.js';
4
+ import { CLAPPR_VERSION } from '../../build.js'
5
5
 
6
- import dvrHTML from '../../../assets/dvr-controls/index.ejs';
7
- import '../../../assets/dvr-controls/dvr_controls.scss';
6
+ import dvrHTML from '../../../assets/dvr-controls/index.ejs'
7
+ import '../../../assets/dvr-controls/dvr_controls.scss'
8
+ import { trace } from '@gcorevideo/utils'
9
+
10
+ const T = 'plugins.dvr_controls'
8
11
 
9
12
  /**
10
13
  * Adds the DVR controls to the media control UI
@@ -18,20 +21,20 @@ import '../../../assets/dvr-controls/dvr_controls.scss';
18
21
  * The plugin renders the live stream indicator and the DVR seek bar, if DVR is enabled, in the media control UI.
19
22
  */
20
23
  export class DvrControls extends UICorePlugin {
21
- private static readonly template = template(dvrHTML);
24
+ private static readonly template = template(dvrHTML)
22
25
 
23
26
  /**
24
27
  * @internal
25
28
  */
26
29
  get name() {
27
- return 'dvr_controls';
30
+ return 'dvr_controls'
28
31
  }
29
32
 
30
33
  /**
31
34
  * @internal
32
35
  */
33
36
  get supportedVersion() {
34
- return { min: CLAPPR_VERSION };
37
+ return { min: CLAPPR_VERSION }
35
38
  }
36
39
 
37
40
  /**
@@ -39,8 +42,8 @@ export class DvrControls extends UICorePlugin {
39
42
  */
40
43
  override get events() {
41
44
  return {
42
- 'click .live-button': 'click'
43
- };
45
+ 'click .live-button': 'click',
46
+ }
44
47
  }
45
48
 
46
49
  /**
@@ -48,96 +51,126 @@ export class DvrControls extends UICorePlugin {
48
51
  */
49
52
  override get attributes() {
50
53
  return {
51
- 'class': 'dvr-controls',
52
- 'data-dvr-controls': ''
53
- };
54
+ class: 'dvr-controls',
55
+ 'data-dvr-controls': '',
56
+ }
54
57
  }
55
58
 
56
59
  constructor(core: Core) {
57
- super(core);
58
- this.settingsUpdate();
60
+ super(core)
61
+ this.settingsUpdate()
59
62
  }
60
63
 
61
64
  /**
62
65
  * @internal
63
66
  */
64
67
  override bindEvents() {
65
- const mediaControl = this.core.getPlugin('media_control');
66
- assert(mediaControl, 'media_control plugin is required');
67
- this.listenTo(mediaControl, Events.MEDIACONTROL_RENDERED, this.settingsUpdate);
68
- this.listenTo(this.core, Events.CORE_OPTIONS_CHANGE, this.render);
69
- this.listenTo(this.core, Events.CORE_ACTIVE_CONTAINER_CHANGED, this.bindContainerEvents);
68
+ const mediaControl = this.core.getPlugin('media_control')
69
+ assert(mediaControl, 'media_control plugin is required')
70
+ this.listenTo(
71
+ mediaControl,
72
+ Events.MEDIACONTROL_RENDERED,
73
+ this.settingsUpdate,
74
+ )
75
+ this.listenTo(this.core, Events.CORE_OPTIONS_CHANGE, this.render)
76
+ this.listenTo(
77
+ this.core,
78
+ Events.CORE_ACTIVE_CONTAINER_CHANGED,
79
+ this.bindContainerEvents,
80
+ )
70
81
  }
71
82
 
72
83
  private bindContainerEvents() {
73
- this.listenToOnce(this.core.activeContainer, Events.CONTAINER_TIMEUPDATE, this.render);
74
- this.listenTo(this.core.activeContainer, Events.CONTAINER_PLAYBACKDVRSTATECHANGED, this.dvrChanged);
84
+ this.listenToOnce(
85
+ this.core.activeContainer,
86
+ Events.CONTAINER_TIMEUPDATE,
87
+ this.render,
88
+ )
89
+ this.listenTo(
90
+ this.core.activeContainer,
91
+ Events.CONTAINER_PLAYBACKDVRSTATECHANGED,
92
+ this.onDvrChanged,
93
+ )
75
94
  }
76
95
 
77
- private dvrChanged(dvrEnabled: boolean) {
96
+ private onDvrChanged(dvrEnabled: boolean) {
97
+ trace(`${T} onDvrChanged`, {
98
+ dvrEnabled,
99
+ })
78
100
  if (this.core.getPlaybackType() !== Playback.LIVE) {
79
- return;
101
+ return
80
102
  }
81
- this.settingsUpdate();
82
- this.core.mediaControl.$el.addClass('live');
103
+ this.settingsUpdate()
104
+ this.core.mediaControl.$el.addClass('live')
83
105
  if (dvrEnabled) {
84
- this.core.mediaControl.$playbackRate.removeClass('playbackrate-enable');
106
+ // TODO
85
107
  this.core.mediaControl.$el
86
108
  .addClass('dvr')
87
- .find('.media-control-indicator[data-position], .media-control-indicator[data-duration]')
88
- .hide();
109
+ .find(
110
+ '.media-control-indicator[data-position], .media-control-indicator[data-duration]',
111
+ )
112
+ .hide()
89
113
  } else {
90
- this.core.mediaControl.$playbackRate.addClass('playbackrate-enable');
91
- this.core.mediaControl.$el.removeClass('dvr');
114
+ this.core.mediaControl.$el.removeClass('dvr')
92
115
  }
93
116
  }
94
117
 
95
118
  private click() {
96
- const mediaControl = this.core.getPlugin('media_control');
97
- const container = this.core.activeContainer;
119
+ const mediaControl = this.core.getPlugin('media_control')
120
+ const container = this.core.activeContainer
98
121
 
99
122
  if (!container.isPlaying()) {
100
- container.play();
123
+ container.play()
101
124
  }
102
125
 
103
126
  if (mediaControl.$el.hasClass('dvr')) {
104
- container.seek(container.getDuration());
127
+ container.seek(container.getDuration())
105
128
  }
106
129
  }
107
130
 
108
131
  private settingsUpdate() {
109
132
  // @ts-ignore
110
- this.stopListening(); // TODO sort out
111
- this.core.getPlugin('media_control').$el.removeClass('live'); // TODO don't access directly
133
+ this.stopListening() // TODO sort out
134
+ this.core.getPlugin('media_control').$el.removeClass('live') // TODO don't access directly
112
135
  if (this.shouldRender()) {
113
- this.render();
114
- this.$el.click(() => this.click());
136
+ this.render()
137
+ this.$el.click(() => this.click())
115
138
  }
116
- this.bindEvents();
139
+ this.bindEvents()
117
140
  }
118
141
 
119
142
  private shouldRender() {
120
- const useDvrControls = this.core.options.useDvrControls === undefined || !!this.core.options.useDvrControls;
143
+ const useDvrControls =
144
+ this.core.options.useDvrControls === undefined ||
145
+ !!this.core.options.useDvrControls
121
146
 
122
- return useDvrControls && this.core.getPlaybackType() === Playback.LIVE;
147
+ return useDvrControls && this.core.getPlaybackType() === Playback.LIVE
123
148
  }
124
149
 
125
150
  /**
126
151
  * @internal
127
152
  */
128
153
  override render() {
129
- this.$el.html(DvrControls.template({
130
- live: this.core.i18n.t('live'),
131
- backToLive: this.core.i18n.t('back_to_live')
132
- }));
133
- if (this.shouldRender()) {
134
- const mediaControl = this.core.getPlugin('media_control');
135
- assert(mediaControl, 'media_control plugin is required');
136
- // TODO don't tap into the $el directly
137
- mediaControl.$el.addClass('live');
138
- mediaControl.$('.media-control-left-panel[data-media-control]').append(this.$el);
154
+ trace(`${T} render`, {
155
+ dvrEnabled: this.core.activePlayback?.dvrEnabled,
156
+ })
157
+ if (!this.shouldRender()) {
158
+ return this
139
159
  }
140
-
141
- return this;
160
+ this.$el.html(
161
+ DvrControls.template({
162
+ live: this.core.i18n.t('live'),
163
+ backToLive: this.core.i18n.t('back_to_live'),
164
+ }),
165
+ )
166
+ const mediaControl = this.core.getPlugin('media_control')
167
+ assert(mediaControl, 'media_control plugin is required')
168
+ // TODO don't tap into the $el directly
169
+ mediaControl.$el.addClass('live')
170
+ mediaControl
171
+ .$('.media-control-left-panel[data-media-control]')
172
+ .append(this.$el)
173
+
174
+ return this
142
175
  }
143
176
  }