itube-modern-player 0.7.0 → 0.7.2
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 +24 -3
- package/dist/core.cjs +1 -4
- package/dist/core.cjs.map +1 -1
- package/dist/core.js +453 -495
- package/dist/core.js.map +1 -1
- package/dist/dom-Bq7EQenh.cjs +5 -0
- package/dist/dom-Bq7EQenh.cjs.map +1 -0
- package/dist/dom-DrpWbY0y.js +87 -0
- package/dist/dom-DrpWbY0y.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +20 -19
- package/dist/index.js.map +1 -1
- package/dist/itube-modern-player.iife.js +2 -2
- package/dist/itube-modern-player.iife.js.map +1 -1
- package/dist/lazy.cjs +1 -1
- package/dist/lazy.cjs.map +1 -1
- package/dist/lazy.d.ts +5 -1
- package/dist/lazy.js +58 -42
- package/dist/lazy.js.map +1 -1
- package/dist/player.d.ts +12 -0
- package/dist/types.d.ts +7 -0
- package/package.json +1 -1
package/dist/core.js
CHANGED
|
@@ -1,79 +1,6 @@
|
|
|
1
|
-
import { d as
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
if (t && (i.className = t), e)
|
|
5
|
-
for (const [s, n] of Object.entries(e)) i.setAttribute(s, n);
|
|
6
|
-
return i;
|
|
7
|
-
}
|
|
8
|
-
function T(o, t) {
|
|
9
|
-
if (o.textContent = "", typeof t == "object") {
|
|
10
|
-
"url" in t ? o.append(l("img", "imp-icon-img", { src: t.url, alt: "" })) : o.innerHTML = t.svg;
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
13
|
-
/^\s*</.test(t) ? o.innerHTML = t : o.append(l("img", "imp-icon-img", { src: t, alt: "" }));
|
|
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
|
-
}
|
|
19
|
-
function g(o, t, e) {
|
|
20
|
-
const i = l("button", `imp-btn ${o}`, { type: "button", "aria-label": t, title: t });
|
|
21
|
-
return T(i, e), i;
|
|
22
|
-
}
|
|
23
|
-
function j(o, t) {
|
|
24
|
-
const e = l("div", `${t}__meta`);
|
|
25
|
-
return o.forEach((i, s) => {
|
|
26
|
-
s > 0 && e.append(document.createTextNode(" "));
|
|
27
|
-
const n = typeof i == "string" ? i : i.text, r = typeof i == "string" ? void 0 : i.icon, a = l("span", `${t}__meta-chunk`);
|
|
28
|
-
if (r) {
|
|
29
|
-
const h = l("span", `${t}__meta-icon`);
|
|
30
|
-
T(h, r), a.append(h);
|
|
31
|
-
}
|
|
32
|
-
a.append(document.createTextNode(n)), e.append(a);
|
|
33
|
-
}), e;
|
|
34
|
-
}
|
|
35
|
-
function I(o, t, e) {
|
|
36
|
-
T(o, t), e !== void 0 && (o.setAttribute("aria-label", e), o.setAttribute("title", e));
|
|
37
|
-
}
|
|
38
|
-
function x(o, t, e) {
|
|
39
|
-
return Math.min(e, Math.max(t, o));
|
|
40
|
-
}
|
|
41
|
-
function _(o) {
|
|
42
|
-
if (!Number.isFinite(o) || o < 0) return "0:00";
|
|
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");
|
|
44
|
-
return i > 0 ? `${i}:${s}:${n}` : `${s}:${n}`;
|
|
45
|
-
}
|
|
46
|
-
function V(o) {
|
|
47
|
-
const t = o.trim().match(/^(?:(\d+):)?(\d{1,2}):(\d{2})(?:[.,](\d{1,3}))?$/);
|
|
48
|
-
if (!t) return null;
|
|
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;
|
|
50
|
-
return e * 3600 + i * 60 + s + n / 1e3;
|
|
51
|
-
}
|
|
52
|
-
function K(o) {
|
|
53
|
-
const t = [], e = o.replace(/\r\n?/g, `
|
|
54
|
-
`).split(/\n\n+/);
|
|
55
|
-
for (const i of e) {
|
|
56
|
-
const s = i.split(`
|
|
57
|
-
`).filter((m) => m.trim() !== "");
|
|
58
|
-
if (s.length === 0) continue;
|
|
59
|
-
let n = s.findIndex((m) => m.includes("-->"));
|
|
60
|
-
if (n === -1) continue;
|
|
61
|
-
const [r, a] = s[n].split("-->"), h = V(r), c = V((a ?? "").split(" ")[1] ?? a ?? "") ?? V(a ?? "");
|
|
62
|
-
if (h === null || c === null) continue;
|
|
63
|
-
const u = s.slice(n + 1).join(`
|
|
64
|
-
`).trim();
|
|
65
|
-
u && t.push({ start: h, end: c, text: u });
|
|
66
|
-
}
|
|
67
|
-
return t;
|
|
68
|
-
}
|
|
69
|
-
function it(o, t) {
|
|
70
|
-
try {
|
|
71
|
-
return new URL(o, new URL(t, window.location.href)).toString();
|
|
72
|
-
} catch {
|
|
73
|
-
return o;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
class st {
|
|
1
|
+
import { e as o, f as _, p as U, r as et, a as q, c as x, i as g, b as S, d as j, s as I } from "./dom-DrpWbY0y.js";
|
|
2
|
+
import { d as H } from "./labels-CCjOCBKU.js";
|
|
3
|
+
class it {
|
|
77
4
|
constructor() {
|
|
78
5
|
this.listeners = /* @__PURE__ */ new Map();
|
|
79
6
|
}
|
|
@@ -105,7 +32,7 @@ class st {
|
|
|
105
32
|
this.listeners.clear();
|
|
106
33
|
}
|
|
107
34
|
}
|
|
108
|
-
const y = (
|
|
35
|
+
const y = (l, t = "0 0 24 24") => `<svg viewBox="${t}" fill="currentColor" aria-hidden="true" focusable="false">${l}</svg>`, st = {
|
|
109
36
|
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
37
|
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
38
|
replay: y('<path d="M12 5V2.5L7.5 6 12 9.5V7a5 5 0 1 1-5 5H5a7 7 0 1 0 7-7Z"/>'),
|
|
@@ -140,54 +67,54 @@ const y = (o, t = "0 0 24 24") => `<svg viewBox="${t}" fill="currentColor" aria-
|
|
|
140
67
|
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"/>'),
|
|
141
68
|
// Generic "channel" glyph (play badge) for preview meta when a channel is set.
|
|
142
69
|
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
|
-
},
|
|
144
|
-
function
|
|
145
|
-
|
|
70
|
+
}, F = { en: H };
|
|
71
|
+
function Nt(l, t) {
|
|
72
|
+
F[l] = t;
|
|
146
73
|
}
|
|
147
|
-
function
|
|
148
|
-
for (const [t, e] of Object.entries(
|
|
149
|
-
e && (
|
|
74
|
+
function qt(l) {
|
|
75
|
+
for (const [t, e] of Object.entries(l))
|
|
76
|
+
e && (F[t] = e);
|
|
150
77
|
}
|
|
151
|
-
function
|
|
152
|
-
return
|
|
78
|
+
function nt(l) {
|
|
79
|
+
return l && F[l] || H;
|
|
153
80
|
}
|
|
154
|
-
function
|
|
155
|
-
return Object.keys(
|
|
81
|
+
function Ft() {
|
|
82
|
+
return Object.keys(F);
|
|
156
83
|
}
|
|
157
|
-
function
|
|
158
|
-
const t = [0.06, 0.24, 0.4, 0.24, 0.06], e =
|
|
159
|
-
return
|
|
84
|
+
function rt(l) {
|
|
85
|
+
const t = [0.06, 0.24, 0.4, 0.24, 0.06], e = l.length;
|
|
86
|
+
return l.map(
|
|
160
87
|
(i, s) => t.reduce((n, r, a) => {
|
|
161
|
-
const
|
|
162
|
-
return n + r *
|
|
88
|
+
const c = Math.min(e - 1, Math.max(0, s + a - 2));
|
|
89
|
+
return n + r * l[c];
|
|
163
90
|
}, 0)
|
|
164
91
|
);
|
|
165
92
|
}
|
|
166
|
-
function
|
|
167
|
-
if (
|
|
168
|
-
const e = Math.min(
|
|
169
|
-
return
|
|
93
|
+
function ot(l, t) {
|
|
94
|
+
if (l.length === 0) return 0;
|
|
95
|
+
const e = Math.min(l.length - 1, Math.max(0, Math.round((l.length - 1) * t)));
|
|
96
|
+
return l[e];
|
|
170
97
|
}
|
|
171
|
-
function
|
|
172
|
-
if (
|
|
173
|
-
const e =
|
|
98
|
+
function K(l, t) {
|
|
99
|
+
if (l.length === 0 || l.every((n) => n <= 0)) return [];
|
|
100
|
+
const e = rt(l), i = t === "retention" ? ot([...e].sort((n, r) => n - r), 0.95) : Math.max(...e);
|
|
174
101
|
if (i <= 0) return [];
|
|
175
102
|
const s = 0.08;
|
|
176
103
|
return e.map((n) => s + (1 - s) * Math.min(1, Math.max(0, n / i)));
|
|
177
104
|
}
|
|
178
|
-
function at(
|
|
179
|
-
if (
|
|
105
|
+
function at(l, t, e = 100) {
|
|
106
|
+
if (l.length === 0 || !Number.isFinite(t) || t <= 0) return [];
|
|
180
107
|
const i = new Array(e).fill(0);
|
|
181
108
|
let s = !1;
|
|
182
|
-
for (const n of
|
|
109
|
+
for (const n of l) {
|
|
183
110
|
if (!Number.isFinite(n.time) || n.time < 0 || n.time > t) continue;
|
|
184
111
|
const r = Math.max(0, n.value);
|
|
185
112
|
r !== 0 && (i[Math.min(e - 1, Math.floor(n.time / t * e))] += r, s = !0);
|
|
186
113
|
}
|
|
187
|
-
return s ?
|
|
114
|
+
return s ? K(i, "peaks") : [];
|
|
188
115
|
}
|
|
189
|
-
function
|
|
190
|
-
let i =
|
|
116
|
+
function lt(l, t = "peaks", e = 200) {
|
|
117
|
+
let i = l.map((s) => Number.isFinite(s) ? Math.max(0, s) : 0);
|
|
191
118
|
if (i.length > e) {
|
|
192
119
|
const s = new Array(e).fill(0), n = new Array(e).fill(0);
|
|
193
120
|
for (let r = 0; r < i.length; r++) {
|
|
@@ -196,35 +123,35 @@ function ht(o, t = "peaks", e = 200) {
|
|
|
196
123
|
}
|
|
197
124
|
i = s.map((r, a) => n[a] > 0 ? r / n[a] : 0);
|
|
198
125
|
}
|
|
199
|
-
return
|
|
126
|
+
return K(i, t);
|
|
200
127
|
}
|
|
201
|
-
function
|
|
202
|
-
const s =
|
|
128
|
+
function ht(l, t = 1, e = 1e3, i = 100) {
|
|
129
|
+
const s = l.length;
|
|
203
130
|
if (s === 0) return "";
|
|
204
|
-
const n = e / (s - 1 || 1), r = Math.max(0, t) / 6, a = (
|
|
205
|
-
const
|
|
206
|
-
return [
|
|
207
|
-
}, [,
|
|
208
|
-
let
|
|
209
|
-
for (let
|
|
210
|
-
const [
|
|
211
|
-
|
|
212
|
-
}
|
|
213
|
-
return
|
|
131
|
+
const n = e / (s - 1 || 1), r = Math.max(0, t) / 6, a = (p) => {
|
|
132
|
+
const v = Math.min(s - 1, Math.max(0, p));
|
|
133
|
+
return [v * n, i - l[v] * i];
|
|
134
|
+
}, [, c] = a(0);
|
|
135
|
+
let h = `M 0 ${i} L 0 ${c.toFixed(1)}`;
|
|
136
|
+
for (let p = 0; p < s - 1; p++) {
|
|
137
|
+
const [v, u] = a(p - 1), [m, f] = a(p), [b, d] = a(p + 1), [k, C] = a(p + 2), P = m + (b - v) * r, V = Math.min(i, Math.max(0, f + (d - u) * r)), M = b - (k - m) * r, A = Math.min(i, Math.max(0, d - (C - f) * r));
|
|
138
|
+
h += ` C ${P.toFixed(1)} ${V.toFixed(1)} ${M.toFixed(1)} ${A.toFixed(1)} ${b.toFixed(1)} ${d.toFixed(1)}`;
|
|
139
|
+
}
|
|
140
|
+
return h += ` L ${e} ${i} Z`, h;
|
|
214
141
|
}
|
|
215
|
-
async function
|
|
216
|
-
if (
|
|
142
|
+
async function ct(l, t) {
|
|
143
|
+
if (l.src)
|
|
217
144
|
return {
|
|
218
|
-
roll:
|
|
219
|
-
mediaUrl:
|
|
220
|
-
clickThrough:
|
|
145
|
+
roll: l.roll,
|
|
146
|
+
mediaUrl: l.src,
|
|
147
|
+
clickThrough: l.clickUrl,
|
|
221
148
|
impressions: [],
|
|
222
149
|
tracking: {}
|
|
223
150
|
};
|
|
224
|
-
if (!
|
|
225
|
-
return
|
|
151
|
+
if (!l.vastTag) throw new Error('Ad roll has neither "vastTag" nor "src"');
|
|
152
|
+
return X(l, l.vastTag, t, 0, { impressions: [], tracking: {} });
|
|
226
153
|
}
|
|
227
|
-
async function
|
|
154
|
+
async function X(l, t, e, i, s) {
|
|
228
155
|
if (i > e.maxWrapperDepth) throw new Error("VAST wrapper depth limit exceeded");
|
|
229
156
|
const n = new AbortController(), r = setTimeout(() => n.abort(), e.requestTimeout);
|
|
230
157
|
let a;
|
|
@@ -235,55 +162,55 @@ async function J(o, t, e, i, s) {
|
|
|
235
162
|
} finally {
|
|
236
163
|
clearTimeout(r);
|
|
237
164
|
}
|
|
238
|
-
const
|
|
239
|
-
if (
|
|
240
|
-
const
|
|
241
|
-
if (!
|
|
242
|
-
|
|
243
|
-
const
|
|
244
|
-
if (
|
|
245
|
-
const f = L(
|
|
165
|
+
const c = new DOMParser().parseFromString(a, "text/xml");
|
|
166
|
+
if (c.querySelector("parsererror")) throw new Error("VAST response is not valid XML");
|
|
167
|
+
const h = c.querySelector("VAST > Ad");
|
|
168
|
+
if (!h) throw new Error("VAST response contains no ads");
|
|
169
|
+
dt(h, s);
|
|
170
|
+
const p = h.querySelector(":scope > Wrapper");
|
|
171
|
+
if (p) {
|
|
172
|
+
const f = L(p.querySelector("VASTAdTagURI"));
|
|
246
173
|
if (!f) throw new Error("VAST wrapper without VASTAdTagURI");
|
|
247
|
-
return
|
|
248
|
-
}
|
|
249
|
-
const
|
|
250
|
-
if (!
|
|
251
|
-
const
|
|
252
|
-
if (!
|
|
253
|
-
const
|
|
254
|
-
if (!
|
|
174
|
+
return X(l, f, e, i + 1, s);
|
|
175
|
+
}
|
|
176
|
+
const v = h.querySelector(":scope > InLine");
|
|
177
|
+
if (!v) throw new Error("VAST ad has neither InLine nor Wrapper");
|
|
178
|
+
const u = v.querySelector("Creatives > Creative > Linear");
|
|
179
|
+
if (!u) throw new Error("VAST ad has no Linear creative");
|
|
180
|
+
const m = ut(u);
|
|
181
|
+
if (!m) throw new Error("VAST ad has no playable MediaFile");
|
|
255
182
|
return {
|
|
256
|
-
roll:
|
|
257
|
-
mediaUrl:
|
|
258
|
-
mediaType:
|
|
259
|
-
clickThrough: L(
|
|
260
|
-
duration:
|
|
261
|
-
skipOffset:
|
|
262
|
-
|
|
263
|
-
|
|
183
|
+
roll: l.roll,
|
|
184
|
+
mediaUrl: m.url,
|
|
185
|
+
mediaType: m.type,
|
|
186
|
+
clickThrough: L(u.querySelector("VideoClicks > ClickThrough")) ?? l.clickUrl,
|
|
187
|
+
duration: O(L(u.querySelector(":scope > Duration"))),
|
|
188
|
+
skipOffset: pt(
|
|
189
|
+
u.getAttribute("skipoffset"),
|
|
190
|
+
O(L(u.querySelector(":scope > Duration")))
|
|
264
191
|
),
|
|
265
192
|
impressions: s.impressions,
|
|
266
193
|
tracking: s.tracking,
|
|
267
|
-
adTitle: L(
|
|
194
|
+
adTitle: L(v.querySelector(":scope > AdTitle")) ?? void 0
|
|
268
195
|
};
|
|
269
196
|
}
|
|
270
|
-
function
|
|
197
|
+
function dt(l, t) {
|
|
271
198
|
var e, i;
|
|
272
|
-
for (const s of
|
|
199
|
+
for (const s of l.querySelectorAll("Impression")) {
|
|
273
200
|
const n = L(s);
|
|
274
201
|
n && t.impressions.push(n);
|
|
275
202
|
}
|
|
276
|
-
for (const s of
|
|
203
|
+
for (const s of l.querySelectorAll("Linear > TrackingEvents > Tracking")) {
|
|
277
204
|
const n = s.getAttribute("event"), r = L(s);
|
|
278
205
|
!n || !r || ["start", "firstQuartile", "midpoint", "thirdQuartile", "complete", "skip", "pause", "resume"].includes(n) && ((e = t.tracking)[n] ?? (e[n] = [])).push(r);
|
|
279
206
|
}
|
|
280
|
-
for (const s of
|
|
207
|
+
for (const s of l.querySelectorAll("Linear > VideoClicks > ClickTracking")) {
|
|
281
208
|
const n = L(s);
|
|
282
209
|
n && ((i = t.tracking).click ?? (i.click = [])).push(n);
|
|
283
210
|
}
|
|
284
211
|
}
|
|
285
|
-
function
|
|
286
|
-
const e = [...
|
|
212
|
+
function ut(l) {
|
|
213
|
+
const e = [...l.querySelectorAll("MediaFiles > MediaFile")].map((r) => ({
|
|
287
214
|
url: L(r) ?? "",
|
|
288
215
|
type: r.getAttribute("type") ?? void 0,
|
|
289
216
|
delivery: r.getAttribute("delivery") ?? "",
|
|
@@ -297,29 +224,29 @@ function pt(o) {
|
|
|
297
224
|
const i = e.filter((r) => r.delivery !== "streaming"), s = i.length > 0 ? i : e, n = s[Math.floor(s.length / 2)];
|
|
298
225
|
return { url: n.url, type: n.type };
|
|
299
226
|
}
|
|
300
|
-
function
|
|
301
|
-
if (!
|
|
302
|
-
const t =
|
|
227
|
+
function O(l) {
|
|
228
|
+
if (!l) return;
|
|
229
|
+
const t = l.trim().match(/^(?:(\d+):)?(\d{1,2}):(\d{2})(?:\.(\d{1,3}))?$/);
|
|
303
230
|
if (t)
|
|
304
231
|
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);
|
|
305
232
|
}
|
|
306
|
-
function
|
|
307
|
-
if (!
|
|
308
|
-
const e =
|
|
309
|
-
return e ? t !== void 0 ? Number(e[1]) / 100 * t : void 0 :
|
|
233
|
+
function pt(l, t) {
|
|
234
|
+
if (!l) return;
|
|
235
|
+
const e = l.trim().match(/^(\d+(?:\.\d+)?)%$/);
|
|
236
|
+
return e ? t !== void 0 ? Number(e[1]) / 100 * t : void 0 : O(l);
|
|
310
237
|
}
|
|
311
|
-
function
|
|
312
|
-
if (
|
|
313
|
-
for (const t of
|
|
238
|
+
function N(l) {
|
|
239
|
+
if (l)
|
|
240
|
+
for (const t of l)
|
|
314
241
|
try {
|
|
315
242
|
new Image().src = t;
|
|
316
243
|
} catch {
|
|
317
244
|
}
|
|
318
245
|
}
|
|
319
|
-
function L(
|
|
320
|
-
return
|
|
246
|
+
function L(l) {
|
|
247
|
+
return l?.textContent?.trim().replace(/^<!\[CDATA\[|\]\]>$/g, "").trim() || null;
|
|
321
248
|
}
|
|
322
|
-
class
|
|
249
|
+
class mt {
|
|
323
250
|
constructor(t, e) {
|
|
324
251
|
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 = {
|
|
325
252
|
skipDelay: 5,
|
|
@@ -338,7 +265,7 @@ class vt {
|
|
|
338
265
|
*/
|
|
339
266
|
ensureAdVideo() {
|
|
340
267
|
if (!this.adVideo) {
|
|
341
|
-
this.adVideo =
|
|
268
|
+
this.adVideo = o("video", "imp-ad__video", { playsinline: "" });
|
|
342
269
|
try {
|
|
343
270
|
this.adVideo.load();
|
|
344
271
|
} catch {
|
|
@@ -386,7 +313,7 @@ class vt {
|
|
|
386
313
|
for (const n of t) {
|
|
387
314
|
this.playedRolls.add(n);
|
|
388
315
|
try {
|
|
389
|
-
const r = await
|
|
316
|
+
const r = await ct(n, this.opts);
|
|
390
317
|
await this.playAd(r);
|
|
391
318
|
} catch (r) {
|
|
392
319
|
const a = r instanceof Error ? r : new Error(String(r));
|
|
@@ -403,68 +330,68 @@ class vt {
|
|
|
403
330
|
}
|
|
404
331
|
playAd(t) {
|
|
405
332
|
return new Promise((e) => {
|
|
406
|
-
const { labels: i } = this.host, s =
|
|
333
|
+
const { labels: i } = this.host, s = o("div", "imp-ad"), n = this.ensureAdVideo(), r = new AbortController(), a = r.signal;
|
|
407
334
|
n.src = t.mediaUrl, n.muted = this.host.contentVideo.muted, n.volume = this.host.contentVideo.volume;
|
|
408
|
-
const
|
|
409
|
-
|
|
410
|
-
const
|
|
411
|
-
|
|
412
|
-
const
|
|
413
|
-
let
|
|
414
|
-
t.clickThrough && (
|
|
415
|
-
const f =
|
|
416
|
-
f.hidden = !0,
|
|
335
|
+
const c = o("div", "imp-spinner imp-ad__spinner"), h = o("div", "imp-ad__hud"), p = o("span", "imp-ad__badge");
|
|
336
|
+
p.textContent = t.adTitle ? `${i.adLabel} · ${t.adTitle}` : i.adLabel;
|
|
337
|
+
const v = o("span", "imp-ad__countdown");
|
|
338
|
+
h.append(p, v);
|
|
339
|
+
const u = o("div", "imp-ad__actions");
|
|
340
|
+
let m = null;
|
|
341
|
+
t.clickThrough && (m = o("button", "imp-ad__visit", { type: "button" }), m.textContent = i.visitAdvertiser, u.append(m));
|
|
342
|
+
const f = o("button", "imp-ad__skip", { type: "button" });
|
|
343
|
+
f.hidden = !0, u.append(f), s.append(n, c, h, u), this.host.container.append(s), this.layer = s;
|
|
417
344
|
const b = t.skipOffset ?? this.opts.skipDelay, d = /* @__PURE__ */ new Set(), k = (w) => {
|
|
418
|
-
d.has(w) || (d.add(w),
|
|
345
|
+
d.has(w) || (d.add(w), N(t.tracking[w]));
|
|
419
346
|
};
|
|
420
|
-
let C = Date.now(),
|
|
421
|
-
const
|
|
347
|
+
let C = Date.now(), P = -1;
|
|
348
|
+
const V = setInterval(() => {
|
|
422
349
|
if (n.paused) {
|
|
423
350
|
C = Date.now();
|
|
424
351
|
return;
|
|
425
352
|
}
|
|
426
|
-
if (n.currentTime !==
|
|
427
|
-
|
|
353
|
+
if (n.currentTime !== P) {
|
|
354
|
+
P = n.currentTime, C = Date.now();
|
|
428
355
|
return;
|
|
429
356
|
}
|
|
430
357
|
Date.now() - C >= this.opts.mediaTimeout && (this.host.emitter.emit("aderror", {
|
|
431
358
|
roll: { roll: t.roll },
|
|
432
359
|
error: new Error(`Ad media stalled for ${this.opts.mediaTimeout} ms — skipping`)
|
|
433
|
-
}),
|
|
434
|
-
}, 500),
|
|
435
|
-
clearInterval(
|
|
436
|
-
},
|
|
437
|
-
w ? (k("skip"), this.host.emitter.emit("adskip", { ad: t })) : k("complete"), this.host.emitter.emit("adend", { ad: t }),
|
|
360
|
+
}), M());
|
|
361
|
+
}, 500), M = () => {
|
|
362
|
+
clearInterval(V), r.abort(), n.pause(), n.removeAttribute("src"), n.load(), s.remove(), this.layer = null, e();
|
|
363
|
+
}, A = (w) => {
|
|
364
|
+
w ? (k("skip"), this.host.emitter.emit("adskip", { ad: t })) : k("complete"), this.host.emitter.emit("adend", { ad: t }), M();
|
|
438
365
|
};
|
|
439
366
|
n.addEventListener("playing", () => {
|
|
440
|
-
|
|
367
|
+
N(t.impressions), k("start"), this.host.emitter.emit("adstart", { ad: t });
|
|
441
368
|
}, { once: !0, signal: a }), n.addEventListener("playing", () => {
|
|
442
|
-
|
|
369
|
+
c.hidden = !0;
|
|
443
370
|
}, { signal: a }), n.addEventListener("waiting", () => {
|
|
444
|
-
|
|
371
|
+
c.hidden = !1;
|
|
445
372
|
}, { signal: a }), n.addEventListener("timeupdate", () => {
|
|
446
|
-
const w = n.currentTime,
|
|
447
|
-
if (Number.isFinite(
|
|
448
|
-
const
|
|
449
|
-
|
|
373
|
+
const w = n.currentTime, T = n.duration;
|
|
374
|
+
if (Number.isFinite(T) && T > 0 && (v.textContent = _(Math.max(0, T - w)), w / T >= 0.25 && k("firstQuartile"), w / T >= 0.5 && k("midpoint"), w / T >= 0.75 && k("thirdQuartile")), b >= 0) {
|
|
375
|
+
const W = Math.ceil(b - w);
|
|
376
|
+
W > 0 ? (f.hidden = !1, f.disabled = !0, f.textContent = `${i.skipAdIn} ${W}`) : (f.hidden = !1, f.disabled = !1, f.textContent = i.skipAd);
|
|
450
377
|
}
|
|
451
|
-
}, { signal: a }), n.addEventListener("ended", () =>
|
|
378
|
+
}, { signal: a }), n.addEventListener("ended", () => A(!1), { signal: a }), n.addEventListener("error", () => {
|
|
452
379
|
this.host.emitter.emit("aderror", {
|
|
453
380
|
roll: { roll: t.roll },
|
|
454
381
|
error: new Error("Ad media failed to play")
|
|
455
|
-
}),
|
|
456
|
-
}, { signal: a }), f.addEventListener("click", () =>
|
|
457
|
-
const
|
|
382
|
+
}), M();
|
|
383
|
+
}, { signal: a }), f.addEventListener("click", () => A(!0));
|
|
384
|
+
const D = () => {
|
|
458
385
|
t.clickThrough && (k("click"), this.host.emitter.emit("adclick", { ad: t }), window.open(t.clickThrough, "_blank", "noopener"), n.pause());
|
|
459
386
|
};
|
|
460
|
-
n.addEventListener("click",
|
|
461
|
-
let
|
|
387
|
+
n.addEventListener("click", D, { signal: a }), m?.addEventListener("click", D);
|
|
388
|
+
let G = !1, R = !1;
|
|
462
389
|
n.addEventListener("playing", () => {
|
|
463
|
-
|
|
390
|
+
G = !0;
|
|
464
391
|
}, { once: !0, signal: a }), n.addEventListener("pause", () => {
|
|
465
|
-
n.ended || !s.isConnected || (s.classList.add("imp-ad--paused"),
|
|
392
|
+
n.ended || !s.isConnected || (s.classList.add("imp-ad--paused"), G && !R && (R = !0, N(t.tracking.pause), this.host.emitter.emit("adpause", { ad: t })));
|
|
466
393
|
}, { signal: a }), n.addEventListener("play", () => {
|
|
467
|
-
s.classList.remove("imp-ad--paused"),
|
|
394
|
+
s.classList.remove("imp-ad--paused"), R && (R = !1, N(t.tracking.resume), this.host.emitter.emit("adresume", { ad: t }));
|
|
468
395
|
}, { signal: a }), s.addEventListener("click", (w) => {
|
|
469
396
|
(w.target === s || s.classList.contains("imp-ad--paused")) && n.paused && n.play().catch(() => {
|
|
470
397
|
});
|
|
@@ -481,8 +408,8 @@ class vt {
|
|
|
481
408
|
this.destroyed = !0, this.adVideo?.pause(), this.layer?.remove(), this.layer = null, this.adVideo = null;
|
|
482
409
|
}
|
|
483
410
|
}
|
|
484
|
-
function
|
|
485
|
-
const e = [...
|
|
411
|
+
function z(l, t) {
|
|
412
|
+
const e = [...l].sort((s, n) => s.start - n.start), i = [];
|
|
486
413
|
for (let s = 0; s < e.length; s++) {
|
|
487
414
|
const n = Math.max(0, e[s].start);
|
|
488
415
|
if (Number.isFinite(t) && n >= t) continue;
|
|
@@ -491,40 +418,40 @@ function Q(o, t) {
|
|
|
491
418
|
}
|
|
492
419
|
return i;
|
|
493
420
|
}
|
|
494
|
-
async function
|
|
495
|
-
const t = await fetch(
|
|
421
|
+
async function vt(l) {
|
|
422
|
+
const t = await fetch(l);
|
|
496
423
|
if (!t.ok) throw new Error(`Failed to load chapters VTT (${t.status})`);
|
|
497
424
|
const e = await t.text();
|
|
498
|
-
return
|
|
425
|
+
return U(e).map((i) => ({ start: i.start, end: i.end, title: i.text }));
|
|
499
426
|
}
|
|
500
|
-
function
|
|
501
|
-
for (const e of
|
|
427
|
+
function J(l, t) {
|
|
428
|
+
for (const e of l)
|
|
502
429
|
if (t >= e.start && t < e.end) return e;
|
|
503
430
|
return null;
|
|
504
431
|
}
|
|
505
|
-
function
|
|
506
|
-
return t ? /application\/(x-mpegurl|vnd\.apple\.mpegurl)/i.test(t) : /\.m3u8(\?|#|$)/i.test(
|
|
432
|
+
function ft(l, t) {
|
|
433
|
+
return t ? /application\/(x-mpegurl|vnd\.apple\.mpegurl)/i.test(t) : /\.m3u8(\?|#|$)/i.test(l);
|
|
507
434
|
}
|
|
508
|
-
let
|
|
509
|
-
async function
|
|
510
|
-
if (
|
|
511
|
-
const
|
|
512
|
-
if (
|
|
513
|
-
return
|
|
435
|
+
let B;
|
|
436
|
+
async function yt() {
|
|
437
|
+
if (B !== void 0) return B;
|
|
438
|
+
const l = globalThis.Hls;
|
|
439
|
+
if (l)
|
|
440
|
+
return B = l, B;
|
|
514
441
|
try {
|
|
515
|
-
return
|
|
442
|
+
return B = (await import("hls.js/light")).default, B;
|
|
516
443
|
} catch {
|
|
517
444
|
return null;
|
|
518
445
|
}
|
|
519
446
|
}
|
|
520
|
-
async function
|
|
521
|
-
if (
|
|
522
|
-
const s =
|
|
523
|
-
return n && n.isSupported() ?
|
|
447
|
+
async function gt(l, t, e, i) {
|
|
448
|
+
if (ft(t, e)) {
|
|
449
|
+
const s = l.canPlayType("application/vnd.apple.mpegurl"), n = s ? null : await yt();
|
|
450
|
+
return n && n.isSupported() ? bt(n, l, t, i) : s ? (l.src = t, $(l)) : (i.onError("HLS is not supported in this browser and hls.js could not be loaded."), $(l));
|
|
524
451
|
}
|
|
525
|
-
return
|
|
452
|
+
return l.src = t, $(l);
|
|
526
453
|
}
|
|
527
|
-
function
|
|
454
|
+
function $(l) {
|
|
528
455
|
return {
|
|
529
456
|
kind: "native",
|
|
530
457
|
levels: [],
|
|
@@ -532,58 +459,58 @@ function O(o) {
|
|
|
532
459
|
setLevel() {
|
|
533
460
|
},
|
|
534
461
|
destroy() {
|
|
535
|
-
|
|
462
|
+
l.removeAttribute("src"), l.load();
|
|
536
463
|
}
|
|
537
464
|
};
|
|
538
465
|
}
|
|
539
|
-
function
|
|
540
|
-
const s = new
|
|
466
|
+
function bt(l, t, e, i) {
|
|
467
|
+
const s = new l({ enableWorker: !0 }), n = {
|
|
541
468
|
kind: "hls",
|
|
542
469
|
levels: [],
|
|
543
470
|
selected: -1,
|
|
544
|
-
setLevel(
|
|
545
|
-
n.selected =
|
|
471
|
+
setLevel(h) {
|
|
472
|
+
n.selected = h, s.currentLevel = h;
|
|
546
473
|
},
|
|
547
474
|
destroy() {
|
|
548
475
|
s.destroy(), t.removeAttribute("src"), t.load();
|
|
549
476
|
}
|
|
550
477
|
};
|
|
551
|
-
s.on(
|
|
552
|
-
n.levels = s.levels.map((
|
|
553
|
-
index:
|
|
554
|
-
label:
|
|
478
|
+
s.on(l.Events.MANIFEST_PARSED, () => {
|
|
479
|
+
n.levels = s.levels.map((h, p) => ({
|
|
480
|
+
index: p,
|
|
481
|
+
label: h.height ? `${h.height}p` : `${Math.round(h.bitrate / 1e3)} kbps`
|
|
555
482
|
})).reverse(), i.onLevels(n.levels);
|
|
556
|
-
}), s.on(
|
|
557
|
-
const
|
|
558
|
-
|
|
483
|
+
}), s.on(l.Events.LEVEL_SWITCHED, (h, p) => {
|
|
484
|
+
const v = s.levels[p.level];
|
|
485
|
+
v && i.onLevelSwitch(v.height ? `${v.height}p` : `${Math.round(v.bitrate / 1e3)} kbps`);
|
|
559
486
|
});
|
|
560
|
-
let r = 0, a = 0,
|
|
561
|
-
return s.on(
|
|
487
|
+
let r = 0, a = 0, c = !1;
|
|
488
|
+
return s.on(l.Events.FRAG_BUFFERED, () => {
|
|
562
489
|
a = 0;
|
|
563
|
-
}), s.on(
|
|
564
|
-
if (
|
|
565
|
-
switch (
|
|
566
|
-
case
|
|
567
|
-
a < 3 ? (a++, s.startLoad()) : (i.onError(`HLS network error: ${
|
|
490
|
+
}), s.on(l.Events.ERROR, (h, p) => {
|
|
491
|
+
if (p.fatal)
|
|
492
|
+
switch (p.type) {
|
|
493
|
+
case l.ErrorTypes.NETWORK_ERROR:
|
|
494
|
+
a < 3 ? (a++, s.startLoad()) : (i.onError(`HLS network error: ${p.details}`, p), s.destroy());
|
|
568
495
|
break;
|
|
569
|
-
case
|
|
570
|
-
r < 3 ? (r++, s.recoverMediaError()) : (i.onError(`HLS media error: ${
|
|
496
|
+
case l.ErrorTypes.MEDIA_ERROR:
|
|
497
|
+
r < 3 ? (r++, s.recoverMediaError()) : (i.onError(`HLS media error: ${p.details}`, p), s.destroy());
|
|
571
498
|
break;
|
|
572
499
|
default:
|
|
573
|
-
if (
|
|
574
|
-
i.onError(`HLS fatal error: ${
|
|
500
|
+
if (c)
|
|
501
|
+
i.onError(`HLS fatal error: ${p.details}`, p), s.destroy();
|
|
575
502
|
else {
|
|
576
|
-
|
|
503
|
+
c = !0;
|
|
577
504
|
try {
|
|
578
505
|
s.loadSource(e), s.startLoad();
|
|
579
506
|
} catch {
|
|
580
|
-
i.onError(`HLS fatal error: ${
|
|
507
|
+
i.onError(`HLS fatal error: ${p.details}`, p), s.destroy();
|
|
581
508
|
}
|
|
582
509
|
}
|
|
583
510
|
}
|
|
584
511
|
}), s.loadSource(e), s.attachMedia(t), n;
|
|
585
512
|
}
|
|
586
|
-
class
|
|
513
|
+
class Z {
|
|
587
514
|
constructor(t) {
|
|
588
515
|
this.cues = t;
|
|
589
516
|
}
|
|
@@ -591,17 +518,17 @@ class D {
|
|
|
591
518
|
const e = await fetch(t);
|
|
592
519
|
if (!e.ok) throw new Error(`Failed to load thumbnails VTT (${e.status})`);
|
|
593
520
|
const i = await e.text(), s = [];
|
|
594
|
-
for (const n of
|
|
521
|
+
for (const n of U(i)) {
|
|
595
522
|
const [r, a] = n.text.trim().split("#");
|
|
596
523
|
if (!r) continue;
|
|
597
|
-
const
|
|
524
|
+
const c = {
|
|
598
525
|
start: n.start,
|
|
599
526
|
end: n.end,
|
|
600
|
-
src:
|
|
601
|
-
},
|
|
602
|
-
|
|
527
|
+
src: et(r, t)
|
|
528
|
+
}, h = a?.match(/xywh=(\d+),(\d+),(\d+),(\d+)/);
|
|
529
|
+
h && (c.xywh = { x: Number(h[1]), y: Number(h[2]), w: Number(h[3]), h: Number(h[4]) }), s.push(c);
|
|
603
530
|
}
|
|
604
|
-
return s.sort((n, r) => n.start - r.start), new
|
|
531
|
+
return s.sort((n, r) => n.start - r.start), new Z(s);
|
|
605
532
|
}
|
|
606
533
|
cueAt(t) {
|
|
607
534
|
let e = 0, i = this.cues.length - 1;
|
|
@@ -614,10 +541,10 @@ class D {
|
|
|
614
541
|
return null;
|
|
615
542
|
}
|
|
616
543
|
}
|
|
617
|
-
const
|
|
618
|
-
class
|
|
544
|
+
const kt = '<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>', 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="m15 6-6 6 6 6"/></svg>';
|
|
545
|
+
class E {
|
|
619
546
|
constructor(t) {
|
|
620
|
-
this.anchor = t, this.outsideListener = null, this.escListener = null, this.root =
|
|
547
|
+
this.anchor = t, this.outsideListener = null, this.escListener = null, this.root = o("div", "imp-menu"), this.root.hidden = !0, this.backdrop = o("div", "imp-menu__backdrop"), this.backdrop.hidden = !0, this.backdrop.addEventListener("pointerdown", (e) => {
|
|
621
548
|
e.preventDefault(), this.close();
|
|
622
549
|
});
|
|
623
550
|
}
|
|
@@ -642,31 +569,31 @@ class M {
|
|
|
642
569
|
}
|
|
643
570
|
renderSettingsRoot(t) {
|
|
644
571
|
this.root.textContent = "";
|
|
645
|
-
const e =
|
|
572
|
+
const e = o("div", "imp-menu__section");
|
|
646
573
|
for (const i of t) {
|
|
647
574
|
if (i.toggle) {
|
|
648
575
|
e.append(this.buildToggleRow(i, i.toggle));
|
|
649
576
|
continue;
|
|
650
577
|
}
|
|
651
|
-
const s =
|
|
578
|
+
const s = o("button", "imp-menu__item imp-menu__row", { type: "button" }), n = o("span", "imp-menu__label");
|
|
652
579
|
n.textContent = i.label;
|
|
653
|
-
const r =
|
|
580
|
+
const r = o("span", "imp-menu__value");
|
|
654
581
|
r.textContent = i.value ?? "";
|
|
655
|
-
const a =
|
|
656
|
-
a.innerHTML =
|
|
582
|
+
const a = o("span", "imp-menu__chevron");
|
|
583
|
+
a.innerHTML = kt, s.append(n, r, a), s.addEventListener("click", () => this.renderSettingsDetail(t, i)), e.append(s);
|
|
657
584
|
}
|
|
658
585
|
this.root.append(e);
|
|
659
586
|
}
|
|
660
587
|
/** Toggle row: label + an on/off switch. Stays in the menu (no close). */
|
|
661
588
|
buildToggleRow(t, e) {
|
|
662
|
-
const i =
|
|
589
|
+
const i = o("button", "imp-menu__item imp-menu__row imp-menu__toggle", {
|
|
663
590
|
type: "button",
|
|
664
591
|
role: "switch",
|
|
665
592
|
"aria-checked": String(e.value)
|
|
666
|
-
}), s =
|
|
593
|
+
}), s = o("span", "imp-menu__label");
|
|
667
594
|
s.textContent = t.label;
|
|
668
|
-
const n =
|
|
669
|
-
return n.append(
|
|
595
|
+
const n = o("span", "imp-switch");
|
|
596
|
+
return n.append(o("span", "imp-switch__knob")), i.classList.toggle("imp-menu__toggle--on", e.value), i.append(s, n), i.addEventListener("click", () => {
|
|
670
597
|
const r = i.getAttribute("aria-checked") !== "true";
|
|
671
598
|
i.setAttribute("aria-checked", String(r)), i.classList.toggle("imp-menu__toggle--on", r), e.onChange(r);
|
|
672
599
|
}), i;
|
|
@@ -674,25 +601,25 @@ class M {
|
|
|
674
601
|
renderSettingsDetail(t, e) {
|
|
675
602
|
if (!e.section) return;
|
|
676
603
|
this.root.textContent = "";
|
|
677
|
-
const i =
|
|
678
|
-
s.innerHTML =
|
|
679
|
-
const n =
|
|
604
|
+
const i = o("button", "imp-menu__item imp-menu__back", { type: "button" }), s = o("span", "imp-menu__chevron");
|
|
605
|
+
s.innerHTML = wt;
|
|
606
|
+
const n = o("span", "imp-menu__label");
|
|
680
607
|
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;
|
|
681
608
|
}
|
|
682
609
|
/** Build one option block (radio items) from a section. */
|
|
683
610
|
renderSection(t) {
|
|
684
|
-
const e =
|
|
611
|
+
const e = o("div", "imp-menu__section");
|
|
685
612
|
if (t.title) {
|
|
686
|
-
const i =
|
|
613
|
+
const i = o("div", "imp-menu__title");
|
|
687
614
|
i.textContent = t.title, e.append(i);
|
|
688
615
|
}
|
|
689
616
|
for (const i of t.items) {
|
|
690
|
-
const s =
|
|
617
|
+
const s = o("button", "imp-menu__item", { type: "button", role: "menuitemradio" });
|
|
691
618
|
if (s.setAttribute("aria-checked", String(i.active)), i.active && s.classList.add("imp-menu__item--active"), i.icon) {
|
|
692
|
-
const r =
|
|
693
|
-
|
|
619
|
+
const r = o("span", "imp-menu__icon");
|
|
620
|
+
q(r, i.icon), s.append(r);
|
|
694
621
|
}
|
|
695
|
-
const n =
|
|
622
|
+
const n = o("span", "imp-menu__label");
|
|
696
623
|
n.textContent = i.label, s.append(n), s.addEventListener("click", () => {
|
|
697
624
|
t.onSelect(i.value), this.close();
|
|
698
625
|
}), e.append(s);
|
|
@@ -718,9 +645,9 @@ class M {
|
|
|
718
645
|
this.close(), this.backdrop.remove(), this.root.remove();
|
|
719
646
|
}
|
|
720
647
|
}
|
|
721
|
-
class
|
|
648
|
+
class xt {
|
|
722
649
|
constructor(t, e = "Seek") {
|
|
723
|
-
this.cb = t, this.segments = [], this.duration = 0, this.chapters = [], this.thumbnails = null, this.scrubbing = !1, this.root =
|
|
650
|
+
this.cb = t, this.segments = [], this.duration = 0, this.chapters = [], this.thumbnails = null, this.scrubbing = !1, this.root = o("div", "imp-progress", { role: "slider", "aria-label": e, tabindex: "-1" }), this.buffered = o("div", "imp-progress__buffered"), this.track = o("div", "imp-progress__track"), this.handle = o("div", "imp-progress__handle"), this.tooltipThumb = o("div", "imp-progress__thumb"), this.tooltipChapter = o("div", "imp-progress__tooltip-chapter"), this.tooltipTime = o("div", "imp-progress__tooltip-time"), this.tooltipCaption = o("div", "imp-progress__caption"), this.tooltipCaption.append(this.tooltipChapter, this.tooltipTime), this.tooltip = o("div", "imp-progress__tooltip"), this.tooltip.append(this.tooltipThumb, this.tooltipCaption), this.heatmap = o("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();
|
|
724
651
|
}
|
|
725
652
|
/** Render the popularity curve (empty array hides it). */
|
|
726
653
|
setHeatmap(t, e = 1) {
|
|
@@ -728,7 +655,7 @@ class _t {
|
|
|
728
655
|
this.heatmap.hidden = !0, this.heatmap.textContent = "";
|
|
729
656
|
return;
|
|
730
657
|
}
|
|
731
|
-
this.heatmap.innerHTML = `<svg viewBox="0 0 1000 100" preserveAspectRatio="none" aria-hidden="true"><path d="${
|
|
658
|
+
this.heatmap.innerHTML = `<svg viewBox="0 0 1000 100" preserveAspectRatio="none" aria-hidden="true"><path d="${ht(t, e)}"/></svg>`, this.heatmap.hidden = !1;
|
|
732
659
|
}
|
|
733
660
|
setDuration(t) {
|
|
734
661
|
this.duration = Number.isFinite(t) ? t : 0, this.root.classList.toggle("imp-progress--live", !Number.isFinite(t)), this.chapters.length === 0 && this.setChapters([]);
|
|
@@ -741,9 +668,9 @@ class _t {
|
|
|
741
668
|
n.start > s && i.push({ start: s, end: n.start, title: "" }), i.push(n), s = n.end;
|
|
742
669
|
this.duration > 0 && s < this.duration && i.push({ start: s, end: this.duration, title: "" });
|
|
743
670
|
for (const n of i) {
|
|
744
|
-
const r =
|
|
671
|
+
const r = o("div", "imp-progress__segment");
|
|
745
672
|
r.style.flexGrow = String(Math.max(n.end - n.start, 0.01));
|
|
746
|
-
const a =
|
|
673
|
+
const a = o("div", "imp-progress__fill");
|
|
747
674
|
r.append(a), this.track.append(r), this.segments.push({ chapter: n, root: r, fill: a });
|
|
748
675
|
}
|
|
749
676
|
}
|
|
@@ -782,22 +709,22 @@ class _t {
|
|
|
782
709
|
showTooltip(t) {
|
|
783
710
|
const e = this.timeFromEvent(t);
|
|
784
711
|
this.tooltipTime.textContent = _(e);
|
|
785
|
-
const i =
|
|
712
|
+
const i = J(this.chapters, e), s = !!i?.title;
|
|
786
713
|
this.tooltipChapter.textContent = i?.title ?? "", this.tooltipChapter.hidden = !s, this.tooltipCaption.classList.toggle("imp-progress__caption--time-only", !s);
|
|
787
714
|
const n = this.thumbnails?.cueAt(e) ?? null;
|
|
788
715
|
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");
|
|
789
|
-
const r = this.root.getBoundingClientRect(), a = x(t.clientX - r.left, 0, r.width),
|
|
790
|
-
this.tooltip.style.left = `${x(a,
|
|
716
|
+
const r = this.root.getBoundingClientRect(), a = x(t.clientX - r.left, 0, r.width), c = this.tooltip.offsetWidth / 2;
|
|
717
|
+
this.tooltip.style.left = `${x(a, c, Math.max(c, r.width - c))}px`;
|
|
791
718
|
}
|
|
792
719
|
hideTooltip() {
|
|
793
720
|
this.tooltip.classList.remove("imp-progress__tooltip--visible");
|
|
794
721
|
}
|
|
795
722
|
}
|
|
796
|
-
class
|
|
723
|
+
class _t {
|
|
797
724
|
constructor(t) {
|
|
798
725
|
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;
|
|
799
726
|
const { labels: e, icons: i } = t, s = t.controlsOptions;
|
|
800
|
-
this.root =
|
|
727
|
+
this.root = o("div", "imp-controls"), this.progress = new xt({
|
|
801
728
|
onSeek: (d) => t.seek(d),
|
|
802
729
|
onScrubStart: () => {
|
|
803
730
|
t.scrubbing = !0, this.wasPlayingBeforeScrub = !t.paused, t.pause();
|
|
@@ -806,16 +733,16 @@ class Lt {
|
|
|
806
733
|
t.scrubbing = !1, this.wasPlayingBeforeScrub && t.play(!0);
|
|
807
734
|
}
|
|
808
735
|
}, t.labels.seek), s.progress && this.root.append(this.progress.root);
|
|
809
|
-
const n =
|
|
736
|
+
const n = o("div", "imp-controls__row");
|
|
810
737
|
this.row = n, this.root.append(n);
|
|
811
|
-
const r =
|
|
738
|
+
const r = o("div", "imp-controls__group"), a = o("div", "imp-controls__group");
|
|
812
739
|
this.rightGroup = a;
|
|
813
|
-
const
|
|
814
|
-
this.chapterLabel =
|
|
815
|
-
const
|
|
816
|
-
if (this.seekLabelFn =
|
|
817
|
-
const d =
|
|
818
|
-
this.muteBtn = g("imp-btn--mute", e.mute, i.volumeHigh), this.muteBtn.addEventListener("click", () => t.toggleMute()), this.volumeSlider =
|
|
740
|
+
const c = o("div", "imp-controls__spacer");
|
|
741
|
+
this.chapterLabel = o("div", "imp-controls__chapter"), n.append(r, c, a), c.append(this.chapterLabel);
|
|
742
|
+
const h = typeof s.seekButtons == "object" ? s.seekButtons : {}, p = h.back ?? t.seekStep, v = h.forward ?? t.seekStep;
|
|
743
|
+
if (this.seekLabelFn = h.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} ${p}s`, i.seekBack), this.addStepBadge(this.seekBackBtn, p, "back"), this.seekBackBtn.addEventListener("click", () => t.skip(-p)), 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} ${v}s`, i.seekForward), this.addStepBadge(this.seekFwdBtn, v, "forward"), this.seekFwdBtn.addEventListener("click", () => t.skip(v)), 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) {
|
|
744
|
+
const d = o("div", "imp-volume");
|
|
745
|
+
this.muteBtn = g("imp-btn--mute", e.mute, i.volumeHigh), this.muteBtn.addEventListener("click", () => t.toggleMute()), this.volumeSlider = o("input", "imp-volume__slider", {
|
|
819
746
|
type: "range",
|
|
820
747
|
min: "0",
|
|
821
748
|
max: "1",
|
|
@@ -825,7 +752,7 @@ class Lt {
|
|
|
825
752
|
t.setVolume(Number(this.volumeSlider.value));
|
|
826
753
|
}), d.append(this.muteBtn, this.volumeSlider), r.append(d);
|
|
827
754
|
}
|
|
828
|
-
s.time && (this.timeLabel =
|
|
755
|
+
s.time && (this.timeLabel = o("div", "imp-controls__time"), this.timeCurrent = o("span", "imp-controls__time-current"), this.timeTotal = o("span", "imp-controls__time-total"), this.timeLabel.append(this.timeCurrent, this.timeTotal), this.liveBadge = o("span", "imp-controls__live"), this.liveBadge.textContent = e.live, this.liveBadge.hidden = !0, r.append(this.timeLabel, this.liveBadge)), this.buildLikeDislike();
|
|
829
756
|
for (const d of (t.actionsOptions.custom ?? []).filter((k) => k.placement === "bar")) {
|
|
830
757
|
const k = g(`imp-btn--custom imp-btn--custom-${d.id}`, d.title, d.icon ?? i.more);
|
|
831
758
|
k.addEventListener("click", () => t.emit("customaction", { id: d.id })), this.rightItems.set(`custom:${d.id}`, k), this.registerCollapsible({
|
|
@@ -836,10 +763,10 @@ class Lt {
|
|
|
836
763
|
section: () => this.simpleSection(`custom:${d.id}`, d.title, d.icon ?? i.more, () => t.emit("customaction", { id: d.id }))
|
|
837
764
|
});
|
|
838
765
|
}
|
|
839
|
-
const
|
|
840
|
-
if (this.gear = { speed: b === "gear", quality: f === "gear", subtitles:
|
|
841
|
-
this.subtitlesBtn = g("imp-btn--subtitles", e.subtitles, i.subtitles), this.subtitlesMenu = new
|
|
842
|
-
const d =
|
|
766
|
+
const u = (d) => d === !1 ? "off" : d === "bar" ? "bar" : "gear", m = u(s.subtitles), f = u(s.quality), b = u(s.speed);
|
|
767
|
+
if (this.gear = { speed: b === "gear", quality: f === "gear", subtitles: m === "gear" }, m === "bar") {
|
|
768
|
+
this.subtitlesBtn = g("imp-btn--subtitles", e.subtitles, i.subtitles), this.subtitlesMenu = new E(this.subtitlesBtn);
|
|
769
|
+
const d = o("div", "imp-controls__menu-anchor");
|
|
843
770
|
d.append(this.subtitlesBtn, this.subtitlesMenu.root), this.subtitlesBtn.addEventListener("click", () => this.toggleSubtitlesMenu()), this.rightItems.set("subtitles", d), this.registerCollapsible({
|
|
844
771
|
key: "subtitles",
|
|
845
772
|
el: d,
|
|
@@ -849,8 +776,8 @@ class Lt {
|
|
|
849
776
|
});
|
|
850
777
|
}
|
|
851
778
|
if (f === "bar") {
|
|
852
|
-
this.qualityBtn = g("imp-btn--quality", e.quality, i.settings), this.qualityMenu = new
|
|
853
|
-
const d =
|
|
779
|
+
this.qualityBtn = g("imp-btn--quality", e.quality, i.settings), this.qualityMenu = new E(this.qualityBtn);
|
|
780
|
+
const d = o("div", "imp-controls__menu-anchor");
|
|
854
781
|
d.append(this.qualityBtn, this.qualityMenu.root), this.qualityBtn.addEventListener("click", () => this.toggleQualityMenu()), this.rightItems.set("quality", d), this.registerCollapsible({
|
|
855
782
|
key: "quality",
|
|
856
783
|
el: d,
|
|
@@ -860,8 +787,8 @@ class Lt {
|
|
|
860
787
|
});
|
|
861
788
|
}
|
|
862
789
|
if (b === "bar") {
|
|
863
|
-
this.settingsBtn = g("imp-btn--speed", e.speed, i.speed), this.settingsMenu = new
|
|
864
|
-
const d =
|
|
790
|
+
this.settingsBtn = g("imp-btn--speed", e.speed, i.speed), this.settingsMenu = new E(this.settingsBtn);
|
|
791
|
+
const d = o("div", "imp-controls__menu-anchor");
|
|
865
792
|
d.append(this.settingsBtn, this.settingsMenu.root), this.settingsBtn.addEventListener("click", () => this.toggleSettingsMenu()), this.rightItems.set("speed", d), this.registerCollapsible({
|
|
866
793
|
key: "speed",
|
|
867
794
|
el: d,
|
|
@@ -877,8 +804,8 @@ class Lt {
|
|
|
877
804
|
available: () => t.chapterList.length > 0,
|
|
878
805
|
section: () => this.simpleSection("scenes", e.scenes, i.scenes, () => t.toggleScenesPanel())
|
|
879
806
|
})), s.sceneTypes !== !1) {
|
|
880
|
-
this.sceneTypeBtn =
|
|
881
|
-
const d =
|
|
807
|
+
this.sceneTypeBtn = o("button", "imp-btn imp-btn--scene-types", { type: "button" }), this.sceneTypeMenu = new E(this.sceneTypeBtn);
|
|
808
|
+
const d = o("div", "imp-controls__menu-anchor");
|
|
882
809
|
d.append(this.sceneTypeBtn, this.sceneTypeMenu.root), this.sceneTypeBtn.addEventListener("click", () => this.toggleSceneTypeMenu()), this.rightItems.set("sceneTypes", d), this.refreshSceneTypeButton(), this.registerCollapsible({
|
|
883
810
|
key: "sceneTypes",
|
|
884
811
|
el: d,
|
|
@@ -926,7 +853,7 @@ class Lt {
|
|
|
926
853
|
el: d,
|
|
927
854
|
priority: 80,
|
|
928
855
|
available: () => Number.isFinite(t.duration) && t.duration > 0,
|
|
929
|
-
section: () => this.simpleSection("seekBack", `${e.seekBack} ${
|
|
856
|
+
section: () => this.simpleSection("seekBack", `${e.seekBack} ${p}s`, i.seekBack, () => t.skip(-p))
|
|
930
857
|
});
|
|
931
858
|
}
|
|
932
859
|
if (this.seekFwdBtn) {
|
|
@@ -936,20 +863,20 @@ class Lt {
|
|
|
936
863
|
el: d,
|
|
937
864
|
priority: 82,
|
|
938
865
|
available: () => Number.isFinite(t.duration) && t.duration > 0,
|
|
939
|
-
section: () => this.simpleSection("seekFwd", `${e.seekForward} ${
|
|
866
|
+
section: () => this.simpleSection("seekFwd", `${e.seekForward} ${v}s`, i.seekForward, () => t.skip(v))
|
|
940
867
|
});
|
|
941
868
|
}
|
|
942
|
-
if (this.center =
|
|
943
|
-
const d = this.makeCenterButton("seek-back", `${e.seekBack} ${
|
|
944
|
-
this.addStepBadge(d,
|
|
869
|
+
if (this.center = o("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) {
|
|
870
|
+
const d = this.makeCenterButton("seek-back", `${e.seekBack} ${p}s`, i.seekBack);
|
|
871
|
+
this.addStepBadge(d, p, "back"), d.addEventListener("click", () => t.skip(-p)), this.center.append(d);
|
|
945
872
|
}
|
|
946
873
|
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) {
|
|
947
|
-
const d = this.makeCenterButton("seek-forward", `${e.seekForward} ${
|
|
948
|
-
this.addStepBadge(d,
|
|
874
|
+
const d = this.makeCenterButton("seek-forward", `${e.seekForward} ${v}s`, i.seekForward);
|
|
875
|
+
this.addStepBadge(d, v, "forward"), d.addEventListener("click", () => t.skip(v)), this.center.append(d);
|
|
949
876
|
}
|
|
950
877
|
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) {
|
|
951
|
-
this.gearBtn = g("imp-btn--settings", e.settings, i.settings), this.gearMenu = new
|
|
952
|
-
const d =
|
|
878
|
+
this.gearBtn = g("imp-btn--settings", e.settings, i.settings), this.gearMenu = new E(this.gearBtn);
|
|
879
|
+
const d = o("div", "imp-controls__menu-anchor");
|
|
953
880
|
d.append(this.gearBtn, this.gearMenu.root), this.gearBtn.addEventListener("click", () => this.toggleGearMenu()), this.rightItems.set("gear", d), this.registerCollapsible({
|
|
954
881
|
key: "gear",
|
|
955
882
|
el: d,
|
|
@@ -985,12 +912,12 @@ class Lt {
|
|
|
985
912
|
}
|
|
986
913
|
/** Center-cluster button — deliberately NOT `.imp-btn` (own sizing/look). */
|
|
987
914
|
makeCenterButton(t, e, i) {
|
|
988
|
-
const s =
|
|
989
|
-
return
|
|
915
|
+
const s = o("button", `imp-center-btn imp-center-btn--${t}`, { type: "button", "aria-label": e, title: e });
|
|
916
|
+
return q(s, i), s;
|
|
990
917
|
}
|
|
991
918
|
/** Caption under the seek arrow. Default "−15s"/"+15s"; overridable via `controls.seekButtons.label`. */
|
|
992
919
|
addStepBadge(t, e, i) {
|
|
993
|
-
const s =
|
|
920
|
+
const s = o("span", "imp-seek-num");
|
|
994
921
|
s.textContent = this.seekLabelFn ? this.seekLabelFn(e, i) : `${i === "back" ? "−" : "+"}${e}${this.player.labels.secondsShort}`, t.append(s);
|
|
995
922
|
}
|
|
996
923
|
// === gear (unified settings) ==========================================
|
|
@@ -1028,10 +955,10 @@ class Lt {
|
|
|
1028
955
|
const e = this.player.activeSceneType;
|
|
1029
956
|
if (t.textContent = "", !e) return;
|
|
1030
957
|
if (e.icon) {
|
|
1031
|
-
const s =
|
|
1032
|
-
|
|
958
|
+
const s = o("span", "imp-scene-type__icon");
|
|
959
|
+
q(s, e.icon), t.append(s);
|
|
1033
960
|
}
|
|
1034
|
-
const i =
|
|
961
|
+
const i = o("span", "imp-scene-type__label");
|
|
1035
962
|
i.textContent = e.title, t.append(i), t.setAttribute("aria-label", `${this.player.labels.sceneTypes}: ${e.title}`), t.title = e.title;
|
|
1036
963
|
}
|
|
1037
964
|
sceneTypeSection() {
|
|
@@ -1067,7 +994,7 @@ class Lt {
|
|
|
1067
994
|
title: i.title ?? !0,
|
|
1068
995
|
duration: i.duration ?? !0,
|
|
1069
996
|
meta: i.meta ?? !0
|
|
1070
|
-
}, this.nextPreviewEl =
|
|
997
|
+
}, this.nextPreviewEl = o("div", "imp-next-preview"), this.nextPreviewEl.hidden = !0, t.container.append(this.nextPreviewEl), this.nextBtn && this.bindNextPreview(this.nextBtn), this.centerNextBtn && this.bindNextPreview(this.centerNextBtn);
|
|
1071
998
|
}
|
|
1072
999
|
bindNextPreview(t) {
|
|
1073
1000
|
t.addEventListener("pointerenter", (e) => {
|
|
@@ -1078,24 +1005,29 @@ class Lt {
|
|
|
1078
1005
|
const e = this.nextPreviewEl, i = this.nextPreviewOpts;
|
|
1079
1006
|
if (!e || !i) return;
|
|
1080
1007
|
const s = this.player.nextSource;
|
|
1081
|
-
if (!s)
|
|
1008
|
+
if (!s) {
|
|
1009
|
+
this.hideNextPreview();
|
|
1010
|
+
return;
|
|
1011
|
+
}
|
|
1082
1012
|
e.textContent = "";
|
|
1083
|
-
const n =
|
|
1013
|
+
const n = o("div", "imp-next-preview__kicker");
|
|
1084
1014
|
if (n.textContent = this.player.labels.next, e.append(n), i.thumbnail && s.poster) {
|
|
1085
|
-
const
|
|
1086
|
-
if (
|
|
1087
|
-
|
|
1088
|
-
|
|
1015
|
+
const u = o("div", "imp-next-preview__thumb"), m = S(s.poster);
|
|
1016
|
+
if (m.addEventListener("error", () => {
|
|
1017
|
+
this.player.markSourceDead(s), this.nextPreviewEl && !this.nextPreviewEl.hidden && this.showNextPreview(t);
|
|
1018
|
+
}, { once: !0 }), u.append(m), i.duration && s.duration) {
|
|
1019
|
+
const f = o("span", "imp-next-preview__duration");
|
|
1020
|
+
f.textContent = _(s.duration), u.append(f);
|
|
1089
1021
|
}
|
|
1090
|
-
e.append(
|
|
1022
|
+
e.append(u);
|
|
1091
1023
|
}
|
|
1092
1024
|
if (i.title && s.title) {
|
|
1093
|
-
const
|
|
1094
|
-
|
|
1025
|
+
const u = o("div", "imp-next-preview__title");
|
|
1026
|
+
u.textContent = s.title, e.append(u);
|
|
1095
1027
|
}
|
|
1096
1028
|
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(),
|
|
1098
|
-
e.style.left = `${
|
|
1029
|
+
const r = this.player.container.getBoundingClientRect(), a = t.getBoundingClientRect(), c = 8, h = e.offsetWidth, p = a.left - r.left + a.width / 2 - h / 2, v = Math.max(c, Math.min(p, r.width - h - c));
|
|
1030
|
+
e.style.left = `${v}px`, e.style.bottom = `${r.height - (a.top - r.top) + 10}px`;
|
|
1099
1031
|
}
|
|
1100
1032
|
hideNextPreview() {
|
|
1101
1033
|
this.nextPreviewEl && (this.nextPreviewEl.hidden = !0);
|
|
@@ -1127,11 +1059,11 @@ class Lt {
|
|
|
1127
1059
|
}
|
|
1128
1060
|
}
|
|
1129
1061
|
attachCountTooltip(t, e) {
|
|
1130
|
-
const i =
|
|
1062
|
+
const i = o("span", "imp-count-tooltip");
|
|
1131
1063
|
return this.setCountText(i, e), i;
|
|
1132
1064
|
}
|
|
1133
1065
|
wrapWithTooltip(t, e) {
|
|
1134
|
-
const i =
|
|
1066
|
+
const i = o("div", "imp-action");
|
|
1135
1067
|
return i.append(t, e), i;
|
|
1136
1068
|
}
|
|
1137
1069
|
setCountText(t, e) {
|
|
@@ -1148,11 +1080,11 @@ class Lt {
|
|
|
1148
1080
|
buildMoreDropdown(t) {
|
|
1149
1081
|
const e = this.player, i = e.actionsOptions, { labels: s, icons: n } = e;
|
|
1150
1082
|
i.addTo && this.actionItems.push({ value: "addTo", label: s.addTo, icon: n.addTo, run: () => e.emit("action", { id: "addTo" }) }), i.share && this.actionItems.push({ value: "share", label: s.share, icon: n.share, run: () => void e.share() }), i.report && this.actionItems.push({ value: "report", label: s.report, icon: n.report, run: () => e.emit("action", { id: "report" }) });
|
|
1151
|
-
for (const
|
|
1152
|
-
this.actionItems.push({ value: `custom:${
|
|
1083
|
+
for (const c of (i.custom ?? []).filter((h) => h.placement !== "bar"))
|
|
1084
|
+
this.actionItems.push({ value: `custom:${c.id}`, label: c.title, icon: c.icon, run: () => e.emit("customaction", { id: c.id }) });
|
|
1153
1085
|
const r = g("imp-btn--more", s.more, n.more);
|
|
1154
|
-
this.moreMenu = new
|
|
1155
|
-
const a =
|
|
1086
|
+
this.moreMenu = new E(r);
|
|
1087
|
+
const a = o("div", "imp-controls__menu-anchor imp-controls__more");
|
|
1156
1088
|
a.append(r, this.moreMenu.root), r.addEventListener("click", () => {
|
|
1157
1089
|
this.closeMenus(this.moreMenu), this.moreMenu?.toggle(this.buildMoreSections());
|
|
1158
1090
|
}), t.append(a), this.moreWrap = a;
|
|
@@ -1160,25 +1092,25 @@ class Lt {
|
|
|
1160
1092
|
/** ⋯ menu = overflowed controls (in display order) + consumer actions. */
|
|
1161
1093
|
buildMoreSections() {
|
|
1162
1094
|
const t = [], e = /* @__PURE__ */ new Map(), i = [], s = ["prev", "next", "seekBack", "seekFwd", "like", "dislike", "scenes", "sceneTypes", "pip", "list", "subtitles", "speed", "quality", "gear"], n = (a) => {
|
|
1163
|
-
const
|
|
1164
|
-
return
|
|
1165
|
-
}, r = this.collapsibles.filter((a) => this.overflowed.has(a.key) && a.available()).sort((a,
|
|
1095
|
+
const c = s.indexOf(a);
|
|
1096
|
+
return c === -1 ? s.length : c;
|
|
1097
|
+
}, r = this.collapsibles.filter((a) => this.overflowed.has(a.key) && a.available()).sort((a, c) => n(a.key) - n(c.key));
|
|
1166
1098
|
for (const a of r) {
|
|
1167
|
-
const
|
|
1168
|
-
if (
|
|
1169
|
-
for (const
|
|
1170
|
-
if (!
|
|
1171
|
-
const
|
|
1172
|
-
i.push(
|
|
1099
|
+
const c = a.section();
|
|
1100
|
+
if (c)
|
|
1101
|
+
for (const h of Array.isArray(c) ? c : [c])
|
|
1102
|
+
if (!h.title && h.items.length === 1) {
|
|
1103
|
+
const p = h.items[0];
|
|
1104
|
+
i.push(p), e.set(p.value, () => h.onSelect(p.value));
|
|
1173
1105
|
} else
|
|
1174
|
-
t.push(
|
|
1106
|
+
t.push(h);
|
|
1175
1107
|
}
|
|
1176
1108
|
if (i.length > 0 && t.unshift({ title: "", items: i, onSelect: (a) => e.get(a)?.() }), this.actionItems.length > 0) {
|
|
1177
|
-
const a = new Map(this.actionItems.map((
|
|
1109
|
+
const a = new Map(this.actionItems.map((c) => [c.value, c.run]));
|
|
1178
1110
|
t.push({
|
|
1179
1111
|
title: "",
|
|
1180
|
-
items: this.actionItems.map(({ value:
|
|
1181
|
-
onSelect: (
|
|
1112
|
+
items: this.actionItems.map(({ value: c, label: h, icon: p }) => ({ value: c, label: h, icon: p, active: !1 })),
|
|
1113
|
+
onSelect: (c) => a.get(c)?.()
|
|
1182
1114
|
});
|
|
1183
1115
|
}
|
|
1184
1116
|
return t;
|
|
@@ -1240,13 +1172,13 @@ class Lt {
|
|
|
1240
1172
|
a.el.style.display = "none";
|
|
1241
1173
|
continue;
|
|
1242
1174
|
}
|
|
1243
|
-
const
|
|
1244
|
-
a.el.style.display =
|
|
1175
|
+
const c = a.available();
|
|
1176
|
+
a.el.style.display = c ? "" : "none", a.el.classList.remove("imp-collapsed");
|
|
1245
1177
|
}
|
|
1246
|
-
const n = this.collapsibles.filter((a) => a.available() && !s(a.key)).sort((a,
|
|
1178
|
+
const n = this.collapsibles.filter((a) => a.available() && !s(a.key)).sort((a, c) => a.priority - c.priority);
|
|
1247
1179
|
let r = n.length;
|
|
1248
1180
|
for (; r-- > 0 && this.overflowsRow(); ) {
|
|
1249
|
-
const a = n.find((
|
|
1181
|
+
const a = n.find((c) => !this.overflowed.has(c.key));
|
|
1250
1182
|
if (!a) break;
|
|
1251
1183
|
a.el.style.display = "none", a.el.classList.add("imp-collapsed"), this.overflowed.add(a.key);
|
|
1252
1184
|
}
|
|
@@ -1294,7 +1226,7 @@ class Lt {
|
|
|
1294
1226
|
}
|
|
1295
1227
|
/** Called by the player when per-source data (chapters/quality/subtitles) changes. */
|
|
1296
1228
|
syncFeatureButtons() {
|
|
1297
|
-
this.refreshSceneTypeButton(), this.scheduleReflow();
|
|
1229
|
+
this.refreshSceneTypeButton(), this.syncPlaylistButtons(), this.scheduleReflow();
|
|
1298
1230
|
}
|
|
1299
1231
|
syncPlaylistButtons() {
|
|
1300
1232
|
const t = this.player;
|
|
@@ -1322,9 +1254,9 @@ class Lt {
|
|
|
1322
1254
|
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();
|
|
1323
1255
|
}
|
|
1324
1256
|
}
|
|
1325
|
-
class
|
|
1257
|
+
class Lt {
|
|
1326
1258
|
constructor(t) {
|
|
1327
|
-
this.root =
|
|
1259
|
+
this.root = o("div", "imp-poster"), this.image = o("div", "imp-poster__image"), this.image.hidden = !0, this.img = S(""), this.image.append(this.img);
|
|
1328
1260
|
const e = g("imp-poster__play", t.labels.play, t.icons.bigPlay);
|
|
1329
1261
|
e.addEventListener("click", () => void t.play()), this.root.append(this.image, e), this.root.addEventListener("pointerup", (i) => {
|
|
1330
1262
|
i.target !== this.root && i.target !== this.image && i.target !== this.img || i.pointerType === "touch" && t.posterTapReveal() || t.play();
|
|
@@ -1342,11 +1274,11 @@ class Tt {
|
|
|
1342
1274
|
}
|
|
1343
1275
|
class St {
|
|
1344
1276
|
constructor(t) {
|
|
1345
|
-
this.labels = t, this.channelUrl = null, this.custom = null, this.visible = { title: !0, description: !0, sponsor: !0 }, this.root =
|
|
1277
|
+
this.labels = t, this.channelUrl = null, this.custom = null, this.visible = { title: !0, description: !0, sponsor: !0 }, this.root = o("div", "imp-pause-screen"), this.root.hidden = !0, this.defaultContent = o("div", "imp-pause-screen__default"), this.channel = o("button", "imp-channel", { type: "button" }), this.channel.hidden = !0, this.channelAvatar = o("div", "imp-channel__avatar"), this.channelName = o("div", "imp-channel__name"), this.channel.append(this.channelName, this.channelAvatar), this.channel.addEventListener("click", () => {
|
|
1346
1278
|
this.channelUrl && window.open(this.channelUrl, "_blank", "noopener");
|
|
1347
1279
|
});
|
|
1348
|
-
const e =
|
|
1349
|
-
this.title =
|
|
1280
|
+
const e = o("div", "imp-pause-screen__heading");
|
|
1281
|
+
this.title = o("div", "imp-pause-screen__title"), this.description = o("div", "imp-pause-screen__description"), this.sponsor = o("a", "imp-sponsor", { target: "_blank", rel: "nofollow noopener" }), this.sponsor.hidden = !0, this.sponsorLabel = o("span", "imp-sponsor__label"), this.sponsorText = o("span", "imp-sponsor__text"), this.sponsor.append(this.sponsorLabel, this.sponsorText), this.sponsor.addEventListener("click", (i) => i.stopPropagation()), e.append(this.sponsor, this.title, this.description), this.defaultContent.append(e, this.channel), this.root.append(this.defaultContent);
|
|
1350
1282
|
}
|
|
1351
1283
|
setCustomContent(t) {
|
|
1352
1284
|
this.custom?.remove(), this.custom = t, t && (t.classList.add("imp-pause-screen__custom"), this.root.append(t)), this.defaultContent.hidden = t !== null, this.root.classList.toggle("imp-pause-screen--custom", t !== null);
|
|
@@ -1377,9 +1309,9 @@ class St {
|
|
|
1377
1309
|
this.root.hidden = !0;
|
|
1378
1310
|
}
|
|
1379
1311
|
}
|
|
1380
|
-
class
|
|
1312
|
+
class Tt {
|
|
1381
1313
|
constructor(t) {
|
|
1382
|
-
this.player = t, this.clickBehavior = "player", this.root =
|
|
1314
|
+
this.player = t, this.clickBehavior = "player", this.root = o("div", "imp-related"), this.root.hidden = !0, this.heading = o("div", "imp-related__title"), this.grid = o("div", "imp-related__grid");
|
|
1383
1315
|
const e = g("imp-related__close", t.labels.close, t.icons.close);
|
|
1384
1316
|
e.addEventListener("click", () => this.hide()), this.root.append(e, this.heading, this.grid);
|
|
1385
1317
|
}
|
|
@@ -1391,12 +1323,12 @@ class Bt {
|
|
|
1391
1323
|
}
|
|
1392
1324
|
}
|
|
1393
1325
|
buildCard(t) {
|
|
1394
|
-
const e =
|
|
1326
|
+
const e = o("button", "imp-related__card", { type: "button" }), i = o("div", "imp-related__thumb");
|
|
1395
1327
|
if (t.poster && i.append(S(t.poster)), t.duration) {
|
|
1396
|
-
const n =
|
|
1328
|
+
const n = o("span", "imp-related__duration");
|
|
1397
1329
|
n.textContent = t.duration, i.append(n);
|
|
1398
1330
|
}
|
|
1399
|
-
const s =
|
|
1331
|
+
const s = o("div", "imp-related__card-title");
|
|
1400
1332
|
return s.textContent = t.title, e.append(i, s), e.addEventListener("click", () => {
|
|
1401
1333
|
this.player.emit("relatedclick", { item: t }), this.hide(), this.activate(t);
|
|
1402
1334
|
}), e;
|
|
@@ -1426,72 +1358,77 @@ class Bt {
|
|
|
1426
1358
|
this.root.hidden = !0;
|
|
1427
1359
|
}
|
|
1428
1360
|
}
|
|
1429
|
-
class
|
|
1361
|
+
class Bt {
|
|
1430
1362
|
constructor(t) {
|
|
1431
|
-
this.player = t, this.root =
|
|
1363
|
+
this.player = t, this.root = o("div", "imp-upnext"), this.root.hidden = !0;
|
|
1432
1364
|
}
|
|
1433
1365
|
get visible() {
|
|
1434
1366
|
return !this.root.hidden;
|
|
1435
1367
|
}
|
|
1436
1368
|
show() {
|
|
1437
1369
|
const t = this.player.nextSource;
|
|
1438
|
-
if (!t)
|
|
1370
|
+
if (!t) {
|
|
1371
|
+
this.hide();
|
|
1372
|
+
return;
|
|
1373
|
+
}
|
|
1439
1374
|
const { labels: e } = this.player;
|
|
1440
1375
|
this.root.textContent = "";
|
|
1441
|
-
const i =
|
|
1376
|
+
const i = o("div", "imp-upnext__card"), s = o("div", "imp-upnext__kicker");
|
|
1442
1377
|
if (s.textContent = e.nextVideo, i.append(s), t.poster) {
|
|
1443
|
-
const r =
|
|
1444
|
-
if (
|
|
1445
|
-
|
|
1378
|
+
const r = o("button", "imp-upnext__thumb", { type: "button", "aria-label": e.playNext }), a = S(t.poster);
|
|
1379
|
+
if (a.addEventListener("error", () => {
|
|
1380
|
+
this.player.markSourceDead(t), this.root.hidden || this.show();
|
|
1381
|
+
}, { once: !0 }), r.append(a), t.duration) {
|
|
1382
|
+
const h = o("span", "imp-upnext__duration");
|
|
1446
1383
|
h.textContent = _(t.duration), r.append(h);
|
|
1447
1384
|
}
|
|
1448
|
-
const
|
|
1449
|
-
|
|
1385
|
+
const c = o("span", "imp-upnext__thumb-play");
|
|
1386
|
+
q(c, this.player.icons.bigPlay), r.append(c), r.addEventListener("click", () => this.player.next()), i.append(r);
|
|
1450
1387
|
}
|
|
1451
1388
|
if (t.title) {
|
|
1452
|
-
const r =
|
|
1389
|
+
const r = o("div", "imp-upnext__title");
|
|
1453
1390
|
r.textContent = t.title, i.append(r);
|
|
1454
1391
|
}
|
|
1455
1392
|
t.previewMeta?.length && i.append(j(t.previewMeta, "imp-upnext"));
|
|
1456
|
-
const n =
|
|
1393
|
+
const n = o("button", "imp-upnext__btn", { type: "button" });
|
|
1457
1394
|
n.textContent = e.playNext, n.addEventListener("click", () => this.player.next()), i.append(n), this.root.append(i), this.root.hidden = !1;
|
|
1458
1395
|
}
|
|
1459
1396
|
hide() {
|
|
1460
1397
|
this.root.hidden = !0;
|
|
1461
1398
|
}
|
|
1462
1399
|
}
|
|
1463
|
-
class
|
|
1400
|
+
class Et {
|
|
1464
1401
|
constructor(t, e = "sidebar", i) {
|
|
1465
|
-
this.player = t, this.root =
|
|
1466
|
-
const s =
|
|
1402
|
+
this.player = t, this.root = o("div", `imp-playlist imp-playlist--${e}`), this.root.hidden = !0;
|
|
1403
|
+
const s = o("div", "imp-playlist__header"), n = o("div", "imp-playlist__heading");
|
|
1467
1404
|
if (i) {
|
|
1468
|
-
const
|
|
1469
|
-
|
|
1470
|
-
const
|
|
1471
|
-
|
|
1405
|
+
const c = o("div", "imp-playlist__kicker");
|
|
1406
|
+
c.textContent = t.labels.playlist;
|
|
1407
|
+
const h = o("div", "imp-playlist__name");
|
|
1408
|
+
h.textContent = i, n.append(c, h);
|
|
1472
1409
|
} else
|
|
1473
1410
|
n.textContent = t.labels.playlist;
|
|
1474
|
-
const r =
|
|
1411
|
+
const r = o("div", "imp-playlist__tools");
|
|
1475
1412
|
this.shuffleBtn = g("imp-playlist__shuffle", t.labels.shuffle, t.icons.shuffle), this.shuffleBtn.addEventListener("click", () => {
|
|
1476
1413
|
t.setShuffle(!t.shuffle), this.syncModes();
|
|
1477
1414
|
}), this.repeatBtn = g("imp-playlist__repeat", t.labels.repeat, t.icons.repeat), this.repeatBtn.addEventListener("click", () => {
|
|
1478
1415
|
t.setRepeat(!t.repeat), this.syncModes();
|
|
1479
1416
|
});
|
|
1480
1417
|
const a = g("imp-playlist__close", t.labels.close, t.icons.close);
|
|
1481
|
-
a.addEventListener("click", () => this.hide()), r.append(this.shuffleBtn, this.repeatBtn, a), s.append(n, r), this.list =
|
|
1418
|
+
a.addEventListener("click", () => this.hide()), r.append(this.shuffleBtn, this.repeatBtn, a), s.append(n, r), this.list = o("div", "imp-playlist__list"), this.root.append(s, this.list), this.rebuild(), this.syncModes();
|
|
1482
1419
|
}
|
|
1483
1420
|
syncModes() {
|
|
1484
1421
|
this.shuffleBtn.classList.toggle("imp-btn--active", this.player.shuffle), this.repeatBtn.classList.toggle("imp-btn--active", this.player.repeat);
|
|
1485
1422
|
}
|
|
1486
1423
|
rebuild() {
|
|
1487
1424
|
this.list.textContent = "", this.player.playlist.forEach((t, e) => {
|
|
1488
|
-
const i =
|
|
1425
|
+
const i = o("button", "imp-playlist__item", { type: "button" });
|
|
1489
1426
|
e === this.player.index && i.classList.add("imp-playlist__item--active");
|
|
1490
|
-
const s =
|
|
1427
|
+
const s = o("div", "imp-playlist__thumb");
|
|
1491
1428
|
t.poster && s.append(S(t.poster));
|
|
1492
|
-
const n =
|
|
1429
|
+
const n = o("div", "imp-playlist__meta"), r = o("div", "imp-playlist__title");
|
|
1493
1430
|
if (r.textContent = t.title ?? `#${e + 1}`, n.append(r), t.duration) {
|
|
1494
|
-
const a =
|
|
1431
|
+
const a = o("div", "imp-playlist__duration");
|
|
1495
1432
|
a.textContent = _(t.duration), n.append(a);
|
|
1496
1433
|
}
|
|
1497
1434
|
i.append(s, n), i.addEventListener("click", () => {
|
|
@@ -1514,26 +1451,26 @@ class Mt {
|
|
|
1514
1451
|
}
|
|
1515
1452
|
class Ct {
|
|
1516
1453
|
constructor(t, e = "bottom") {
|
|
1517
|
-
this.player = t, this.items = [], this.root =
|
|
1518
|
-
const i =
|
|
1454
|
+
this.player = t, this.items = [], this.root = o("div", `imp-playlist imp-scenes imp-playlist--${e}`), this.root.hidden = !0;
|
|
1455
|
+
const i = o("div", "imp-playlist__header"), s = o("span");
|
|
1519
1456
|
s.textContent = t.labels.scenes;
|
|
1520
1457
|
const n = g("imp-playlist__close", t.labels.close, t.icons.close);
|
|
1521
|
-
n.addEventListener("click", () => this.hide()), i.append(s, n), this.list =
|
|
1458
|
+
n.addEventListener("click", () => this.hide()), i.append(s, n), this.list = o("div", "imp-playlist__list"), this.root.append(i, this.list), t.on("chapterchange", () => this.syncActive());
|
|
1522
1459
|
}
|
|
1523
1460
|
/** Re-render from the player's current chapters + thumbnail track. */
|
|
1524
1461
|
rebuild() {
|
|
1525
1462
|
this.list.textContent = "", this.items = [];
|
|
1526
1463
|
const t = this.player.thumbnails;
|
|
1527
1464
|
for (const e of this.player.chapterList) {
|
|
1528
|
-
const i =
|
|
1465
|
+
const i = o("button", "imp-playlist__item", { type: "button" }), s = o("div", "imp-playlist__thumb"), n = t?.cueAt(e.start + 0.01) ?? null;
|
|
1529
1466
|
if (n?.xywh) {
|
|
1530
|
-
const
|
|
1531
|
-
|
|
1467
|
+
const h = o("div", "imp-scenes__sprite");
|
|
1468
|
+
h.style.width = `${n.xywh.w}px`, h.style.height = `${n.xywh.h}px`, h.style.backgroundImage = `url("${n.src}")`, h.style.backgroundPosition = `-${n.xywh.x}px -${n.xywh.y}px`, h.style.setProperty("--imp-sprite-w", String(n.xywh.w)), s.append(h);
|
|
1532
1469
|
} else n && s.append(S(n.src));
|
|
1533
|
-
const r =
|
|
1470
|
+
const r = o("div", "imp-playlist__meta"), a = o("div", "imp-playlist__title");
|
|
1534
1471
|
a.textContent = e.title || _(e.start);
|
|
1535
|
-
const
|
|
1536
|
-
|
|
1472
|
+
const c = o("div", "imp-playlist__duration");
|
|
1473
|
+
c.textContent = _(e.start), r.append(a, c), i.append(s, r), i.addEventListener("click", () => {
|
|
1537
1474
|
this.player.seek(e.start), this.player.play(), window.innerWidth <= 767 && this.hide();
|
|
1538
1475
|
}), this.list.append(i), this.items.push(i);
|
|
1539
1476
|
}
|
|
@@ -1558,21 +1495,21 @@ class Ct {
|
|
|
1558
1495
|
this.visible ? this.hide() : this.show();
|
|
1559
1496
|
}
|
|
1560
1497
|
}
|
|
1561
|
-
let
|
|
1562
|
-
function
|
|
1563
|
-
const t =
|
|
1564
|
-
t?.name === "AbortError" && /interrupted by a (new load request|call to pause)/i.test(t.message ?? "") &&
|
|
1498
|
+
let Y = 0;
|
|
1499
|
+
function tt(l) {
|
|
1500
|
+
const t = l.reason;
|
|
1501
|
+
t?.name === "AbortError" && /interrupted by a (new load request|call to pause)/i.test(t.message ?? "") && l.preventDefault();
|
|
1565
1502
|
}
|
|
1566
|
-
function
|
|
1567
|
-
typeof window < "u" && ++
|
|
1503
|
+
function Mt() {
|
|
1504
|
+
typeof window < "u" && ++Y === 1 && window.addEventListener("unhandledrejection", tt);
|
|
1568
1505
|
}
|
|
1569
|
-
function
|
|
1570
|
-
typeof window < "u" && --
|
|
1506
|
+
function Pt() {
|
|
1507
|
+
typeof window < "u" && --Y === 0 && window.removeEventListener("unhandledrejection", tt);
|
|
1571
1508
|
}
|
|
1572
|
-
function
|
|
1573
|
-
return
|
|
1509
|
+
function Q(l) {
|
|
1510
|
+
return l ? typeof l == "string" ? [{ src: l, label: "Subtitles" }] : Array.isArray(l) ? l : [l] : [];
|
|
1574
1511
|
}
|
|
1575
|
-
const
|
|
1512
|
+
const At = {
|
|
1576
1513
|
play: !0,
|
|
1577
1514
|
progress: !0,
|
|
1578
1515
|
time: !0,
|
|
@@ -1601,48 +1538,48 @@ const Rt = {
|
|
|
1601
1538
|
hideDelay: 2500,
|
|
1602
1539
|
revealBeforePlay: !0
|
|
1603
1540
|
};
|
|
1604
|
-
class
|
|
1541
|
+
class Vt {
|
|
1605
1542
|
constructor(t, e = {}) {
|
|
1606
|
-
this.scrubbing = !1, this.emitter = new
|
|
1543
|
+
this.scrubbing = !1, this.emitter = new it(), this.externalAdvance = !1, this.abort = new AbortController(), this.sources = [], this.deadSources = /* @__PURE__ */ new WeakSet(), 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;
|
|
1607
1544
|
const i = typeof t == "string" ? document.querySelector(t) : t;
|
|
1608
1545
|
if (!i) throw new Error(`[itube-player] mount target not found: ${String(t)}`);
|
|
1609
|
-
this.mount = i, this.options = e, this.labels = { ...
|
|
1546
|
+
this.mount = i, this.options = e, this.labels = { ...H, ...nt(e.language), ...e.labels }, this.icons = { ...st, ...e.icons };
|
|
1610
1547
|
const s = e.controls ?? {}, n = s.speed ?? s.settings ?? "gear";
|
|
1611
|
-
if (this.controlsOptions = { ...
|
|
1548
|
+
if (this.controlsOptions = { ...At, ...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
1549
|
const b = e.persist === !0 ? {} : e.persist;
|
|
1613
1550
|
this.persistKey = b.key ?? "itube-player", this.persistVolume = b.volume !== !1, this.persistAutoAdvance = b.autoAdvance !== !1;
|
|
1614
1551
|
}
|
|
1615
1552
|
const r = this.readPersisted();
|
|
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 =
|
|
1553
|
+
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 = o("div", "imp-player", { tabindex: "0" }), e.className && this.container.classList.add(e.className);
|
|
1617
1554
|
const a = e.styling;
|
|
1618
1555
|
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) {
|
|
1619
1556
|
const b = typeof a.borderRadius == "number" ? `${a.borderRadius}px` : a.borderRadius;
|
|
1620
1557
|
this.container.style.setProperty("--imp-radius", b);
|
|
1621
1558
|
}
|
|
1622
|
-
a?.playButtonStyle === "inverted" && this.container.classList.add("imp-player--play-inverted"), this.video =
|
|
1623
|
-
const
|
|
1624
|
-
this.video.volume = x(
|
|
1625
|
-
const
|
|
1626
|
-
this.spinner =
|
|
1627
|
-
const
|
|
1628
|
-
|
|
1559
|
+
a?.playButtonStyle === "inverted" && this.container.classList.add("imp-player--play-inverted"), this.video = o("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);
|
|
1560
|
+
const c = this.persistVolume ? r : null;
|
|
1561
|
+
this.video.volume = x(c?.volume ?? e.volume ?? 1, 0, 1), (c?.muted ?? e.muted) && (this.video.muted = !0);
|
|
1562
|
+
const h = o("div", "imp-layer");
|
|
1563
|
+
this.spinner = o("div", "imp-spinner"), this.spinner.hidden = !0, this.errorBox = o("div", "imp-error"), this.errorBox.hidden = !0, this.errorText = o("div", "imp-error__text"), this.retryBtn = o("button", "imp-error__retry", { type: "button" });
|
|
1564
|
+
const p = o("span", "imp-error__retry-label");
|
|
1565
|
+
p.textContent = this.labels.tryAgain, this.retryBtn.append(p, o("span", "imp-error__retry-spinner")), this.retryBtn.addEventListener("click", () => this.retry()), this.errorNextBtn = o("button", "imp-error__next", { type: "button" }), this.errorNextBtn.textContent = this.labels.nextVideo, this.errorNextBtn.addEventListener("click", () => {
|
|
1629
1566
|
this.clearError(), this.next();
|
|
1630
1567
|
});
|
|
1631
|
-
const
|
|
1632
|
-
|
|
1633
|
-
const
|
|
1634
|
-
|
|
1635
|
-
const
|
|
1636
|
-
|
|
1568
|
+
const v = o("div", "imp-error__actions");
|
|
1569
|
+
v.append(this.retryBtn, this.errorNextBtn), this.errorBox.append(this.errorText, v), this.pauseScreen = new St(this.labels), this.poster = new Lt(this), this.related = new Tt(this), this.related.setOptions(e.related), this.upNext = new Bt(this), this.controls = new _t(this), this.playlistPanel = new Et(this, this.playlistOptions.layout, this.playlistOptions.title || void 0), this.scenesPanel = new Ct(this, e.scenes?.layout ?? "bottom");
|
|
1570
|
+
const u = o("div", "imp-layer__middle");
|
|
1571
|
+
u.append(this.spinner, this.errorBox, this.controls.center);
|
|
1572
|
+
const m = o("div", "imp-layer__bottom");
|
|
1573
|
+
m.append(this.controls.root), h.append(this.pauseScreen.root, this.related.root, this.upNext.root, u, m), this.container.append(this.video, h, 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
1574
|
const f = e.adConfig ?? e.ads;
|
|
1638
|
-
f && f.adList.length > 0 && (this.adManager = new
|
|
1575
|
+
f && f.adList.length > 0 && (this.adManager = new mt(
|
|
1639
1576
|
{ container: this.container, contentVideo: this.video, emitter: this.emitter, labels: this.labels, closeIcon: this.icons.close },
|
|
1640
1577
|
f
|
|
1641
1578
|
)), this.emitter.on("error", ({ fatal: b }) => {
|
|
1642
1579
|
if (!b) return;
|
|
1643
1580
|
const d = this.lastPlayheadTime || this.video.currentTime;
|
|
1644
1581
|
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
|
-
}),
|
|
1582
|
+
}), Mt(), this.bindVideoEvents(), this.bindIdleHide(), e.keyboard !== !1 && this.bindKeyboard(), this.video.addEventListener("pointerup", (b) => {
|
|
1646
1583
|
if (!(this.adPlaying || !this.playedOnce)) {
|
|
1647
1584
|
if (b.pointerType === "mouse") {
|
|
1648
1585
|
this.togglePlay();
|
|
@@ -1652,7 +1589,7 @@ class Ft {
|
|
|
1652
1589
|
}
|
|
1653
1590
|
}, { signal: this.abort.signal }), this.pauseScreen.root.addEventListener("click", (b) => {
|
|
1654
1591
|
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(() => {
|
|
1592
|
+
}, { signal: this.abort.signal }), this.sources.length > 0 && this.loadItem(x(this.playlistOptions.startIndex, 0, this.sources.length - 1), !!(e.playOnInit ?? e.autoplay)), queueMicrotask(() => {
|
|
1656
1593
|
this.destroyed || this.emitter.emit("ready", { player: this });
|
|
1657
1594
|
});
|
|
1658
1595
|
}
|
|
@@ -1834,7 +1771,7 @@ class Ft {
|
|
|
1834
1771
|
}
|
|
1835
1772
|
// === subtitles ========================================================
|
|
1836
1773
|
get subtitleTracks() {
|
|
1837
|
-
return
|
|
1774
|
+
return Q(this.source?.subtitles);
|
|
1838
1775
|
}
|
|
1839
1776
|
get activeSubtitle() {
|
|
1840
1777
|
const t = this.video.textTracks;
|
|
@@ -1858,20 +1795,42 @@ class Ft {
|
|
|
1858
1795
|
get source() {
|
|
1859
1796
|
return this.sources[this.currentIndex] ?? null;
|
|
1860
1797
|
}
|
|
1798
|
+
/**
|
|
1799
|
+
* Mark a source as broken (e.g. its poster came back 4xx/5xx while building
|
|
1800
|
+
* the next-up preview — the video itself won't load either). Every "next"
|
|
1801
|
+
* computation (hover preview, end overlay, `next()`, auto-advance) skips
|
|
1802
|
+
* dead sources from then on. The playlist panel still lists them.
|
|
1803
|
+
*/
|
|
1804
|
+
markSourceDead(t) {
|
|
1805
|
+
this.deadSources.add(t), this.controls.syncFeatureButtons();
|
|
1806
|
+
}
|
|
1807
|
+
/** Linear index of the next non-dead item; -1 when nothing playable is ahead. */
|
|
1808
|
+
nextAliveIndex() {
|
|
1809
|
+
const t = this.sources.length;
|
|
1810
|
+
if (t < 2) return -1;
|
|
1811
|
+
for (let e = 1; e < t; e++) {
|
|
1812
|
+
const i = this.currentIndex + e;
|
|
1813
|
+
if (i >= t && !this.playlistOptions.loop) return -1;
|
|
1814
|
+
const s = i % t;
|
|
1815
|
+
if (!this.deadSources.has(this.sources[s])) return s;
|
|
1816
|
+
}
|
|
1817
|
+
return -1;
|
|
1818
|
+
}
|
|
1861
1819
|
/**
|
|
1862
1820
|
* The item that `next()` would play in linear order (for the next-up preview).
|
|
1863
1821
|
* `null` in shuffle mode (the pick is random) or when there is no next item.
|
|
1822
|
+
* Skips sources marked dead via `markSourceDead`.
|
|
1864
1823
|
*/
|
|
1865
1824
|
get nextSource() {
|
|
1866
1825
|
if (this.shuffleMode || this.sources.length < 2) return null;
|
|
1867
|
-
const t = this.
|
|
1868
|
-
return t
|
|
1826
|
+
const t = this.nextAliveIndex();
|
|
1827
|
+
return t === -1 ? null : this.sources[t];
|
|
1869
1828
|
}
|
|
1870
1829
|
get hasPlaylist() {
|
|
1871
1830
|
return this.sources.length > 1 || this.externalAdvance;
|
|
1872
1831
|
}
|
|
1873
1832
|
get hasNext() {
|
|
1874
|
-
return this.externalAdvance ? !0 : this.shuffleMode
|
|
1833
|
+
return this.externalAdvance ? !0 : this.shuffleMode ? this.sources.length > 1 : this.nextAliveIndex() !== -1;
|
|
1875
1834
|
}
|
|
1876
1835
|
get hasPrevious() {
|
|
1877
1836
|
return this.externalAdvance ? !0 : this.playlistOptions.loop ? this.sources.length > 1 : this.currentIndex > 0;
|
|
@@ -1901,15 +1860,14 @@ class Ft {
|
|
|
1901
1860
|
}), !0;
|
|
1902
1861
|
}
|
|
1903
1862
|
next() {
|
|
1904
|
-
if (this.hasNext
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
return;
|
|
1910
|
-
}
|
|
1911
|
-
this.playItem((this.currentIndex + 1) % this.sources.length);
|
|
1863
|
+
if (!this.hasNext || this.emitAdvanceRequest("next", this.sources.length > 1 ? (this.currentIndex + 1) % this.sources.length : null)) return;
|
|
1864
|
+
if (this.shuffleMode && this.sources.length > 1) {
|
|
1865
|
+
const e = this.sources.map((s, n) => ({ s, i: n })).filter(({ s, i: n }) => n !== this.currentIndex && !this.deadSources.has(s)), i = e.length > 0 ? e.map(({ i: s }) => s) : this.sources.map((s, n) => n).filter((s) => s !== this.currentIndex);
|
|
1866
|
+
this.playItem(i[Math.floor(Math.random() * i.length)]);
|
|
1867
|
+
return;
|
|
1912
1868
|
}
|
|
1869
|
+
const t = this.nextAliveIndex();
|
|
1870
|
+
t !== -1 && this.playItem(t);
|
|
1913
1871
|
}
|
|
1914
1872
|
previous() {
|
|
1915
1873
|
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));
|
|
@@ -1976,7 +1934,7 @@ class Ft {
|
|
|
1976
1934
|
}
|
|
1977
1935
|
/** Normalize the active group's scenes into `chapters` and refresh the UI. */
|
|
1978
1936
|
applyActiveSceneGroup() {
|
|
1979
|
-
this.chapters =
|
|
1937
|
+
this.chapters = z(this.activeSceneType?.scenes ?? [], this.video.duration), this.currentChapter = null, this.controls.progress.setChapters(this.chapters), this.controls.syncFeatureButtons(), this.scenesPanel.visible && this.scenesPanel.rebuild();
|
|
1980
1938
|
}
|
|
1981
1939
|
// === actions ==========================================================
|
|
1982
1940
|
/**
|
|
@@ -2013,66 +1971,66 @@ class Ft {
|
|
|
2013
1971
|
}
|
|
2014
1972
|
// === teardown =========================================================
|
|
2015
1973
|
destroy() {
|
|
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(),
|
|
1974
|
+
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(), Pt(), this.emitter.emit("destroy", void 0), this.emitter.removeAll());
|
|
2017
1975
|
}
|
|
2018
1976
|
// === internals ========================================================
|
|
2019
1977
|
async loadItem(t, e, i = !1) {
|
|
2020
1978
|
const s = ++this.loadToken, n = this.sources[t];
|
|
2021
1979
|
if (!n) return;
|
|
2022
1980
|
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
|
|
1981
|
+
for (const u of [...this.video.querySelectorAll("track")]) u.remove();
|
|
2024
1982
|
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
|
|
2026
|
-
const
|
|
1983
|
+
for (const u of Q(n.subtitles)) {
|
|
1984
|
+
const m = o("track", "", {
|
|
2027
1985
|
kind: "subtitles",
|
|
2028
|
-
src:
|
|
2029
|
-
label:
|
|
2030
|
-
...
|
|
1986
|
+
src: u.src,
|
|
1987
|
+
label: u.label,
|
|
1988
|
+
...u.srclang ? { srclang: u.srclang } : {}
|
|
2031
1989
|
});
|
|
2032
|
-
|
|
1990
|
+
u.default && m.setAttribute("default", ""), this.video.append(m);
|
|
2033
1991
|
}
|
|
2034
1992
|
let r = n.src, a = n.type;
|
|
2035
1993
|
if (n.qualities && n.qualities.length > 0) {
|
|
2036
|
-
const
|
|
2037
|
-
this.progressiveQuality =
|
|
1994
|
+
const u = Math.max(0, n.qualities.findIndex((m) => m.src === n.src));
|
|
1995
|
+
this.progressiveQuality = u, r = n.qualities[u].src, a = n.qualities[u].type ?? a;
|
|
2038
1996
|
}
|
|
2039
1997
|
this.video.preload = this.adManager?.hasPendingPreRoll ? "auto" : "metadata";
|
|
2040
|
-
const
|
|
1998
|
+
const c = await gt(this.video, r, a, {
|
|
2041
1999
|
onLevels: () => {
|
|
2042
2000
|
s === this.loadToken && this.controls.syncFeatureButtons();
|
|
2043
2001
|
},
|
|
2044
|
-
onLevelSwitch: (
|
|
2045
|
-
onError: (
|
|
2002
|
+
onLevelSwitch: (u) => this.emitter.emit("qualitychange", { label: u }),
|
|
2003
|
+
onError: (u, m) => this.emitter.emit("error", { message: u, cause: m, fatal: !0 })
|
|
2046
2004
|
});
|
|
2047
2005
|
if (s !== this.loadToken) {
|
|
2048
|
-
|
|
2006
|
+
c.destroy();
|
|
2049
2007
|
return;
|
|
2050
2008
|
}
|
|
2051
|
-
if (this.sourceController =
|
|
2052
|
-
s === this.loadToken && (this.thumbTrack =
|
|
2053
|
-
}).catch((
|
|
2009
|
+
if (this.sourceController = c, this.emitter.emit("sourcechange", { source: n, index: t }), n.thumbnails && Z.load(n.thumbnails).then((u) => {
|
|
2010
|
+
s === this.loadToken && (this.thumbTrack = u, this.controls.progress.setThumbnails(u), this.scenesPanel.visible && this.scenesPanel.rebuild());
|
|
2011
|
+
}).catch((u) => this.emitter.emit("error", { message: "Failed to load thumbnails track", cause: u })), n.sceneGroups && n.sceneGroups.length > 0) {
|
|
2054
2012
|
this.sceneGroupList = n.sceneGroups, this.activeSceneGroupId = n.sceneGroups[0].id;
|
|
2055
|
-
const
|
|
2013
|
+
const u = () => {
|
|
2056
2014
|
s === this.loadToken && this.applyActiveSceneGroup();
|
|
2057
2015
|
};
|
|
2058
|
-
Number.isFinite(this.video.duration) && this.video.duration > 0 ?
|
|
2016
|
+
Number.isFinite(this.video.duration) && this.video.duration > 0 ? u() : this.video.addEventListener("loadedmetadata", u, { once: !0, signal: this.abort.signal });
|
|
2059
2017
|
} else if (n.chapters) {
|
|
2060
|
-
const
|
|
2018
|
+
const u = (m) => {
|
|
2061
2019
|
const f = () => {
|
|
2062
|
-
s === this.loadToken && (this.chapters =
|
|
2020
|
+
s === this.loadToken && (this.chapters = z(m, this.video.duration), this.controls.progress.setChapters(this.chapters), this.controls.syncFeatureButtons(), this.scenesPanel.visible && this.scenesPanel.rebuild());
|
|
2063
2021
|
};
|
|
2064
2022
|
Number.isFinite(this.video.duration) && this.video.duration > 0 ? f() : this.video.addEventListener("loadedmetadata", f, { once: !0, signal: this.abort.signal });
|
|
2065
2023
|
};
|
|
2066
|
-
typeof n.chapters == "string" ?
|
|
2024
|
+
typeof n.chapters == "string" ? vt(n.chapters).then((m) => u(m)).catch((m) => this.emitter.emit("error", { message: "Failed to load chapters track", cause: m })) : u(n.chapters);
|
|
2067
2025
|
}
|
|
2068
|
-
const
|
|
2069
|
-
if (
|
|
2070
|
-
const
|
|
2026
|
+
const h = n.heatmap, p = h && !Array.isArray(h), v = p ? h.values.length > 0 : !!(h && h.length > 0);
|
|
2027
|
+
if (h && v && this.controlsOptions.heatmap) {
|
|
2028
|
+
const u = () => {
|
|
2071
2029
|
if (s !== this.loadToken) return;
|
|
2072
|
-
const
|
|
2073
|
-
this.controls.progress.setHeatmap(
|
|
2030
|
+
const m = p ? lt(h.values, h.mode) : at(h, this.video.duration);
|
|
2031
|
+
this.controls.progress.setHeatmap(m, p ? h.smoothing ?? 1 : 1);
|
|
2074
2032
|
};
|
|
2075
|
-
|
|
2033
|
+
p || Number.isFinite(this.video.duration) && this.video.duration > 0 ? u() : this.video.addEventListener("loadedmetadata", u, { once: !0, signal: this.abort.signal });
|
|
2076
2034
|
}
|
|
2077
2035
|
e && this.play(i);
|
|
2078
2036
|
}
|
|
@@ -2086,7 +2044,7 @@ class Ft {
|
|
|
2086
2044
|
this.handleEnded();
|
|
2087
2045
|
}, { signal: t }), e.addEventListener("timeupdate", () => {
|
|
2088
2046
|
!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 =
|
|
2047
|
+
const i = J(this.chapters, e.currentTime);
|
|
2090
2048
|
i !== this.currentChapter && (this.currentChapter = i, this.emitter.emit("chapterchange", { chapter: i }));
|
|
2091
2049
|
}, { signal: t }), e.addEventListener("progress", () => {
|
|
2092
2050
|
this.emitter.emit("progress", { buffered: this.bufferedEnd });
|
|
@@ -2232,22 +2190,22 @@ class Ft {
|
|
|
2232
2190
|
}
|
|
2233
2191
|
}
|
|
2234
2192
|
export {
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2193
|
+
it as Emitter,
|
|
2194
|
+
Vt as Player,
|
|
2195
|
+
Z as ThumbnailTrack,
|
|
2238
2196
|
at as buildHeatmapValues,
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2197
|
+
J as chapterAt,
|
|
2198
|
+
st as defaultIcons,
|
|
2199
|
+
H as defaultLabels,
|
|
2242
2200
|
_ as formatTime,
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2201
|
+
nt as getLocale,
|
|
2202
|
+
ht as heatmapPath,
|
|
2203
|
+
ft as isHlsSource,
|
|
2204
|
+
vt as loadChaptersVtt,
|
|
2205
|
+
z as normalizeChapters,
|
|
2206
|
+
Nt as registerLocale,
|
|
2207
|
+
qt as registerLocales,
|
|
2208
|
+
Ft as registeredLanguages,
|
|
2209
|
+
ct as resolveVast
|
|
2252
2210
|
};
|
|
2253
2211
|
//# sourceMappingURL=core.js.map
|