@gcorevideo/player 2.22.20 → 2.22.21

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.
@@ -1,7 +1,8 @@
1
- import { UICorePlugin, Events, Browser, $, Container } from '@clappr/core';
2
- import { reportError } from '@gcorevideo/utils';
1
+ import { UICorePlugin, Events, Browser, $, Core } from '@clappr/core'
2
+ import { reportError, trace } from '@gcorevideo/utils'
3
3
 
4
- import { TimerId } from '../../utils/types.js';
4
+ import { TimerId } from '../../utils/types.js'
5
+ import { ExtendedEvents } from '../media-control/MediaControl.js'
5
6
 
6
7
  /**
7
8
  * Events emitted by the VolumeFade plugin.
@@ -11,114 +12,130 @@ export enum VolumeFadeEvents {
11
12
  FADE = 'core:volume:fade',
12
13
  }
13
14
 
15
+ const T = 'plugins.volume_fade'
16
+
17
+ const DEFAULT_DURATION = 600
18
+
19
+ /**
20
+ * @beta
21
+ */
22
+ export type VolumeFadeSettings = {
23
+ /**
24
+ * Initial active volume level, effective until volume is changed via media control
25
+ */
26
+ level?: number
27
+ /**
28
+ * Fade duration, ms
29
+ */
30
+ duration?: number
31
+ }
32
+
14
33
  /**
15
34
  * `PLUGIN` that applies fade effect to the player's volume change.
16
35
  * @beta
36
+ *
37
+ * @remarks
38
+ * Depends on {@link MediaControl} plugin.
39
+ * Configuration options - {@link VolumeFadeSettings}
17
40
  */
