@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
@@ -17,6 +17,17 @@ import volumeMaxIcon from '../../../assets/icons/new/volume-max.svg';
17
17
  import volumeOffIcon from '../../../assets/icons/new/volume-off.svg';
18
18
  import fullscreenOffIcon from '../../../assets/icons/new/fullscreen-off.svg';
19
19
  import fullscreenOnIcon from '../../../assets/icons/new/fullscreen-on.svg';
20
+ /**
21
+ * Custom events emitted by the plugins to communicate with one another
22
+ * @beta
23
+ */
24
+ export var MediaControlEvents;
25
+ (function (MediaControlEvents) {
26
+ /**
27
+ * Emitted when the gear menu is rendered
28
+ */
29
+ MediaControlEvents["MEDIACONTROL_GEAR_RENDERED"] = "mediacontrol:gear:rendered";
30
+ })(MediaControlEvents || (MediaControlEvents = {}));
20
31
  const T = 'plugins.media_control';
21
32
  const LEFT_ORDER = [
22
33
  'playpause',
@@ -51,7 +62,7 @@ export class MediaControl extends UICorePlugin {
51
62
  buttonsColor = null;
52
63
  currentDurationValue = 0;
53
64
  currentPositionValue = 0;
54
- currentSeekBarPercentage = null;
65
+ currentSeekBarPercentage = 0;
55
66
  disabledClickableList = [];
56
67
  displayedDuration = null;
57
68
  displayedPosition = null;
@@ -169,6 +180,9 @@ export class MediaControl extends UICorePlugin {
169
180
  'mouseleave .media-control-layer[data-controls]': 'resetUserKeepVisible',
170
181
  };
171
182
  }
183
+ get currentSeekPos() {
184
+ return this.currentSeekBarPercentage;
185
+ }
172
186
  /**
173
187
  * Current volume [0..100]
174
188
  */
@@ -531,8 +545,7 @@ export class MediaControl extends UICorePlugin {
531
545
  this.changeTogglePlay();
532
546
  this.bindContainerEvents();
533
547
  this.settingsUpdate();
534
- this.core.activeContainer &&
535
- this.core.activeContainer.trigger(Events.CONTAINER_PLAYBACKDVRSTATECHANGED, this.core.activeContainer.isDvrInUse());
548
+ this.core.activeContainer.trigger(Events.CONTAINER_PLAYBACKDVRSTATECHANGED, this.core.activeContainer.isDvrInUse());
536
549
  // TODO test
537
550
  if (this.core.activeContainer.mediaControlDisabled) {
538
551
  this.disable();
@@ -1,6 +1,6 @@
1
- import { UICorePlugin } from '@clappr/core';
1
+ import { UICorePlugin, Core } from '@clappr/core';
2
2
  /**
3
- * Allows changing the playback speed of the video.
3
+ * PLUGIN that allows changing the playback speed of the video.
4
4
  * @beta
5
5
  *
6
6
  * @remarks
@@ -10,12 +10,12 @@ import { UICorePlugin } from '@clappr/core';
10
10
  *
11
11
  * - {@link BottomGear | bottom_gear}
12
12
  *
13
- * It renders a button in the gear menu, which opens a dropdown with the available playback rates.
13
+ * It renders a button in the gear menu, which opens a dropdown with the options to change the playback rate.
14
14
  */
15
15
  export declare class PlaybackRate extends UICorePlugin {
16
- private currentPlayback;
17
16
  private playbackRates;
18
17
  private prevSelectedRate;
18
+ private rendered;
19
19
  private selectedRate;
20
20
  /**
21
21
  * @internal
@@ -27,9 +27,9 @@ export declare class PlaybackRate extends UICorePlugin {
27
27
  get supportedVersion(): {
28
28
  min: string;
29
29
  };
30
- private static readonly template;
31
30
  private static readonly buttonTemplate;
32
31
  private static readonly listTemplate;
32
+ constructor(core: Core);
33
33
  /**
34
34
  * @internal
35
35
  */
@@ -49,12 +49,13 @@ export declare class PlaybackRate extends UICorePlugin {
49
49
  * @internal
50
50
  */
51
51
  bindEvents(): void;
52
- private unBindEvents;
52
+ private onCoreReady;
53
+ private onActiveContainerChange;
54
+ private onGearRendered;
55
+ private onDvrStateChanged;
53
56
  private allRateElements;
54
57
  private rateElement;
55
- private onDashRateChange;
56
- private updateLiveStatus;
57
- private reload;
58
+ private onPlaybackRateChange;
58
59
  private shouldRender;
59
60
  /**
60
61
  * @internal
@@ -63,11 +64,11 @@ export declare class PlaybackRate extends UICorePlugin {
63
64
  private onStartAd;
64
65
  private onFinishAd;
65
66
  private onPlay;
67
+ private resetPlaybackRate;
66
68
  private onStop;
67
69
  private onRateSelect;
68
70
  private onShowMenu;
69
71
  private goBack;
70
- private updatePlaybackRate;
71
72
  private setSelectedRate;
72
73
  private getTitle;
73
74
  private highlightCurrentRate;
@@ -1 +1 @@
1
- {"version":3,"file":"PlaybackRate.d.ts","sourceRoot":"","sources":["../../../src/plugins/playback-rate/PlaybackRate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,YAAY,EAAsB,MAAM,cAAc,CAAC;AAiCxE;;;;;;;;;;;;GAYG;AACH,qBAAa,YAAa,SAAQ,YAAY;IAC5C,OAAO,CAAC,eAAe,CAAyB;IAEhD,OAAO,CAAC,aAAa,CAAgD;IAErE,OAAO,CAAC,gBAAgB,CAAqB;IAE7C,OAAO,CAAC,YAAY,CAAiC;IAErD;;OAEG;IACH,IAAI,IAAI,WAEP;IAED;;OAEG;IACH,IAAI,gBAAgB;;MAEnB;IAED,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAwB;IAExD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAwB;IAE9D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAsB;IAE1D;;OAEG;IACH,IAAa,UAAU;;;MAKtB;IAED;;OAEG;IACH,IAAa,MAAM;;;;MAMlB;IAED;;OAEG;IACM,UAAU;IAqBnB,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,MAAM;IAKd,OAAO,CAAC,YAAY;IAUpB;;OAEG;IACM,MAAM;IAuCf,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,MAAM;IAWd,OAAO,CAAC,MAAM;IAGd,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,QAAQ;IAYhB,OAAO,CAAC,oBAAoB;CAS7B"}
1
+ {"version":3,"file":"PlaybackRate.d.ts","sourceRoot":"","sources":["../../../src/plugins/playback-rate/PlaybackRate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,YAAY,EAAsB,IAAI,EAAE,MAAM,cAAc,CAAC;AAoC9E;;;;;;;;;;;;GAYG;AACH,qBAAa,YAAa,SAAQ,YAAY;IAC5C,OAAO,CAAC,aAAa,CAAgD;IAGrE,OAAO,CAAC,gBAAgB,CAAqB;IAE7C,OAAO,CAAC,QAAQ,CAAS;IAEzB,OAAO,CAAC,YAAY,CAAiC;IAErD;;OAEG;IACH,IAAI,IAAI,WAEP;IAED;;OAEG;IACH,IAAI,gBAAgB;;MAEnB;IAED,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAwB;IAE9D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAsB;gBAE9C,IAAI,EAAE,IAAI;IAMtB;;OAEG;IACH,IAAa,UAAU;;;MAKtB;IAED;;OAEG;IACH,IAAa,MAAM;;;;MAMlB;IAED;;OAEG;IACM,UAAU;IAKnB,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,uBAAuB;IAO/B,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,iBAAiB;IASzB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,oBAAoB;IAW5B,OAAO,CAAC,YAAY;IAYpB;;OAEG;IACM,MAAM;IA6Bf,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,MAAM;IAQd,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,MAAM;IAGd,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,UAAU;IAUlB,OAAO,CAAC,MAAM;IAMd,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,oBAAoB;CAS7B"}
@@ -1,12 +1,15 @@
1
1
  import { Events, UICorePlugin, Playback, template } from '@clappr/core';
2
+ import { trace } from '@gcorevideo/utils';
3
+ import assert from 'assert';
2
4
  import { CLAPPR_VERSION } from '../../build.js';
3
- import pluginHtml from '../../../assets/playback-rate/playback-rate-selector.ejs';
4
5
  import buttonHtml from '../../../assets/playback-rate/button.ejs';
5
6
  import listHtml from '../../../assets/playback-rate/list.ejs';
6
7
  import speedIcon from '../../../assets/icons/new/speed.svg';
7
8
  import arrowRightIcon from '../../../assets/icons/new/arrow-right.svg';
8
9
  import arrowLeftIcon from '../../../assets/icons/new/arrow-left.svg';
9
10
  import checkIcon from '../../../assets/icons/new/check.svg';
11
+ import { PlaybackEvents } from '../../playback/types.js';
12
+ import { MediaControlEvents } from '../media-control/MediaControl.js';
10
13
  const DEFAULT_PLAYBACK_RATES = [
11
14
  { value: '0.5', label: '0.5x' },
12
15
  { value: '0.75', label: '0.75x' },
@@ -17,10 +20,9 @@ const DEFAULT_PLAYBACK_RATES = [
17
20
  { value: '2.0', label: '2x' }
18
21
  ];
19
22
  const DEFAULT_PLAYBACK_RATE = '1.0';
20
- // TODO
21
- const MEDIACONTROL_PLAYBACKRATE = 'playbackRate';
23
+ const T = 'plugins.playback_rate';
22
24
  /**
23
- * Allows changing the playback speed of the video.
25
+ * PLUGIN that allows changing the playback speed of the video.
24
26
  * @beta
25
27
  *
26
28
  * @remarks
@@ -30,12 +32,13 @@ const MEDIACONTROL_PLAYBACKRATE = 'playbackRate';
30
32
  *
31
33
  * - {@link BottomGear | bottom_gear}
32
34
  *
33
- * It renders a button in the gear menu, which opens a dropdown with the available playback rates.
35
+ * It renders a button in the gear menu, which opens a dropdown with the options to change the playback rate.
34
36
  */
35
37
  export class PlaybackRate extends UICorePlugin {
36
- currentPlayback = null;
37
38
  playbackRates = DEFAULT_PLAYBACK_RATES;
39
+ // Saved when an ad starts to restore after it finishes
38
40
  prevSelectedRate;
41
+ rendered = false;
39
42
  selectedRate = DEFAULT_PLAYBACK_RATE;
40
43
  /**
41
44
  * @internal
@@ -49,9 +52,13 @@ export class PlaybackRate extends UICorePlugin {
49
52
  get supportedVersion() {
50
53
  return { min: CLAPPR_VERSION };
51
54
  }
52
- static template = template(pluginHtml);
53
55
  static buttonTemplate = template(buttonHtml);
54
56
  static listTemplate = template(listHtml);
57
+ constructor(core) {
58
+ super(core);
59
+ this.playbackRates = core.options.playbackRate?.options || DEFAULT_PLAYBACK_RATES;
60
+ this.selectedRate = core.options.playbackRate?.defaultValue || DEFAULT_PLAYBACK_RATE;
61
+ }
55
62
  /**
56
63
  * @internal
57
64
  */
@@ -75,27 +82,36 @@ export class PlaybackRate extends UICorePlugin {
75
82
  * @internal
76
83
  */
77
84
  bindEvents() {
78
- this.listenTo(this.core, 'gear:rendered', this.render);
79
- // TODO this.core.getPlugin('media_control'), bottom_gear
80
- this.listenTo(this.core.mediaControl, Events.MEDIACONTROL_CONTAINERCHANGED, this.reload);
81
- this.listenTo(this.core.mediaControl, MEDIACONTROL_PLAYBACKRATE, this.updatePlaybackRate);
82
- this.listenTo(this.core, 'core:advertisement:start', this.onStartAd);
83
- this.listenTo(this.core, 'core:advertisement:finish', this.onFinishAd);
84
- if (this.core.activeContainer) {
85
- this.listenTo(this.core.activePlayback, Events.PLAYBACK_BUFFERFULL, this.updateLiveStatus);
86
- }
87
- if (this.currentPlayback) {
88
- this.listenTo(this.currentPlayback, Events.PLAYBACK_STOP, this.onStop);
89
- this.listenTo(this.currentPlayback, Events.PLAYBACK_PLAY, this.onPlay);
90
- // TODO import dash playback events
91
- this.listenTo(this.currentPlayback, 'dash:playback-rate-changed', this.onDashRateChange);
92
- }
85
+ this.listenTo(this.core, Events.CORE_READY, this.onCoreReady);
86
+ this.listenTo(this.core, Events.CORE_ACTIVE_CONTAINER_CHANGED, this.onActiveContainerChange);
87
+ }
88
+ onCoreReady() {
89
+ const mediaControl = this.core.getPlugin('media_control');
90
+ assert(mediaControl, 'media_control plugin is required');
91
+ const gear = this.core.getPlugin('bottom_gear');
92
+ assert(gear, 'bottom_gear plugin is required');
93
+ this.listenTo(mediaControl, MediaControlEvents.MEDIACONTROL_GEAR_RENDERED, this.onGearRendered);
94
+ }
95
+ onActiveContainerChange() {
96
+ this.listenTo(this.core.activePlayback, Events.PLAYBACK_STOP, this.onStop);
97
+ this.listenTo(this.core.activePlayback, Events.PLAYBACK_PLAY, this.onPlay);
98
+ this.listenTo(this.core.activePlayback, PlaybackEvents.PLAYBACK_RATE_CHANGED, this.onPlaybackRateChange);
99
+ this.listenTo(this.core.activeContainer, Events.CONTAINER_PLAYBACKDVRSTATECHANGED, this.onDvrStateChanged);
100
+ }
101
+ onGearRendered() {
102
+ trace(`${T} onGearRendered`, {
103
+ rendered: this.rendered,
104
+ });
105
+ this.rendered = false;
106
+ this.render();
93
107
  }
94
- unBindEvents() {
95
- this.stopListening(this.core, 'gear:rendered', this.render);
96
- this.stopListening(this.core.mediaControl, Events.MEDIACONTROL_CONTAINERCHANGED, this.reload);
97
- this.stopListening(this.core, 'core:advertisement:start', this.onStartAd);
98
- this.stopListening(this.core, 'core:advertisement:finish', this.onFinishAd);
108
+ onDvrStateChanged(dvrEnabled) {
109
+ trace(`${T} onDvrStateChanged`, {
110
+ dvrEnabled,
111
+ });
112
+ if (dvrEnabled) {
113
+ this.render();
114
+ }
99
115
  }
100
116
  allRateElements() {
101
117
  return this.$('ul.gear-sub-menu li');
@@ -103,68 +119,53 @@ export class PlaybackRate extends UICorePlugin {
103
119
  rateElement(rate = "1") {
104
120
  return this.$(`ul.gear-sub-menu a[data-rate="${rate}"]`).parent();
105
121
  }
106
- onDashRateChange() {
107
- // TODO consider removing
108
- this.currentPlayback._dash?.setPlaybackRate(this.selectedRate);
109
- }
110
- updateLiveStatus() {
111
- if (this.core.getPlaybackType() === Playback.LIVE) {
112
- if (this.core.mediaControl.currentSeekBarPercentage <= 98.9) {
113
- this.core.mediaControl.$playbackRate.removeClass('playbackrate-enable');
114
- this.core.mediaControl.$el.addClass('dvr');
115
- return;
116
- }
117
- this.updatePlaybackRate(DEFAULT_PLAYBACK_RATE);
118
- this.core.mediaControl.$playbackRate.addClass('playbackrate-enable');
119
- this.core.mediaControl.$el.removeClass('dvr');
122
+ onPlaybackRateChange(playbackRate) {
123
+ const selectedRate = parseInt(this.selectedRate, 10);
124
+ if (playbackRate !== selectedRate) {
125
+ trace(`${T} onPlaybackRateChange setting target rate`, {
126
+ playbackRate,
127
+ selectedRate,
128
+ });
129
+ this.core.activePlayback?.setPlaybackRate(selectedRate);
120
130
  }
121
131
  }
122
- reload() {
123
- this.unBindEvents();
124
- this.bindEvents();
125
- }
126
132
  shouldRender() {
127
133
  if (!this.core.activeContainer) {
128
134
  return false;
129
135
  }
130
- this.currentPlayback = this.core.activePlayback;
131
- return !(this.currentPlayback?.tagName !== 'video' && this.currentPlayback?.tagName !== 'audio');
136
+ if (this.core.getPlaybackType() === Playback.LIVE && !this.core.activePlayback.dvrEnabled) {
137
+ return false;
138
+ }
139
+ return 'setPlaybackRate' in this.core.activePlayback;
132
140
  }
133
141
  /**
134
142
  * @internal
135
143
  */
136
144
  render() {
137
- const container = this.core.activeContainer;
138
- if (this.core.getPlaybackType() === Playback.LIVE && !container.isDvrEnabled()) {
145
+ trace(`${T} render`, {
146
+ rendered: this.rendered,
147
+ shouldRender: this.shouldRender(),
148
+ });
149
+ if (!this.shouldRender()) {
139
150
  return this;
140
151
  }
141
- const cfg = this.core.options.playbackRateConfig || {};
142
- if (!this.playbackRates) {
143
- this.playbackRates = cfg.options || DEFAULT_PLAYBACK_RATES;
144
- }
145
- if (!this.selectedRate) {
146
- this.selectedRate = cfg.defaultValue || DEFAULT_PLAYBACK_RATE;
147
- }
148
- if (this.shouldRender()) {
149
- const button = PlaybackRate.buttonTemplate({
150
- title: this.getTitle(),
151
- speedIcon,
152
- arrowRightIcon,
153
- });
154
- this.$el.html(button);
155
- // if (this.core.getPlaybackType() === Playback.LIVE) {
156
- // this.core.mediaControl.$playbackRate.addClass('playbackrate-enable');
157
- // }
158
- // this.core.mediaControl.$playbackRate.append(this.el);
159
- this.core.mediaControl.$el?.find('.gear-options-list [data-rate]').html(this.el);
160
- // this.updateText();
152
+ if (this.rendered) {
153
+ return this;
161
154
  }
155
+ const button = PlaybackRate.buttonTemplate({
156
+ title: this.getTitle(),
157
+ speedIcon,
158
+ arrowRightIcon,
159
+ });
160
+ this.$el.html(button);
161
+ this.core.getPlugin('bottom_gear')?.getElement('rate')?.html(this.el);
162
+ this.rendered = true;
162
163
  return this;
163
164
  }
164
165
  onStartAd() {
165
166
  this.prevSelectedRate = this.selectedRate;
166
- this.setSelectedRate('1.0');
167
- this.listenToOnce(this.currentPlayback, Events.PLAYBACK_PLAY, this.onFinishAd);
167
+ this.resetPlaybackRate();
168
+ this.listenToOnce(this.core.activePlayback, Events.PLAYBACK_PLAY, this.onFinishAd);
168
169
  }
169
170
  onFinishAd() {
170
171
  if (this.prevSelectedRate) {
@@ -172,16 +173,16 @@ export class PlaybackRate extends UICorePlugin {
172
173
  }
173
174
  }
174
175
  onPlay() {
175
- if (!this.core.mediaControl.$el.hasClass('dvr')) {
176
- if (this.core.getPlaybackType() === Playback.LIVE) {
177
- this.updatePlaybackRate(DEFAULT_PLAYBACK_RATE);
178
- this.core.mediaControl.$playbackRate.addClass('playbackrate-enable');
179
- }
176
+ if (this.core.getPlaybackType() === Playback.LIVE && !this.core.activePlayback.dvrEnabled) {
177
+ this.resetPlaybackRate();
180
178
  }
181
179
  else {
182
180
  this.setSelectedRate(this.selectedRate);
183
181
  }
184
182
  }
183
+ resetPlaybackRate() {
184
+ this.setSelectedRate(DEFAULT_PLAYBACK_RATE);
185
+ }
185
186
  onStop() {
186
187
  }
187
188
  onRateSelect(event) {
@@ -199,30 +200,21 @@ export class PlaybackRate extends UICorePlugin {
199
200
  arrowLeftIcon,
200
201
  checkIcon,
201
202
  }));
202
- this.core.mediaControl.$el?.find('.gear-wrapper').html(this.el);
203
+ this.core.getPlugin('bottom_gear')?.setContent(this.el);
203
204
  this.highlightCurrentRate();
204
205
  }
205
206
  goBack() {
206
- this.core.trigger('gear:refresh');
207
- }
208
- updatePlaybackRate(rate) {
209
- this.setSelectedRate(rate);
207
+ setTimeout(() => {
208
+ this.core.getPlugin('bottom_gear').refresh();
209
+ }, 0);
210
210
  }
211
211
  setSelectedRate(rate) {
212
212
  // Set <video playbackRate="..."
213
- this.core.$el.find('video,audio').get(0).playbackRate = rate;
213
+ this.core.activePlayback?.setPlaybackRate(rate);
214
214
  this.selectedRate = rate;
215
- // TODO
216
- // Player.player.trigger('playbackRateChanged', rate);
217
215
  }
218
216
  getTitle() {
219
- let title = this.selectedRate;
220
- this.playbackRates.forEach((r) => {
221
- if (r.value === this.selectedRate) {
222
- title = r.label;
223
- }
224
- });
225
- return title;
217
+ return this.playbackRates.find((r) => r.value === this.selectedRate)?.label || this.selectedRate;
226
218
  }
227
219
  highlightCurrentRate() {
228
220
  this.allRateElements().removeClass('current');
@@ -21,6 +21,7 @@ export declare class SourceController extends CorePlugin {
21
21
  private currentSourceIndex;
22
22
  private sourcesDelay;
23
23
  private active;
24
+ private switching;
24
25
  private sync;
25
26
  /**
26
27
  * @internal
@@ -1 +1 @@
1
- {"version":3,"file":"SourceController.d.ts","sourceRoot":"","sources":["../../../src/plugins/source-controller/SourceController.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,UAAU,EACV,KAAK,IAAI,IAAI,UAAU,EACxB,MAAM,cAAc,CAAA;AAwBrB;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,gBAAiB,SAAQ,UAAU;IAuC9C,OAAO,CAAC,WAAW,CAA8B;IAEjD,OAAO,CAAC,kBAAkB,CAAI;IAE9B,OAAO,CAAC,YAAY,CAA6B;IAEjD,OAAO,CAAC,MAAM,CAAQ;IAEtB,OAAO,CAAC,IAAI,CAAiB;IAE7B;;OAEG;IACH,IAAI,IAAI,WAEP;IAED;;OAEG;IACH,IAAI,gBAAgB;;MAEnB;gBAEW,IAAI,EAAE,UAAU;IAW5B;;OAEG;IACM,UAAU;IAWnB,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,wBAAwB;IAoBhC,OAAO,CAAC,2BAA2B;IAsCnC,OAAO,CAAC,KAAK;IAKb,OAAO,CAAC,aAAa;IA2BrB,OAAO,CAAC,kBAAkB;IAe1B;;OAEG;IACH,MAAM,KAAK,OAAO,WAEjB;CACF"}
1
+ {"version":3,"file":"SourceController.d.ts","sourceRoot":"","sources":["../../../src/plugins/source-controller/SourceController.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,UAAU,EACV,KAAK,IAAI,IAAI,UAAU,EACxB,MAAM,cAAc,CAAA;AAwBrB;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,gBAAiB,SAAQ,UAAU;IAuC9C,OAAO,CAAC,WAAW,CAA8B;IAEjD,OAAO,CAAC,kBAAkB,CAAI;IAE9B,OAAO,CAAC,YAAY,CAA6B;IAEjD,OAAO,CAAC,MAAM,CAAQ;IAEtB,OAAO,CAAC,SAAS,CAAQ;IAEzB,OAAO,CAAC,IAAI,CAAiB;IAE7B;;OAEG;IACH,IAAI,IAAI,WAEP;IAED;;OAEG;IACH,IAAI,gBAAgB;;MAEnB;gBAEW,IAAI,EAAE,UAAU;IAW5B;;OAEG;IACM,UAAU;IAWnB,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,wBAAwB;IAoBhC,OAAO,CAAC,2BAA2B;IAwCnC,OAAO,CAAC,KAAK;IAKb,OAAO,CAAC,aAAa;IA4BrB,OAAO,CAAC,kBAAkB;IAe1B;;OAEG;IACH,MAAM,KAAK,OAAO,WAEjB;CACF"}
@@ -71,6 +71,7 @@ export class SourceController extends CorePlugin {
71
71
  currentSourceIndex = 0;
72
72
  sourcesDelay = {};
73
73
  active = false;
74
+ switching = false;
74
75
  sync = noSync;
75
76
  /**
76
77
  * @internal
@@ -135,15 +136,18 @@ export class SourceController extends CorePlugin {
135
136
  description: error?.description,
136
137
  level: error?.level,
137
138
  },
139
+ switching: this.switching,
138
140
  retrying: this.active,
139
141
  currentSource: this.sourcesList[this.currentSourceIndex],
140
142
  });
143
+ if (this.switching) {
144
+ return;
145
+ }
141
146
  switch (error.code) {
142
147
  case PlaybackErrorCode.MediaSourceUnavailable:
143
148
  this.core.activeContainer?.getPlugin('poster_custom')?.disable();
144
- setTimeout(() => this.retryPlayback(), 0);
149
+ this.retryPlayback();
145
150
  break;
146
- // TODO handle other errors
147
151
  default:
148
152
  break;
149
153
  }
@@ -155,7 +159,6 @@ export class SourceController extends CorePlugin {
155
159
  });
156
160
  if (this.active) {
157
161
  this.reset();
158
- // TODO make poster reset its state on enable
159
162
  this.core.activeContainer?.getPlugin('poster_custom')?.enable();
160
163
  this.core.activeContainer?.getPlugin('spinner')?.hide();
161
164
  }
@@ -171,6 +174,7 @@ export class SourceController extends CorePlugin {
171
174
  currentSource: this.sourcesList[this.currentSourceIndex],
172
175
  });
173
176
  this.active = true;
177
+ this.switching = true;
174
178
  this.core.activeContainer?.getPlugin('spinner')?.show(0);
175
179
  this.getNextMediaSource().then((nextSource) => {
176
180
  trace(`${T} retryPlayback syncing...`, {
@@ -179,12 +183,12 @@ export class SourceController extends CorePlugin {
179
183
  const rnd = RETRY_DELAY_BLUR * Math.random();
180
184
  this.sync(() => {
181
185
  trace(`${T} retryPlayback loading...`);
186
+ this.switching = false;
182
187
  this.core.load(nextSource.source, nextSource.mimeType);
183
188
  trace(`${T} retryPlayback loaded`, {
184
189
  nextSource,
185
190
  });
186
191
  setTimeout(() => {
187
- // this.core.activePlayback.consent()
188
192
  this.core.activePlayback.play();
189
193
  trace(`${T} retryPlayback playing`);
190
194
  }, rnd);
@@ -17,6 +17,7 @@ export declare enum SpinnerEvents {
17
17
  * The plugin emits
18
18
  */
19
19
  export declare class SpinnerThreeBounce extends UIContainerPlugin {
20
+ private userShown;
20
21
  /**
21
22
  * @internal
22
23
  */
@@ -34,7 +35,6 @@ export declare class SpinnerThreeBounce extends UIContainerPlugin {
34
35
  'data-spinner': string;
35
36
  class: string;
36
37
  };
37
- private hideTimeout;
38
38
  private showTimeout;
39
39
  private template;
40
40
  private hasFatalError;
@@ -46,13 +46,17 @@ export declare class SpinnerThreeBounce extends UIContainerPlugin {
46
46
  private onStop;
47
47
  private onError;
48
48
  /**
49
- * Shows the spinner
49
+ * Shows the spinner.
50
+ *
51
+ * When called, the spinner will not hide (due to its built-in logic) until {@link SpinnerThreeBounce#hide} is called
50
52
  */
51
53
  show(delay?: number): void;
52
54
  /**
53
- * Hides the spinner
55
+ * Hides the spinner.
54
56
  */
55
57
  hide(): void;
58
+ private _show;
59
+ private _hide;
56
60
  /**
57
61
  * @internal
58
62
  */
@@ -1 +1 @@
1
- {"version":3,"file":"SpinnerThreeBounce.d.ts","sourceRoot":"","sources":["../../../src/plugins/spinner-three-bounce/SpinnerThreeBounce.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAA0B,iBAAiB,EAAY,MAAM,cAAc,CAAC;AAK9F,OAAO,mDAAmD,CAAC;AAM3D;;GAEG;AACH,oBAAY,aAAa;IACvB;;;OAGG;IACH,IAAI,yBAAyB;CAC9B;AAED;;;;;GAKG;AACH,qBAAa,kBAAmB,SAAQ,iBAAiB;IACvD;;OAEG;IACH,IAAI,IAAI,WAEP;IAED;;OAEG;IACH,IAAI,gBAAgB;;MAEnB;IAED;;OAEG;IACH,IAAa,UAAU;;;MAKtB;IAED,OAAO,CAAC,WAAW,CAAwB;IAE3C,OAAO,CAAC,WAAW,CAAwB;IAE3C,OAAO,CAAC,QAAQ,CAAyB;IAEzC,OAAO,CAAC,aAAa,CAAQ;IAE7B,OAAO,CAAC,YAAY,CAAQ;gBAEhB,SAAS,EAAE,SAAS;IAWhC,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,MAAM;IAKd,OAAO,CAAC,MAAM;IAUd,OAAO,CAAC,OAAO;IAef;;OAEG;IACH,IAAI,CAAC,KAAK,SAAM;IAchB;;OAEG;IACH,IAAI;IAaJ;;OAEG;IACM,MAAM;CAmBhB"}
1
+ {"version":3,"file":"SpinnerThreeBounce.d.ts","sourceRoot":"","sources":["../../../src/plugins/spinner-three-bounce/SpinnerThreeBounce.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,SAAS,EAET,iBAAiB,EAElB,MAAM,cAAc,CAAA;AAKrB,OAAO,mDAAmD,CAAA;AAM1D;;GAEG;AACH,oBAAY,aAAa;IACvB;;;OAGG;IACH,IAAI,yBAAyB;CAC9B;AAED;;;;;GAKG;AACH,qBAAa,kBAAmB,SAAQ,iBAAiB;IACvD,OAAO,CAAC,SAAS,CAAQ;IAEzB;;OAEG;IACH,IAAI,IAAI,WAEP;IAED;;OAEG;IACH,IAAI,gBAAgB;;MAEnB;IAED;;OAEG;IACH,IAAa,UAAU;;;MAKtB;IAED,OAAO,CAAC,WAAW,CAAuB;IAE1C,OAAO,CAAC,QAAQ,CAAwB;IAExC,OAAO,CAAC,aAAa,CAAQ;IAE7B,OAAO,CAAC,YAAY,CAAQ;gBAEhB,SAAS,EAAE,SAAS;IAmBhC,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,MAAM;IAKd,OAAO,CAAC,MAAM;IAUd,OAAO,CAAC,OAAO;IAef;;;;OAIG;IACH,IAAI,CAAC,KAAK,SAAM;IAMhB;;OAEG;IACH,IAAI;IAKJ,OAAO,CAAC,KAAK;IASb,OAAO,CAAC,KAAK;IAeb;;OAEG;IACM,MAAM;CAmBhB"}
@@ -1,9 +1,9 @@
1
1
  // Copyright 2014 Globo.com Player authors. All rights reserved.
2
2
  // Use of this source code is governed by a BSD-style
3
3
  // license that can be found in the LICENSE file.
4
- import { Events as ClapprEvents, UIContainerPlugin, template } from '@clappr/core';
5
- import { PlaybackErrorCode } from '../../playback.types.js';
4
+ import { Events as ClapprEvents, UIContainerPlugin, template, } from '@clappr/core';
6
5
  import { trace } from '@gcorevideo/utils';
6
+ import { PlaybackErrorCode } from '../../playback.types.js';
7
7
  import spinnerHTML from '../../../assets/spinner-three-bounce/spinner.ejs';
8
8
  import '../../../assets/spinner-three-bounce/spinner.scss';
9
9
  import { CLAPPR_VERSION } from '../../build.js';
@@ -26,6 +26,7 @@ export var SpinnerEvents;
26
26
  * The plugin emits
27
27
  */
28
28
  export class SpinnerThreeBounce extends UIContainerPlugin {
29
+ userShown = false;
29
30
  /**
30
31
  * @internal
31
32
  */
@@ -44,10 +45,9 @@ export class SpinnerThreeBounce extends UIContainerPlugin {
44
45
  get attributes() {
45
46
  return {
46
47
  'data-spinner': '',
47
- 'class': 'spinner-three-bounce'
48
+ class: 'spinner-three-bounce',
48
49
  };
49
50
  }
50
- hideTimeout = null;
51
51
  showTimeout = null;
52
52
  template = template(spinnerHTML);
53
53
  hasFatalError = false;
@@ -64,17 +64,17 @@ export class SpinnerThreeBounce extends UIContainerPlugin {
64
64
  }
65
65
  onBuffering() {
66
66
  this.hasBuffering = true;
67
- this.show();
67
+ this._show();
68
68
  }
69
69
  onBufferFull() {
70
70
  if (!this.hasFatalError && this.hasBuffering) {
71
- this.hide();
71
+ this._hide();
72
72
  }
73
73
  this.hasBuffering = false;
74
74
  }
75
75
  onPlay() {
76
76
  trace(`${T} onPlay`);
77
- this.hide();
77
+ this._hide();
78
78
  }
79
79
  onStop() {
80
80
  trace(`${T} onStop`, {
@@ -82,7 +82,7 @@ export class SpinnerThreeBounce extends UIContainerPlugin {
82
82
  hasFatalError: this.hasFatalError,
83
83
  });
84
84
  if (!(this.hasFatalError && this.options.spinner?.showOnError)) {
85
- this.hide();
85
+ this._hide();
86
86
  }
87
87
  }
88
88
  onError(e) {
@@ -94,42 +94,50 @@ export class SpinnerThreeBounce extends UIContainerPlugin {
94
94
  error: e.code,
95
95
  });
96
96
  if (this.options.spinner?.showOnError) {
97
- this.show();
97
+ this._show();
98
98
  }
99
99
  else {
100
- this.hide();
100
+ this._hide();
101
101
  }
102
102
  }
103
103
  /**
104
- * Shows the spinner
104
+ * Shows the spinner.
105
+ *
106
+ * When called, the spinner will not hide (due to its built-in logic) until {@link SpinnerThreeBounce#hide} is called
105
107
  */
106
108
  show(delay = 300) {
107
109
  trace(`${T} show`);
110
+ this.userShown = true;
111
+ this._show(delay);
112
+ }
113
+ /**
114
+ * Hides the spinner.
115
+ */
116
+ hide() {
117
+ this.userShown = false;
118
+ this._hide();
119
+ }
120
+ _show(delay = 300) {
108
121
  if (this.showTimeout === null) {
109
- if (this.hideTimeout !== null) {
110
- clearTimeout(this.hideTimeout);
111
- this.hideTimeout = null;
112
- }
113
122
  this.showTimeout = setTimeout(() => {
114
123
  this.showTimeout = null;
115
124
  this.$el.show();
116
125
  }, delay);
117
126
  }
118
127
  }
119
- /**
120
- * Hides the spinner
121
- */
122
- hide() {
128
+ _hide() {
129
+ trace(`${T} _hide`, {
130
+ userShown: this.userShown,
131
+ });
132
+ if (this.userShown) {
133
+ return;
134
+ }
123
135
  if (this.showTimeout !== null) {
124
136
  clearTimeout(this.showTimeout);
125
137
  this.showTimeout = null;
126
138
  }
127
- this.hideTimeout = setTimeout(() => {
128
- this.hideTimeout = null;
129
- if (this.showTimeout === null) {
130
- this.$el.hide();
131
- }
132
- }, 0);
139
+ this.$el.hide();
140
+ this.trigger(SpinnerEvents.SYNC); // TODO test
133
141
  }
134
142
  /**
135
143
  * @internal
@@ -146,10 +154,10 @@ export class SpinnerThreeBounce extends UIContainerPlugin {
146
154
  });
147
155
  this.container.$el.append(this.$el[0]);
148
156
  if (showOnStart || this.container.buffering) {
149
- this.show();
157
+ this._show();
150
158
  }
151
159
  else {
152
- this.hide();
160
+ this._hide();
153
161
  }
154
162
  return this;
155
163
  }