@eluvio/elv-player-js 2.0.30 → 2.0.31
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/README.md +2 -0
- package/dist/.vite/manifest.json +17 -17
- package/dist/{Analytics-CPnNuFCG.js → Analytics-C3Wlfggq.js} +1 -1
- package/dist/{Analytics-CDHiK0YD.mjs → Analytics-Db4Y6O86.mjs} +1 -1
- package/dist/{dash.all.min-8uHXzdUT.js → dash.all.min-BKFMPAlA.js} +1 -1
- package/dist/{dash.all.min-D1JVzlKd.mjs → dash.all.min-C9-x0osa.mjs} +1 -1
- package/dist/elv-player-js.cjs.js +1 -1
- package/dist/elv-player-js.css +1 -1
- package/dist/elv-player-js.es.js +1 -1
- package/dist/{index-kBF15h_J.js → index-B6twYHJw.js} +74 -74
- package/dist/{index-D-ZvMxzR.mjs → index-B7c1jTSa.mjs} +1 -1
- package/dist/{index-nZRZlezJ.js → index-CEQNadM6.js} +1 -1
- package/dist/{index-CEg6alSD.mjs → index-nNplF-cb.mjs} +7627 -7529
- package/lib/player/Controls.js +20 -0
- package/lib/player/Player.js +22 -9
- package/lib/player/PlayerParameters.js +1 -5
- package/lib/static/icons/Icons.js +1 -0
- package/lib/static/icons/svgs/info.svg +1 -0
- package/lib/static/stylesheets/player.module.scss +35 -5
- package/lib/ui/BuildIcons.cjs +2 -1
- package/lib/ui/Components.jsx +88 -35
- package/lib/ui/PlayerUI.jsx +14 -2
- package/package.json +1 -1
package/lib/player/Controls.js
CHANGED
|
@@ -1053,6 +1053,26 @@ class PlayerControls {
|
|
|
1053
1053
|
Destroy() {
|
|
1054
1054
|
this.player.Destroy();
|
|
1055
1055
|
}
|
|
1056
|
+
|
|
1057
|
+
GetDebugInfo() {
|
|
1058
|
+
const sourceOptions = JSON.parse(JSON.stringify(this.player.sourceOptions));
|
|
1059
|
+
delete sourceOptions.playoutOptions;
|
|
1060
|
+
|
|
1061
|
+
let error = this.player.__error && JSON.parse(JSON.stringify(this.player.__error));
|
|
1062
|
+
if(error && Object.keys(error).length === 0) {
|
|
1063
|
+
error = this.player.__error.toString();
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
return {
|
|
1067
|
+
appUrl: window.location.href,
|
|
1068
|
+
userAddress: this.player.userAddress,
|
|
1069
|
+
userAgent: navigator.userAgent,
|
|
1070
|
+
userLanguage: navigator.language,
|
|
1071
|
+
playoutUrl: this.player.playoutUrl,
|
|
1072
|
+
sourceOptions,
|
|
1073
|
+
error
|
|
1074
|
+
};
|
|
1075
|
+
}
|
|
1056
1076
|
}
|
|
1057
1077
|
|
|
1058
1078
|
export default PlayerControls;
|
package/lib/player/Player.js
CHANGED
|
@@ -48,7 +48,6 @@ export class EluvioPlayer {
|
|
|
48
48
|
this.loading = true;
|
|
49
49
|
this.target = target;
|
|
50
50
|
this.video = video;
|
|
51
|
-
this.SetErrorMessage = SetErrorMessage;
|
|
52
51
|
this.controls = new PlayerControls({player: this});
|
|
53
52
|
this.__settingsListeners = [];
|
|
54
53
|
this.__listenerDisposers = [];
|
|
@@ -68,6 +67,12 @@ export class EluvioPlayer {
|
|
|
68
67
|
EluvioPlayerParameters.controls.ON,
|
|
69
68
|
EluvioPlayerParameters.controls.AUTO_HIDE
|
|
70
69
|
].includes(parameters.playerOptions.controls);
|
|
70
|
+
this.__error = undefined;
|
|
71
|
+
|
|
72
|
+
this.SetErrorMessage = (message, error) => {
|
|
73
|
+
SetErrorMessage(message);
|
|
74
|
+
this.__error = error;
|
|
75
|
+
};
|
|
71
76
|
|
|
72
77
|
try {
|
|
73
78
|
// If custom HLS parameters are specified, set profile to custom
|
|
@@ -124,6 +129,8 @@ export class EluvioPlayer {
|
|
|
124
129
|
this.__tokenResolved = true;
|
|
125
130
|
}
|
|
126
131
|
|
|
132
|
+
this.userAddress = this.clientOptions.client.CurrentAccountAddress();
|
|
133
|
+
|
|
127
134
|
return this.clientOptions.client;
|
|
128
135
|
}
|
|
129
136
|
|
|
@@ -326,8 +333,6 @@ export class EluvioPlayer {
|
|
|
326
333
|
|
|
327
334
|
this.__Reset();
|
|
328
335
|
|
|
329
|
-
|
|
330
|
-
|
|
331
336
|
this.initialized = false;
|
|
332
337
|
this.loading = true;
|
|
333
338
|
this.initTime = Date.now();
|
|
@@ -401,6 +406,10 @@ export class EluvioPlayer {
|
|
|
401
406
|
this.video.textTracks && this.video.textTracks.addEventListener("change", () => this.__SettingsUpdate());
|
|
402
407
|
this.video.audioTracks && this.video.audioTracks.addEventListener("change", () => this.__SettingsUpdate());
|
|
403
408
|
|
|
409
|
+
if(this.playerOptions.startTime) {
|
|
410
|
+
this.controls.Seek({time: this.playerOptions.startTime});
|
|
411
|
+
}
|
|
412
|
+
|
|
404
413
|
if(this.playerOptions.autoplay === EluvioPlayerParameters.autoplay.ON) {
|
|
405
414
|
this.controls.Play();
|
|
406
415
|
}
|
|
@@ -515,7 +524,7 @@ export class EluvioPlayer {
|
|
|
515
524
|
|
|
516
525
|
if(permissionErrorMessage) {
|
|
517
526
|
error.permission_message = permissionErrorMessage;
|
|
518
|
-
this.SetErrorMessage(permissionErrorMessage);
|
|
527
|
+
this.SetErrorMessage(permissionErrorMessage, error);
|
|
519
528
|
|
|
520
529
|
if(typeof error === "object") {
|
|
521
530
|
error.permission_message = permissionErrorMessage;
|
|
@@ -523,11 +532,11 @@ export class EluvioPlayer {
|
|
|
523
532
|
this.Log(permissionErrorMessage, true);
|
|
524
533
|
}
|
|
525
534
|
} else {
|
|
526
|
-
this.SetErrorMessage(error.displayMessage || "Insufficient permissions");
|
|
535
|
+
this.SetErrorMessage(error.displayMessage || "Insufficient permissions", error);
|
|
527
536
|
}
|
|
528
537
|
// eslint-disable-next-line no-empty
|
|
529
538
|
} catch (error) {
|
|
530
|
-
this.SetErrorMessage(error.displayMessage || "Insufficient permissions");
|
|
539
|
+
this.SetErrorMessage(error.displayMessage || "Insufficient permissions", error);
|
|
531
540
|
}
|
|
532
541
|
} else if(error.status >= 500) {
|
|
533
542
|
this.__HardReload(error, 10000);
|
|
@@ -721,7 +730,7 @@ export class EluvioPlayer {
|
|
|
721
730
|
|
|
722
731
|
if(error.response && error.response.code === 403) {
|
|
723
732
|
// Not allowed to access
|
|
724
|
-
this.SetErrorMessage("Insufficient permissions");
|
|
733
|
+
this.SetErrorMessage("Insufficient permissions", error);
|
|
725
734
|
} else if(this.errors < 5) {
|
|
726
735
|
if(error.fatal) {
|
|
727
736
|
if(error.data && error.data.type === this.HLS.ErrorTypes.MEDIA_ERROR) {
|
|
@@ -1119,6 +1128,7 @@ export class EluvioPlayer {
|
|
|
1119
1128
|
this.airplayAvailable = false;
|
|
1120
1129
|
this.chromecastAvailable = chromecastAvailable && this.playerOptions.allowCasting;
|
|
1121
1130
|
this.casting = false;
|
|
1131
|
+
this.__error = undefined;
|
|
1122
1132
|
}
|
|
1123
1133
|
|
|
1124
1134
|
async __HardReload(error, delay=6000) {
|
|
@@ -1128,7 +1138,7 @@ export class EluvioPlayer {
|
|
|
1128
1138
|
this.reloads += 1;
|
|
1129
1139
|
|
|
1130
1140
|
if(this.reloads > 10) {
|
|
1131
|
-
this.SetErrorMessage((error && error.displayMessage) || "Unable to play content");
|
|
1141
|
+
this.SetErrorMessage((error && error.displayMessage) || "Unable to play content", error);
|
|
1132
1142
|
return;
|
|
1133
1143
|
}
|
|
1134
1144
|
|
|
@@ -1147,7 +1157,10 @@ export class EluvioPlayer {
|
|
|
1147
1157
|
}
|
|
1148
1158
|
}
|
|
1149
1159
|
|
|
1150
|
-
this.SetErrorMessage(
|
|
1160
|
+
this.SetErrorMessage(
|
|
1161
|
+
(error && error.displayMessage) || "Something went wrong, reloading player...",
|
|
1162
|
+
error
|
|
1163
|
+
);
|
|
1151
1164
|
await new Promise(resolve => setTimeout(resolve, delay));
|
|
1152
1165
|
|
|
1153
1166
|
if(this.__destroyed) { return; }
|
|
@@ -139,11 +139,6 @@ export const DefaultParameters = {
|
|
|
139
139
|
liveDVR: PlayerParameters.liveDVR.OFF,
|
|
140
140
|
headers: []
|
|
141
141
|
},
|
|
142
|
-
mediaCollectionOptions: {
|
|
143
|
-
mediaCatalogObjectId: undefined,
|
|
144
|
-
mediaCatalogVersionHash: undefined,
|
|
145
|
-
collectionId: undefined
|
|
146
|
-
},
|
|
147
142
|
playoutOptions: undefined,
|
|
148
143
|
playoutParameters: {
|
|
149
144
|
objectId: undefined,
|
|
@@ -180,6 +175,7 @@ export const DefaultParameters = {
|
|
|
180
175
|
showLoader: PlayerParameters.showLoader.ON,
|
|
181
176
|
permanentPoster: PlayerParameters.permanentPoster.OFF,
|
|
182
177
|
allowCasting: PlayerParameters.allowCasting.ON,
|
|
178
|
+
startTime: undefined,
|
|
183
179
|
hlsjsOptions: undefined,
|
|
184
180
|
dashjsOptions: undefined,
|
|
185
181
|
debugLogging: false,
|
|
@@ -34,3 +34,4 @@ export const ContentCredentialsIcon = "<svg width=\"26\" height=\"26\" viewBox=\
|
|
|
34
34
|
export const CopyIcon = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"feather feather-copy\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" ry=\"2\"></rect><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"></path></svg>";
|
|
35
35
|
export const AirplayIcon = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"feather feather-airplay\"><path d=\"M5 17H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2h-1\"></path><polygon points=\"12 15 17 21 7 21 12 15\"></polygon></svg>";
|
|
36
36
|
export const ChromecastIcon = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"feather feather-cast\"><path d=\"M2 16.1A5 5 0 0 1 5.9 20M2 12.05A9 9 0 0 1 9.95 20M2 8V6a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2h-6\"></path><line x1=\"2\" y1=\"20\" x2=\"2.01\" y2=\"20\"></line></svg>";
|
|
37
|
+
export const InfoIcon = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"feather feather-info\"><circle cx=\"12\" cy=\"12\" r=\"10\"></circle><line x1=\"12\" y1=\"16\" x2=\"12\" y2=\"12\"></line><line x1=\"12\" y1=\"8\" x2=\"12.01\" y2=\"8\"></line></svg>";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-info"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="16" x2="12" y2="12"></line><line x1="12" y1="8" x2="12.01" y2="8"></line></svg>
|
|
@@ -9,14 +9,15 @@
|
|
|
9
9
|
--layer-error: 4;
|
|
10
10
|
--layer-controls: 5;
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
--color-error: #FFF;
|
|
14
|
-
|
|
12
|
+
font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
|
15
13
|
height: 100%;
|
|
16
14
|
inset: 0;
|
|
17
15
|
position: absolute;
|
|
18
16
|
width: 100%;
|
|
19
17
|
|
|
18
|
+
--color-highlight: #3784eb;
|
|
19
|
+
--color-error: #FFF;
|
|
20
|
+
|
|
20
21
|
&--rotated {
|
|
21
22
|
height: 100vw;
|
|
22
23
|
margin-top: -100vw;
|
|
@@ -88,8 +89,8 @@
|
|
|
88
89
|
align-items: center;
|
|
89
90
|
color: var(--color-error);
|
|
90
91
|
display: flex;
|
|
91
|
-
|
|
92
|
-
|
|
92
|
+
flex-direction: column;
|
|
93
|
+
gap: 30px;
|
|
93
94
|
height: 100%;
|
|
94
95
|
justify-content: center;
|
|
95
96
|
left: 0;
|
|
@@ -98,6 +99,35 @@
|
|
|
98
99
|
top: 0;
|
|
99
100
|
width: 100%;
|
|
100
101
|
z-index: var(--layer-error);
|
|
102
|
+
|
|
103
|
+
&__message {
|
|
104
|
+
font-size: 24px;
|
|
105
|
+
font-weight: 300;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
&__copy-debug-button {
|
|
109
|
+
align-items: center;
|
|
110
|
+
background-color: var(--color-error);
|
|
111
|
+
border: 1px solid var(--color-error);
|
|
112
|
+
border-radius: 5px;
|
|
113
|
+
color: #000;
|
|
114
|
+
display: flex;
|
|
115
|
+
gap: 10px;
|
|
116
|
+
height: 45px;
|
|
117
|
+
opacity: 0.9;
|
|
118
|
+
padding: 10px 20px;
|
|
119
|
+
transition: opacity 0.15s ease;
|
|
120
|
+
|
|
121
|
+
&:hover {
|
|
122
|
+
opacity: 1;
|
|
123
|
+
transition: opacity 0.35s ease;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
&__icon {
|
|
128
|
+
height: 18px;
|
|
129
|
+
width: 18px;
|
|
130
|
+
}
|
|
101
131
|
}
|
|
102
132
|
|
|
103
133
|
:global(.__eluvio-player--size-md),
|
package/lib/ui/BuildIcons.cjs
CHANGED
|
@@ -36,7 +36,8 @@ const iconSource = {
|
|
|
36
36
|
ContentCredentialsIcon: Path.resolve(__dirname, "../static/icons/svgs/content-credentials.svg"),
|
|
37
37
|
CopyIcon: Path.resolve(__dirname, "../static/icons/svgs/copy.svg"),
|
|
38
38
|
AirplayIcon: Path.resolve(__dirname, "../static/icons/svgs/airplay.svg"),
|
|
39
|
-
ChromecastIcon: Path.resolve(__dirname, "../static/icons/svgs/cast.svg")
|
|
39
|
+
ChromecastIcon: Path.resolve(__dirname, "../static/icons/svgs/cast.svg"),
|
|
40
|
+
InfoIcon: Path.resolve(__dirname, "../static/icons/svgs/info.svg")
|
|
40
41
|
};
|
|
41
42
|
|
|
42
43
|
let iconFile = "// WARNING: Do not edit this file manually\n";
|
package/lib/ui/Components.jsx
CHANGED
|
@@ -17,6 +17,20 @@ export const Spinner = ({light, className=""}) => (
|
|
|
17
17
|
|
|
18
18
|
export const SVG = ({icon, className=""}) => <div className={`${CommonStyles["svg"]} ${className}`} dangerouslySetInnerHTML={{__html: icon}} />;
|
|
19
19
|
|
|
20
|
+
export const Copy = async (value) => {
|
|
21
|
+
try {
|
|
22
|
+
value = (value || "").toString();
|
|
23
|
+
|
|
24
|
+
await navigator.clipboard.writeText(value);
|
|
25
|
+
} catch(error) {
|
|
26
|
+
const input = document.createElement("input");
|
|
27
|
+
|
|
28
|
+
input.value = value;
|
|
29
|
+
input.select();
|
|
30
|
+
input.setSelectionRange(0, 99999);
|
|
31
|
+
document.execCommand("copy");
|
|
32
|
+
}
|
|
33
|
+
};
|
|
20
34
|
|
|
21
35
|
const icons = {
|
|
22
36
|
[ACTIONS.PLAY]: Icons.PlayIcon,
|
|
@@ -209,6 +223,15 @@ export const SettingsMenu = ({player, Hide, className=""}) => {
|
|
|
209
223
|
rate: {
|
|
210
224
|
label: "Playback Rate",
|
|
211
225
|
Update: index => player.controls.SetPlaybackRate({index})
|
|
226
|
+
},
|
|
227
|
+
advanced: {
|
|
228
|
+
label: "Advanced",
|
|
229
|
+
Update: option => {
|
|
230
|
+
if(option === "copy_debug_info") {
|
|
231
|
+
Copy(JSON.stringify(player.controls.GetDebugInfo(), null, 2));
|
|
232
|
+
Hide();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
212
235
|
}
|
|
213
236
|
};
|
|
214
237
|
|
|
@@ -225,23 +248,36 @@ export const SettingsMenu = ({player, Hide, className=""}) => {
|
|
|
225
248
|
<div>{ settings[activeMenu].label }</div>
|
|
226
249
|
</button>
|
|
227
250
|
{
|
|
228
|
-
|
|
251
|
+
activeMenu === "advanced" ?
|
|
229
252
|
<button
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
aria-
|
|
233
|
-
autoFocus={option.active}
|
|
234
|
-
aria-label={`${settings[activeMenu].label}: ${option.label || ""}`}
|
|
253
|
+
role="button"
|
|
254
|
+
autoFocus
|
|
255
|
+
aria-label="Copy Debug Info"
|
|
235
256
|
onClick={() => {
|
|
236
|
-
settings[activeMenu].Update(
|
|
257
|
+
settings[activeMenu].Update("copy_debug_info");
|
|
237
258
|
SetSubmenu(undefined);
|
|
238
259
|
}}
|
|
239
|
-
className={
|
|
260
|
+
className={CommonStyles["menu-option"]}
|
|
240
261
|
>
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
262
|
+
Copy Debug Info
|
|
263
|
+
</button> :
|
|
264
|
+
options[activeMenu].options.map(option =>
|
|
265
|
+
<button
|
|
266
|
+
key={`option-${option.index}`}
|
|
267
|
+
role="menuitemradio"
|
|
268
|
+
aria-checked={option.active}
|
|
269
|
+
autoFocus={option.active}
|
|
270
|
+
aria-label={`${settings[activeMenu].label}: ${option.label || ""}`}
|
|
271
|
+
onClick={() => {
|
|
272
|
+
settings[activeMenu].Update(option.index);
|
|
273
|
+
SetSubmenu(undefined);
|
|
274
|
+
}}
|
|
275
|
+
className={`${CommonStyles["menu-option"]} ${option.active ? CommonStyles["menu-option-active"] : ""}`}
|
|
276
|
+
>
|
|
277
|
+
{option.label || ""}
|
|
278
|
+
{option.active ? <SVG icon={Icons.CheckmarkIcon} className={CommonStyles["menu-option-icon"]}/> : null}
|
|
279
|
+
</button>
|
|
280
|
+
)
|
|
245
281
|
}
|
|
246
282
|
</div>
|
|
247
283
|
);
|
|
@@ -250,47 +286,79 @@ export const SettingsMenu = ({player, Hide, className=""}) => {
|
|
|
250
286
|
<div key="menu" role="menu" className={`${CommonStyles["menu"]} ${className}`}>
|
|
251
287
|
{
|
|
252
288
|
!options.hasQualityOptions ? null :
|
|
253
|
-
<button
|
|
254
|
-
|
|
289
|
+
<button
|
|
290
|
+
autoFocus role="menuitem"
|
|
291
|
+
onClick={() => SetSubmenu("quality")}
|
|
292
|
+
className={CommonStyles["menu-option"]}
|
|
293
|
+
>
|
|
255
294
|
{`${settings.quality.label}: ${(options.quality.active && options.quality.active.activeLabel) || ""}`}
|
|
256
295
|
<SVG icon={Icons.ChevronRightIcon} className={CommonStyles["menu-option-icon"]}/>
|
|
257
296
|
</button>
|
|
258
297
|
}
|
|
259
298
|
{
|
|
260
299
|
!options.hasAudioOptions ? null :
|
|
261
|
-
<button
|
|
300
|
+
<button
|
|
301
|
+
autoFocus={!options.hasQualityOptions}
|
|
302
|
+
role="menuitem"
|
|
303
|
+
onClick={() => SetSubmenu("audio")}
|
|
304
|
+
className={CommonStyles["menu-option"]}
|
|
305
|
+
>
|
|
262
306
|
{`${settings.audio.label}: ${(options.audio.active && options.audio.active.label) || ""}`}
|
|
263
307
|
<SVG icon={Icons.ChevronRightIcon} className={CommonStyles["menu-option-icon"]}/>
|
|
264
308
|
</button>
|
|
265
309
|
}
|
|
266
310
|
{
|
|
267
311
|
!options.hasTextOptions ? null :
|
|
268
|
-
<button
|
|
312
|
+
<button
|
|
313
|
+
autoFocus={!options.hasQualityOptions && !options.hasAudioOptions}
|
|
314
|
+
role="menuitem"
|
|
315
|
+
onClick={() => SetSubmenu("text")}
|
|
316
|
+
className={CommonStyles["menu-option"]}
|
|
317
|
+
>
|
|
269
318
|
{`${settings.text.label}: ${(options.text.active && options.text.active.label) || ""}`}
|
|
270
319
|
<SVG icon={Icons.ChevronRightIcon} className={CommonStyles["menu-option-icon"]}/>
|
|
271
320
|
</button>
|
|
272
321
|
}
|
|
273
322
|
{
|
|
274
323
|
!options.hasProfileOptons ? null :
|
|
275
|
-
<button
|
|
324
|
+
<button
|
|
325
|
+
autoFocus={!options.hasQualityOptions && !options.hasAudioOptions && !options.hasTextOptions}
|
|
326
|
+
role="menuitem"
|
|
327
|
+
onClick={() => SetSubmenu("profile")}
|
|
328
|
+
className={CommonStyles["menu-option"]}
|
|
329
|
+
>
|
|
276
330
|
{`${settings.profile.label}: ${(options.profile.active && options.profile.active.label) || ""}`}
|
|
277
331
|
<SVG icon={Icons.ChevronRightIcon} className={CommonStyles["menu-option-icon"]}/>
|
|
278
332
|
</button>
|
|
279
333
|
}
|
|
280
334
|
{
|
|
281
335
|
!options.hasRateOptions ? null :
|
|
282
|
-
<button
|
|
336
|
+
<button
|
|
337
|
+
autoFocus={!options.hasQualityOptions && !options.hasAudioOptions && !options.hasTextOptions && !options.hasProfileOptons}
|
|
338
|
+
role="menuitem"
|
|
339
|
+
onClick={() => SetSubmenu("rate")}
|
|
340
|
+
className={CommonStyles["menu-option"]}
|
|
341
|
+
>
|
|
283
342
|
{`${settings.rate.label}: ${(options.rate.active && options.rate.active.label) || ""}`}
|
|
284
343
|
<SVG icon={Icons.ChevronRightIcon} className={CommonStyles["menu-option-icon"]}/>
|
|
285
344
|
</button>
|
|
286
345
|
}
|
|
346
|
+
<button
|
|
347
|
+
autoFocus={!options.hasRateOptions && !options.hasQualityOptions && !options.hasAudioOptions && !options.hasTextOptions && !options.hasProfileOptons}
|
|
348
|
+
role="button"
|
|
349
|
+
onClick={() => SetSubmenu("advanced")}
|
|
350
|
+
className={CommonStyles["menu-option"]}
|
|
351
|
+
>
|
|
352
|
+
{ settings.advanced.label }
|
|
353
|
+
<SVG icon={Icons.ChevronRightIcon} className={CommonStyles["menu-option-icon"]}/>
|
|
354
|
+
</button>
|
|
287
355
|
</div>
|
|
288
356
|
);
|
|
289
357
|
}
|
|
290
358
|
|
|
291
359
|
return (
|
|
292
360
|
<div ref={menuRef}>
|
|
293
|
-
{
|
|
361
|
+
{content}
|
|
294
362
|
</div>
|
|
295
363
|
);
|
|
296
364
|
};
|
|
@@ -302,7 +370,7 @@ export const DVRToggle = ({player}) => {
|
|
|
302
370
|
const disposer = player.controls.RegisterSettingsListener(() => {
|
|
303
371
|
if(!player.controls) { return; }
|
|
304
372
|
|
|
305
|
-
setDVREnabled(player.controls.IsDVREnabled())
|
|
373
|
+
setDVREnabled(player.controls.IsDVREnabled());
|
|
306
374
|
});
|
|
307
375
|
|
|
308
376
|
return () => disposer && disposer();
|
|
@@ -327,21 +395,6 @@ export const DVRToggle = ({player}) => {
|
|
|
327
395
|
);
|
|
328
396
|
};
|
|
329
397
|
|
|
330
|
-
export const Copy = async (value) => {
|
|
331
|
-
try {
|
|
332
|
-
value = (value || "").toString();
|
|
333
|
-
|
|
334
|
-
await navigator.clipboard.writeText(value);
|
|
335
|
-
} catch(error) {
|
|
336
|
-
const input = document.createElement("input");
|
|
337
|
-
|
|
338
|
-
input.value = value;
|
|
339
|
-
input.select();
|
|
340
|
-
input.setSelectionRange(0, 99999);
|
|
341
|
-
document.execCommand("copy");
|
|
342
|
-
}
|
|
343
|
-
};
|
|
344
|
-
|
|
345
398
|
export const CopyButton = ({label, value, className=""}) => {
|
|
346
399
|
const [copied, setCopied] = useState(false);
|
|
347
400
|
|
package/lib/ui/PlayerUI.jsx
CHANGED
|
@@ -15,11 +15,12 @@ import {
|
|
|
15
15
|
} from "./Observers.js";
|
|
16
16
|
import WebControls from "./WebControls.jsx";
|
|
17
17
|
import TicketForm from "./TicketForm.jsx";
|
|
18
|
-
import {Spinner, UserActionIndicator} from "./Components.jsx";
|
|
18
|
+
import {Copy, Spinner, SVG, UserActionIndicator} from "./Components.jsx";
|
|
19
19
|
import TVControls from "./TVControls.jsx";
|
|
20
20
|
import PlayerProfileForm from "./PlayerProfileForm.jsx";
|
|
21
21
|
import {ImageUrl, MergeDefaultParameters} from "./Common.js";
|
|
22
22
|
import {ChromecastIcon} from "../static/icons/Icons.js";
|
|
23
|
+
import * as Icons from "../static/icons/Icons";
|
|
23
24
|
|
|
24
25
|
const Poster = ({player}) => {
|
|
25
26
|
const [imageUrl, setImageUrl] = useState(undefined);
|
|
@@ -249,7 +250,18 @@ const PlayerUI = ({target, parameters, InitCallback, ErrorCallback, Unmount, Res
|
|
|
249
250
|
}
|
|
250
251
|
{
|
|
251
252
|
!errorMessage ? null :
|
|
252
|
-
<div className={PlayerStyles["error-message"]}>
|
|
253
|
+
<div className={PlayerStyles["error-message"]}>
|
|
254
|
+
<div className={PlayerStyles["error-message__message"]}>
|
|
255
|
+
{ errorMessage }
|
|
256
|
+
</div>
|
|
257
|
+
<button
|
|
258
|
+
className={PlayerStyles["error-message__copy-debug-button"]}
|
|
259
|
+
onClick={() => Copy(JSON.stringify(player.controls.GetDebugInfo(), null, 2))}
|
|
260
|
+
>
|
|
261
|
+
<SVG icon={Icons.InfoIcon} className={PlayerStyles["error-message__icon"]}/>
|
|
262
|
+
Copy Troubleshooting Info
|
|
263
|
+
</button>
|
|
264
|
+
</div>
|
|
253
265
|
}
|
|
254
266
|
{
|
|
255
267
|
!player ? null :
|