@hopeplayer/core 1.4.0 → 1.6.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 +42 -2
- package/dist/HopePlayerElement.d.ts.map +1 -1
- package/dist/chunks/NativeEme-CXosVcw8.js +80 -0
- package/dist/chunks/NativeEme-CXosVcw8.js.map +1 -0
- package/dist/chunks/{accessibility-DeUIoAda.js → accessibility-DFx4CE0H.js} +9 -8
- package/dist/chunks/{accessibility-DeUIoAda.js.map → accessibility-DFx4CE0H.js.map} +1 -1
- package/dist/chunks/adTriggers-BIAWe8o4.js +419 -0
- package/dist/chunks/adTriggers-BIAWe8o4.js.map +1 -0
- package/dist/chunks/{ads-CdWbE9aD.js → ads-DlpHPpR9.js} +3 -3
- package/dist/chunks/ads-DlpHPpR9.js.map +1 -0
- package/dist/chunks/analytics-DEjTAJO9.js +281 -0
- package/dist/chunks/analytics-DEjTAJO9.js.map +1 -0
- package/dist/chunks/{cast-BQ-suTcF.js → cast-vHyi7oV_.js} +2 -2
- package/dist/chunks/{cast-BQ-suTcF.js.map → cast-vHyi7oV_.js.map} +1 -1
- package/dist/chunks/dash-CWjy-y7B.js +22 -0
- package/dist/chunks/dash-CWjy-y7B.js.map +1 -0
- package/dist/chunks/docPip-wybMVP1H.js +82 -0
- package/dist/chunks/docPip-wybMVP1H.js.map +1 -0
- package/dist/chunks/heatmap-Bb7neaYU.js +92 -0
- package/dist/chunks/heatmap-Bb7neaYU.js.map +1 -0
- package/dist/chunks/{history-DAbqEhNB.js → history-CwqLXiZi.js} +2 -2
- package/dist/chunks/{history-DAbqEhNB.js.map → history-CwqLXiZi.js.map} +1 -1
- package/dist/chunks/interactive-CgltIneu.js +189 -0
- package/dist/chunks/interactive-CgltIneu.js.map +1 -0
- package/dist/chunks/keySystems-CNzjRq6e.js +70 -0
- package/dist/chunks/keySystems-CNzjRq6e.js.map +1 -0
- package/dist/chunks/{loopSection-CvF4l5uf.js → loopSection-Bwk4W8vz.js} +16 -16
- package/dist/chunks/loopSection-Bwk4W8vz.js.map +1 -0
- package/dist/chunks/{markers-B04NMI79.js → markers-L69W3kj6.js} +53 -51
- package/dist/chunks/markers-L69W3kj6.js.map +1 -0
- package/dist/chunks/player-D2_HRzot.js +4351 -0
- package/dist/chunks/player-D2_HRzot.js.map +1 -0
- package/dist/chunks/{playlist-C6Mh9BE8.js → playlist-CHfStNbQ.js} +29 -21
- package/dist/chunks/playlist-CHfStNbQ.js.map +1 -0
- package/dist/chunks/plugin-style-CPJELe-i.js +17 -0
- package/dist/chunks/plugin-style-CPJELe-i.js.map +1 -0
- package/dist/chunks/pluginHost-cN2uGFeG.js +566 -0
- package/dist/chunks/pluginHost-cN2uGFeG.js.map +1 -0
- package/dist/chunks/redirectScreen-TIqLdvBY.js +239 -0
- package/dist/chunks/redirectScreen-TIqLdvBY.js.map +1 -0
- package/dist/chunks/{rewardedUnlock-CGhQyWOk.js → rewardedUnlock-DUqYwXTr.js} +2 -2
- package/dist/chunks/{rewardedUnlock-CGhQyWOk.js.map → rewardedUnlock-DUqYwXTr.js.map} +1 -1
- package/dist/chunks/segments-Ds-c1b5e.js +66 -0
- package/dist/chunks/segments-Ds-c1b5e.js.map +1 -0
- package/dist/chunks/{skipSegments-BbWzPpXz.js → skipSegments-ByNoF1qZ.js} +2 -2
- package/dist/chunks/{skipSegments-BbWzPpXz.js.map → skipSegments-ByNoF1qZ.js.map} +1 -1
- package/dist/chunks/{spriteThumbnails-B7oDZFTo.js → spriteThumbnails-Cr9UmkM9.js} +74 -51
- package/dist/chunks/spriteThumbnails-Cr9UmkM9.js.map +1 -0
- package/dist/chunks/{statsPanel-DSClIwA3.js → statsPanel-D0DtoFgS.js} +2 -2
- package/dist/chunks/statsPanel-D0DtoFgS.js.map +1 -0
- package/dist/chunks/{sticky-D_eLCNFk.js → sticky-BDStzjBM.js} +27 -26
- package/dist/chunks/sticky-BDStzjBM.js.map +1 -0
- package/dist/chunks/{story-BLBij82f.js → story-CodA2dfn.js} +2 -2
- package/dist/chunks/{story-BLBij82f.js.map → story-CodA2dfn.js.map} +1 -1
- package/dist/chunks/transcript-LG7E9UYE.js +186 -0
- package/dist/chunks/transcript-LG7E9UYE.js.map +1 -0
- package/dist/controls/ContextMenu.d.ts +1 -0
- package/dist/controls/ContextMenu.d.ts.map +1 -1
- package/dist/controls/ControlBar.d.ts +6 -0
- package/dist/controls/ControlBar.d.ts.map +1 -1
- package/dist/controls/SeekBar.d.ts +5 -2
- package/dist/controls/SeekBar.d.ts.map +1 -1
- package/dist/controls/SettingsMenu.d.ts +2 -1
- package/dist/controls/SettingsMenu.d.ts.map +1 -1
- package/dist/drm/NativeEme.d.ts +23 -0
- package/dist/drm/NativeEme.d.ts.map +1 -0
- package/dist/drm/keySystems.d.ts +18 -0
- package/dist/drm/keySystems.d.ts.map +1 -0
- package/dist/hls/SourceManager.d.ts +31 -5
- package/dist/hls/SourceManager.d.ts.map +1 -1
- package/dist/hls/dashEngine.d.ts +85 -0
- package/dist/hls/dashEngine.d.ts.map +1 -0
- package/dist/hls/sourceGroups.d.ts.map +1 -1
- package/dist/hope-player.js +1 -1
- package/dist/i18n/locales/en.d.ts.map +1 -1
- package/dist/i18n/locales/tr.d.ts.map +1 -1
- package/dist/i18n/types.d.ts +28 -0
- package/dist/i18n/types.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/keyboard/KeyboardController.d.ts +14 -0
- package/dist/keyboard/KeyboardController.d.ts.map +1 -1
- package/dist/plugin-api/PluginAds.d.ts +61 -0
- package/dist/plugin-api/PluginAds.d.ts.map +1 -0
- package/dist/plugin-api/PluginHost.d.ts +6 -0
- package/dist/plugin-api/PluginHost.d.ts.map +1 -1
- package/dist/plugin-api/types.d.ts +39 -0
- package/dist/plugin-api/types.d.ts.map +1 -1
- package/dist/plugins/accessibility/Accessibility.d.ts.map +1 -1
- package/dist/plugins/ad-triggers/AdTriggers.d.ts +5 -0
- package/dist/plugins/ad-triggers/AdTriggers.d.ts.map +1 -1
- package/dist/plugins/ads/AdsController.d.ts +2 -0
- package/dist/plugins/ads/AdsController.d.ts.map +1 -1
- package/dist/plugins/analytics/QoeTracker.d.ts +71 -0
- package/dist/plugins/analytics/QoeTracker.d.ts.map +1 -0
- package/dist/plugins/analytics/index.d.ts +6 -0
- package/dist/plugins/analytics/index.d.ts.map +1 -0
- package/dist/plugins/doc-pip/DocumentPip.d.ts +44 -0
- package/dist/plugins/doc-pip/DocumentPip.d.ts.map +1 -0
- package/dist/plugins/doc-pip/index.d.ts +5 -0
- package/dist/plugins/doc-pip/index.d.ts.map +1 -0
- package/dist/plugins/heatmap/Heatmap.d.ts +36 -0
- package/dist/plugins/heatmap/Heatmap.d.ts.map +1 -0
- package/dist/plugins/heatmap/index.d.ts +6 -0
- package/dist/plugins/heatmap/index.d.ts.map +1 -0
- package/dist/plugins/interactive/Interactive.d.ts +45 -0
- package/dist/plugins/interactive/Interactive.d.ts.map +1 -0
- package/dist/plugins/interactive/index.d.ts +6 -0
- package/dist/plugins/interactive/index.d.ts.map +1 -0
- package/dist/plugins/markers/MarkProgress.d.ts +3 -1
- package/dist/plugins/markers/MarkProgress.d.ts.map +1 -1
- package/dist/plugins/playlist/PlaylistRunner.d.ts +2 -0
- package/dist/plugins/playlist/PlaylistRunner.d.ts.map +1 -1
- package/dist/plugins/redirect-screen/RedirectScreen.d.ts +3 -1
- package/dist/plugins/redirect-screen/RedirectScreen.d.ts.map +1 -1
- package/dist/plugins/segments/Segments.d.ts +1 -0
- package/dist/plugins/segments/Segments.d.ts.map +1 -1
- package/dist/plugins/sprite-thumbnails/SpriteThumbnails.d.ts +9 -0
- package/dist/plugins/sprite-thumbnails/SpriteThumbnails.d.ts.map +1 -1
- package/dist/plugins/sticky/StickyManager.d.ts +2 -0
- package/dist/plugins/sticky/StickyManager.d.ts.map +1 -1
- package/dist/plugins/transcript/Transcript.d.ts +65 -0
- package/dist/plugins/transcript/Transcript.d.ts.map +1 -0
- package/dist/plugins/transcript/index.d.ts +6 -0
- package/dist/plugins/transcript/index.d.ts.map +1 -0
- package/dist/screens/ErrorScreen.d.ts +1 -1
- package/dist/screens/ErrorScreen.d.ts.map +1 -1
- package/dist/subtitles/attachTracks.d.ts +6 -0
- package/dist/subtitles/attachTracks.d.ts.map +1 -1
- package/dist/types/index.d.ts +320 -16
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/plugin-style.d.ts +5 -0
- package/dist/utils/plugin-style.d.ts.map +1 -0
- package/package.json +2 -1
- package/dist/chunks/adTriggers-DXmtF4t2.js +0 -410
- package/dist/chunks/adTriggers-DXmtF4t2.js.map +0 -1
- package/dist/chunks/ads-CdWbE9aD.js.map +0 -1
- package/dist/chunks/loopSection-CvF4l5uf.js.map +0 -1
- package/dist/chunks/markers-B04NMI79.js.map +0 -1
- package/dist/chunks/player-D7WQxMzr.js +0 -3894
- package/dist/chunks/player-D7WQxMzr.js.map +0 -1
- package/dist/chunks/playlist-C6Mh9BE8.js.map +0 -1
- package/dist/chunks/pluginHost-DjvLmMYZ.js +0 -376
- package/dist/chunks/pluginHost-DjvLmMYZ.js.map +0 -1
- package/dist/chunks/redirectScreen-5HAVRtxe.js +0 -208
- package/dist/chunks/redirectScreen-5HAVRtxe.js.map +0 -1
- package/dist/chunks/segments-gCPrWRig.js +0 -63
- package/dist/chunks/segments-gCPrWRig.js.map +0 -1
- package/dist/chunks/spriteThumbnails-B7oDZFTo.js.map +0 -1
- package/dist/chunks/statsPanel-DSClIwA3.js.map +0 -1
- package/dist/chunks/sticky-D_eLCNFk.js.map +0 -1
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
var w = Object.defineProperty;
|
|
2
|
+
var v = (s, t, e) => t in s ? w(s, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : s[t] = e;
|
|
3
|
+
var d = (s, t, e) => v(s, typeof t != "symbol" ? t + "" : t, e);
|
|
4
|
+
import { c as E } from "./player-D2_HRzot.js";
|
|
5
|
+
import { a as k, c as b } from "./plugin-style-CPJELe-i.js";
|
|
6
|
+
const C = ":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}";
|
|
7
|
+
function A() {
|
|
8
|
+
return window.documentPictureInPicture ?? null;
|
|
9
|
+
}
|
|
10
|
+
class P {
|
|
11
|
+
constructor(t) {
|
|
12
|
+
d(this, "win", null);
|
|
13
|
+
d(this, "placeholder", null);
|
|
14
|
+
d(this, "pipRoot", null);
|
|
15
|
+
d(this, "restore", () => {
|
|
16
|
+
const t = this.placeholder;
|
|
17
|
+
if (!t) return;
|
|
18
|
+
const { videoArea: e } = this.ctx;
|
|
19
|
+
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
|
+
});
|
|
21
|
+
this.ctx = t, k(t.rootEl, "doc-pip", C);
|
|
22
|
+
}
|
|
23
|
+
get active() {
|
|
24
|
+
return this.win !== null;
|
|
25
|
+
}
|
|
26
|
+
async open(t) {
|
|
27
|
+
const e = A();
|
|
28
|
+
if (!e || this.win) return !1;
|
|
29
|
+
const n = this.ctx.videoArea.getBoundingClientRect(), c = 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 * c), u = await e.requestWindow({ width: l, height: h });
|
|
30
|
+
return this.mount(u), !0;
|
|
31
|
+
}
|
|
32
|
+
close() {
|
|
33
|
+
var t;
|
|
34
|
+
(t = this.win) == null || t.close();
|
|
35
|
+
}
|
|
36
|
+
destroy() {
|
|
37
|
+
if (this.win) {
|
|
38
|
+
const t = this.win;
|
|
39
|
+
this.restore(), t.close();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
mount(t) {
|
|
43
|
+
const e = t.document, { hostEl: n, videoArea: c, rootEl: l } = this.ctx;
|
|
44
|
+
e.title = document.title;
|
|
45
|
+
const h = e.createElement("style");
|
|
46
|
+
h.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}", e.head.appendChild(h);
|
|
47
|
+
const u = document.getElementById("hope-player-icon-font");
|
|
48
|
+
u && e.head.appendChild(u.cloneNode(!0));
|
|
49
|
+
const a = e.createElement("div");
|
|
50
|
+
a.className = "hp-docpip";
|
|
51
|
+
for (const { name: o, value: i } of Array.from(n.attributes)) o.startsWith("data-") && a.setAttribute(o, i);
|
|
52
|
+
const f = getComputedStyle(n);
|
|
53
|
+
for (let o = 0; o < f.length; o++) {
|
|
54
|
+
const i = f[o];
|
|
55
|
+
i.startsWith("--hp-") && a.style.setProperty(i, f.getPropertyValue(i));
|
|
56
|
+
}
|
|
57
|
+
a.style.fontFamily = f.fontFamily;
|
|
58
|
+
const m = a.attachShadow({ mode: "open" }), y = e.createElement("style");
|
|
59
|
+
y.textContent = this.ctx.css;
|
|
60
|
+
const x = e.createElement("div");
|
|
61
|
+
x.className = "hp-root", m.append(y, x), b(n.shadowRoot, m), this.pipRoot = m, e.body.appendChild(a);
|
|
62
|
+
const r = document.createElement("div");
|
|
63
|
+
r.className = "hp-docpip-placeholder", r.setAttribute("part", "pip-placeholder");
|
|
64
|
+
const g = document.createElement("span");
|
|
65
|
+
g.textContent = this.ctx.i18n.pipPlaying;
|
|
66
|
+
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()), r.append(g, p), r.style.aspectRatio = `${Math.max(1, c.offsetWidth)} / ${Math.max(1, c.offsetHeight)}`, l.insertBefore(r, c), x.appendChild(c), c.setAttribute("data-docpip", ""), this.placeholder = r, this.win = t, e.addEventListener("keydown", (o) => {
|
|
68
|
+
if (o.defaultPrevented) return;
|
|
69
|
+
const i = o.composedPath()[0];
|
|
70
|
+
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
|
+
}), t.addEventListener("pagehide", this.restore, { once: !0 }), this.ctx.onChange(!0, t);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function W(s) {
|
|
75
|
+
return new P(s);
|
|
76
|
+
}
|
|
77
|
+
export {
|
|
78
|
+
P as DocumentPip,
|
|
79
|
+
A as documentPipApi,
|
|
80
|
+
W as installDocumentPip
|
|
81
|
+
};
|
|
82
|
+
//# sourceMappingURL=docPip-wybMVP1H.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docPip-wybMVP1H.js","sources":["../../src/plugins/doc-pip/DocumentPip.ts","../../src/plugins/doc-pip/index.ts"],"sourcesContent":["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 { DocumentPip, documentPipApi, type DocumentPipContext } from './DocumentPip';\n\nexport function installDocumentPip(ctx: DocumentPipContext): DocumentPip {\n return new DocumentPip(ctx);\n}\n\nexport { DocumentPip, documentPipApi };\nexport type { DocumentPipContext };\n"],"names":["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","installDocumentPip"],"mappings":"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"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
var b = Object.defineProperty;
|
|
2
|
+
var E = (s, t, e) => t in s ? b(s, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : s[t] = e;
|
|
3
|
+
var r = (s, t, e) => E(s, typeof t != "symbol" ? t + "" : t, e);
|
|
4
|
+
import { a as g } from "./plugin-style-CPJELe-i.js";
|
|
5
|
+
const L = ".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-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;
|
|
6
|
+
function w(s) {
|
|
7
|
+
const t = s.map((a) => Number.isFinite(a) && a > 0 ? a : 0), e = Math.max(0, ...t);
|
|
8
|
+
return e > 0 ? t.map((a) => a / e) : t;
|
|
9
|
+
}
|
|
10
|
+
function A(s) {
|
|
11
|
+
const t = s.length;
|
|
12
|
+
if (!t) return "";
|
|
13
|
+
const e = s.map((i, o) => [(o + 0.5) / t * d, p - i * p * 0.92]);
|
|
14
|
+
e.unshift([0, e[0][1]]), e.push([d, e[e.length - 1][1]]);
|
|
15
|
+
let a = `M0 ${p}L${e[0][0]} ${e[0][1].toFixed(1)}`;
|
|
16
|
+
for (let i = 0; i < e.length - 1; i++) {
|
|
17
|
+
const o = e[i - 1] ?? e[i], n = e[i], h = e[i + 1], l = e[i + 2] ?? h, u = Math.min(p, Math.max(0, n[1] + (h[1] - o[1]) / 6)), v = Math.min(p, Math.max(0, h[1] - (l[1] - n[1]) / 6)), f = n[0] + (h[0] - o[0]) / 6, y = h[0] - (l[0] - n[0]) / 6;
|
|
18
|
+
a += `C${f.toFixed(1)} ${u.toFixed(1)} ${y.toFixed(1)} ${v.toFixed(1)} ${h[0].toFixed(1)} ${h[1].toFixed(1)}`;
|
|
19
|
+
}
|
|
20
|
+
return `${a}L${d} ${p}Z`;
|
|
21
|
+
}
|
|
22
|
+
function c(s) {
|
|
23
|
+
const t = document.createElement("div");
|
|
24
|
+
t.className = s;
|
|
25
|
+
const e = document.createElementNS(m, "svg");
|
|
26
|
+
e.setAttribute("viewBox", `0 0 ${d} ${p}`), e.setAttribute("preserveAspectRatio", "none"), e.setAttribute("aria-hidden", "true");
|
|
27
|
+
const a = document.createElementNS(m, "path");
|
|
28
|
+
return e.appendChild(a), t.appendChild(e), { el: t, path: a };
|
|
29
|
+
}
|
|
30
|
+
class x {
|
|
31
|
+
constructor(t, e) {
|
|
32
|
+
r(this, "el");
|
|
33
|
+
r(this, "base");
|
|
34
|
+
r(this, "played");
|
|
35
|
+
r(this, "destroyed", !1);
|
|
36
|
+
r(this, "rafId", null);
|
|
37
|
+
r(this, "startLoop", () => {
|
|
38
|
+
if (this.rafId !== null) return;
|
|
39
|
+
const t = () => {
|
|
40
|
+
this.onTime(), this.rafId = requestAnimationFrame(t);
|
|
41
|
+
};
|
|
42
|
+
this.rafId = requestAnimationFrame(t);
|
|
43
|
+
});
|
|
44
|
+
r(this, "stopLoop", () => {
|
|
45
|
+
this.rafId !== null && cancelAnimationFrame(this.rafId), this.rafId = null, this.onTime();
|
|
46
|
+
});
|
|
47
|
+
r(this, "onDuration", () => {
|
|
48
|
+
const t = this.ctx.videoEl.duration;
|
|
49
|
+
this.el.hidden = !Number.isFinite(t) || t <= 0 || this.el.hasAttribute("data-empty") || !this.base.getAttribute("d"), this.onTime();
|
|
50
|
+
});
|
|
51
|
+
r(this, "onTime", () => {
|
|
52
|
+
const t = this.ctx.videoEl, e = Number.isFinite(t.duration) && t.duration > 0 ? Math.min(1, Math.max(0, t.currentTime / t.duration)) : 0;
|
|
53
|
+
this.el.hidden || this.el.style.setProperty("--hp-heatmap-p", `${(e * 100).toFixed(3)}%`);
|
|
54
|
+
});
|
|
55
|
+
var n;
|
|
56
|
+
this.ctx = t, this.options = e, g(t.seekBar.el, "heatmap", L);
|
|
57
|
+
const a = document.createElement("div");
|
|
58
|
+
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`);
|
|
59
|
+
const i = c("hp-heatmap-base"), o = c("hp-heatmap-played");
|
|
60
|
+
a.append(i.el, o.el), this.el = a, this.base = i.path, this.played = o.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), (n = e.data) != null && n.length ? this.setData(e.data) : e.src && this.fetchData(e.src);
|
|
61
|
+
}
|
|
62
|
+
/** Yeni değerler (ör. sunucudan güncel istatistik). */
|
|
63
|
+
setData(t) {
|
|
64
|
+
const e = A(w(t));
|
|
65
|
+
this.base.setAttribute("d", e), this.played.setAttribute("d", e), this.el.toggleAttribute("data-empty", !e), this.onDuration();
|
|
66
|
+
}
|
|
67
|
+
destroy() {
|
|
68
|
+
this.destroyed = !0;
|
|
69
|
+
const t = this.ctx.videoEl;
|
|
70
|
+
t.removeEventListener("timeupdate", this.onTime), t.removeEventListener("seeking", this.onTime), t.removeEventListener("durationchange", this.onDuration), t.removeEventListener("loadedmetadata", this.onDuration), t.removeEventListener("play", this.startLoop), t.removeEventListener("pause", this.stopLoop), t.removeEventListener("ended", this.stopLoop), this.stopLoop(), this.el.remove();
|
|
71
|
+
}
|
|
72
|
+
async fetchData(t) {
|
|
73
|
+
var e, a;
|
|
74
|
+
try {
|
|
75
|
+
const i = await fetch(t);
|
|
76
|
+
if (!i.ok) throw new Error(`HTTP ${i.status}`);
|
|
77
|
+
const o = await i.json(), n = Array.isArray(o) ? o : o == null ? void 0 : o.data;
|
|
78
|
+
if (!Array.isArray(n)) throw new Error("number[] bekleniyordu");
|
|
79
|
+
this.destroyed || this.setData(n.map(Number));
|
|
80
|
+
} catch (i) {
|
|
81
|
+
(a = (e = this.ctx).log) == null || a.call(e, { message: `Heatmap data could not be loaded: ${String(i)}`, details: { src: t } });
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function D(s, t) {
|
|
86
|
+
return new x(s, t);
|
|
87
|
+
}
|
|
88
|
+
export {
|
|
89
|
+
x as Heatmap,
|
|
90
|
+
D as installHeatmap
|
|
91
|
+
};
|
|
92
|
+
//# sourceMappingURL=heatmap-Bb7neaYU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heatmap-Bb7neaYU.js","sources":["../../src/plugins/heatmap/Heatmap.ts","../../src/plugins/heatmap/index.ts"],"sourcesContent":["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 };\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\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 d = heatmapPath(normalize(values));\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 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 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 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 { Heatmap, type HeatmapPlayerContext } from './Heatmap';\nimport type { HeatmapOptions } from '../../types';\n\nexport function installHeatmap(ctx: HeatmapPlayerContext, options: HeatmapOptions): Heatmap {\n return new Heatmap(ctx, options);\n}\n\nexport { Heatmap };\nexport type { HeatmapPlayerContext };\n"],"names":["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","src","res","json","err","_b","installHeatmap"],"mappings":";;;;0uBAUMA,IAAS,8BACTC,IAAI,KACJC,IAAI;AAGV,SAASC,EAAUC,GAA4B;AAC3C,QAAMC,IAAQD,EAAO,IAAI,CAACE,MAAO,OAAO,SAASA,CAAC,KAAKA,IAAI,IAAIA,IAAI,CAAE,GAC/DC,IAAM,KAAK,IAAI,GAAG,GAAGF,CAAK;AAChC,SAAOE,IAAM,IAAIF,EAAM,IAAI,CAACC,MAAMA,IAAIC,CAAG,IAAIF;AACjD;AAGO,SAASG,EAAYJ,GAA0B;AAClD,QAAMK,IAAIL,EAAO;AACjB,MAAI,CAACK,EAAG,QAAO;AACf,QAAMC,IAA0BN,EAAO,IAAI,CAACE,GAAGK,MAAM,EAAGA,IAAI,OAAOF,IAAKR,GAAGC,IAAII,IAAIJ,IAAI,IAAI,CAAC;AAC5F,EAAAQ,EAAI,QAAQ,CAAC,GAAGA,EAAI,CAAC,EAAG,CAAC,CAAC,CAAC,GAC3BA,EAAI,KAAK,CAACT,GAAGS,EAAIA,EAAI,SAAS,CAAC,EAAG,CAAC,CAAC,CAAC;AACrC,MAAIE,IAAI,MAAMV,CAAC,IAAIQ,EAAI,CAAC,EAAG,CAAC,CAAC,IAAIA,EAAI,CAAC,EAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;AACtD,WAAS,IAAI,GAAG,IAAIA,EAAI,SAAS,GAAG,KAAK;AACrC,UAAMG,IAAKH,EAAI,IAAI,CAAC,KAAKA,EAAI,CAAC,GACxBI,IAAKJ,EAAI,CAAC,GACVK,IAAKL,EAAI,IAAI,CAAC,GACdM,IAAKN,EAAI,IAAI,CAAC,KAAKK,GAEnBE,IAAM,KAAK,IAAIf,GAAG,KAAK,IAAI,GAAGY,EAAG,CAAC,KAAKC,EAAG,CAAC,IAAIF,EAAG,CAAC,KAAK,CAAC,CAAC,GAC1DK,IAAM,KAAK,IAAIhB,GAAG,KAAK,IAAI,GAAGa,EAAG,CAAC,KAAKC,EAAG,CAAC,IAAIF,EAAG,CAAC,KAAK,CAAC,CAAC,GAC1DK,IAAML,EAAG,CAAC,KAAKC,EAAG,CAAC,IAAIF,EAAG,CAAC,KAAK,GAChCO,IAAML,EAAG,CAAC,KAAKC,EAAG,CAAC,IAAIF,EAAG,CAAC,KAAK;AACtC,IAAAF,KAAK,IAAIO,EAAI,QAAQ,CAAC,CAAC,IAAIF,EAAI,QAAQ,CAAC,CAAC,IAAIG,EAAI,QAAQ,CAAC,CAAC,IAAIF,EAAI,QAAQ,CAAC,CAAC,IAAIH,EAAG,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAIA,EAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;AAAA,EACzH;AACA,SAAO,GAAGH,CAAC,IAAIX,CAAC,IAAIC,CAAC;AACzB;AAEA,SAASmB,EAAMC,GAAiE;AAC5E,QAAMC,IAAK,SAAS,cAAc,KAAK;AACvC,EAAAA,EAAG,YAAYD;AACf,QAAME,IAAM,SAAS,gBAAgBxB,GAAQ,KAAK;AAClD,EAAAwB,EAAI,aAAa,WAAW,OAAOvB,CAAC,IAAIC,CAAC,EAAE,GAC3CsB,EAAI,aAAa,uBAAuB,MAAM,GAC9CA,EAAI,aAAa,eAAe,MAAM;AACtC,QAAMC,IAAO,SAAS,gBAAgBzB,GAAQ,MAAM;AACpD,SAAAwB,EAAI,YAAYC,CAAI,GACpBF,EAAG,YAAYC,CAAG,GACX,EAAE,IAAAD,GAAI,MAAAE,EAAA;AACjB;AAMO,MAAMC,EAAQ;AAAA,EAMjB,YACqBC,GACAC,GACnB;AARe,IAAAC,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACT,IAAAA,EAAA,mBAAY;AA2DZ,IAAAA,EAAA,eAAuB;AAEd,IAAAA,EAAA,mBAAY,MAAY;AACrC,UAAI,KAAK,UAAU,KAAM;AACzB,YAAMC,IAAO,MAAY;AACrB,aAAK,OAAA,GACL,KAAK,QAAQ,sBAAsBA,CAAI;AAAA,MAC3C;AACA,WAAK,QAAQ,sBAAsBA,CAAI;AAAA,IAC3C;AAEiB,IAAAD,EAAA,kBAAW,MAAY;AACpC,MAAI,KAAK,UAAU,QAAM,qBAAqB,KAAK,KAAK,GACxD,KAAK,QAAQ,MACb,KAAK,OAAA;AAAA,IACT;AAeiB,IAAAA,EAAA,oBAAa,MAAY;AACtC,YAAMjB,IAAI,KAAK,IAAI,QAAQ;AAC3B,WAAK,GAAG,SAAS,CAAC,OAAO,SAASA,CAAC,KAAKA,KAAK,KAAK,KAAK,GAAG,aAAa,YAAY,KAAK,CAAC,KAAK,KAAK,aAAa,GAAG,GACnH,KAAK,OAAA;AAAA,IACT;AAEiB,IAAAiB,EAAA,gBAAS,MAAY;AAClC,YAAMvB,IAAI,KAAK,IAAI,SACbyB,IAAQ,OAAO,SAASzB,EAAE,QAAQ,KAAKA,EAAE,WAAW,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAGA,EAAE,cAAcA,EAAE,QAAQ,CAAC,IAAI;AAErH,MAAI,KAAK,GAAG,UACZ,KAAK,GAAG,MAAM,YAAY,kBAAkB,IAAIyB,IAAQ,KAAK,QAAQ,CAAC,CAAC,GAAG;AAAA,IAC9E;;AAlGqB,SAAA,MAAAJ,GACA,KAAA,UAAAC,GAEjBI,EAAWL,EAAI,QAAQ,IAAI,WAAWM,CAAG;AACzC,UAAMV,IAAK,SAAS,cAAc,KAAK;AACvC,IAAAA,EAAG,YAAY,cACfA,EAAG,aAAa,QAAQ,SAAS,GACjCA,EAAG,aAAa,eAAe,MAAM,GACrCA,EAAG,aAAa,aAAaK,EAAQ,SAAS,WAAW,WAAW,OAAO,GACvEA,EAAQ,UAAQL,EAAG,MAAM,YAAY,kBAAkB,GAAG,KAAK,IAAI,GAAGK,EAAQ,MAAM,CAAC,IAAI;AAC7F,UAAMM,IAAOb,EAAM,iBAAiB,GAC9Bc,IAASd,EAAM,mBAAmB;AACxC,IAAAE,EAAG,OAAOW,EAAK,IAAIC,EAAO,EAAE,GAC5B,KAAK,KAAKZ,GACV,KAAK,OAAOW,EAAK,MACjB,KAAK,SAASC,EAAO,MACrBZ,EAAG,SAAS,IACZI,EAAI,QAAQ,GAAG,QAAQJ,CAAE,GAEzBI,EAAI,QAAQ,iBAAiB,cAAc,KAAK,MAAM,GACtDA,EAAI,QAAQ,iBAAiB,WAAW,KAAK,MAAM,GAEnDA,EAAI,QAAQ,iBAAiB,QAAQ,KAAK,SAAS,GACnDA,EAAI,QAAQ,iBAAiB,SAAS,KAAK,QAAQ,GACnDA,EAAI,QAAQ,iBAAiB,SAAS,KAAK,QAAQ,GAC9CA,EAAI,QAAQ,eAAa,UAAA,GAC9BA,EAAI,QAAQ,iBAAiB,kBAAkB,KAAK,UAAU,GAC9DA,EAAI,QAAQ,iBAAiB,kBAAkB,KAAK,UAAU,IAE1DS,IAAAR,EAAQ,SAAR,QAAAQ,EAAc,SAAQ,KAAK,QAAQR,EAAQ,IAAI,IAC1CA,EAAQ,OAAU,KAAK,UAAUA,EAAQ,GAAG;AAAA,EACzD;AAAA;AAAA,EAGA,QAAQxB,GAAwB;AAC5B,UAAMQ,IAAIJ,EAAYL,EAAUC,CAAM,CAAC;AACvC,SAAK,KAAK,aAAa,KAAKQ,CAAC,GAC7B,KAAK,OAAO,aAAa,KAAKA,CAAC,GAC/B,KAAK,GAAG,gBAAgB,cAAc,CAACA,CAAC,GACxC,KAAK,WAAA;AAAA,EACT;AAAA,EAEA,UAAgB;AACZ,SAAK,YAAY;AACjB,UAAMN,IAAI,KAAK,IAAI;AACnB,IAAAA,EAAE,oBAAoB,cAAc,KAAK,MAAM,GAC/CA,EAAE,oBAAoB,WAAW,KAAK,MAAM,GAC5CA,EAAE,oBAAoB,kBAAkB,KAAK,UAAU,GACvDA,EAAE,oBAAoB,kBAAkB,KAAK,UAAU,GACvDA,EAAE,oBAAoB,QAAQ,KAAK,SAAS,GAC5CA,EAAE,oBAAoB,SAAS,KAAK,QAAQ,GAC5CA,EAAE,oBAAoB,SAAS,KAAK,QAAQ,GAC5C,KAAK,SAAA,GACL,KAAK,GAAG,OAAA;AAAA,EACZ;AAAA,EAmBA,MAAc,UAAU+B,GAA4B;;AAChD,QAAI;AACA,YAAMC,IAAM,MAAM,MAAMD,CAAG;AAC3B,UAAI,CAACC,EAAI,GAAI,OAAM,IAAI,MAAM,QAAQA,EAAI,MAAM,EAAE;AACjD,YAAMC,IAAgB,MAAMD,EAAI,KAAA,GAC1BlC,IAAS,MAAM,QAAQmC,CAAI,IAAIA,IAAQA,KAAA,gBAAAA,EAA6B;AAC1E,UAAI,CAAC,MAAM,QAAQnC,CAAM,EAAG,OAAM,IAAI,MAAM,uBAAuB;AACnE,MAAK,KAAK,aAAW,KAAK,QAAQA,EAAO,IAAI,MAAM,CAAC;AAAA,IACxD,SAASoC,GAAK;AACV,OAAAC,KAAAL,IAAA,KAAK,KAAI,QAAT,QAAAK,EAAA,KAAAL,GAAe,EAAE,SAAS,qCAAqC,OAAOI,CAAG,CAAC,IAAI,SAAS,EAAE,KAAAH,EAAA;IAC7F;AAAA,EACJ;AAeJ;ACpKO,SAASK,EAAef,GAA2BC,GAAkC;AACxF,SAAO,IAAIF,EAAQC,GAAKC,CAAO;AACnC;"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
var m = Object.defineProperty;
|
|
2
2
|
var v = (n, t, e) => t in n ? m(n, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : n[t] = e;
|
|
3
3
|
var s = (n, t, e) => v(n, typeof t != "symbol" ? t + "" : t, e);
|
|
4
|
-
import { f as E } from "./player-
|
|
4
|
+
import { f as E } from "./player-D2_HRzot.js";
|
|
5
5
|
import { s as p } from "./seekWhenReady-Clzne3-S.js";
|
|
6
6
|
const d = "hp-history-positions", c = "hp-history-volume", y = 10, f = 15, L = 50, k = 30, T = 5e3, N = 6e3;
|
|
7
7
|
class x {
|
|
@@ -141,4 +141,4 @@ export {
|
|
|
141
141
|
x as PlaybackHistory,
|
|
142
142
|
w as installHistory
|
|
143
143
|
};
|
|
144
|
-
//# sourceMappingURL=history-
|
|
144
|
+
//# sourceMappingURL=history-CwqLXiZi.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"history-DAbqEhNB.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-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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"}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
var A = Object.defineProperty;
|
|
2
|
+
var z = (p, t, i) => t in p ? A(p, t, { enumerable: !0, configurable: !0, writable: !0, value: i }) : p[t] = i;
|
|
3
|
+
var d = (p, t, i) => z(p, typeof t != "symbol" ? t + "" : t, i);
|
|
4
|
+
import { c as L } from "./player-D2_HRzot.js";
|
|
5
|
+
import { a as S } from "./plugin-style-CPJELe-i.js";
|
|
6
|
+
const q = '.hp-ia{position:absolute;z-index:24;width:min(320px,calc(100% - 24px));max-height:calc(100% - 100px);overflow-y:auto;box-sizing:border-box;padding:12px;border:1px solid rgba(255,255,255,.12);border-radius:12px;background:#0e0e12e0;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);color:#fff;box-shadow:0 16px 36px -14px #000000d9;font:13px/1.4 system-ui,-apple-system,sans-serif;animation:hp-redirect-in .3s cubic-bezier(.2,.8,.2,1)}.hp-ia[data-position=top-right]{top:12px;right:12px}.hp-ia[data-position=top-left]{top:12px;left:12px}.hp-ia[data-position=bottom-right]{right:12px;bottom:76px}.hp-ia[data-position=bottom-left]{left:12px;bottom:76px}.hp-ia[data-position=center]{top:50%;left:50%;transform:translate(-50%,-50%);animation:hp-redirect-fade .25s ease-out}.video-area[data-chrome-hidden] .hp-ia[data-position^=bottom]{bottom:12px}.video-area[data-compact] .hp-ia{width:calc(100% - 16px);max-height:calc(100% - 64px);padding:10px}.video-area[data-compact] .hp-ia[data-position$=right],.video-area[data-compact] .hp-ia[data-position$=left]{left:8px;right:8px}.video-area[data-compact] .hp-ia[data-position^=top]{top:8px}.video-area[data-compact] .hp-ia[data-position^=bottom]{bottom:56px}.hp-ia-close{position:absolute;top:8px;right:8px;display:grid;place-items:center;width:24px;height:24px;padding:0;border:0;border-radius:999px;background:#ffffff1f;color:#fff;font-size:12px;cursor:pointer}.hp-ia-close:hover{background:#ffffff3d}.hp-ia-label{display:block;margin-bottom:4px;color:var(--hp-color-accent, #fff);font:700 10px/1.2 system-ui,-apple-system,sans-serif;letter-spacing:.1em;text-transform:uppercase}.hp-ia-question{margin:0 28px 10px 0;font-weight:600;font-size:14px}.hp-ia-choices{display:grid;gap:6px}.hp-ia-choice{position:relative;display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;overflow:hidden;padding:8px 10px;border:1px solid rgba(255,255,255,.16);border-radius:8px;background:#ffffff0f;color:#fff;font:inherit;text-align:start;cursor:pointer;transition:background .15s,border-color .15s}.hp-ia-choice:hover:not(:disabled){background:#ffffff24}.hp-ia-choice:disabled{cursor:default}.hp-ia-choice[data-result]:before{content:"";position:absolute;inset:0 auto 0 0;width:var(--hp-ia-pct, 0%);background:#ffffff24;transition:width .6s cubic-bezier(.2,.8,.2,1)}.hp-ia-choice>span{position:relative}.hp-ia-choice[data-picked]{border-color:var(--hp-color-accent, #fff)}.hp-ia-choice[data-correct]{border-color:#2fbf71;background:#2fbf7138}.hp-ia-choice[data-wrong]{border-color:#e5484d;background:#e5484d38}.hp-ia-pct{flex:none;font-weight:600;font-variant-numeric:tabular-nums}.hp-ia-status{margin:8px 0 0;font-size:12.5px;opacity:.85}.hp-ia-status:empty{display:none}.hp-ia[data-type=product],.hp-ia[data-type=link]{padding:0}.hp-ia-card{display:flex;gap:10px;padding:8px 34px 8px 8px;color:#fff;text-decoration:none}.hp-ia-image{flex:none;width:72px;height:72px;border-radius:8px;object-fit:cover;background:#111}.hp-ia-body{display:flex;flex-direction:column;gap:2px;min-width:0}.hp-ia-body .hp-ia-label{margin-bottom:0}.hp-ia-title{display:-webkit-box;overflow:hidden;-webkit-line-clamp:2;-webkit-box-orient:vertical;font-weight:600}.hp-ia-sub{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;opacity:.7;font-size:12px}.hp-ia-price{display:flex;gap:6px;align-items:baseline}.hp-ia-price s{opacity:.55;font-size:12px}.hp-ia-cta{align-self:flex-start;margin-top:4px;padding:5px 12px;border-radius:999px;background:var(--hp-color-accent, #fff);color:var(--hp-color-on-accent, #000);font-weight:600;font-size:12px}.hp-ia-card:hover .hp-ia-cta{filter:brightness(.92)}.hp-ia-choice:focus-visible,.hp-ia-close:focus-visible,.hp-ia-card:focus-visible{outline:2px solid var(--hp-color-accent, #fff);outline-offset:2px}.hp-seek-marker.hp-ia-marker{background:var(--hp-ia-marker-color, #f5c518)}@media(prefers-reduced-motion:reduce){.hp-ia,.hp-ia-choice[data-result]:before{animation:none;transition:none}}', E = "hp-interactive:", C = 1.5;
|
|
7
|
+
function T(p, t) {
|
|
8
|
+
return typeof p == "string" ? { id: String(t), text: p } : { id: p.id ?? String(t), text: p.text };
|
|
9
|
+
}
|
|
10
|
+
function n(p, t, i) {
|
|
11
|
+
const e = document.createElement(p);
|
|
12
|
+
return e.className = t, i !== void 0 && (e.textContent = i), e;
|
|
13
|
+
}
|
|
14
|
+
class $ {
|
|
15
|
+
constructor(t, i) {
|
|
16
|
+
d(this, "entries", []);
|
|
17
|
+
d(this, "active", null);
|
|
18
|
+
d(this, "markers", []);
|
|
19
|
+
d(this, "closeTimer", null);
|
|
20
|
+
d(this, "drawMarkers", () => {
|
|
21
|
+
for (const i of this.markers) i.remove();
|
|
22
|
+
this.markers = [];
|
|
23
|
+
const t = this.ctx.videoEl.duration;
|
|
24
|
+
if (!(this.options.markers === !1 || !Number.isFinite(t) || t <= 0))
|
|
25
|
+
for (const i of this.entries) {
|
|
26
|
+
if (i.item.time < 0 || i.item.time > t) continue;
|
|
27
|
+
const e = this.ctx.addSeekBarMarker(i.item.time / t, "hp-ia-marker", "question" in i.item ? i.item.question : i.item.title), o = i.item.markerColor ?? this.options.markerColor;
|
|
28
|
+
o && (e.style.backgroundColor = o), this.markers.push(e);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
/** Yeni kaynak: oturum durumu sıfırlanır. */
|
|
32
|
+
d(this, "onEmptied", () => {
|
|
33
|
+
this.hide(null);
|
|
34
|
+
for (const t of this.entries) t.done = !1;
|
|
35
|
+
});
|
|
36
|
+
d(this, "onAdStart", () => {
|
|
37
|
+
this.active && !this.active.answered && this.hide("timeout");
|
|
38
|
+
});
|
|
39
|
+
/** Geri sarınca sonraki öğeler yeniden gösterilebilir (cevaplanmış anket / quiz yine sorulmaz). */
|
|
40
|
+
d(this, "onSeeked", () => {
|
|
41
|
+
var i;
|
|
42
|
+
const t = this.ctx.videoEl.currentTime;
|
|
43
|
+
for (const e of this.entries) e.item.time > t + 0.1 && e !== ((i = this.active) == null ? void 0 : i.entry) && (e.done = !1);
|
|
44
|
+
this.onTime();
|
|
45
|
+
});
|
|
46
|
+
d(this, "onTime", () => {
|
|
47
|
+
const t = this.ctx.videoEl.currentTime, i = this.active;
|
|
48
|
+
if (i)
|
|
49
|
+
if (t < i.entry.item.time - 0.5) this.hide("seek");
|
|
50
|
+
else if (!i.answered && t >= i.shownAt + this.duration(i.entry.item)) this.hide("timeout");
|
|
51
|
+
else if (i.answered && this.entries.some((e) => !e.done && t >= e.item.time && t - e.item.time <= C)) this.hide(null);
|
|
52
|
+
else return;
|
|
53
|
+
if (!this.ctx.isAdActive()) {
|
|
54
|
+
for (const e of this.entries)
|
|
55
|
+
if (!(e.done || t < e.item.time) && (e.done = !0, !(t - e.item.time > C || this.remembered(e)))) {
|
|
56
|
+
this.show(e, t);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
this.ctx = t, this.options = i, S(t.overlayEl, "interactive", q), this.entries = i.items.map((o, s) => ({ item: o, id: o.id ?? `i${s}`, done: !1 }));
|
|
62
|
+
const e = t.videoEl;
|
|
63
|
+
e.addEventListener("timeupdate", this.onTime), e.addEventListener("seeked", this.onSeeked), e.addEventListener("loadedmetadata", this.drawMarkers), e.addEventListener("emptied", this.onEmptied), t.hostEl.addEventListener("hp:adstart", this.onAdStart), e.readyState >= 1 && this.drawMarkers();
|
|
64
|
+
}
|
|
65
|
+
/** Yalnızca fonksiyonlar değişti (ör. React'te her render'da yeni onAnswer). */
|
|
66
|
+
setOptions(t) {
|
|
67
|
+
this.options = t;
|
|
68
|
+
}
|
|
69
|
+
refreshLabels() {
|
|
70
|
+
var t, i;
|
|
71
|
+
(i = (t = this.active) == null ? void 0 : t.el.querySelector(".hp-ia-close")) == null || i.setAttribute("aria-label", this.ctx.i18n.interactiveClose);
|
|
72
|
+
}
|
|
73
|
+
destroy() {
|
|
74
|
+
const t = this.ctx.videoEl;
|
|
75
|
+
t.removeEventListener("timeupdate", this.onTime), t.removeEventListener("seeked", this.onSeeked), t.removeEventListener("loadedmetadata", this.drawMarkers), t.removeEventListener("emptied", this.onEmptied), this.ctx.hostEl.removeEventListener("hp:adstart", this.onAdStart), this.hide(null);
|
|
76
|
+
for (const i of this.markers) i.remove();
|
|
77
|
+
this.markers = [];
|
|
78
|
+
}
|
|
79
|
+
emit(t, i, e = {}) {
|
|
80
|
+
return this.ctx.hostEl.dispatchEvent(
|
|
81
|
+
new CustomEvent("hp:interactive", { detail: { state: t, id: i.id, type: i.item.type, ...e }, cancelable: t === "click" })
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
remembered(t) {
|
|
85
|
+
if (this.options.rememberAnswers === !1 || t.item.type !== "poll" && t.item.type !== "quiz") return !1;
|
|
86
|
+
try {
|
|
87
|
+
return localStorage.getItem(E + t.id) !== null;
|
|
88
|
+
} catch {
|
|
89
|
+
return !1;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
remember(t, i) {
|
|
93
|
+
if (this.options.rememberAnswers !== !1)
|
|
94
|
+
try {
|
|
95
|
+
localStorage.setItem(E + t.id, String(i));
|
|
96
|
+
} catch {
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
duration(t) {
|
|
100
|
+
return t.duration ?? (t.type === "poll" || t.type === "quiz" ? 15 : 8);
|
|
101
|
+
}
|
|
102
|
+
show(t, i) {
|
|
103
|
+
const e = t.item, o = n("div", "hp-ia");
|
|
104
|
+
o.setAttribute("part", `interactive interactive-${e.type}`), o.setAttribute("data-type", e.type), o.setAttribute("data-position", e.position ?? (e.type === "poll" || e.type === "quiz" ? "top-right" : "bottom-right")), o.setAttribute("role", "group");
|
|
105
|
+
for (const a of ["pointerdown", "click", "dblclick"]) o.addEventListener(a, (f) => f.stopPropagation());
|
|
106
|
+
if (o.addEventListener("keydown", (a) => a.stopPropagation()), e.dismissible !== !1) {
|
|
107
|
+
const a = n("button", "hp-ia-close");
|
|
108
|
+
a.type = "button", a.setAttribute("aria-label", this.ctx.i18n.interactiveClose), a.appendChild(L("close")), a.addEventListener("click", () => this.hide("user")), o.appendChild(a);
|
|
109
|
+
}
|
|
110
|
+
e.type === "poll" || e.type === "quiz" ? this.buildQuestion(o, t) : this.buildCard(o, t, e), this.ctx.overlayEl.appendChild(o);
|
|
111
|
+
const s = this.ctx.videoEl, r = !!e.pause && !s.paused;
|
|
112
|
+
r && s.pause(), this.active = { entry: t, el: o, shownAt: i, pausedByUs: r, answered: !1 }, this.emit("shown", t);
|
|
113
|
+
}
|
|
114
|
+
buildQuestion(t, i) {
|
|
115
|
+
const e = i.item, o = this.ctx.i18n;
|
|
116
|
+
t.appendChild(n("span", "hp-ia-label", e.type === "poll" ? o.interactivePoll : o.interactiveQuiz));
|
|
117
|
+
const s = n("p", "hp-ia-question", e.question);
|
|
118
|
+
s.id = `hp-ia-q-${i.id}`, t.setAttribute("aria-labelledby", s.id), t.appendChild(s);
|
|
119
|
+
const r = n("div", "hp-ia-choices"), a = e.choices.map(T), f = a.map((v, u) => {
|
|
120
|
+
const c = n("button", "hp-ia-choice");
|
|
121
|
+
return c.type = "button", c.appendChild(n("span", "hp-ia-choice-text", v.text)), c.addEventListener("click", () => void this.answer(i, u, a[u].id, f)), r.appendChild(c), c;
|
|
122
|
+
});
|
|
123
|
+
t.appendChild(r);
|
|
124
|
+
const l = n("p", "hp-ia-status");
|
|
125
|
+
l.setAttribute("aria-live", "polite"), t.appendChild(l);
|
|
126
|
+
}
|
|
127
|
+
async answer(t, i, e, o) {
|
|
128
|
+
var v, u, c, g, y, k;
|
|
129
|
+
const s = this.active;
|
|
130
|
+
if (!s || s.entry !== t || s.answered) return;
|
|
131
|
+
s.answered = !0;
|
|
132
|
+
const r = t.item, a = r.type === "quiz" ? i === r.answer : void 0;
|
|
133
|
+
this.remember(t, i);
|
|
134
|
+
for (const m of o) m.disabled = !0;
|
|
135
|
+
(v = o[i]) == null || v.setAttribute("data-picked", "");
|
|
136
|
+
const f = s.el.querySelector(".hp-ia-status");
|
|
137
|
+
this.emit("answer", t, { choice: i, choiceId: e, ...a !== void 0 ? { correct: a } : {} });
|
|
138
|
+
let l;
|
|
139
|
+
try {
|
|
140
|
+
l = await ((c = (u = this.options).onAnswer) == null ? void 0 : c.call(u, { item: r, id: t.id, choice: i, choiceId: e, correct: a }));
|
|
141
|
+
} catch {
|
|
142
|
+
l = void 0;
|
|
143
|
+
}
|
|
144
|
+
if (((g = this.active) == null ? void 0 : g.entry) === t) {
|
|
145
|
+
if (r.type === "quiz")
|
|
146
|
+
(y = o[r.answer]) == null || y.setAttribute("data-correct", ""), a || (k = o[i]) == null || k.setAttribute("data-wrong", ""), f && (f.textContent = `${a ? this.ctx.i18n.interactiveCorrect : this.ctx.i18n.interactiveWrong}${r.explanation ? ` ${r.explanation}` : ""}`);
|
|
147
|
+
else {
|
|
148
|
+
const m = Array.isArray(l) ? l : r.results ? r.results.map((x, h) => x + (h === i ? 1 : 0)) : null;
|
|
149
|
+
if (m) {
|
|
150
|
+
const x = m.reduce((h, b) => h + (Number.isFinite(b) && b > 0 ? b : 0), 0) || 1;
|
|
151
|
+
o.forEach((h, b) => {
|
|
152
|
+
const w = Math.round((m[b] ?? 0) / x * 100);
|
|
153
|
+
h.style.setProperty("--hp-ia-pct", `${w}%`), h.setAttribute("data-result", ""), h.appendChild(n("span", "hp-ia-pct", this.ctx.i18n.interactiveVotes(w)));
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
this.closeTimer = setTimeout(() => this.hide(null), r.type === "quiz" ? 5e3 : 3500);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
buildCard(t, i, e) {
|
|
161
|
+
const o = this.ctx.i18n, s = n("a", "hp-ia-card");
|
|
162
|
+
if (s.href = e.url, e.newTab !== !1 && (s.target = "_blank", s.rel = "noopener"), e.image) {
|
|
163
|
+
const a = n("img", "hp-ia-image");
|
|
164
|
+
a.src = e.image, a.alt = "", a.decoding = "async", a.addEventListener("error", () => a.remove()), s.appendChild(a);
|
|
165
|
+
}
|
|
166
|
+
const r = n("span", "hp-ia-body");
|
|
167
|
+
if (e.sponsored && r.appendChild(n("span", "hp-ia-label", o.interactiveSponsored)), r.appendChild(n("span", "hp-ia-title", e.title)), e.subtitle && r.appendChild(n("span", "hp-ia-sub", e.subtitle)), e.price || e.oldPrice) {
|
|
168
|
+
const a = n("span", "hp-ia-price");
|
|
169
|
+
e.price && a.appendChild(n("strong", "", e.price)), e.oldPrice && a.appendChild(n("s", "", e.oldPrice)), r.appendChild(a);
|
|
170
|
+
}
|
|
171
|
+
r.appendChild(n("span", "hp-ia-cta", e.cta ?? (e.type === "product" ? o.interactiveBuy : o.interactiveGo))), s.appendChild(r), s.addEventListener("click", (a) => {
|
|
172
|
+
this.emit("click", i, { url: e.url }) || a.preventDefault();
|
|
173
|
+
}), t.setAttribute("aria-label", e.title), t.appendChild(s);
|
|
174
|
+
}
|
|
175
|
+
hide(t) {
|
|
176
|
+
this.closeTimer && clearTimeout(this.closeTimer), this.closeTimer = null;
|
|
177
|
+
const i = this.active;
|
|
178
|
+
i && (this.active = null, i.el.remove(), t && this.emit("dismiss", i.entry, { reason: t }), i.pausedByUs && t !== "seek" && this.ctx.videoEl.play().catch(() => {
|
|
179
|
+
}));
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
function I(p, t) {
|
|
183
|
+
return new $(p, t);
|
|
184
|
+
}
|
|
185
|
+
export {
|
|
186
|
+
$ as Interactive,
|
|
187
|
+
I as installInteractive
|
|
188
|
+
};
|
|
189
|
+
//# sourceMappingURL=interactive-CgltIneu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactive-CgltIneu.js","sources":["../../src/plugins/interactive/Interactive.ts","../../src/plugins/interactive/index.ts"],"sourcesContent":["import type { InteractiveCard, InteractiveChoice, InteractiveItem, InteractiveOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\nimport { createIcon } from '../../icons/Icon';\nimport { adoptStyle } from '../../utils/plugin-style';\nimport css from './interactive.css?inline';\n\nexport interface InteractivePlayerContext {\n hostEl: HTMLElement;\n videoEl: HTMLVideoElement;\n overlayEl: HTMLElement;\n i18n: HopeLocaleStrings;\n isAdActive(): boolean;\n addSeekBarMarker(ratio: number, extraClass?: string, label?: string): HTMLElement;\n}\n\ninterface Entry {\n item: InteractiveItem;\n id: string;\n /** Bu oturumda gösterildi (ileri geri sarınca tekrar sorulmaz). */\n done: boolean;\n}\n\nconst STORE = 'hp-interactive:';\n/** Bu kadar saniye geç kalınırsa (ileri sarma) öğe atlanır. */\nconst LATE = 1.5;\n\nfunction choiceOf(c: string | InteractiveChoice, i: number): { id: string; text: string } {\n return typeof c === 'string' ? { id: String(i), text: c } : { id: c.id ?? String(i), text: c.text };\n}\n\nfunction el<K extends keyof HTMLElementTagNameMap>(tag: K, className: string, text?: string): HTMLElementTagNameMap[K] {\n const e = document.createElement(tag);\n e.className = className;\n if (text !== undefined) e.textContent = text;\n return e;\n}\n\n/**\n * Etkileşimli içerik: belirli saniyelerde anket, quiz, ürün ya da bağlantı kartı. Zamanlama videonun zamanıyla\n * işler (duraklatınca süre durur); ileri sarılıp geçilen öğe gösterilmez. Cevaplanan anket / quiz izleyiciye bir daha\n * sorulmaz (localStorage). Reklam oynarken gizlenir.\n */\nexport class Interactive {\n private entries: Entry[] = [];\n private active: { entry: Entry; el: HTMLElement; shownAt: number; pausedByUs: boolean; answered: boolean } | null = null;\n private markers: HTMLElement[] = [];\n private closeTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(\n private readonly ctx: InteractivePlayerContext,\n private options: InteractiveOptions\n ) {\n adoptStyle(ctx.overlayEl, 'interactive', css);\n this.entries = options.items.map((item, i) => ({ item, id: item.id ?? `i${i}`, done: false }));\n const v = ctx.videoEl;\n v.addEventListener('timeupdate', this.onTime);\n v.addEventListener('seeked', this.onSeeked);\n v.addEventListener('loadedmetadata', this.drawMarkers);\n v.addEventListener('emptied', this.onEmptied);\n ctx.hostEl.addEventListener('hp:adstart', this.onAdStart);\n if (v.readyState >= 1) this.drawMarkers();\n }\n\n /** Yalnızca fonksiyonlar değişti (ör. React'te her render'da yeni onAnswer). */\n setOptions(options: InteractiveOptions): void {\n this.options = options;\n }\n\n refreshLabels(): void {\n // Açık öğenin metinleri bir sonraki gösterimde dilden okunur; açık olanın kapat etiketi güncellenir.\n this.active?.el.querySelector('.hp-ia-close')?.setAttribute('aria-label', this.ctx.i18n.interactiveClose);\n }\n\n destroy(): void {\n const v = this.ctx.videoEl;\n v.removeEventListener('timeupdate', this.onTime);\n v.removeEventListener('seeked', this.onSeeked);\n v.removeEventListener('loadedmetadata', this.drawMarkers);\n v.removeEventListener('emptied', this.onEmptied);\n this.ctx.hostEl.removeEventListener('hp:adstart', this.onAdStart);\n this.hide(null);\n for (const m of this.markers) m.remove();\n this.markers = [];\n }\n\n private emit(state: 'shown' | 'answer' | 'click' | 'dismiss', entry: Entry, extra: Record<string, unknown> = {}): boolean {\n return this.ctx.hostEl.dispatchEvent(\n new CustomEvent('hp:interactive', { detail: { state, id: entry.id, type: entry.item.type, ...extra }, cancelable: state === 'click' })\n );\n }\n\n private readonly drawMarkers = (): void => {\n for (const m of this.markers) m.remove();\n this.markers = [];\n const d = this.ctx.videoEl.duration;\n if (this.options.markers === false || !Number.isFinite(d) || d <= 0) return;\n for (const e of this.entries) {\n if (e.item.time < 0 || e.item.time > d) continue;\n const m = this.ctx.addSeekBarMarker(e.item.time / d, 'hp-ia-marker', 'question' in e.item ? e.item.question : e.item.title);\n const color = e.item.markerColor ?? this.options.markerColor;\n if (color) m.style.backgroundColor = color;\n this.markers.push(m);\n }\n };\n\n /** Yeni kaynak: oturum durumu sıfırlanır. */\n private readonly onEmptied = (): void => {\n this.hide(null);\n for (const e of this.entries) e.done = false;\n };\n\n private readonly onAdStart = (): void => {\n // Reklam açık öğeyi örtmesin — kapat, reklamdan sonra tekrar gösterilmez.\n if (this.active && !this.active.answered) this.hide('timeout');\n };\n\n private remembered(entry: Entry): boolean {\n if (this.options.rememberAnswers === false || (entry.item.type !== 'poll' && entry.item.type !== 'quiz')) return false;\n try {\n return localStorage.getItem(STORE + entry.id) !== null;\n } catch {\n return false;\n }\n }\n\n private remember(entry: Entry, choice: number): void {\n if (this.options.rememberAnswers === false) return;\n try {\n localStorage.setItem(STORE + entry.id, String(choice));\n } catch {\n /* depolama kapalı */\n }\n }\n\n private duration(item: InteractiveItem): number {\n return item.duration ?? (item.type === 'poll' || item.type === 'quiz' ? 15 : 8);\n }\n\n /** Geri sarınca sonraki öğeler yeniden gösterilebilir (cevaplanmış anket / quiz yine sorulmaz). */\n private readonly onSeeked = (): void => {\n const t = this.ctx.videoEl.currentTime;\n for (const e of this.entries) if (e.item.time > t + 0.1 && e !== this.active?.entry) e.done = false;\n this.onTime();\n };\n\n private readonly onTime = (): void => {\n const t = this.ctx.videoEl.currentTime;\n const a = this.active;\n if (a) {\n // Geri sarıldı ya da süresi doldu (cevaplanmış anket sonucu kendi zamanlayıcısıyla kapanır).\n if (t < a.entry.item.time - 0.5) this.hide('seek');\n else if (!a.answered && t >= a.shownAt + this.duration(a.entry.item)) this.hide('timeout');\n // Sonuç gösterilirken sıradaki öğenin zamanı geldi — sonucu kapat, yenisini göster.\n else if (a.answered && this.entries.some((e) => !e.done && t >= e.item.time && t - e.item.time <= LATE)) this.hide(null);\n else return;\n }\n if (this.ctx.isAdActive()) return;\n for (const e of this.entries) {\n if (e.done || t < e.item.time) continue;\n e.done = true;\n // İleri sarılıp geçildiyse ya da daha önce cevaplandıysa gösterme.\n if (t - e.item.time > LATE || this.remembered(e)) continue;\n this.show(e, t);\n return;\n }\n };\n\n private show(entry: Entry, t: number): void {\n const item = entry.item;\n const box = el('div', 'hp-ia');\n box.setAttribute('part', `interactive interactive-${item.type}`);\n box.setAttribute('data-type', item.type);\n box.setAttribute('data-position', item.position ?? (item.type === 'poll' || item.type === 'quiz' ? 'top-right' : 'bottom-right'));\n box.setAttribute('role', 'group');\n for (const ev of ['pointerdown', 'click', 'dblclick'] as const) box.addEventListener(ev, (e) => e.stopPropagation());\n box.addEventListener('keydown', (e) => e.stopPropagation());\n\n if (item.dismissible !== false) {\n const close = el('button', 'hp-ia-close');\n close.type = 'button';\n close.setAttribute('aria-label', this.ctx.i18n.interactiveClose);\n close.appendChild(createIcon('close'));\n close.addEventListener('click', () => this.hide('user'));\n box.appendChild(close);\n }\n\n if (item.type === 'poll' || item.type === 'quiz') this.buildQuestion(box, entry);\n else this.buildCard(box, entry, item);\n\n this.ctx.overlayEl.appendChild(box);\n const v = this.ctx.videoEl;\n const pausedByUs = !!item.pause && !v.paused;\n if (pausedByUs) v.pause();\n this.active = { entry, el: box, shownAt: t, pausedByUs, answered: false };\n this.emit('shown', entry);\n }\n\n private buildQuestion(box: HTMLElement, entry: Entry): void {\n const item = entry.item as Extract<InteractiveItem, { type: 'poll' | 'quiz' }>;\n const i18n = this.ctx.i18n;\n box.appendChild(el('span', 'hp-ia-label', item.type === 'poll' ? i18n.interactivePoll : i18n.interactiveQuiz));\n const q = el('p', 'hp-ia-question', item.question);\n q.id = `hp-ia-q-${entry.id}`;\n box.setAttribute('aria-labelledby', q.id);\n box.appendChild(q);\n const list = el('div', 'hp-ia-choices');\n const choices = item.choices.map(choiceOf);\n const buttons = choices.map((c, i) => {\n const b = el('button', 'hp-ia-choice');\n b.type = 'button';\n b.appendChild(el('span', 'hp-ia-choice-text', c.text));\n b.addEventListener('click', () => void this.answer(entry, i, choices[i]!.id, buttons));\n list.appendChild(b);\n return b;\n });\n box.appendChild(list);\n const status = el('p', 'hp-ia-status');\n status.setAttribute('aria-live', 'polite');\n box.appendChild(status);\n }\n\n private async answer(entry: Entry, choice: number, choiceId: string, buttons: HTMLButtonElement[]): Promise<void> {\n const a = this.active;\n if (!a || a.entry !== entry || a.answered) return;\n a.answered = true;\n const item = entry.item as Extract<InteractiveItem, { type: 'poll' | 'quiz' }>;\n const correct = item.type === 'quiz' ? choice === item.answer : undefined;\n this.remember(entry, choice);\n for (const b of buttons) b.disabled = true;\n buttons[choice]?.setAttribute('data-picked', '');\n const status = a.el.querySelector<HTMLElement>('.hp-ia-status');\n this.emit('answer', entry, { choice, choiceId, ...(correct !== undefined ? { correct } : {}) });\n\n let results: number[] | void | undefined;\n try {\n results = await this.options.onAnswer?.({ item, id: entry.id, choice, choiceId, correct });\n } catch {\n results = undefined;\n }\n if (this.active?.entry !== entry) return;\n\n if (item.type === 'quiz') {\n buttons[item.answer]?.setAttribute('data-correct', '');\n if (!correct) buttons[choice]?.setAttribute('data-wrong', '');\n if (status) status.textContent = `${correct ? this.ctx.i18n.interactiveCorrect : this.ctx.i18n.interactiveWrong}${item.explanation ? ` ${item.explanation}` : ''}`;\n } else {\n // Sonuç: onAnswer'ın döndürdüğü, yoksa verilen dağılım + bu oy.\n const base = Array.isArray(results) ? results : item.results ? item.results.map((n, i) => n + (i === choice ? 1 : 0)) : null;\n if (base) {\n const total = base.reduce((s, n) => s + (Number.isFinite(n) && n > 0 ? n : 0), 0) || 1;\n buttons.forEach((b, i) => {\n const pct = Math.round(((base[i] ?? 0) / total) * 100);\n b.style.setProperty('--hp-ia-pct', `${pct}%`);\n b.setAttribute('data-result', '');\n b.appendChild(el('span', 'hp-ia-pct', this.ctx.i18n.interactiveVotes(pct)));\n });\n }\n }\n // Sonuç birkaç saniye görünür, sonra kapanır (duraklattıysak oynatma devam eder).\n this.closeTimer = setTimeout(() => this.hide(null), item.type === 'quiz' ? 5000 : 3500);\n }\n\n private buildCard(box: HTMLElement, entry: Entry, item: InteractiveCard): void {\n const i18n = this.ctx.i18n;\n const link = el('a', 'hp-ia-card');\n link.href = item.url;\n if (item.newTab !== false) {\n link.target = '_blank';\n link.rel = 'noopener';\n }\n if (item.image) {\n const img = el('img', 'hp-ia-image');\n img.src = item.image;\n img.alt = '';\n img.decoding = 'async';\n img.addEventListener('error', () => img.remove());\n link.appendChild(img);\n }\n const body = el('span', 'hp-ia-body');\n if (item.sponsored) body.appendChild(el('span', 'hp-ia-label', i18n.interactiveSponsored));\n body.appendChild(el('span', 'hp-ia-title', item.title));\n if (item.subtitle) body.appendChild(el('span', 'hp-ia-sub', item.subtitle));\n if (item.price || item.oldPrice) {\n const price = el('span', 'hp-ia-price');\n if (item.price) price.appendChild(el('strong', '', item.price));\n if (item.oldPrice) price.appendChild(el('s', '', item.oldPrice));\n body.appendChild(price);\n }\n body.appendChild(el('span', 'hp-ia-cta', item.cta ?? (item.type === 'product' ? i18n.interactiveBuy : i18n.interactiveGo)));\n link.appendChild(body);\n link.addEventListener('click', (e) => {\n // preventDefault → entegratör kendisi açar (sepete ekle, SPA router).\n if (!this.emit('click', entry, { url: item.url })) e.preventDefault();\n });\n box.setAttribute('aria-label', item.title);\n box.appendChild(link);\n }\n\n private hide(reason: 'user' | 'timeout' | 'seek' | null): void {\n if (this.closeTimer) clearTimeout(this.closeTimer);\n this.closeTimer = null;\n const a = this.active;\n if (!a) return;\n this.active = null;\n a.el.remove();\n if (reason) this.emit('dismiss', a.entry, { reason });\n if (a.pausedByUs && reason !== 'seek') void this.ctx.videoEl.play().catch(() => {});\n }\n}\n","import { Interactive, type InteractivePlayerContext } from './Interactive';\nimport type { InteractiveOptions } from '../../types';\n\nexport function installInteractive(ctx: InteractivePlayerContext, options: InteractiveOptions): Interactive {\n return new Interactive(ctx, options);\n}\n\nexport { Interactive };\nexport type { InteractivePlayerContext };\n"],"names":["STORE","LATE","choiceOf","c","i","el","tag","className","text","Interactive","ctx","options","__publicField","m","d","e","color","_a","a","adoptStyle","css","item","v","_b","state","entry","extra","choice","t","box","ev","close","createIcon","pausedByUs","i18n","q","list","choices","buttons","b","status","choiceId","correct","results","_c","_d","_e","_f","base","n","total","s","pct","link","img","body","price","reason","installInteractive"],"mappings":"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"}
|