@gcorevideo/player 2.28.3 → 2.28.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.
- package/dist/core.js +1 -1
- package/dist/index.css +507 -507
- package/dist/index.js +1 -1
- package/package.json +2 -2
- package/tsconfig.tsbuildinfo +1 -1
- package/coverage/clover.xml +0 -6
- package/coverage/coverage-final.json +0 -1
- package/coverage/lcov-report/base.css +0 -224
- package/coverage/lcov-report/block-navigation.js +0 -87
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +0 -101
- package/coverage/lcov-report/prettify.css +0 -1
- package/coverage/lcov-report/prettify.js +0 -2
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +0 -196
- package/coverage/lcov.info +0 -0
- package/dist/player.d.ts +0 -3369
- package/lib/playback/utils.d.ts +0 -2
- package/lib/playback/utils.d.ts.map +0 -1
- package/lib/playback/utils.js +0 -1
- package/lib/plugins/audio-selector/AudioSelector.d.ts +0 -67
- package/lib/plugins/audio-selector/AudioSelector.d.ts.map +0 -1
- package/lib/plugins/audio-selector/AudioSelector.js +0 -172
- package/lib/plugins/build.d.ts +0 -2
- package/lib/plugins/build.d.ts.map +0 -1
- package/lib/plugins/build.js +0 -1
- package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.d.ts +0 -83
- package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.d.ts.map +0 -1
- package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.js +0 -339
- package/lib/plugins/disable-controls/DisableControls.d.ts +0 -15
- package/lib/plugins/disable-controls/DisableControls.d.ts.map +0 -1
- package/lib/plugins/disable-controls/DisableControls.js +0 -67
- package/lib/plugins/index.d.ts +0 -35
- package/lib/plugins/index.d.ts.map +0 -1
- package/lib/plugins/index.js +0 -37
- package/lib/plugins/level-selector/LevelSelector.d.ts +0 -112
- package/lib/plugins/level-selector/LevelSelector.d.ts.map +0 -1
- package/lib/plugins/level-selector/LevelSelector.js +0 -280
- package/lib/plugins/statistics/Statistics.d.ts +0 -87
- package/lib/plugins/statistics/Statistics.d.ts.map +0 -1
- package/lib/plugins/statistics/Statistics.js +0 -172
- package/lib/plugins/subtitles/Subtitles.d.ts +0 -115
- package/lib/plugins/subtitles/Subtitles.d.ts.map +0 -1
- package/lib/plugins/subtitles/Subtitles.js +0 -345
- package/lib/tsdoc-metadata.json +0 -11
- package/lib/utils/fullscreen.d.ts +0 -3
- package/lib/utils/fullscreen.d.ts.map +0 -1
- package/lib/utils/fullscreen.js +0 -2
- package/release.txt +0 -395
- package/release_notes +0 -297
- package/src/plugins/telemetry/Statistics copy.js +0 -296
- package/temp/player.api.json +0 -10275
package/lib/playback/utils.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/playback/utils.ts"],"names":[],"mappings":""}
|
package/lib/playback/utils.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { UICorePlugin } from '@clappr/core';
|
|
2
|
-
import '../../../assets/audio-selector/style.scss';
|
|
3
|
-
/**
|
|
4
|
-
* `PLUGIN` that makes possible to switch audio tracks via the media control UI.
|
|
5
|
-
* @beta
|
|
6
|
-
* @remarks
|
|
7
|
-
* The plugin is activated when there are multiple audio tracks available.
|
|
8
|
-
* The plugin adds a button showing the current audio track and a dropdown to switch to another audio track.
|
|
9
|
-
* Depends on:
|
|
10
|
-
*
|
|
11
|
-
* - {@link MediaControl}
|
|
12
|
-
*/
|
|
13
|
-
export declare class AudioTracks extends UICorePlugin {
|
|
14
|
-
private currentTrack;
|
|
15
|
-
private tracks;
|
|
16
|
-
/**
|
|
17
|
-
* @internal
|
|
18
|
-
*/
|
|
19
|
-
get name(): string;
|
|
20
|
-
/**
|
|
21
|
-
* @internal
|
|
22
|
-
*/
|
|
23
|
-
get supportedVersion(): {
|
|
24
|
-
min: string;
|
|
25
|
-
};
|
|
26
|
-
/**
|
|
27
|
-
* @internal
|
|
28
|
-
*/
|
|
29
|
-
static get version(): string;
|
|
30
|
-
private static readonly template;
|
|
31
|
-
/**
|
|
32
|
-
* @internal
|
|
33
|
-
*/
|
|
34
|
-
get attributes(): {
|
|
35
|
-
class: string;
|
|
36
|
-
};
|
|
37
|
-
/**
|
|
38
|
-
* @internal
|
|
39
|
-
*/
|
|
40
|
-
get events(): {
|
|
41
|
-
'click [data-audiotracks-select]': string;
|
|
42
|
-
'click #audiotracks-button': string;
|
|
43
|
-
};
|
|
44
|
-
/**
|
|
45
|
-
* @internal
|
|
46
|
-
*/
|
|
47
|
-
bindEvents(): void;
|
|
48
|
-
private onCoreReady;
|
|
49
|
-
private onActiveContainerChanged;
|
|
50
|
-
private shouldRender;
|
|
51
|
-
/**
|
|
52
|
-
* @internal
|
|
53
|
-
*/
|
|
54
|
-
render(): this;
|
|
55
|
-
private onTrackSelect;
|
|
56
|
-
private selectAudioTrack;
|
|
57
|
-
private hideMenu;
|
|
58
|
-
private toggleContextMenu;
|
|
59
|
-
private buttonElement;
|
|
60
|
-
private buttonElementText;
|
|
61
|
-
private trackElement;
|
|
62
|
-
private getTitle;
|
|
63
|
-
private startTrackSwitching;
|
|
64
|
-
private updateText;
|
|
65
|
-
private highlightCurrentTrack;
|
|
66
|
-
}
|
|
67
|
-
//# sourceMappingURL=AudioSelector.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AudioSelector.d.ts","sourceRoot":"","sources":["../../../src/plugins/audio-selector/AudioSelector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,YAAY,EAAY,MAAM,cAAc,CAAA;AAO7D,OAAO,2CAA2C,CAAA;AAUlD;;;;;;;;;GASG;AACH,qBAAa,WAAY,SAAQ,YAAY;IAC3C,OAAO,CAAC,YAAY,CAA0B;IAE9C,OAAO,CAAC,MAAM,CAAmB;IAEjC;;OAEG;IACH,IAAI,IAAI,WAEP;IAED;;OAEG;IACH,IAAI,gBAAgB;;MAEnB;IAED;;OAEG;IACH,MAAM,KAAK,OAAO,WAEjB;IAED,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAuB;IAEvD;;OAEG;IACH,IAAa,UAAU;;MAItB;IAED;;OAEG;IACH,IAAa,MAAM;;;MAKlB;IAED;;OAEG;IACM,UAAU;IASnB,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,wBAAwB;IAwBhC,OAAO,CAAC,YAAY;IAMpB;;OAEG;IACM,MAAM;IAmBf,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,QAAQ;IAOhB,OAAO,CAAC,mBAAmB;IAI3B,OAAO,CAAC,UAAU;IAOlB,OAAO,CAAC,qBAAqB;CAe9B"}
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
import { Events, UICorePlugin, template } from '@clappr/core';
|
|
2
|
-
import assert from 'assert';
|
|
3
|
-
import { CLAPPR_VERSION } from '../../build.js';
|
|
4
|
-
import pluginHtml from '../../../assets/audio-selector/track-selector.ejs';
|
|
5
|
-
import '../../../assets/audio-selector/style.scss';
|
|
6
|
-
import audioArrow from '../../../assets/icons/old/quality-arrow.svg';
|
|
7
|
-
// import { trace } from '@gcorevideo/utils'
|
|
8
|
-
const VERSION = '2.22.4';
|
|
9
|
-
// const T = 'plugins.audiotracks'
|
|
10
|
-
/**
|
|
11
|
-
* `PLUGIN` that makes possible to switch audio tracks via the media control UI.
|
|
12
|
-
* @beta
|
|
13
|
-
* @remarks
|
|
14
|
-
* The plugin is activated when there are multiple audio tracks available.
|
|
15
|
-
* The plugin adds a button showing the current audio track and a dropdown to switch to another audio track.
|
|
16
|
-
* Depends on:
|
|
17
|
-
*
|
|
18
|
-
* - {@link MediaControl}
|
|
19
|
-
*/
|
|
20
|
-
export class AudioTracks extends UICorePlugin {
|
|
21
|
-
currentTrack = null;
|
|
22
|
-
tracks = [];
|
|
23
|
-
/**
|
|
24
|
-
* @internal
|
|
25
|
-
*/
|
|
26
|
-
get name() {
|
|
27
|
-
return 'audio_selector'; // TODO rename to audiotracks
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* @internal
|
|
31
|
-
*/
|
|
32
|
-
get supportedVersion() {
|
|
33
|
-
return { min: CLAPPR_VERSION };
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* @internal
|
|
37
|
-
*/
|
|
38
|
-
static get version() {
|
|
39
|
-
return VERSION;
|
|
40
|
-
}
|
|
41
|
-
static template = template(pluginHtml);
|
|
42
|
-
/**
|
|
43
|
-
* @internal
|
|
44
|
-
*/
|
|
45
|
-
get attributes() {
|
|
46
|
-
return {
|
|
47
|
-
class: 'media-control-audiotracks',
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* @internal
|
|
52
|
-
*/
|
|
53
|
-
get events() {
|
|
54
|
-
return {
|
|
55
|
-
'click [data-audiotracks-select]': 'onTrackSelect',
|
|
56
|
-
'click #audiotracks-button': 'toggleContextMenu',
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* @internal
|
|
61
|
-
*/
|
|
62
|
-
bindEvents() {
|
|
63
|
-
this.listenToOnce(this.core, Events.CORE_READY, this.onCoreReady);
|
|
64
|
-
this.listenTo(this.core, Events.CORE_ACTIVE_CONTAINER_CHANGED, this.onActiveContainerChanged);
|
|
65
|
-
}
|
|
66
|
-
onCoreReady() {
|
|
67
|
-
const mediaControl = this.core.getPlugin('media_control');
|
|
68
|
-
assert(mediaControl, 'media_control plugin is required');
|
|
69
|
-
this.listenTo(mediaControl, Events.MEDIACONTROL_RENDERED, () => {
|
|
70
|
-
mediaControl.mount('audiotracks', this.$el);
|
|
71
|
-
});
|
|
72
|
-
this.listenTo(mediaControl, Events.MEDIACONTROL_HIDE, this.hideMenu);
|
|
73
|
-
}
|
|
74
|
-
onActiveContainerChanged() {
|
|
75
|
-
this.currentTrack = null;
|
|
76
|
-
this.listenTo(this.core.activeContainer, Events.CONTAINER_AUDIO_AVAILABLE, (tracks) => {
|
|
77
|
-
this.currentTrack =
|
|
78
|
-
tracks.find((track) => track.kind === 'main') ?? null; // TODO test
|
|
79
|
-
this.tracks = tracks;
|
|
80
|
-
this.render();
|
|
81
|
-
});
|
|
82
|
-
this.listenTo(this.core.activeContainer, Events.CONTAINER_AUDIO_CHANGED, (track) => {
|
|
83
|
-
this.currentTrack = track;
|
|
84
|
-
this.highlightCurrentTrack();
|
|
85
|
-
this.buttonElement().removeClass('changing');
|
|
86
|
-
this.updateText();
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
shouldRender() {
|
|
90
|
-
// Render is called from the parent class constructor so tracks aren't available
|
|
91
|
-
// Only care if we have at least 2 to choose from
|
|
92
|
-
return this.tracks?.length > 1;
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* @internal
|
|
96
|
-
*/
|
|
97
|
-
render() {
|
|
98
|
-
if (!this.shouldRender()) {
|
|
99
|
-
return this;
|
|
100
|
-
}
|
|
101
|
-
this.$el.html(AudioTracks.template({
|
|
102
|
-
tracks: this.tracks,
|
|
103
|
-
title: this.getTitle(),
|
|
104
|
-
icon: audioArrow,
|
|
105
|
-
current: this.currentTrack?.id,
|
|
106
|
-
}));
|
|
107
|
-
this.updateText();
|
|
108
|
-
this.highlightCurrentTrack();
|
|
109
|
-
return this;
|
|
110
|
-
}
|
|
111
|
-
onTrackSelect(event) {
|
|
112
|
-
const id = event.currentTarget?.dataset?.audiotracksSelect;
|
|
113
|
-
if (id) {
|
|
114
|
-
this.selectAudioTrack(id);
|
|
115
|
-
}
|
|
116
|
-
this.hideMenu();
|
|
117
|
-
event.stopPropagation();
|
|
118
|
-
return false;
|
|
119
|
-
}
|
|
120
|
-
selectAudioTrack(id) {
|
|
121
|
-
this.startTrackSwitching();
|
|
122
|
-
this.core.activeContainer.switchAudioTrack(id);
|
|
123
|
-
this.updateText();
|
|
124
|
-
}
|
|
125
|
-
hideMenu() {
|
|
126
|
-
this.$el.find('#audiotracks-select').addClass('hidden');
|
|
127
|
-
}
|
|
128
|
-
toggleContextMenu() {
|
|
129
|
-
this.$el.find('#audiotracks-select').toggleClass('hidden'); // TODO use plain CSS display: none
|
|
130
|
-
const open = !this.$el.find('#audiotracks-select').hasClass('hidden'); // TODO hold state
|
|
131
|
-
this.$el.find('#audiotracks-button').attr('aria-expanded', open);
|
|
132
|
-
}
|
|
133
|
-
buttonElement() {
|
|
134
|
-
return this.$('button');
|
|
135
|
-
}
|
|
136
|
-
buttonElementText() {
|
|
137
|
-
return this.$('button .audio-text');
|
|
138
|
-
}
|
|
139
|
-
trackElement(id) {
|
|
140
|
-
return this.$('#audiotracks-select a' +
|
|
141
|
-
(id !== undefined ? `[data-audiotracks-select="${id}"]` : '')).parent();
|
|
142
|
-
}
|
|
143
|
-
getTitle() {
|
|
144
|
-
if (!this.currentTrack) {
|
|
145
|
-
return '';
|
|
146
|
-
}
|
|
147
|
-
return this.currentTrack.label || this.currentTrack.language;
|
|
148
|
-
}
|
|
149
|
-
startTrackSwitching() {
|
|
150
|
-
this.buttonElement().addClass('changing');
|
|
151
|
-
}
|
|
152
|
-
updateText() {
|
|
153
|
-
if (!this.currentTrack) {
|
|
154
|
-
return;
|
|
155
|
-
}
|
|
156
|
-
this.buttonElementText().text(this.currentTrack.label);
|
|
157
|
-
}
|
|
158
|
-
highlightCurrentTrack() {
|
|
159
|
-
this.trackElement().removeClass('current');
|
|
160
|
-
this.trackElement()
|
|
161
|
-
.find('a')
|
|
162
|
-
.removeClass('gcore-skin-active')
|
|
163
|
-
.attr('aria-checked', 'false');
|
|
164
|
-
if (this.currentTrack) {
|
|
165
|
-
this.trackElement(this.currentTrack.id)
|
|
166
|
-
.addClass('current')
|
|
167
|
-
.find('a')
|
|
168
|
-
.addClass('gcore-skin-active')
|
|
169
|
-
.attr('aria-checked', 'true');
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
package/lib/plugins/build.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/plugins/build.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,EAAE,MAAiB,CAAC"}
|
package/lib/plugins/build.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const CLAPPR_VERSION = '0.11.3';
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { UICorePlugin, Core } from '@clappr/core';
|
|
2
|
-
import '../../../assets/clappr-nerd-stats/clappr-nerd-stats.scss';
|
|
3
|
-
/**
|
|
4
|
-
* `PLUGIN` that displays useful network-related statistics.
|
|
5
|
-
* @beta
|
|
6
|
-
*
|
|
7
|
-
* @remarks
|
|
8
|
-
* Depends on:
|
|
9
|
-
*
|
|
10
|
-
* - {@link BottomGear}
|
|
11
|
-
*
|
|
12
|
-
* - {@link ClapprStats}
|
|
13
|
-
*
|
|
14
|
-
* The plugin is rendered as an item in the gear menu.
|
|
15
|
-
*
|
|
16
|
-
* When clicked, it shows an overlay window with the information about the network speed, latency, etc,
|
|
17
|
-
* and recommended quality level.
|
|
18
|
-
*/
|
|
19
|
-
export declare class ClapprNerdStats extends UICorePlugin {
|
|
20
|
-
private container;
|
|
21
|
-
private customMetrics;
|
|
22
|
-
private metrics;
|
|
23
|
-
private showing;
|
|
24
|
-
private shortcut;
|
|
25
|
-
private iconPosition;
|
|
26
|
-
private static readonly buttonTemplate;
|
|
27
|
-
/**
|
|
28
|
-
* @internal
|
|
29
|
-
*/
|
|
30
|
-
get name(): string;
|
|
31
|
-
/**
|
|
32
|
-
* @internal
|
|
33
|
-
*/
|
|
34
|
-
get supportedVersion(): {
|
|
35
|
-
min: string;
|
|
36
|
-
};
|
|
37
|
-
private static readonly template;
|
|
38
|
-
/**
|
|
39
|
-
* @internal
|
|
40
|
-
*/
|
|
41
|
-
get attributes(): {
|
|
42
|
-
'data-clappr-nerd-stats': string;
|
|
43
|
-
class: string;
|
|
44
|
-
};
|
|
45
|
-
/**
|
|
46
|
-
* @internal
|
|
47
|
-
*/
|
|
48
|
-
get events(): {
|
|
49
|
-
'click [data-show-stats-button]': string;
|
|
50
|
-
'click [data-close-button]': string;
|
|
51
|
-
'click [data-refresh-button]': string;
|
|
52
|
-
};
|
|
53
|
-
private get statsBoxElem();
|
|
54
|
-
private get statsBoxWidthThreshold();
|
|
55
|
-
private get playerWidth();
|
|
56
|
-
private get playerHeight();
|
|
57
|
-
constructor(core: Core);
|
|
58
|
-
/**
|
|
59
|
-
* @internal
|
|
60
|
-
*/
|
|
61
|
-
bindEvents(): void;
|
|
62
|
-
private onCoreReady;
|
|
63
|
-
/**
|
|
64
|
-
* @internal
|
|
65
|
-
*/
|
|
66
|
-
destroy(): import("@clappr/core").UIObject;
|
|
67
|
-
private toggle;
|
|
68
|
-
private show;
|
|
69
|
-
private hide;
|
|
70
|
-
private onPlayerResize;
|
|
71
|
-
private addGeneralMetrics;
|
|
72
|
-
private addCustomMetrics;
|
|
73
|
-
private updateMetrics;
|
|
74
|
-
private setStatsBoxSize;
|
|
75
|
-
/**
|
|
76
|
-
* @internal
|
|
77
|
-
*/
|
|
78
|
-
render(): this;
|
|
79
|
-
private addToBottomGear;
|
|
80
|
-
private clearCustomMetrics;
|
|
81
|
-
private refreshSpeedTest;
|
|
82
|
-
}
|
|
83
|
-
//# sourceMappingURL=ClapprNerdStats.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ClapprNerdStats.d.ts","sourceRoot":"","sources":["../../../src/plugins/clappr-nerd-stats/ClapprNerdStats.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAoB,IAAI,EAAa,MAAM,cAAc,CAAA;AAuB9E,OAAO,0DAA0D,CAAA;AA8FjE;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,OAAO,CAAC,SAAS,CAAyB;IAE1C,OAAO,CAAC,aAAa,CAIpB;IAED,OAAO,CAAC,OAAO,CAAwB;IAEvC,OAAO,CAAC,OAAO,CAAQ;IAEvB,OAAO,CAAC,QAAQ,CAAU;IAE1B,OAAO,CAAC,YAAY,CAAc;IAElC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAuB;IAE7D;;OAEG;IACH,IAAI,IAAI,WAEP;IAED;;OAEG;IACH,IAAI,gBAAgB;;MAEnB;IAED,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAuB;IAEvD;;OAEG;IACH,IAAa,UAAU;;;MAKtB;IAED;;OAEG;IACH,IAAa,MAAM;;;;MAMlB;IAED,OAAO,KAAK,YAAY,GAEvB;IAED,OAAO,KAAK,sBAAsB,GAEjC;IAED,OAAO,KAAK,WAAW,GAEtB;IAED,OAAO,KAAK,YAAY,GAEvB;gBAEW,IAAI,EAAE,IAAI;IAgBtB;;OAEG;IACM,UAAU;IAInB,OAAO,CAAC,WAAW;IAoBnB;;OAEG;IACM,OAAO;IAKhB,OAAO,CAAC,MAAM,CAMb;IAED,OAAO,CAAC,IAAI;IAeZ,OAAO,CAAC,IAAI;IAMZ,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,gBAAgB;IA+BxB,OAAO,CAAC,aAAa;IA4BrB,OAAO,CAAC,eAAe;IAUvB;;OAEG;IACM,MAAM;IASf,OAAO,CAAC,eAAe;IAiBvB,OAAO,CAAC,kBAAkB;IAY1B,OAAO,CAAC,gBAAgB;CAWzB"}
|
|
@@ -1,339 +0,0 @@
|
|
|
1
|
-
import { UICorePlugin, Events, template } from '@clappr/core';
|
|
2
|
-
import { reportError, trace } from '@gcorevideo/utils';
|
|
3
|
-
import Mousetrap from 'mousetrap';
|
|
4
|
-
import assert from 'assert';
|
|
5
|
-
import { CLAPPR_VERSION } from '../../build.js';
|
|
6
|
-
import { ClapprStatsEvents, } from '../clappr-stats/types.js';
|
|
7
|
-
import { newMetrics as newBaseMetrics } from '../clappr-stats/utils.js';
|
|
8
|
-
import Formatter from './formatter.js';
|
|
9
|
-
import { clearSpeedTestResults, configureSpeedTest, drawSpeedTestResults, initSpeedTest, startSpeedtest, stopSpeedtest, } from './speedtest/index.js';
|
|
10
|
-
import '../../../assets/clappr-nerd-stats/clappr-nerd-stats.scss';
|
|
11
|
-
import pluginHtml from '../../../assets/clappr-nerd-stats/clappr-nerd-stats.ejs';
|
|
12
|
-
import buttonHtml from '../../../assets/clappr-nerd-stats/button.ejs';
|
|
13
|
-
import statsIcon from '../../../assets/icons/new/stats.svg';
|
|
14
|
-
import { GearEvents } from '../bottom-gear/BottomGear.js';
|
|
15
|
-
const qualityClasses = [
|
|
16
|
-
'speedtest-quality-value-1',
|
|
17
|
-
'speedtest-quality-value-2',
|
|
18
|
-
'speedtest-quality-value-3',
|
|
19
|
-
'speedtest-quality-value-4',
|
|
20
|
-
'speedtest-quality-value-5',
|
|
21
|
-
];
|
|
22
|
-
const getDownloadQuality = (speedValue) => {
|
|
23
|
-
if (speedValue < 3) {
|
|
24
|
-
return 1;
|
|
25
|
-
}
|
|
26
|
-
else if (speedValue < 7) {
|
|
27
|
-
return 2;
|
|
28
|
-
}
|
|
29
|
-
else if (speedValue < 13) {
|
|
30
|
-
return 3;
|
|
31
|
-
}
|
|
32
|
-
else if (speedValue < 25) {
|
|
33
|
-
return 4;
|
|
34
|
-
}
|
|
35
|
-
else {
|
|
36
|
-
return 5;
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
const getPingQuality = (pingValue) => {
|
|
40
|
-
if (pingValue < 20) {
|
|
41
|
-
return 5;
|
|
42
|
-
}
|
|
43
|
-
else if (pingValue < 50) {
|
|
44
|
-
return 4;
|
|
45
|
-
}
|
|
46
|
-
else if (pingValue < 100) {
|
|
47
|
-
return 3;
|
|
48
|
-
}
|
|
49
|
-
else if (pingValue < 150) {
|
|
50
|
-
return 2;
|
|
51
|
-
}
|
|
52
|
-
else {
|
|
53
|
-
return 1;
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
const generateQualityHtml = (quality) => {
|
|
57
|
-
const html = [];
|
|
58
|
-
const qualityClassName = qualityClasses[quality - 1];
|
|
59
|
-
for (let i = 0; i < qualityClasses.length; i++) {
|
|
60
|
-
if (i < quality) {
|
|
61
|
-
html.push(`<div class="speedtest-quality-content-item ${qualityClassName}"></div>`);
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
html.push('<div class="speedtest-quality-content-item"></div>');
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
return html.join('');
|
|
68
|
-
};
|
|
69
|
-
const drawSummary = (customMetrics, vodContainer, liveContainer) => {
|
|
70
|
-
const { connectionSpeed, ping } = customMetrics;
|
|
71
|
-
if (!connectionSpeed || !ping) {
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
const downloadQuality = getDownloadQuality(connectionSpeed);
|
|
75
|
-
const pingQuality = getPingQuality(ping);
|
|
76
|
-
const liveQuality = Math.min(downloadQuality, pingQuality);
|
|
77
|
-
const vodHtml = generateQualityHtml(downloadQuality);
|
|
78
|
-
const liveHtml = generateQualityHtml(liveQuality);
|
|
79
|
-
vodContainer.html(vodHtml);
|
|
80
|
-
liveContainer.html(liveHtml);
|
|
81
|
-
};
|
|
82
|
-
const T = 'plugins.nerd_stats';
|
|
83
|
-
/**
|
|
84
|
-
* `PLUGIN` that displays useful network-related statistics.
|
|
85
|
-
* @beta
|
|
86
|
-
*
|
|
87
|
-
* @remarks
|
|
88
|
-
* Depends on:
|
|
89
|
-
*
|
|
90
|
-
* - {@link BottomGear}
|
|
91
|
-
*
|
|
92
|
-
* - {@link ClapprStats}
|
|
93
|
-
*
|
|
94
|
-
* The plugin is rendered as an item in the gear menu.
|
|
95
|
-
*
|
|
96
|
-
* When clicked, it shows an overlay window with the information about the network speed, latency, etc,
|
|
97
|
-
* and recommended quality level.
|
|
98
|
-
*/
|
|
99
|
-
export class ClapprNerdStats extends UICorePlugin {
|
|
100
|
-
container = null;
|
|
101
|
-
customMetrics = {
|
|
102
|
-
connectionSpeed: 0,
|
|
103
|
-
ping: 0,
|
|
104
|
-
jitter: 0,
|
|
105
|
-
};
|
|
106
|
-
metrics = newMetrics();
|
|
107
|
-
showing = false;
|
|
108
|
-
shortcut;
|
|
109
|
-
iconPosition;
|
|
110
|
-
static buttonTemplate = template(buttonHtml);
|
|
111
|
-
/**
|
|
112
|
-
* @internal
|
|
113
|
-
*/
|
|
114
|
-
get name() {
|
|
115
|
-
return 'nerd_stats';
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* @internal
|
|
119
|
-
*/
|
|
120
|
-
get supportedVersion() {
|
|
121
|
-
return { min: CLAPPR_VERSION };
|
|
122
|
-
}
|
|
123
|
-
static template = template(pluginHtml);
|
|
124
|
-
/**
|
|
125
|
-
* @internal
|
|
126
|
-
*/
|
|
127
|
-
get attributes() {
|
|
128
|
-
return {
|
|
129
|
-
'data-clappr-nerd-stats': '',
|
|
130
|
-
class: 'clappr-nerd-stats',
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
/**
|
|
134
|
-
* @internal
|
|
135
|
-
*/
|
|
136
|
-
get events() {
|
|
137
|
-
return {
|
|
138
|
-
'click [data-show-stats-button]': 'showOrHide',
|
|
139
|
-
'click [data-close-button]': 'hide',
|
|
140
|
-
'click [data-refresh-button]': 'refreshSpeedTest',
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
get statsBoxElem() {
|
|
144
|
-
return '.clappr-nerd-stats[data-clappr-nerd-stats] .stats-box';
|
|
145
|
-
}
|
|
146
|
-
get statsBoxWidthThreshold() {
|
|
147
|
-
return 720;
|
|
148
|
-
}
|
|
149
|
-
get playerWidth() {
|
|
150
|
-
return this.core.$el.width();
|
|
151
|
-
}
|
|
152
|
-
get playerHeight() {
|
|
153
|
-
return this.core.$el.height();
|
|
154
|
-
}
|
|
155
|
-
constructor(core) {
|
|
156
|
-
super(core);
|
|
157
|
-
this.shortcut = core.options.clapprNerdStats?.shortcut ?? [
|
|
158
|
-
'command+shift+s',
|
|
159
|
-
'ctrl+shift+s',
|
|
160
|
-
];
|
|
161
|
-
this.iconPosition =
|
|
162
|
-
core.options.clapprNerdStats?.iconPosition ?? 'bottom-right';
|
|
163
|
-
this.customMetrics = {
|
|
164
|
-
connectionSpeed: 0,
|
|
165
|
-
ping: 0,
|
|
166
|
-
jitter: 0,
|
|
167
|
-
};
|
|
168
|
-
configureSpeedTest(core.options.clapprNerdStats?.speedTestServers ?? []);
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* @internal
|
|
172
|
-
*/
|
|
173
|
-
bindEvents() {
|
|
174
|
-
this.listenToOnce(this.core, Events.CORE_READY, this.onCoreReady);
|
|
175
|
-
}
|
|
176
|
-
onCoreReady() {
|
|
177
|
-
const bottomGear = this.core.getPlugin('bottom_gear');
|
|
178
|
-
assert(bottomGear, 'bottom_gear plugin is required');
|
|
179
|
-
this.listenTo(bottomGear, GearEvents.RENDERED, this.addToBottomGear);
|
|
180
|
-
this.container = this.core.activeContainer;
|
|
181
|
-
const clapprStats = this.container?.getPlugin('clappr_stats');
|
|
182
|
-
assert(clapprStats, 'clappr-stats not available. Please, include it as a plugin of your Clappr instance.\n' +
|
|
183
|
-
'For more info, visit: https://github.com/clappr/clappr-stats.');
|
|
184
|
-
Mousetrap.bind(this.shortcut, this.toggle);
|
|
185
|
-
this.listenTo(this.core, Events.CORE_RESIZE, this.onPlayerResize);
|
|
186
|
-
this.listenTo(clapprStats, ClapprStatsEvents.REPORT, this.updateMetrics);
|
|
187
|
-
this.updateMetrics(clapprStats.exportMetrics());
|
|
188
|
-
this.render();
|
|
189
|
-
}
|
|
190
|
-
/**
|
|
191
|
-
* @internal
|
|
192
|
-
*/
|
|
193
|
-
destroy() {
|
|
194
|
-
Mousetrap.unbind(this.shortcut);
|
|
195
|
-
return super.destroy();
|
|
196
|
-
}
|
|
197
|
-
toggle = () => {
|
|
198
|
-
if (this.showing) {
|
|
199
|
-
this.hide();
|
|
200
|
-
}
|
|
201
|
-
else {
|
|
202
|
-
this.show();
|
|
203
|
-
}
|
|
204
|
-
};
|
|
205
|
-
show() {
|
|
206
|
-
this.core.$el.find(this.statsBoxElem).show();
|
|
207
|
-
this.showing = true;
|
|
208
|
-
this.refreshSpeedTest();
|
|
209
|
-
initSpeedTest(this.customMetrics)
|
|
210
|
-
.then(() => {
|
|
211
|
-
startSpeedtest();
|
|
212
|
-
})
|
|
213
|
-
.catch((e) => {
|
|
214
|
-
reportError(e);
|
|
215
|
-
this.disable();
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
|
-
hide() {
|
|
219
|
-
this.core.$el.find(this.statsBoxElem).hide();
|
|
220
|
-
this.showing = false;
|
|
221
|
-
stopSpeedtest();
|
|
222
|
-
}
|
|
223
|
-
onPlayerResize() {
|
|
224
|
-
this.setStatsBoxSize();
|
|
225
|
-
}
|
|
226
|
-
addGeneralMetrics() {
|
|
227
|
-
this.metrics.general = {
|
|
228
|
-
displayResolution: this.playerWidth + 'x' + this.playerHeight,
|
|
229
|
-
volume: this.container?.volume,
|
|
230
|
-
};
|
|
231
|
-
}
|
|
232
|
-
addCustomMetrics() {
|
|
233
|
-
this.metrics.custom = this.customMetrics;
|
|
234
|
-
const videoQualityNames = [
|
|
235
|
-
'SD (480p)',
|
|
236
|
-
'HD (720p)',
|
|
237
|
-
'Full HD (1080p)',
|
|
238
|
-
'2K (1440p)',
|
|
239
|
-
'4K (2160p)',
|
|
240
|
-
];
|
|
241
|
-
const { connectionSpeed, ping } = this.customMetrics;
|
|
242
|
-
if (!connectionSpeed || !ping) {
|
|
243
|
-
const calculatingText = 'Calculating... Please wait.';
|
|
244
|
-
this.metrics.custom.vodQuality = calculatingText;
|
|
245
|
-
this.metrics.custom.liveQuality = calculatingText;
|
|
246
|
-
return;
|
|
247
|
-
}
|
|
248
|
-
const downloadQuality = getDownloadQuality(connectionSpeed);
|
|
249
|
-
const pingQuality = getPingQuality(ping);
|
|
250
|
-
const liveQuality = Math.min(downloadQuality, pingQuality);
|
|
251
|
-
const prefix = 'Optimal for ';
|
|
252
|
-
this.metrics.custom.vodQuality =
|
|
253
|
-
prefix + videoQualityNames[downloadQuality - 1];
|
|
254
|
-
this.metrics.custom.liveQuality =
|
|
255
|
-
prefix + videoQualityNames[liveQuality - 1];
|
|
256
|
-
}
|
|
257
|
-
updateMetrics(metrics) {
|
|
258
|
-
Object.assign(this.metrics, metrics);
|
|
259
|
-
this.addGeneralMetrics();
|
|
260
|
-
this.addCustomMetrics();
|
|
261
|
-
const scrollTop = this.core.$el.find(this.statsBoxElem).scrollTop();
|
|
262
|
-
this.$el.html(ClapprNerdStats.template({
|
|
263
|
-
metrics: Formatter.format(this.metrics),
|
|
264
|
-
iconPosition: this.iconPosition,
|
|
265
|
-
}));
|
|
266
|
-
this.setStatsBoxSize();
|
|
267
|
-
drawSpeedTestResults();
|
|
268
|
-
drawSummary(this.metrics?.custom, this.$el.find('.speedtest-quality-content[data-streaming-type="vod"]'), this.$el.find('.speedtest-quality-content[data-streaming-type="live"]'));
|
|
269
|
-
this.core.$el.find(this.statsBoxElem).scrollTop(scrollTop);
|
|
270
|
-
if (!this.showing) {
|
|
271
|
-
this.hide();
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
setStatsBoxSize() {
|
|
275
|
-
if (this.playerWidth >= this.statsBoxWidthThreshold) {
|
|
276
|
-
this.$el.find(this.statsBoxElem).addClass('wide');
|
|
277
|
-
this.$el.find(this.statsBoxElem).removeClass('narrow');
|
|
278
|
-
}
|
|
279
|
-
else {
|
|
280
|
-
this.$el.find(this.statsBoxElem).removeClass('wide');
|
|
281
|
-
this.$el.find(this.statsBoxElem).addClass('narrow');
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
/**
|
|
285
|
-
* @internal
|
|
286
|
-
*/
|
|
287
|
-
render() {
|
|
288
|
-
trace(`${T} render`);
|
|
289
|
-
// TODO append to the container
|
|
290
|
-
this.core.$el.append(this.$el[0]);
|
|
291
|
-
this.hide();
|
|
292
|
-
return this;
|
|
293
|
-
}
|
|
294
|
-
addToBottomGear() {
|
|
295
|
-
trace(`${T} addToBottomGear`);
|
|
296
|
-
const gear = this.core.getPlugin('bottom_gear');
|
|
297
|
-
gear
|
|
298
|
-
.addItem('nerd_stats')
|
|
299
|
-
.html(ClapprNerdStats.buttonTemplate({
|
|
300
|
-
icon: statsIcon,
|
|
301
|
-
i18n: this.core.i18n,
|
|
302
|
-
}))
|
|
303
|
-
.on('click', (e) => {
|
|
304
|
-
e.stopPropagation();
|
|
305
|
-
this.toggle();
|
|
306
|
-
});
|
|
307
|
-
}
|
|
308
|
-
clearCustomMetrics() {
|
|
309
|
-
const clapprStats = this.container?.getPlugin('clappr_stats');
|
|
310
|
-
this.customMetrics.connectionSpeed = 0;
|
|
311
|
-
this.customMetrics.ping = 0;
|
|
312
|
-
this.customMetrics.jitter = 0;
|
|
313
|
-
if (clapprStats) {
|
|
314
|
-
this.updateMetrics(clapprStats.exportMetrics());
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
refreshSpeedTest() {
|
|
318
|
-
stopSpeedtest();
|
|
319
|
-
setTimeout(() => {
|
|
320
|
-
this.clearCustomMetrics();
|
|
321
|
-
clearSpeedTestResults();
|
|
322
|
-
drawSpeedTestResults();
|
|
323
|
-
}, 200);
|
|
324
|
-
setTimeout(() => {
|
|
325
|
-
startSpeedtest();
|
|
326
|
-
}, 800);
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
function newMetrics() {
|
|
330
|
-
return {
|
|
331
|
-
...newBaseMetrics(),
|
|
332
|
-
general: {},
|
|
333
|
-
custom: {
|
|
334
|
-
connectionSpeed: 0,
|
|
335
|
-
ping: 0,
|
|
336
|
-
jitter: 0,
|
|
337
|
-
},
|
|
338
|
-
};
|
|
339
|
-
}
|