@gcorevideo/player 2.21.4 → 2.22.0

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.
@@ -19,6 +19,12 @@ import volumeMaxIcon from '../../../assets/icons/new/volume-max.svg';
19
19
  import volumeOffIcon from '../../../assets/icons/new/volume-off.svg';
20
20
  import fullscreenOffIcon from '../../../assets/icons/new/fullscreen-off.svg';
21
21
  import fullscreenOnIcon from '../../../assets/icons/new/fullscreen-on.svg';
22
+ const DEFAULT_SETTINGS = {
23
+ left: [],
24
+ right: [],
25
+ default: [],
26
+ seekEnabled: true,
27
+ };
22
28
  /**
23
29
  * Custom events emitted by the plugins to communicate with one another
24
30
  * @beta
@@ -34,7 +40,8 @@ const T = 'plugins.media_control';
34
40
  const LEFT_ORDER = [
35
41
  'playpause',
36
42
  'playstop',
37
- 'live',
43
+ // 'live',
44
+ 'dvr',
38
45
  'volume',
39
46
  'position',
40
47
  'duration',
@@ -68,14 +75,13 @@ export class MediaControl extends UICorePlugin {
68
75
  hideId = null;
69
76
  hideVolumeId = null;
70
77
  intendedVolume = 100;
71
- isHD = false;
72
78
  keepVisible = false;
73
79
  kibo;
74
80
  lastMouseX = 0;
75
81
  lastMouseY = 0;
76
82
  persistConfig;
77
83
  rendered = false;
78
- settings = {}; // TODO & seekEnabled: boolean, ...
84
+ settings = DEFAULT_SETTINGS;
79
85
  userDisabled = false;
80
86
  userKeepVisible = false;
81
87
  verticalVolume = false;
@@ -219,8 +225,6 @@ export class MediaControl extends UICorePlugin {
219
225
  * @internal
220
226
  */