18
41
  export class VolumeFade extends UICorePlugin {
19
- private _aboveBorderVolume = 0;
42
+ private activeVolume = 0
20
43
 
21
- private container: Container | null = null;
44
+ private duration = 0
22
45
 
23
- private delay = 0;
24
-
25
- private interval: TimerId | null = null;
46
+ private timerId: TimerId | null = null
26
47
 
27
48
  /**
28
49
  * @internal
29
50
  */
30
51
  get name() {
31
- return 'volume_fade';
52
+ return 'volume_fade'
53
+ }
54
+
55
+ constructor(core: Core) {
56
+ super(core)
57
+ if (typeof this.options.volumeFade?.level === 'number') {
58
+ this.activeVolume = this.options.volumeFade.level
59
+ }
32
60
  }
33
61
 
34
62
  /**
35
63
  * @internal
36
64
  */
37
65
  override bindEvents() {
38
- // TODO on container changed
39
- this.listenTo(this.core, Events.CORE_READY, this.onCoreReady);
40
- if (this.core.mediaControl) {
41
- this.listenTo(this.core.mediaControl, 'mediacontrol:volume:user', this._onUserChangeVolume);
42
- }
43
- // this.listenTo(this.core, 'core:volume:config', this._onVolumeConfig);
44
- }
45
-
46
- private unBindEvents() {
47
- this.core.$el.off('mouseleave.volume');
48
- this.core.$el.off('mouseenter.volume');
49
- }
50
-
51
- private _onUserChangeVolume(volume: number) {
52
- this._aboveBorderVolume = volume;
53
- }
54
-
55
- private _onVolumeConfig(value: number) {
56
- this._aboveBorderVolume = value;
57
- this.container?.setVolume(0);
66
+ this.listenTo(this.core, Events.CORE_READY, this.onCoreReady)
58
67
  }
59
68
 
60
69
  private onCoreReady() {
61
- this.unBindEvents();
62
- this.container = this.core.activeContainer;
63
- if (this.core && this.core.$el) {
64
- // TODO find out why options.playerElement instead of this.core.$el or this.container.$el
65
- $(this.options.playerElement).on('mouseenter.volume', () => {
66
- this.onEnter();
67
- });
68
- $(this.options.playerElement).on('mouseleave.volume', () => {
69
- this.onLeave();
70
- });
70
+ const mediaControl = this.core.getPlugin('media_control')
71
+ if (Browser.isMobile) {
72
+ this.destroy()
73
+ return
71
74
  }
72
- if (!this._aboveBorderVolume) {
73
- this._aboveBorderVolume = this.container?.volume && !isNaN(this.container.volume) ? this.container.volume : 80;
75
+ if (mediaControl) {
76
+ this.listenTo(
77
+ mediaControl,
78
+ ExtendedEvents.MEDIACONTROL_VOLUME,
79
+ this.onVolumeChange,
80
+ )
74
81
  }
75
- if (this.options.mute || Browser.isMobile) {
76
- this.destroy();
77
-
78
- return;
82
+ $(this.core.$el).on('mouseenter', () => this.onEnter())
83
+ $(this.core.$el).on('mouseleave', () => this.onLeave())
84
+ if (!this.activeVolume) {
85
+ this.activeVolume =
86
+ this.core.activeContainer?.volume &&
87
+ !isNaN(this.core.activeContainer.volume)
88
+ ? this.core.activeContainer.volume
89
+ : 80
79
90
  }
80
- this.delay = this.options.volumeFade && this.options.volumeFade.delay || 600;
81
- this.container?.setVolume(0);
82
- }
83
91
 
84
- private onEnter() {
85
- this.numberTo(this.delay);
92
+ this.duration = this.options.volumeFade?.duration || DEFAULT_DURATION
93
+ // TODO check if mute must be respected
94
+ this.core.activeContainer?.setVolume(this.activeVolume)
95
+ this.core.activePlayback.volume(0)
86
96
  }
87
97
 
88
- private numberTo(duration: number, contra = 0) {
89
- this.clearCurrentInterval();
90
- const start = new Date().getTime();
98
+ private onVolumeChange(volume: number) {
99
+ trace(`${T} onVolumeChange`, { volume })
100
+ this.activeVolume = volume
101
+ }
91
102
 
92
- this.interval = setInterval(() => {
93
- let now = (new Date().getTime()) - start;
103
+ private onEnter() {
104
+ trace(`${T} onEnter`)
105
+ this.fade(this.duration, 1)
106
+ }
94
107
 
95
- if (now > duration) {
96
- now = duration;
97
- }
98
- const progress = Math.abs(contra - now / duration);
108
+ private onLeave() {
109
+ trace(`${T} onLeave`)
110
+ this.fade(this.duration, 0)
111
+ }
99
112
 
113
+ private fade(duration: number, to: 0 | 1) {
114
+ this.stopFade()
115
+ const start = new Date().getTime()
116
+ const from = 1 - to
117
+ this.timerId = setInterval(() => {
118
+ const delta = new Date().getTime() - start
119
+ const progress = Math.min(1, delta / duration)
120
+ const normVol = progress * to + (1 - progress) * from
121
+ const volume = normVol * this.activeVolume
122
+ this.core.activePlayback.volume(volume)
100
123
  try {
101
- this.container?.setVolume(progress * this._aboveBorderVolume);
102
- this.core.trigger(VolumeFadeEvents.FADE, progress * this._aboveBorderVolume);
124
+ this.core.trigger(VolumeFadeEvents.FADE, volume)
103
125
  } catch (error) {
104
- // LogManager.exception(error);
105
- reportError(error);
106
- this.clearCurrentInterval();
126
+ reportError(error)
107
127
  }
108
- if (progress >= 1 || progress <= 0) {
109
- this.clearCurrentInterval();
128
+ if (progress >= 1) {
129
+ this.stopFade()
110
130
  }
111
- }, 10);
131
+ }, 10)
112
132
  }
113
133
 
114
- private clearCurrentInterval() {
115
- if (this.interval !== null) {
116
- clearInterval(this.interval);
117
- this.interval = null;
134
+ private stopFade() {
135
+ trace(`${T} stopFade`)
136
+ if (this.timerId !== null) {
137
+ clearInterval(this.timerId)
138
+ this.timerId = null
118
139
  }
119
140
  }
120
-
121
- private onLeave() {
122
- this.numberTo(this.delay, 1);
123
- }
124
141
  }
@@ -234,32 +234,6 @@
234
234
  },
235
235
  "implementsTokenRanges": []
236
236
  },
237
- {
238
- "kind": "TypeAlias",
239
- "canonicalReference": "@gcorevideo/player!BitrateTrackRecord:type",
240
- "docComment": "/**\n * @beta\n */\n",
241
- "excerptTokens": [
242
- {
243
- "kind": "Content",
244
- "text": "export type BitrateTrackRecord = "
245
- },
246
- {
247
- "kind": "Content",
248
- "text": "{\n start: number;\n end?: number;\n time?: number;\n bitrate: number;\n}"
249
- },
250
- {
251
- "kind": "Content",
252
- "text": ";"
253
- }
254
- ],
255
- "fileUrlPath": "src/plugins/clappr-stats/types.ts",
256
- "releaseTag": "Beta",
257
- "name": "BitrateTrackRecord",
258
- "typeTokenRange": {
259
- "startIndex": 1,
260
- "endIndex": 2
261
- }
262
- },
263
237
  {
264
238
  "kind": "Class",
265
239
  "canonicalReference": "@gcorevideo/player!BottomGear:class",
@@ -486,6 +460,32 @@
486
460
  },
487
461
  "implementsTokenRanges": []
488
462
  },
463
+ {
464
+ "kind": "TypeAlias",
465
+ "canonicalReference": "@gcorevideo/player!ClapprStatsBitrateTrack:type",
466
+ "docComment": "/**\n * @beta\n */\n",
467
+ "excerptTokens": [
468
+ {
469
+ "kind": "Content",
470
+ "text": "export type ClapprStatsBitrateTrack = "
471
+ },
472
+ {
473
+ "kind": "Content",
474
+ "text": "{\n start: number;\n end?: number;\n time?: number;\n bitrate: number;\n}"
475
+ },
476
+ {
477
+ "kind": "Content",
478
+ "text": ";"
479
+ }
480
+ ],
481
+ "fileUrlPath": "src/plugins/clappr-stats/types.ts",
482
+ "releaseTag": "Beta",
483
+ "name": "ClapprStatsBitrateTrack",
484
+ "typeTokenRange": {
485
+ "startIndex": 1,
486
+ "endIndex": 2
487
+ }
488
+ },
489
489
  {
490
490
  "kind": "Enum",
491
491
  "canonicalReference": "@gcorevideo/player!ClapprStatsChronograph:enum",
@@ -1053,8 +1053,8 @@
1053
1053
  },
1054
1054
  {
1055
1055
  "kind": "Reference",
1056
- "text": "BitrateTrackRecord",
1057
- "canonicalReference": "@gcorevideo/player!BitrateTrackRecord:type"
1056
+ "text": "ClapprStatsBitrateTrack",
1057
+ "canonicalReference": "@gcorevideo/player!ClapprStatsBitrateTrack:type"
1058
1058
  },
1059
1059
  {
1060
1060
  "kind": "Content",
@@ -2019,7 +2019,7 @@
2019
2019
  {
2020
2020
  "kind": "EnumMember",
2021
2021
  "canonicalReference": "@gcorevideo/player!GearEvents.RENDERED:member",
2022
- "docComment": "/**\n * Use this event to accurately attach an item to the gear menu\n */\n",
2022
+ "docComment": "/**\n * Subscribe to this event to accurately attach an item to the gear menu\n */\n",
2023
2023
  "excerptTokens": [
2024
2024
  {
2025
2025
  "kind": "Content",
@@ -3276,7 +3276,7 @@
3276
3276
  {
3277
3277
  "kind": "Method",
3278
3278
  "canonicalReference": "@gcorevideo/player!MediaControl#mount:member(1)",
3279
- "docComment": "/**\n * Get a media control element DOM node\n *\n * @remarks\n *\n * Use this method to render custom media control UI in a plugin\n *\n * @deprecated\n *\n * Use {@link MediaControl.putElement} instead\n *\n * @param name - The name of the media control element\n *\n * @returns The DOM node to render to or extend\n *\n * @example\n * ```ts\n * class MyPlugin extends UICorePlugin {\n * override render() {\n * this.$el.html('<div data-clips>Here we go</div>')\n * this.core.getPlugin('media_control').mount('clips', this.$el)\n * return this\n * }\n * }\n * ```\n *\n */\n",
3279
+ "docComment": "/**\n * Get a media control element DOM node\n *\n * @remarks\n *\n * Use this method to render custom media control UI in a plugin\n *\n * @param name - The name of the media control element\n *\n * @returns The DOM node to render to or extend\n *\n * @example\n * ```ts\n * class MyPlugin extends UICorePlugin {\n * override render() {\n * this.$el.html('<div data-clips>Here we go</div>')\n * this.core.getPlugin('media_control').mount('clips', this.$el)\n * return this\n * }\n * }\n * ```\n *\n */\n",
3280
3280
  "excerptTokens": [
3281
3281
  {
3282
3282
  "kind": "Content",
@@ -3372,7 +3372,7 @@
3372
3372
  {
3373
3373
  "kind": "Method",
3374
3374
  "canonicalReference": "@gcorevideo/player!MediaControl#putElement:member(1)",
3375
- "docComment": "",
3375
+ "docComment": "/**\n * @deprecated\n *\n * Use {@link MediaControl.mount} instead\n *\n * @param name - \n *\n * @param element - \n */\n",
3376
3376
  "excerptTokens": [
3377
3377
  {
3378
3378
  "kind": "Content",
@@ -3533,7 +3533,7 @@
3533
3533
  {
3534
3534
  "kind": "Method",
3535
3535
  "canonicalReference": "@gcorevideo/player!MediaControl#toggleElement:member(1)",
3536
- "docComment": "/**\n * Toggle the visibility of a media control element\n *\n * @param name - The name of the media control element\n *\n * @param show - Whether to show or hide the element\n */\n",
3536
+ "docComment": "/**\n * Toggle the visibility of a media control element\n *\n * @param name - The name of the media control element\n *\n * @param show - Visibility state\n */\n",
3537
3537
  "excerptTokens": [
3538
3538
  {
3539
3539
  "kind": "Content",