@gcorevideo/player 2.21.4 → 2.21.6

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) {
@@ -607,9 +617,9 @@ export class MediaControl extends UICorePlugin {
607
617
  }
608
618
  // default to 100%
609
619
  this.currentSeekBarPercentage = 100;
610
- if (this.container &&
611
- (this.container.getPlaybackType() !== Playback.LIVE ||
612
- this.container.isDvrInUse())) {
620
+ if (this.core.activeContainer &&
621
+ (this.core.activeContainer.getPlaybackType() !== Playback.LIVE ||
622
+ this.core.activeContainer.isDvrInUse())) {
613
623
  this.currentSeekBarPercentage =
614
624
  (this.currentPositionValue / this.currentDurationValue) * 100;
615
625
  }
@@ -636,16 +646,10 @@ export class MediaControl extends UICorePlugin {
636
646
  const offsetX = MediaControl.getPageX(event) - this.$seekBarContainer.offset().left;
637
647
  let pos = (offsetX / this.$seekBarContainer.width()) * 100;
638
648
  pos = Math.min(100, Math.max(pos, 0));
639
- this.container && this.container.seekPercentage(pos);
649
+ this.core.activeContainer && this.core.activeContainer.seekPercentage(pos);
640
650
  this.setSeekPercentage(pos);
641
651
  return false;
642
652
  }
643
- setKeepVisible() {
644
- this.keepVisible = true;
645
- }
646
- resetKeepVisible() {
647
- this.keepVisible = false;
648
- }
649
653
  setUserKeepVisible() {
650
654
  this.userKeepVisible = true;
651
655
  }
@@ -723,7 +727,12 @@ export class MediaControl extends UICorePlugin {
723
727
  default: [],
724
728
  right: [],
725
729
  }, this.core.activeContainer.settings);
730
+ // TODO make order controlled via CSS
726
731
  newSettings.left = orderByOrderPattern([...newSettings.left, 'clipsText', 'volume'], LEFT_ORDER);
732
+ if (this.core.activePlayback.getPlaybackType() === Playback.LIVE &&
733
+ this.core.activePlayback.dvrEnabled) {
734
+ newSettings.left.push('dvr');
735
+ }
727
736
  // actual order of the items appear rendered is controlled by CSS
728
737
  newSettings.right = [
729
738
  'fullscreen',
@@ -745,17 +754,18 @@ export class MediaControl extends UICorePlugin {
745
754
  }
746
755
  removeArrayItem(newSettings.default, 'hd-indicator');
747
756
  removeArrayItem(newSettings.left, 'hd-indicator');
757
+ // TODO get from container's settings
748
758
  if (this.core.activePlayback.name === 'html5_video') {
749
759
  newSettings.seekEnabled = this.isSeekEnabledForHtml5Playback();
750
760
  }
751
- const settingsChanged = JSON.stringify(this.settings) !== JSON.stringify(newSettings);
761
+ const settingsChanged = serializeSettings(this.settings) !== serializeSettings(newSettings);
752
762
  if (settingsChanged) {
753
763
  this.settings = newSettings;
754
764
  this.render();
755
765
  }
756
766
  }
757
- highDefinitionUpdate(isHD) {
758
- this.isHD = isHD;
767
+ onHdUpdate(isHD) {
768
+ // TODO render?
759
769
  }
760
770
  createCachedElements() {
761
771
  const $layer = this.$el.find('.media-control-layer');
@@ -818,7 +828,7 @@ export class MediaControl extends UICorePlugin {
818
828
  trace(`${T} putElement`, { name, panel: !!panel });
819
829
  if (panel) {
820
830
  const current = panel.find(`[data-${name}]`);
821
- element.setAttribute(`data-${name}`, "");
831
+ element.setAttribute(`data-${name}`, '');
822
832
  // TODO test
823
833
  if (current.length) {
824
834
  if (current[0] === element) {
@@ -832,16 +842,16 @@ export class MediaControl extends UICorePlugin {
832
842
  }
833
843
  }
834
844
  /**
835
- * Get the right panel area to append custom elements to
836
- * @returns ZeptoSelector of the right panel element
845
+ * Toggle the visibility of a media control element
846
+ * @param name - The name of the media control element
847
+ * @param show - Whether to show or hide the element
837
848
  */
849
+ toggleElement(name, show) {
850
+ this.$el.find(`[data-${name}]`).toggle(show);
851
+ }
838
852
  getRightPanel() {
839
853
  return this.$el.find('.media-control-right-panel');
840
854
  }
841
- /**
842
- * Get the left panel area to append custom elements to
843
- * @returns ZeptoSelector of the left panel element
844
- */
845
855
  getLeftPanel() {
846
856
  return this.$el.find('.media-control-left-panel');
847
857
  }
@@ -1040,7 +1050,6 @@ export class MediaControl extends UICorePlugin {
1040
1050
  this.hideVolumeBar(0);
1041
1051
  }, 0);
1042
1052
  this.parseColors();
1043
- this.highDefinitionUpdate(this.isHD);
1044
1053
  this.core.$el.append(this.el);
1045
1054
  this.rendered = true;
1046
1055
  this.updateVolumeUI();
@@ -1127,7 +1136,24 @@ export class MediaControl extends UICorePlugin {
1127
1136
  }
1128
1137
  return null;
1129
1138
  }
1139
+ onDvrStateChanged(dvrInUse) {
1140
+ if (dvrInUse) {
1141
+ this.$el.addClass('dvr');
1142
+ }
1143
+ else {
1144
+ this.$el.removeClass('dvr');
1145
+ }
1146
+ }
1130
1147
  }
1131
1148
  MediaControl.extend = function (properties) {
1132
1149
  return extend(MediaControl, properties);
1133
1150
  };
1151
+ function serializeSettings(s) {
1152
+ return s.left
1153
+ .slice()
1154
+ .sort()
1155
+ .concat(s.right.slice().sort())
1156
+ .concat(s.default.slice().sort())
1157
+ .concat([s.seekEnabled])
1158
+ .join(',');
1159
+ }
@@ -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.21.6",
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(() => {
@@ -78,11 +72,13 @@ describe('DvrControls', () => {
78
72
  })
79
73
  describe('VOD stream', () => {
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
83
  it('should not render', () => {
88
84
  expect(dvrControls.el.textContent).toBeFalsy()
@@ -1,43 +1,19 @@
1
1
  // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
2
 
3
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>
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
9
  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>
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
- `;