221
227
  bindEvents() {
222
- // @ts-ignore
223
- this.stopListening();
224
228
  this.listenTo(this.core, Events.CORE_ACTIVE_CONTAINER_CHANGED, this.onActiveContainerChanged);
225
229
  this.listenTo(this.core, Events.CORE_MOUSE_MOVE, this.show);
226
230
  this.listenTo(this.core, Events.CORE_MOUSE_LEAVE, () => this.hide(this.options.hideMediaControlDelay));
@@ -257,8 +261,8 @@ export class MediaControl extends UICorePlugin {
257
261
  this.listenTo(this.core.activeContainer, Events.CONTAINER_TIMEUPDATE, this.onTimeUpdate);
258
262
  this.listenTo(this.core.activeContainer, Events.CONTAINER_PROGRESS, this.updateProgressBar);
259
263
  this.listenTo(this.core.activeContainer, Events.CONTAINER_SETTINGSUPDATE, this.updateSettings);
260
- this.listenTo(this.core.activeContainer, Events.CONTAINER_PLAYBACKDVRSTATECHANGED, this.updateSettings);
261
- this.listenTo(this.core.activeContainer, Events.CONTAINER_HIGHDEFINITIONUPDATE, this.highDefinitionUpdate);
264
+ this.listenTo(this.core.activeContainer, Events.CONTAINER_PLAYBACKDVRSTATECHANGED, this.onDvrStateChanged);
265
+ this.listenTo(this.core.activeContainer, Events.CONTAINER_HIGHDEFINITIONUPDATE, this.onHdUpdate);
262
266
  this.listenTo(this.core.activeContainer, Events.CONTAINER_MEDIACONTROL_DISABLE, this.disable);
263
267
  this.listenTo(this.core.activeContainer, Events.CONTAINER_MEDIACONTROL_ENABLE, this.enable);
264
268
  this.listenTo(this.core.activeContainer, Events.CONTAINER_ENDED, this.ended);
@@ -306,7 +310,13 @@ export class MediaControl extends UICorePlugin {
306
310
  // see https://github.com/clappr/clappr/issues/1127
307
311
  if (!Fullscreen.fullscreenEnabled() && video.webkitSupportsFullscreen) {
308
312
  this.fullScreenOnVideoTagSupported = true;
309
- this.updateSettings();
313
+ }
314
+ this.updateSettings();
315
+ if (this.core.activeContainer.getPlaybackType() === Playback.LIVE) {
316
+ this.$el.addClass('live');
317
+ }
318
+ else {
319
+ this.$el.removeClass('live');
310
320
  }
311
321
  }
312
322
  updateVolumeUI() {
@@ -315,8 +325,6 @@ export class MediaControl extends UICorePlugin {
315
325
  return;
316
326
  }
317
327
  assert.ok(this.$volumeBarContainer, 'volume bar container must be present');
318
- // update volume bar scrubber/fill on bar mode
319
- // this.$volumeBarContainer.find('.bar-fill-2').css({});
320
328
  const containerWidth = this.$volumeBarContainer.width();
321
329
  assert.ok(this.$volumeBarBackground, 'volume bar background must be present');
322
330
  const barWidth = this.$volumeBarBackground.width();
@@ -505,17 +513,18 @@ export class MediaControl extends UICorePlugin {
505
513
  // if the container is not ready etc
506
514
  this.intendedVolume = value;
507
515
  this.persistConfig && !isInitialVolume && Config.persist('volume', value);
516
+ // TODO
508
517
  const setWhenContainerReady = () => {
509
- if (this.container && this.container.isReady) {
510
- this.container.setVolume(value);
518
+ if (this.core.activeContainer && this.core.activeContainer.isReady) {
519
+ this.core.activeContainer.setVolume(value);
511
520
  }
512
521
  else {
513
- this.listenToOnce(this.container, Events.CONTAINER_READY, () => {
514
- this.container.setVolume(value);
522
+ this.listenToOnce(this.core.activeContainer, Events.CONTAINER_READY, () => {
523
+ this.core.activeContainer.setVolume(value);
515
524
  });
516
525
  }
517
526
  };
518
- if (!this.container) {
527
+ if (!this.core.activeContainer) {
519
528
  this.listenToOnce(this, Events.MEDIACONTROL_CONTAINERCHANGED, () => setWhenContainerReady());
520
529
  }
521
530
  else {
@@ -525,7 +534,7 @@ export class MediaControl extends UICorePlugin {
525
534
  toggleFullscreen() {
526
535
  if (!Browser.isMobile) {
527
536
  this.trigger(Events.MEDIACONTROL_FULLSCREEN, this.name);
528
- this.container.fullscreen();
537
+ this.core.activeContainer.fullscreen();
529
538
  this.core.toggleFullscreen();
530
539
  this.resetUserKeepVisible();
531
540
  }
@@ -537,6 +546,7 @@ export class MediaControl extends UICorePlugin {
537
546
  this.changeTogglePlay();
538
547
  this.bindContainerEvents();
539
548
  this.updateSettings();
549
+ // TODO remove
540
550
  this.core.activeContainer.trigger(Events.CONTAINER_PLAYBACKDVRSTATECHANGED, this.core.activeContainer.isDvrInUse());
541
551
  // TODO test
542
552
  if (this.core.activeContainer.mediaControlDisabled) {
@@ -561,7 +571,9 @@ export class MediaControl extends UICorePlugin {
561
571
  seekTimePlugin?.$el.find('span').addClass('gcore-skin-text-color');
562
572
  }
563
573
  showVolumeBar() {
564
- this.hideVolumeId && clearTimeout(this.hideVolumeId);
574
+ if (this.hideVolumeId) {
575
+ clearTimeout(this.hideVolumeId);
576
+ }
565
577
  this.$volumeBarContainer?.removeClass('volume-bar-hide');
566
578
  }
567
579
  hideVolumeBar(timeout = 400) {
@@ -607,9 +619,9 @@ export class MediaControl extends UICorePlugin {
607
619
  }
608
620
  // default to 100%
609
621
  this.currentSeekBarPercentage = 100;
610
- if (this.container &&
611
- (this.container.getPlaybackType() !== Playback.LIVE ||
612
- this.container.isDvrInUse())) {
622
+ if (this.core.activeContainer &&
623
+ (this.core.activeContainer.getPlaybackType() !== Playback.LIVE ||
624
+ this.core.activeContainer.isDvrInUse())) {
613
625
  this.currentSeekBarPercentage =
614
626
  (this.currentPositionValue / this.currentDurationValue) * 100;
615
627
  }
@@ -636,16 +648,10 @@ export class MediaControl extends UICorePlugin {
636
648
  const offsetX = MediaControl.getPageX(event) - this.$seekBarContainer.offset().left;
637
649
  let pos = (offsetX / this.$seekBarContainer.width()) * 100;
638
650
  pos = Math.min(100, Math.max(pos, 0));
639
- this.container && this.container.seekPercentage(pos);
651
+ this.core.activeContainer && this.core.activeContainer.seekPercentage(pos);
640
652
  this.setSeekPercentage(pos);
641
653
  return false;
642
654
  }
643
- setKeepVisible() {
644
- this.keepVisible = true;
645
- }
646
- resetKeepVisible() {
647
- this.keepVisible = false;
648
- }
649
655
  setUserKeepVisible() {
650
656
  this.userKeepVisible = true;
651
657
  }
@@ -723,7 +729,12 @@ export class MediaControl extends UICorePlugin {
723
729
  default: [],
724
730
  right: [],
725
731
  }, this.core.activeContainer.settings);
732
+ // TODO make order controlled via CSS
726
733
  newSettings.left = orderByOrderPattern([...newSettings.left, 'clipsText', 'volume'], LEFT_ORDER);
734
+ if (this.core.activePlayback.getPlaybackType() === Playback.LIVE &&
735
+ this.core.activePlayback.dvrEnabled) {
736
+ newSettings.left.push('dvr');
737
+ }
727
738
  // actual order of the items appear rendered is controlled by CSS
728
739
  newSettings.right = [
729
740
  'fullscreen',
@@ -745,17 +756,18 @@ export class MediaControl extends UICorePlugin {
745
756
  }
746
757
  removeArrayItem(newSettings.default, 'hd-indicator');
747
758
  removeArrayItem(newSettings.left, 'hd-indicator');
759
+ // TODO get from container's settings
748
760
  if (this.core.activePlayback.name === 'html5_video') {
749
761
  newSettings.seekEnabled = this.isSeekEnabledForHtml5Playback();
750
762
  }
751
- const settingsChanged = JSON.stringify(this.settings) !== JSON.stringify(newSettings);
763
+ const settingsChanged = serializeSettings(this.settings) !== serializeSettings(newSettings);
752
764
  if (settingsChanged) {
753
765
  this.settings = newSettings;
754
766
  this.render();
755
767
  }
756
768
  }
757
- highDefinitionUpdate(isHD) {
758
- this.isHD = isHD;
769
+ onHdUpdate(isHD) {
770
+ // TODO render?
759
771
  }
760
772
  createCachedElements() {
761
773
  const $layer = this.$el.find('.media-control-layer');
@@ -818,7 +830,7 @@ export class MediaControl extends UICorePlugin {
818
830
  trace(`${T} putElement`, { name, panel: !!panel });
819
831
  if (panel) {
820
832
  const current = panel.find(`[data-${name}]`);
821
- element.setAttribute(`data-${name}`, "");
833
+ element.setAttribute(`data-${name}`, '');
822
834
  // TODO test
823
835
  if (current.length) {
824
836
  if (current[0] === element) {
@@ -832,16 +844,16 @@ export class MediaControl extends UICorePlugin {
832
844
  }
833
845
  }
834
846
  /**
835
- * Get the right panel area to append custom elements to
836
- * @returns ZeptoSelector of the right panel element
847
+ * Toggle the visibility of a media control element
848
+ * @param name - The name of the media control element
849
+ * @param show - Whether to show or hide the element
837
850
  */
851
+ toggleElement(name, show) {
852
+ this.$el.find(`[data-${name}]`).toggle(show);
853
+ }
838
854
  getRightPanel() {
839
855
  return this.$el.find('.media-control-right-panel');
840
856
  }
841
- /**
842
- * Get the left panel area to append custom elements to
843
- * @returns ZeptoSelector of the left panel element
844
- */
845
857
  getLeftPanel() {
846
858
  return this.$el.find('.media-control-left-panel');
847
859
  }
@@ -1040,7 +1052,6 @@ export class MediaControl extends UICorePlugin {
1040
1052
  this.hideVolumeBar(0);
1041
1053
  }, 0);
1042
1054
  this.parseColors();
1043
- this.highDefinitionUpdate(this.isHD);
1044
1055
  this.core.$el.append(this.el);
1045
1056
  this.rendered = true;
1046
1057
  this.updateVolumeUI();
@@ -1127,7 +1138,24 @@ export class MediaControl extends UICorePlugin {
1127
1138
  }
1128
1139
  return null;
1129
1140
  }
1141
+ onDvrStateChanged(dvrInUse) {
1142
+ if (dvrInUse) {
1143
+ this.$el.addClass('dvr');
1144
+ }
1145
+ else {
1146
+ this.$el.removeClass('dvr');
1147
+ }
1148
+ }
1130
1149
  }
1131
1150
  MediaControl.extend = function (properties) {
1132
1151
  return extend(MediaControl, properties);
1133
1152
  };
1153
+ function serializeSettings(s) {
1154
+ return s.left
1155
+ .slice()
1156
+ .sort()
1157
+ .concat(s.right.slice().sort())
1158
+ .concat(s.default.slice().sort())
1159
+ .concat([s.seekEnabled])
1160
+ .join(',');
1161
+ }
@@ -65,7 +65,9 @@ export declare function createSpinnerPlugin(): Events<string | symbol, any> & {
65
65
  export declare function createMockPlayback(name?: string): Events<string | symbol, any> & {
66
66
  name: string;
67
67
  currentLevel: number;
68
+ el: HTMLVideoElement;
68
69
  dvrEnabled: boolean;
70
+ dvrInUse: boolean;
69
71
  levels: never[];
70
72
  consent(): void;
71
73
  play(): void;
@@ -92,13 +94,14 @@ export declare function createMockPlayback(name?: string): Events<string | symbo
92
94
  trigger: <T extends string | symbol>(event: T, ...args: any[]) => boolean;
93
95
  };
94
96
  export declare function createMockContainer(playback?: any): Events<string | symbol, any> & {
95
- el: HTMLDivElement;
97
+ el: any;
96
98
  playback: any;
97
99
  $el: any;
98
100
  getDuration: import("vitest").Mock<(...args: any[]) => any>;
99
101
  getPlugin: import("vitest").Mock<(...args: any[]) => any>;
100
102
  getPlaybackType: import("vitest").Mock<(...args: any[]) => any>;
101
103
  isDvrInUse: import("vitest").Mock<(...args: any[]) => any>;
104
+ isDvrEnabled: import("vitest").Mock<(...args: any[]) => any>;
102
105
  isPlaying: import("vitest").Mock<(...args: any[]) => any>;
103
106
  play: import("vitest").Mock<(...args: any[]) => any>;
104
107
  seek: import("vitest").Mock<(...args: any[]) => any>;
@@ -1 +1 @@
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,CAC5B,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACrC,SAAS,GAAE,GAA2B;;;;;;;;;;;;;;;;EAqBvC;AAED,wBAAgB,gBAAgB;;;EAK/B;AAED,wBAAgB,mBAAmB;;;;;;EAKlC;AAED,wBAAgB,kBAAkB,CAAC,IAAI,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+B/C;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,GAAE,GAA0B;;;;;;;;;;;;EAgBvE;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,GAAG,gBAqB/C"}
1
+ {"version":3,"file":"testUtils.d.ts","sourceRoot":"","sources":["../src/testUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,YAAY,EAAE,MAAM,cAAc,CAAA;AACxD,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,CAC5B,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACrC,SAAS,GAAE,GAA2B;;;;;;;;;;;;;;;;EAqBvC;AAED,wBAAgB,gBAAgB;;;EAK/B;AAED,wBAAgB,mBAAmB;;;;;;EAKlC;AAED,wBAAgB,kBAAkB,CAAC,IAAI,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiC/C;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,GAAE,GAA0B;;;;;;;;;;;;;EAiBvE;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,GAAG,gBAiB/C"}
package/lib/testUtils.js CHANGED
@@ -1,4 +1,4 @@
1
- import { $, UICorePlugin } from '@clappr/core';
1
+ import { $, Playback, UICorePlugin } from '@clappr/core';
2
2
  import Events from 'eventemitter3';
3
3
  import { vi } from 'vitest';
4
4
  /**
@@ -32,7 +32,7 @@ export class _MockPlayback extends Events {
32
32
  enterPiP() { }
33
33
  exitPiP() { }
34
34
  getPlaybackType() {
35
- return 'live';
35
+ return Playback.LIVE;
36
36
  }
37
37
  getStartTimeOffset() {
38
38
  return 0;
@@ -75,7 +75,7 @@ export function createMockCore(options = {}, container = createMockContainer())
75
75
  ...options,
76
76
  },
77
77
  configure: vi.fn(),
78
- getPlaybackType: vi.fn(),
78
+ getPlaybackType: vi.fn().mockReturnValue(Playback.LIVE),
79
79
  getPlugin: vi.fn(),
80
80
  load: vi.fn(),
81
81
  trigger: emitter.emit,
@@ -98,7 +98,9 @@ export function createMockPlayback(name = 'mock') {
98
98
  return Object.assign(emitter, {
99
99
  name,
100
100
  currentLevel: -1,
101
+ el: document.createElement('video'),
101
102
  dvrEnabled: false,
103
+ dvrInUse: false,
102
104
  levels: [],
103
105
  consent() { },
104
106
  play() { },
@@ -110,7 +112,7 @@ export function createMockPlayback(name = 'mock') {
110
112
  getDuration: vi.fn().mockImplementation(() => 100),
111
113
  enterPiP: vi.fn(),
112
114
  exitPiP: vi.fn(),
113
- getPlaybackType: vi.fn().mockImplementation(() => 'live'),
115
+ getPlaybackType: vi.fn().mockImplementation(() => Playback.LIVE),
114
116
  getStartTimeOffset: vi.fn().mockImplementation(() => 0),
115
117
  getCurrentTime: vi.fn().mockImplementation(() => 0),
116
118
  isHighDefinitionInUse: vi.fn().mockImplementation(() => false),
@@ -126,7 +128,7 @@ export function createMockPlayback(name = 'mock') {
126
128
  });
127
129
  }
128
130
  export function createMockContainer(playback = createMockPlayback()) {
129
- const el = document.createElement('div');
131
+ const el = playback.el;
130
132
  const emitter = new Events();
131
133
  return Object.assign(emitter, {
132
134
  el,
@@ -134,8 +136,9 @@ export function createMockContainer(playback = createMockPlayback()) {
134
136
  $el: $(el),
135
137
  getDuration: vi.fn().mockReturnValue(0),
136
138
  getPlugin: vi.fn(),
137
- getPlaybackType: vi.fn().mockReturnValue('live'),
139
+ getPlaybackType: vi.fn().mockReturnValue(Playback.LIVE),
138
140
  isDvrInUse: vi.fn().mockReturnValue(false),
141
+ isDvrEnabled: vi.fn().mockReturnValue(false),
139
142
  isPlaying: vi.fn().mockReturnValue(false),
140
143
  play: vi.fn(),
141
144
  seek: vi.fn(),
@@ -155,10 +158,6 @@ export function createMockMediaControl(core) {
155
158
  // @ts-ignore
156
159
  mediaControl.putElement = vi.fn();
157
160
  // @ts-ignore
158
- mediaControl.getLeftPanel = vi.fn().mockImplementation(() => mediaControl.$el.find('.media-control-left-panel'));
159
- // @ts-ignore
160
- mediaControl.getRightPanel = vi.fn().mockImplementation(() => mediaControl.$el.find('.media-control-right-panel'));
161
- // @ts-ignore
162
- mediaControl.getCenterPanel = vi.fn().mockImplementation(() => mediaControl.$el.find('.media-control-center-panel'));
161
+ mediaControl.toggleElement = vi.fn();
163
162
  return mediaControl;
164
163
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gcorevideo/player",
3
- "version": "2.21.4",
3
+ "version": "2.22.0",
4
4
  "description": "Gcore JavaScript video player",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -56,7 +56,6 @@ export class DvrControls extends UICorePlugin {
56
56
  override get attributes() {
57
57
  return {
58
58
  class: 'dvr-controls',
59
- 'data-dvr-controls': '',
60
59
  }
61
60
  }
62
61
 
@@ -65,7 +64,6 @@ export class DvrControls extends UICorePlugin {
65
64
  */
66
65
  override bindEvents() {
67
66
  this.listenTo(this.core, Events.CORE_READY, this.onCoreReady)
68
- this.listenTo(this.core, Events.CORE_OPTIONS_CHANGE, this.render)
69
67
  this.listenTo(
70
68
  this.core,
71
69
  Events.CORE_ACTIVE_CONTAINER_CHANGED,
@@ -76,48 +74,23 @@ export class DvrControls extends UICorePlugin {
76
74
  private onCoreReady() {
77
75
  const mediaControl = this.core.getPlugin('media_control')
78
76
  assert(mediaControl, 'media_control plugin is required')
77
+
79
78
  this.listenTo(
80
79
  mediaControl,
81
80
  Events.MEDIACONTROL_RENDERED,
82
- this.settingsUpdate,
81
+ this.render,
83
82
  )
84
- this.settingsUpdate()
83
+ // MediaControl has been rendered
84
+ this.render()
85
85
  }
86
86
 
87
87
  private bindContainerEvents() {
88
+ trace(`${T} bindContainerEvents`)
88
89
  this.listenToOnce(
89
90
  this.core.activeContainer,
90
91
  Events.CONTAINER_TIMEUPDATE,
91
92
  this.render,
92
93
  )
93
- this.listenTo(
94
- this.core.activeContainer,
95
- Events.CONTAINER_PLAYBACKDVRSTATECHANGED,
96
- this.onDvrChanged,
97
- )
98
- }
99
-
100
- private onDvrChanged(dvrInUse: boolean) {
101
- trace(`${T} onDvrChanged`, {
102
- dvrInUse,
103
- })
104
- if (this.core.getPlaybackType() !== Playback.LIVE) {
105
- return
106
- }
107
- this.render()
108
- const mediaControl = this.core.getPlugin('media_control')
109
- mediaControl.$el.addClass('live')
110
- if (dvrInUse) {
111
- mediaControl.$el
112
- .addClass('dvr')
113
- .find(
114
- // TODO add API, test
115
- '.media-control-indicator[data-position], .media-control-indicator[data-duration]',
116
- )
117
- .hide()
118
- } else {
119
- mediaControl.$el.removeClass('dvr')
120
- }
121
94
  }
122
95
 
123
96
  private click() {
@@ -128,14 +101,8 @@ export class DvrControls extends UICorePlugin {
128
101
  container.seek(container.getDuration())
129
102
  }
130
103
 
131
- private settingsUpdate() {
132
- this.core.getPlugin('media_control').$el.removeClass('live')
133
- this.render()
134
- }
135
-
136
104
  private shouldRender() {
137
- const useDvrControls = this.core.options.useDvrControls !== false
138
- return useDvrControls && this.core.getPlaybackType() === Playback.LIVE
105
+ return this.core.getPlaybackType() === Playback.LIVE
139
106
  }
140
107
 
141
108
  /**
@@ -146,18 +113,23 @@ export class DvrControls extends UICorePlugin {
146
113
  dvrEnabled: this.core.activePlayback?.dvrEnabled,
147
114
  playbackType: this.core.getPlaybackType(),
148
115
  })
116
+ const mediaControl = this.core.getPlugin('media_control') as MediaControl
117
+ if (!mediaControl) {
118
+ return this
119
+ }
149
120
  if (!this.shouldRender()) {
150
121
  return this
151
122
  }
123
+
124
+ mediaControl.toggleElement('duration', false)
125
+ mediaControl.toggleElement('position', false)
126
+
152
127
  this.$el.html(
153
128
  DvrControls.template({
154
- live: this.core.i18n.t('live'),
155
- backToLive: this.core.i18n.t('back_to_live'),
129
+ i18n: this.core.i18n,
156
130
  }),
157
131
  )
158
- const mediaControl = this.core.getPlugin('media_control') as MediaControl
159
- mediaControl.$el.addClass('live')
160
- mediaControl.getLeftPanel().append(this.$el)
132
+ mediaControl.putElement('dvr', this.el)
161
133
 
162
134
  return this
163
135
  }
@@ -1,6 +1,7 @@
1
1
  import { beforeEach, describe, expect, it, vi } from 'vitest'
2
2
  import { DvrControls } from '../DvrControls.js'
3
3
  import { createMockCore, createMockMediaControl } from '../../../testUtils.js'
4
+ import { Events, Playback } from '@clappr/core'
4
5
  // import { LogTracer, Logger, setTracer } from '@gcorevideo/utils'
5
6
 
6
7
  // setTracer(new LogTracer('DvrControls.test'))
@@ -28,36 +29,29 @@ describe('DvrControls', () => {
28
29
  describe.each([
29
30
  ['no DVR', false, false, false],
30
31
  ['DVR at live edge', true, false, false],
31
- ['DVR behind live edge', true, true, true],
32
- ])('%s', (_, dvrEnabled, dvrInUse, indicateDvr) => {
32
+ ])('%s', (_, dvrEnabled, dvrInUse) => {
33
33
  beforeEach(() => {
34
34
  core.activePlayback.dvrEnabled = dvrEnabled
35
- core.trigger('core:ready')
36
- core.trigger('core:active:container:changed')
35
+ core.activeContainer.isDvrEnabled.mockReturnValue(dvrEnabled)
36
+ core.trigger(Events.CORE_READY)
37
+ core.trigger(Events.CORE_ACTIVE_CONTAINER_CHANGED, core.activeContainer)
37
38
  if (dvrInUse) {
38
- core.activeContainer.trigger('container:dvr', true)
39
+ core.activePlayback.dvrInUse = true
40
+ core.activeContainer.isDvrInUse.mockReturnValue(true)
41
+ core.activeContainer.emit(Events.CONTAINER_PLAYBACKDVRSTATECHANGED, true)
39
42
  }
40
43
  })
41
44
  it('should render', () => {
42
45
  expect(dvrControls.el.textContent).toBeTruthy()
43
46
  expect(dvrControls.el.innerHTML).toMatchSnapshot()
44
47
  })
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
+ it('should hide duration and position indicators', () => {
49
+ expect(mediaControl.toggleElement).toHaveBeenCalledWith('duration', false)
50
+ expect(mediaControl.toggleElement).toHaveBeenCalledWith('position', false)
48
51
  })
49
- it('should indicate live streaming mode', () => {
50
- expect(mediaControl.$el.hasClass('live')).toBe(true)
52
+ it('should render to the media control', () => {
53
+ expect(mediaControl.putElement).toHaveBeenCalledWith('dvr', dvrControls.el)
51
54
  })
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
55
  })
62
56
  describe('when back_to_live button is clicked', () => {
63
57
  beforeEach(() => {
@@ -76,16 +70,20 @@ describe('DvrControls', () => {
76
70
  })
77
71
  })
78
72
  })
79
- describe('VOD stream', () => {
73
+ describe('basically', () => {
80
74
  beforeEach(() => {
81
- core.getPlaybackType.mockReturnValue('vod')
75
+ core.getPlaybackType.mockReturnValue(Playback.VOD)
76
+ core.activeContainer.getPlaybackType.mockReturnValue(Playback.VOD)
77
+ core.activePlayback.getPlaybackType.mockReturnValue(Playback.VOD)
82
78
  })
83
79
  beforeEach(() => {
84
- core.trigger('core:ready')
85
- core.trigger('core:active:container:changed')
80
+ core.trigger(Events.CORE_READY)
81
+ core.trigger(Events.CORE_ACTIVE_CONTAINER_CHANGED, core.activeContainer)
86
82
  })
87
- it('should not render', () => {
88
- expect(dvrControls.el.textContent).toBeFalsy()
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')
89
87
  })
90
88
  })
91
89
  })
@@ -1,43 +1,19 @@
1
1
  // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
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>
3
+ exports[`DvrControls > basically > should render 1`] = `
4
+ "<div class="live-info" id="media-control-live">live</div>
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
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>
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>
20
12
  "
21
13
  `;
22
14
 
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
15
  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>
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>
34
18
  "
35
19
  `;
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
- `;