@hopeplayer/core 1.6.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/HopePlayerElement.d.ts +23 -0
- package/dist/HopePlayerElement.d.ts.map +1 -1
- package/dist/chunks/{adTriggers-BIAWe8o4.js → adTriggers-DVqgm92F.js} +94 -93
- package/dist/chunks/{adTriggers-BIAWe8o4.js.map → adTriggers-DVqgm92F.js.map} +1 -1
- package/dist/chunks/{ads-DlpHPpR9.js → ads-eSKyiH1o.js} +2 -2
- package/dist/chunks/{ads-DlpHPpR9.js.map → ads-eSKyiH1o.js.map} +1 -1
- package/dist/chunks/audioDescription-cpprKeB-.js +146 -0
- package/dist/chunks/audioDescription-cpprKeB-.js.map +1 -0
- package/dist/chunks/{cast-vHyi7oV_.js → cast-DEowHmqA.js} +29 -28
- package/dist/chunks/{cast-vHyi7oV_.js.map → cast-DEowHmqA.js.map} +1 -1
- package/dist/chunks/{docPip-wybMVP1H.js → docPip-Bh6BWPk-.js} +30 -20
- package/dist/chunks/docPip-Bh6BWPk-.js.map +1 -0
- package/dist/chunks/heatmap-Bz_EMQFk.js +117 -0
- package/dist/chunks/heatmap-Bz_EMQFk.js.map +1 -0
- package/dist/chunks/{history-CwqLXiZi.js → history-ZSdDDsRF.js} +35 -34
- package/dist/chunks/{history-CwqLXiZi.js.map → history-ZSdDDsRF.js.map} +1 -1
- package/dist/chunks/interactive-ClJC5Vyo.js +213 -0
- package/dist/chunks/interactive-ClJC5Vyo.js.map +1 -0
- package/dist/chunks/{markers-L69W3kj6.js → markers-D32rI-x-.js} +2 -2
- package/dist/chunks/{markers-L69W3kj6.js.map → markers-D32rI-x-.js.map} +1 -1
- package/dist/chunks/multiview-CL1WfJKt.js +295 -0
- package/dist/chunks/multiview-CL1WfJKt.js.map +1 -0
- package/dist/chunks/{pauseAd-BQQe21X4.js → pauseAd-DF7KGwUs.js} +32 -31
- package/dist/chunks/{pauseAd-BQQe21X4.js.map → pauseAd-DF7KGwUs.js.map} +1 -1
- package/dist/chunks/{player-D2_HRzot.js → player-B7mYS--8.js} +754 -682
- package/dist/chunks/player-B7mYS--8.js.map +1 -0
- package/dist/chunks/{playlist-CHfStNbQ.js → playlist-BkhIOfCy.js} +2 -2
- package/dist/chunks/{playlist-CHfStNbQ.js.map → playlist-BkhIOfCy.js.map} +1 -1
- package/dist/chunks/{pluginHost-cN2uGFeG.js → pluginHost-CXqkjNV1.js} +2 -2
- package/dist/chunks/{pluginHost-cN2uGFeG.js.map → pluginHost-CXqkjNV1.js.map} +1 -1
- package/dist/chunks/{redirectScreen-TIqLdvBY.js → redirectScreen-DgmjFVJH.js} +51 -39
- package/dist/chunks/redirectScreen-DgmjFVJH.js.map +1 -0
- package/dist/chunks/rewardedUnlock-BL97P5ht.js +265 -0
- package/dist/chunks/{rewardedUnlock-DUqYwXTr.js.map → rewardedUnlock-BL97P5ht.js.map} +1 -1
- package/dist/chunks/{segments-Ds-c1b5e.js → segments-CuQQEIAX.js} +2 -2
- package/dist/chunks/{segments-Ds-c1b5e.js.map → segments-CuQQEIAX.js.map} +1 -1
- package/dist/chunks/share-BdqQ8sGE.js +216 -0
- package/dist/chunks/share-BdqQ8sGE.js.map +1 -0
- package/dist/chunks/{skipSegments-ByNoF1qZ.js → skipSegments-BbepQ4Y6.js} +2 -2
- package/dist/chunks/{skipSegments-ByNoF1qZ.js.map → skipSegments-BbepQ4Y6.js.map} +1 -1
- package/dist/chunks/sponsorship-DoAZBbHE.js +241 -0
- package/dist/chunks/{sponsorship-BT21uwN5.js.map → sponsorship-DoAZBbHE.js.map} +1 -1
- package/dist/chunks/{spriteThumbnails-Cr9UmkM9.js → spriteThumbnails-BYg-DHx4.js} +2 -2
- package/dist/chunks/{spriteThumbnails-Cr9UmkM9.js.map → spriteThumbnails-BYg-DHx4.js.map} +1 -1
- package/dist/chunks/{story-CodA2dfn.js → story-DcBG6jUg.js} +2 -2
- package/dist/chunks/{story-CodA2dfn.js.map → story-DcBG6jUg.js.map} +1 -1
- package/dist/chunks/{transcript-LG7E9UYE.js → transcript-CHPQ6S6E.js} +33 -13
- package/dist/chunks/transcript-CHPQ6S6E.js.map +1 -0
- package/dist/controls/SeekBar.d.ts.map +1 -1
- package/dist/hls/SourceManager.d.ts +2 -0
- package/dist/hls/SourceManager.d.ts.map +1 -1
- package/dist/hope-player.js +3 -3
- package/dist/i18n/index.d.ts +9 -0
- package/dist/i18n/index.d.ts.map +1 -1
- package/dist/i18n/locales/en.d.ts +2 -2
- package/dist/i18n/locales/en.d.ts.map +1 -1
- package/dist/i18n/locales/tr.d.ts +2 -2
- package/dist/i18n/locales/tr.d.ts.map +1 -1
- package/dist/i18n/types.d.ts +27 -0
- package/dist/i18n/types.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/plugins/ad-triggers/index.d.ts.map +1 -1
- package/dist/plugins/audio-description/AudioDescription.d.ts +52 -0
- package/dist/plugins/audio-description/AudioDescription.d.ts.map +1 -0
- package/dist/plugins/audio-description/index.d.ts +6 -0
- package/dist/plugins/audio-description/index.d.ts.map +1 -0
- package/dist/plugins/audio-description/strings.d.ts +8 -0
- package/dist/plugins/audio-description/strings.d.ts.map +1 -0
- package/dist/plugins/cast/index.d.ts.map +1 -1
- package/dist/plugins/doc-pip/index.d.ts.map +1 -1
- package/dist/plugins/doc-pip/strings.d.ts +8 -0
- package/dist/plugins/doc-pip/strings.d.ts.map +1 -0
- package/dist/plugins/heatmap/Heatmap.d.ts +8 -0
- package/dist/plugins/heatmap/Heatmap.d.ts.map +1 -1
- package/dist/plugins/heatmap/index.d.ts.map +1 -1
- package/dist/plugins/heatmap/strings.d.ts +8 -0
- package/dist/plugins/heatmap/strings.d.ts.map +1 -0
- package/dist/plugins/history/index.d.ts.map +1 -1
- package/dist/plugins/interactive/index.d.ts.map +1 -1
- package/dist/plugins/interactive/strings.d.ts +8 -0
- package/dist/plugins/interactive/strings.d.ts.map +1 -0
- package/dist/plugins/multiview/Multiview.d.ts +92 -0
- package/dist/plugins/multiview/Multiview.d.ts.map +1 -0
- package/dist/plugins/multiview/index.d.ts +6 -0
- package/dist/plugins/multiview/index.d.ts.map +1 -0
- package/dist/plugins/multiview/strings.d.ts +8 -0
- package/dist/plugins/multiview/strings.d.ts.map +1 -0
- package/dist/plugins/pause-ad/index.d.ts.map +1 -1
- package/dist/plugins/redirect-screen/index.d.ts.map +1 -1
- package/dist/plugins/redirect-screen/strings.d.ts +8 -0
- package/dist/plugins/redirect-screen/strings.d.ts.map +1 -0
- package/dist/plugins/rewarded/index.d.ts.map +1 -1
- package/dist/plugins/share/Share.d.ts +45 -0
- package/dist/plugins/share/Share.d.ts.map +1 -0
- package/dist/plugins/share/index.d.ts +6 -0
- package/dist/plugins/share/index.d.ts.map +1 -0
- package/dist/plugins/share/strings.d.ts +8 -0
- package/dist/plugins/share/strings.d.ts.map +1 -0
- package/dist/plugins/skip-segments/index.d.ts.map +1 -1
- package/dist/plugins/sponsorship/index.d.ts.map +1 -1
- package/dist/plugins/transcript/index.d.ts.map +1 -1
- package/dist/plugins/transcript/strings.d.ts +8 -0
- package/dist/plugins/transcript/strings.d.ts.map +1 -0
- package/dist/types/index.d.ts +93 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/chunks/docPip-wybMVP1H.js.map +0 -1
- package/dist/chunks/heatmap-Bb7neaYU.js +0 -92
- package/dist/chunks/heatmap-Bb7neaYU.js.map +0 -1
- package/dist/chunks/interactive-CgltIneu.js +0 -189
- package/dist/chunks/interactive-CgltIneu.js.map +0 -1
- package/dist/chunks/player-D2_HRzot.js.map +0 -1
- package/dist/chunks/redirectScreen-TIqLdvBY.js.map +0 -1
- package/dist/chunks/rewardedUnlock-DUqYwXTr.js +0 -264
- package/dist/chunks/sponsorship-BT21uwN5.js +0 -240
- package/dist/chunks/transcript-LG7E9UYE.js.map +0 -1
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
var w = Object.defineProperty;
|
|
2
2
|
var v = (s, t, e) => t in s ? w(s, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : s[t] = e;
|
|
3
3
|
var d = (s, t, e) => v(s, typeof t != "symbol" ? t + "" : t, e);
|
|
4
|
-
import { c as E } from "./player-
|
|
5
|
-
import { a as
|
|
6
|
-
const C =
|
|
7
|
-
|
|
4
|
+
import { c as E, r as k } from "./player-B7mYS--8.js";
|
|
5
|
+
import { a as P, c as b } from "./plugin-style-CPJELe-i.js";
|
|
6
|
+
const C = {
|
|
7
|
+
tr: {
|
|
8
|
+
pipPlaying: "Resim içinde resim penceresinde oynatılıyor",
|
|
9
|
+
pipBack: "Buraya geri al"
|
|
10
|
+
},
|
|
11
|
+
en: {
|
|
12
|
+
pipPlaying: "Playing in picture-in-picture",
|
|
13
|
+
pipBack: "Bring it back"
|
|
14
|
+
}
|
|
15
|
+
}, A = ":host(.hp-docpip){display:block;width:100%;height:100%}:host(.hp-docpip) .hp-root{height:100%}:host(.hp-docpip) .video-area{width:100%;height:100%;aspect-ratio:auto;border-radius:0;background:#000}.hp-docpip-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;width:100%;box-sizing:border-box;padding:16px;border-radius:var(--hp-radius);background:#0b0b0f;color:#fff;font:500 14px/1.4 system-ui,-apple-system,sans-serif;text-align:center}.hp-docpip-btn{display:inline-flex;align-items:center;gap:6px;padding:7px 16px;border:0;border-radius:999px;background:#ffffff24;color:#fff;font:600 13px/1 system-ui,-apple-system,sans-serif;cursor:pointer}.hp-docpip-btn:hover{background:#ffffff3d}.hp-docpip-btn:focus-visible{outline:2px solid var(--hp-color-accent, #fff);outline-offset:2px}";
|
|
16
|
+
function R() {
|
|
8
17
|
return window.documentPictureInPicture ?? null;
|
|
9
18
|
}
|
|
10
|
-
class
|
|
19
|
+
class B {
|
|
11
20
|
constructor(t) {
|
|
12
21
|
d(this, "win", null);
|
|
13
22
|
d(this, "placeholder", null);
|
|
@@ -18,15 +27,15 @@ class P {
|
|
|
18
27
|
const { videoArea: e } = this.ctx;
|
|
19
28
|
e.removeAttribute("data-docpip"), this.pipRoot && b(this.pipRoot, this.ctx.hostEl.shadowRoot), this.pipRoot = null, t.replaceWith(e), this.placeholder = null, this.win = null, this.ctx.onChange(!1, null);
|
|
20
29
|
});
|
|
21
|
-
this.ctx = t,
|
|
30
|
+
this.ctx = t, P(t.rootEl, "doc-pip", A);
|
|
22
31
|
}
|
|
23
32
|
get active() {
|
|
24
33
|
return this.win !== null;
|
|
25
34
|
}
|
|
26
35
|
async open(t) {
|
|
27
|
-
const e =
|
|
36
|
+
const e = R();
|
|
28
37
|
if (!e || this.win) return !1;
|
|
29
|
-
const n = this.ctx.videoArea.getBoundingClientRect(),
|
|
38
|
+
const n = this.ctx.videoArea.getBoundingClientRect(), r = n.width > 0 && n.height > 0 ? n.height / n.width : 9 / 16, l = Math.round(t.width ?? Math.min(Math.max(n.width, 320), 640)), h = Math.round(t.height ?? l * r), u = await e.requestWindow({ width: l, height: h });
|
|
30
39
|
return this.mount(u), !0;
|
|
31
40
|
}
|
|
32
41
|
close() {
|
|
@@ -40,7 +49,7 @@ class P {
|
|
|
40
49
|
}
|
|
41
50
|
}
|
|
42
51
|
mount(t) {
|
|
43
|
-
const e = t.document, { hostEl: n, videoArea:
|
|
52
|
+
const e = t.document, { hostEl: n, videoArea: r, rootEl: l } = this.ctx;
|
|
44
53
|
e.title = document.title;
|
|
45
54
|
const h = e.createElement("style");
|
|
46
55
|
h.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}", e.head.appendChild(h);
|
|
@@ -57,26 +66,27 @@ class P {
|
|
|
57
66
|
a.style.fontFamily = f.fontFamily;
|
|
58
67
|
const m = a.attachShadow({ mode: "open" }), y = e.createElement("style");
|
|
59
68
|
y.textContent = this.ctx.css;
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
const
|
|
65
|
-
|
|
69
|
+
const g = e.createElement("div");
|
|
70
|
+
g.className = "hp-root", m.append(y, g), b(n.shadowRoot, m), this.pipRoot = m, e.body.appendChild(a);
|
|
71
|
+
const c = document.createElement("div");
|
|
72
|
+
c.className = "hp-docpip-placeholder", c.setAttribute("part", "pip-placeholder");
|
|
73
|
+
const x = document.createElement("span");
|
|
74
|
+
x.textContent = this.ctx.i18n.pipPlaying;
|
|
66
75
|
const p = document.createElement("button");
|
|
67
|
-
p.type = "button", p.className = "hp-docpip-btn", p.append(E("pip"), document.createTextNode(this.ctx.i18n.pipBack)), p.addEventListener("click", () => this.close()),
|
|
76
|
+
p.type = "button", p.className = "hp-docpip-btn", p.append(E("pip"), document.createTextNode(this.ctx.i18n.pipBack)), p.addEventListener("click", () => this.close()), c.append(x, p), c.style.aspectRatio = `${Math.max(1, r.offsetWidth)} / ${Math.max(1, r.offsetHeight)}`, l.insertBefore(c, r), g.appendChild(r), r.setAttribute("data-docpip", ""), this.placeholder = c, this.win = t, e.addEventListener("keydown", (o) => {
|
|
68
77
|
if (o.defaultPrevented) return;
|
|
69
78
|
const i = o.composedPath()[0];
|
|
70
79
|
i instanceof Element && i.closest("input, textarea, select") || (o.key === " " || o.key === "Enter") && i instanceof Element && i.closest("button") || this.ctx.forwardKey(o) && o.preventDefault();
|
|
71
80
|
}), t.addEventListener("pagehide", this.restore, { once: !0 }), this.ctx.onChange(!0, t);
|
|
72
81
|
}
|
|
73
82
|
}
|
|
83
|
+
k(C);
|
|
74
84
|
function W(s) {
|
|
75
|
-
return new
|
|
85
|
+
return new B(s);
|
|
76
86
|
}
|
|
77
87
|
export {
|
|
78
|
-
|
|
79
|
-
|
|
88
|
+
B as DocumentPip,
|
|
89
|
+
R as documentPipApi,
|
|
80
90
|
W as installDocumentPip
|
|
81
91
|
};
|
|
82
|
-
//# sourceMappingURL=docPip-
|
|
92
|
+
//# sourceMappingURL=docPip-Bh6BWPk-.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docPip-Bh6BWPk-.js","sources":["../../src/plugins/doc-pip/strings.ts","../../src/plugins/doc-pip/DocumentPip.ts","../../src/plugins/doc-pip/index.ts"],"sourcesContent":["// Bu eklentinin metinleri — ana pakete girmez, eklenti yüklenince sözlüğe eklenir (bkz. i18n/index.ts).\nimport type { HopeLocaleStrings } from '../../i18n/types';\n\ntype Strings = Pick<HopeLocaleStrings, 'pipPlaying' | 'pipBack'>;\n\nexport const strings: { tr: Strings; en: Strings } = {\n tr: {\n pipPlaying: 'Resim içinde resim penceresinde oynatılıyor',\n pipBack: 'Buraya geri al',\n },\n en: {\n pipPlaying: 'Playing in picture-in-picture',\n pipBack: 'Bring it back',\n },\n};\n","import type { DocumentPipOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\nimport { createIcon } from '../../icons/Icon';\nimport { adoptStyle, copyAdoptedStyles } from '../../utils/plugin-style';\nimport css from './doc-pip.css?inline';\n\nexport interface DocumentPipContext {\n hostEl: HTMLElement;\n /** Taşınan katman: video + kontroller + reklam + eklentiler. */\n videoArea: HTMLElement;\n /** videoArea'nın shadow içindeki kabı (.hp-root) — yer tutucu buraya girer. */\n rootEl: HTMLElement;\n css: string;\n i18n: HopeLocaleStrings;\n /** Pencere açıldı / kapandı. */\n onChange(active: boolean, win: Window | null): void;\n /** PiP penceresindeki tuşu player'a ilet; işlendiyse true. */\n forwardKey(e: KeyboardEvent): boolean;\n}\n\ninterface DocPipApi {\n requestWindow(options?: { width?: number; height?: number; disallowReturnToOpener?: boolean }): Promise<Window>;\n window: Window | null;\n}\n\nexport function documentPipApi(): DocPipApi | null {\n return (window as unknown as { documentPictureInPicture?: DocPipApi }).documentPictureInPicture ?? null;\n}\n\n/**\n * Document Picture-in-Picture (Chrome / Edge 116+): oynatıcının video alanı — kontroller, altyazı, menüler, reklam\n * katmanı ve eklentiler — her zaman üstte duran ayrı bir pencereye taşınır. Pencere kapanınca (X, \"geri al\",\n * sayfadan ayrılma) yerine döner. Video elementi aynı kalır: oynatma, tampon ve reklam durumu kesilmez.\n */\nexport class DocumentPip {\n private win: Window | null = null;\n private placeholder: HTMLElement | null = null;\n\n private pipRoot: ShadowRoot | null = null;\n\n constructor(private readonly ctx: DocumentPipContext) {\n adoptStyle(ctx.rootEl, 'doc-pip', css);\n }\n\n get active(): boolean {\n return this.win !== null;\n }\n\n async open(options: DocumentPipOptions): Promise<boolean> {\n const api = documentPipApi();\n if (!api || this.win) return false;\n const rect = this.ctx.videoArea.getBoundingClientRect();\n const ratio = rect.width > 0 && rect.height > 0 ? rect.height / rect.width : 9 / 16;\n const width = Math.round(options.width ?? Math.min(Math.max(rect.width, 320), 640));\n const height = Math.round(options.height ?? width * ratio);\n const win = await api.requestWindow({ width, height });\n this.mount(win);\n return true;\n }\n\n close(): void {\n this.win?.close();\n }\n\n destroy(): void {\n if (this.win) {\n const win = this.win;\n this.restore();\n win.close();\n }\n }\n\n private mount(win: Window): void {\n const doc = win.document;\n const { hostEl, videoArea, rootEl } = this.ctx;\n doc.title = document.title;\n const base = doc.createElement('style');\n base.textContent = 'html,body{margin:0;height:100%;background:#000;overflow:hidden}';\n doc.head.appendChild(base);\n // İkon fontu belge başına enjekte edilir (Shadow DOM'da @font-face çalışmıyor).\n const iconFont = document.getElementById('hope-player-icon-font');\n if (iconFont) doc.head.appendChild(iconFont.cloneNode(true));\n\n const host = doc.createElement('div');\n host.className = 'hp-docpip';\n // Tema ve sayfadan gelen token'lar (`hope-player { --hp-color-accent: … }`) pencereye de geçsin.\n for (const { name, value } of Array.from(hostEl.attributes)) if (name.startsWith('data-')) host.setAttribute(name, value);\n const computed = getComputedStyle(hostEl);\n for (let i = 0; i < computed.length; i++) {\n const prop = computed[i]!;\n if (prop.startsWith('--hp-')) host.style.setProperty(prop, computed.getPropertyValue(prop));\n }\n host.style.fontFamily = computed.fontFamily;\n const shadow = host.attachShadow({ mode: 'open' });\n const style = doc.createElement('style');\n style.textContent = this.ctx.css;\n const wrap = doc.createElement('div');\n wrap.className = 'hp-root';\n shadow.append(style, wrap);\n // Eklentilerin sonradan eklenen stilleri (transkript, etkileşimli…) pencereye de.\n copyAdoptedStyles(hostEl.shadowRoot!, shadow);\n this.pipRoot = shadow;\n doc.body.appendChild(host);\n\n const placeholder = document.createElement('div');\n placeholder.className = 'hp-docpip-placeholder';\n placeholder.setAttribute('part', 'pip-placeholder');\n const text = document.createElement('span');\n text.textContent = this.ctx.i18n.pipPlaying;\n const back = document.createElement('button');\n back.type = 'button';\n back.className = 'hp-docpip-btn';\n back.append(createIcon('pip'), document.createTextNode(this.ctx.i18n.pipBack));\n back.addEventListener('click', () => this.close());\n placeholder.append(text, back);\n // Yer tutucu oynatıcının boyutunu korur — sayfa düzeni kaymasın.\n placeholder.style.aspectRatio = `${Math.max(1, videoArea.offsetWidth)} / ${Math.max(1, videoArea.offsetHeight)}`;\n\n // Taşıma tek adımda (appendChild) — video oynamaya devam eder.\n rootEl.insertBefore(placeholder, videoArea);\n wrap.appendChild(videoArea);\n videoArea.setAttribute('data-docpip', '');\n this.placeholder = placeholder;\n this.win = win;\n\n doc.addEventListener('keydown', (e) => {\n if (e.defaultPrevented) return;\n const t = e.composedPath()[0];\n // Odaktaki buton / alan tuşu kendisi işlesin.\n if (t instanceof Element && t.closest('input, textarea, select')) return;\n if ((e.key === ' ' || e.key === 'Enter') && t instanceof Element && t.closest('button')) return;\n if (this.ctx.forwardKey(e)) e.preventDefault();\n });\n win.addEventListener('pagehide', this.restore, { once: true });\n this.ctx.onChange(true, win);\n }\n\n private readonly restore = (): void => {\n const placeholder = this.placeholder;\n if (!placeholder) return;\n const { videoArea } = this.ctx;\n videoArea.removeAttribute('data-docpip');\n // Pencere açıkken kurulan eklentilerin stilleri sayfaya dönsün.\n if (this.pipRoot) copyAdoptedStyles(this.pipRoot, this.ctx.hostEl.shadowRoot!);\n this.pipRoot = null;\n placeholder.replaceWith(videoArea);\n this.placeholder = null;\n this.win = null;\n this.ctx.onChange(false, null);\n };\n}\n","import { registerLocaleStrings } from '../../i18n';\nimport { strings } from './strings';\nimport { DocumentPip, documentPipApi, type DocumentPipContext } from './DocumentPip';\n\nregisterLocaleStrings(strings);\n\nexport function installDocumentPip(ctx: DocumentPipContext): DocumentPip {\n return new DocumentPip(ctx);\n}\n\nexport { DocumentPip, documentPipApi };\nexport type { DocumentPipContext };\n"],"names":["strings","documentPipApi","DocumentPip","ctx","__publicField","placeholder","videoArea","copyAdoptedStyles","adoptStyle","css","options","api","rect","ratio","width","height","win","_a","doc","hostEl","rootEl","base","iconFont","host","name","value","computed","i","prop","shadow","style","wrap","text","back","createIcon","e","t","registerLocaleStrings","installDocumentPip"],"mappings":";;;;;AAKO,MAAMA,IAAwC;AAAA,EACjD,IAAI;AAAA,IACA,YAAY;AAAA,IACZ,SAAS;AAAA,EAAA;AAAA,EAEb,IAAI;AAAA,IACA,YAAY;AAAA,IACZ,SAAS;AAAA,EAAA;AAEjB;ACWO,SAASC,IAAmC;AAC/C,SAAQ,OAA+D,4BAA4B;AACvG;AAOO,MAAMC,EAAY;AAAA,EAMrB,YAA6BC,GAAyB;AAL9C,IAAAC,EAAA,aAAqB;AACrB,IAAAA,EAAA,qBAAkC;AAElC,IAAAA,EAAA,iBAA6B;AAmGpB,IAAAA,EAAA,iBAAU,MAAY;AACnC,YAAMC,IAAc,KAAK;AACzB,UAAI,CAACA,EAAa;AAClB,YAAM,EAAE,WAAAC,MAAc,KAAK;AAC3B,MAAAA,EAAU,gBAAgB,aAAa,GAEnC,KAAK,WAASC,EAAkB,KAAK,SAAS,KAAK,IAAI,OAAO,UAAW,GAC7E,KAAK,UAAU,MACfF,EAAY,YAAYC,CAAS,GACjC,KAAK,cAAc,MACnB,KAAK,MAAM,MACX,KAAK,IAAI,SAAS,IAAO,IAAI;AAAA,IACjC;AA7G6B,SAAA,MAAAH,GACzBK,EAAWL,EAAI,QAAQ,WAAWM,CAAG;AAAA,EACzC;AAAA,EAEA,IAAI,SAAkB;AAClB,WAAO,KAAK,QAAQ;AAAA,EACxB;AAAA,EAEA,MAAM,KAAKC,GAA+C;AACtD,UAAMC,IAAMV,EAAA;AACZ,QAAI,CAACU,KAAO,KAAK,IAAK,QAAO;AAC7B,UAAMC,IAAO,KAAK,IAAI,UAAU,sBAAA,GAC1BC,IAAQD,EAAK,QAAQ,KAAKA,EAAK,SAAS,IAAIA,EAAK,SAASA,EAAK,QAAQ,IAAI,IAC3EE,IAAQ,KAAK,MAAMJ,EAAQ,SAAS,KAAK,IAAI,KAAK,IAAIE,EAAK,OAAO,GAAG,GAAG,GAAG,CAAC,GAC5EG,IAAS,KAAK,MAAML,EAAQ,UAAUI,IAAQD,CAAK,GACnDG,IAAM,MAAML,EAAI,cAAc,EAAE,OAAAG,GAAO,QAAAC,GAAQ;AACrD,gBAAK,MAAMC,CAAG,GACP;AAAA,EACX;AAAA,EAEA,QAAc;;AACV,KAAAC,IAAA,KAAK,QAAL,QAAAA,EAAU;AAAA,EACd;AAAA,EAEA,UAAgB;AACZ,QAAI,KAAK,KAAK;AACV,YAAMD,IAAM,KAAK;AACjB,WAAK,QAAA,GACLA,EAAI,MAAA;AAAA,IACR;AAAA,EACJ;AAAA,EAEQ,MAAMA,GAAmB;AAC7B,UAAME,IAAMF,EAAI,UACV,EAAE,QAAAG,GAAQ,WAAAb,GAAW,QAAAc,EAAA,IAAW,KAAK;AAC3C,IAAAF,EAAI,QAAQ,SAAS;AACrB,UAAMG,IAAOH,EAAI,cAAc,OAAO;AACtC,IAAAG,EAAK,cAAc,mEACnBH,EAAI,KAAK,YAAYG,CAAI;AAEzB,UAAMC,IAAW,SAAS,eAAe,uBAAuB;AAChE,IAAIA,KAAUJ,EAAI,KAAK,YAAYI,EAAS,UAAU,EAAI,CAAC;AAE3D,UAAMC,IAAOL,EAAI,cAAc,KAAK;AACpC,IAAAK,EAAK,YAAY;AAEjB,eAAW,EAAE,MAAAC,GAAM,OAAAC,EAAA,KAAW,MAAM,KAAKN,EAAO,UAAU,EAAG,CAAIK,EAAK,WAAW,OAAO,KAAGD,EAAK,aAAaC,GAAMC,CAAK;AACxH,UAAMC,IAAW,iBAAiBP,CAAM;AACxC,aAASQ,IAAI,GAAGA,IAAID,EAAS,QAAQC,KAAK;AACtC,YAAMC,IAAOF,EAASC,CAAC;AACvB,MAAIC,EAAK,WAAW,OAAO,KAAGL,EAAK,MAAM,YAAYK,GAAMF,EAAS,iBAAiBE,CAAI,CAAC;AAAA,IAC9F;AACA,IAAAL,EAAK,MAAM,aAAaG,EAAS;AACjC,UAAMG,IAASN,EAAK,aAAa,EAAE,MAAM,QAAQ,GAC3CO,IAAQZ,EAAI,cAAc,OAAO;AACvC,IAAAY,EAAM,cAAc,KAAK,IAAI;AAC7B,UAAMC,IAAOb,EAAI,cAAc,KAAK;AACpC,IAAAa,EAAK,YAAY,WACjBF,EAAO,OAAOC,GAAOC,CAAI,GAEzBxB,EAAkBY,EAAO,YAAaU,CAAM,GAC5C,KAAK,UAAUA,GACfX,EAAI,KAAK,YAAYK,CAAI;AAEzB,UAAMlB,IAAc,SAAS,cAAc,KAAK;AAChD,IAAAA,EAAY,YAAY,yBACxBA,EAAY,aAAa,QAAQ,iBAAiB;AAClD,UAAM2B,IAAO,SAAS,cAAc,MAAM;AAC1C,IAAAA,EAAK,cAAc,KAAK,IAAI,KAAK;AACjC,UAAMC,IAAO,SAAS,cAAc,QAAQ;AAC5C,IAAAA,EAAK,OAAO,UACZA,EAAK,YAAY,iBACjBA,EAAK,OAAOC,EAAW,KAAK,GAAG,SAAS,eAAe,KAAK,IAAI,KAAK,OAAO,CAAC,GAC7ED,EAAK,iBAAiB,SAAS,MAAM,KAAK,OAAO,GACjD5B,EAAY,OAAO2B,GAAMC,CAAI,GAE7B5B,EAAY,MAAM,cAAc,GAAG,KAAK,IAAI,GAAGC,EAAU,WAAW,CAAC,MAAM,KAAK,IAAI,GAAGA,EAAU,YAAY,CAAC,IAG9Gc,EAAO,aAAaf,GAAaC,CAAS,GAC1CyB,EAAK,YAAYzB,CAAS,GAC1BA,EAAU,aAAa,eAAe,EAAE,GACxC,KAAK,cAAcD,GACnB,KAAK,MAAMW,GAEXE,EAAI,iBAAiB,WAAW,CAACiB,MAAM;AACnC,UAAIA,EAAE,iBAAkB;AACxB,YAAMC,IAAID,EAAE,aAAA,EAAe,CAAC;AAE5B,MAAIC,aAAa,WAAWA,EAAE,QAAQ,yBAAyB,MAC1DD,EAAE,QAAQ,OAAOA,EAAE,QAAQ,YAAYC,aAAa,WAAWA,EAAE,QAAQ,QAAQ,KAClF,KAAK,IAAI,WAAWD,CAAC,OAAK,eAAA;AAAA,IAClC,CAAC,GACDnB,EAAI,iBAAiB,YAAY,KAAK,SAAS,EAAE,MAAM,IAAM,GAC7D,KAAK,IAAI,SAAS,IAAMA,CAAG;AAAA,EAC/B;AAeJ;AClJAqB,EAAsBrC,CAAO;AAEtB,SAASsC,EAAmBnC,GAAsC;AACrE,SAAO,IAAID,EAAYC,CAAG;AAC9B;"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
var b = Object.defineProperty;
|
|
2
|
+
var g = (n, t, e) => t in n ? b(n, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : n[t] = e;
|
|
3
|
+
var o = (n, t, e) => g(n, typeof t != "symbol" ? t + "" : t, e);
|
|
4
|
+
import { r as k } from "./player-B7mYS--8.js";
|
|
5
|
+
import { a as E } from "./plugin-style-CPJELe-i.js";
|
|
6
|
+
const L = {
|
|
7
|
+
tr: {
|
|
8
|
+
heatmapPeak: "En çok izlenen an"
|
|
9
|
+
},
|
|
10
|
+
en: {
|
|
11
|
+
heatmapPeak: "Most watched moment"
|
|
12
|
+
}
|
|
13
|
+
}, x = ".hp-heatmap{position:absolute;left:0;right:0;bottom:50%;height:var(--hp-heatmap-h, 36px);pointer-events:none;opacity:0;transition:opacity .2s ease}.hp-heatmap[hidden]{display:none}.hp-heatmap[data-show=always],.hp-seekbar:hover .hp-heatmap,.hp-seekbar:focus-visible .hp-heatmap{opacity:1}.hp-heatmap-base,.hp-heatmap-played{position:absolute;top:0;right:0;bottom:0;left:0}.hp-heatmap svg{display:block;filter:drop-shadow(0 0 1.5px rgba(0,0,0,.25));width:100%;height:100%}.hp-heatmap-base path{fill:color-mix(in srgb,var(--hp-color-on-surface) 28%,transparent)}.hp-heatmap-played{clip-path:inset(0 calc(100% - var(--hp-heatmap-p, 0%)) 0 0)}.hp-seek-marker.hp-heatmap-peak{visibility:hidden}.hp-heatmap-played path{fill:color-mix(in srgb,var(--hp-color-accent, #fff) 60%,transparent)}", m = "http://www.w3.org/2000/svg", d = 1e3, p = 100;
|
|
14
|
+
function w(n) {
|
|
15
|
+
const t = n.map((a) => Number.isFinite(a) && a > 0 ? a : 0), e = Math.max(0, ...t);
|
|
16
|
+
return e > 0 ? t.map((a) => a / e) : t;
|
|
17
|
+
}
|
|
18
|
+
function A(n) {
|
|
19
|
+
const t = n.length;
|
|
20
|
+
if (!t) return "";
|
|
21
|
+
const e = n.map((i, s) => [(s + 0.5) / t * d, p - i * p * 0.92]);
|
|
22
|
+
e.unshift([0, e[0][1]]), e.push([d, e[e.length - 1][1]]);
|
|
23
|
+
let a = `M0 ${p}L${e[0][0]} ${e[0][1].toFixed(1)}`;
|
|
24
|
+
for (let i = 0; i < e.length - 1; i++) {
|
|
25
|
+
const s = e[i - 1] ?? e[i], r = e[i], h = e[i + 1], l = e[i + 2] ?? h, u = Math.min(p, Math.max(0, r[1] + (h[1] - s[1]) / 6)), v = Math.min(p, Math.max(0, h[1] - (l[1] - r[1]) / 6)), f = r[0] + (h[0] - s[0]) / 6, y = h[0] - (l[0] - r[0]) / 6;
|
|
26
|
+
a += `C${f.toFixed(1)} ${u.toFixed(1)} ${y.toFixed(1)} ${v.toFixed(1)} ${h[0].toFixed(1)} ${h[1].toFixed(1)}`;
|
|
27
|
+
}
|
|
28
|
+
return `${a}L${d} ${p}Z`;
|
|
29
|
+
}
|
|
30
|
+
function c(n) {
|
|
31
|
+
const t = document.createElement("div");
|
|
32
|
+
t.className = n;
|
|
33
|
+
const e = document.createElementNS(m, "svg");
|
|
34
|
+
e.setAttribute("viewBox", `0 0 ${d} ${p}`), e.setAttribute("preserveAspectRatio", "none"), e.setAttribute("aria-hidden", "true");
|
|
35
|
+
const a = document.createElementNS(m, "path");
|
|
36
|
+
return e.appendChild(a), t.appendChild(e), { el: t, path: a };
|
|
37
|
+
}
|
|
38
|
+
class $ {
|
|
39
|
+
constructor(t, e) {
|
|
40
|
+
o(this, "el");
|
|
41
|
+
o(this, "base");
|
|
42
|
+
o(this, "played");
|
|
43
|
+
o(this, "destroyed", !1);
|
|
44
|
+
/** Tepe noktası: görünmez işaret — üzerine gelince "En çok izlenen an · 1:23". */
|
|
45
|
+
o(this, "peak", null);
|
|
46
|
+
o(this, "rafId", null);
|
|
47
|
+
o(this, "startLoop", () => {
|
|
48
|
+
if (this.rafId !== null) return;
|
|
49
|
+
const t = () => {
|
|
50
|
+
this.onTime(), this.rafId = requestAnimationFrame(t);
|
|
51
|
+
};
|
|
52
|
+
this.rafId = requestAnimationFrame(t);
|
|
53
|
+
});
|
|
54
|
+
o(this, "stopLoop", () => {
|
|
55
|
+
this.rafId !== null && cancelAnimationFrame(this.rafId), this.rafId = null, this.onTime();
|
|
56
|
+
});
|
|
57
|
+
o(this, "onDuration", () => {
|
|
58
|
+
const t = this.ctx.videoEl.duration;
|
|
59
|
+
this.el.hidden = !Number.isFinite(t) || t <= 0 || this.el.hasAttribute("data-empty") || !this.base.getAttribute("d"), this.peak && (this.el.hidden ? this.peak.remove() : this.peak.isConnected || this.ctx.seekBar.el.appendChild(this.peak)), this.onTime();
|
|
60
|
+
});
|
|
61
|
+
o(this, "onTime", () => {
|
|
62
|
+
const t = this.ctx.videoEl, e = Number.isFinite(t.duration) && t.duration > 0 ? Math.min(1, Math.max(0, t.currentTime / t.duration)) : 0;
|
|
63
|
+
this.el.hidden || this.el.style.setProperty("--hp-heatmap-p", `${(e * 100).toFixed(3)}%`);
|
|
64
|
+
});
|
|
65
|
+
var r;
|
|
66
|
+
this.ctx = t, this.options = e, E(t.seekBar.el, "heatmap", x);
|
|
67
|
+
const a = document.createElement("div");
|
|
68
|
+
a.className = "hp-heatmap", a.setAttribute("part", "heatmap"), a.setAttribute("aria-hidden", "true"), a.setAttribute("data-show", e.show === "always" ? "always" : "hover"), e.height && a.style.setProperty("--hp-heatmap-h", `${Math.max(8, e.height)}px`);
|
|
69
|
+
const i = c("hp-heatmap-base"), s = c("hp-heatmap-played");
|
|
70
|
+
a.append(i.el, s.el), this.el = a, this.base = i.path, this.played = s.path, a.hidden = !0, t.seekBar.el.prepend(a), t.videoEl.addEventListener("timeupdate", this.onTime), t.videoEl.addEventListener("seeking", this.onTime), t.videoEl.addEventListener("play", this.startLoop), t.videoEl.addEventListener("pause", this.stopLoop), t.videoEl.addEventListener("ended", this.stopLoop), t.videoEl.paused || this.startLoop(), t.videoEl.addEventListener("durationchange", this.onDuration), t.videoEl.addEventListener("loadedmetadata", this.onDuration), (r = e.data) != null && r.length ? this.setData(e.data) : e.src && this.fetchData(e.src);
|
|
71
|
+
}
|
|
72
|
+
/** Yeni değerler (ör. sunucudan güncel istatistik). */
|
|
73
|
+
setData(t) {
|
|
74
|
+
const e = w(t);
|
|
75
|
+
this.setPeak(e);
|
|
76
|
+
const a = A(e);
|
|
77
|
+
this.base.setAttribute("d", a), this.played.setAttribute("d", a), this.el.toggleAttribute("data-empty", !a), this.onDuration();
|
|
78
|
+
}
|
|
79
|
+
destroy() {
|
|
80
|
+
var e;
|
|
81
|
+
this.destroyed = !0;
|
|
82
|
+
const t = this.ctx.videoEl;
|
|
83
|
+
t.removeEventListener("timeupdate", this.onTime), t.removeEventListener("seeking", this.onTime), t.removeEventListener("durationchange", this.onDuration), t.removeEventListener("loadedmetadata", this.onDuration), (e = this.peak) == null || e.remove(), t.removeEventListener("play", this.startLoop), t.removeEventListener("pause", this.stopLoop), t.removeEventListener("ended", this.stopLoop), this.stopLoop(), this.el.remove();
|
|
84
|
+
}
|
|
85
|
+
/** En yüksek dilim (birden fazlaysa ilki) — üzerine gelince etiket. */
|
|
86
|
+
setPeak(t) {
|
|
87
|
+
var s;
|
|
88
|
+
(s = this.peak) == null || s.remove(), this.peak = null;
|
|
89
|
+
const e = this.options.peakLabel;
|
|
90
|
+
if (e === !1 || !t.length) return;
|
|
91
|
+
const a = t.indexOf(1);
|
|
92
|
+
if (a < 0) return;
|
|
93
|
+
const i = this.ctx.seekBar.addMarker((a + 0.5) / t.length, "hp-heatmap-peak", typeof e == "string" ? e : this.ctx.i18n.heatmapPeak);
|
|
94
|
+
i.dataset.hitRatio = String(0.5 / t.length), this.peak = i;
|
|
95
|
+
}
|
|
96
|
+
async fetchData(t) {
|
|
97
|
+
var e, a;
|
|
98
|
+
try {
|
|
99
|
+
const i = await fetch(t);
|
|
100
|
+
if (!i.ok) throw new Error(`HTTP ${i.status}`);
|
|
101
|
+
const s = await i.json(), r = Array.isArray(s) ? s : s == null ? void 0 : s.data;
|
|
102
|
+
if (!Array.isArray(r)) throw new Error("number[] bekleniyordu");
|
|
103
|
+
this.destroyed || this.setData(r.map(Number));
|
|
104
|
+
} catch (i) {
|
|
105
|
+
(a = (e = this.ctx).log) == null || a.call(e, { message: `Heatmap data could not be loaded: ${String(i)}`, details: { src: t } });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
k(L);
|
|
110
|
+
function T(n, t) {
|
|
111
|
+
return new $(n, t);
|
|
112
|
+
}
|
|
113
|
+
export {
|
|
114
|
+
$ as Heatmap,
|
|
115
|
+
T as installHeatmap
|
|
116
|
+
};
|
|
117
|
+
//# sourceMappingURL=heatmap-Bz_EMQFk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heatmap-Bz_EMQFk.js","sources":["../../src/plugins/heatmap/strings.ts","../../src/plugins/heatmap/Heatmap.ts","../../src/plugins/heatmap/index.ts"],"sourcesContent":["// Bu eklentinin metinleri — ana pakete girmez, eklenti yüklenince sözlüğe eklenir (bkz. i18n/index.ts).\nimport type { HopeLocaleStrings } from '../../i18n/types';\n\ntype Strings = Pick<HopeLocaleStrings, 'heatmapPeak'>;\n\nexport const strings: { tr: Strings; en: Strings } = {\n tr: {\n heatmapPeak: 'En çok izlenen an',\n },\n en: {\n heatmapPeak: 'Most watched moment',\n },\n};\n","import type { HeatmapOptions } from '../../types';\nimport { adoptStyle } from '../../utils/plugin-style';\nimport css from './heatmap.css?inline';\n\nexport interface HeatmapPlayerContext {\n videoEl: HTMLVideoElement;\n seekBar: { readonly el: HTMLElement; addMarker(ratio: number, extraClass?: string, label?: string): HTMLElement };\n i18n: { heatmapPeak: string };\n log?: (entry: { message: string; details?: Record<string, string> }) => void;\n}\n\nconst SVG_NS = 'http://www.w3.org/2000/svg';\nconst W = 1000;\nconst H = 100;\n\n/** Değerleri 0–1'e indirger (en yüksek = 1); geçersizler 0. */\nfunction normalize(values: number[]): number[] {\n const clean = values.map((v) => (Number.isFinite(v) && v > 0 ? v : 0));\n const max = Math.max(0, ...clean);\n return max > 0 ? clean.map((v) => v / max) : clean;\n}\n\n/** Noktalardan yumuşak (Catmull-Rom → Bezier) kapalı alan yolu; tabanı seek bar çizgisi. */\nexport function heatmapPath(values: number[]): string {\n const n = values.length;\n if (!n) return '';\n const pts: [number, number][] = values.map((v, i) => [((i + 0.5) / n) * W, H - v * H * 0.92]);\n pts.unshift([0, pts[0]![1]]);\n pts.push([W, pts[pts.length - 1]![1]]);\n let d = `M0 ${H}L${pts[0]![0]} ${pts[0]![1].toFixed(1)}`;\n for (let i = 0; i < pts.length - 1; i++) {\n const p0 = pts[i - 1] ?? pts[i]!;\n const p1 = pts[i]!;\n const p2 = pts[i + 1]!;\n const p3 = pts[i + 2] ?? p2;\n // Kontrol noktaları tabanın altına / tepenin üstüne taşmasın.\n const c1y = Math.min(H, Math.max(0, p1[1] + (p2[1] - p0[1]) / 6));\n const c2y = Math.min(H, Math.max(0, p2[1] - (p3[1] - p1[1]) / 6));\n const c1x = p1[0] + (p2[0] - p0[0]) / 6;\n const c2x = p2[0] - (p3[0] - p1[0]) / 6;\n d += `C${c1x.toFixed(1)} ${c1y.toFixed(1)} ${c2x.toFixed(1)} ${c2y.toFixed(1)} ${p2[0].toFixed(1)} ${p2[1].toFixed(1)}`;\n }\n return `${d}L${W} ${H}Z`;\n}\n\nfunction layer(className: string): { el: HTMLDivElement; path: SVGPathElement } {\n const el = document.createElement('div');\n el.className = className;\n const svg = document.createElementNS(SVG_NS, 'svg');\n svg.setAttribute('viewBox', `0 0 ${W} ${H}`);\n svg.setAttribute('preserveAspectRatio', 'none');\n svg.setAttribute('aria-hidden', 'true');\n const path = document.createElementNS(SVG_NS, 'path');\n svg.appendChild(path);\n el.appendChild(svg);\n return { el, path };\n}\n\n/**\n * \"En çok izlenen\" ısı haritası: seek bar'ın hemen üstünde yoğunluk eğrisi. Değerler videoya eşit aralıklarla\n * yayılır; izlenen kısım vurgu rengiyle dolar. Canlı yayında (süre bilinmiyorsa) gizlenir.\n */\nexport class Heatmap {\n private readonly el: HTMLDivElement;\n private readonly base: SVGPathElement;\n private readonly played: SVGPathElement;\n private destroyed = false;\n /** Tepe noktası: görünmez işaret — üzerine gelince \"En çok izlenen an · 1:23\". */\n private peak: HTMLElement | null = null;\n\n constructor(\n private readonly ctx: HeatmapPlayerContext,\n private readonly options: HeatmapOptions\n ) {\n adoptStyle(ctx.seekBar.el, 'heatmap', css);\n const el = document.createElement('div');\n el.className = 'hp-heatmap';\n el.setAttribute('part', 'heatmap');\n el.setAttribute('aria-hidden', 'true');\n el.setAttribute('data-show', options.show === 'always' ? 'always' : 'hover');\n if (options.height) el.style.setProperty('--hp-heatmap-h', `${Math.max(8, options.height)}px`);\n const base = layer('hp-heatmap-base');\n const played = layer('hp-heatmap-played');\n el.append(base.el, played.el);\n this.el = el;\n this.base = base.path;\n this.played = played.path;\n el.hidden = true;\n ctx.seekBar.el.prepend(el);\n\n ctx.videoEl.addEventListener('timeupdate', this.onTime);\n ctx.videoEl.addEventListener('seeking', this.onTime);\n // Oynarken her karede güncellenir — seek bar'daki ilerleme gibi akıcı.\n ctx.videoEl.addEventListener('play', this.startLoop);\n ctx.videoEl.addEventListener('pause', this.stopLoop);\n ctx.videoEl.addEventListener('ended', this.stopLoop);\n if (!ctx.videoEl.paused) this.startLoop();\n ctx.videoEl.addEventListener('durationchange', this.onDuration);\n ctx.videoEl.addEventListener('loadedmetadata', this.onDuration);\n\n if (options.data?.length) this.setData(options.data);\n else if (options.src) void this.fetchData(options.src);\n }\n\n /** Yeni değerler (ör. sunucudan güncel istatistik). */\n setData(values: number[]): void {\n const norm = normalize(values);\n this.setPeak(norm);\n const d = heatmapPath(norm);\n this.base.setAttribute('d', d);\n this.played.setAttribute('d', d);\n this.el.toggleAttribute('data-empty', !d);\n this.onDuration();\n }\n\n destroy(): void {\n this.destroyed = true;\n const v = this.ctx.videoEl;\n v.removeEventListener('timeupdate', this.onTime);\n v.removeEventListener('seeking', this.onTime);\n v.removeEventListener('durationchange', this.onDuration);\n v.removeEventListener('loadedmetadata', this.onDuration);\n this.peak?.remove();\n v.removeEventListener('play', this.startLoop);\n v.removeEventListener('pause', this.stopLoop);\n v.removeEventListener('ended', this.stopLoop);\n this.stopLoop();\n this.el.remove();\n }\n\n private rafId: number | null = null;\n\n private readonly startLoop = (): void => {\n if (this.rafId !== null) return;\n const tick = (): void => {\n this.onTime();\n this.rafId = requestAnimationFrame(tick);\n };\n this.rafId = requestAnimationFrame(tick);\n };\n\n private readonly stopLoop = (): void => {\n if (this.rafId !== null) cancelAnimationFrame(this.rafId);\n this.rafId = null;\n this.onTime();\n };\n\n /** En yüksek dilim (birden fazlaysa ilki) — üzerine gelince etiket. */\n private setPeak(norm: number[]): void {\n this.peak?.remove();\n this.peak = null;\n const label = this.options.peakLabel;\n if (label === false || !norm.length) return;\n const i = norm.indexOf(1);\n if (i < 0) return;\n const el = this.ctx.seekBar.addMarker((i + 0.5) / norm.length, 'hp-heatmap-peak', typeof label === 'string' ? label : this.ctx.i18n.heatmapPeak);\n el.dataset.hitRatio = String(0.5 / norm.length);\n this.peak = el;\n }\n\n private async fetchData(src: string): Promise<void> {\n try {\n const res = await fetch(src);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const json: unknown = await res.json();\n const values = Array.isArray(json) ? json : (json as { data?: unknown })?.data;\n if (!Array.isArray(values)) throw new Error('number[] bekleniyordu');\n if (!this.destroyed) this.setData(values.map(Number));\n } catch (err) {\n this.ctx.log?.({ message: `Heatmap data could not be loaded: ${String(err)}`, details: { src } });\n }\n }\n\n private readonly onDuration = (): void => {\n const d = this.ctx.videoEl.duration;\n this.el.hidden = !Number.isFinite(d) || d <= 0 || this.el.hasAttribute('data-empty') || !this.base.getAttribute('d');\n // Canlıda / veri yokken tepe etiketi de yok (işaret DOM'dan çıkar, geri gelince eklenir).\n if (this.peak) {\n if (this.el.hidden) this.peak.remove();\n else if (!this.peak.isConnected) this.ctx.seekBar.el.appendChild(this.peak);\n }\n this.onTime();\n };\n\n private readonly onTime = (): void => {\n const v = this.ctx.videoEl;\n const ratio = Number.isFinite(v.duration) && v.duration > 0 ? Math.min(1, Math.max(0, v.currentTime / v.duration)) : 0;\n // Gizliyken (canlı yayın / veri yok) stil yazma.\n if (this.el.hidden) return;\n this.el.style.setProperty('--hp-heatmap-p', `${(ratio * 100).toFixed(3)}%`);\n };\n}\n","import { registerLocaleStrings } from '../../i18n';\nimport { strings } from './strings';\nimport { Heatmap, type HeatmapPlayerContext } from './Heatmap';\nimport type { HeatmapOptions } from '../../types';\n\nregisterLocaleStrings(strings);\n\nexport function installHeatmap(ctx: HeatmapPlayerContext, options: HeatmapOptions): Heatmap {\n return new Heatmap(ctx, options);\n}\n\nexport { Heatmap };\nexport type { HeatmapPlayerContext };\n"],"names":["strings","SVG_NS","W","H","normalize","values","clean","v","max","heatmapPath","n","pts","i","d","p0","p1","p2","p3","c1y","c2y","c1x","c2x","layer","className","el","svg","path","Heatmap","ctx","options","__publicField","tick","ratio","adoptStyle","css","base","played","_a","norm","label","src","res","json","err","_b","registerLocaleStrings","installHeatmap"],"mappings":"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"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var s = (
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
var u = Object.defineProperty;
|
|
2
|
+
var p = (o, t, e) => t in o ? u(o, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : o[t] = e;
|
|
3
|
+
var s = (o, t, e) => p(o, typeof t != "symbol" ? t + "" : t, e);
|
|
4
|
+
import { a as v } from "./plugin-style-CPJELe-i.js";
|
|
5
|
+
import { f } from "./player-B7mYS--8.js";
|
|
6
|
+
import { s as x } from "./seekWhenReady-Clzne3-S.js";
|
|
7
|
+
const y = ".hp-history-notice{position:absolute;left:16px;bottom:76px;z-index:23;display:inline-flex;align-items:center;gap:12px;max-width:calc(100% - 32px);padding:8px 8px 8px 14px;border-radius:999px;background:#0e0e12d1;color:#fff;font:500 13px/1.3 system-ui,-apple-system,sans-serif;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);box-shadow:0 10px 28px -12px #000c;animation:hp-redirect-in .3s cubic-bezier(.2,.8,.2,1);transition:bottom .25s}.video-area[data-chrome-hidden] .hp-history-notice{bottom:16px}.hp-history-restart{flex-shrink:0;padding:6px 12px;border:0;border-radius:999px;background:var(--hp-color-accent, #fff);color:var(--hp-color-on-accent, #0a0a0a);font:600 12.5px/1.2 system-ui,-apple-system,sans-serif;cursor:pointer}.hp-history-restart:focus-visible{outline:2px solid var(--hp-color-accent, #fff);outline-offset:2px}.video-area[data-compact] .hp-history-notice{left:8px;bottom:56px;gap:8px;padding:6px 6px 6px 10px;font-size:11.5px}.video-area[data-compact][data-chrome-hidden] .hp-history-notice{bottom:10px}@media(prefers-reduced-motion:reduce){.hp-history-notice{animation:none}}", h = "hp-history-positions", c = "hp-history-volume", E = 10, b = 15, k = 50, L = 30, g = 5e3, T = 6e3;
|
|
8
|
+
class N {
|
|
8
9
|
constructor(t, e) {
|
|
9
10
|
s(this, "key", null);
|
|
10
11
|
s(this, "lastSaveAt", 0);
|
|
@@ -24,10 +25,10 @@ class x {
|
|
|
24
25
|
}
|
|
25
26
|
if (t.currentTime > 1) return;
|
|
26
27
|
const e = this.entries()[this.key];
|
|
27
|
-
!e || e.t < this.minWatched || e.t > t.duration - this.endMargin || (
|
|
28
|
+
!e || e.t < this.minWatched || e.t > t.duration - this.endMargin || (x(t, e.t, { attempts: 2 }), this.showNotice(e.t), this.emit("resumed", e.t));
|
|
28
29
|
});
|
|
29
30
|
s(this, "onTimeUpdate", () => {
|
|
30
|
-
Date.now() - this.lastSaveAt <
|
|
31
|
+
Date.now() - this.lastSaveAt < g || this.savePosition();
|
|
31
32
|
});
|
|
32
33
|
s(this, "onVisibility", () => {
|
|
33
34
|
document.visibilityState === "hidden" && this.savePosition();
|
|
@@ -38,11 +39,11 @@ class x {
|
|
|
38
39
|
const e = t.duration;
|
|
39
40
|
if (!Number.isFinite(e) || e <= 0) return;
|
|
40
41
|
this.lastSaveAt = Date.now();
|
|
41
|
-
const i = t.currentTime,
|
|
42
|
-
if (i >= e - this.endMargin) delete
|
|
43
|
-
else if (i >= this.minWatched)
|
|
42
|
+
const i = t.currentTime, n = this.entries();
|
|
43
|
+
if (i >= e - this.endMargin) delete n[this.key];
|
|
44
|
+
else if (i >= this.minWatched) n[this.key] = { t: Math.floor(i), d: Math.round(e), at: Date.now() };
|
|
44
45
|
else return;
|
|
45
|
-
this.store(
|
|
46
|
+
this.store(n);
|
|
46
47
|
});
|
|
47
48
|
s(this, "onEnded", () => {
|
|
48
49
|
if (!this.key) return;
|
|
@@ -52,9 +53,9 @@ class x {
|
|
|
52
53
|
s(this, "saveVolume", () => {
|
|
53
54
|
if (this.ctx.isAdActive()) return;
|
|
54
55
|
const t = this.ctx.videoEl;
|
|
55
|
-
|
|
56
|
+
m(c, { volume: Math.round(t.volume * 100) / 100, muted: t.muted });
|
|
56
57
|
});
|
|
57
|
-
this.ctx = t, this.options = e, this.position = e.position !== !1, this.volume = e.volume !== !1, this.minWatched = e.minWatched ??
|
|
58
|
+
this.ctx = t, this.options = e, this.position = e.position !== !1, this.volume = e.volume !== !1, this.minWatched = e.minWatched ?? E, this.endMargin = e.endMargin ?? b, this.skipNextRestore = t.linkTimePresent;
|
|
58
59
|
const i = t.videoEl;
|
|
59
60
|
this.volume && (this.restoreVolume(), i.addEventListener("volumechange", this.saveVolume)), this.position && (i.addEventListener("loadedmetadata", this.onLoadedMetadata), i.addEventListener("timeupdate", this.onTimeUpdate), i.addEventListener("pause", this.savePosition), i.addEventListener("seeked", this.savePosition), i.addEventListener("ended", this.onEnded), window.addEventListener("pagehide", this.savePosition), document.addEventListener("visibilitychange", this.onVisibility), i.readyState >= 1 && this.onLoadedMetadata());
|
|
60
61
|
}
|
|
@@ -79,11 +80,11 @@ class x {
|
|
|
79
80
|
}
|
|
80
81
|
/** Süresi geçenleri at, en yeni `maxEntries` kaydı tut. */
|
|
81
82
|
store(t) {
|
|
82
|
-
const e = (this.options.ttlDays ??
|
|
83
|
-
|
|
83
|
+
const e = (this.options.ttlDays ?? L) * 864e5, i = this.options.maxEntries ?? k, n = Date.now(), r = Object.entries(t).filter(([, a]) => n - a.at < e).sort((a, d) => d[1].at - a[1].at).slice(0, i);
|
|
84
|
+
m(h, Object.fromEntries(r));
|
|
84
85
|
}
|
|
85
86
|
entries() {
|
|
86
|
-
const t = l(
|
|
87
|
+
const t = l(h);
|
|
87
88
|
return t && typeof t == "object" ? t : {};
|
|
88
89
|
}
|
|
89
90
|
// ── Ses ──
|
|
@@ -99,19 +100,19 @@ class x {
|
|
|
99
100
|
this.hideNotice();
|
|
100
101
|
const e = this.ctx.i18n, i = document.createElement("div");
|
|
101
102
|
i.className = "hp-history-notice", i.setAttribute("part", "history-notice"), i.setAttribute("role", "status");
|
|
102
|
-
const
|
|
103
|
-
|
|
103
|
+
const n = document.createElement("span");
|
|
104
|
+
n.textContent = e.historyResumed(f(t));
|
|
104
105
|
const r = document.createElement("button");
|
|
105
106
|
r.type = "button", r.className = "hp-history-restart", r.textContent = e.historyRestart, r.addEventListener("click", () => {
|
|
106
107
|
const a = this.ctx.videoEl;
|
|
107
108
|
if (a.currentTime = 0, this.key) {
|
|
108
|
-
const
|
|
109
|
-
delete
|
|
109
|
+
const d = this.entries();
|
|
110
|
+
delete d[this.key], this.store(d);
|
|
110
111
|
}
|
|
111
112
|
this.emit("restart", 0), this.hideNotice();
|
|
112
|
-
}), i.append(
|
|
113
|
-
for (const a of ["pointerdown", "mousedown", "mouseup", "touchstart", "touchend", "click", "dblclick"]) i.addEventListener(a, (
|
|
114
|
-
this.ctx.overlayContainerEl.appendChild(i), this.noticeEl = i, this.noticeTimer = setTimeout(() => this.hideNotice(),
|
|
113
|
+
}), i.append(n, r);
|
|
114
|
+
for (const a of ["pointerdown", "mousedown", "mouseup", "touchstart", "touchend", "click", "dblclick"]) i.addEventListener(a, (d) => d.stopPropagation());
|
|
115
|
+
this.ctx.overlayContainerEl.appendChild(i), this.noticeEl = i, this.noticeTimer = setTimeout(() => this.hideNotice(), T);
|
|
115
116
|
}
|
|
116
117
|
hideNotice() {
|
|
117
118
|
var t;
|
|
@@ -121,24 +122,24 @@ class x {
|
|
|
121
122
|
this.ctx.hostEl.dispatchEvent(new CustomEvent("hp:history", { detail: { state: t, time: e, id: this.key } }));
|
|
122
123
|
}
|
|
123
124
|
}
|
|
124
|
-
function l(
|
|
125
|
+
function l(o) {
|
|
125
126
|
try {
|
|
126
|
-
return JSON.parse(localStorage.getItem(
|
|
127
|
+
return JSON.parse(localStorage.getItem(o) ?? "null");
|
|
127
128
|
} catch {
|
|
128
129
|
return null;
|
|
129
130
|
}
|
|
130
131
|
}
|
|
131
|
-
function
|
|
132
|
+
function m(o, t) {
|
|
132
133
|
try {
|
|
133
|
-
localStorage.setItem(
|
|
134
|
+
localStorage.setItem(o, JSON.stringify(t));
|
|
134
135
|
} catch {
|
|
135
136
|
}
|
|
136
137
|
}
|
|
137
|
-
function
|
|
138
|
-
return new
|
|
138
|
+
function P(o, t) {
|
|
139
|
+
return v(o.videoEl, "history", y), new N(o, t);
|
|
139
140
|
}
|
|
140
141
|
export {
|
|
141
|
-
|
|
142
|
-
|
|
142
|
+
N as PlaybackHistory,
|
|
143
|
+
P as installHistory
|
|
143
144
|
};
|
|
144
|
-
//# sourceMappingURL=history-
|
|
145
|
+
//# sourceMappingURL=history-ZSdDDsRF.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"history-CwqLXiZi.js","sources":["../../src/plugins/history/PlaybackHistory.ts","../../src/plugins/history/index.ts"],"sourcesContent":["import type { HistoryOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\nimport { formatTime } from '../../utils/format-time';\nimport { seekWhenReady } from '../shared/seekWhenReady';\n\nexport interface HistoryPlayerContext {\n hostEl: HTMLElement;\n videoEl: HTMLVideoElement;\n overlayContainerEl: HTMLElement;\n i18n: HopeLocaleStrings;\n /** Şu an yüklü kaynağın adresi (hls.js'te blob değil gerçek .m3u8) — `id` verilmezse videonun anahtarı. */\n currentSrc(): string | null;\n isAdActive(): boolean;\n /** `options.muted` — otomatik oynatma için sessiz istendiyse hatırlanan \"sesli\" durumu onu bozmasın. */\n mutedRequested(): boolean;\n /** QR ile devam (`?vtime=`) bu sayfa açılışında bir konum getirdiyse — ilk yüklemede o kazanır. */\n linkTimePresent: boolean;\n}\n\nconst POSITIONS_KEY = 'hp-history-positions';\nconst VOLUME_KEY = 'hp-history-volume';\n/** Bu kadar saniye izlenmeden konum kaydedilmez (yanlışlıkla açılan video). */\nconst DEFAULT_MIN_WATCHED = 10;\n/** Sona bu kadar kala \"bitti\" sayılır — kayıt silinir, sonraki açılışta baştan başlar. */\nconst DEFAULT_END_MARGIN = 15;\nconst DEFAULT_MAX_ENTRIES = 50;\nconst DEFAULT_TTL_DAYS = 30;\n/** Oynarken konum en fazla bu sıklıkla yazılır (ms). */\nconst SAVE_EVERY_MS = 5000;\nconst NOTICE_MS = 6000;\n\ninterface Entry {\n t: number;\n d: number;\n at: number;\n}\n\n/**\n * Zaman ve ses geçmişi: video yarıda bırakılırsa bir sonraki açılışta kaldığı yerden başlar (\"Kaldığınız yerden devam:\n * 0:42 · Baştan başla\" bildirimiyle); ses seviyesi ve sessiz durumu sitede hatırlanır. Kayıtlar tarayıcıda (localStorage).\n * Canlı yayında, reklam sırasında ve sona yakın konumda kayıt yapılmaz.\n */\nexport class PlaybackHistory {\n private key: string | null = null;\n private lastSaveAt = 0;\n private noticeEl: HTMLDivElement | null = null;\n private noticeTimer: ReturnType<typeof setTimeout> | null = null;\n private skipNextRestore: boolean;\n private readonly position: boolean;\n private readonly volume: boolean;\n private readonly minWatched: number;\n private readonly endMargin: number;\n\n constructor(\n private readonly ctx: HistoryPlayerContext,\n private readonly options: HistoryOptions\n ) {\n this.position = options.position !== false;\n this.volume = options.volume !== false;\n this.minWatched = options.minWatched ?? DEFAULT_MIN_WATCHED;\n this.endMargin = options.endMargin ?? DEFAULT_END_MARGIN;\n this.skipNextRestore = ctx.linkTimePresent;\n\n const v = ctx.videoEl;\n if (this.volume) {\n this.restoreVolume();\n v.addEventListener('volumechange', this.saveVolume);\n }\n if (this.position) {\n v.addEventListener('loadedmetadata', this.onLoadedMetadata);\n v.addEventListener('timeupdate', this.onTimeUpdate);\n v.addEventListener('pause', this.savePosition);\n v.addEventListener('seeked', this.savePosition);\n v.addEventListener('ended', this.onEnded);\n window.addEventListener('pagehide', this.savePosition);\n document.addEventListener('visibilitychange', this.onVisibility);\n if (v.readyState >= 1) this.onLoadedMetadata();\n }\n }\n\n destroy(): void {\n const v = this.ctx.videoEl;\n this.savePosition();\n v.removeEventListener('volumechange', this.saveVolume);\n v.removeEventListener('loadedmetadata', this.onLoadedMetadata);\n v.removeEventListener('timeupdate', this.onTimeUpdate);\n v.removeEventListener('pause', this.savePosition);\n v.removeEventListener('seeked', this.savePosition);\n v.removeEventListener('ended', this.onEnded);\n window.removeEventListener('pagehide', this.savePosition);\n document.removeEventListener('visibilitychange', this.onVisibility);\n this.hideNotice();\n }\n\n refreshLabels(): void {\n this.hideNotice();\n }\n\n // ── Konum ──\n\n private videoKey(): string | null {\n if (this.options.id) return `id:${this.options.id}`;\n const src = this.ctx.currentSrc();\n if (!src || src.startsWith('blob:') || src.startsWith('data:')) return null;\n try {\n const u = new URL(src, location.href);\n u.hash = '';\n return u.href;\n } catch {\n return src;\n }\n }\n\n private readonly onLoadedMetadata = (): void => {\n const v = this.ctx.videoEl;\n this.key = this.videoKey();\n this.lastSaveAt = 0;\n if (!this.key || !Number.isFinite(v.duration)) return;\n // Link ile gelen konum (QR ile devam) yalnızca bu açılışta kazanır.\n if (this.skipNextRestore) {\n this.skipNextRestore = false;\n return;\n }\n // Başka bir şey zaten sarmışsa (ör. kaynak değişiminde korunan konum) dokunma.\n if (v.currentTime > 1) return;\n const entry = this.entries()[this.key];\n if (!entry || entry.t < this.minWatched || entry.t > v.duration - this.endMargin) return;\n seekWhenReady(v, entry.t, { attempts: 2 });\n this.showNotice(entry.t);\n this.emit('resumed', entry.t);\n };\n\n private readonly onTimeUpdate = (): void => {\n if (Date.now() - this.lastSaveAt < SAVE_EVERY_MS) return;\n this.savePosition();\n };\n\n private readonly onVisibility = (): void => {\n if (document.visibilityState === 'hidden') this.savePosition();\n };\n\n private readonly savePosition = (): void => {\n const v = this.ctx.videoEl;\n if (!this.key || this.ctx.isAdActive() || v.seeking) return;\n const d = v.duration;\n if (!Number.isFinite(d) || d <= 0) return; // canlı yayın\n this.lastSaveAt = Date.now();\n const t = v.currentTime;\n const all = this.entries();\n if (t >= d - this.endMargin) delete all[this.key];\n else if (t >= this.minWatched) all[this.key] = { t: Math.floor(t), d: Math.round(d), at: Date.now() };\n else return;\n this.store(all);\n };\n\n private readonly onEnded = (): void => {\n if (!this.key) return;\n const all = this.entries();\n delete all[this.key];\n this.store(all);\n };\n\n /** Süresi geçenleri at, en yeni `maxEntries` kaydı tut. */\n private store(all: Record<string, Entry>): void {\n const ttl = (this.options.ttlDays ?? DEFAULT_TTL_DAYS) * 86_400_000;\n const max = this.options.maxEntries ?? DEFAULT_MAX_ENTRIES;\n const now = Date.now();\n const kept = Object.entries(all)\n .filter(([, e]) => now - e.at < ttl)\n .sort((a, b) => b[1].at - a[1].at)\n .slice(0, max);\n write(POSITIONS_KEY, Object.fromEntries(kept));\n }\n\n private entries(): Record<string, Entry> {\n const raw = read<Record<string, Entry>>(POSITIONS_KEY);\n return raw && typeof raw === 'object' ? raw : {};\n }\n\n // ── Ses ──\n\n private restoreVolume(): void {\n const saved = read<{ volume: number; muted: boolean }>(VOLUME_KEY);\n if (!saved || typeof saved.volume !== 'number') return;\n const v = this.ctx.videoEl;\n v.volume = Math.min(1, Math.max(0, saved.volume));\n // Sessiz otomatik oynatma istendiyse (options.muted) \"sesli\" kaydı onu bozmasın; kullanıcı sessize aldıysa korunur.\n v.muted = this.ctx.mutedRequested() || !!saved.muted;\n }\n\n private readonly saveVolume = (): void => {\n if (this.ctx.isAdActive()) return;\n const v = this.ctx.videoEl;\n write(VOLUME_KEY, { volume: Math.round(v.volume * 100) / 100, muted: v.muted });\n };\n\n // ── Bildirim ──\n\n private showNotice(time: number): void {\n if (this.options.notice === false) return;\n this.hideNotice();\n const t = this.ctx.i18n;\n const el = document.createElement('div');\n el.className = 'hp-history-notice';\n el.setAttribute('part', 'history-notice');\n el.setAttribute('role', 'status');\n const text = document.createElement('span');\n text.textContent = t.historyResumed(formatTime(time));\n const restart = document.createElement('button');\n restart.type = 'button';\n restart.className = 'hp-history-restart';\n restart.textContent = t.historyRestart;\n restart.addEventListener('click', () => {\n const v = this.ctx.videoEl;\n v.currentTime = 0;\n if (this.key) {\n const all = this.entries();\n delete all[this.key];\n this.store(all);\n }\n this.emit('restart', 0);\n this.hideNotice();\n });\n el.append(text, restart);\n // Bildirimdeki tıklama oynat / duraklat'a geçmesin.\n for (const ev of ['pointerdown', 'mousedown', 'mouseup', 'touchstart', 'touchend', 'click', 'dblclick'] as const) el.addEventListener(ev, (e) => e.stopPropagation());\n this.ctx.overlayContainerEl.appendChild(el);\n this.noticeEl = el;\n this.noticeTimer = setTimeout(() => this.hideNotice(), NOTICE_MS);\n }\n\n private hideNotice(): void {\n if (this.noticeTimer) clearTimeout(this.noticeTimer);\n this.noticeTimer = null;\n this.noticeEl?.remove();\n this.noticeEl = null;\n }\n\n private emit(state: 'resumed' | 'restart', time: number): void {\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:history', { detail: { state, time, id: this.key } }));\n }\n}\n\nfunction read<T>(key: string): T | null {\n try {\n return JSON.parse(localStorage.getItem(key) ?? 'null') as T | null;\n } catch {\n return null;\n }\n}\n\nfunction write(key: string, value: unknown): void {\n try {\n localStorage.setItem(key, JSON.stringify(value));\n } catch {\n /* gizli sekme / kota dolu — geçmiş yalnızca bu oturumda yok */\n }\n}\n","import { PlaybackHistory, type HistoryPlayerContext } from './PlaybackHistory';\nimport type { HistoryOptions } from '../../types';\n\nexport function installHistory(ctx: HistoryPlayerContext, options: HistoryOptions): PlaybackHistory {\n return new PlaybackHistory(ctx, options);\n}\n\nexport { PlaybackHistory };\nexport type { HistoryPlayerContext };\n"],"names":["POSITIONS_KEY","VOLUME_KEY","DEFAULT_MIN_WATCHED","DEFAULT_END_MARGIN","DEFAULT_MAX_ENTRIES","DEFAULT_TTL_DAYS","SAVE_EVERY_MS","NOTICE_MS","PlaybackHistory","ctx","options","__publicField","v","entry","seekWhenReady","d","t","all","write","src","u","ttl","max","now","kept","e","b","raw","read","saved","time","el","text","formatTime","restart","ev","_a","state","key","value","installHistory"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"history-ZSdDDsRF.js","sources":["../../src/plugins/history/PlaybackHistory.ts","../../src/plugins/history/index.ts"],"sourcesContent":["import type { HistoryOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\nimport { formatTime } from '../../utils/format-time';\nimport { seekWhenReady } from '../shared/seekWhenReady';\n\nexport interface HistoryPlayerContext {\n hostEl: HTMLElement;\n videoEl: HTMLVideoElement;\n overlayContainerEl: HTMLElement;\n i18n: HopeLocaleStrings;\n /** Şu an yüklü kaynağın adresi (hls.js'te blob değil gerçek .m3u8) — `id` verilmezse videonun anahtarı. */\n currentSrc(): string | null;\n isAdActive(): boolean;\n /** `options.muted` — otomatik oynatma için sessiz istendiyse hatırlanan \"sesli\" durumu onu bozmasın. */\n mutedRequested(): boolean;\n /** QR ile devam (`?vtime=`) bu sayfa açılışında bir konum getirdiyse — ilk yüklemede o kazanır. */\n linkTimePresent: boolean;\n}\n\nconst POSITIONS_KEY = 'hp-history-positions';\nconst VOLUME_KEY = 'hp-history-volume';\n/** Bu kadar saniye izlenmeden konum kaydedilmez (yanlışlıkla açılan video). */\nconst DEFAULT_MIN_WATCHED = 10;\n/** Sona bu kadar kala \"bitti\" sayılır — kayıt silinir, sonraki açılışta baştan başlar. */\nconst DEFAULT_END_MARGIN = 15;\nconst DEFAULT_MAX_ENTRIES = 50;\nconst DEFAULT_TTL_DAYS = 30;\n/** Oynarken konum en fazla bu sıklıkla yazılır (ms). */\nconst SAVE_EVERY_MS = 5000;\nconst NOTICE_MS = 6000;\n\ninterface Entry {\n t: number;\n d: number;\n at: number;\n}\n\n/**\n * Zaman ve ses geçmişi: video yarıda bırakılırsa bir sonraki açılışta kaldığı yerden başlar (\"Kaldığınız yerden devam:\n * 0:42 · Baştan başla\" bildirimiyle); ses seviyesi ve sessiz durumu sitede hatırlanır. Kayıtlar tarayıcıda (localStorage).\n * Canlı yayında, reklam sırasında ve sona yakın konumda kayıt yapılmaz.\n */\nexport class PlaybackHistory {\n private key: string | null = null;\n private lastSaveAt = 0;\n private noticeEl: HTMLDivElement | null = null;\n private noticeTimer: ReturnType<typeof setTimeout> | null = null;\n private skipNextRestore: boolean;\n private readonly position: boolean;\n private readonly volume: boolean;\n private readonly minWatched: number;\n private readonly endMargin: number;\n\n constructor(\n private readonly ctx: HistoryPlayerContext,\n private readonly options: HistoryOptions\n ) {\n this.position = options.position !== false;\n this.volume = options.volume !== false;\n this.minWatched = options.minWatched ?? DEFAULT_MIN_WATCHED;\n this.endMargin = options.endMargin ?? DEFAULT_END_MARGIN;\n this.skipNextRestore = ctx.linkTimePresent;\n\n const v = ctx.videoEl;\n if (this.volume) {\n this.restoreVolume();\n v.addEventListener('volumechange', this.saveVolume);\n }\n if (this.position) {\n v.addEventListener('loadedmetadata', this.onLoadedMetadata);\n v.addEventListener('timeupdate', this.onTimeUpdate);\n v.addEventListener('pause', this.savePosition);\n v.addEventListener('seeked', this.savePosition);\n v.addEventListener('ended', this.onEnded);\n window.addEventListener('pagehide', this.savePosition);\n document.addEventListener('visibilitychange', this.onVisibility);\n if (v.readyState >= 1) this.onLoadedMetadata();\n }\n }\n\n destroy(): void {\n const v = this.ctx.videoEl;\n this.savePosition();\n v.removeEventListener('volumechange', this.saveVolume);\n v.removeEventListener('loadedmetadata', this.onLoadedMetadata);\n v.removeEventListener('timeupdate', this.onTimeUpdate);\n v.removeEventListener('pause', this.savePosition);\n v.removeEventListener('seeked', this.savePosition);\n v.removeEventListener('ended', this.onEnded);\n window.removeEventListener('pagehide', this.savePosition);\n document.removeEventListener('visibilitychange', this.onVisibility);\n this.hideNotice();\n }\n\n refreshLabels(): void {\n this.hideNotice();\n }\n\n // ── Konum ──\n\n private videoKey(): string | null {\n if (this.options.id) return `id:${this.options.id}`;\n const src = this.ctx.currentSrc();\n if (!src || src.startsWith('blob:') || src.startsWith('data:')) return null;\n try {\n const u = new URL(src, location.href);\n u.hash = '';\n return u.href;\n } catch {\n return src;\n }\n }\n\n private readonly onLoadedMetadata = (): void => {\n const v = this.ctx.videoEl;\n this.key = this.videoKey();\n this.lastSaveAt = 0;\n if (!this.key || !Number.isFinite(v.duration)) return;\n // Link ile gelen konum (QR ile devam) yalnızca bu açılışta kazanır.\n if (this.skipNextRestore) {\n this.skipNextRestore = false;\n return;\n }\n // Başka bir şey zaten sarmışsa (ör. kaynak değişiminde korunan konum) dokunma.\n if (v.currentTime > 1) return;\n const entry = this.entries()[this.key];\n if (!entry || entry.t < this.minWatched || entry.t > v.duration - this.endMargin) return;\n seekWhenReady(v, entry.t, { attempts: 2 });\n this.showNotice(entry.t);\n this.emit('resumed', entry.t);\n };\n\n private readonly onTimeUpdate = (): void => {\n if (Date.now() - this.lastSaveAt < SAVE_EVERY_MS) return;\n this.savePosition();\n };\n\n private readonly onVisibility = (): void => {\n if (document.visibilityState === 'hidden') this.savePosition();\n };\n\n private readonly savePosition = (): void => {\n const v = this.ctx.videoEl;\n if (!this.key || this.ctx.isAdActive() || v.seeking) return;\n const d = v.duration;\n if (!Number.isFinite(d) || d <= 0) return; // canlı yayın\n this.lastSaveAt = Date.now();\n const t = v.currentTime;\n const all = this.entries();\n if (t >= d - this.endMargin) delete all[this.key];\n else if (t >= this.minWatched) all[this.key] = { t: Math.floor(t), d: Math.round(d), at: Date.now() };\n else return;\n this.store(all);\n };\n\n private readonly onEnded = (): void => {\n if (!this.key) return;\n const all = this.entries();\n delete all[this.key];\n this.store(all);\n };\n\n /** Süresi geçenleri at, en yeni `maxEntries` kaydı tut. */\n private store(all: Record<string, Entry>): void {\n const ttl = (this.options.ttlDays ?? DEFAULT_TTL_DAYS) * 86_400_000;\n const max = this.options.maxEntries ?? DEFAULT_MAX_ENTRIES;\n const now = Date.now();\n const kept = Object.entries(all)\n .filter(([, e]) => now - e.at < ttl)\n .sort((a, b) => b[1].at - a[1].at)\n .slice(0, max);\n write(POSITIONS_KEY, Object.fromEntries(kept));\n }\n\n private entries(): Record<string, Entry> {\n const raw = read<Record<string, Entry>>(POSITIONS_KEY);\n return raw && typeof raw === 'object' ? raw : {};\n }\n\n // ── Ses ──\n\n private restoreVolume(): void {\n const saved = read<{ volume: number; muted: boolean }>(VOLUME_KEY);\n if (!saved || typeof saved.volume !== 'number') return;\n const v = this.ctx.videoEl;\n v.volume = Math.min(1, Math.max(0, saved.volume));\n // Sessiz otomatik oynatma istendiyse (options.muted) \"sesli\" kaydı onu bozmasın; kullanıcı sessize aldıysa korunur.\n v.muted = this.ctx.mutedRequested() || !!saved.muted;\n }\n\n private readonly saveVolume = (): void => {\n if (this.ctx.isAdActive()) return;\n const v = this.ctx.videoEl;\n write(VOLUME_KEY, { volume: Math.round(v.volume * 100) / 100, muted: v.muted });\n };\n\n // ── Bildirim ──\n\n private showNotice(time: number): void {\n if (this.options.notice === false) return;\n this.hideNotice();\n const t = this.ctx.i18n;\n const el = document.createElement('div');\n el.className = 'hp-history-notice';\n el.setAttribute('part', 'history-notice');\n el.setAttribute('role', 'status');\n const text = document.createElement('span');\n text.textContent = t.historyResumed(formatTime(time));\n const restart = document.createElement('button');\n restart.type = 'button';\n restart.className = 'hp-history-restart';\n restart.textContent = t.historyRestart;\n restart.addEventListener('click', () => {\n const v = this.ctx.videoEl;\n v.currentTime = 0;\n if (this.key) {\n const all = this.entries();\n delete all[this.key];\n this.store(all);\n }\n this.emit('restart', 0);\n this.hideNotice();\n });\n el.append(text, restart);\n // Bildirimdeki tıklama oynat / duraklat'a geçmesin.\n for (const ev of ['pointerdown', 'mousedown', 'mouseup', 'touchstart', 'touchend', 'click', 'dblclick'] as const) el.addEventListener(ev, (e) => e.stopPropagation());\n this.ctx.overlayContainerEl.appendChild(el);\n this.noticeEl = el;\n this.noticeTimer = setTimeout(() => this.hideNotice(), NOTICE_MS);\n }\n\n private hideNotice(): void {\n if (this.noticeTimer) clearTimeout(this.noticeTimer);\n this.noticeTimer = null;\n this.noticeEl?.remove();\n this.noticeEl = null;\n }\n\n private emit(state: 'resumed' | 'restart', time: number): void {\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:history', { detail: { state, time, id: this.key } }));\n }\n}\n\nfunction read<T>(key: string): T | null {\n try {\n return JSON.parse(localStorage.getItem(key) ?? 'null') as T | null;\n } catch {\n return null;\n }\n}\n\nfunction write(key: string, value: unknown): void {\n try {\n localStorage.setItem(key, JSON.stringify(value));\n } catch {\n /* gizli sekme / kota dolu — geçmiş yalnızca bu oturumda yok */\n }\n}\n","import { adoptStyle } from '../../utils/plugin-style';\nimport css from './history.css?inline';\nimport { PlaybackHistory, type HistoryPlayerContext } from './PlaybackHistory';\nimport type { HistoryOptions } from '../../types';\n\nexport function installHistory(ctx: HistoryPlayerContext, options: HistoryOptions): PlaybackHistory {\n adoptStyle(ctx.videoEl, 'history', css);\n return new PlaybackHistory(ctx, options);\n}\n\nexport { PlaybackHistory };\nexport type { HistoryPlayerContext };\n"],"names":["POSITIONS_KEY","VOLUME_KEY","DEFAULT_MIN_WATCHED","DEFAULT_END_MARGIN","DEFAULT_MAX_ENTRIES","DEFAULT_TTL_DAYS","SAVE_EVERY_MS","NOTICE_MS","PlaybackHistory","ctx","options","__publicField","v","entry","seekWhenReady","d","t","all","write","src","u","ttl","max","now","kept","e","b","raw","read","saved","time","el","text","formatTime","restart","ev","_a","state","key","value","installHistory","adoptStyle","css"],"mappings":";;;;;;kmCAmBMA,IAAgB,wBAChBC,IAAa,qBAEbC,IAAsB,IAEtBC,IAAqB,IACrBC,IAAsB,IACtBC,IAAmB,IAEnBC,IAAgB,KAChBC,IAAY;AAaX,MAAMC,EAAgB;AAAA,EAWzB,YACqBC,GACAC,GACnB;AAbM,IAAAC,EAAA,aAAqB;AACrB,IAAAA,EAAA,oBAAa;AACb,IAAAA,EAAA,kBAAkC;AAClC,IAAAA,EAAA,qBAAoD;AACpD,IAAAA,EAAA;AACS,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AA8DA,IAAAA,EAAA,0BAAmB,MAAY;AAC5C,YAAMC,IAAI,KAAK,IAAI;AAGnB,UAFA,KAAK,MAAM,KAAK,SAAA,GAChB,KAAK,aAAa,GACd,CAAC,KAAK,OAAO,CAAC,OAAO,SAASA,EAAE,QAAQ,EAAG;AAE/C,UAAI,KAAK,iBAAiB;AACtB,aAAK,kBAAkB;AACvB;AAAA,MACJ;AAEA,UAAIA,EAAE,cAAc,EAAG;AACvB,YAAMC,IAAQ,KAAK,QAAA,EAAU,KAAK,GAAG;AACrC,MAAI,CAACA,KAASA,EAAM,IAAI,KAAK,cAAcA,EAAM,IAAID,EAAE,WAAW,KAAK,cACvEE,EAAcF,GAAGC,EAAM,GAAG,EAAE,UAAU,GAAG,GACzC,KAAK,WAAWA,EAAM,CAAC,GACvB,KAAK,KAAK,WAAWA,EAAM,CAAC;AAAA,IAChC;AAEiB,IAAAF,EAAA,sBAAe,MAAY;AACxC,MAAI,KAAK,IAAA,IAAQ,KAAK,aAAaL,KACnC,KAAK,aAAA;AAAA,IACT;AAEiB,IAAAK,EAAA,sBAAe,MAAY;AACxC,MAAI,SAAS,oBAAoB,YAAU,KAAK,aAAA;AAAA,IACpD;AAEiB,IAAAA,EAAA,sBAAe,MAAY;AACxC,YAAMC,IAAI,KAAK,IAAI;AACnB,UAAI,CAAC,KAAK,OAAO,KAAK,IAAI,WAAA,KAAgBA,EAAE,QAAS;AACrD,YAAMG,IAAIH,EAAE;AACZ,UAAI,CAAC,OAAO,SAASG,CAAC,KAAKA,KAAK,EAAG;AACnC,WAAK,aAAa,KAAK,IAAA;AACvB,YAAMC,IAAIJ,EAAE,aACNK,IAAM,KAAK,QAAA;AACjB,UAAID,KAAKD,IAAI,KAAK,UAAW,QAAOE,EAAI,KAAK,GAAG;AAAA,eACvCD,KAAK,KAAK,WAAY,CAAAC,EAAI,KAAK,GAAG,IAAI,EAAE,GAAG,KAAK,MAAMD,CAAC,GAAG,GAAG,KAAK,MAAMD,CAAC,GAAG,IAAI,KAAK,MAAI;AAAA,UAC7F;AACL,WAAK,MAAME,CAAG;AAAA,IAClB;AAEiB,IAAAN,EAAA,iBAAU,MAAY;AACnC,UAAI,CAAC,KAAK,IAAK;AACf,YAAMM,IAAM,KAAK,QAAA;AACjB,aAAOA,EAAI,KAAK,GAAG,GACnB,KAAK,MAAMA,CAAG;AAAA,IAClB;AA8BiB,IAAAN,EAAA,oBAAa,MAAY;AACtC,UAAI,KAAK,IAAI,aAAc;AAC3B,YAAMC,IAAI,KAAK,IAAI;AACnB,MAAAM,EAAMjB,GAAY,EAAE,QAAQ,KAAK,MAAMW,EAAE,SAAS,GAAG,IAAI,KAAK,OAAOA,EAAE,OAAO;AAAA,IAClF;AA5IqB,SAAA,MAAAH,GACA,KAAA,UAAAC,GAEjB,KAAK,WAAWA,EAAQ,aAAa,IACrC,KAAK,SAASA,EAAQ,WAAW,IACjC,KAAK,aAAaA,EAAQ,cAAcR,GACxC,KAAK,YAAYQ,EAAQ,aAAaP,GACtC,KAAK,kBAAkBM,EAAI;AAE3B,UAAMG,IAAIH,EAAI;AACd,IAAI,KAAK,WACL,KAAK,cAAA,GACLG,EAAE,iBAAiB,gBAAgB,KAAK,UAAU,IAElD,KAAK,aACLA,EAAE,iBAAiB,kBAAkB,KAAK,gBAAgB,GAC1DA,EAAE,iBAAiB,cAAc,KAAK,YAAY,GAClDA,EAAE,iBAAiB,SAAS,KAAK,YAAY,GAC7CA,EAAE,iBAAiB,UAAU,KAAK,YAAY,GAC9CA,EAAE,iBAAiB,SAAS,KAAK,OAAO,GACxC,OAAO,iBAAiB,YAAY,KAAK,YAAY,GACrD,SAAS,iBAAiB,oBAAoB,KAAK,YAAY,GAC3DA,EAAE,cAAc,KAAG,KAAK,iBAAA;AAAA,EAEpC;AAAA,EAEA,UAAgB;AACZ,UAAMA,IAAI,KAAK,IAAI;AACnB,SAAK,aAAA,GACLA,EAAE,oBAAoB,gBAAgB,KAAK,UAAU,GACrDA,EAAE,oBAAoB,kBAAkB,KAAK,gBAAgB,GAC7DA,EAAE,oBAAoB,cAAc,KAAK,YAAY,GACrDA,EAAE,oBAAoB,SAAS,KAAK,YAAY,GAChDA,EAAE,oBAAoB,UAAU,KAAK,YAAY,GACjDA,EAAE,oBAAoB,SAAS,KAAK,OAAO,GAC3C,OAAO,oBAAoB,YAAY,KAAK,YAAY,GACxD,SAAS,oBAAoB,oBAAoB,KAAK,YAAY,GAClE,KAAK,WAAA;AAAA,EACT;AAAA,EAEA,gBAAsB;AAClB,SAAK,WAAA;AAAA,EACT;AAAA;AAAA,EAIQ,WAA0B;AAC9B,QAAI,KAAK,QAAQ,WAAW,MAAM,KAAK,QAAQ,EAAE;AACjD,UAAMO,IAAM,KAAK,IAAI,WAAA;AACrB,QAAI,CAACA,KAAOA,EAAI,WAAW,OAAO,KAAKA,EAAI,WAAW,OAAO,EAAG,QAAO;AACvE,QAAI;AACA,YAAMC,IAAI,IAAI,IAAID,GAAK,SAAS,IAAI;AACpC,aAAAC,EAAE,OAAO,IACFA,EAAE;AAAA,IACb,QAAQ;AACJ,aAAOD;AAAA,IACX;AAAA,EACJ;AAAA;AAAA,EAoDQ,MAAMF,GAAkC;AAC5C,UAAMI,KAAO,KAAK,QAAQ,WAAWhB,KAAoB,OACnDiB,IAAM,KAAK,QAAQ,cAAclB,GACjCmB,IAAM,KAAK,IAAA,GACXC,IAAO,OAAO,QAAQP,CAAG,EAC1B,OAAO,CAAC,CAAA,EAAGQ,CAAC,MAAMF,IAAME,EAAE,KAAKJ,CAAG,EAClC,KAAK,CAAC,GAAGK,MAAMA,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAChC,MAAM,GAAGJ,CAAG;AACjB,IAAAJ,EAAMlB,GAAe,OAAO,YAAYwB,CAAI,CAAC;AAAA,EACjD;AAAA,EAEQ,UAAiC;AACrC,UAAMG,IAAMC,EAA4B5B,CAAa;AACrD,WAAO2B,KAAO,OAAOA,KAAQ,WAAWA,IAAM,CAAA;AAAA,EAClD;AAAA;AAAA,EAIQ,gBAAsB;AAC1B,UAAME,IAAQD,EAAyC3B,CAAU;AACjE,QAAI,CAAC4B,KAAS,OAAOA,EAAM,UAAW,SAAU;AAChD,UAAMjB,IAAI,KAAK,IAAI;AACnB,IAAAA,EAAE,SAAS,KAAK,IAAI,GAAG,KAAK,IAAI,GAAGiB,EAAM,MAAM,CAAC,GAEhDjB,EAAE,QAAQ,KAAK,IAAI,oBAAoB,CAAC,CAACiB,EAAM;AAAA,EACnD;AAAA;AAAA,EAUQ,WAAWC,GAAoB;AACnC,QAAI,KAAK,QAAQ,WAAW,GAAO;AACnC,SAAK,WAAA;AACL,UAAMd,IAAI,KAAK,IAAI,MACbe,IAAK,SAAS,cAAc,KAAK;AACvC,IAAAA,EAAG,YAAY,qBACfA,EAAG,aAAa,QAAQ,gBAAgB,GACxCA,EAAG,aAAa,QAAQ,QAAQ;AAChC,UAAMC,IAAO,SAAS,cAAc,MAAM;AAC1C,IAAAA,EAAK,cAAchB,EAAE,eAAeiB,EAAWH,CAAI,CAAC;AACpD,UAAMI,IAAU,SAAS,cAAc,QAAQ;AAC/C,IAAAA,EAAQ,OAAO,UACfA,EAAQ,YAAY,sBACpBA,EAAQ,cAAclB,EAAE,gBACxBkB,EAAQ,iBAAiB,SAAS,MAAM;AACpC,YAAMtB,IAAI,KAAK,IAAI;AAEnB,UADAA,EAAE,cAAc,GACZ,KAAK,KAAK;AACV,cAAMK,IAAM,KAAK,QAAA;AACjB,eAAOA,EAAI,KAAK,GAAG,GACnB,KAAK,MAAMA,CAAG;AAAA,MAClB;AACA,WAAK,KAAK,WAAW,CAAC,GACtB,KAAK,WAAA;AAAA,IACT,CAAC,GACDc,EAAG,OAAOC,GAAME,CAAO;AAEvB,eAAWC,KAAM,CAAC,eAAe,aAAa,WAAW,cAAc,YAAY,SAAS,UAAU,KAAe,iBAAiBA,GAAI,CAACV,MAAMA,EAAE,iBAAiB;AACpK,SAAK,IAAI,mBAAmB,YAAYM,CAAE,GAC1C,KAAK,WAAWA,GAChB,KAAK,cAAc,WAAW,MAAM,KAAK,WAAA,GAAcxB,CAAS;AAAA,EACpE;AAAA,EAEQ,aAAmB;;AACvB,IAAI,KAAK,eAAa,aAAa,KAAK,WAAW,GACnD,KAAK,cAAc,OACnB6B,IAAA,KAAK,aAAL,QAAAA,EAAe,UACf,KAAK,WAAW;AAAA,EACpB;AAAA,EAEQ,KAAKC,GAA8BP,GAAoB;AAC3D,SAAK,IAAI,OAAO,cAAc,IAAI,YAAY,cAAc,EAAE,QAAQ,EAAE,OAAAO,GAAO,MAAAP,GAAM,IAAI,KAAK,IAAA,EAAI,CAAG,CAAC;AAAA,EAC1G;AACJ;AAEA,SAASF,EAAQU,GAAuB;AACpC,MAAI;AACA,WAAO,KAAK,MAAM,aAAa,QAAQA,CAAG,KAAK,MAAM;AAAA,EACzD,QAAQ;AACJ,WAAO;AAAA,EACX;AACJ;AAEA,SAASpB,EAAMoB,GAAaC,GAAsB;AAC9C,MAAI;AACA,iBAAa,QAAQD,GAAK,KAAK,UAAUC,CAAK,CAAC;AAAA,EACnD,QAAQ;AAAA,EAER;AACJ;AC5PO,SAASC,EAAe/B,GAA2BC,GAA0C;AAChG,SAAA+B,EAAWhC,EAAI,SAAS,WAAWiC,CAAG,GAC/B,IAAIlC,EAAgBC,GAAKC,CAAO;AAC3C;"}
|