itube-modern-player 0.6.0 → 0.7.0
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 +27 -0
- package/dist/core/dom.d.ts +7 -0
- package/dist/core.cjs +3 -3
- package/dist/core.cjs.map +1 -1
- package/dist/core.js +508 -394
- package/dist/core.js.map +1 -1
- package/dist/features/heatmap.d.ts +3 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/itube-modern-player.iife.js +3 -3
- package/dist/itube-modern-player.iife.js.map +1 -1
- package/dist/{labels-ub9G1Vyq.cjs → labels-BOrrLImF.cjs} +2 -2
- package/dist/{labels-ub9G1Vyq.cjs.map → labels-BOrrLImF.cjs.map} +1 -1
- package/dist/{labels-DRuCG6N8.js → labels-CCjOCBKU.js} +8 -2
- package/dist/{labels-DRuCG6N8.js.map → labels-CCjOCBKU.js.map} +1 -1
- package/dist/lazy.cjs +1 -1
- package/dist/lazy.cjs.map +1 -1
- package/dist/lazy.js +43 -37
- package/dist/lazy.js.map +1 -1
- package/dist/locales.cjs +1 -1
- package/dist/locales.cjs.map +1 -1
- package/dist/locales.js +71 -11
- package/dist/locales.js.map +1 -1
- package/dist/player.d.ts +26 -2
- package/dist/style.css +1 -1
- package/dist/types.d.ts +42 -1
- package/dist/ui/menu.d.ts +2 -1
- package/dist/ui/overlays.d.ts +3 -1
- package/dist/ui/progress.d.ts +1 -1
- package/dist/vue.cjs +1 -1
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.d.ts +3 -1
- package/dist/vue.js +11 -9
- package/dist/vue.js.map +1 -1
- package/package.json +1 -1
package/dist/core.js
CHANGED
|
@@ -1,75 +1,79 @@
|
|
|
1
|
-
import { d as
|
|
1
|
+
import { d as Z } from "./labels-CCjOCBKU.js";
|
|
2
2
|
function l(o, t, e) {
|
|
3
3
|
const i = document.createElement(o);
|
|
4
4
|
if (t && (i.className = t), e)
|
|
5
5
|
for (const [s, n] of Object.entries(e)) i.setAttribute(s, n);
|
|
6
6
|
return i;
|
|
7
7
|
}
|
|
8
|
-
function
|
|
8
|
+
function T(o, t) {
|
|
9
9
|
if (o.textContent = "", typeof t == "object") {
|
|
10
10
|
"url" in t ? o.append(l("img", "imp-icon-img", { src: t.url, alt: "" })) : o.innerHTML = t.svg;
|
|
11
11
|
return;
|
|
12
12
|
}
|
|
13
13
|
/^\s*</.test(t) ? o.innerHTML = t : o.append(l("img", "imp-icon-img", { src: t, alt: "" }));
|
|
14
14
|
}
|
|
15
|
+
function S(o, t = "") {
|
|
16
|
+
const e = l("img", "imp-cover-img", { alt: t, decoding: "async" });
|
|
17
|
+
return e.src = o, e;
|
|
18
|
+
}
|
|
15
19
|
function g(o, t, e) {
|
|
16
20
|
const i = l("button", `imp-btn ${o}`, { type: "button", "aria-label": t, title: t });
|
|
17
|
-
return
|
|
21
|
+
return T(i, e), i;
|
|
18
22
|
}
|
|
19
|
-
function
|
|
23
|
+
function j(o, t) {
|
|
20
24
|
const e = l("div", `${t}__meta`);
|
|
21
25
|
return o.forEach((i, s) => {
|
|
22
26
|
s > 0 && e.append(document.createTextNode(" "));
|
|
23
27
|
const n = typeof i == "string" ? i : i.text, r = typeof i == "string" ? void 0 : i.icon, a = l("span", `${t}__meta-chunk`);
|
|
24
28
|
if (r) {
|
|
25
29
|
const h = l("span", `${t}__meta-icon`);
|
|
26
|
-
|
|
30
|
+
T(h, r), a.append(h);
|
|
27
31
|
}
|
|
28
32
|
a.append(document.createTextNode(n)), e.append(a);
|
|
29
33
|
}), e;
|
|
30
34
|
}
|
|
31
35
|
function I(o, t, e) {
|
|
32
|
-
|
|
36
|
+
T(o, t), e !== void 0 && (o.setAttribute("aria-label", e), o.setAttribute("title", e));
|
|
33
37
|
}
|
|
34
|
-
function
|
|
38
|
+
function x(o, t, e) {
|
|
35
39
|
return Math.min(e, Math.max(t, o));
|
|
36
40
|
}
|
|
37
|
-
function
|
|
41
|
+
function _(o) {
|
|
38
42
|
if (!Number.isFinite(o) || o < 0) return "0:00";
|
|
39
43
|
const t = Math.floor(o % 60), e = Math.floor(o / 60 % 60), i = Math.floor(o / 3600), s = i > 0 ? String(e).padStart(2, "0") : String(e), n = String(t).padStart(2, "0");
|
|
40
44
|
return i > 0 ? `${i}:${s}:${n}` : `${s}:${n}`;
|
|
41
45
|
}
|
|
42
|
-
function
|
|
46
|
+
function V(o) {
|
|
43
47
|
const t = o.trim().match(/^(?:(\d+):)?(\d{1,2}):(\d{2})(?:[.,](\d{1,3}))?$/);
|
|
44
48
|
if (!t) return null;
|
|
45
49
|
const e = t[1] ? Number(t[1]) : 0, i = Number(t[2]), s = Number(t[3]), n = t[4] ? Number(t[4].padEnd(3, "0")) : 0;
|
|
46
50
|
return e * 3600 + i * 60 + s + n / 1e3;
|
|
47
51
|
}
|
|
48
|
-
function
|
|
52
|
+
function K(o) {
|
|
49
53
|
const t = [], e = o.replace(/\r\n?/g, `
|
|
50
54
|
`).split(/\n\n+/);
|
|
51
55
|
for (const i of e) {
|
|
52
56
|
const s = i.split(`
|
|
53
|
-
`).filter((
|
|
57
|
+
`).filter((m) => m.trim() !== "");
|
|
54
58
|
if (s.length === 0) continue;
|
|
55
|
-
let n = s.findIndex((
|
|
59
|
+
let n = s.findIndex((m) => m.includes("-->"));
|
|
56
60
|
if (n === -1) continue;
|
|
57
|
-
const [r, a] = s[n].split("-->"), h =
|
|
61
|
+
const [r, a] = s[n].split("-->"), h = V(r), c = V((a ?? "").split(" ")[1] ?? a ?? "") ?? V(a ?? "");
|
|
58
62
|
if (h === null || c === null) continue;
|
|
59
|
-
const
|
|
63
|
+
const u = s.slice(n + 1).join(`
|
|
60
64
|
`).trim();
|
|
61
|
-
|
|
65
|
+
u && t.push({ start: h, end: c, text: u });
|
|
62
66
|
}
|
|
63
67
|
return t;
|
|
64
68
|
}
|
|
65
|
-
function
|
|
69
|
+
function it(o, t) {
|
|
66
70
|
try {
|
|
67
71
|
return new URL(o, new URL(t, window.location.href)).toString();
|
|
68
72
|
} catch {
|
|
69
73
|
return o;
|
|
70
74
|
}
|
|
71
75
|
}
|
|
72
|
-
class
|
|
76
|
+
class st {
|
|
73
77
|
constructor() {
|
|
74
78
|
this.listeners = /* @__PURE__ */ new Map();
|
|
75
79
|
}
|
|
@@ -101,56 +105,56 @@ class tt {
|
|
|
101
105
|
this.listeners.clear();
|
|
102
106
|
}
|
|
103
107
|
}
|
|
104
|
-
const
|
|
105
|
-
play:
|
|
106
|
-
pause:
|
|
107
|
-
replay:
|
|
108
|
-
bigPlay:
|
|
109
|
-
volumeHigh:
|
|
110
|
-
volumeLow:
|
|
111
|
-
volumeMute:
|
|
112
|
-
fullscreen:
|
|
113
|
-
fullscreenExit:
|
|
114
|
-
pip:
|
|
115
|
-
settings:
|
|
116
|
-
speed:
|
|
117
|
-
scenes:
|
|
118
|
-
shuffle:
|
|
119
|
-
repeat:
|
|
120
|
-
subtitles:
|
|
121
|
-
list:
|
|
122
|
-
next:
|
|
123
|
-
previous:
|
|
108
|
+
const y = (o, t = "0 0 24 24") => `<svg viewBox="${t}" fill="currentColor" aria-hidden="true" focusable="false">${o}</svg>`, nt = {
|
|
109
|
+
play: y('<path d="M8 5.14v13.72c0 .8.87 1.3 1.56.88l10.54-6.86a1.05 1.05 0 0 0 0-1.76L9.56 4.26C8.87 3.84 8 4.34 8 5.14Z"/>'),
|
|
110
|
+
pause: y('<rect x="6" y="5" width="4" height="14" rx="1"/><rect x="14" y="5" width="4" height="14" rx="1"/>'),
|
|
111
|
+
replay: y('<path d="M12 5V2.5L7.5 6 12 9.5V7a5 5 0 1 1-5 5H5a7 7 0 1 0 7-7Z"/>'),
|
|
112
|
+
bigPlay: y('<path d="M8 5.14v13.72c0 .8.87 1.3 1.56.88l10.54-6.86a1.05 1.05 0 0 0 0-1.76L9.56 4.26C8.87 3.84 8 4.34 8 5.14Z"/>'),
|
|
113
|
+
volumeHigh: y('<path d="M4 9v6h3.5L12 19.5v-15L7.5 9H4Z"/><path d="M14.5 8.6a4.5 4.5 0 0 1 0 6.8v-1.9a2.5 2.5 0 0 0 0-3v-1.9Z"/><path d="M14.5 5.2a8 8 0 0 1 0 13.6v-2a6 6 0 0 0 0-9.6v-2Z"/>'),
|
|
114
|
+
volumeLow: y('<path d="M4 9v6h3.5L12 19.5v-15L7.5 9H4Z"/><path d="M14.5 8.6a4.5 4.5 0 0 1 0 6.8v-1.9a2.5 2.5 0 0 0 0-3v-1.9Z"/>'),
|
|
115
|
+
volumeMute: y('<path d="M4 9v6h3.5L12 19.5v-15L7.5 9H4Z"/><path d="m15.3 9.3 1.4 1.4 1.4-1.4 1.4 1.4-1.4 1.4 1.4 1.4-1.4 1.4-1.4-1.4-1.4 1.4-1.4-1.4 1.4-1.4-1.4-1.4 1.4-1.4Z"/>'),
|
|
116
|
+
fullscreen: y('<path d="M5 5h5v2H7v3H5V5Zm9 0h5v5h-2V7h-3V5ZM5 14h2v3h3v2H5v-5Zm12 0h2v5h-5v-2h3v-3Z"/>'),
|
|
117
|
+
fullscreenExit: y('<path d="M10 10H5V8h3V5h2v5Zm4 0V5h2v3h3v2h-5Zm-4 4v5H8v-3H5v-2h5Zm4 0h5v2h-3v3h-2v-5Z"/>'),
|
|
118
|
+
pip: y('<path d="M3 5h18v14H3V5Zm2 2v10h14V7H5Z"/><rect x="12" y="11" width="6" height="4"/>'),
|
|
119
|
+
settings: y('<path d="M12 8.5A3.5 3.5 0 1 0 12 15.5 3.5 3.5 0 0 0 12 8.5Zm0 2a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3Z"/><path d="M10.3 2.8 9.9 5.1a7 7 0 0 0-1.5.86l-2.2-.8-1.7 3 1.8 1.5a7 7 0 0 0 0 1.7l-1.8 1.5 1.7 3 2.2-.8c.46.36.97.65 1.5.86l.4 2.3h3.4l.4-2.3a7 7 0 0 0 1.5-.86l2.2.8 1.7-3-1.8-1.5a7 7 0 0 0 0-1.7l1.8-1.5-1.7-3-2.2.8a7 7 0 0 0-1.5-.86l-.4-2.3h-3.4Zm1.7 5.7a3.5 3.5 0 1 1 0 7 3.5 3.5 0 0 1 0-7Z"/>'),
|
|
120
|
+
speed: y('<path d="M12 4a9 9 0 0 0-9 9 8.96 8.96 0 0 0 1.62 5.16l1.64-1.15A7 7 0 0 1 5 13a7 7 0 1 1 12.74 4.01l1.64 1.15A8.96 8.96 0 0 0 21 13a9 9 0 0 0-9-9Z"/><path d="m15.6 8.3-3.95 3.13a1.5 1.5 0 1 0 1.92 1.92L16.7 9.4a.78.78 0 0 0-1.1-1.1Z"/>'),
|
|
121
|
+
scenes: y('<path d="M3 5h18v14H3V5Zm2 2v10h3V7H5Zm5 0v10h9V7h-9Zm-5 3h3v1H5v-1Zm0 3h3v1H5v-1Z"/>'),
|
|
122
|
+
shuffle: y('<path d="M4 6h2.6c1.5 0 2.9.7 3.8 1.9l4.1 5.4a2.75 2.75 0 0 0 2.2 1.1H19l-1.8-1.8 1.4-1.4 4.2 4.2-4.2 4.2-1.4-1.4L19 16.4h-2.3a4.75 4.75 0 0 1-3.8-1.9L8.8 9.1A2.75 2.75 0 0 0 6.6 8H4V6Z"/><path d="M19 7.6h-2.3c-.86 0-1.67.41-2.18 1.1l-.93 1.23-1.25-1.65.58-.77A4.75 4.75 0 0 1 16.7 5.6H19L17.2 3.8l1.4-1.4 4.2 4.2-4.2 4.2-1.4-1.4L19 7.6Z" transform="translate(0 1.2)"/>'),
|
|
123
|
+
repeat: y('<path d="M7 7h10v2.5L21 6l-4-3.5V5H5v6h2V7Zm10 10H7v-2.5L3 18l4 3.5V19h12v-6h-2v4Z"/>'),
|
|
124
|
+
subtitles: y('<path d="M3 5h18v14H3V5Zm2 2v10h14V7H5Zm2 3h6v2H7v-2Zm8 0h2v2h-2v-2ZM7 14h2v2H7v-2Zm4 0h6v2h-6v-2Z"/>'),
|
|
125
|
+
list: y('<path d="M4 6h2v2H4V6Zm4 0h12v2H8V6ZM4 11h2v2H4v-2Zm4 0h12v2H8v-2ZM4 16h2v2H4v-2Zm4 0h12v2H8v-2Z"/>'),
|
|
126
|
+
next: y('<path d="M6 5.5v13c0 .77.84 1.25 1.5.85l9-6.5a1 1 0 0 0 0-1.7l-9-6.5c-.66-.4-1.5.08-1.5.85Z"/><rect x="17" y="5" width="2.5" height="14" rx="1"/>'),
|
|
127
|
+
previous: y('<path d="M18 5.5v13c0 .77-.84 1.25-1.5.85l-9-6.5a1 1 0 0 1 0-1.7l9-6.5c.66-.4 1.5.08 1.5.85Z"/><rect x="4.5" y="5" width="2.5" height="14" rx="1"/>'),
|
|
124
128
|
// Thin circular-arrow ("rotate") icons — open center so the step number reads
|
|
125
129
|
// clearly inside the ring (matches the reference skip ±N look).
|
|
126
130
|
seekForward: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><polyline points="23 4 23 10 17 10"/><path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"/></svg>',
|
|
127
131
|
seekBack: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><polyline points="1 4 1 10 7 10"/><path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"/></svg>',
|
|
128
|
-
like:
|
|
129
|
-
dislike:
|
|
130
|
-
addTo:
|
|
131
|
-
share:
|
|
132
|
-
report:
|
|
133
|
-
more:
|
|
134
|
-
close:
|
|
132
|
+
like: y('<path d="M9 21H5a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h4v11Zm2 0h7.1a2 2 0 0 0 2-1.6l1.3-7a2 2 0 0 0-2-2.4H14V5.5A2.5 2.5 0 0 0 11.5 3l-.5.1V10h-.9L11 21Z"/>'),
|
|
133
|
+
dislike: y('<path d="M15 3h4a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2h-4V3Zm-2 0H5.9a2 2 0 0 0-2 1.6l-1.3 7a2 2 0 0 0 2 2.4H10v4.5A2.5 2.5 0 0 0 12.5 21l.5-.1V14h.9L13 3Z"/>'),
|
|
134
|
+
addTo: y('<path d="M4 6h12v2H4V6Zm0 4h12v2H4v-2Zm0 4h8v2H4v-2Zm14 0v-4h2v4h4v2h-4v4h-2v-4h-4v-2h4Z"/>'),
|
|
135
|
+
share: y('<path d="M18 8a3 3 0 1 0-2.83-4H15a3 3 0 0 0 .14 1.06L8.4 8.94a3 3 0 1 0 0 6.12l6.74 3.88A3 3 0 1 0 16 16.6l-6.74-3.88a3.03 3.03 0 0 0 0-1.44L16 7.4c.55.38 1.24.6 2 .6Z"/>'),
|
|
136
|
+
report: y('<path d="M5 3h2v18H5V3Zm4 1h10l-2.5 4L19 12H9V4Z"/>'),
|
|
137
|
+
more: y('<circle cx="12" cy="5" r="2"/><circle cx="12" cy="12" r="2"/><circle cx="12" cy="19" r="2"/>'),
|
|
138
|
+
close: y('<path d="m6.4 5 5.6 5.6L17.6 5 19 6.4 13.4 12l5.6 5.6-1.4 1.4-5.6-5.6L6.4 19 5 17.6 10.6 12 5 6.4 6.4 5Z"/>'),
|
|
135
139
|
// Generic "uploaded by a user" glyph (head + shoulders) for preview meta.
|
|
136
|
-
user:
|
|
140
|
+
user: y('<path d="M12 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8Zm0 2c-3.6 0-8 1.8-8 4.4V21h16v-2.6c0-2.6-4.4-4.4-8-4.4Z"/>'),
|
|
137
141
|
// Generic "channel" glyph (play badge) for preview meta when a channel is set.
|
|
138
|
-
channel:
|
|
139
|
-
},
|
|
140
|
-
function
|
|
141
|
-
|
|
142
|
+
channel: y('<path d="M3 5h18a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1Zm7 3.5v7l6-3.5-6-3.5Z"/>')
|
|
143
|
+
}, q = { en: Z };
|
|
144
|
+
function It(o, t) {
|
|
145
|
+
q[o] = t;
|
|
142
146
|
}
|
|
143
|
-
function
|
|
147
|
+
function $t(o) {
|
|
144
148
|
for (const [t, e] of Object.entries(o))
|
|
145
|
-
e && (
|
|
149
|
+
e && (q[t] = e);
|
|
146
150
|
}
|
|
147
|
-
function
|
|
148
|
-
return o &&
|
|
151
|
+
function rt(o) {
|
|
152
|
+
return o && q[o] || Z;
|
|
149
153
|
}
|
|
150
|
-
function
|
|
151
|
-
return Object.keys(
|
|
154
|
+
function qt() {
|
|
155
|
+
return Object.keys(q);
|
|
152
156
|
}
|
|
153
|
-
function
|
|
157
|
+
function ot(o) {
|
|
154
158
|
const t = [0.06, 0.24, 0.4, 0.24, 0.06], e = o.length;
|
|
155
159
|
return o.map(
|
|
156
160
|
(i, s) => t.reduce((n, r, a) => {
|
|
@@ -159,19 +163,19 @@ function st(o) {
|
|
|
159
163
|
}, 0)
|
|
160
164
|
);
|
|
161
165
|
}
|
|
162
|
-
function
|
|
166
|
+
function lt(o, t) {
|
|
163
167
|
if (o.length === 0) return 0;
|
|
164
168
|
const e = Math.min(o.length - 1, Math.max(0, Math.round((o.length - 1) * t)));
|
|
165
169
|
return o[e];
|
|
166
170
|
}
|
|
167
|
-
function
|
|
171
|
+
function X(o, t) {
|
|
168
172
|
if (o.length === 0 || o.every((n) => n <= 0)) return [];
|
|
169
|
-
const e =
|
|
173
|
+
const e = ot(o), i = t === "retention" ? lt([...e].sort((n, r) => n - r), 0.95) : Math.max(...e);
|
|
170
174
|
if (i <= 0) return [];
|
|
171
175
|
const s = 0.08;
|
|
172
176
|
return e.map((n) => s + (1 - s) * Math.min(1, Math.max(0, n / i)));
|
|
173
177
|
}
|
|
174
|
-
function
|
|
178
|
+
function at(o, t, e = 100) {
|
|
175
179
|
if (o.length === 0 || !Number.isFinite(t) || t <= 0) return [];
|
|
176
180
|
const i = new Array(e).fill(0);
|
|
177
181
|
let s = !1;
|
|
@@ -180,27 +184,35 @@ function rt(o, t, e = 100) {
|
|
|
180
184
|
const r = Math.max(0, n.value);
|
|
181
185
|
r !== 0 && (i[Math.min(e - 1, Math.floor(n.time / t * e))] += r, s = !0);
|
|
182
186
|
}
|
|
183
|
-
return s ?
|
|
187
|
+
return s ? X(i, "peaks") : [];
|
|
184
188
|
}
|
|
185
|
-
function
|
|
186
|
-
|
|
187
|
-
|
|
189
|
+
function ht(o, t = "peaks", e = 200) {
|
|
190
|
+
let i = o.map((s) => Number.isFinite(s) ? Math.max(0, s) : 0);
|
|
191
|
+
if (i.length > e) {
|
|
192
|
+
const s = new Array(e).fill(0), n = new Array(e).fill(0);
|
|
193
|
+
for (let r = 0; r < i.length; r++) {
|
|
194
|
+
const a = Math.min(e - 1, Math.floor(r / i.length * e));
|
|
195
|
+
s[a] += i[r], n[a]++;
|
|
196
|
+
}
|
|
197
|
+
i = s.map((r, a) => n[a] > 0 ? r / n[a] : 0);
|
|
198
|
+
}
|
|
199
|
+
return X(i, t);
|
|
188
200
|
}
|
|
189
|
-
function
|
|
201
|
+
function ct(o, t = 1, e = 1e3, i = 100) {
|
|
190
202
|
const s = o.length;
|
|
191
203
|
if (s === 0) return "";
|
|
192
|
-
const n = e / (s - 1 || 1), r = Math.max(0, t) / 6, a = (
|
|
193
|
-
const
|
|
194
|
-
return [
|
|
204
|
+
const n = e / (s - 1 || 1), r = Math.max(0, t) / 6, a = (u) => {
|
|
205
|
+
const m = Math.min(s - 1, Math.max(0, u));
|
|
206
|
+
return [m * n, i - o[m] * i];
|
|
195
207
|
}, [, h] = a(0);
|
|
196
208
|
let c = `M 0 ${i} L 0 ${h.toFixed(1)}`;
|
|
197
|
-
for (let
|
|
198
|
-
const [
|
|
199
|
-
c += ` C ${
|
|
209
|
+
for (let u = 0; u < s - 1; u++) {
|
|
210
|
+
const [m, p] = a(u - 1), [v, f] = a(u), [b, d] = a(u + 1), [k, C] = a(u + 2), A = v + (b - m) * r, F = Math.min(i, Math.max(0, f + (d - p) * r)), P = b - (k - v) * r, R = Math.min(i, Math.max(0, d - (C - f) * r));
|
|
211
|
+
c += ` C ${A.toFixed(1)} ${F.toFixed(1)} ${P.toFixed(1)} ${R.toFixed(1)} ${b.toFixed(1)} ${d.toFixed(1)}`;
|
|
200
212
|
}
|
|
201
213
|
return c += ` L ${e} ${i} Z`, c;
|
|
202
214
|
}
|
|
203
|
-
async function
|
|
215
|
+
async function dt(o, t) {
|
|
204
216
|
if (o.src)
|
|
205
217
|
return {
|
|
206
218
|
roll: o.roll,
|
|
@@ -210,16 +222,16 @@ async function at(o, t) {
|
|
|
210
222
|
tracking: {}
|
|
211
223
|
};
|
|
212
224
|
if (!o.vastTag) throw new Error('Ad roll has neither "vastTag" nor "src"');
|
|
213
|
-
return
|
|
225
|
+
return J(o, o.vastTag, t, 0, { impressions: [], tracking: {} });
|
|
214
226
|
}
|
|
215
|
-
async function
|
|
227
|
+
async function J(o, t, e, i, s) {
|
|
216
228
|
if (i > e.maxWrapperDepth) throw new Error("VAST wrapper depth limit exceeded");
|
|
217
229
|
const n = new AbortController(), r = setTimeout(() => n.abort(), e.requestTimeout);
|
|
218
230
|
let a;
|
|
219
231
|
try {
|
|
220
|
-
const
|
|
221
|
-
if (!
|
|
222
|
-
a = await
|
|
232
|
+
const f = await fetch(t, { signal: n.signal, credentials: "omit" });
|
|
233
|
+
if (!f.ok) throw new Error(`VAST request failed (${f.status})`);
|
|
234
|
+
a = await f.text();
|
|
223
235
|
} finally {
|
|
224
236
|
clearTimeout(r);
|
|
225
237
|
}
|
|
@@ -227,52 +239,52 @@ async function X(o, t, e, i, s) {
|
|
|
227
239
|
if (h.querySelector("parsererror")) throw new Error("VAST response is not valid XML");
|
|
228
240
|
const c = h.querySelector("VAST > Ad");
|
|
229
241
|
if (!c) throw new Error("VAST response contains no ads");
|
|
230
|
-
|
|
231
|
-
const
|
|
232
|
-
if (
|
|
233
|
-
const
|
|
234
|
-
if (!
|
|
235
|
-
return
|
|
236
|
-
}
|
|
237
|
-
const
|
|
238
|
-
if (!
|
|
239
|
-
const
|
|
240
|
-
if (!
|
|
241
|
-
const v =
|
|
242
|
+
ut(c, s);
|
|
243
|
+
const u = c.querySelector(":scope > Wrapper");
|
|
244
|
+
if (u) {
|
|
245
|
+
const f = L(u.querySelector("VASTAdTagURI"));
|
|
246
|
+
if (!f) throw new Error("VAST wrapper without VASTAdTagURI");
|
|
247
|
+
return J(o, f, e, i + 1, s);
|
|
248
|
+
}
|
|
249
|
+
const m = c.querySelector(":scope > InLine");
|
|
250
|
+
if (!m) throw new Error("VAST ad has neither InLine nor Wrapper");
|
|
251
|
+
const p = m.querySelector("Creatives > Creative > Linear");
|
|
252
|
+
if (!p) throw new Error("VAST ad has no Linear creative");
|
|
253
|
+
const v = pt(p);
|
|
242
254
|
if (!v) throw new Error("VAST ad has no playable MediaFile");
|
|
243
255
|
return {
|
|
244
256
|
roll: o.roll,
|
|
245
257
|
mediaUrl: v.url,
|
|
246
258
|
mediaType: v.type,
|
|
247
|
-
clickThrough:
|
|
248
|
-
duration:
|
|
249
|
-
skipOffset:
|
|
250
|
-
|
|
251
|
-
|
|
259
|
+
clickThrough: L(p.querySelector("VideoClicks > ClickThrough")) ?? o.clickUrl,
|
|
260
|
+
duration: H(L(p.querySelector(":scope > Duration"))),
|
|
261
|
+
skipOffset: mt(
|
|
262
|
+
p.getAttribute("skipoffset"),
|
|
263
|
+
H(L(p.querySelector(":scope > Duration")))
|
|
252
264
|
),
|
|
253
265
|
impressions: s.impressions,
|
|
254
266
|
tracking: s.tracking,
|
|
255
|
-
adTitle:
|
|
267
|
+
adTitle: L(m.querySelector(":scope > AdTitle")) ?? void 0
|
|
256
268
|
};
|
|
257
269
|
}
|
|
258
|
-
function
|
|
270
|
+
function ut(o, t) {
|
|
259
271
|
var e, i;
|
|
260
272
|
for (const s of o.querySelectorAll("Impression")) {
|
|
261
|
-
const n =
|
|
273
|
+
const n = L(s);
|
|
262
274
|
n && t.impressions.push(n);
|
|
263
275
|
}
|
|
264
276
|
for (const s of o.querySelectorAll("Linear > TrackingEvents > Tracking")) {
|
|
265
|
-
const n = s.getAttribute("event"), r =
|
|
277
|
+
const n = s.getAttribute("event"), r = L(s);
|
|
266
278
|
!n || !r || ["start", "firstQuartile", "midpoint", "thirdQuartile", "complete", "skip", "pause", "resume"].includes(n) && ((e = t.tracking)[n] ?? (e[n] = [])).push(r);
|
|
267
279
|
}
|
|
268
280
|
for (const s of o.querySelectorAll("Linear > VideoClicks > ClickTracking")) {
|
|
269
|
-
const n =
|
|
281
|
+
const n = L(s);
|
|
270
282
|
n && ((i = t.tracking).click ?? (i.click = [])).push(n);
|
|
271
283
|
}
|
|
272
284
|
}
|
|
273
|
-
function
|
|
285
|
+
function pt(o) {
|
|
274
286
|
const e = [...o.querySelectorAll("MediaFiles > MediaFile")].map((r) => ({
|
|
275
|
-
url:
|
|
287
|
+
url: L(r) ?? "",
|
|
276
288
|
type: r.getAttribute("type") ?? void 0,
|
|
277
289
|
delivery: r.getAttribute("delivery") ?? "",
|
|
278
290
|
bitrate: Number(r.getAttribute("bitrate") ?? 0),
|
|
@@ -285,16 +297,16 @@ function ct(o) {
|
|
|
285
297
|
const i = e.filter((r) => r.delivery !== "streaming"), s = i.length > 0 ? i : e, n = s[Math.floor(s.length / 2)];
|
|
286
298
|
return { url: n.url, type: n.type };
|
|
287
299
|
}
|
|
288
|
-
function
|
|
300
|
+
function H(o) {
|
|
289
301
|
if (!o) return;
|
|
290
302
|
const t = o.trim().match(/^(?:(\d+):)?(\d{1,2}):(\d{2})(?:\.(\d{1,3}))?$/);
|
|
291
303
|
if (t)
|
|
292
304
|
return (t[1] ? Number(t[1]) * 3600 : 0) + Number(t[2]) * 60 + Number(t[3]) + (t[4] ? Number(t[4].padEnd(3, "0")) / 1e3 : 0);
|
|
293
305
|
}
|
|
294
|
-
function
|
|
306
|
+
function mt(o, t) {
|
|
295
307
|
if (!o) return;
|
|
296
308
|
const e = o.trim().match(/^(\d+(?:\.\d+)?)%$/);
|
|
297
|
-
return e ? t !== void 0 ? Number(e[1]) / 100 * t : void 0 :
|
|
309
|
+
return e ? t !== void 0 ? Number(e[1]) / 100 * t : void 0 : H(o);
|
|
298
310
|
}
|
|
299
311
|
function $(o) {
|
|
300
312
|
if (o)
|
|
@@ -304,10 +316,10 @@ function $(o) {
|
|
|
304
316
|
} catch {
|
|
305
317
|
}
|
|
306
318
|
}
|
|
307
|
-
function
|
|
319
|
+
function L(o) {
|
|
308
320
|
return o?.textContent?.trim().replace(/^<!\[CDATA\[|\]\]>$/g, "").trim() || null;
|
|
309
321
|
}
|
|
310
|
-
class
|
|
322
|
+
class vt {
|
|
311
323
|
constructor(t, e) {
|
|
312
324
|
this.host = t, this.playedRolls = /* @__PURE__ */ new Set(), this.sourcesSeen = 0, this.activeBreak = null, this.layer = null, this.adVideo = null, this.destroyed = !1, this.opts = {
|
|
313
325
|
skipDelay: 5,
|
|
@@ -374,7 +386,7 @@ class ut {
|
|
|
374
386
|
for (const n of t) {
|
|
375
387
|
this.playedRolls.add(n);
|
|
376
388
|
try {
|
|
377
|
-
const r = await
|
|
389
|
+
const r = await dt(n, this.opts);
|
|
378
390
|
await this.playAd(r);
|
|
379
391
|
} catch (r) {
|
|
380
392
|
const a = r instanceof Error ? r : new Error(String(r));
|
|
@@ -393,68 +405,68 @@ class ut {
|
|
|
393
405
|
return new Promise((e) => {
|
|
394
406
|
const { labels: i } = this.host, s = l("div", "imp-ad"), n = this.ensureAdVideo(), r = new AbortController(), a = r.signal;
|
|
395
407
|
n.src = t.mediaUrl, n.muted = this.host.contentVideo.muted, n.volume = this.host.contentVideo.volume;
|
|
396
|
-
const h = l("div", "imp-spinner imp-ad__spinner"), c = l("div", "imp-ad__hud"),
|
|
397
|
-
|
|
398
|
-
const
|
|
399
|
-
c.append(
|
|
400
|
-
const
|
|
408
|
+
const h = l("div", "imp-spinner imp-ad__spinner"), c = l("div", "imp-ad__hud"), u = l("span", "imp-ad__badge");
|
|
409
|
+
u.textContent = t.adTitle ? `${i.adLabel} · ${t.adTitle}` : i.adLabel;
|
|
410
|
+
const m = l("span", "imp-ad__countdown");
|
|
411
|
+
c.append(u, m);
|
|
412
|
+
const p = l("div", "imp-ad__actions");
|
|
401
413
|
let v = null;
|
|
402
|
-
t.clickThrough && (v = l("button", "imp-ad__visit", { type: "button" }), v.textContent = i.visitAdvertiser,
|
|
403
|
-
const
|
|
404
|
-
|
|
405
|
-
const
|
|
406
|
-
d.has(
|
|
414
|
+
t.clickThrough && (v = l("button", "imp-ad__visit", { type: "button" }), v.textContent = i.visitAdvertiser, p.append(v));
|
|
415
|
+
const f = l("button", "imp-ad__skip", { type: "button" });
|
|
416
|
+
f.hidden = !0, p.append(f), s.append(n, h, c, p), this.host.container.append(s), this.layer = s;
|
|
417
|
+
const b = t.skipOffset ?? this.opts.skipDelay, d = /* @__PURE__ */ new Set(), k = (w) => {
|
|
418
|
+
d.has(w) || (d.add(w), $(t.tracking[w]));
|
|
407
419
|
};
|
|
408
|
-
let
|
|
409
|
-
const
|
|
420
|
+
let C = Date.now(), A = -1;
|
|
421
|
+
const F = setInterval(() => {
|
|
410
422
|
if (n.paused) {
|
|
411
|
-
|
|
423
|
+
C = Date.now();
|
|
412
424
|
return;
|
|
413
425
|
}
|
|
414
|
-
if (n.currentTime !==
|
|
415
|
-
|
|
426
|
+
if (n.currentTime !== A) {
|
|
427
|
+
A = n.currentTime, C = Date.now();
|
|
416
428
|
return;
|
|
417
429
|
}
|
|
418
|
-
Date.now() -
|
|
430
|
+
Date.now() - C >= this.opts.mediaTimeout && (this.host.emitter.emit("aderror", {
|
|
419
431
|
roll: { roll: t.roll },
|
|
420
432
|
error: new Error(`Ad media stalled for ${this.opts.mediaTimeout} ms — skipping`)
|
|
421
|
-
}),
|
|
422
|
-
}, 500),
|
|
423
|
-
clearInterval(
|
|
424
|
-
},
|
|
425
|
-
|
|
433
|
+
}), P());
|
|
434
|
+
}, 500), P = () => {
|
|
435
|
+
clearInterval(F), r.abort(), n.pause(), n.removeAttribute("src"), n.load(), s.remove(), this.layer = null, e();
|
|
436
|
+
}, R = (w) => {
|
|
437
|
+
w ? (k("skip"), this.host.emitter.emit("adskip", { ad: t })) : k("complete"), this.host.emitter.emit("adend", { ad: t }), P();
|
|
426
438
|
};
|
|
427
439
|
n.addEventListener("playing", () => {
|
|
428
|
-
$(t.impressions),
|
|
440
|
+
$(t.impressions), k("start"), this.host.emitter.emit("adstart", { ad: t });
|
|
429
441
|
}, { once: !0, signal: a }), n.addEventListener("playing", () => {
|
|
430
442
|
h.hidden = !0;
|
|
431
443
|
}, { signal: a }), n.addEventListener("waiting", () => {
|
|
432
444
|
h.hidden = !1;
|
|
433
445
|
}, { signal: a }), n.addEventListener("timeupdate", () => {
|
|
434
|
-
const
|
|
435
|
-
if (Number.isFinite(
|
|
436
|
-
const
|
|
437
|
-
|
|
446
|
+
const w = n.currentTime, B = n.duration;
|
|
447
|
+
if (Number.isFinite(B) && B > 0 && (m.textContent = _(Math.max(0, B - w)), w / B >= 0.25 && k("firstQuartile"), w / B >= 0.5 && k("midpoint"), w / B >= 0.75 && k("thirdQuartile")), b >= 0) {
|
|
448
|
+
const z = Math.ceil(b - w);
|
|
449
|
+
z > 0 ? (f.hidden = !1, f.disabled = !0, f.textContent = `${i.skipAdIn} ${z}`) : (f.hidden = !1, f.disabled = !1, f.textContent = i.skipAd);
|
|
438
450
|
}
|
|
439
|
-
}, { signal: a }), n.addEventListener("ended", () =>
|
|
451
|
+
}, { signal: a }), n.addEventListener("ended", () => R(!1), { signal: a }), n.addEventListener("error", () => {
|
|
440
452
|
this.host.emitter.emit("aderror", {
|
|
441
453
|
roll: { roll: t.roll },
|
|
442
454
|
error: new Error("Ad media failed to play")
|
|
443
|
-
}),
|
|
444
|
-
}, { signal: a }),
|
|
445
|
-
const
|
|
446
|
-
t.clickThrough && (
|
|
455
|
+
}), P();
|
|
456
|
+
}, { signal: a }), f.addEventListener("click", () => R(!0));
|
|
457
|
+
const G = () => {
|
|
458
|
+
t.clickThrough && (k("click"), this.host.emitter.emit("adclick", { ad: t }), window.open(t.clickThrough, "_blank", "noopener"), n.pause());
|
|
447
459
|
};
|
|
448
|
-
n.addEventListener("click",
|
|
449
|
-
let
|
|
460
|
+
n.addEventListener("click", G, { signal: a }), v?.addEventListener("click", G);
|
|
461
|
+
let W = !1, N = !1;
|
|
450
462
|
n.addEventListener("playing", () => {
|
|
451
|
-
|
|
463
|
+
W = !0;
|
|
452
464
|
}, { once: !0, signal: a }), n.addEventListener("pause", () => {
|
|
453
|
-
n.ended || !s.isConnected || (s.classList.add("imp-ad--paused"),
|
|
465
|
+
n.ended || !s.isConnected || (s.classList.add("imp-ad--paused"), W && !N && (N = !0, $(t.tracking.pause), this.host.emitter.emit("adpause", { ad: t })));
|
|
454
466
|
}, { signal: a }), n.addEventListener("play", () => {
|
|
455
|
-
s.classList.remove("imp-ad--paused"),
|
|
456
|
-
}, { signal: a }), s.addEventListener("click", (
|
|
457
|
-
(
|
|
467
|
+
s.classList.remove("imp-ad--paused"), N && (N = !1, $(t.tracking.resume), this.host.emitter.emit("adresume", { ad: t }));
|
|
468
|
+
}, { signal: a }), s.addEventListener("click", (w) => {
|
|
469
|
+
(w.target === s || s.classList.contains("imp-ad--paused")) && n.paused && n.play().catch(() => {
|
|
458
470
|
});
|
|
459
471
|
}), n.play().catch(() => {
|
|
460
472
|
s.classList.add("imp-ad--paused");
|
|
@@ -469,7 +481,7 @@ class ut {
|
|
|
469
481
|
this.destroyed = !0, this.adVideo?.pause(), this.layer?.remove(), this.layer = null, this.adVideo = null;
|
|
470
482
|
}
|
|
471
483
|
}
|
|
472
|
-
function
|
|
484
|
+
function Q(o, t) {
|
|
473
485
|
const e = [...o].sort((s, n) => s.start - n.start), i = [];
|
|
474
486
|
for (let s = 0; s < e.length; s++) {
|
|
475
487
|
const n = Math.max(0, e[s].start);
|
|
@@ -479,41 +491,40 @@ function z(o, t) {
|
|
|
479
491
|
}
|
|
480
492
|
return i;
|
|
481
493
|
}
|
|
482
|
-
async function
|
|
494
|
+
async function ft(o) {
|
|
483
495
|
const t = await fetch(o);
|
|
484
496
|
if (!t.ok) throw new Error(`Failed to load chapters VTT (${t.status})`);
|
|
485
497
|
const e = await t.text();
|
|
486
|
-
return
|
|
498
|
+
return K(e).map((i) => ({ start: i.start, end: i.end, title: i.text }));
|
|
487
499
|
}
|
|
488
|
-
function
|
|
500
|
+
function Y(o, t) {
|
|
489
501
|
for (const e of o)
|
|
490
502
|
if (t >= e.start && t < e.end) return e;
|
|
491
503
|
return null;
|
|
492
504
|
}
|
|
493
|
-
function
|
|
505
|
+
function yt(o, t) {
|
|
494
506
|
return t ? /application\/(x-mpegurl|vnd\.apple\.mpegurl)/i.test(t) : /\.m3u8(\?|#|$)/i.test(o);
|
|
495
507
|
}
|
|
496
|
-
let
|
|
497
|
-
async function
|
|
498
|
-
if (
|
|
508
|
+
let E;
|
|
509
|
+
async function gt() {
|
|
510
|
+
if (E !== void 0) return E;
|
|
499
511
|
const o = globalThis.Hls;
|
|
500
512
|
if (o)
|
|
501
|
-
return
|
|
513
|
+
return E = o, E;
|
|
502
514
|
try {
|
|
503
|
-
|
|
515
|
+
return E = (await import("hls.js/light")).default, E;
|
|
504
516
|
} catch {
|
|
505
|
-
|
|
517
|
+
return null;
|
|
506
518
|
}
|
|
507
|
-
return L;
|
|
508
519
|
}
|
|
509
|
-
async function
|
|
510
|
-
if (
|
|
511
|
-
const s = o.canPlayType("application/vnd.apple.mpegurl"), n = s ? null : await
|
|
512
|
-
return n && n.isSupported() ?
|
|
520
|
+
async function bt(o, t, e, i) {
|
|
521
|
+
if (yt(t, e)) {
|
|
522
|
+
const s = o.canPlayType("application/vnd.apple.mpegurl"), n = s ? null : await gt();
|
|
523
|
+
return n && n.isSupported() ? kt(n, o, t, i) : s ? (o.src = t, O(o)) : (i.onError("HLS is not supported in this browser and hls.js could not be loaded."), O(o));
|
|
513
524
|
}
|
|
514
|
-
return o.src = t,
|
|
525
|
+
return o.src = t, O(o);
|
|
515
526
|
}
|
|
516
|
-
function
|
|
527
|
+
function O(o) {
|
|
517
528
|
return {
|
|
518
529
|
kind: "native",
|
|
519
530
|
levels: [],
|
|
@@ -525,52 +536,54 @@ function q(o) {
|
|
|
525
536
|
}
|
|
526
537
|
};
|
|
527
538
|
}
|
|
528
|
-
function
|
|
539
|
+
function kt(o, t, e, i) {
|
|
529
540
|
const s = new o({ enableWorker: !0 }), n = {
|
|
530
541
|
kind: "hls",
|
|
531
542
|
levels: [],
|
|
532
543
|
selected: -1,
|
|
533
|
-
setLevel(
|
|
534
|
-
n.selected =
|
|
544
|
+
setLevel(c) {
|
|
545
|
+
n.selected = c, s.currentLevel = c;
|
|
535
546
|
},
|
|
536
547
|
destroy() {
|
|
537
548
|
s.destroy(), t.removeAttribute("src"), t.load();
|
|
538
549
|
}
|
|
539
550
|
};
|
|
540
551
|
s.on(o.Events.MANIFEST_PARSED, () => {
|
|
541
|
-
n.levels = s.levels.map((
|
|
542
|
-
index:
|
|
543
|
-
label:
|
|
552
|
+
n.levels = s.levels.map((c, u) => ({
|
|
553
|
+
index: u,
|
|
554
|
+
label: c.height ? `${c.height}p` : `${Math.round(c.bitrate / 1e3)} kbps`
|
|
544
555
|
})).reverse(), i.onLevels(n.levels);
|
|
545
|
-
}), s.on(o.Events.LEVEL_SWITCHED, (
|
|
546
|
-
const
|
|
547
|
-
|
|
556
|
+
}), s.on(o.Events.LEVEL_SWITCHED, (c, u) => {
|
|
557
|
+
const m = s.levels[u.level];
|
|
558
|
+
m && i.onLevelSwitch(m.height ? `${m.height}p` : `${Math.round(m.bitrate / 1e3)} kbps`);
|
|
548
559
|
});
|
|
549
|
-
let r = 0, a = !1;
|
|
550
|
-
return s.on(o.Events.
|
|
551
|
-
|
|
552
|
-
|
|
560
|
+
let r = 0, a = 0, h = !1;
|
|
561
|
+
return s.on(o.Events.FRAG_BUFFERED, () => {
|
|
562
|
+
a = 0;
|
|
563
|
+
}), s.on(o.Events.ERROR, (c, u) => {
|
|
564
|
+
if (u.fatal)
|
|
565
|
+
switch (u.type) {
|
|
553
566
|
case o.ErrorTypes.NETWORK_ERROR:
|
|
554
|
-
s.startLoad();
|
|
567
|
+
a < 3 ? (a++, s.startLoad()) : (i.onError(`HLS network error: ${u.details}`, u), s.destroy());
|
|
555
568
|
break;
|
|
556
569
|
case o.ErrorTypes.MEDIA_ERROR:
|
|
557
|
-
r < 3 ? (r++, s.recoverMediaError()) : (i.onError(`HLS media error: ${
|
|
570
|
+
r < 3 ? (r++, s.recoverMediaError()) : (i.onError(`HLS media error: ${u.details}`, u), s.destroy());
|
|
558
571
|
break;
|
|
559
572
|
default:
|
|
560
|
-
if (
|
|
561
|
-
i.onError(`HLS fatal error: ${
|
|
573
|
+
if (h)
|
|
574
|
+
i.onError(`HLS fatal error: ${u.details}`, u), s.destroy();
|
|
562
575
|
else {
|
|
563
|
-
|
|
576
|
+
h = !0;
|
|
564
577
|
try {
|
|
565
578
|
s.loadSource(e), s.startLoad();
|
|
566
579
|
} catch {
|
|
567
|
-
i.onError(`HLS fatal error: ${
|
|
580
|
+
i.onError(`HLS fatal error: ${u.details}`, u), s.destroy();
|
|
568
581
|
}
|
|
569
582
|
}
|
|
570
583
|
}
|
|
571
584
|
}), s.loadSource(e), s.attachMedia(t), n;
|
|
572
585
|
}
|
|
573
|
-
class
|
|
586
|
+
class D {
|
|
574
587
|
constructor(t) {
|
|
575
588
|
this.cues = t;
|
|
576
589
|
}
|
|
@@ -578,17 +591,17 @@ class Z {
|
|
|
578
591
|
const e = await fetch(t);
|
|
579
592
|
if (!e.ok) throw new Error(`Failed to load thumbnails VTT (${e.status})`);
|
|
580
593
|
const i = await e.text(), s = [];
|
|
581
|
-
for (const n of
|
|
594
|
+
for (const n of K(i)) {
|
|
582
595
|
const [r, a] = n.text.trim().split("#");
|
|
583
596
|
if (!r) continue;
|
|
584
597
|
const h = {
|
|
585
598
|
start: n.start,
|
|
586
599
|
end: n.end,
|
|
587
|
-
src:
|
|
600
|
+
src: it(r, t)
|
|
588
601
|
}, c = a?.match(/xywh=(\d+),(\d+),(\d+),(\d+)/);
|
|
589
602
|
c && (h.xywh = { x: Number(c[1]), y: Number(c[2]), w: Number(c[3]), h: Number(c[4]) }), s.push(h);
|
|
590
603
|
}
|
|
591
|
-
return s.sort((n, r) => n.start - r.start), new
|
|
604
|
+
return s.sort((n, r) => n.start - r.start), new D(s);
|
|
592
605
|
}
|
|
593
606
|
cueAt(t) {
|
|
594
607
|
let e = 0, i = this.cues.length - 1;
|
|
@@ -601,12 +614,12 @@ class Z {
|
|
|
601
614
|
return null;
|
|
602
615
|
}
|
|
603
616
|
}
|
|
604
|
-
const
|
|
605
|
-
class
|
|
617
|
+
const wt = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m9 6 6 6-6 6"/></svg>', xt = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m15 6-6 6 6 6"/></svg>';
|
|
618
|
+
class M {
|
|
606
619
|
constructor(t) {
|
|
607
|
-
this.anchor = t, this.outsideListener = null, this.root = l("div", "imp-menu"), this.root.hidden = !0, this.backdrop = l("div", "imp-menu__backdrop"), this.backdrop.hidden = !0, this.backdrop.addEventListener("pointerdown", (e) => {
|
|
620
|
+
this.anchor = t, this.outsideListener = null, this.escListener = null, this.root = l("div", "imp-menu"), this.root.hidden = !0, this.backdrop = l("div", "imp-menu__backdrop"), this.backdrop.hidden = !0, this.backdrop.addEventListener("pointerdown", (e) => {
|
|
608
621
|
e.preventDefault(), this.close();
|
|
609
|
-
})
|
|
622
|
+
});
|
|
610
623
|
}
|
|
611
624
|
get open() {
|
|
612
625
|
return !this.root.hidden;
|
|
@@ -640,7 +653,7 @@ class C {
|
|
|
640
653
|
const r = l("span", "imp-menu__value");
|
|
641
654
|
r.textContent = i.value ?? "";
|
|
642
655
|
const a = l("span", "imp-menu__chevron");
|
|
643
|
-
a.innerHTML =
|
|
656
|
+
a.innerHTML = wt, s.append(n, r, a), s.addEventListener("click", () => this.renderSettingsDetail(t, i)), e.append(s);
|
|
644
657
|
}
|
|
645
658
|
this.root.append(e);
|
|
646
659
|
}
|
|
@@ -662,7 +675,7 @@ class C {
|
|
|
662
675
|
if (!e.section) return;
|
|
663
676
|
this.root.textContent = "";
|
|
664
677
|
const i = l("button", "imp-menu__item imp-menu__back", { type: "button" }), s = l("span", "imp-menu__chevron");
|
|
665
|
-
s.innerHTML =
|
|
678
|
+
s.innerHTML = xt;
|
|
666
679
|
const n = l("span", "imp-menu__label");
|
|
667
680
|
n.textContent = e.label, i.append(s, n), i.addEventListener("click", () => this.renderSettingsRoot(t)), this.root.append(i), this.root.append(this.renderSection(e.section())), this.root.scrollTop = 0;
|
|
668
681
|
}
|
|
@@ -677,7 +690,7 @@ class C {
|
|
|
677
690
|
const s = l("button", "imp-menu__item", { type: "button", role: "menuitemradio" });
|
|
678
691
|
if (s.setAttribute("aria-checked", String(i.active)), i.active && s.classList.add("imp-menu__item--active"), i.icon) {
|
|
679
692
|
const r = l("span", "imp-menu__icon");
|
|
680
|
-
|
|
693
|
+
T(r, i.icon), s.append(r);
|
|
681
694
|
}
|
|
682
695
|
const n = l("span", "imp-menu__label");
|
|
683
696
|
n.textContent = i.label, s.append(n), s.addEventListener("click", () => {
|
|
@@ -686,25 +699,28 @@ class C {
|
|
|
686
699
|
}
|
|
687
700
|
return e;
|
|
688
701
|
}
|
|
689
|
-
/** Reveal the populated menu + backdrop and arm
|
|
702
|
+
/** Reveal the populated menu + backdrop and arm outside-click / Escape. */
|
|
690
703
|
reveal() {
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
704
|
+
const t = this.root.parentElement;
|
|
705
|
+
t && this.backdrop.parentElement !== t && t.insertBefore(this.backdrop, this.root), this.root.hidden = !1, this.backdrop.hidden = !1, this.outsideListener = (e) => {
|
|
706
|
+
const i = e.target;
|
|
707
|
+
!this.root.contains(i) && !this.anchor.contains(i) && this.close();
|
|
708
|
+
}, this.escListener = (e) => {
|
|
709
|
+
e.key === "Escape" && this.close();
|
|
710
|
+
}, document.addEventListener("keydown", this.escListener), setTimeout(() => {
|
|
695
711
|
this.outsideListener && document.addEventListener("pointerdown", this.outsideListener);
|
|
696
712
|
}, 0);
|
|
697
713
|
}
|
|
698
714
|
close() {
|
|
699
|
-
this.root.hidden = !0, this.root.classList.remove("imp-menu--wide"), this.backdrop.hidden = !0, this.outsideListener && (document.removeEventListener("pointerdown", this.outsideListener), this.outsideListener = null);
|
|
715
|
+
this.root.hidden = !0, this.root.classList.remove("imp-menu--wide"), this.backdrop.hidden = !0, this.outsideListener && (document.removeEventListener("pointerdown", this.outsideListener), this.outsideListener = null), this.escListener && (document.removeEventListener("keydown", this.escListener), this.escListener = null);
|
|
700
716
|
}
|
|
701
717
|
destroy() {
|
|
702
|
-
this.close(), this.root.remove();
|
|
718
|
+
this.close(), this.backdrop.remove(), this.root.remove();
|
|
703
719
|
}
|
|
704
720
|
}
|
|
705
|
-
class
|
|
706
|
-
constructor(t) {
|
|
707
|
-
this.cb = t, this.segments = [], this.duration = 0, this.chapters = [], this.thumbnails = null, this.scrubbing = !1, this.root = l("div", "imp-progress", { role: "slider", "aria-label":
|
|
721
|
+
class _t {
|
|
722
|
+
constructor(t, e = "Seek") {
|
|
723
|
+
this.cb = t, this.segments = [], this.duration = 0, this.chapters = [], this.thumbnails = null, this.scrubbing = !1, this.root = l("div", "imp-progress", { role: "slider", "aria-label": e, tabindex: "-1" }), this.buffered = l("div", "imp-progress__buffered"), this.track = l("div", "imp-progress__track"), this.handle = l("div", "imp-progress__handle"), this.tooltipThumb = l("div", "imp-progress__thumb"), this.tooltipChapter = l("div", "imp-progress__tooltip-chapter"), this.tooltipTime = l("div", "imp-progress__tooltip-time"), this.tooltipCaption = l("div", "imp-progress__caption"), this.tooltipCaption.append(this.tooltipChapter, this.tooltipTime), this.tooltip = l("div", "imp-progress__tooltip"), this.tooltip.append(this.tooltipThumb, this.tooltipCaption), this.heatmap = l("div", "imp-progress__heatmap"), this.heatmap.hidden = !0, this.root.append(this.heatmap, this.buffered, this.track, this.handle, this.tooltip), this.setChapters([]), this.bindPointer();
|
|
708
724
|
}
|
|
709
725
|
/** Render the popularity curve (empty array hides it). */
|
|
710
726
|
setHeatmap(t, e = 1) {
|
|
@@ -712,7 +728,7 @@ class kt {
|
|
|
712
728
|
this.heatmap.hidden = !0, this.heatmap.textContent = "";
|
|
713
729
|
return;
|
|
714
730
|
}
|
|
715
|
-
this.heatmap.innerHTML = `<svg viewBox="0 0 1000 100" preserveAspectRatio="none" aria-hidden="true"><path d="${
|
|
731
|
+
this.heatmap.innerHTML = `<svg viewBox="0 0 1000 100" preserveAspectRatio="none" aria-hidden="true"><path d="${ct(t, e)}"/></svg>`, this.heatmap.hidden = !1;
|
|
716
732
|
}
|
|
717
733
|
setDuration(t) {
|
|
718
734
|
this.duration = Number.isFinite(t) ? t : 0, this.root.classList.toggle("imp-progress--live", !Number.isFinite(t)), this.chapters.length === 0 && this.setChapters([]);
|
|
@@ -737,20 +753,20 @@ class kt {
|
|
|
737
753
|
update(t, e, i) {
|
|
738
754
|
if (e !== this.duration && Number.isFinite(e) && this.setDuration(e), this.scrubbing) return;
|
|
739
755
|
this.render(t);
|
|
740
|
-
const s = this.duration > 0 ?
|
|
741
|
-
this.buffered.style.width = `${s * 100}%`, this.root.setAttribute("aria-valuemin", "0"), this.root.setAttribute("aria-valuemax", String(Math.round(this.duration))), this.root.setAttribute("aria-valuenow", String(Math.round(t))), this.root.setAttribute("aria-valuetext", `${
|
|
756
|
+
const s = this.duration > 0 ? x(i / this.duration, 0, 1) : 0;
|
|
757
|
+
this.buffered.style.width = `${s * 100}%`, this.root.setAttribute("aria-valuemin", "0"), this.root.setAttribute("aria-valuemax", String(Math.round(this.duration))), this.root.setAttribute("aria-valuenow", String(Math.round(t))), this.root.setAttribute("aria-valuetext", `${_(t)} / ${_(this.duration)}`);
|
|
742
758
|
}
|
|
743
759
|
render(t) {
|
|
744
760
|
for (const { chapter: i, fill: s } of this.segments) {
|
|
745
|
-
const n = i.end - i.start, r = n > 0 ?
|
|
761
|
+
const n = i.end - i.start, r = n > 0 ? x((t - i.start) / n, 0, 1) : 0;
|
|
746
762
|
s.style.transform = `scaleX(${r})`;
|
|
747
763
|
}
|
|
748
|
-
const e = this.duration > 0 ?
|
|
764
|
+
const e = this.duration > 0 ? x(t / this.duration, 0, 1) : 0;
|
|
749
765
|
this.handle.style.left = `${e * 100}%`;
|
|
750
766
|
}
|
|
751
767
|
timeFromEvent(t) {
|
|
752
768
|
const e = this.root.getBoundingClientRect();
|
|
753
|
-
return (e.width > 0 ?
|
|
769
|
+
return (e.width > 0 ? x((t.clientX - e.left) / e.width, 0, 1) : 0) * this.duration;
|
|
754
770
|
}
|
|
755
771
|
bindPointer() {
|
|
756
772
|
this.root.addEventListener("pointerdown", (t) => {
|
|
@@ -765,64 +781,64 @@ class kt {
|
|
|
765
781
|
}
|
|
766
782
|
showTooltip(t) {
|
|
767
783
|
const e = this.timeFromEvent(t);
|
|
768
|
-
this.tooltipTime.textContent =
|
|
769
|
-
const i =
|
|
784
|
+
this.tooltipTime.textContent = _(e);
|
|
785
|
+
const i = Y(this.chapters, e), s = !!i?.title;
|
|
770
786
|
this.tooltipChapter.textContent = i?.title ?? "", this.tooltipChapter.hidden = !s, this.tooltipCaption.classList.toggle("imp-progress__caption--time-only", !s);
|
|
771
787
|
const n = this.thumbnails?.cueAt(e) ?? null;
|
|
772
788
|
this.tooltip.classList.toggle("imp-progress__tooltip--thumb", !!n), n ? (this.tooltipThumb.hidden = !1, this.tooltipThumb.style.backgroundImage = `url("${n.src}")`, n.xywh ? (this.tooltipThumb.style.width = `${n.xywh.w}px`, this.tooltipThumb.style.height = `${n.xywh.h}px`, this.tooltipThumb.style.backgroundPosition = `-${n.xywh.x}px -${n.xywh.y}px`, this.tooltipThumb.style.backgroundSize = "auto") : (this.tooltipThumb.style.width = "160px", this.tooltipThumb.style.height = "90px", this.tooltipThumb.style.backgroundPosition = "center", this.tooltipThumb.style.backgroundSize = "cover")) : this.tooltipThumb.hidden = !0, this.tooltip.classList.add("imp-progress__tooltip--visible");
|
|
773
|
-
const r = this.root.getBoundingClientRect(), a =
|
|
774
|
-
this.tooltip.style.left = `${
|
|
789
|
+
const r = this.root.getBoundingClientRect(), a = x(t.clientX - r.left, 0, r.width), h = this.tooltip.offsetWidth / 2;
|
|
790
|
+
this.tooltip.style.left = `${x(a, h, Math.max(h, r.width - h))}px`;
|
|
775
791
|
}
|
|
776
792
|
hideTooltip() {
|
|
777
793
|
this.tooltip.classList.remove("imp-progress__tooltip--visible");
|
|
778
794
|
}
|
|
779
795
|
}
|
|
780
|
-
class
|
|
796
|
+
class Lt {
|
|
781
797
|
constructor(t) {
|
|
782
798
|
this.player = t, this.rightItems = /* @__PURE__ */ new Map(), this.subtitlesBtn = null, this.settingsBtn = null, this.settingsMenu = null, this.subtitlesMenu = null, this.moreMenu = null, this.moreWrap = null, this.qualityBtn = null, this.qualityMenu = null, this.gearBtn = null, this.gearMenu = null, this.gear = { speed: !1, quality: !1, subtitles: !1 }, this.nextPreviewEl = null, this.nextPreviewOpts = null, this.scenesBtn = null, this.sceneTypeBtn = null, this.sceneTypeMenu = null, this.likeBtn = null, this.dislikeBtn = null, this.likeCountEl = null, this.dislikeCountEl = null, this.prevBtn = null, this.nextBtn = null, this.seekBackBtn = null, this.seekFwdBtn = null, this.centerPlayBtn = null, this.centerPrevBtn = null, this.centerNextBtn = null, this.collapsibles = [], this.overflowed = /* @__PURE__ */ new Set(), this.resizeObserver = null, this.reflowScheduled = !1, this.actionItems = [], this.wasPlayingBeforeScrub = !1, this.disposers = [], this.onWindowResize = null;
|
|
783
799
|
const { labels: e, icons: i } = t, s = t.controlsOptions;
|
|
784
|
-
this.root = l("div", "imp-controls"), this.progress = new
|
|
800
|
+
this.root = l("div", "imp-controls"), this.progress = new _t({
|
|
785
801
|
onSeek: (d) => t.seek(d),
|
|
786
802
|
onScrubStart: () => {
|
|
787
|
-
this.wasPlayingBeforeScrub = !t.paused, t.pause();
|
|
803
|
+
t.scrubbing = !0, this.wasPlayingBeforeScrub = !t.paused, t.pause();
|
|
788
804
|
},
|
|
789
805
|
onScrubEnd: () => {
|
|
790
|
-
this.wasPlayingBeforeScrub && t.play();
|
|
806
|
+
t.scrubbing = !1, this.wasPlayingBeforeScrub && t.play(!0);
|
|
791
807
|
}
|
|
792
|
-
}), s.progress && this.root.append(this.progress.root);
|
|
808
|
+
}, t.labels.seek), s.progress && this.root.append(this.progress.root);
|
|
793
809
|
const n = l("div", "imp-controls__row");
|
|
794
810
|
this.row = n, this.root.append(n);
|
|
795
811
|
const r = l("div", "imp-controls__group"), a = l("div", "imp-controls__group");
|
|
796
812
|
this.rightGroup = a;
|
|
797
813
|
const h = l("div", "imp-controls__spacer");
|
|
798
814
|
this.chapterLabel = l("div", "imp-controls__chapter"), n.append(r, h, a), h.append(this.chapterLabel);
|
|
799
|
-
const c = typeof s.seekButtons == "object" ? s.seekButtons : {},
|
|
800
|
-
if (this.seekLabelFn = c.label, s.playlist && t.hasPlaylist && !s.hidePrev && (this.prevBtn = g("imp-btn--prev", e.previous, i.previous), this.prevBtn.addEventListener("click", () => t.previous()), r.append(this.prevBtn)), s.seekButtons && (this.seekBackBtn = g("imp-btn--seek-back", `${e.seekBack} ${
|
|
815
|
+
const c = typeof s.seekButtons == "object" ? s.seekButtons : {}, u = c.back ?? t.seekStep, m = c.forward ?? t.seekStep;
|
|
816
|
+
if (this.seekLabelFn = c.label, s.playlist && t.hasPlaylist && !s.hidePrev && (this.prevBtn = g("imp-btn--prev", e.previous, i.previous), this.prevBtn.addEventListener("click", () => t.previous()), r.append(this.prevBtn)), s.seekButtons && (this.seekBackBtn = g("imp-btn--seek-back", `${e.seekBack} ${u}s`, i.seekBack), this.addStepBadge(this.seekBackBtn, u, "back"), this.seekBackBtn.addEventListener("click", () => t.skip(-u)), r.append(this.seekBackBtn)), s.play && (this.playBtn = g("imp-btn--play", e.play, i.play), this.playBtn.addEventListener("click", () => t.togglePlay()), r.append(this.playBtn)), s.seekButtons && (this.seekFwdBtn = g("imp-btn--seek-forward", `${e.seekForward} ${m}s`, i.seekForward), this.addStepBadge(this.seekFwdBtn, m, "forward"), this.seekFwdBtn.addEventListener("click", () => t.skip(m)), r.append(this.seekFwdBtn)), s.playlist && t.hasPlaylist && !s.hideNext && (this.nextBtn = g("imp-btn--next", e.next, i.next), this.nextBtn.addEventListener("click", () => t.next()), r.append(this.nextBtn)), s.volume) {
|
|
801
817
|
const d = l("div", "imp-volume");
|
|
802
818
|
this.muteBtn = g("imp-btn--mute", e.mute, i.volumeHigh), this.muteBtn.addEventListener("click", () => t.toggleMute()), this.volumeSlider = l("input", "imp-volume__slider", {
|
|
803
819
|
type: "range",
|
|
804
820
|
min: "0",
|
|
805
821
|
max: "1",
|
|
806
822
|
step: "0.05",
|
|
807
|
-
"aria-label":
|
|
823
|
+
"aria-label": e.volume
|
|
808
824
|
}), this.volumeSlider.addEventListener("input", () => {
|
|
809
825
|
t.setVolume(Number(this.volumeSlider.value));
|
|
810
826
|
}), d.append(this.muteBtn, this.volumeSlider), r.append(d);
|
|
811
827
|
}
|
|
812
828
|
s.time && (this.timeLabel = l("div", "imp-controls__time"), this.timeCurrent = l("span", "imp-controls__time-current"), this.timeTotal = l("span", "imp-controls__time-total"), this.timeLabel.append(this.timeCurrent, this.timeTotal), this.liveBadge = l("span", "imp-controls__live"), this.liveBadge.textContent = e.live, this.liveBadge.hidden = !0, r.append(this.timeLabel, this.liveBadge)), this.buildLikeDislike();
|
|
813
|
-
for (const d of (t.actionsOptions.custom ?? []).filter((
|
|
814
|
-
const
|
|
815
|
-
|
|
829
|
+
for (const d of (t.actionsOptions.custom ?? []).filter((k) => k.placement === "bar")) {
|
|
830
|
+
const k = g(`imp-btn--custom imp-btn--custom-${d.id}`, d.title, d.icon ?? i.more);
|
|
831
|
+
k.addEventListener("click", () => t.emit("customaction", { id: d.id })), this.rightItems.set(`custom:${d.id}`, k), this.registerCollapsible({
|
|
816
832
|
key: `custom:${d.id}`,
|
|
817
|
-
el:
|
|
833
|
+
el: k,
|
|
818
834
|
priority: 55,
|
|
819
835
|
available: () => !0,
|
|
820
836
|
section: () => this.simpleSection(`custom:${d.id}`, d.title, d.icon ?? i.more, () => t.emit("customaction", { id: d.id }))
|
|
821
837
|
});
|
|
822
838
|
}
|
|
823
|
-
const
|
|
824
|
-
if (this.gear = { speed:
|
|
825
|
-
this.subtitlesBtn = g("imp-btn--subtitles", e.subtitles, i.subtitles), this.subtitlesMenu = new
|
|
839
|
+
const p = (d) => d === !1 ? "off" : d === "bar" ? "bar" : "gear", v = p(s.subtitles), f = p(s.quality), b = p(s.speed);
|
|
840
|
+
if (this.gear = { speed: b === "gear", quality: f === "gear", subtitles: v === "gear" }, v === "bar") {
|
|
841
|
+
this.subtitlesBtn = g("imp-btn--subtitles", e.subtitles, i.subtitles), this.subtitlesMenu = new M(this.subtitlesBtn);
|
|
826
842
|
const d = l("div", "imp-controls__menu-anchor");
|
|
827
843
|
d.append(this.subtitlesBtn, this.subtitlesMenu.root), this.subtitlesBtn.addEventListener("click", () => this.toggleSubtitlesMenu()), this.rightItems.set("subtitles", d), this.registerCollapsible({
|
|
828
844
|
key: "subtitles",
|
|
@@ -832,8 +848,8 @@ class wt {
|
|
|
832
848
|
section: () => this.subtitlesSection()
|
|
833
849
|
});
|
|
834
850
|
}
|
|
835
|
-
if (
|
|
836
|
-
this.qualityBtn = g("imp-btn--quality", e.quality, i.settings), this.qualityMenu = new
|
|
851
|
+
if (f === "bar") {
|
|
852
|
+
this.qualityBtn = g("imp-btn--quality", e.quality, i.settings), this.qualityMenu = new M(this.qualityBtn);
|
|
837
853
|
const d = l("div", "imp-controls__menu-anchor");
|
|
838
854
|
d.append(this.qualityBtn, this.qualityMenu.root), this.qualityBtn.addEventListener("click", () => this.toggleQualityMenu()), this.rightItems.set("quality", d), this.registerCollapsible({
|
|
839
855
|
key: "quality",
|
|
@@ -843,8 +859,8 @@ class wt {
|
|
|
843
859
|
section: () => this.qualitySection()
|
|
844
860
|
});
|
|
845
861
|
}
|
|
846
|
-
if (
|
|
847
|
-
this.settingsBtn = g("imp-btn--speed", e.speed, i.speed), this.settingsMenu = new
|
|
862
|
+
if (b === "bar") {
|
|
863
|
+
this.settingsBtn = g("imp-btn--speed", e.speed, i.speed), this.settingsMenu = new M(this.settingsBtn);
|
|
848
864
|
const d = l("div", "imp-controls__menu-anchor");
|
|
849
865
|
d.append(this.settingsBtn, this.settingsMenu.root), this.settingsBtn.addEventListener("click", () => this.toggleSettingsMenu()), this.rightItems.set("speed", d), this.registerCollapsible({
|
|
850
866
|
key: "speed",
|
|
@@ -861,7 +877,7 @@ class wt {
|
|
|
861
877
|
available: () => t.chapterList.length > 0,
|
|
862
878
|
section: () => this.simpleSection("scenes", e.scenes, i.scenes, () => t.toggleScenesPanel())
|
|
863
879
|
})), s.sceneTypes !== !1) {
|
|
864
|
-
this.sceneTypeBtn = l("button", "imp-btn imp-btn--scene-types", { type: "button" }), this.sceneTypeMenu = new
|
|
880
|
+
this.sceneTypeBtn = l("button", "imp-btn imp-btn--scene-types", { type: "button" }), this.sceneTypeMenu = new M(this.sceneTypeBtn);
|
|
865
881
|
const d = l("div", "imp-controls__menu-anchor");
|
|
866
882
|
d.append(this.sceneTypeBtn, this.sceneTypeMenu.root), this.sceneTypeBtn.addEventListener("click", () => this.toggleSceneTypeMenu()), this.rightItems.set("sceneTypes", d), this.refreshSceneTypeButton(), this.registerCollapsible({
|
|
867
883
|
key: "sceneTypes",
|
|
@@ -871,7 +887,7 @@ class wt {
|
|
|
871
887
|
section: () => this.sceneTypeSection()
|
|
872
888
|
});
|
|
873
889
|
}
|
|
874
|
-
if (s.playlist && t.hasPlaylist) {
|
|
890
|
+
if (s.playlist && t.hasPlaylist && s.playlistButton !== !1) {
|
|
875
891
|
const d = g("imp-btn--list", e.playlist, i.list);
|
|
876
892
|
d.addEventListener("click", () => t.togglePlaylistPanel()), this.rightItems.set("playlist", d), this.registerCollapsible({
|
|
877
893
|
key: "list",
|
|
@@ -910,7 +926,7 @@ class wt {
|
|
|
910
926
|
el: d,
|
|
911
927
|
priority: 80,
|
|
912
928
|
available: () => Number.isFinite(t.duration) && t.duration > 0,
|
|
913
|
-
section: () => this.simpleSection("seekBack", `${e.seekBack} ${
|
|
929
|
+
section: () => this.simpleSection("seekBack", `${e.seekBack} ${u}s`, i.seekBack, () => t.skip(-u))
|
|
914
930
|
});
|
|
915
931
|
}
|
|
916
932
|
if (this.seekFwdBtn) {
|
|
@@ -920,19 +936,19 @@ class wt {
|
|
|
920
936
|
el: d,
|
|
921
937
|
priority: 82,
|
|
922
938
|
available: () => Number.isFinite(t.duration) && t.duration > 0,
|
|
923
|
-
section: () => this.simpleSection("seekFwd", `${e.seekForward} ${
|
|
939
|
+
section: () => this.simpleSection("seekFwd", `${e.seekForward} ${m}s`, i.seekForward, () => t.skip(m))
|
|
924
940
|
});
|
|
925
941
|
}
|
|
926
942
|
if (this.center = l("div", "imp-center-controls"), s.playlist && t.hasPlaylist && (this.centerPrevBtn = this.makeCenterButton("prev", e.previous, i.previous), this.centerPrevBtn.addEventListener("click", () => t.previous()), this.center.append(this.centerPrevBtn)), s.seekButtons) {
|
|
927
|
-
const d = this.makeCenterButton("seek-back", `${e.seekBack} ${
|
|
928
|
-
this.addStepBadge(d,
|
|
943
|
+
const d = this.makeCenterButton("seek-back", `${e.seekBack} ${u}s`, i.seekBack);
|
|
944
|
+
this.addStepBadge(d, u, "back"), d.addEventListener("click", () => t.skip(-u)), this.center.append(d);
|
|
929
945
|
}
|
|
930
946
|
if (s.play && (this.centerPlayBtn = this.makeCenterButton("play", e.play, i.play), this.centerPlayBtn.addEventListener("click", () => t.togglePlay()), this.center.append(this.centerPlayBtn)), s.seekButtons) {
|
|
931
|
-
const d = this.makeCenterButton("seek-forward", `${e.seekForward} ${
|
|
932
|
-
this.addStepBadge(d,
|
|
947
|
+
const d = this.makeCenterButton("seek-forward", `${e.seekForward} ${m}s`, i.seekForward);
|
|
948
|
+
this.addStepBadge(d, m, "forward"), d.addEventListener("click", () => t.skip(m)), this.center.append(d);
|
|
933
949
|
}
|
|
934
950
|
if (s.playlist && t.hasPlaylist && (this.centerNextBtn = this.makeCenterButton("next", e.next, i.next), this.centerNextBtn.addEventListener("click", () => t.next()), this.center.append(this.centerNextBtn)), this.center.style.display = "none", this.setupNextPreview(), this.gear.speed || this.gear.quality || this.gear.subtitles) {
|
|
935
|
-
this.gearBtn = g("imp-btn--settings", e.settings, i.settings), this.gearMenu = new
|
|
951
|
+
this.gearBtn = g("imp-btn--settings", e.settings, i.settings), this.gearMenu = new M(this.gearBtn);
|
|
936
952
|
const d = l("div", "imp-controls__menu-anchor");
|
|
937
953
|
d.append(this.gearBtn, this.gearMenu.root), this.gearBtn.addEventListener("click", () => this.toggleGearMenu()), this.rightItems.set("gear", d), this.registerCollapsible({
|
|
938
954
|
key: "gear",
|
|
@@ -970,7 +986,7 @@ class wt {
|
|
|
970
986
|
/** Center-cluster button — deliberately NOT `.imp-btn` (own sizing/look). */
|
|
971
987
|
makeCenterButton(t, e, i) {
|
|
972
988
|
const s = l("button", `imp-center-btn imp-center-btn--${t}`, { type: "button", "aria-label": e, title: e });
|
|
973
|
-
return
|
|
989
|
+
return T(s, i), s;
|
|
974
990
|
}
|
|
975
991
|
/** Caption under the seek arrow. Default "−15s"/"+15s"; overridable via `controls.seekButtons.label`. */
|
|
976
992
|
addStepBadge(t, e, i) {
|
|
@@ -996,7 +1012,7 @@ class wt {
|
|
|
996
1012
|
}
|
|
997
1013
|
if (this.gear.speed) {
|
|
998
1014
|
const i = t.playbackRate;
|
|
999
|
-
e.push({ key: "speed", label: t.labels.speed, value: i === 1 ?
|
|
1015
|
+
e.push({ key: "speed", label: t.labels.speed, value: i === 1 ? t.labels.speedNormal : `${i}×`, section: () => this.speedSection() });
|
|
1000
1016
|
}
|
|
1001
1017
|
if (this.gear.subtitles && t.subtitleTracks.length > 0) {
|
|
1002
1018
|
const i = t.activeSubtitle === -1 ? t.labels.subtitlesOff : t.subtitleTracks[t.activeSubtitle]?.label ?? t.labels.subtitlesOff;
|
|
@@ -1013,7 +1029,7 @@ class wt {
|
|
|
1013
1029
|
if (t.textContent = "", !e) return;
|
|
1014
1030
|
if (e.icon) {
|
|
1015
1031
|
const s = l("span", "imp-scene-type__icon");
|
|
1016
|
-
|
|
1032
|
+
T(s, e.icon), t.append(s);
|
|
1017
1033
|
}
|
|
1018
1034
|
const i = l("span", "imp-scene-type__label");
|
|
1019
1035
|
i.textContent = e.title, t.append(i), t.setAttribute("aria-label", `${this.player.labels.sceneTypes}: ${e.title}`), t.title = e.title;
|
|
@@ -1066,20 +1082,20 @@ class wt {
|
|
|
1066
1082
|
e.textContent = "";
|
|
1067
1083
|
const n = l("div", "imp-next-preview__kicker");
|
|
1068
1084
|
if (n.textContent = this.player.labels.next, e.append(n), i.thumbnail && s.poster) {
|
|
1069
|
-
const
|
|
1070
|
-
if (
|
|
1085
|
+
const p = l("div", "imp-next-preview__thumb");
|
|
1086
|
+
if (p.append(S(s.poster)), i.duration && s.duration) {
|
|
1071
1087
|
const v = l("span", "imp-next-preview__duration");
|
|
1072
|
-
v.textContent =
|
|
1088
|
+
v.textContent = _(s.duration), p.append(v);
|
|
1073
1089
|
}
|
|
1074
|
-
e.append(
|
|
1090
|
+
e.append(p);
|
|
1075
1091
|
}
|
|
1076
1092
|
if (i.title && s.title) {
|
|
1077
|
-
const
|
|
1078
|
-
|
|
1093
|
+
const p = l("div", "imp-next-preview__title");
|
|
1094
|
+
p.textContent = s.title, e.append(p);
|
|
1079
1095
|
}
|
|
1080
|
-
i.meta && s.previewMeta?.length && e.append(
|
|
1081
|
-
const r = this.player.container.getBoundingClientRect(), a = t.getBoundingClientRect(), h = 8, c = e.offsetWidth,
|
|
1082
|
-
e.style.left = `${
|
|
1096
|
+
i.meta && s.previewMeta?.length && e.append(j(s.previewMeta, "imp-next-preview")), e.hidden = !1;
|
|
1097
|
+
const r = this.player.container.getBoundingClientRect(), a = t.getBoundingClientRect(), h = 8, c = e.offsetWidth, u = a.left - r.left + a.width / 2 - c / 2, m = Math.max(h, Math.min(u, r.width - c - h));
|
|
1098
|
+
e.style.left = `${m}px`, e.style.bottom = `${r.height - (a.top - r.top) + 10}px`;
|
|
1083
1099
|
}
|
|
1084
1100
|
hideNextPreview() {
|
|
1085
1101
|
this.nextPreviewEl && (this.nextPreviewEl.hidden = !0);
|
|
@@ -1135,7 +1151,7 @@ class wt {
|
|
|
1135
1151
|
for (const h of (i.custom ?? []).filter((c) => c.placement !== "bar"))
|
|
1136
1152
|
this.actionItems.push({ value: `custom:${h.id}`, label: h.title, icon: h.icon, run: () => e.emit("customaction", { id: h.id }) });
|
|
1137
1153
|
const r = g("imp-btn--more", s.more, n.more);
|
|
1138
|
-
this.moreMenu = new
|
|
1154
|
+
this.moreMenu = new M(r);
|
|
1139
1155
|
const a = l("div", "imp-controls__menu-anchor imp-controls__more");
|
|
1140
1156
|
a.append(r, this.moreMenu.root), r.addEventListener("click", () => {
|
|
1141
1157
|
this.closeMenus(this.moreMenu), this.moreMenu?.toggle(this.buildMoreSections());
|
|
@@ -1152,8 +1168,8 @@ class wt {
|
|
|
1152
1168
|
if (h)
|
|
1153
1169
|
for (const c of Array.isArray(h) ? h : [h])
|
|
1154
1170
|
if (!c.title && c.items.length === 1) {
|
|
1155
|
-
const
|
|
1156
|
-
i.push(
|
|
1171
|
+
const u = c.items[0];
|
|
1172
|
+
i.push(u), e.set(u.value, () => c.onSelect(u.value));
|
|
1157
1173
|
} else
|
|
1158
1174
|
t.push(c);
|
|
1159
1175
|
}
|
|
@@ -1161,7 +1177,7 @@ class wt {
|
|
|
1161
1177
|
const a = new Map(this.actionItems.map((h) => [h.value, h.run]));
|
|
1162
1178
|
t.push({
|
|
1163
1179
|
title: "",
|
|
1164
|
-
items: this.actionItems.map(({ value: h, label: c, icon:
|
|
1180
|
+
items: this.actionItems.map(({ value: h, label: c, icon: u }) => ({ value: h, label: c, icon: u, active: !1 })),
|
|
1165
1181
|
onSelect: (h) => a.get(h)?.()
|
|
1166
1182
|
});
|
|
1167
1183
|
}
|
|
@@ -1175,7 +1191,7 @@ class wt {
|
|
|
1175
1191
|
return {
|
|
1176
1192
|
title: t.labels.speed,
|
|
1177
1193
|
items: t.playbackRates.map((e) => ({
|
|
1178
|
-
label: e === 1 ?
|
|
1194
|
+
label: e === 1 ? t.labels.speedNormal : `${e}×`,
|
|
1179
1195
|
value: String(e),
|
|
1180
1196
|
active: t.playbackRate === e
|
|
1181
1197
|
})),
|
|
@@ -1247,7 +1263,7 @@ class wt {
|
|
|
1247
1263
|
const t = this.player;
|
|
1248
1264
|
this.disposers.push(
|
|
1249
1265
|
t.on("timeupdate", ({ currentTime: e, duration: i }) => {
|
|
1250
|
-
this.progress.update(e, i, t.bufferedEnd), this.timeLabel && (t.live ? (this.timeLabel.hidden = !0, this.liveBadge.hidden = !1) : (this.timeLabel.hidden = !1, this.liveBadge.hidden = !0, this.timeCurrent.textContent =
|
|
1266
|
+
this.progress.update(e, i, t.bufferedEnd), this.timeLabel && (t.live ? (this.timeLabel.hidden = !0, this.liveBadge.hidden = !1) : (this.timeLabel.hidden = !1, this.liveBadge.hidden = !0, this.timeCurrent.textContent = _(e), this.timeTotal.textContent = ` / ${_(i)}`));
|
|
1251
1267
|
}),
|
|
1252
1268
|
t.on("play", () => this.syncPlayState()),
|
|
1253
1269
|
t.on("pause", () => this.syncPlayState()),
|
|
@@ -1306,16 +1322,16 @@ class wt {
|
|
|
1306
1322
|
this.disposers = [], this.resizeObserver?.disconnect(), this.onWindowResize && window.removeEventListener("resize", this.onWindowResize), this.gearMenu?.destroy(), this.sceneTypeMenu?.destroy(), this.settingsMenu?.destroy(), this.subtitlesMenu?.destroy(), this.qualityMenu?.destroy(), this.moreMenu?.destroy(), this.nextPreviewEl?.remove(), this.root.remove();
|
|
1307
1323
|
}
|
|
1308
1324
|
}
|
|
1309
|
-
class
|
|
1325
|
+
class Tt {
|
|
1310
1326
|
constructor(t) {
|
|
1311
|
-
this.root = l("div", "imp-poster"), this.image = l("
|
|
1327
|
+
this.root = l("div", "imp-poster"), this.image = l("div", "imp-poster__image"), this.image.hidden = !0, this.img = S(""), this.image.append(this.img);
|
|
1312
1328
|
const e = g("imp-poster__play", t.labels.play, t.icons.bigPlay);
|
|
1313
1329
|
e.addEventListener("click", () => void t.play()), this.root.append(this.image, e), this.root.addEventListener("pointerup", (i) => {
|
|
1314
|
-
i.target !== this.root && i.target !== this.image || i.pointerType === "touch" && t.posterTapReveal() || t.play();
|
|
1330
|
+
i.target !== this.root && i.target !== this.image && i.target !== this.img || i.pointerType === "touch" && t.posterTapReveal() || t.play();
|
|
1315
1331
|
});
|
|
1316
1332
|
}
|
|
1317
1333
|
setSource(t) {
|
|
1318
|
-
t?.poster ? (this.
|
|
1334
|
+
t?.poster ? (this.img.src = t.poster, this.img.fetchPriority = "high", this.image.hidden = !1) : (this.img.removeAttribute("src"), this.image.hidden = !0);
|
|
1319
1335
|
}
|
|
1320
1336
|
show() {
|
|
1321
1337
|
this.root.hidden = !1;
|
|
@@ -1324,7 +1340,7 @@ class xt {
|
|
|
1324
1340
|
this.root.hidden = !0;
|
|
1325
1341
|
}
|
|
1326
1342
|
}
|
|
1327
|
-
class
|
|
1343
|
+
class St {
|
|
1328
1344
|
constructor(t) {
|
|
1329
1345
|
this.labels = t, this.channelUrl = null, this.custom = null, this.visible = { title: !0, description: !0, sponsor: !0 }, this.root = l("div", "imp-pause-screen"), this.root.hidden = !0, this.defaultContent = l("div", "imp-pause-screen__default"), this.channel = l("button", "imp-channel", { type: "button" }), this.channel.hidden = !0, this.channelAvatar = l("div", "imp-channel__avatar"), this.channelName = l("div", "imp-channel__name"), this.channel.append(this.channelName, this.channelAvatar), this.channel.addEventListener("click", () => {
|
|
1330
1346
|
this.channelUrl && window.open(this.channelUrl, "_blank", "noopener");
|
|
@@ -1352,7 +1368,7 @@ class _t {
|
|
|
1352
1368
|
const e = this.visible.sponsor ? t?.sponsor : void 0;
|
|
1353
1369
|
this.sponsor.hidden = !e, e && (this.sponsor.href = e.url, this.sponsorText.textContent = e.text, this.sponsorLabel.textContent = e.label ?? this.labels.sponsored);
|
|
1354
1370
|
const i = t?.channel;
|
|
1355
|
-
this.channel.hidden = !i, this.channelUrl = i?.url ?? null, this.channel.classList.toggle("imp-channel--link", !!i?.url), i && (this.channelName.textContent = i.name, this.channelAvatar.className = `imp-channel__avatar imp-channel__avatar--${i.avatarShape ?? "circle"}`, i.avatar ? (this.channelAvatar.textContent = "", this.channelAvatar.
|
|
1371
|
+
this.channel.hidden = !i, this.channelUrl = i?.url ?? null, this.channel.classList.toggle("imp-channel--link", !!i?.url), i && (this.channelName.textContent = i.name, this.channelAvatar.className = `imp-channel__avatar imp-channel__avatar--${i.avatarShape ?? "circle"}`, i.avatar ? (this.channelAvatar.textContent = "", this.channelAvatar.append(S(i.avatar, i.name))) : this.channelAvatar.textContent = (i.name.trim()[0] ?? "?").toUpperCase());
|
|
1356
1372
|
}
|
|
1357
1373
|
show() {
|
|
1358
1374
|
this.root.hidden = !1;
|
|
@@ -1361,10 +1377,10 @@ class _t {
|
|
|
1361
1377
|
this.root.hidden = !0;
|
|
1362
1378
|
}
|
|
1363
1379
|
}
|
|
1364
|
-
class
|
|
1380
|
+
class Bt {
|
|
1365
1381
|
constructor(t) {
|
|
1366
1382
|
this.player = t, this.clickBehavior = "player", this.root = l("div", "imp-related"), this.root.hidden = !0, this.heading = l("div", "imp-related__title"), this.grid = l("div", "imp-related__grid");
|
|
1367
|
-
const e = g("imp-related__close",
|
|
1383
|
+
const e = g("imp-related__close", t.labels.close, t.icons.close);
|
|
1368
1384
|
e.addEventListener("click", () => this.hide()), this.root.append(e, this.heading, this.grid);
|
|
1369
1385
|
}
|
|
1370
1386
|
setOptions(t) {
|
|
@@ -1376,7 +1392,7 @@ class St {
|
|
|
1376
1392
|
}
|
|
1377
1393
|
buildCard(t) {
|
|
1378
1394
|
const e = l("button", "imp-related__card", { type: "button" }), i = l("div", "imp-related__thumb");
|
|
1379
|
-
if (t.poster &&
|
|
1395
|
+
if (t.poster && i.append(S(t.poster)), t.duration) {
|
|
1380
1396
|
const n = l("span", "imp-related__duration");
|
|
1381
1397
|
n.textContent = t.duration, i.append(n);
|
|
1382
1398
|
}
|
|
@@ -1410,7 +1426,7 @@ class St {
|
|
|
1410
1426
|
this.root.hidden = !0;
|
|
1411
1427
|
}
|
|
1412
1428
|
}
|
|
1413
|
-
class
|
|
1429
|
+
class Et {
|
|
1414
1430
|
constructor(t) {
|
|
1415
1431
|
this.player = t, this.root = l("div", "imp-upnext"), this.root.hidden = !0;
|
|
1416
1432
|
}
|
|
@@ -1425,18 +1441,18 @@ class Lt {
|
|
|
1425
1441
|
const i = l("div", "imp-upnext__card"), s = l("div", "imp-upnext__kicker");
|
|
1426
1442
|
if (s.textContent = e.nextVideo, i.append(s), t.poster) {
|
|
1427
1443
|
const r = l("button", "imp-upnext__thumb", { type: "button", "aria-label": e.playNext });
|
|
1428
|
-
if (r.
|
|
1444
|
+
if (r.append(S(t.poster)), t.duration) {
|
|
1429
1445
|
const h = l("span", "imp-upnext__duration");
|
|
1430
|
-
h.textContent =
|
|
1446
|
+
h.textContent = _(t.duration), r.append(h);
|
|
1431
1447
|
}
|
|
1432
1448
|
const a = l("span", "imp-upnext__thumb-play");
|
|
1433
|
-
|
|
1449
|
+
T(a, this.player.icons.bigPlay), r.append(a), r.addEventListener("click", () => this.player.next()), i.append(r);
|
|
1434
1450
|
}
|
|
1435
1451
|
if (t.title) {
|
|
1436
1452
|
const r = l("div", "imp-upnext__title");
|
|
1437
1453
|
r.textContent = t.title, i.append(r);
|
|
1438
1454
|
}
|
|
1439
|
-
t.previewMeta?.length && i.append(
|
|
1455
|
+
t.previewMeta?.length && i.append(j(t.previewMeta, "imp-upnext"));
|
|
1440
1456
|
const n = l("button", "imp-upnext__btn", { type: "button" });
|
|
1441
1457
|
n.textContent = e.playNext, n.addEventListener("click", () => this.player.next()), i.append(n), this.root.append(i), this.root.hidden = !1;
|
|
1442
1458
|
}
|
|
@@ -1444,7 +1460,7 @@ class Lt {
|
|
|
1444
1460
|
this.root.hidden = !0;
|
|
1445
1461
|
}
|
|
1446
1462
|
}
|
|
1447
|
-
class
|
|
1463
|
+
class Mt {
|
|
1448
1464
|
constructor(t, e = "sidebar", i) {
|
|
1449
1465
|
this.player = t, this.root = l("div", `imp-playlist imp-playlist--${e}`), this.root.hidden = !0;
|
|
1450
1466
|
const s = l("div", "imp-playlist__header"), n = l("div", "imp-playlist__heading");
|
|
@@ -1461,7 +1477,7 @@ class Bt {
|
|
|
1461
1477
|
}), this.repeatBtn = g("imp-playlist__repeat", t.labels.repeat, t.icons.repeat), this.repeatBtn.addEventListener("click", () => {
|
|
1462
1478
|
t.setRepeat(!t.repeat), this.syncModes();
|
|
1463
1479
|
});
|
|
1464
|
-
const a = g("imp-playlist__close",
|
|
1480
|
+
const a = g("imp-playlist__close", t.labels.close, t.icons.close);
|
|
1465
1481
|
a.addEventListener("click", () => this.hide()), r.append(this.shuffleBtn, this.repeatBtn, a), s.append(n, r), this.list = l("div", "imp-playlist__list"), this.root.append(s, this.list), this.rebuild(), this.syncModes();
|
|
1466
1482
|
}
|
|
1467
1483
|
syncModes() {
|
|
@@ -1472,11 +1488,11 @@ class Bt {
|
|
|
1472
1488
|
const i = l("button", "imp-playlist__item", { type: "button" });
|
|
1473
1489
|
e === this.player.index && i.classList.add("imp-playlist__item--active");
|
|
1474
1490
|
const s = l("div", "imp-playlist__thumb");
|
|
1475
|
-
t.poster &&
|
|
1491
|
+
t.poster && s.append(S(t.poster));
|
|
1476
1492
|
const n = l("div", "imp-playlist__meta"), r = l("div", "imp-playlist__title");
|
|
1477
1493
|
if (r.textContent = t.title ?? `#${e + 1}`, n.append(r), t.duration) {
|
|
1478
1494
|
const a = l("div", "imp-playlist__duration");
|
|
1479
|
-
a.textContent =
|
|
1495
|
+
a.textContent = _(t.duration), n.append(a);
|
|
1480
1496
|
}
|
|
1481
1497
|
i.append(s, n), i.addEventListener("click", () => {
|
|
1482
1498
|
this.player.playItem(e), window.innerWidth <= 767 && this.hide();
|
|
@@ -1496,12 +1512,12 @@ class Bt {
|
|
|
1496
1512
|
this.visible ? this.hide() : this.show();
|
|
1497
1513
|
}
|
|
1498
1514
|
}
|
|
1499
|
-
class
|
|
1515
|
+
class Ct {
|
|
1500
1516
|
constructor(t, e = "bottom") {
|
|
1501
1517
|
this.player = t, this.items = [], this.root = l("div", `imp-playlist imp-scenes imp-playlist--${e}`), this.root.hidden = !0;
|
|
1502
1518
|
const i = l("div", "imp-playlist__header"), s = l("span");
|
|
1503
1519
|
s.textContent = t.labels.scenes;
|
|
1504
|
-
const n = g("imp-playlist__close",
|
|
1520
|
+
const n = g("imp-playlist__close", t.labels.close, t.icons.close);
|
|
1505
1521
|
n.addEventListener("click", () => this.hide()), i.append(s, n), this.list = l("div", "imp-playlist__list"), this.root.append(i, this.list), t.on("chapterchange", () => this.syncActive());
|
|
1506
1522
|
}
|
|
1507
1523
|
/** Re-render from the player's current chapters + thumbnail track. */
|
|
@@ -1513,11 +1529,11 @@ class Tt {
|
|
|
1513
1529
|
if (n?.xywh) {
|
|
1514
1530
|
const c = l("div", "imp-scenes__sprite");
|
|
1515
1531
|
c.style.width = `${n.xywh.w}px`, c.style.height = `${n.xywh.h}px`, c.style.backgroundImage = `url("${n.src}")`, c.style.backgroundPosition = `-${n.xywh.x}px -${n.xywh.y}px`, c.style.setProperty("--imp-sprite-w", String(n.xywh.w)), s.append(c);
|
|
1516
|
-
} else n &&
|
|
1532
|
+
} else n && s.append(S(n.src));
|
|
1517
1533
|
const r = l("div", "imp-playlist__meta"), a = l("div", "imp-playlist__title");
|
|
1518
|
-
a.textContent = e.title ||
|
|
1534
|
+
a.textContent = e.title || _(e.start);
|
|
1519
1535
|
const h = l("div", "imp-playlist__duration");
|
|
1520
|
-
h.textContent =
|
|
1536
|
+
h.textContent = _(e.start), r.append(a, h), i.append(s, r), i.addEventListener("click", () => {
|
|
1521
1537
|
this.player.seek(e.start), this.player.play(), window.innerWidth <= 767 && this.hide();
|
|
1522
1538
|
}), this.list.append(i), this.items.push(i);
|
|
1523
1539
|
}
|
|
@@ -1542,10 +1558,21 @@ class Tt {
|
|
|
1542
1558
|
this.visible ? this.hide() : this.show();
|
|
1543
1559
|
}
|
|
1544
1560
|
}
|
|
1545
|
-
|
|
1561
|
+
let tt = 0;
|
|
1562
|
+
function et(o) {
|
|
1563
|
+
const t = o.reason;
|
|
1564
|
+
t?.name === "AbortError" && /interrupted by a (new load request|call to pause)/i.test(t.message ?? "") && o.preventDefault();
|
|
1565
|
+
}
|
|
1566
|
+
function Pt() {
|
|
1567
|
+
typeof window < "u" && ++tt === 1 && window.addEventListener("unhandledrejection", et);
|
|
1568
|
+
}
|
|
1569
|
+
function At() {
|
|
1570
|
+
typeof window < "u" && --tt === 0 && window.removeEventListener("unhandledrejection", et);
|
|
1571
|
+
}
|
|
1572
|
+
function U(o) {
|
|
1546
1573
|
return o ? typeof o == "string" ? [{ src: o, label: "Subtitles" }] : Array.isArray(o) ? o : [o] : [];
|
|
1547
1574
|
}
|
|
1548
|
-
const
|
|
1575
|
+
const Rt = {
|
|
1549
1576
|
play: !0,
|
|
1550
1577
|
progress: !0,
|
|
1551
1578
|
time: !0,
|
|
@@ -1568,54 +1595,66 @@ const Ct = {
|
|
|
1568
1595
|
// empty → built-in right-cluster order
|
|
1569
1596
|
playlist: !0,
|
|
1570
1597
|
hidePrev: !0,
|
|
1598
|
+
hideNext: !1,
|
|
1599
|
+
playlistButton: !0,
|
|
1571
1600
|
nextPreview: !0,
|
|
1572
1601
|
hideDelay: 2500,
|
|
1573
1602
|
revealBeforePlay: !0
|
|
1574
1603
|
};
|
|
1575
|
-
class
|
|
1604
|
+
class Ft {
|
|
1576
1605
|
constructor(t, e = {}) {
|
|
1577
|
-
this.scrubbing = !1, this.emitter = new
|
|
1606
|
+
this.scrubbing = !1, this.emitter = new st(), this.externalAdvance = !1, this.abort = new AbortController(), this.sources = [], this.currentIndex = -1, this.sourceController = null, this.loadToken = 0, this.chapters = [], this.currentChapter = null, this.sceneGroupList = [], this.activeSceneGroupId = "", this.progressiveQuality = -1, this.thumbTrack = null, this.shuffleMode = !1, this.autoAdvanceEnabled = !0, this.persistKey = null, this.persistVolume = !1, this.persistAutoAdvance = !1, this.decodeRecoveries = 0, this.adManager = null, this.playedOnce = !1, this.idleTimer = null, this.peekTimer = null, this.lastRetryAt = 0, this.retryTimer = null, this.errorResumeTime = 0, this.lastPlayheadTime = 0, this.destroyed = !1, this.persistTimer = null;
|
|
1578
1607
|
const i = typeof t == "string" ? document.querySelector(t) : t;
|
|
1579
1608
|
if (!i) throw new Error(`[itube-player] mount target not found: ${String(t)}`);
|
|
1580
|
-
this.mount = i, this.options = e, this.labels = { ...
|
|
1609
|
+
this.mount = i, this.options = e, this.labels = { ...Z, ...rt(e.language), ...e.labels }, this.icons = { ...nt, ...e.icons };
|
|
1581
1610
|
const s = e.controls ?? {}, n = s.speed ?? s.settings ?? "gear";
|
|
1582
|
-
if (this.controlsOptions = { ...
|
|
1583
|
-
const
|
|
1584
|
-
this.persistKey =
|
|
1611
|
+
if (this.controlsOptions = { ...Rt, ...s, speed: n, settings: n }, this.actionsOptions = e.actions ?? {}, this.playbackRates = e.playbackRates ?? [0.5, 1, 1.5, 2], this.seekStep = e.seekStep ?? 15, this.playlistOptions = { title: "", autoAdvance: !0, loop: !1, shuffle: !1, startIndex: 0, layout: "sidebar", externalAdvance: !1, ...e.playlist }, this.shuffleMode = this.playlistOptions.shuffle, this.externalAdvance = this.playlistOptions.externalAdvance, e.persist) {
|
|
1612
|
+
const b = e.persist === !0 ? {} : e.persist;
|
|
1613
|
+
this.persistKey = b.key ?? "itube-player", this.persistVolume = b.volume !== !1, this.persistAutoAdvance = b.autoAdvance !== !1;
|
|
1585
1614
|
}
|
|
1586
1615
|
const r = this.readPersisted();
|
|
1587
1616
|
this.autoAdvanceEnabled = this.persistAutoAdvance && typeof r?.autoAdvance == "boolean" ? r.autoAdvance : this.playlistOptions.autoAdvance, this.sources = e.source ? Array.isArray(e.source) ? [...e.source] : [e.source] : [], this.container = l("div", "imp-player", { tabindex: "0" }), e.className && this.container.classList.add(e.className);
|
|
1588
1617
|
const a = e.styling;
|
|
1589
1618
|
if (a?.themeColor && this.container.style.setProperty("--imp-accent", a.themeColor), a?.likeColor && this.container.style.setProperty("--imp-like", a.likeColor), a?.dislikeColor && this.container.style.setProperty("--imp-dislike", a.dislikeColor), a?.fontFamily && this.container.style.setProperty("--imp-font", a.fontFamily), a?.borderRadius !== void 0) {
|
|
1590
|
-
const
|
|
1591
|
-
this.container.style.setProperty("--imp-radius",
|
|
1619
|
+
const b = typeof a.borderRadius == "number" ? `${a.borderRadius}px` : a.borderRadius;
|
|
1620
|
+
this.container.style.setProperty("--imp-radius", b);
|
|
1592
1621
|
}
|
|
1593
1622
|
a?.playButtonStyle === "inverted" && this.container.classList.add("imp-player--play-inverted"), this.video = l("video", "imp-video"), e.playsInline !== !1 && this.video.setAttribute("playsinline", ""), e.crossOrigin !== void 0 && (this.video.crossOrigin = e.crossOrigin), this.video.preload = "metadata", e.loop && (this.video.loop = !0);
|
|
1594
1623
|
const h = this.persistVolume ? r : null;
|
|
1595
|
-
this.video.volume =
|
|
1624
|
+
this.video.volume = x(h?.volume ?? e.volume ?? 1, 0, 1), (h?.muted ?? e.muted) && (this.video.muted = !0);
|
|
1596
1625
|
const c = l("div", "imp-layer");
|
|
1597
|
-
this.spinner = l("div", "imp-spinner"), this.spinner.hidden = !0, this.errorBox = l("div", "imp-error"), this.errorBox.hidden = !0, this.
|
|
1626
|
+
this.spinner = l("div", "imp-spinner"), this.spinner.hidden = !0, this.errorBox = l("div", "imp-error"), this.errorBox.hidden = !0, this.errorText = l("div", "imp-error__text"), this.retryBtn = l("button", "imp-error__retry", { type: "button" });
|
|
1627
|
+
const u = l("span", "imp-error__retry-label");
|
|
1628
|
+
u.textContent = this.labels.tryAgain, this.retryBtn.append(u, l("span", "imp-error__retry-spinner")), this.retryBtn.addEventListener("click", () => this.retry()), this.errorNextBtn = l("button", "imp-error__next", { type: "button" }), this.errorNextBtn.textContent = this.labels.nextVideo, this.errorNextBtn.addEventListener("click", () => {
|
|
1629
|
+
this.clearError(), this.next();
|
|
1630
|
+
});
|
|
1631
|
+
const m = l("div", "imp-error__actions");
|
|
1632
|
+
m.append(this.retryBtn, this.errorNextBtn), this.errorBox.append(this.errorText, m), this.pauseScreen = new St(this.labels), this.poster = new Tt(this), this.related = new Bt(this), this.related.setOptions(e.related), this.upNext = new Et(this), this.controls = new Lt(this), this.playlistPanel = new Mt(this, this.playlistOptions.layout, this.playlistOptions.title || void 0), this.scenesPanel = new Ct(this, e.scenes?.layout ?? "bottom");
|
|
1598
1633
|
const p = l("div", "imp-layer__middle");
|
|
1599
1634
|
p.append(this.spinner, this.errorBox, this.controls.center);
|
|
1600
|
-
const
|
|
1601
|
-
|
|
1602
|
-
const
|
|
1603
|
-
|
|
1635
|
+
const v = l("div", "imp-layer__bottom");
|
|
1636
|
+
v.append(this.controls.root), c.append(this.pauseScreen.root, this.related.root, this.upNext.root, p, v), this.container.append(this.video, c, this.poster.root, this.playlistPanel.root, this.scenesPanel.root), this.mount.append(this.container), e.pauseScreen instanceof HTMLElement ? this.pauseScreen.setCustomContent(e.pauseScreen) : typeof e.pauseScreen == "function" ? this.pauseScreen.setCustomContent(e.pauseScreen(this)) : e.pauseScreen && typeof e.pauseScreen == "object" && this.pauseScreen.setVisibility(e.pauseScreen);
|
|
1637
|
+
const f = e.adConfig ?? e.ads;
|
|
1638
|
+
f && f.adList.length > 0 && (this.adManager = new vt(
|
|
1604
1639
|
{ container: this.container, contentVideo: this.video, emitter: this.emitter, labels: this.labels, closeIcon: this.icons.close },
|
|
1605
|
-
|
|
1606
|
-
)), this.emitter.on("error", ({
|
|
1607
|
-
|
|
1608
|
-
|
|
1640
|
+
f
|
|
1641
|
+
)), this.emitter.on("error", ({ fatal: b }) => {
|
|
1642
|
+
if (!b) return;
|
|
1643
|
+
const d = this.lastPlayheadTime || this.video.currentTime;
|
|
1644
|
+
Number.isFinite(d) && d > 0 && (this.errorResumeTime = d), this.errorText.textContent = this.labels.videoNotFound, this.errorNextBtn.hidden = !this.hasNext, this.errorBox.hidden = !1, this.spinner.hidden = !0, this.poster.hide(), this.container.classList.add("imp-player--error");
|
|
1645
|
+
}), Pt(), this.bindVideoEvents(), this.bindIdleHide(), e.keyboard !== !1 && this.bindKeyboard(), this.video.addEventListener("pointerup", (b) => {
|
|
1609
1646
|
if (!(this.adPlaying || !this.playedOnce)) {
|
|
1610
|
-
if (
|
|
1647
|
+
if (b.pointerType === "mouse") {
|
|
1611
1648
|
this.togglePlay();
|
|
1612
1649
|
return;
|
|
1613
1650
|
}
|
|
1614
1651
|
this.container.classList.contains("imp-player--idle") ? (this.showControlsNow(), this.scheduleIdle()) : this.video.paused || this.container.classList.add("imp-player--idle");
|
|
1615
1652
|
}
|
|
1616
|
-
}, { signal: this.abort.signal }), this.pauseScreen.root.addEventListener("click", (
|
|
1617
|
-
this.pauseScreen.hasCustom ||
|
|
1618
|
-
}, { signal: this.abort.signal }), this.sources.length > 0 && this.loadItem(
|
|
1653
|
+
}, { signal: this.abort.signal }), this.pauseScreen.root.addEventListener("click", (b) => {
|
|
1654
|
+
this.pauseScreen.hasCustom || b.target === this.pauseScreen.root && this.togglePlay();
|
|
1655
|
+
}, { signal: this.abort.signal }), this.sources.length > 0 && this.loadItem(x(this.playlistOptions.startIndex, 0, this.sources.length - 1), !!e.autoplay), queueMicrotask(() => {
|
|
1656
|
+
this.destroyed || this.emitter.emit("ready", { player: this });
|
|
1657
|
+
});
|
|
1619
1658
|
}
|
|
1620
1659
|
// === events ===========================================================
|
|
1621
1660
|
on(t, e) {
|
|
@@ -1654,8 +1693,22 @@ class Rt {
|
|
|
1654
1693
|
get adPlaying() {
|
|
1655
1694
|
return this.adManager?.adPlaying ?? !1;
|
|
1656
1695
|
}
|
|
1657
|
-
async play() {
|
|
1658
|
-
this.destroyed || this.adPlaying
|
|
1696
|
+
async play(t = !1) {
|
|
1697
|
+
if (!(this.destroyed || this.adPlaying) && !(this.adManager && !t && (await this.adManager.playPreRoll(), this.destroyed || !this.video.paused)))
|
|
1698
|
+
try {
|
|
1699
|
+
await this.video.play();
|
|
1700
|
+
} catch (e) {
|
|
1701
|
+
const i = e?.name;
|
|
1702
|
+
if (i === "NotSupportedError" && this.video.readyState === 0) {
|
|
1703
|
+
const s = this.loadToken;
|
|
1704
|
+
this.video.addEventListener("loadedmetadata", () => {
|
|
1705
|
+
s === this.loadToken && this.video.play().catch(() => {
|
|
1706
|
+
});
|
|
1707
|
+
}, { once: !0, signal: this.abort.signal });
|
|
1708
|
+
return;
|
|
1709
|
+
}
|
|
1710
|
+
i !== "AbortError" && !this.playedOnce && this.poster.show();
|
|
1711
|
+
}
|
|
1659
1712
|
}
|
|
1660
1713
|
pause() {
|
|
1661
1714
|
this.adPlaying || this.video.pause();
|
|
@@ -1663,8 +1716,34 @@ class Rt {
|
|
|
1663
1716
|
togglePlay() {
|
|
1664
1717
|
this.video.paused || this.video.ended ? this.play() : this.pause();
|
|
1665
1718
|
}
|
|
1719
|
+
/**
|
|
1720
|
+
* Clear a fatal-error overlay and reload the current source, resuming from
|
|
1721
|
+
* where playback broke. Rate-limited by `options.retryThrottle` (default 5s):
|
|
1722
|
+
* the button is disabled for that window after each press.
|
|
1723
|
+
*/
|
|
1724
|
+
retry() {
|
|
1725
|
+
const t = this.options.retryThrottle ?? 5e3, e = Date.now();
|
|
1726
|
+
if (e - this.lastRetryAt < t) return;
|
|
1727
|
+
this.lastRetryAt = e, this.retryBtn.disabled = !0, this.retryBtn.classList.add("imp-error__retry--loading"), this.retryTimer && clearTimeout(this.retryTimer), this.retryTimer = setTimeout(() => {
|
|
1728
|
+
this.destroyed || (this.retryBtn.disabled = !1, this.retryBtn.classList.remove("imp-error__retry--loading"));
|
|
1729
|
+
}, t);
|
|
1730
|
+
const i = this.errorResumeTime;
|
|
1731
|
+
if (this.loadItem(this.currentIndex, !0, !0), this.errorResumeTime = i, i > 0) {
|
|
1732
|
+
const s = this.loadToken;
|
|
1733
|
+
this.video.addEventListener("loadedmetadata", () => {
|
|
1734
|
+
if (s === this.loadToken)
|
|
1735
|
+
try {
|
|
1736
|
+
this.video.currentTime = i;
|
|
1737
|
+
} catch {
|
|
1738
|
+
}
|
|
1739
|
+
}, { once: !0, signal: this.abort.signal });
|
|
1740
|
+
}
|
|
1741
|
+
}
|
|
1742
|
+
clearError() {
|
|
1743
|
+
this.errorBox.hidden = !0, this.container.classList.remove("imp-player--error");
|
|
1744
|
+
}
|
|
1666
1745
|
seek(t) {
|
|
1667
|
-
Number.isFinite(this.video.duration) && (this.video.currentTime =
|
|
1746
|
+
Number.isFinite(this.video.duration) && (this.video.currentTime = x(t, 0, this.video.duration));
|
|
1668
1747
|
}
|
|
1669
1748
|
/** Relative seek, e.g. `skip(-10)`. */
|
|
1670
1749
|
skip(t) {
|
|
@@ -1678,7 +1757,7 @@ class Rt {
|
|
|
1678
1757
|
return this.video.muted;
|
|
1679
1758
|
}
|
|
1680
1759
|
setVolume(t) {
|
|
1681
|
-
this.video.volume =
|
|
1760
|
+
this.video.volume = x(t, 0, 1), t > 0 && (this.video.muted = !1);
|
|
1682
1761
|
}
|
|
1683
1762
|
setMuted(t) {
|
|
1684
1763
|
this.video.muted = t;
|
|
@@ -1697,6 +1776,12 @@ class Rt {
|
|
|
1697
1776
|
return null;
|
|
1698
1777
|
}
|
|
1699
1778
|
}
|
|
1779
|
+
/** Debounced persistState — for high-frequency triggers (volume drag). */
|
|
1780
|
+
schedulePersist() {
|
|
1781
|
+
this.persistTimer && clearTimeout(this.persistTimer), this.persistTimer = setTimeout(() => {
|
|
1782
|
+
this.persistTimer = null, this.destroyed || this.persistState();
|
|
1783
|
+
}, 300);
|
|
1784
|
+
}
|
|
1700
1785
|
/** Write the enabled prefs to localStorage. No-op when persistence is off. */
|
|
1701
1786
|
persistState() {
|
|
1702
1787
|
if (this.persistKey)
|
|
@@ -1727,19 +1812,29 @@ class Rt {
|
|
|
1727
1812
|
setQuality(t) {
|
|
1728
1813
|
if (this.sourceController?.kind === "hls") {
|
|
1729
1814
|
this.sourceController.setLevel(t);
|
|
1730
|
-
const
|
|
1731
|
-
this.emitter.emit("qualitychange", { label:
|
|
1815
|
+
const r = t === -1 ? this.labels.qualityAuto : this.sourceController.levels.find((a) => a.index === t)?.label ?? String(t);
|
|
1816
|
+
this.emitter.emit("qualitychange", { label: r });
|
|
1732
1817
|
return;
|
|
1733
1818
|
}
|
|
1734
1819
|
const e = this.source?.qualities;
|
|
1735
1820
|
if (!e || !e[t] || t === this.progressiveQuality) return;
|
|
1736
1821
|
const i = this.video.currentTime, s = !this.video.paused && !this.video.ended;
|
|
1737
|
-
this.progressiveQuality = t, this.video.src = e[t].src
|
|
1738
|
-
|
|
1822
|
+
this.progressiveQuality = t, this.video.src = e[t].src;
|
|
1823
|
+
const n = this.loadToken;
|
|
1824
|
+
this.video.addEventListener("loadedmetadata", () => {
|
|
1825
|
+
if (n === this.loadToken) {
|
|
1826
|
+
try {
|
|
1827
|
+
this.video.currentTime = i;
|
|
1828
|
+
} catch {
|
|
1829
|
+
}
|
|
1830
|
+
s && this.video.play().catch(() => {
|
|
1831
|
+
});
|
|
1832
|
+
}
|
|
1833
|
+
}, { once: !0, signal: this.abort.signal }), this.emitter.emit("qualitychange", { label: e[t].label ?? String(e[t].quality ?? t) });
|
|
1739
1834
|
}
|
|
1740
1835
|
// === subtitles ========================================================
|
|
1741
1836
|
get subtitleTracks() {
|
|
1742
|
-
return
|
|
1837
|
+
return U(this.source?.subtitles);
|
|
1743
1838
|
}
|
|
1744
1839
|
get activeSubtitle() {
|
|
1745
1840
|
const t = this.video.textTracks;
|
|
@@ -1773,13 +1868,13 @@ class Rt {
|
|
|
1773
1868
|
return t < this.sources.length ? this.sources[t] : this.playlistOptions.loop ? this.sources[0] ?? null : null;
|
|
1774
1869
|
}
|
|
1775
1870
|
get hasPlaylist() {
|
|
1776
|
-
return this.sources.length > 1;
|
|
1871
|
+
return this.sources.length > 1 || this.externalAdvance;
|
|
1777
1872
|
}
|
|
1778
1873
|
get hasNext() {
|
|
1779
|
-
return this.shuffleMode || this.playlistOptions.loop ? this.sources.length > 1 : this.currentIndex < this.sources.length - 1;
|
|
1874
|
+
return this.externalAdvance ? !0 : this.shuffleMode || this.playlistOptions.loop ? this.sources.length > 1 : this.currentIndex < this.sources.length - 1;
|
|
1780
1875
|
}
|
|
1781
1876
|
get hasPrevious() {
|
|
1782
|
-
return this.playlistOptions.loop ? this.sources.length > 1 : this.currentIndex > 0;
|
|
1877
|
+
return this.externalAdvance ? !0 : this.playlistOptions.loop ? this.sources.length > 1 : this.currentIndex > 0;
|
|
1783
1878
|
}
|
|
1784
1879
|
/** Shuffle mode: `next()` and auto-advance pick a random item. */
|
|
1785
1880
|
get shuffle() {
|
|
@@ -1795,8 +1890,18 @@ class Rt {
|
|
|
1795
1890
|
setRepeat(t) {
|
|
1796
1891
|
this.playlistOptions.loop = t;
|
|
1797
1892
|
}
|
|
1893
|
+
/** External mode: emit the intent instead of switching. Returns true when handled. */
|
|
1894
|
+
emitAdvanceRequest(t, e) {
|
|
1895
|
+
if (!this.externalAdvance) return !1;
|
|
1896
|
+
const i = e !== null && e >= 0 && e < this.sources.length;
|
|
1897
|
+
return this.emitter.emit("advancerequest", {
|
|
1898
|
+
direction: t,
|
|
1899
|
+
index: i ? e : null,
|
|
1900
|
+
source: i ? this.sources[e] : null
|
|
1901
|
+
}), !0;
|
|
1902
|
+
}
|
|
1798
1903
|
next() {
|
|
1799
|
-
if (this.hasNext) {
|
|
1904
|
+
if (this.hasNext && !this.emitAdvanceRequest("next", this.sources.length > 1 ? (this.currentIndex + 1) % this.sources.length : null)) {
|
|
1800
1905
|
if (this.shuffleMode && this.sources.length > 1) {
|
|
1801
1906
|
let t = this.currentIndex;
|
|
1802
1907
|
for (; t === this.currentIndex; ) t = Math.floor(Math.random() * this.sources.length);
|
|
@@ -1807,11 +1912,11 @@ class Rt {
|
|
|
1807
1912
|
}
|
|
1808
1913
|
}
|
|
1809
1914
|
previous() {
|
|
1810
|
-
this.hasPrevious && this.playItem((this.currentIndex - 1 + this.sources.length) % this.sources.length);
|
|
1915
|
+
this.hasPrevious && (this.emitAdvanceRequest("previous", this.sources.length > 1 ? (this.currentIndex - 1 + this.sources.length) % this.sources.length : null) || this.playItem((this.currentIndex - 1 + this.sources.length) % this.sources.length));
|
|
1811
1916
|
}
|
|
1812
|
-
/** Jump to a playlist item and start playback. */
|
|
1917
|
+
/** Jump to a playlist item and start playback (external mode: emits the intent instead). */
|
|
1813
1918
|
playItem(t) {
|
|
1814
|
-
t < 0 || t >= this.sources.length || this.loadItem(t, !0).then(() => {
|
|
1919
|
+
t < 0 || t >= this.sources.length || t !== this.currentIndex && this.emitAdvanceRequest("select", t) || this.loadItem(t, !0).then(() => {
|
|
1815
1920
|
this.emitter.emit("playlistitemchange", { source: this.sources[t], index: t });
|
|
1816
1921
|
});
|
|
1817
1922
|
}
|
|
@@ -1830,17 +1935,23 @@ class Rt {
|
|
|
1830
1935
|
* to one item; an array installs a new playlist.
|
|
1831
1936
|
*/
|
|
1832
1937
|
load(t, e = 0) {
|
|
1833
|
-
this.sources = Array.isArray(t) ? [...t] : [t], this.playlistPanel.rebuild(), this.loadItem(
|
|
1938
|
+
this.sources = Array.isArray(t) ? [...t] : [t], this.playlistPanel.rebuild(), this.loadItem(x(e, 0, this.sources.length - 1), !1);
|
|
1834
1939
|
}
|
|
1835
1940
|
// === fullscreen / pip =================================================
|
|
1836
1941
|
get isFullscreen() {
|
|
1837
1942
|
return document.fullscreenElement === this.container;
|
|
1838
1943
|
}
|
|
1839
1944
|
async toggleFullscreen() {
|
|
1840
|
-
|
|
1945
|
+
try {
|
|
1946
|
+
this.isFullscreen ? await document.exitFullscreen() : this.container.requestFullscreen ? await this.container.requestFullscreen() : this.video.webkitEnterFullscreen?.();
|
|
1947
|
+
} catch {
|
|
1948
|
+
}
|
|
1841
1949
|
}
|
|
1842
1950
|
async togglePip() {
|
|
1843
|
-
|
|
1951
|
+
try {
|
|
1952
|
+
document.pictureInPictureElement === this.video ? await document.exitPictureInPicture() : await this.video.requestPictureInPicture();
|
|
1953
|
+
} catch {
|
|
1954
|
+
}
|
|
1844
1955
|
}
|
|
1845
1956
|
// === chapters =========================================================
|
|
1846
1957
|
/** Normalized chapters of the current source (after metadata is known). */
|
|
@@ -1865,7 +1976,7 @@ class Rt {
|
|
|
1865
1976
|
}
|
|
1866
1977
|
/** Normalize the active group's scenes into `chapters` and refresh the UI. */
|
|
1867
1978
|
applyActiveSceneGroup() {
|
|
1868
|
-
this.chapters =
|
|
1979
|
+
this.chapters = Q(this.activeSceneType?.scenes ?? [], this.video.duration), this.currentChapter = null, this.controls.progress.setChapters(this.chapters), this.controls.syncFeatureButtons(), this.scenesPanel.visible && this.scenesPanel.rebuild();
|
|
1869
1980
|
}
|
|
1870
1981
|
// === actions ==========================================================
|
|
1871
1982
|
/**
|
|
@@ -1902,70 +2013,68 @@ class Rt {
|
|
|
1902
2013
|
}
|
|
1903
2014
|
// === teardown =========================================================
|
|
1904
2015
|
destroy() {
|
|
1905
|
-
this.destroyed || (this.destroyed = !0, this.loadToken++, this.adManager?.destroy(), this.controls.destroy(), this.sourceController?.destroy(), this.abort.abort(), this.idleTimer && clearTimeout(this.idleTimer), this.peekTimer && clearTimeout(this.peekTimer), this.container.remove(), this.emitter.emit("destroy", void 0), this.emitter.removeAll());
|
|
2016
|
+
this.destroyed || (this.destroyed = !0, this.loadToken++, this.adManager?.destroy(), this.controls.destroy(), this.sourceController?.destroy(), this.abort.abort(), this.idleTimer && clearTimeout(this.idleTimer), this.peekTimer && clearTimeout(this.peekTimer), this.retryTimer && clearTimeout(this.retryTimer), this.persistTimer && (clearTimeout(this.persistTimer), this.persistTimer = null, this.persistState()), this.container.remove(), At(), this.emitter.emit("destroy", void 0), this.emitter.removeAll());
|
|
1906
2017
|
}
|
|
1907
2018
|
// === internals ========================================================
|
|
1908
|
-
async loadItem(t, e) {
|
|
1909
|
-
const
|
|
1910
|
-
if (!
|
|
1911
|
-
this.currentIndex = t, this.sourceController?.destroy(), this.sourceController = null, this.chapters = [], this.currentChapter = null, this.sceneGroupList = [], this.activeSceneGroupId = "", this.progressiveQuality = -1, this.playedOnce = !1, this.endPeek();
|
|
1912
|
-
for (const
|
|
1913
|
-
this.adManager?.resetForNewSource(), this.related.hide(), this.upNext.hide(), this.pauseScreen.hide(), this.scenesPanel.hide(), this.thumbTrack = null, this.
|
|
1914
|
-
for (const
|
|
1915
|
-
const
|
|
2019
|
+
async loadItem(t, e, i = !1) {
|
|
2020
|
+
const s = ++this.loadToken, n = this.sources[t];
|
|
2021
|
+
if (!n) return;
|
|
2022
|
+
this.currentIndex = t, this.sourceController?.destroy(), this.sourceController = null, this.chapters = [], this.currentChapter = null, this.sceneGroupList = [], this.activeSceneGroupId = "", this.progressiveQuality = -1, this.playedOnce = !1, this.lastPlayheadTime = 0, this.errorResumeTime = 0, this.endPeek();
|
|
2023
|
+
for (const p of [...this.video.querySelectorAll("track")]) p.remove();
|
|
2024
|
+
this.adManager?.resetForNewSource(), this.related.hide(), this.upNext.hide(), this.pauseScreen.hide(), this.scenesPanel.hide(), this.thumbTrack = null, this.decodeRecoveries = 0, this.video.poster = n.poster ?? "", this.poster.setSource(n), this.pauseScreen.setSource(n), this.controls.progress.setChapters([]), this.controls.progress.setThumbnails(null), this.controls.progress.setHeatmap([]), e ? this.poster.hide() : this.poster.show(), this.playlistPanel.rebuild();
|
|
2025
|
+
for (const p of U(n.subtitles)) {
|
|
2026
|
+
const v = l("track", "", {
|
|
1916
2027
|
kind: "subtitles",
|
|
1917
|
-
src:
|
|
1918
|
-
label:
|
|
1919
|
-
...
|
|
2028
|
+
src: p.src,
|
|
2029
|
+
label: p.label,
|
|
2030
|
+
...p.srclang ? { srclang: p.srclang } : {}
|
|
1920
2031
|
});
|
|
1921
|
-
|
|
2032
|
+
p.default && v.setAttribute("default", ""), this.video.append(v);
|
|
1922
2033
|
}
|
|
1923
|
-
let
|
|
1924
|
-
if (
|
|
1925
|
-
const
|
|
1926
|
-
this.progressiveQuality =
|
|
2034
|
+
let r = n.src, a = n.type;
|
|
2035
|
+
if (n.qualities && n.qualities.length > 0) {
|
|
2036
|
+
const p = Math.max(0, n.qualities.findIndex((v) => v.src === n.src));
|
|
2037
|
+
this.progressiveQuality = p, r = n.qualities[p].src, a = n.qualities[p].type ?? a;
|
|
1927
2038
|
}
|
|
1928
2039
|
this.video.preload = this.adManager?.hasPendingPreRoll ? "auto" : "metadata";
|
|
1929
|
-
const
|
|
2040
|
+
const h = await bt(this.video, r, a, {
|
|
1930
2041
|
onLevels: () => {
|
|
1931
|
-
|
|
2042
|
+
s === this.loadToken && this.controls.syncFeatureButtons();
|
|
1932
2043
|
},
|
|
1933
|
-
onLevelSwitch: (
|
|
1934
|
-
onError: (
|
|
2044
|
+
onLevelSwitch: (p) => this.emitter.emit("qualitychange", { label: p }),
|
|
2045
|
+
onError: (p, v) => this.emitter.emit("error", { message: p, cause: v, fatal: !0 })
|
|
1935
2046
|
});
|
|
1936
|
-
if (
|
|
1937
|
-
|
|
2047
|
+
if (s !== this.loadToken) {
|
|
2048
|
+
h.destroy();
|
|
1938
2049
|
return;
|
|
1939
2050
|
}
|
|
1940
|
-
if (this.sourceController =
|
|
1941
|
-
|
|
1942
|
-
}).catch((
|
|
1943
|
-
this.sceneGroupList =
|
|
1944
|
-
const
|
|
1945
|
-
|
|
2051
|
+
if (this.sourceController = h, this.emitter.emit("sourcechange", { source: n, index: t }), n.thumbnails && D.load(n.thumbnails).then((p) => {
|
|
2052
|
+
s === this.loadToken && (this.thumbTrack = p, this.controls.progress.setThumbnails(p), this.scenesPanel.visible && this.scenesPanel.rebuild());
|
|
2053
|
+
}).catch((p) => this.emitter.emit("error", { message: "Failed to load thumbnails track", cause: p })), n.sceneGroups && n.sceneGroups.length > 0) {
|
|
2054
|
+
this.sceneGroupList = n.sceneGroups, this.activeSceneGroupId = n.sceneGroups[0].id;
|
|
2055
|
+
const p = () => {
|
|
2056
|
+
s === this.loadToken && this.applyActiveSceneGroup();
|
|
1946
2057
|
};
|
|
1947
|
-
Number.isFinite(this.video.duration) && this.video.duration > 0 ?
|
|
1948
|
-
} else if (
|
|
1949
|
-
const
|
|
1950
|
-
const
|
|
1951
|
-
|
|
2058
|
+
Number.isFinite(this.video.duration) && this.video.duration > 0 ? p() : this.video.addEventListener("loadedmetadata", p, { once: !0, signal: this.abort.signal });
|
|
2059
|
+
} else if (n.chapters) {
|
|
2060
|
+
const p = (v) => {
|
|
2061
|
+
const f = () => {
|
|
2062
|
+
s === this.loadToken && (this.chapters = Q(v, this.video.duration), this.controls.progress.setChapters(this.chapters), this.controls.syncFeatureButtons(), this.scenesPanel.visible && this.scenesPanel.rebuild());
|
|
1952
2063
|
};
|
|
1953
|
-
Number.isFinite(this.video.duration) && this.video.duration > 0 ?
|
|
2064
|
+
Number.isFinite(this.video.duration) && this.video.duration > 0 ? f() : this.video.addEventListener("loadedmetadata", f, { once: !0, signal: this.abort.signal });
|
|
1954
2065
|
};
|
|
1955
|
-
typeof
|
|
2066
|
+
typeof n.chapters == "string" ? ft(n.chapters).then((v) => p(v)).catch((v) => this.emitter.emit("error", { message: "Failed to load chapters track", cause: v })) : p(n.chapters);
|
|
1956
2067
|
}
|
|
1957
|
-
const
|
|
1958
|
-
if (
|
|
1959
|
-
const
|
|
1960
|
-
if (
|
|
1961
|
-
const
|
|
1962
|
-
this.controls.progress.setHeatmap(
|
|
2068
|
+
const c = n.heatmap, u = c && !Array.isArray(c), m = u ? c.values.length > 0 : !!(c && c.length > 0);
|
|
2069
|
+
if (c && m && this.controlsOptions.heatmap) {
|
|
2070
|
+
const p = () => {
|
|
2071
|
+
if (s !== this.loadToken) return;
|
|
2072
|
+
const v = u ? ht(c.values, c.mode) : at(c, this.video.duration);
|
|
2073
|
+
this.controls.progress.setHeatmap(v, u ? c.smoothing ?? 1 : 1);
|
|
1963
2074
|
};
|
|
1964
|
-
|
|
2075
|
+
u || Number.isFinite(this.video.duration) && this.video.duration > 0 ? p() : this.video.addEventListener("loadedmetadata", p, { once: !0, signal: this.abort.signal });
|
|
1965
2076
|
}
|
|
1966
|
-
e && this.play()
|
|
1967
|
-
i === this.loadToken && this.poster.show();
|
|
1968
|
-
});
|
|
2077
|
+
e && this.play(i);
|
|
1969
2078
|
}
|
|
1970
2079
|
bindVideoEvents() {
|
|
1971
2080
|
const { signal: t } = this.abort, e = this.video;
|
|
@@ -1976,19 +2085,19 @@ class Rt {
|
|
|
1976
2085
|
}, { signal: t }), e.addEventListener("ended", () => {
|
|
1977
2086
|
this.handleEnded();
|
|
1978
2087
|
}, { signal: t }), e.addEventListener("timeupdate", () => {
|
|
1979
|
-
this.emitter.emit("timeupdate", { currentTime: e.currentTime, duration: e.duration || 0 }), this.adManager?.checkMidRolls(e.currentTime);
|
|
1980
|
-
const i =
|
|
2088
|
+
!this.adPlaying && e.currentTime > 0 && (this.lastPlayheadTime = e.currentTime), this.emitter.emit("timeupdate", { currentTime: e.currentTime, duration: e.duration || 0 }), this.adManager?.checkMidRolls(e.currentTime);
|
|
2089
|
+
const i = Y(this.chapters, e.currentTime);
|
|
1981
2090
|
i !== this.currentChapter && (this.currentChapter = i, this.emitter.emit("chapterchange", { chapter: i }));
|
|
1982
2091
|
}, { signal: t }), e.addEventListener("progress", () => {
|
|
1983
2092
|
this.emitter.emit("progress", { buffered: this.bufferedEnd });
|
|
1984
2093
|
}, { signal: t }), e.addEventListener("volumechange", () => {
|
|
1985
|
-
this.emitter.emit("volumechange", { volume: e.volume, muted: e.muted }), this.persistVolume && this.
|
|
2094
|
+
this.emitter.emit("volumechange", { volume: e.volume, muted: e.muted }), this.persistVolume && this.schedulePersist();
|
|
1986
2095
|
}, { signal: t }), e.addEventListener("seeking", () => this.emitter.emit("seeking", { currentTime: e.currentTime }), { signal: t }), e.addEventListener("seeked", () => this.emitter.emit("seeked", { currentTime: e.currentTime }), { signal: t }), e.addEventListener("waiting", () => {
|
|
1987
2096
|
this.spinner.hidden = !1;
|
|
1988
2097
|
}, { signal: t });
|
|
1989
2098
|
for (const i of ["playing", "canplay", "seeked"])
|
|
1990
2099
|
e.addEventListener(i, () => {
|
|
1991
|
-
this.spinner.hidden = !0, this.
|
|
2100
|
+
this.spinner.hidden = !0, this.decodeRecoveries = 0, i === "playing" && this.clearError();
|
|
1992
2101
|
}, { signal: t });
|
|
1993
2102
|
e.addEventListener("error", () => {
|
|
1994
2103
|
const i = e.error;
|
|
@@ -2008,14 +2117,19 @@ class Rt {
|
|
|
2008
2117
|
e.readyState >= 1 ? a() : e.addEventListener("loadedmetadata", a, { once: !0, signal: this.abort.signal });
|
|
2009
2118
|
return;
|
|
2010
2119
|
}
|
|
2011
|
-
this.emitter.emit("error", { message: i.message || `Media error (code ${i.code})`, cause: i });
|
|
2120
|
+
this.emitter.emit("error", { message: i.message || `Media error (code ${i.code})`, cause: i, fatal: !0 });
|
|
2012
2121
|
}, { signal: t }), e.addEventListener("enterpictureinpicture", () => this.emitter.emit("pipchange", { active: !0 }), { signal: t }), e.addEventListener("leavepictureinpicture", () => this.emitter.emit("pipchange", { active: !1 }), { signal: t }), document.addEventListener("fullscreenchange", () => {
|
|
2013
2122
|
this.emitter.emit("fullscreenchange", { active: this.isFullscreen }), this.container.classList.toggle("imp-player--fullscreen", this.isFullscreen);
|
|
2123
|
+
}, { signal: t }), e.addEventListener("webkitbeginfullscreen", () => {
|
|
2124
|
+
this.emitter.emit("fullscreenchange", { active: !0 }), this.container.classList.add("imp-player--fullscreen");
|
|
2125
|
+
}, { signal: t }), e.addEventListener("webkitendfullscreen", () => {
|
|
2126
|
+
this.emitter.emit("fullscreenchange", { active: !1 }), this.container.classList.remove("imp-player--fullscreen");
|
|
2014
2127
|
}, { signal: t });
|
|
2015
2128
|
}
|
|
2016
2129
|
async handleEnded() {
|
|
2017
2130
|
if (this.emitter.emit("ended", void 0), this.showControlsNow(), !(this.adManager && (await this.adManager.playPostRoll(), this.destroyed))) {
|
|
2018
2131
|
if (this.autoAdvanceEnabled && this.hasNext) {
|
|
2132
|
+
if (this.emitAdvanceRequest("ended", this.sources.length > 1 ? (this.currentIndex + 1) % this.sources.length : null)) return;
|
|
2019
2133
|
this.next();
|
|
2020
2134
|
return;
|
|
2021
2135
|
}
|
|
@@ -2118,22 +2232,22 @@ class Rt {
|
|
|
2118
2232
|
}
|
|
2119
2233
|
}
|
|
2120
2234
|
export {
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2235
|
+
st as Emitter,
|
|
2236
|
+
Ft as Player,
|
|
2237
|
+
D as ThumbnailTrack,
|
|
2238
|
+
at as buildHeatmapValues,
|
|
2239
|
+
Y as chapterAt,
|
|
2240
|
+
nt as defaultIcons,
|
|
2241
|
+
Z as defaultLabels,
|
|
2242
|
+
_ as formatTime,
|
|
2243
|
+
rt as getLocale,
|
|
2244
|
+
ct as heatmapPath,
|
|
2245
|
+
yt as isHlsSource,
|
|
2246
|
+
ft as loadChaptersVtt,
|
|
2247
|
+
Q as normalizeChapters,
|
|
2248
|
+
It as registerLocale,
|
|
2249
|
+
$t as registerLocales,
|
|
2250
|
+
qt as registeredLanguages,
|
|
2251
|
+
dt as resolveVast
|
|
2138
2252
|
};
|
|
2139
2253
|
//# sourceMappingURL=core.js.map
|