itube-modern-player 0.4.0 → 0.4.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 +17 -0
- package/dist/core.cjs +3 -3
- package/dist/core.cjs.map +1 -1
- package/dist/core.js +325 -292
- package/dist/core.js.map +1 -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-DZFT0XMa.js → labels-DRuCG6N8.js} +2 -1
- package/dist/labels-DRuCG6N8.js.map +1 -0
- package/dist/labels-ub9G1Vyq.cjs +2 -0
- package/dist/labels-ub9G1Vyq.cjs.map +1 -0
- package/dist/locales.cjs +1 -1
- package/dist/locales.cjs.map +1 -1
- package/dist/locales.js +11 -1
- package/dist/locales.js.map +1 -1
- package/dist/player.d.ts +8 -0
- package/dist/style.css +1 -1
- package/dist/types.d.ts +27 -1
- package/package.json +1 -1
- package/dist/labels-DZFT0XMa.js.map +0 -1
- package/dist/labels-y0IHe3i9.cjs +0 -2
- package/dist/labels-y0IHe3i9.cjs.map +0 -1
package/dist/core.js
CHANGED
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
import { d as
|
|
2
|
-
function o(
|
|
3
|
-
const i = document.createElement(
|
|
1
|
+
import { d as V } from "./labels-DRuCG6N8.js";
|
|
2
|
+
function o(a, t, e) {
|
|
3
|
+
const i = document.createElement(a);
|
|
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
|
|
9
|
-
const i = o("button", `imp-btn ${
|
|
8
|
+
function g(a, t, e) {
|
|
9
|
+
const i = o("button", `imp-btn ${a}`, { type: "button", "aria-label": t, title: t });
|
|
10
10
|
return i.innerHTML = e, i;
|
|
11
11
|
}
|
|
12
|
-
function E(
|
|
13
|
-
|
|
12
|
+
function E(a, t, e) {
|
|
13
|
+
a.innerHTML = t, e !== void 0 && (a.setAttribute("aria-label", e), a.setAttribute("title", e));
|
|
14
14
|
}
|
|
15
|
-
function w(
|
|
16
|
-
return Math.min(e, Math.max(t,
|
|
15
|
+
function w(a, t, e) {
|
|
16
|
+
return Math.min(e, Math.max(t, a));
|
|
17
17
|
}
|
|
18
|
-
function x(
|
|
19
|
-
if (!Number.isFinite(
|
|
20
|
-
const t = Math.floor(
|
|
18
|
+
function x(a) {
|
|
19
|
+
if (!Number.isFinite(a) || a < 0) return "0:00";
|
|
20
|
+
const t = Math.floor(a % 60), e = Math.floor(a / 60 % 60), i = Math.floor(a / 3600), s = i > 0 ? String(e).padStart(2, "0") : String(e), n = String(t).padStart(2, "0");
|
|
21
21
|
return i > 0 ? `${i}:${s}:${n}` : `${s}:${n}`;
|
|
22
22
|
}
|
|
23
|
-
function I(
|
|
24
|
-
const t =
|
|
23
|
+
function I(a) {
|
|
24
|
+
const t = a.trim().match(/^(?:(\d+):)?(\d{1,2}):(\d{2})(?:[.,](\d{1,3}))?$/);
|
|
25
25
|
if (!t) return null;
|
|
26
26
|
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;
|
|
27
27
|
return e * 3600 + i * 60 + s + n / 1e3;
|
|
28
28
|
}
|
|
29
|
-
function Q(
|
|
30
|
-
const t = [], e =
|
|
29
|
+
function Q(a) {
|
|
30
|
+
const t = [], e = a.replace(/\r\n?/g, `
|
|
31
31
|
`).split(/\n\n+/);
|
|
32
32
|
for (const i of e) {
|
|
33
33
|
const s = i.split(`
|
|
34
|
-
`).filter((
|
|
34
|
+
`).filter((m) => m.trim() !== "");
|
|
35
35
|
if (s.length === 0) continue;
|
|
36
|
-
let n = s.findIndex((
|
|
36
|
+
let n = s.findIndex((m) => m.includes("-->"));
|
|
37
37
|
if (n === -1) continue;
|
|
38
|
-
const [r,
|
|
38
|
+
const [r, l] = s[n].split("-->"), h = I(r), c = I((l ?? "").split(" ")[1] ?? l ?? "") ?? I(l ?? "");
|
|
39
39
|
if (h === null || c === null) continue;
|
|
40
40
|
const u = s.slice(n + 1).join(`
|
|
41
41
|
`).trim();
|
|
@@ -43,14 +43,14 @@ function Q(l) {
|
|
|
43
43
|
}
|
|
44
44
|
return t;
|
|
45
45
|
}
|
|
46
|
-
function
|
|
46
|
+
function K(a, t) {
|
|
47
47
|
try {
|
|
48
|
-
return new URL(
|
|
48
|
+
return new URL(a, new URL(t, window.location.href)).toString();
|
|
49
49
|
} catch {
|
|
50
|
-
return
|
|
50
|
+
return a;
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
|
-
class
|
|
53
|
+
class X {
|
|
54
54
|
constructor() {
|
|
55
55
|
this.listeners = /* @__PURE__ */ new Map();
|
|
56
56
|
}
|
|
@@ -82,150 +82,154 @@ class K {
|
|
|
82
82
|
this.listeners.clear();
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
|
-
const
|
|
86
|
-
play:
|
|
87
|
-
pause:
|
|
88
|
-
replay:
|
|
89
|
-
bigPlay:
|
|
90
|
-
volumeHigh:
|
|
91
|
-
volumeLow:
|
|
92
|
-
volumeMute:
|
|
93
|
-
fullscreen:
|
|
94
|
-
fullscreenExit:
|
|
95
|
-
pip:
|
|
96
|
-
settings:
|
|
97
|
-
speed:
|
|
98
|
-
scenes:
|
|
99
|
-
shuffle:
|
|
100
|
-
repeat:
|
|
101
|
-
subtitles:
|
|
102
|
-
list:
|
|
103
|
-
next:
|
|
104
|
-
previous:
|
|
85
|
+
const f = (a, t = "0 0 24 24") => `<svg viewBox="${t}" fill="currentColor" aria-hidden="true" focusable="false">${a}</svg>`, J = {
|
|
86
|
+
play: f('<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"/>'),
|
|
87
|
+
pause: f('<rect x="6" y="5" width="4" height="14" rx="1"/><rect x="14" y="5" width="4" height="14" rx="1"/>'),
|
|
88
|
+
replay: f('<path d="M12 5V2.5L7.5 6 12 9.5V7a5 5 0 1 1-5 5H5a7 7 0 1 0 7-7Z"/>'),
|
|
89
|
+
bigPlay: f('<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"/>'),
|
|
90
|
+
volumeHigh: f('<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"/>'),
|
|
91
|
+
volumeLow: f('<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"/>'),
|
|
92
|
+
volumeMute: f('<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"/>'),
|
|
93
|
+
fullscreen: f('<path d="M5 5h5v2H7v3H5V5Zm9 0h5v5h-2V7h-3V5ZM5 14h2v3h3v2H5v-5Zm12 0h2v5h-5v-2h3v-3Z"/>'),
|
|
94
|
+
fullscreenExit: f('<path d="M10 10H5V8h3V5h2v5Zm4 0V5h2v3h3v2h-5Zm-4 4v5H8v-3H5v-2h5Zm4 0h5v2h-3v3h-2v-5Z"/>'),
|
|
95
|
+
pip: f('<path d="M3 5h18v14H3V5Zm2 2v10h14V7H5Z"/><rect x="12" y="11" width="6" height="4"/>'),
|
|
96
|
+
settings: f('<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"/>'),
|
|
97
|
+
speed: f('<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"/>'),
|
|
98
|
+
scenes: f('<path d="M3 5h18v14H3V5Zm2 2v10h3V7H5Zm5 0v10h9V7h-9Zm-5 3h3v1H5v-1Zm0 3h3v1H5v-1Z"/>'),
|
|
99
|
+
shuffle: f('<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)"/>'),
|
|
100
|
+
repeat: f('<path d="M7 7h10v2.5L21 6l-4-3.5V5H5v6h2V7Zm10 10H7v-2.5L3 18l4 3.5V19h12v-6h-2v4Z"/>'),
|
|
101
|
+
subtitles: f('<path d="M3 5h18v14H3V5Zm2 2v10h14V7H5Zm2 3h6v2H7v-2Zm8 0h2v2h-2v-2ZM7 14h2v2H7v-2Zm4 0h6v2h-6v-2Z"/>'),
|
|
102
|
+
list: f('<path d="M4 6h2v2H4V6Zm4 0h12v2H8V6ZM4 11h2v2H4v-2Zm4 0h12v2H8v-2ZM4 16h2v2H4v-2Zm4 0h12v2H8v-2Z"/>'),
|
|
103
|
+
next: f('<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"/>'),
|
|
104
|
+
previous: f('<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"/>'),
|
|
105
105
|
// Thin circular-arrow ("rotate") icons — open center so the step number reads
|
|
106
106
|
// clearly inside the ring (matches the reference skip ±N look).
|
|
107
107
|
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>',
|
|
108
108
|
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>',
|
|
109
|
-
like:
|
|
110
|
-
dislike:
|
|
111
|
-
addTo:
|
|
112
|
-
share:
|
|
113
|
-
report:
|
|
114
|
-
more:
|
|
115
|
-
close:
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
109
|
+
like: f('<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"/>'),
|
|
110
|
+
dislike: f('<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"/>'),
|
|
111
|
+
addTo: f('<path d="M4 6h12v2H4V6Zm0 4h12v2H4v-2Zm0 4h8v2H4v-2Zm14 0v-4h2v4h4v2h-4v4h-2v-4h-4v-2h4Z"/>'),
|
|
112
|
+
share: f('<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"/>'),
|
|
113
|
+
report: f('<path d="M5 3h2v18H5V3Zm4 1h10l-2.5 4L19 12H9V4Z"/>'),
|
|
114
|
+
more: f('<circle cx="12" cy="5" r="2"/><circle cx="12" cy="12" r="2"/><circle cx="12" cy="19" r="2"/>'),
|
|
115
|
+
close: f('<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"/>'),
|
|
116
|
+
// Generic "uploaded by a user" glyph (head + shoulders) for preview meta.
|
|
117
|
+
user: f('<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"/>'),
|
|
118
|
+
// Generic "channel" glyph (play badge) for preview meta when a channel is set.
|
|
119
|
+
channel: f('<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"/>')
|
|
120
|
+
}, P = { en: V };
|
|
121
|
+
function _t(a, t) {
|
|
122
|
+
P[a] = t;
|
|
119
123
|
}
|
|
120
|
-
function Lt(
|
|
121
|
-
for (const [t, e] of Object.entries(
|
|
124
|
+
function Lt(a) {
|
|
125
|
+
for (const [t, e] of Object.entries(a))
|
|
122
126
|
e && (P[t] = e);
|
|
123
127
|
}
|
|
124
|
-
function Y(
|
|
125
|
-
return
|
|
128
|
+
function Y(a) {
|
|
129
|
+
return a && P[a] || V;
|
|
126
130
|
}
|
|
127
131
|
function Bt() {
|
|
128
132
|
return Object.keys(P);
|
|
129
133
|
}
|
|
130
|
-
function tt(
|
|
131
|
-
if (
|
|
134
|
+
function tt(a, t, e = 100) {
|
|
135
|
+
if (a.length === 0 || !Number.isFinite(t) || t <= 0) return [];
|
|
132
136
|
const i = new Array(e).fill(0);
|
|
133
137
|
let s = !1;
|
|
134
|
-
for (const c of
|
|
138
|
+
for (const c of a) {
|
|
135
139
|
if (!Number.isFinite(c.time) || c.time < 0 || c.time > t) continue;
|
|
136
140
|
const u = Math.max(0, c.value);
|
|
137
141
|
if (u === 0) continue;
|
|
138
|
-
const
|
|
139
|
-
i[
|
|
142
|
+
const m = Math.min(e - 1, Math.floor(c.time / t * e));
|
|
143
|
+
i[m] += u, s = !0;
|
|
140
144
|
}
|
|
141
145
|
if (!s) return [];
|
|
142
146
|
const n = [0.06, 0.24, 0.4, 0.24, 0.06], r = i.map(
|
|
143
|
-
(c, u) => n.reduce((
|
|
144
|
-
),
|
|
145
|
-
if (
|
|
147
|
+
(c, u) => n.reduce((m, p, v) => m + p * (i[u + v - 2] ?? 0), 0)
|
|
148
|
+
), l = Math.max(...r);
|
|
149
|
+
if (l <= 0) return [];
|
|
146
150
|
const h = 0.08;
|
|
147
|
-
return r.map((c) => h + (1 - h) * (c /
|
|
151
|
+
return r.map((c) => h + (1 - h) * (c / l));
|
|
148
152
|
}
|
|
149
|
-
function et(
|
|
150
|
-
if (
|
|
151
|
-
const i = t / (
|
|
153
|
+
function et(a, t = 1e3, e = 100) {
|
|
154
|
+
if (a.length === 0) return "";
|
|
155
|
+
const i = t / (a.length - 1 || 1);
|
|
152
156
|
let s = `M 0 ${e}`;
|
|
153
|
-
return
|
|
157
|
+
return a.forEach((n, r) => {
|
|
154
158
|
s += ` L ${(r * i).toFixed(1)} ${(e - n * e).toFixed(1)}`;
|
|
155
159
|
}), s += ` L ${t} ${e} Z`, s;
|
|
156
160
|
}
|
|
157
|
-
async function it(
|
|
158
|
-
if (
|
|
161
|
+
async function it(a, t) {
|
|
162
|
+
if (a.src)
|
|
159
163
|
return {
|
|
160
|
-
roll:
|
|
161
|
-
mediaUrl:
|
|
162
|
-
clickThrough:
|
|
164
|
+
roll: a.roll,
|
|
165
|
+
mediaUrl: a.src,
|
|
166
|
+
clickThrough: a.clickUrl,
|
|
163
167
|
impressions: [],
|
|
164
168
|
tracking: {}
|
|
165
169
|
};
|
|
166
|
-
if (!
|
|
167
|
-
return z(
|
|
170
|
+
if (!a.vastTag) throw new Error('Ad roll has neither "vastTag" nor "src"');
|
|
171
|
+
return z(a, a.vastTag, t, 0, { impressions: [], tracking: {} });
|
|
168
172
|
}
|
|
169
|
-
async function z(
|
|
173
|
+
async function z(a, t, e, i, s) {
|
|
170
174
|
if (i > e.maxWrapperDepth) throw new Error("VAST wrapper depth limit exceeded");
|
|
171
175
|
const n = new AbortController(), r = setTimeout(() => n.abort(), e.requestTimeout);
|
|
172
|
-
let
|
|
176
|
+
let l;
|
|
173
177
|
try {
|
|
174
|
-
const
|
|
175
|
-
if (!
|
|
176
|
-
|
|
178
|
+
const y = await fetch(t, { signal: n.signal, credentials: "omit" });
|
|
179
|
+
if (!y.ok) throw new Error(`VAST request failed (${y.status})`);
|
|
180
|
+
l = await y.text();
|
|
177
181
|
} finally {
|
|
178
182
|
clearTimeout(r);
|
|
179
183
|
}
|
|
180
|
-
const h = new DOMParser().parseFromString(
|
|
184
|
+
const h = new DOMParser().parseFromString(l, "text/xml");
|
|
181
185
|
if (h.querySelector("parsererror")) throw new Error("VAST response is not valid XML");
|
|
182
186
|
const c = h.querySelector("VAST > Ad");
|
|
183
187
|
if (!c) throw new Error("VAST response contains no ads");
|
|
184
188
|
st(c, s);
|
|
185
189
|
const u = c.querySelector(":scope > Wrapper");
|
|
186
190
|
if (u) {
|
|
187
|
-
const
|
|
188
|
-
if (!
|
|
189
|
-
return z(
|
|
190
|
-
}
|
|
191
|
-
const
|
|
192
|
-
if (!
|
|
193
|
-
const
|
|
194
|
-
if (!
|
|
195
|
-
const
|
|
196
|
-
if (!
|
|
191
|
+
const y = S(u.querySelector("VASTAdTagURI"));
|
|
192
|
+
if (!y) throw new Error("VAST wrapper without VASTAdTagURI");
|
|
193
|
+
return z(a, y, e, i + 1, s);
|
|
194
|
+
}
|
|
195
|
+
const m = c.querySelector(":scope > InLine");
|
|
196
|
+
if (!m) throw new Error("VAST ad has neither InLine nor Wrapper");
|
|
197
|
+
const p = m.querySelector("Creatives > Creative > Linear");
|
|
198
|
+
if (!p) throw new Error("VAST ad has no Linear creative");
|
|
199
|
+
const v = nt(p);
|
|
200
|
+
if (!v) throw new Error("VAST ad has no playable MediaFile");
|
|
197
201
|
return {
|
|
198
|
-
roll:
|
|
199
|
-
mediaUrl:
|
|
200
|
-
mediaType:
|
|
201
|
-
clickThrough: S(
|
|
202
|
-
duration: N(S(
|
|
202
|
+
roll: a.roll,
|
|
203
|
+
mediaUrl: v.url,
|
|
204
|
+
mediaType: v.type,
|
|
205
|
+
clickThrough: S(p.querySelector("VideoClicks > ClickThrough")) ?? a.clickUrl,
|
|
206
|
+
duration: N(S(p.querySelector(":scope > Duration"))),
|
|
203
207
|
skipOffset: rt(
|
|
204
|
-
|
|
205
|
-
N(S(
|
|
208
|
+
p.getAttribute("skipoffset"),
|
|
209
|
+
N(S(p.querySelector(":scope > Duration")))
|
|
206
210
|
),
|
|
207
211
|
impressions: s.impressions,
|
|
208
212
|
tracking: s.tracking,
|
|
209
|
-
adTitle: S(
|
|
213
|
+
adTitle: S(m.querySelector(":scope > AdTitle")) ?? void 0
|
|
210
214
|
};
|
|
211
215
|
}
|
|
212
|
-
function st(
|
|
216
|
+
function st(a, t) {
|
|
213
217
|
var e, i;
|
|
214
|
-
for (const s of
|
|
218
|
+
for (const s of a.querySelectorAll("Impression")) {
|
|
215
219
|
const n = S(s);
|
|
216
220
|
n && t.impressions.push(n);
|
|
217
221
|
}
|
|
218
|
-
for (const s of
|
|
222
|
+
for (const s of a.querySelectorAll("Linear > TrackingEvents > Tracking")) {
|
|
219
223
|
const n = s.getAttribute("event"), r = S(s);
|
|
220
224
|
!n || !r || ["start", "firstQuartile", "midpoint", "thirdQuartile", "complete", "skip", "pause", "resume"].includes(n) && ((e = t.tracking)[n] ?? (e[n] = [])).push(r);
|
|
221
225
|
}
|
|
222
|
-
for (const s of
|
|
226
|
+
for (const s of a.querySelectorAll("Linear > VideoClicks > ClickTracking")) {
|
|
223
227
|
const n = S(s);
|
|
224
228
|
n && ((i = t.tracking).click ?? (i.click = [])).push(n);
|
|
225
229
|
}
|
|
226
230
|
}
|
|
227
|
-
function nt(
|
|
228
|
-
const e = [...
|
|
231
|
+
function nt(a) {
|
|
232
|
+
const e = [...a.querySelectorAll("MediaFiles > MediaFile")].map((r) => ({
|
|
229
233
|
url: S(r) ?? "",
|
|
230
234
|
type: r.getAttribute("type") ?? void 0,
|
|
231
235
|
delivery: r.getAttribute("delivery") ?? "",
|
|
@@ -235,31 +239,31 @@ function nt(l) {
|
|
|
235
239
|
(r) => !r.type || /(video\/(mp4|webm|ogg)|application\/(x-mpegurl|vnd\.apple\.mpegurl))/i.test(r.type)
|
|
236
240
|
);
|
|
237
241
|
if (e.length === 0) return null;
|
|
238
|
-
e.sort((r,
|
|
242
|
+
e.sort((r, l) => r.bitrate - l.bitrate);
|
|
239
243
|
const i = e.filter((r) => r.delivery !== "streaming"), s = i.length > 0 ? i : e, n = s[Math.floor(s.length / 2)];
|
|
240
244
|
return { url: n.url, type: n.type };
|
|
241
245
|
}
|
|
242
|
-
function N(
|
|
243
|
-
if (!
|
|
244
|
-
const t =
|
|
246
|
+
function N(a) {
|
|
247
|
+
if (!a) return;
|
|
248
|
+
const t = a.trim().match(/^(?:(\d+):)?(\d{1,2}):(\d{2})(?:\.(\d{1,3}))?$/);
|
|
245
249
|
if (t)
|
|
246
250
|
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);
|
|
247
251
|
}
|
|
248
|
-
function rt(
|
|
249
|
-
if (!
|
|
250
|
-
const e =
|
|
251
|
-
return e ? t !== void 0 ? Number(e[1]) / 100 * t : void 0 : N(
|
|
252
|
+
function rt(a, t) {
|
|
253
|
+
if (!a) return;
|
|
254
|
+
const e = a.trim().match(/^(\d+(?:\.\d+)?)%$/);
|
|
255
|
+
return e ? t !== void 0 ? Number(e[1]) / 100 * t : void 0 : N(a);
|
|
252
256
|
}
|
|
253
|
-
function M(
|
|
254
|
-
if (
|
|
255
|
-
for (const t of
|
|
257
|
+
function M(a) {
|
|
258
|
+
if (a)
|
|
259
|
+
for (const t of a)
|
|
256
260
|
try {
|
|
257
261
|
new Image().src = t;
|
|
258
262
|
} catch {
|
|
259
263
|
}
|
|
260
264
|
}
|
|
261
|
-
function S(
|
|
262
|
-
return
|
|
265
|
+
function S(a) {
|
|
266
|
+
return a?.textContent?.trim().replace(/^<!\[CDATA\[|\]\]>$/g, "").trim() || null;
|
|
263
267
|
}
|
|
264
268
|
class ot {
|
|
265
269
|
constructor(t, e) {
|
|
@@ -331,8 +335,8 @@ class ot {
|
|
|
331
335
|
const r = await it(n, this.opts);
|
|
332
336
|
await this.playAd(r);
|
|
333
337
|
} catch (r) {
|
|
334
|
-
const
|
|
335
|
-
this.host.emitter.emit("aderror", { roll: n, error:
|
|
338
|
+
const l = r instanceof Error ? r : new Error(String(r));
|
|
339
|
+
this.host.emitter.emit("aderror", { roll: n, error: l });
|
|
336
340
|
}
|
|
337
341
|
if (this.destroyed) return;
|
|
338
342
|
}
|
|
@@ -345,28 +349,28 @@ class ot {
|
|
|
345
349
|
}
|
|
346
350
|
playAd(t) {
|
|
347
351
|
return new Promise((e) => {
|
|
348
|
-
const { labels: i } = this.host, s = o("div", "imp-ad"), n = this.ensureAdVideo(), r = new AbortController(),
|
|
352
|
+
const { labels: i } = this.host, s = o("div", "imp-ad"), n = this.ensureAdVideo(), r = new AbortController(), l = r.signal;
|
|
349
353
|
n.src = t.mediaUrl, n.muted = this.host.contentVideo.muted, n.volume = this.host.contentVideo.volume;
|
|
350
354
|
const h = o("div", "imp-spinner imp-ad__spinner"), c = o("div", "imp-ad__hud"), u = o("span", "imp-ad__badge");
|
|
351
355
|
u.textContent = t.adTitle ? `${i.adLabel} · ${t.adTitle}` : i.adLabel;
|
|
352
|
-
const
|
|
353
|
-
c.append(u,
|
|
354
|
-
const
|
|
355
|
-
let
|
|
356
|
-
t.clickThrough && (
|
|
357
|
-
const
|
|
358
|
-
|
|
356
|
+
const m = o("span", "imp-ad__countdown");
|
|
357
|
+
c.append(u, m);
|
|
358
|
+
const p = o("div", "imp-ad__actions");
|
|
359
|
+
let v = null;
|
|
360
|
+
t.clickThrough && (v = o("button", "imp-ad__visit", { type: "button" }), v.textContent = i.visitAdvertiser, p.append(v));
|
|
361
|
+
const y = o("button", "imp-ad__skip", { type: "button" });
|
|
362
|
+
y.hidden = !0, p.append(y), s.append(n, h, c, p), this.host.container.append(s), this.layer = s;
|
|
359
363
|
const T = t.skipOffset ?? this.opts.skipDelay, d = /* @__PURE__ */ new Set(), b = (k) => {
|
|
360
364
|
d.has(k) || (d.add(k), M(t.tracking[k]));
|
|
361
365
|
};
|
|
362
|
-
let A = Date.now(),
|
|
366
|
+
let A = Date.now(), F = -1;
|
|
363
367
|
const j = setInterval(() => {
|
|
364
368
|
if (n.paused) {
|
|
365
369
|
A = Date.now();
|
|
366
370
|
return;
|
|
367
371
|
}
|
|
368
|
-
if (n.currentTime !==
|
|
369
|
-
|
|
372
|
+
if (n.currentTime !== F) {
|
|
373
|
+
F = n.currentTime, A = Date.now();
|
|
370
374
|
return;
|
|
371
375
|
}
|
|
372
376
|
Date.now() - A >= this.opts.mediaTimeout && (this.host.emitter.emit("aderror", {
|
|
@@ -380,34 +384,34 @@ class ot {
|
|
|
380
384
|
};
|
|
381
385
|
n.addEventListener("playing", () => {
|
|
382
386
|
M(t.impressions), b("start"), this.host.emitter.emit("adstart", { ad: t });
|
|
383
|
-
}, { once: !0, signal:
|
|
387
|
+
}, { once: !0, signal: l }), n.addEventListener("playing", () => {
|
|
384
388
|
h.hidden = !0;
|
|
385
|
-
}, { signal:
|
|
389
|
+
}, { signal: l }), n.addEventListener("waiting", () => {
|
|
386
390
|
h.hidden = !1;
|
|
387
|
-
}, { signal:
|
|
391
|
+
}, { signal: l }), n.addEventListener("timeupdate", () => {
|
|
388
392
|
const k = n.currentTime, L = n.duration;
|
|
389
|
-
if (Number.isFinite(L) && L > 0 && (
|
|
393
|
+
if (Number.isFinite(L) && L > 0 && (m.textContent = x(Math.max(0, L - k)), k / L >= 0.25 && b("firstQuartile"), k / L >= 0.5 && b("midpoint"), k / L >= 0.75 && b("thirdQuartile")), T >= 0) {
|
|
390
394
|
const D = Math.ceil(T - k);
|
|
391
|
-
D > 0 ? (
|
|
395
|
+
D > 0 ? (y.hidden = !1, y.disabled = !0, y.textContent = `${i.skipAdIn} ${D}`) : (y.hidden = !1, y.disabled = !1, y.textContent = i.skipAd);
|
|
392
396
|
}
|
|
393
|
-
}, { signal:
|
|
397
|
+
}, { signal: l }), n.addEventListener("ended", () => H(!1), { signal: l }), n.addEventListener("error", () => {
|
|
394
398
|
this.host.emitter.emit("aderror", {
|
|
395
399
|
roll: { roll: t.roll },
|
|
396
400
|
error: new Error("Ad media failed to play")
|
|
397
401
|
}), R();
|
|
398
|
-
}, { signal:
|
|
402
|
+
}, { signal: l }), y.addEventListener("click", () => H(!0));
|
|
399
403
|
const O = () => {
|
|
400
404
|
t.clickThrough && (b("click"), this.host.emitter.emit("adclick", { ad: t }), window.open(t.clickThrough, "_blank", "noopener"), n.pause());
|
|
401
405
|
};
|
|
402
|
-
n.addEventListener("click", O, { signal:
|
|
406
|
+
n.addEventListener("click", O, { signal: l }), v?.addEventListener("click", O);
|
|
403
407
|
let Z = !1, C = !1;
|
|
404
408
|
n.addEventListener("playing", () => {
|
|
405
409
|
Z = !0;
|
|
406
|
-
}, { once: !0, signal:
|
|
410
|
+
}, { once: !0, signal: l }), n.addEventListener("pause", () => {
|
|
407
411
|
n.ended || !s.isConnected || (s.classList.add("imp-ad--paused"), Z && !C && (C = !0, M(t.tracking.pause), this.host.emitter.emit("adpause", { ad: t })));
|
|
408
|
-
}, { signal:
|
|
412
|
+
}, { signal: l }), n.addEventListener("play", () => {
|
|
409
413
|
s.classList.remove("imp-ad--paused"), C && (C = !1, M(t.tracking.resume), this.host.emitter.emit("adresume", { ad: t }));
|
|
410
|
-
}, { signal:
|
|
414
|
+
}, { signal: l }), s.addEventListener("click", (k) => {
|
|
411
415
|
(k.target === s || s.classList.contains("imp-ad--paused")) && n.paused && n.play().catch(() => {
|
|
412
416
|
});
|
|
413
417
|
}), n.play().catch(() => {
|
|
@@ -423,8 +427,8 @@ class ot {
|
|
|
423
427
|
this.destroyed = !0, this.adVideo?.pause(), this.layer?.remove(), this.layer = null, this.adVideo = null;
|
|
424
428
|
}
|
|
425
429
|
}
|
|
426
|
-
function W(
|
|
427
|
-
const e = [...
|
|
430
|
+
function W(a, t) {
|
|
431
|
+
const e = [...a].sort((s, n) => s.start - n.start), i = [];
|
|
428
432
|
for (let s = 0; s < e.length; s++) {
|
|
429
433
|
const n = Math.max(0, e[s].start);
|
|
430
434
|
if (Number.isFinite(t) && n >= t) continue;
|
|
@@ -433,26 +437,26 @@ function W(l, t) {
|
|
|
433
437
|
}
|
|
434
438
|
return i;
|
|
435
439
|
}
|
|
436
|
-
async function lt(
|
|
437
|
-
const t = await fetch(
|
|
440
|
+
async function lt(a) {
|
|
441
|
+
const t = await fetch(a);
|
|
438
442
|
if (!t.ok) throw new Error(`Failed to load chapters VTT (${t.status})`);
|
|
439
443
|
const e = await t.text();
|
|
440
444
|
return Q(e).map((i) => ({ start: i.start, end: i.end, title: i.text }));
|
|
441
445
|
}
|
|
442
|
-
function U(
|
|
443
|
-
for (const e of
|
|
446
|
+
function U(a, t) {
|
|
447
|
+
for (const e of a)
|
|
444
448
|
if (t >= e.start && t < e.end) return e;
|
|
445
449
|
return null;
|
|
446
450
|
}
|
|
447
|
-
function at(
|
|
448
|
-
return t ? /application\/(x-mpegurl|vnd\.apple\.mpegurl)/i.test(t) : /\.m3u8(\?|#|$)/i.test(
|
|
451
|
+
function at(a, t) {
|
|
452
|
+
return t ? /application\/(x-mpegurl|vnd\.apple\.mpegurl)/i.test(t) : /\.m3u8(\?|#|$)/i.test(a);
|
|
449
453
|
}
|
|
450
454
|
let _;
|
|
451
455
|
async function ht() {
|
|
452
456
|
if (_ !== void 0) return _;
|
|
453
|
-
const
|
|
454
|
-
if (
|
|
455
|
-
return _ =
|
|
457
|
+
const a = globalThis.Hls;
|
|
458
|
+
if (a)
|
|
459
|
+
return _ = a, _;
|
|
456
460
|
try {
|
|
457
461
|
_ = (await import("hls.js/light")).default;
|
|
458
462
|
} catch {
|
|
@@ -460,14 +464,14 @@ async function ht() {
|
|
|
460
464
|
}
|
|
461
465
|
return _;
|
|
462
466
|
}
|
|
463
|
-
async function ct(
|
|
467
|
+
async function ct(a, t, e, i) {
|
|
464
468
|
if (at(t, e)) {
|
|
465
|
-
const s =
|
|
466
|
-
return n && n.isSupported() ? dt(n,
|
|
469
|
+
const s = a.canPlayType("application/vnd.apple.mpegurl"), n = s ? null : await ht();
|
|
470
|
+
return n && n.isSupported() ? dt(n, a, t, i) : s ? (a.src = t, $(a)) : (i.onError("HLS is not supported in this browser and hls.js could not be loaded."), $(a));
|
|
467
471
|
}
|
|
468
|
-
return
|
|
472
|
+
return a.src = t, $(a);
|
|
469
473
|
}
|
|
470
|
-
function $(
|
|
474
|
+
function $(a) {
|
|
471
475
|
return {
|
|
472
476
|
kind: "native",
|
|
473
477
|
levels: [],
|
|
@@ -475,12 +479,12 @@ function $(l) {
|
|
|
475
479
|
setLevel() {
|
|
476
480
|
},
|
|
477
481
|
destroy() {
|
|
478
|
-
|
|
482
|
+
a.removeAttribute("src"), a.load();
|
|
479
483
|
}
|
|
480
484
|
};
|
|
481
485
|
}
|
|
482
|
-
function dt(
|
|
483
|
-
const s = new
|
|
486
|
+
function dt(a, t, e, i) {
|
|
487
|
+
const s = new a({ enableWorker: !0 }), n = {
|
|
484
488
|
kind: "hls",
|
|
485
489
|
levels: [],
|
|
486
490
|
selected: -1,
|
|
@@ -491,30 +495,30 @@ function dt(l, t, e, i) {
|
|
|
491
495
|
s.destroy(), t.removeAttribute("src"), t.load();
|
|
492
496
|
}
|
|
493
497
|
};
|
|
494
|
-
s.on(
|
|
498
|
+
s.on(a.Events.MANIFEST_PARSED, () => {
|
|
495
499
|
n.levels = s.levels.map((h, c) => ({
|
|
496
500
|
index: c,
|
|
497
501
|
label: h.height ? `${h.height}p` : `${Math.round(h.bitrate / 1e3)} kbps`
|
|
498
502
|
})).reverse(), i.onLevels(n.levels);
|
|
499
|
-
}), s.on(
|
|
503
|
+
}), s.on(a.Events.LEVEL_SWITCHED, (h, c) => {
|
|
500
504
|
const u = s.levels[c.level];
|
|
501
505
|
u && i.onLevelSwitch(u.height ? `${u.height}p` : `${Math.round(u.bitrate / 1e3)} kbps`);
|
|
502
506
|
});
|
|
503
|
-
let r = 0,
|
|
504
|
-
return s.on(
|
|
507
|
+
let r = 0, l = !1;
|
|
508
|
+
return s.on(a.Events.ERROR, (h, c) => {
|
|
505
509
|
if (c.fatal)
|
|
506
510
|
switch (c.type) {
|
|
507
|
-
case
|
|
511
|
+
case a.ErrorTypes.NETWORK_ERROR:
|
|
508
512
|
s.startLoad();
|
|
509
513
|
break;
|
|
510
|
-
case
|
|
514
|
+
case a.ErrorTypes.MEDIA_ERROR:
|
|
511
515
|
r < 3 ? (r++, s.recoverMediaError()) : (i.onError(`HLS media error: ${c.details}`, c), s.destroy());
|
|
512
516
|
break;
|
|
513
517
|
default:
|
|
514
|
-
if (
|
|
518
|
+
if (l)
|
|
515
519
|
i.onError(`HLS fatal error: ${c.details}`, c), s.destroy();
|
|
516
520
|
else {
|
|
517
|
-
|
|
521
|
+
l = !0;
|
|
518
522
|
try {
|
|
519
523
|
s.loadSource(e), s.startLoad();
|
|
520
524
|
} catch {
|
|
@@ -524,7 +528,7 @@ function dt(l, t, e, i) {
|
|
|
524
528
|
}
|
|
525
529
|
}), s.loadSource(e), s.attachMedia(t), n;
|
|
526
530
|
}
|
|
527
|
-
class
|
|
531
|
+
class q {
|
|
528
532
|
constructor(t) {
|
|
529
533
|
this.cues = t;
|
|
530
534
|
}
|
|
@@ -533,16 +537,16 @@ class F {
|
|
|
533
537
|
if (!e.ok) throw new Error(`Failed to load thumbnails VTT (${e.status})`);
|
|
534
538
|
const i = await e.text(), s = [];
|
|
535
539
|
for (const n of Q(i)) {
|
|
536
|
-
const [r,
|
|
540
|
+
const [r, l] = n.text.trim().split("#");
|
|
537
541
|
if (!r) continue;
|
|
538
542
|
const h = {
|
|
539
543
|
start: n.start,
|
|
540
544
|
end: n.end,
|
|
541
|
-
src:
|
|
542
|
-
}, c =
|
|
545
|
+
src: K(r, t)
|
|
546
|
+
}, c = l?.match(/xywh=(\d+),(\d+),(\d+),(\d+)/);
|
|
543
547
|
c && (h.xywh = { x: Number(c[1]), y: Number(c[2]), w: Number(c[3]), h: Number(c[4]) }), s.push(h);
|
|
544
548
|
}
|
|
545
|
-
return s.sort((n, r) => n.start - r.start), new
|
|
549
|
+
return s.sort((n, r) => n.start - r.start), new q(s);
|
|
546
550
|
}
|
|
547
551
|
cueAt(t) {
|
|
548
552
|
let e = 0, i = this.cues.length - 1;
|
|
@@ -593,8 +597,8 @@ class B {
|
|
|
593
597
|
n.textContent = i.label;
|
|
594
598
|
const r = o("span", "imp-menu__value");
|
|
595
599
|
r.textContent = i.value ?? "";
|
|
596
|
-
const
|
|
597
|
-
|
|
600
|
+
const l = o("span", "imp-menu__chevron");
|
|
601
|
+
l.innerHTML = ut, s.append(n, r, l), s.addEventListener("click", () => this.renderSettingsDetail(t, i)), e.append(s);
|
|
598
602
|
}
|
|
599
603
|
this.root.append(e);
|
|
600
604
|
}
|
|
@@ -681,8 +685,8 @@ class mt {
|
|
|
681
685
|
for (const n of i) {
|
|
682
686
|
const r = o("div", "imp-progress__segment");
|
|
683
687
|
r.style.flexGrow = String(Math.max(n.end - n.start, 0.01));
|
|
684
|
-
const
|
|
685
|
-
r.append(
|
|
688
|
+
const l = o("div", "imp-progress__fill");
|
|
689
|
+
r.append(l), this.track.append(r), this.segments.push({ chapter: n, root: r, fill: l });
|
|
686
690
|
}
|
|
687
691
|
}
|
|
688
692
|
setThumbnails(t) {
|
|
@@ -724,8 +728,8 @@ class mt {
|
|
|
724
728
|
this.tooltipChapter.textContent = i?.title ?? "", this.tooltipChapter.hidden = !i?.title;
|
|
725
729
|
const s = this.thumbnails?.cueAt(e) ?? null;
|
|
726
730
|
s ? (this.tooltipThumb.hidden = !1, this.tooltipThumb.style.backgroundImage = `url("${s.src}")`, s.xywh ? (this.tooltipThumb.style.width = `${s.xywh.w}px`, this.tooltipThumb.style.height = `${s.xywh.h}px`, this.tooltipThumb.style.backgroundPosition = `-${s.xywh.x}px -${s.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");
|
|
727
|
-
const n = this.root.getBoundingClientRect(), r = w(t.clientX - n.left, 0, n.width),
|
|
728
|
-
this.tooltip.style.left = `${w(r,
|
|
731
|
+
const n = this.root.getBoundingClientRect(), r = w(t.clientX - n.left, 0, n.width), l = this.tooltip.offsetWidth / 2;
|
|
732
|
+
this.tooltip.style.left = `${w(r, l, Math.max(l, n.width - l))}px`;
|
|
729
733
|
}
|
|
730
734
|
hideTooltip() {
|
|
731
735
|
this.tooltip.classList.remove("imp-progress__tooltip--visible");
|
|
@@ -746,14 +750,14 @@ class vt {
|
|
|
746
750
|
}), s.progress && this.root.append(this.progress.root);
|
|
747
751
|
const n = o("div", "imp-controls__row");
|
|
748
752
|
this.row = n, this.root.append(n);
|
|
749
|
-
const r = o("div", "imp-controls__group"),
|
|
750
|
-
this.rightGroup =
|
|
753
|
+
const r = o("div", "imp-controls__group"), l = o("div", "imp-controls__group");
|
|
754
|
+
this.rightGroup = l;
|
|
751
755
|
const h = o("div", "imp-controls__spacer");
|
|
752
|
-
this.chapterLabel = o("div", "imp-controls__chapter"), n.append(r, h,
|
|
753
|
-
const c = typeof s.seekButtons == "object" ? s.seekButtons : {}, u = c.back ?? t.seekStep,
|
|
754
|
-
if (this.seekLabelFn = c.label, s.playlist && t.hasPlaylist && !s.hidePrev && (this.prevBtn =
|
|
756
|
+
this.chapterLabel = o("div", "imp-controls__chapter"), n.append(r, h, l), h.append(this.chapterLabel);
|
|
757
|
+
const c = typeof s.seekButtons == "object" ? s.seekButtons : {}, u = c.back ?? t.seekStep, m = c.forward ?? t.seekStep;
|
|
758
|
+
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 && (this.nextBtn = g("imp-btn--next", e.next, i.next), this.nextBtn.addEventListener("click", () => t.next()), r.append(this.nextBtn)), s.volume) {
|
|
755
759
|
const d = o("div", "imp-volume");
|
|
756
|
-
this.muteBtn =
|
|
760
|
+
this.muteBtn = g("imp-btn--mute", e.mute, i.volumeHigh), this.muteBtn.addEventListener("click", () => t.toggleMute()), this.volumeSlider = o("input", "imp-volume__slider", {
|
|
757
761
|
type: "range",
|
|
758
762
|
min: "0",
|
|
759
763
|
max: "1",
|
|
@@ -765,7 +769,7 @@ class vt {
|
|
|
765
769
|
}
|
|
766
770
|
s.time && (this.timeLabel = o("div", "imp-controls__time"), this.liveBadge = o("span", "imp-controls__live"), this.liveBadge.textContent = e.live, this.liveBadge.hidden = !0, r.append(this.timeLabel, this.liveBadge)), this.buildLikeDislike();
|
|
767
771
|
for (const d of (t.actionsOptions.custom ?? []).filter((b) => b.placement === "bar")) {
|
|
768
|
-
const b =
|
|
772
|
+
const b = g(`imp-btn--custom imp-btn--custom-${d.id}`, d.title, d.icon ?? i.more);
|
|
769
773
|
b.addEventListener("click", () => t.emit("customaction", { id: d.id })), this.rightItems.set(`custom:${d.id}`, b), this.registerCollapsible({
|
|
770
774
|
key: `custom:${d.id}`,
|
|
771
775
|
el: b,
|
|
@@ -774,9 +778,9 @@ class vt {
|
|
|
774
778
|
section: () => this.simpleSection(`custom:${d.id}`, d.title, d.icon ?? i.more, () => t.emit("customaction", { id: d.id }))
|
|
775
779
|
});
|
|
776
780
|
}
|
|
777
|
-
const
|
|
778
|
-
if (this.gear = { speed: T === "gear", quality:
|
|
779
|
-
this.subtitlesBtn =
|
|
781
|
+
const p = (d) => d === !1 ? "off" : d === "bar" ? "bar" : "gear", v = p(s.subtitles), y = p(s.quality), T = p(s.speed);
|
|
782
|
+
if (this.gear = { speed: T === "gear", quality: y === "gear", subtitles: v === "gear" }, v === "bar") {
|
|
783
|
+
this.subtitlesBtn = g("imp-btn--subtitles", e.subtitles, i.subtitles), this.subtitlesMenu = new B(this.subtitlesBtn);
|
|
780
784
|
const d = o("div", "imp-controls__menu-anchor");
|
|
781
785
|
d.append(this.subtitlesBtn, this.subtitlesMenu.root), this.subtitlesBtn.addEventListener("click", () => this.toggleSubtitlesMenu()), this.rightItems.set("subtitles", d), this.registerCollapsible({
|
|
782
786
|
key: "subtitles",
|
|
@@ -786,8 +790,8 @@ class vt {
|
|
|
786
790
|
section: () => this.subtitlesSection()
|
|
787
791
|
});
|
|
788
792
|
}
|
|
789
|
-
if (
|
|
790
|
-
this.qualityBtn =
|
|
793
|
+
if (y === "bar") {
|
|
794
|
+
this.qualityBtn = g("imp-btn--quality", e.quality, i.settings), this.qualityMenu = new B(this.qualityBtn);
|
|
791
795
|
const d = o("div", "imp-controls__menu-anchor");
|
|
792
796
|
d.append(this.qualityBtn, this.qualityMenu.root), this.qualityBtn.addEventListener("click", () => this.toggleQualityMenu()), this.rightItems.set("quality", d), this.registerCollapsible({
|
|
793
797
|
key: "quality",
|
|
@@ -798,7 +802,7 @@ class vt {
|
|
|
798
802
|
});
|
|
799
803
|
}
|
|
800
804
|
if (T === "bar") {
|
|
801
|
-
this.settingsBtn =
|
|
805
|
+
this.settingsBtn = g("imp-btn--speed", e.speed, i.speed), this.settingsMenu = new B(this.settingsBtn);
|
|
802
806
|
const d = o("div", "imp-controls__menu-anchor");
|
|
803
807
|
d.append(this.settingsBtn, this.settingsMenu.root), this.settingsBtn.addEventListener("click", () => this.toggleSettingsMenu()), this.rightItems.set("speed", d), this.registerCollapsible({
|
|
804
808
|
key: "speed",
|
|
@@ -808,7 +812,7 @@ class vt {
|
|
|
808
812
|
section: () => this.speedSection()
|
|
809
813
|
});
|
|
810
814
|
}
|
|
811
|
-
if (s.scenes && (this.scenesBtn =
|
|
815
|
+
if (s.scenes && (this.scenesBtn = g("imp-btn--scenes", e.scenes, i.scenes), this.scenesBtn.addEventListener("click", () => t.toggleScenesPanel()), this.rightItems.set("scenes", this.scenesBtn), this.registerCollapsible({
|
|
812
816
|
key: "scenes",
|
|
813
817
|
el: this.scenesBtn,
|
|
814
818
|
priority: 25,
|
|
@@ -826,7 +830,7 @@ class vt {
|
|
|
826
830
|
});
|
|
827
831
|
}
|
|
828
832
|
if (s.playlist && t.hasPlaylist) {
|
|
829
|
-
const d =
|
|
833
|
+
const d = g("imp-btn--list", e.playlist, i.list);
|
|
830
834
|
d.addEventListener("click", () => t.togglePlaylistPanel()), this.rightItems.set("playlist", d), this.registerCollapsible({
|
|
831
835
|
key: "list",
|
|
832
836
|
el: d,
|
|
@@ -836,7 +840,7 @@ class vt {
|
|
|
836
840
|
});
|
|
837
841
|
}
|
|
838
842
|
if (s.pip && "requestPictureInPicture" in HTMLVideoElement.prototype) {
|
|
839
|
-
const d =
|
|
843
|
+
const d = g("imp-btn--pip", e.pip, i.pip);
|
|
840
844
|
d.addEventListener("click", () => void t.togglePip()), this.rightItems.set("pip", d), this.registerCollapsible({
|
|
841
845
|
key: "pip",
|
|
842
846
|
el: d,
|
|
@@ -845,7 +849,7 @@ class vt {
|
|
|
845
849
|
section: () => this.simpleSection("pip", e.pip, i.pip, () => void t.togglePip())
|
|
846
850
|
});
|
|
847
851
|
}
|
|
848
|
-
if (s.fullscreen && (this.fullscreenBtn =
|
|
852
|
+
if (s.fullscreen && (this.fullscreenBtn = g("imp-btn--fullscreen", e.fullscreen, i.fullscreen), this.fullscreenBtn.addEventListener("click", () => void t.toggleFullscreen()), this.rightItems.set("fullscreen", this.fullscreenBtn)), this.prevBtn && this.registerCollapsible({
|
|
849
853
|
key: "prev",
|
|
850
854
|
el: this.prevBtn,
|
|
851
855
|
priority: 70,
|
|
@@ -874,7 +878,7 @@ class vt {
|
|
|
874
878
|
el: d,
|
|
875
879
|
priority: 82,
|
|
876
880
|
available: () => Number.isFinite(t.duration) && t.duration > 0,
|
|
877
|
-
section: () => this.simpleSection("seekFwd", `${e.seekForward} ${
|
|
881
|
+
section: () => this.simpleSection("seekFwd", `${e.seekForward} ${m}s`, i.seekForward, () => t.skip(m))
|
|
878
882
|
});
|
|
879
883
|
}
|
|
880
884
|
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) {
|
|
@@ -882,11 +886,11 @@ class vt {
|
|
|
882
886
|
this.addStepBadge(d, u, "back"), d.addEventListener("click", () => t.skip(-u)), this.center.append(d);
|
|
883
887
|
}
|
|
884
888
|
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) {
|
|
885
|
-
const d = this.makeCenterButton("seek-forward", `${e.seekForward} ${
|
|
886
|
-
this.addStepBadge(d,
|
|
889
|
+
const d = this.makeCenterButton("seek-forward", `${e.seekForward} ${m}s`, i.seekForward);
|
|
890
|
+
this.addStepBadge(d, m, "forward"), d.addEventListener("click", () => t.skip(m)), this.center.append(d);
|
|
887
891
|
}
|
|
888
892
|
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) {
|
|
889
|
-
this.gearBtn =
|
|
893
|
+
this.gearBtn = g("imp-btn--settings", e.settings, i.settings), this.gearMenu = new B(this.gearBtn);
|
|
890
894
|
const d = o("div", "imp-controls__menu-anchor");
|
|
891
895
|
d.append(this.gearBtn, this.gearMenu.root), this.gearBtn.addEventListener("click", () => this.toggleGearMenu()), this.rightItems.set("gear", d), this.registerCollapsible({
|
|
892
896
|
key: "gear",
|
|
@@ -896,7 +900,7 @@ class vt {
|
|
|
896
900
|
section: () => this.gearSections()
|
|
897
901
|
});
|
|
898
902
|
}
|
|
899
|
-
this.layoutRightCluster(
|
|
903
|
+
this.layoutRightCluster(l), this.buildMoreDropdown(l), this.bind(), this.syncVolume(), this.syncPlayState(), this.setLikeState(t.actionsOptions.likeState ?? null), typeof ResizeObserver < "u" && (this.resizeObserver = new ResizeObserver(() => this.scheduleReflow()), this.resizeObserver.observe(t.container)), this.onWindowResize = () => this.scheduleReflow(), window.addEventListener("resize", this.onWindowResize);
|
|
900
904
|
}
|
|
901
905
|
registerCollapsible(t) {
|
|
902
906
|
this.collapsibles.push(t);
|
|
@@ -1020,24 +1024,24 @@ class vt {
|
|
|
1020
1024
|
e.textContent = "";
|
|
1021
1025
|
const n = o("div", "imp-next-preview__kicker");
|
|
1022
1026
|
if (n.textContent = this.player.labels.next, e.append(n), i.thumbnail && s.poster) {
|
|
1023
|
-
const
|
|
1024
|
-
if (
|
|
1025
|
-
const
|
|
1026
|
-
|
|
1027
|
+
const p = o("div", "imp-next-preview__thumb");
|
|
1028
|
+
if (p.style.backgroundImage = `url("${s.poster}")`, i.duration && s.duration) {
|
|
1029
|
+
const v = o("span", "imp-next-preview__duration");
|
|
1030
|
+
v.textContent = x(s.duration), p.append(v);
|
|
1027
1031
|
}
|
|
1028
|
-
e.append(
|
|
1032
|
+
e.append(p);
|
|
1029
1033
|
}
|
|
1030
1034
|
if (i.title && s.title) {
|
|
1031
|
-
const
|
|
1032
|
-
|
|
1035
|
+
const p = o("div", "imp-next-preview__title");
|
|
1036
|
+
p.textContent = s.title, e.append(p);
|
|
1033
1037
|
}
|
|
1034
1038
|
if (i.meta && s.previewMeta?.length) {
|
|
1035
|
-
const
|
|
1036
|
-
|
|
1039
|
+
const p = o("div", "imp-next-preview__meta");
|
|
1040
|
+
p.textContent = s.previewMeta.join(" · "), e.append(p);
|
|
1037
1041
|
}
|
|
1038
1042
|
e.hidden = !1;
|
|
1039
|
-
const r = this.player.container.getBoundingClientRect(),
|
|
1040
|
-
e.style.left = `${
|
|
1043
|
+
const r = this.player.container.getBoundingClientRect(), l = t.getBoundingClientRect(), h = 8, c = e.offsetWidth, u = l.left - r.left + l.width / 2 - c / 2, m = Math.max(h, Math.min(u, r.width - c - h));
|
|
1044
|
+
e.style.left = `${m}px`, e.style.bottom = `${r.height - (l.top - r.top) + 10}px`;
|
|
1041
1045
|
}
|
|
1042
1046
|
hideNextPreview() {
|
|
1043
1047
|
this.nextPreviewEl && (this.nextPreviewEl.hidden = !0);
|
|
@@ -1046,7 +1050,7 @@ class vt {
|
|
|
1046
1050
|
buildLikeDislike() {
|
|
1047
1051
|
const t = this.player, e = t.actionsOptions, { labels: i, icons: s } = t;
|
|
1048
1052
|
if (e.like) {
|
|
1049
|
-
this.likeBtn =
|
|
1053
|
+
this.likeBtn = g("imp-btn--like", i.like, s.like), this.likeBtn.addEventListener("click", () => t.emit("action", { id: "like" })), this.likeCountEl = this.attachCountTooltip(this.likeBtn, e.likeCount);
|
|
1050
1054
|
const n = this.wrapWithTooltip(this.likeBtn, this.likeCountEl);
|
|
1051
1055
|
this.rightItems.set("like", n), this.registerCollapsible({
|
|
1052
1056
|
key: "like",
|
|
@@ -1057,7 +1061,7 @@ class vt {
|
|
|
1057
1061
|
});
|
|
1058
1062
|
}
|
|
1059
1063
|
if (e.dislike) {
|
|
1060
|
-
this.dislikeBtn =
|
|
1064
|
+
this.dislikeBtn = g("imp-btn--dislike", i.dislike, s.dislike), this.dislikeBtn.addEventListener("click", () => t.emit("action", { id: "dislike" })), this.dislikeCountEl = this.attachCountTooltip(this.dislikeBtn, e.dislikeCount);
|
|
1061
1065
|
const n = this.wrapWithTooltip(this.dislikeBtn, this.dislikeCountEl);
|
|
1062
1066
|
this.rightItems.set("dislike", n), this.registerCollapsible({
|
|
1063
1067
|
key: "dislike",
|
|
@@ -1092,21 +1096,21 @@ class vt {
|
|
|
1092
1096
|
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" }) });
|
|
1093
1097
|
for (const h of (i.custom ?? []).filter((c) => c.placement !== "bar"))
|
|
1094
1098
|
this.actionItems.push({ value: `custom:${h.id}`, label: h.title, icon: h.icon, run: () => e.emit("customaction", { id: h.id }) });
|
|
1095
|
-
const r =
|
|
1099
|
+
const r = g("imp-btn--more", s.more, n.more);
|
|
1096
1100
|
this.moreMenu = new B(r);
|
|
1097
|
-
const
|
|
1098
|
-
|
|
1101
|
+
const l = o("div", "imp-controls__menu-anchor imp-controls__more");
|
|
1102
|
+
l.append(r, this.moreMenu.root), r.addEventListener("click", () => {
|
|
1099
1103
|
this.closeMenus(this.moreMenu), this.moreMenu?.toggle(this.buildMoreSections());
|
|
1100
|
-
}), t.append(
|
|
1104
|
+
}), t.append(l), this.moreWrap = l;
|
|
1101
1105
|
}
|
|
1102
1106
|
/** ⋯ menu = overflowed controls (in display order) + consumer actions. */
|
|
1103
1107
|
buildMoreSections() {
|
|
1104
|
-
const t = [], e = /* @__PURE__ */ new Map(), i = [], s = ["prev", "next", "seekBack", "seekFwd", "like", "dislike", "scenes", "sceneTypes", "pip", "list", "subtitles", "speed", "quality", "gear"], n = (
|
|
1105
|
-
const h = s.indexOf(
|
|
1108
|
+
const t = [], e = /* @__PURE__ */ new Map(), i = [], s = ["prev", "next", "seekBack", "seekFwd", "like", "dislike", "scenes", "sceneTypes", "pip", "list", "subtitles", "speed", "quality", "gear"], n = (l) => {
|
|
1109
|
+
const h = s.indexOf(l);
|
|
1106
1110
|
return h === -1 ? s.length : h;
|
|
1107
|
-
}, r = this.collapsibles.filter((
|
|
1108
|
-
for (const
|
|
1109
|
-
const h =
|
|
1111
|
+
}, r = this.collapsibles.filter((l) => this.overflowed.has(l.key) && l.available()).sort((l, h) => n(l.key) - n(h.key));
|
|
1112
|
+
for (const l of r) {
|
|
1113
|
+
const h = l.section();
|
|
1110
1114
|
if (h)
|
|
1111
1115
|
for (const c of Array.isArray(h) ? h : [h])
|
|
1112
1116
|
if (!c.title && c.items.length === 1) {
|
|
@@ -1115,12 +1119,12 @@ class vt {
|
|
|
1115
1119
|
} else
|
|
1116
1120
|
t.push(c);
|
|
1117
1121
|
}
|
|
1118
|
-
if (i.length > 0 && t.unshift({ title: "", items: i, onSelect: (
|
|
1119
|
-
const
|
|
1122
|
+
if (i.length > 0 && t.unshift({ title: "", items: i, onSelect: (l) => e.get(l)?.() }), this.actionItems.length > 0) {
|
|
1123
|
+
const l = new Map(this.actionItems.map((h) => [h.value, h.run]));
|
|
1120
1124
|
t.push({
|
|
1121
1125
|
title: "",
|
|
1122
1126
|
items: this.actionItems.map(({ value: h, label: c, icon: u }) => ({ value: h, label: c, icon: u, active: !1 })),
|
|
1123
|
-
onSelect: (h) =>
|
|
1127
|
+
onSelect: (h) => l.get(h)?.()
|
|
1124
1128
|
});
|
|
1125
1129
|
}
|
|
1126
1130
|
return t;
|
|
@@ -1175,26 +1179,26 @@ class vt {
|
|
|
1175
1179
|
reflow() {
|
|
1176
1180
|
const t = window.innerWidth <= 767, i = this.player.controlsOptions.seekPlacement !== "bar" || t;
|
|
1177
1181
|
this.center.style.display = i ? "flex" : "none", this.centerPrevBtn && (this.centerPrevBtn.style.display = t ? "" : "none"), this.centerNextBtn && (this.centerNextBtn.style.display = t ? "" : "none"), this.playBtn && (this.playBtn.style.display = t ? "none" : "");
|
|
1178
|
-
const s = (
|
|
1182
|
+
const s = (l) => l === "seekBack" || l === "seekFwd" ? i : l === "prev" || l === "next" ? t : !1;
|
|
1179
1183
|
this.overflowed.clear();
|
|
1180
|
-
for (const
|
|
1181
|
-
if (s(
|
|
1182
|
-
|
|
1184
|
+
for (const l of this.collapsibles) {
|
|
1185
|
+
if (s(l.key)) {
|
|
1186
|
+
l.el.style.display = "none";
|
|
1183
1187
|
continue;
|
|
1184
1188
|
}
|
|
1185
|
-
const h =
|
|
1186
|
-
|
|
1189
|
+
const h = l.available();
|
|
1190
|
+
l.el.style.display = h ? "" : "none", l.el.classList.remove("imp-collapsed");
|
|
1187
1191
|
}
|
|
1188
|
-
const n = this.collapsibles.filter((
|
|
1192
|
+
const n = this.collapsibles.filter((l) => l.available() && !s(l.key)).sort((l, h) => l.priority - h.priority);
|
|
1189
1193
|
let r = n.length;
|
|
1190
1194
|
for (; r-- > 0 && this.overflowsRow(); ) {
|
|
1191
|
-
const
|
|
1192
|
-
if (!
|
|
1193
|
-
|
|
1195
|
+
const l = n.find((h) => !this.overflowed.has(h.key));
|
|
1196
|
+
if (!l) break;
|
|
1197
|
+
l.el.style.display = "none", l.el.classList.add("imp-collapsed"), this.overflowed.add(l.key);
|
|
1194
1198
|
}
|
|
1195
1199
|
if (this.moreWrap) {
|
|
1196
|
-
const
|
|
1197
|
-
this.moreWrap.style.display =
|
|
1200
|
+
const l = this.actionItems.length > 0 || this.overflowed.size > 0;
|
|
1201
|
+
this.moreWrap.style.display = l ? "" : "none";
|
|
1198
1202
|
}
|
|
1199
1203
|
}
|
|
1200
1204
|
overflowsRow() {
|
|
@@ -1263,7 +1267,7 @@ class vt {
|
|
|
1263
1267
|
class ft {
|
|
1264
1268
|
constructor(t) {
|
|
1265
1269
|
this.root = o("div", "imp-poster"), this.image = o("img", "imp-poster__image", { alt: "", decoding: "async" }), this.image.hidden = !0;
|
|
1266
|
-
const e =
|
|
1270
|
+
const e = g("imp-poster__play", t.labels.play, t.icons.bigPlay);
|
|
1267
1271
|
e.addEventListener("click", () => void t.play()), this.root.append(this.image, e), this.root.addEventListener("click", (i) => {
|
|
1268
1272
|
(i.target === this.root || i.target === this.image) && t.play();
|
|
1269
1273
|
});
|
|
@@ -1318,7 +1322,7 @@ class gt {
|
|
|
1318
1322
|
class yt {
|
|
1319
1323
|
constructor(t) {
|
|
1320
1324
|
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");
|
|
1321
|
-
const e =
|
|
1325
|
+
const e = g("imp-related__close", "Close", t.icons.close);
|
|
1322
1326
|
e.addEventListener("click", () => this.hide()), this.root.append(e, this.heading, this.grid);
|
|
1323
1327
|
}
|
|
1324
1328
|
setOptions(t) {
|
|
@@ -1377,22 +1381,24 @@ class bt {
|
|
|
1377
1381
|
const { labels: e } = this.player;
|
|
1378
1382
|
this.root.textContent = "";
|
|
1379
1383
|
const i = o("div", "imp-upnext__card"), s = o("div", "imp-upnext__kicker");
|
|
1380
|
-
if (s.textContent = e.
|
|
1384
|
+
if (s.textContent = e.nextVideo, i.append(s), t.poster) {
|
|
1381
1385
|
const r = o("button", "imp-upnext__thumb", { type: "button", "aria-label": e.playNext });
|
|
1382
1386
|
if (r.style.backgroundImage = `url("${t.poster}")`, t.duration) {
|
|
1383
1387
|
const h = o("span", "imp-upnext__duration");
|
|
1384
1388
|
h.textContent = x(t.duration), r.append(h);
|
|
1385
1389
|
}
|
|
1386
|
-
const
|
|
1387
|
-
|
|
1390
|
+
const l = o("span", "imp-upnext__thumb-play");
|
|
1391
|
+
l.innerHTML = this.player.icons.bigPlay, r.append(l), r.addEventListener("click", () => this.player.next()), i.append(r);
|
|
1388
1392
|
}
|
|
1389
1393
|
if (t.title) {
|
|
1390
1394
|
const r = o("div", "imp-upnext__title");
|
|
1391
1395
|
r.textContent = t.title, i.append(r);
|
|
1392
1396
|
}
|
|
1393
1397
|
if (t.previewMeta?.length) {
|
|
1394
|
-
const r = o("div", "imp-upnext__meta");
|
|
1395
|
-
|
|
1398
|
+
const r = o("div", "imp-upnext__meta"), l = o("span", "imp-upnext__meta-icon");
|
|
1399
|
+
l.innerHTML = t.metaIcon ?? (t.channel ? this.player.icons.channel : this.player.icons.user);
|
|
1400
|
+
const h = o("span", "imp-upnext__meta-text");
|
|
1401
|
+
h.textContent = t.previewMeta.join(" · "), r.append(l, h), i.append(r);
|
|
1396
1402
|
}
|
|
1397
1403
|
const n = o("button", "imp-upnext__btn", { type: "button" });
|
|
1398
1404
|
n.textContent = e.playNext, n.addEventListener("click", () => this.player.next()), i.append(n), this.root.append(i), this.root.hidden = !1;
|
|
@@ -1413,13 +1419,13 @@ class kt {
|
|
|
1413
1419
|
} else
|
|
1414
1420
|
n.textContent = t.labels.playlist;
|
|
1415
1421
|
const r = o("div", "imp-playlist__tools");
|
|
1416
|
-
this.shuffleBtn =
|
|
1422
|
+
this.shuffleBtn = g("imp-playlist__shuffle", t.labels.shuffle, t.icons.shuffle), this.shuffleBtn.addEventListener("click", () => {
|
|
1417
1423
|
t.setShuffle(!t.shuffle), this.syncModes();
|
|
1418
|
-
}), this.repeatBtn =
|
|
1424
|
+
}), this.repeatBtn = g("imp-playlist__repeat", t.labels.repeat, t.icons.repeat), this.repeatBtn.addEventListener("click", () => {
|
|
1419
1425
|
t.setRepeat(!t.repeat), this.syncModes();
|
|
1420
1426
|
});
|
|
1421
|
-
const
|
|
1422
|
-
|
|
1427
|
+
const l = g("imp-playlist__close", "Close", t.icons.close);
|
|
1428
|
+
l.addEventListener("click", () => this.hide()), r.append(this.shuffleBtn, this.repeatBtn, l), s.append(n, r), this.list = o("div", "imp-playlist__list"), this.root.append(s, this.list), this.rebuild(), this.syncModes();
|
|
1423
1429
|
}
|
|
1424
1430
|
syncModes() {
|
|
1425
1431
|
this.shuffleBtn.classList.toggle("imp-btn--active", this.player.shuffle), this.repeatBtn.classList.toggle("imp-btn--active", this.player.repeat);
|
|
@@ -1432,8 +1438,8 @@ class kt {
|
|
|
1432
1438
|
t.poster && (s.style.backgroundImage = `url("${t.poster}")`);
|
|
1433
1439
|
const n = o("div", "imp-playlist__meta"), r = o("div", "imp-playlist__title");
|
|
1434
1440
|
if (r.textContent = t.title ?? `#${e + 1}`, n.append(r), t.duration) {
|
|
1435
|
-
const
|
|
1436
|
-
|
|
1441
|
+
const l = o("div", "imp-playlist__duration");
|
|
1442
|
+
l.textContent = x(t.duration), n.append(l);
|
|
1437
1443
|
}
|
|
1438
1444
|
i.append(s, n), i.addEventListener("click", () => {
|
|
1439
1445
|
this.player.playItem(e), window.innerWidth <= 767 && this.hide();
|
|
@@ -1458,7 +1464,7 @@ class wt {
|
|
|
1458
1464
|
this.player = t, this.items = [], this.root = o("div", `imp-playlist imp-scenes imp-playlist--${e}`), this.root.hidden = !0;
|
|
1459
1465
|
const i = o("div", "imp-playlist__header"), s = o("span");
|
|
1460
1466
|
s.textContent = t.labels.scenes;
|
|
1461
|
-
const n =
|
|
1467
|
+
const n = g("imp-playlist__close", "Close", t.icons.close);
|
|
1462
1468
|
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());
|
|
1463
1469
|
}
|
|
1464
1470
|
/** Re-render from the player's current chapters + thumbnail track. */
|
|
@@ -1471,10 +1477,10 @@ class wt {
|
|
|
1471
1477
|
const c = o("div", "imp-scenes__sprite");
|
|
1472
1478
|
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);
|
|
1473
1479
|
} else n && (s.style.backgroundImage = `url("${n.src}")`);
|
|
1474
|
-
const r = o("div", "imp-playlist__meta"),
|
|
1475
|
-
|
|
1480
|
+
const r = o("div", "imp-playlist__meta"), l = o("div", "imp-playlist__title");
|
|
1481
|
+
l.textContent = e.title || x(e.start);
|
|
1476
1482
|
const h = o("div", "imp-playlist__duration");
|
|
1477
|
-
h.textContent = x(e.start), r.append(
|
|
1483
|
+
h.textContent = x(e.start), r.append(l, h), i.append(s, r), i.addEventListener("click", () => {
|
|
1478
1484
|
this.player.seek(e.start), this.player.play(), window.innerWidth <= 767 && this.hide();
|
|
1479
1485
|
}), this.list.append(i), this.items.push(i);
|
|
1480
1486
|
}
|
|
@@ -1499,8 +1505,8 @@ class wt {
|
|
|
1499
1505
|
this.visible ? this.hide() : this.show();
|
|
1500
1506
|
}
|
|
1501
1507
|
}
|
|
1502
|
-
function G(
|
|
1503
|
-
return
|
|
1508
|
+
function G(a) {
|
|
1509
|
+
return a ? typeof a == "string" ? [{ src: a, label: "Subtitles" }] : Array.isArray(a) ? a : [a] : [];
|
|
1504
1510
|
}
|
|
1505
1511
|
const xt = {
|
|
1506
1512
|
play: !0,
|
|
@@ -1530,40 +1536,47 @@ const xt = {
|
|
|
1530
1536
|
};
|
|
1531
1537
|
class Tt {
|
|
1532
1538
|
constructor(t, e = {}) {
|
|
1533
|
-
this.scrubbing = !1, this.emitter = new
|
|
1539
|
+
this.scrubbing = !1, this.emitter = new X(), 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.destroyed = !1;
|
|
1534
1540
|
const i = typeof t == "string" ? document.querySelector(t) : t;
|
|
1535
1541
|
if (!i) throw new Error(`[itube-player] mount target not found: ${String(t)}`);
|
|
1536
|
-
this.mount = i, this.options = e, this.labels = { ...
|
|
1542
|
+
this.mount = i, this.options = e, this.labels = { ...V, ...Y(e.language), ...e.labels }, this.icons = { ...J, ...e.icons };
|
|
1537
1543
|
const s = e.controls ?? {}, n = s.speed ?? s.settings ?? "gear";
|
|
1538
|
-
this.controlsOptions = { ...xt, ...s, speed: n, settings: n }, this.actionsOptions = e.actions ?? {}, this.playbackRates = e.playbackRates ?? [0.5, 0.75, 1, 1.25, 1.5, 2], this.seekStep = e.seekStep ?? 15, this.playlistOptions = { title: "", autoAdvance: !0, loop: !1, shuffle: !1, startIndex: 0, layout: "sidebar", ...e.playlist }, this.shuffleMode = this.playlistOptions.shuffle,
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
const p = typeof r.borderRadius == "number" ? `${r.borderRadius}px` : r.borderRadius;
|
|
1542
|
-
this.container.style.setProperty("--imp-radius", p);
|
|
1544
|
+
if (this.controlsOptions = { ...xt, ...s, speed: n, settings: n }, this.actionsOptions = e.actions ?? {}, this.playbackRates = e.playbackRates ?? [0.5, 0.75, 1, 1.25, 1.5, 2], this.seekStep = e.seekStep ?? 15, this.playlistOptions = { title: "", autoAdvance: !0, loop: !1, shuffle: !1, startIndex: 0, layout: "sidebar", ...e.playlist }, this.shuffleMode = this.playlistOptions.shuffle, e.persist) {
|
|
1545
|
+
const v = e.persist === !0 ? {} : e.persist;
|
|
1546
|
+
this.persistKey = v.key ?? "itube-player", this.persistVolume = v.volume !== !1, this.persistAutoAdvance = v.autoAdvance !== !1;
|
|
1543
1547
|
}
|
|
1544
|
-
r
|
|
1545
|
-
|
|
1548
|
+
const r = this.readPersisted();
|
|
1549
|
+
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);
|
|
1550
|
+
const l = e.styling;
|
|
1551
|
+
if (l?.themeColor && this.container.style.setProperty("--imp-accent", l.themeColor), l?.likeColor && this.container.style.setProperty("--imp-like", l.likeColor), l?.dislikeColor && this.container.style.setProperty("--imp-dislike", l.dislikeColor), l?.borderRadius !== void 0) {
|
|
1552
|
+
const v = typeof l.borderRadius == "number" ? `${l.borderRadius}px` : l.borderRadius;
|
|
1553
|
+
this.container.style.setProperty("--imp-radius", v);
|
|
1554
|
+
}
|
|
1555
|
+
l?.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);
|
|
1556
|
+
const h = this.persistVolume ? r : null;
|
|
1557
|
+
this.video.volume = w(h?.volume ?? e.volume ?? 1, 0, 1), (h?.muted ?? e.muted) && (this.video.muted = !0);
|
|
1558
|
+
const c = o("div", "imp-layer");
|
|
1546
1559
|
this.spinner = o("div", "imp-spinner"), this.spinner.hidden = !0, this.errorBox = o("div", "imp-error"), this.errorBox.hidden = !0, this.pauseScreen = new gt(this.labels), this.poster = new ft(this), this.related = new yt(this), this.related.setOptions(e.related), this.upNext = new bt(this), this.controls = new vt(this), this.playlistPanel = new kt(this, this.playlistOptions.layout, this.playlistOptions.title || void 0), this.scenesPanel = new wt(this, e.scenes?.layout ?? "bottom");
|
|
1547
|
-
const
|
|
1548
|
-
|
|
1549
|
-
const
|
|
1550
|
-
|
|
1551
|
-
const
|
|
1552
|
-
|
|
1560
|
+
const u = o("div", "imp-layer__middle");
|
|
1561
|
+
u.append(this.spinner, this.errorBox, this.controls.center);
|
|
1562
|
+
const m = o("div", "imp-layer__bottom");
|
|
1563
|
+
m.append(this.controls.root), c.append(this.pauseScreen.root, this.related.root, this.upNext.root, u, m), 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);
|
|
1564
|
+
const p = e.adConfig ?? e.ads;
|
|
1565
|
+
p && p.adList.length > 0 && (this.adManager = new ot(
|
|
1553
1566
|
{ container: this.container, contentVideo: this.video, emitter: this.emitter, labels: this.labels, closeIcon: this.icons.close },
|
|
1554
|
-
|
|
1555
|
-
)), this.emitter.on("error", ({ message:
|
|
1556
|
-
this.errorBox.textContent =
|
|
1557
|
-
}), this.bindVideoEvents(), this.bindIdleHide(), e.keyboard !== !1 && this.bindKeyboard(), this.video.addEventListener("pointerup", (
|
|
1567
|
+
p
|
|
1568
|
+
)), this.emitter.on("error", ({ message: v }) => {
|
|
1569
|
+
this.errorBox.textContent = v, this.errorBox.hidden = !1, this.spinner.hidden = !0, this.poster.hide();
|
|
1570
|
+
}), this.bindVideoEvents(), this.bindIdleHide(), e.keyboard !== !1 && this.bindKeyboard(), this.video.addEventListener("pointerup", (v) => {
|
|
1558
1571
|
if (!(this.adPlaying || !this.playedOnce)) {
|
|
1559
|
-
if (
|
|
1572
|
+
if (v.pointerType === "mouse") {
|
|
1560
1573
|
this.togglePlay();
|
|
1561
1574
|
return;
|
|
1562
1575
|
}
|
|
1563
1576
|
this.container.classList.contains("imp-player--idle") ? (this.showControlsNow(), this.scheduleIdle()) : this.video.paused || this.container.classList.add("imp-player--idle");
|
|
1564
1577
|
}
|
|
1565
|
-
}, { signal: this.abort.signal }), this.pauseScreen.root.addEventListener("click", (
|
|
1566
|
-
this.pauseScreen.hasCustom ||
|
|
1578
|
+
}, { signal: this.abort.signal }), this.pauseScreen.root.addEventListener("click", (v) => {
|
|
1579
|
+
this.pauseScreen.hasCustom || v.target === this.pauseScreen.root && this.togglePlay();
|
|
1567
1580
|
}, { signal: this.abort.signal }), this.sources.length > 0 && this.loadItem(w(this.playlistOptions.startIndex, 0, this.sources.length - 1), !!e.autoplay), this.emitter.emit("ready", { player: this });
|
|
1568
1581
|
}
|
|
1569
1582
|
// === events ===========================================================
|
|
@@ -1635,6 +1648,26 @@ class Tt {
|
|
|
1635
1648
|
toggleMute() {
|
|
1636
1649
|
this.video.muted = !this.video.muted;
|
|
1637
1650
|
}
|
|
1651
|
+
// === persistence ======================================================
|
|
1652
|
+
/** Read persisted prefs (safe against private mode / SSR / bad JSON). */
|
|
1653
|
+
readPersisted() {
|
|
1654
|
+
if (!this.persistKey) return null;
|
|
1655
|
+
try {
|
|
1656
|
+
const t = localStorage.getItem(this.persistKey), e = t ? JSON.parse(t) : null;
|
|
1657
|
+
return e && typeof e == "object" ? e : null;
|
|
1658
|
+
} catch {
|
|
1659
|
+
return null;
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
/** Write the enabled prefs to localStorage. No-op when persistence is off. */
|
|
1663
|
+
persistState() {
|
|
1664
|
+
if (this.persistKey)
|
|
1665
|
+
try {
|
|
1666
|
+
const t = {};
|
|
1667
|
+
this.persistVolume && (t.volume = this.video.volume, t.muted = this.video.muted), this.persistAutoAdvance && (t.autoAdvance = this.autoAdvanceEnabled), localStorage.setItem(this.persistKey, JSON.stringify(t));
|
|
1668
|
+
} catch {
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1638
1671
|
// === rate / quality ===================================================
|
|
1639
1672
|
get playbackRate() {
|
|
1640
1673
|
return this.video.playbackRate;
|
|
@@ -1855,7 +1888,7 @@ class Tt {
|
|
|
1855
1888
|
this.progressiveQuality = h, n = s.qualities[h].src, r = s.qualities[h].type ?? r;
|
|
1856
1889
|
}
|
|
1857
1890
|
this.video.preload = this.adManager?.hasPendingPreRoll ? "auto" : "metadata";
|
|
1858
|
-
const
|
|
1891
|
+
const l = await ct(this.video, n, r, {
|
|
1859
1892
|
onLevels: () => {
|
|
1860
1893
|
i === this.loadToken && this.controls.syncFeatureButtons();
|
|
1861
1894
|
},
|
|
@@ -1863,10 +1896,10 @@ class Tt {
|
|
|
1863
1896
|
onError: (h, c) => this.emitter.emit("error", { message: h, cause: c })
|
|
1864
1897
|
});
|
|
1865
1898
|
if (i !== this.loadToken) {
|
|
1866
|
-
|
|
1899
|
+
l.destroy();
|
|
1867
1900
|
return;
|
|
1868
1901
|
}
|
|
1869
|
-
if (this.sourceController =
|
|
1902
|
+
if (this.sourceController = l, this.emitter.emit("sourcechange", { source: s, index: t }), s.thumbnails && q.load(s.thumbnails).then((h) => {
|
|
1870
1903
|
i === this.loadToken && (this.thumbTrack = h, this.controls.progress.setThumbnails(h), this.scenesPanel.visible && this.scenesPanel.rebuild());
|
|
1871
1904
|
}).catch((h) => this.emitter.emit("error", { message: "Failed to load thumbnails track", cause: h })), s.sceneGroups && s.sceneGroups.length > 0) {
|
|
1872
1905
|
this.sceneGroupList = s.sceneGroups, this.activeSceneGroupId = s.sceneGroups[0].id;
|
|
@@ -1908,7 +1941,7 @@ class Tt {
|
|
|
1908
1941
|
}, { signal: t }), e.addEventListener("progress", () => {
|
|
1909
1942
|
this.emitter.emit("progress", { buffered: this.bufferedEnd });
|
|
1910
1943
|
}, { signal: t }), e.addEventListener("volumechange", () => {
|
|
1911
|
-
this.emitter.emit("volumechange", { volume: e.volume, muted: e.muted });
|
|
1944
|
+
this.emitter.emit("volumechange", { volume: e.volume, muted: e.muted }), this.persistVolume && this.persistState();
|
|
1912
1945
|
}, { 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", () => {
|
|
1913
1946
|
this.spinner.hidden = !1;
|
|
1914
1947
|
}, { signal: t });
|
|
@@ -1923,7 +1956,7 @@ class Tt {
|
|
|
1923
1956
|
this.decodeRecoveries++;
|
|
1924
1957
|
const n = e.currentTime, r = !e.paused;
|
|
1925
1958
|
e.load();
|
|
1926
|
-
const
|
|
1959
|
+
const l = () => {
|
|
1927
1960
|
try {
|
|
1928
1961
|
e.currentTime = n;
|
|
1929
1962
|
} catch {
|
|
@@ -1931,7 +1964,7 @@ class Tt {
|
|
|
1931
1964
|
r && e.play().catch(() => {
|
|
1932
1965
|
});
|
|
1933
1966
|
};
|
|
1934
|
-
e.readyState >= 1 ?
|
|
1967
|
+
e.readyState >= 1 ? l() : e.addEventListener("loadedmetadata", l, { once: !0, signal: this.abort.signal });
|
|
1935
1968
|
return;
|
|
1936
1969
|
}
|
|
1937
1970
|
this.emitter.emit("error", { message: i.message || `Media error (code ${i.code})`, cause: i });
|
|
@@ -1957,7 +1990,7 @@ class Tt {
|
|
|
1957
1990
|
return this.autoAdvanceEnabled;
|
|
1958
1991
|
}
|
|
1959
1992
|
setAutoAdvance(t) {
|
|
1960
|
-
this.autoAdvanceEnabled = t, t && this.upNext.hide();
|
|
1993
|
+
this.autoAdvanceEnabled = t, t && this.upNext.hide(), this.persistAutoAdvance && this.persistState();
|
|
1961
1994
|
}
|
|
1962
1995
|
// === controls visibility ==============================================
|
|
1963
1996
|
bindIdleHide() {
|
|
@@ -2023,13 +2056,13 @@ class Tt {
|
|
|
2023
2056
|
}
|
|
2024
2057
|
}
|
|
2025
2058
|
export {
|
|
2026
|
-
|
|
2059
|
+
X as Emitter,
|
|
2027
2060
|
Tt as Player,
|
|
2028
|
-
|
|
2061
|
+
q as ThumbnailTrack,
|
|
2029
2062
|
tt as buildHeatmapValues,
|
|
2030
2063
|
U as chapterAt,
|
|
2031
2064
|
J as defaultIcons,
|
|
2032
|
-
|
|
2065
|
+
V as defaultLabels,
|
|
2033
2066
|
x as formatTime,
|
|
2034
2067
|
Y as getLocale,
|
|
2035
2068
|
et as heatmapPath,
|