@hopeplayer/core 1.3.1 → 1.5.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.
Files changed (97) hide show
  1. package/README.md +4 -0
  2. package/dist/HopePlayerElement.d.ts +29 -4
  3. package/dist/HopePlayerElement.d.ts.map +1 -1
  4. package/dist/chunks/NativeEme-CXosVcw8.js +80 -0
  5. package/dist/chunks/NativeEme-CXosVcw8.js.map +1 -0
  6. package/dist/chunks/{accessibility-CehDBG3h.js → accessibility-DFx4CE0H.js} +45 -41
  7. package/dist/chunks/accessibility-DFx4CE0H.js.map +1 -0
  8. package/dist/chunks/{ads-BFmyld9u.js → ads-C4tDPsUs.js} +3 -3
  9. package/dist/chunks/ads-C4tDPsUs.js.map +1 -0
  10. package/dist/chunks/analytics-DEjTAJO9.js +281 -0
  11. package/dist/chunks/analytics-DEjTAJO9.js.map +1 -0
  12. package/dist/chunks/{cast-DJXOJLEZ.js → cast-Baxvu76A.js} +2 -2
  13. package/dist/chunks/{cast-DJXOJLEZ.js.map → cast-Baxvu76A.js.map} +1 -1
  14. package/dist/chunks/dash-CWjy-y7B.js +22 -0
  15. package/dist/chunks/dash-CWjy-y7B.js.map +1 -0
  16. package/dist/chunks/{history-YQ9A8HBv.js → history-CvydU0aN.js} +2 -2
  17. package/dist/chunks/{history-YQ9A8HBv.js.map → history-CvydU0aN.js.map} +1 -1
  18. package/dist/chunks/keySystems-CNzjRq6e.js +70 -0
  19. package/dist/chunks/keySystems-CNzjRq6e.js.map +1 -0
  20. package/dist/chunks/{markers-BmcD53SJ.js → markers-Dr4-CCxE.js} +2 -2
  21. package/dist/chunks/{markers-BmcD53SJ.js.map → markers-Dr4-CCxE.js.map} +1 -1
  22. package/dist/chunks/{player-BVkwkn4b.js → player-DV4Hf5Cw.js} +1320 -993
  23. package/dist/chunks/player-DV4Hf5Cw.js.map +1 -0
  24. package/dist/chunks/{playlist-jDbObKz3.js → playlist-DJsdK6xm.js} +29 -21
  25. package/dist/chunks/playlist-DJsdK6xm.js.map +1 -0
  26. package/dist/chunks/pluginHost-GxNfyP5E.js +566 -0
  27. package/dist/chunks/pluginHost-GxNfyP5E.js.map +1 -0
  28. package/dist/chunks/{redirectScreen-CFZKtEdv.js → redirectScreen-BT_26-5g.js} +2 -2
  29. package/dist/chunks/{redirectScreen-CFZKtEdv.js.map → redirectScreen-BT_26-5g.js.map} +1 -1
  30. package/dist/chunks/{rewardedUnlock-Cn4_68a3.js → rewardedUnlock-jFOdzfSq.js} +2 -2
  31. package/dist/chunks/{rewardedUnlock-Cn4_68a3.js.map → rewardedUnlock-jFOdzfSq.js.map} +1 -1
  32. package/dist/chunks/{segments-DXARAkpS.js → segments--hl_QVrI.js} +2 -2
  33. package/dist/chunks/{segments-DXARAkpS.js.map → segments--hl_QVrI.js.map} +1 -1
  34. package/dist/chunks/{skipSegments-U0aUwoDt.js → skipSegments-vJMhdiJn.js} +55 -42
  35. package/dist/chunks/{skipSegments-U0aUwoDt.js.map → skipSegments-vJMhdiJn.js.map} +1 -1
  36. package/dist/chunks/{spriteThumbnails-DLfTFsPU.js → spriteThumbnails-BoxVY--_.js} +76 -53
  37. package/dist/chunks/spriteThumbnails-BoxVY--_.js.map +1 -0
  38. package/dist/chunks/{statsPanel-DSClIwA3.js → statsPanel-D0DtoFgS.js} +2 -2
  39. package/dist/chunks/statsPanel-D0DtoFgS.js.map +1 -0
  40. package/dist/chunks/{story-Ce56rEaN.js → story-BRkhSDhR.js} +2 -2
  41. package/dist/chunks/{story-Ce56rEaN.js.map → story-BRkhSDhR.js.map} +1 -1
  42. package/dist/controls/ControlBar.d.ts +2 -0
  43. package/dist/controls/ControlBar.d.ts.map +1 -1
  44. package/dist/controls/SeekBar.d.ts.map +1 -1
  45. package/dist/controls/SettingsMenu.d.ts +5 -0
  46. package/dist/controls/SettingsMenu.d.ts.map +1 -1
  47. package/dist/drm/NativeEme.d.ts +23 -0
  48. package/dist/drm/NativeEme.d.ts.map +1 -0
  49. package/dist/drm/keySystems.d.ts +18 -0
  50. package/dist/drm/keySystems.d.ts.map +1 -0
  51. package/dist/hls/SourceManager.d.ts +31 -5
  52. package/dist/hls/SourceManager.d.ts.map +1 -1
  53. package/dist/hls/dashEngine.d.ts +85 -0
  54. package/dist/hls/dashEngine.d.ts.map +1 -0
  55. package/dist/hls/sourceGroups.d.ts.map +1 -1
  56. package/dist/hope-player.js +6 -3
  57. package/dist/i18n/locales/en.d.ts.map +1 -1
  58. package/dist/i18n/locales/tr.d.ts.map +1 -1
  59. package/dist/i18n/types.d.ts +3 -0
  60. package/dist/i18n/types.d.ts.map +1 -1
  61. package/dist/index.d.ts +4 -1
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/keyboard/KeyboardController.d.ts +14 -0
  64. package/dist/keyboard/KeyboardController.d.ts.map +1 -1
  65. package/dist/plugin-api/PluginAds.d.ts +61 -0
  66. package/dist/plugin-api/PluginAds.d.ts.map +1 -0
  67. package/dist/plugin-api/PluginHost.d.ts +71 -0
  68. package/dist/plugin-api/PluginHost.d.ts.map +1 -0
  69. package/dist/plugin-api/registry.d.ts +10 -0
  70. package/dist/plugin-api/registry.d.ts.map +1 -0
  71. package/dist/plugin-api/types.d.ts +209 -0
  72. package/dist/plugin-api/types.d.ts.map +1 -0
  73. package/dist/plugins/accessibility/Accessibility.d.ts +5 -0
  74. package/dist/plugins/accessibility/Accessibility.d.ts.map +1 -1
  75. package/dist/plugins/ads/AdsController.d.ts +2 -0
  76. package/dist/plugins/ads/AdsController.d.ts.map +1 -1
  77. package/dist/plugins/analytics/QoeTracker.d.ts +71 -0
  78. package/dist/plugins/analytics/QoeTracker.d.ts.map +1 -0
  79. package/dist/plugins/analytics/index.d.ts +6 -0
  80. package/dist/plugins/analytics/index.d.ts.map +1 -0
  81. package/dist/plugins/playlist/PlaylistRunner.d.ts +2 -0
  82. package/dist/plugins/playlist/PlaylistRunner.d.ts.map +1 -1
  83. package/dist/plugins/skip-segments/index.d.ts +2 -0
  84. package/dist/plugins/skip-segments/index.d.ts.map +1 -1
  85. package/dist/plugins/sprite-thumbnails/SpriteThumbnails.d.ts +8 -0
  86. package/dist/plugins/sprite-thumbnails/SpriteThumbnails.d.ts.map +1 -1
  87. package/dist/screens/ErrorScreen.d.ts +1 -1
  88. package/dist/screens/ErrorScreen.d.ts.map +1 -1
  89. package/dist/types/index.d.ts +159 -4
  90. package/dist/types/index.d.ts.map +1 -1
  91. package/package.json +2 -1
  92. package/dist/chunks/accessibility-CehDBG3h.js.map +0 -1
  93. package/dist/chunks/ads-BFmyld9u.js.map +0 -1
  94. package/dist/chunks/player-BVkwkn4b.js.map +0 -1
  95. package/dist/chunks/playlist-jDbObKz3.js.map +0 -1
  96. package/dist/chunks/spriteThumbnails-DLfTFsPU.js.map +0 -1
  97. package/dist/chunks/statsPanel-DSClIwA3.js.map +0 -1
@@ -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-BVkwkn4b.js";
4
+ import { f as E } from "./player-DV4Hf5Cw.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-YQ9A8HBv.js.map
144
+ //# sourceMappingURL=history-CvydU0aN.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"history-YQ9A8HBv.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-CvydU0aN.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,70 @@
1
+ const u = {
2
+ widevine: "com.widevine.alpha",
3
+ playready: "com.microsoft.playready",
4
+ fairplay: "com.apple.fps",
5
+ clearkey: "org.w3.clearkey"
6
+ };
7
+ function y(e) {
8
+ return e ? ["fairplay", "widevine", "playready", "clearkey"].filter((s) => {
9
+ var r;
10
+ return (r = e[s]) == null ? void 0 : r.licenseUrl;
11
+ }).map((s) => [s, e[s]]) : [];
12
+ }
13
+ function g(e) {
14
+ return y(e).length > 0;
15
+ }
16
+ const R = (e) => Object.keys(u).find((n) => u[n] === e);
17
+ function A(e, n) {
18
+ var w, v;
19
+ const s = {};
20
+ for (const [t, c] of y(e)) {
21
+ const a = t === "fairplay" ? e.fairplay.certificateUrl : void 0;
22
+ s[u[t]] = { licenseUrl: c.licenseUrl, ...a ? { serverCertificateUrl: a } : {} };
23
+ }
24
+ const r = n.licenseXhrSetup, i = n.licenseResponseCallback, p = {
25
+ emeEnabled: !0,
26
+ drmSystems: s,
27
+ licenseXhrSetup(t, c, a, l) {
28
+ var h;
29
+ const f = R(a.keySystem), o = f ? e[f] : void 0;
30
+ for (const [d, U] of Object.entries((o == null ? void 0 : o.headers) ?? {})) t.setRequestHeader(d, U);
31
+ return o != null && o.withCredentials && (t.withCredentials = !0), f === "fairplay" && ((h = e.fairplay) != null && h.prepareLicenseRequest) ? Promise.resolve(e.fairplay.prepareLicenseRequest(l, new Uint8Array(0))).then(b) : r == null ? void 0 : r.call(this, t, c, a, l);
32
+ }
33
+ };
34
+ return ((w = e.fairplay) != null && w.parseLicenseResponse || i) && (p.licenseResponseCallback = function(t, c, a) {
35
+ var l;
36
+ if (R(a.keySystem) === "fairplay" && ((l = e.fairplay) != null && l.parseLicenseResponse)) {
37
+ const f = e.fairplay.parseLicenseResponse(t.response);
38
+ if (!(f instanceof Promise)) return S(f);
39
+ }
40
+ return i ? i.call(this, t, c, a) : t.response;
41
+ }), (v = e.widevine) != null && v.robustness && (p.drmSystemOptions = { videoRobustness: e.widevine.robustness, audioRobustness: e.widevine.robustness }), p;
42
+ }
43
+ function b(e) {
44
+ return typeof e == "string" || e instanceof Uint8Array ? e : e instanceof ArrayBuffer ? new Uint8Array(e) : ArrayBuffer.isView(e) ? new Uint8Array(e.buffer, e.byteOffset, e.byteLength) : String(e);
45
+ }
46
+ function S(e) {
47
+ if (e instanceof ArrayBuffer) return e;
48
+ const n = e;
49
+ return n.buffer.slice(n.byteOffset, n.byteOffset + n.byteLength);
50
+ }
51
+ function L(e) {
52
+ var s;
53
+ const n = {};
54
+ for (const [r, i] of y(e))
55
+ r !== "fairplay" && (n[u[r]] = {
56
+ serverURL: i.licenseUrl,
57
+ ...i.headers ? { httpRequestHeaders: i.headers } : {},
58
+ ...i.withCredentials ? { withCredentials: !0 } : {},
59
+ ...r === "widevine" && ((s = e.widevine) != null && s.robustness) ? { videoRobustness: e.widevine.robustness, audioRobustness: e.widevine.robustness } : {}
60
+ });
61
+ return n;
62
+ }
63
+ export {
64
+ u as KEY_SYSTEMS,
65
+ L as dashProtectionData,
66
+ y as drmEntries,
67
+ g as hasDrm,
68
+ A as hlsDrmConfig
69
+ };
70
+ //# sourceMappingURL=keySystems-CNzjRq6e.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keySystems-CNzjRq6e.js","sources":["../../src/drm/keySystems.ts"],"sourcesContent":["// `options.drm` → hls.js / dash.js ayarları.\nimport type { HlsConfig } from 'hls.js';\nimport type { ProtectionDataSet } from 'dashjs';\nimport type { HopeDrmLicense, HopeDrmOptions } from '../types';\n\nexport const KEY_SYSTEMS = {\n widevine: 'com.widevine.alpha',\n playready: 'com.microsoft.playready',\n fairplay: 'com.apple.fps',\n clearkey: 'org.w3.clearkey',\n} as const;\n\nexport type DrmName = keyof typeof KEY_SYSTEMS;\n\n/** Verilen sistemler, öncelik sırasıyla. */\nexport function drmEntries(drm: HopeDrmOptions | undefined): Array<[DrmName, HopeDrmLicense]> {\n if (!drm) return [];\n const order: DrmName[] = ['fairplay', 'widevine', 'playready', 'clearkey'];\n return order.filter((n) => drm[n]?.licenseUrl).map((n) => [n, drm[n]!]);\n}\n\nexport function hasDrm(drm: HopeDrmOptions | undefined): boolean {\n return drmEntries(drm).length > 0;\n}\n\nconst nameOf = (keySystem: string): DrmName | undefined => (Object.keys(KEY_SYSTEMS) as DrmName[]).find((n) => KEY_SYSTEMS[n] === keySystem);\n\n/** hls.js EME ayarları. */\nexport function hlsDrmConfig(drm: HopeDrmOptions, user: Partial<HlsConfig>): Partial<HlsConfig> {\n const drmSystems: NonNullable<HlsConfig['drmSystems']> = {};\n for (const [name, lic] of drmEntries(drm)) {\n const cert = name === 'fairplay' ? drm.fairplay!.certificateUrl : undefined;\n drmSystems[KEY_SYSTEMS[name] as keyof typeof drmSystems] = { licenseUrl: lic.licenseUrl, ...(cert ? { serverCertificateUrl: cert } : {}) };\n }\n const userSetup = user.licenseXhrSetup;\n const userResponse = user.licenseResponseCallback;\n const config: Partial<HlsConfig> = {\n emeEnabled: true,\n drmSystems,\n licenseXhrSetup(xhr, url, keyContext, challenge) {\n const name = nameOf(keyContext.keySystem);\n const lic = name ? drm[name] : undefined;\n for (const [k, v] of Object.entries(lic?.headers ?? {})) xhr.setRequestHeader(k, v);\n if (lic?.withCredentials) xhr.withCredentials = true;\n if (name === 'fairplay' && drm.fairplay?.prepareLicenseRequest) {\n return Promise.resolve(drm.fairplay.prepareLicenseRequest(challenge, new Uint8Array(0))).then(toChallenge);\n }\n return userSetup?.call(this, xhr, url, keyContext, challenge);\n },\n };\n if (drm.fairplay?.parseLicenseResponse || userResponse) {\n config.licenseResponseCallback = function (xhr, url, keyContext) {\n if (nameOf(keyContext.keySystem) === 'fairplay' && drm.fairplay?.parseLicenseResponse) {\n // hls.js eşzamanlı yanıt bekler; Promise dönen ayrıştırıcı burada kullanılamaz.\n const out = drm.fairplay.parseLicenseResponse(xhr.response as ArrayBuffer);\n if (!(out instanceof Promise)) return toArrayBuffer(out);\n }\n return userResponse ? userResponse.call(this, xhr, url, keyContext) : (xhr.response as ArrayBuffer);\n };\n }\n if (drm.widevine?.robustness) {\n config.drmSystemOptions = { videoRobustness: drm.widevine.robustness, audioRobustness: drm.widevine.robustness };\n }\n return config;\n}\n\nfunction toChallenge(body: BodyInit): Uint8Array | string {\n if (typeof body === 'string') return body;\n if (body instanceof Uint8Array) return body;\n if (body instanceof ArrayBuffer) return new Uint8Array(body);\n if (ArrayBuffer.isView(body)) return new Uint8Array(body.buffer, body.byteOffset, body.byteLength);\n return String(body);\n}\n\nfunction toArrayBuffer(b: BufferSource): ArrayBuffer {\n if (b instanceof ArrayBuffer) return b;\n const view = b as ArrayBufferView;\n return view.buffer.slice(view.byteOffset, view.byteOffset + view.byteLength) as ArrayBuffer;\n}\n\n/** dash.js koruma verisi (FairPlay DASH'te kullanılmaz). */\nexport function dashProtectionData(drm: HopeDrmOptions): ProtectionDataSet {\n const out: ProtectionDataSet = {};\n for (const [name, lic] of drmEntries(drm)) {\n if (name === 'fairplay') continue;\n out[KEY_SYSTEMS[name]] = {\n serverURL: lic.licenseUrl,\n ...(lic.headers ? { httpRequestHeaders: lic.headers } : {}),\n ...(lic.withCredentials ? { withCredentials: true } : {}),\n ...(name === 'widevine' && drm.widevine?.robustness ? { videoRobustness: drm.widevine.robustness, audioRobustness: drm.widevine.robustness } : {}),\n };\n }\n return out;\n}\n"],"names":["KEY_SYSTEMS","drmEntries","drm","n","_a","hasDrm","nameOf","keySystem","hlsDrmConfig","user","_b","drmSystems","name","lic","cert","userSetup","userResponse","config","xhr","url","keyContext","challenge","k","v","toChallenge","out","toArrayBuffer","body","b","view","dashProtectionData"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  var u = Object.defineProperty;
2
2
  var m = (p, e, t) => e in p ? u(p, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : p[e] = t;
3
3
  var o = (p, e, t) => m(p, typeof e != "symbol" ? e + "" : e, t);
4
- import { c as b } from "./player-BVkwkn4b.js";
4
+ import { c as b } from "./player-DV4Hf5Cw.js";
5
5
  const f = {
6
6
  enabled: !1,
7
7
  mode: "rich",
@@ -202,4 +202,4 @@ export {
202
202
  v as MarkProgress,
203
203
  y as installMarkers
204
204
  };
205
- //# sourceMappingURL=markers-BmcD53SJ.js.map
205
+ //# sourceMappingURL=markers-Dr4-CCxE.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"markers-BmcD53SJ.js","sources":["../../src/plugins/markers/MarkProgress.ts","../../src/plugins/markers/index.ts"],"sourcesContent":["import { createIcon } from '../../icons/Icon';\nimport type { MarkerItem, MarkerPingOptions, MarkerPopupOptions, MarkersOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\n\nexport interface MarkersPlayerContext {\n videoEl: HTMLVideoElement;\n /** Popup overlay'in ekleneceği katman (shadow root içinde, video üzerinde). */\n overlayContainerEl: HTMLElement;\n /** Seek bar üzerinde işaretçi çizmek için — SeekBar.addMarker ile aynı imza. */\n addSeekBarMarker(ratio: number, extraClass?: string): HTMLDivElement;\n i18n: HopeLocaleStrings;\n}\n\ninterface NormalizedMarker extends Required<Pick<MarkerItem, 'time'>> {\n idx: number;\n color?: string;\n label: string;\n pauseOnHit: boolean;\n once: boolean;\n tolerance: number;\n cooldownMs: number;\n action?: MarkerItem['action'];\n popup: MarkerPopupOptions | null;\n pingUrl: string;\n el?: HTMLElement;\n}\n\nconst POPUP_DEFAULTS: Required<MarkerPopupOptions> = {\n enabled: false,\n mode: 'rich',\n text: '',\n imageUrl: '',\n imageAlt: '',\n linkUrl: '',\n // Boş bırakılıyor (sentinel) — gerçek varsayılan metin showPopup()'ta\n // `ctx.i18n.markerLearnMore`/`markerContinue`'dan okunuyor, dil\n // değişimini takip edebilsin diye burada SABİT bir dilde gömülü değil.\n linkText: '',\n continueText: '',\n showContinue: true,\n showClose: true,\n autoplayOnClose: true,\n autoplayOnContinue: true,\n};\n\nconst PING_DEFAULTS: Required<MarkerPingOptions> = { enabled: false, url: '', method: 'GET', includeMarker: false };\n\n/** Zaman tabanlı seek bar işaretçileri — seek/jump koruması, once/cooldown, popup/ping/aksiyon. */\nexport class MarkProgress {\n private readonly markers: NormalizedMarker[];\n private readonly popupGlobal: Required<MarkerPopupOptions>;\n private readonly pingGlobal: Required<MarkerPingOptions>;\n private readonly triggerOnSeek: boolean;\n private readonly seekJumpThresholdSec: number;\n private readonly seekIgnoreWindowMs: number;\n\n private hitSet = new Set<string>();\n private lastHitAt = new Map<string, number>();\n private lastTime = 0;\n private isSeeking = false;\n private ignoreUntilTs = 0;\n private popupEl: HTMLElement | null = null;\n\n constructor(\n private readonly ctx: MarkersPlayerContext,\n options: MarkersOptions\n ) {\n this.triggerOnSeek = options.triggerOnSeek === true;\n this.seekJumpThresholdSec = options.seekJumpThresholdSec ?? 1;\n this.seekIgnoreWindowMs = options.seekIgnoreWindowMs ?? 250;\n this.popupGlobal = { ...POPUP_DEFAULTS, ...options.popup };\n this.pingGlobal = { ...PING_DEFAULTS, ...options.ping };\n\n this.markers = (options.items || [])\n .map((m, idx) => this.normalize(m, idx))\n .filter((m) => Number.isFinite(m.time) && m.time >= 0)\n .sort((a, b) => a.time - b.time);\n\n ctx.videoEl.addEventListener('loadedmetadata', this.onLoadedMetadata);\n ctx.videoEl.addEventListener('timeupdate', this.onTimeUpdate);\n ctx.videoEl.addEventListener('seeking', this.onSeeking);\n ctx.videoEl.addEventListener('seeked', this.onSeeked);\n\n if (ctx.videoEl.readyState >= 1) this.onLoadedMetadata();\n }\n\n /** Popup lazy oluşturulup yeniden kullanılıyor (`ensurePopup`) — zaten açıksa close butonunun statik etiketini tazeler. */\n refreshLabels(): void {\n const closeBtn = this.popupEl?.querySelector('button') as HTMLButtonElement | null;\n if (closeBtn) {\n closeBtn.setAttribute('aria-label', this.ctx.i18n.close);\n }\n }\n\n destroy(): void {\n this.ctx.videoEl.removeEventListener('loadedmetadata', this.onLoadedMetadata);\n this.ctx.videoEl.removeEventListener('timeupdate', this.onTimeUpdate);\n this.ctx.videoEl.removeEventListener('seeking', this.onSeeking);\n this.ctx.videoEl.removeEventListener('seeked', this.onSeeked);\n this.markers.forEach((m) => m.el?.remove());\n this.popupEl?.remove();\n this.popupEl = null;\n this.hitSet.clear();\n this.lastHitAt.clear();\n }\n\n private normalize(m: MarkerItem, idx: number): NormalizedMarker {\n return {\n idx,\n time: Number(m.time),\n color: m.color,\n label: m.label ?? '',\n pauseOnHit: m.pauseOnHit ?? true,\n once: m.once ?? true,\n tolerance: m.tolerance ?? 0.25,\n cooldownMs: m.cooldownMs ?? 600,\n action: m.action,\n popup: m.popup ?? null,\n pingUrl: m.pingUrl ?? '',\n };\n }\n\n private readonly onLoadedMetadata = (): void => {\n const duration = this.ctx.videoEl.duration;\n if (!Number.isFinite(duration) || duration <= 0) return;\n\n this.markers.forEach((m) => {\n if (m.el) return;\n const el = this.ctx.addSeekBarMarker(m.time / duration);\n if (m.color) el.style.backgroundColor = m.color;\n if (m.label) el.title = m.label;\n m.el = el;\n });\n\n this.lastTime = this.ctx.videoEl.currentTime || 0;\n };\n\n private readonly onSeeking = (): void => {\n this.isSeeking = true;\n this.ignoreUntilTs = Date.now() + this.seekIgnoreWindowMs;\n this.lastTime = this.ctx.videoEl.currentTime || 0;\n };\n\n private readonly onSeeked = (): void => {\n this.lastTime = this.ctx.videoEl.currentTime || 0;\n this.isSeeking = false;\n this.ignoreUntilTs = Date.now() + this.seekIgnoreWindowMs;\n };\n\n private readonly onTimeUpdate = (): void => {\n const now = Date.now();\n if (now < this.ignoreUntilTs) return;\n if (this.isSeeking) return;\n\n const t = this.ctx.videoEl.currentTime;\n if (!Number.isFinite(t)) return;\n\n const jumped = Math.abs(t - this.lastTime) >= this.seekJumpThresholdSec;\n if (jumped && !this.triggerOnSeek) {\n this.lastTime = t;\n return;\n }\n\n for (const m of this.markers) {\n const key = `${m.time}-${m.idx}`;\n if (m.once && this.hitSet.has(key)) continue;\n if (!m.once) {\n const last = this.lastHitAt.get(key) || 0;\n if (now - last < m.cooldownMs) continue;\n }\n\n const crossed = this.lastTime < m.time && t >= m.time - m.tolerance;\n if (!crossed) continue;\n\n if (m.once) this.hitSet.add(key);\n else this.lastHitAt.set(key, now);\n\n if (m.pauseOnHit) this.ctx.videoEl.pause();\n\n this.firePing(m);\n this.fireAction(m);\n\n const popupCfg = m.popup ? { ...this.popupGlobal, ...m.popup } : this.popupGlobal;\n if (popupCfg.enabled) {\n this.ctx.videoEl.pause();\n this.showPopup(popupCfg);\n }\n break;\n }\n\n this.lastTime = t;\n };\n\n private resolveUrlTemplate(url: string, m: NormalizedMarker): string {\n if (!url) return '';\n return url.replaceAll('{time}', encodeURIComponent(String(m.time))).replaceAll('{label}', encodeURIComponent(m.label));\n }\n\n private firePing(m: NormalizedMarker): void {\n const baseUrl = m.pingUrl || this.pingGlobal.url;\n const url = this.resolveUrlTemplate(baseUrl, m);\n if (!this.pingGlobal.enabled || !url) return;\n\n try {\n if (this.pingGlobal.method === 'POST') {\n fetch(url, {\n method: 'POST',\n keepalive: true,\n headers: this.pingGlobal.includeMarker ? { 'Content-Type': 'application/json' } : undefined,\n body: this.pingGlobal.includeMarker ? JSON.stringify({ time: m.time, label: m.label, ts: Date.now() }) : undefined,\n }).catch(() => {});\n } else {\n fetch(url, { method: 'GET', keepalive: true }).catch(() => {});\n }\n } catch {\n /* no-op */\n }\n }\n\n private fireAction(m: NormalizedMarker): void {\n const a = m.action;\n if (!a) return;\n\n if (a.type === 'log') {\n console.log('[HopePlayer markers]', a.name || 'marker_hit', { time: m.time, label: m.label }, a.payload);\n return;\n }\n\n if (a.type === 'datalayer') {\n try {\n const w = window as unknown as { dataLayer?: unknown[] };\n w.dataLayer = w.dataLayer || [];\n w.dataLayer.push({\n event: 'HopePlayerVideoEvents',\n trigger: a.name || 'marker_hit',\n marker: { time: m.time, label: m.label, color: m.color },\n payload: a.payload ?? {},\n ts: Date.now(),\n });\n } catch {\n /* no-op */\n }\n return;\n }\n\n if (a.type === 'custom') {\n const fn = a.name ? (window as unknown as Record<string, unknown>)[a.name] : null;\n if (typeof fn === 'function') {\n try {\n (fn as (ctx: unknown) => void)({ marker: m, payload: a.payload });\n } catch (err) {\n console.warn('[HopePlayer markers] custom action fonksiyonu hata verdi:', err);\n }\n } else {\n console.warn('[HopePlayer markers] custom action fonksiyonu bulunamadı: window.' + a.name);\n }\n }\n }\n\n private ensurePopup(): HTMLElement {\n if (this.popupEl) return this.popupEl;\n\n const overlay = document.createElement('div');\n overlay.setAttribute('part', 'marker-popup');\n overlay.className = 'hp:hidden hp:absolute hp:inset-0 hp:z-30 hp:items-center hp:justify-center hp:bg-black/70';\n\n const panel = document.createElement('div');\n panel.className = 'hp:relative hp:max-w-[85%] hp:bg-surface-elev hp:text-on-surface hp:rounded-lg hp:p-4 hp:text-center hp:shadow-xl';\n panel.setAttribute('role', 'dialog');\n panel.setAttribute('aria-modal', 'true');\n\n const closeBtn = document.createElement('button');\n closeBtn.type = 'button';\n closeBtn.setAttribute('aria-label', this.ctx.i18n.close);\n closeBtn.className = 'hp:absolute hp:top-1 hp:right-1 hp:w-6 hp:h-6 hp:flex hp:items-center hp:justify-center hp:bg-transparent hp:border-0 hp:cursor-pointer hp:text-on-surface';\n closeBtn.appendChild(createIcon('close', 'hp:text-sm'));\n\n const mediaWrap = document.createElement('div');\n mediaWrap.className = 'hp:hidden hp:mb-2';\n const img = document.createElement('img');\n img.className = 'hp:max-w-full hp:rounded';\n mediaWrap.appendChild(img);\n\n const textEl = document.createElement('div');\n textEl.className = 'hp:text-sm hp:mb-2';\n\n const linkEl = document.createElement('a');\n linkEl.target = '_blank';\n linkEl.rel = 'noopener noreferrer';\n linkEl.className = 'hp:hidden hp:text-accent hp:underline hp:text-sm hp:block hp:mb-2';\n\n const continueBtn = document.createElement('button');\n continueBtn.type = 'button';\n continueBtn.className = 'hp:hidden hp:px-4 hp:py-1.5 hp:rounded hp:bg-accent hp:text-on-accent hp:border-0 hp:cursor-pointer hp:text-sm';\n\n panel.append(closeBtn, mediaWrap, textEl, linkEl, continueBtn);\n overlay.appendChild(panel);\n this.ctx.overlayContainerEl.appendChild(overlay);\n this.popupEl = overlay;\n return overlay;\n }\n\n private hidePopup(): void {\n this.popupEl?.classList.add('hp:hidden');\n this.popupEl?.classList.remove('hp:flex');\n }\n\n private safePlay(): void {\n void this.ctx.videoEl.play().catch(() => {});\n }\n\n private showPopup(cfg: Required<MarkerPopupOptions>): void {\n const el = this.ensurePopup();\n const textEl = el.querySelector('div.hp\\\\:text-sm.hp\\\\:mb-2:not(.hp\\\\:hidden)') as HTMLElement | null;\n const mediaWrap = el.querySelector('div.hp\\\\:mb-2') as HTMLElement | null;\n const img = el.querySelector('img') as HTMLImageElement | null;\n const linkEl = el.querySelector('a') as HTMLAnchorElement | null;\n const continueBtn = el.querySelectorAll('button')[1] as HTMLButtonElement | null;\n const closeBtn = el.querySelector('button') as HTMLButtonElement | null;\n\n if (closeBtn) closeBtn.style.display = cfg.showClose === false ? 'none' : '';\n if (textEl) textEl.textContent = cfg.text || '';\n\n const isRich = cfg.mode === 'rich';\n if (mediaWrap && img) {\n if (isRich && cfg.imageUrl) {\n mediaWrap.classList.remove('hp:hidden');\n img.src = cfg.imageUrl;\n img.alt = cfg.imageAlt || '';\n } else {\n mediaWrap.classList.add('hp:hidden');\n img.removeAttribute('src');\n }\n }\n\n if (linkEl) {\n if (isRich && cfg.linkUrl) {\n linkEl.classList.remove('hp:hidden');\n linkEl.href = cfg.linkUrl;\n linkEl.textContent = cfg.linkText || this.ctx.i18n.markerLearnMore;\n } else {\n linkEl.classList.add('hp:hidden');\n linkEl.removeAttribute('href');\n }\n }\n\n if (continueBtn) {\n if (cfg.showContinue) {\n continueBtn.classList.remove('hp:hidden');\n continueBtn.textContent = cfg.continueText || this.ctx.i18n.markerContinue;\n } else {\n continueBtn.classList.add('hp:hidden');\n }\n }\n\n const newClose = closeBtn?.cloneNode(true) as HTMLButtonElement | undefined;\n if (closeBtn && newClose) closeBtn.replaceWith(newClose);\n const newCont = continueBtn?.cloneNode(true) as HTMLButtonElement | undefined;\n if (continueBtn && newCont) continueBtn.replaceWith(newCont);\n\n newClose?.addEventListener('click', () => {\n this.hidePopup();\n if (cfg.autoplayOnClose) this.safePlay();\n });\n newCont?.addEventListener('click', () => {\n this.hidePopup();\n if (cfg.autoplayOnContinue) this.safePlay();\n });\n\n el.classList.remove('hp:hidden');\n el.classList.add('hp:flex');\n }\n}\n","import { MarkProgress, type MarkersPlayerContext } from './MarkProgress';\nimport type { MarkersOptions } from '../../types';\n\nexport function installMarkers(ctx: MarkersPlayerContext, options: MarkersOptions): MarkProgress {\n return new MarkProgress(ctx, options);\n}\n\nexport { MarkProgress };\nexport type { MarkersPlayerContext };\n"],"names":["POPUP_DEFAULTS","PING_DEFAULTS","MarkProgress","ctx","options","__publicField","duration","m","el","now","key","last","popupCfg","idx","a","b","closeBtn","_a","url","baseUrl","w","fn","err","overlay","panel","createIcon","mediaWrap","img","textEl","linkEl","continueBtn","_b","cfg","isRich","newClose","newCont","installMarkers"],"mappings":"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"}
1
+ {"version":3,"file":"markers-Dr4-CCxE.js","sources":["../../src/plugins/markers/MarkProgress.ts","../../src/plugins/markers/index.ts"],"sourcesContent":["import { createIcon } from '../../icons/Icon';\nimport type { MarkerItem, MarkerPingOptions, MarkerPopupOptions, MarkersOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\n\nexport interface MarkersPlayerContext {\n videoEl: HTMLVideoElement;\n /** Popup overlay'in ekleneceği katman (shadow root içinde, video üzerinde). */\n overlayContainerEl: HTMLElement;\n /** Seek bar üzerinde işaretçi çizmek için — SeekBar.addMarker ile aynı imza. */\n addSeekBarMarker(ratio: number, extraClass?: string): HTMLDivElement;\n i18n: HopeLocaleStrings;\n}\n\ninterface NormalizedMarker extends Required<Pick<MarkerItem, 'time'>> {\n idx: number;\n color?: string;\n label: string;\n pauseOnHit: boolean;\n once: boolean;\n tolerance: number;\n cooldownMs: number;\n action?: MarkerItem['action'];\n popup: MarkerPopupOptions | null;\n pingUrl: string;\n el?: HTMLElement;\n}\n\nconst POPUP_DEFAULTS: Required<MarkerPopupOptions> = {\n enabled: false,\n mode: 'rich',\n text: '',\n imageUrl: '',\n imageAlt: '',\n linkUrl: '',\n // Boş bırakılıyor (sentinel) — gerçek varsayılan metin showPopup()'ta\n // `ctx.i18n.markerLearnMore`/`markerContinue`'dan okunuyor, dil\n // değişimini takip edebilsin diye burada SABİT bir dilde gömülü değil.\n linkText: '',\n continueText: '',\n showContinue: true,\n showClose: true,\n autoplayOnClose: true,\n autoplayOnContinue: true,\n};\n\nconst PING_DEFAULTS: Required<MarkerPingOptions> = { enabled: false, url: '', method: 'GET', includeMarker: false };\n\n/** Zaman tabanlı seek bar işaretçileri — seek/jump koruması, once/cooldown, popup/ping/aksiyon. */\nexport class MarkProgress {\n private readonly markers: NormalizedMarker[];\n private readonly popupGlobal: Required<MarkerPopupOptions>;\n private readonly pingGlobal: Required<MarkerPingOptions>;\n private readonly triggerOnSeek: boolean;\n private readonly seekJumpThresholdSec: number;\n private readonly seekIgnoreWindowMs: number;\n\n private hitSet = new Set<string>();\n private lastHitAt = new Map<string, number>();\n private lastTime = 0;\n private isSeeking = false;\n private ignoreUntilTs = 0;\n private popupEl: HTMLElement | null = null;\n\n constructor(\n private readonly ctx: MarkersPlayerContext,\n options: MarkersOptions\n ) {\n this.triggerOnSeek = options.triggerOnSeek === true;\n this.seekJumpThresholdSec = options.seekJumpThresholdSec ?? 1;\n this.seekIgnoreWindowMs = options.seekIgnoreWindowMs ?? 250;\n this.popupGlobal = { ...POPUP_DEFAULTS, ...options.popup };\n this.pingGlobal = { ...PING_DEFAULTS, ...options.ping };\n\n this.markers = (options.items || [])\n .map((m, idx) => this.normalize(m, idx))\n .filter((m) => Number.isFinite(m.time) && m.time >= 0)\n .sort((a, b) => a.time - b.time);\n\n ctx.videoEl.addEventListener('loadedmetadata', this.onLoadedMetadata);\n ctx.videoEl.addEventListener('timeupdate', this.onTimeUpdate);\n ctx.videoEl.addEventListener('seeking', this.onSeeking);\n ctx.videoEl.addEventListener('seeked', this.onSeeked);\n\n if (ctx.videoEl.readyState >= 1) this.onLoadedMetadata();\n }\n\n /** Popup lazy oluşturulup yeniden kullanılıyor (`ensurePopup`) — zaten açıksa close butonunun statik etiketini tazeler. */\n refreshLabels(): void {\n const closeBtn = this.popupEl?.querySelector('button') as HTMLButtonElement | null;\n if (closeBtn) {\n closeBtn.setAttribute('aria-label', this.ctx.i18n.close);\n }\n }\n\n destroy(): void {\n this.ctx.videoEl.removeEventListener('loadedmetadata', this.onLoadedMetadata);\n this.ctx.videoEl.removeEventListener('timeupdate', this.onTimeUpdate);\n this.ctx.videoEl.removeEventListener('seeking', this.onSeeking);\n this.ctx.videoEl.removeEventListener('seeked', this.onSeeked);\n this.markers.forEach((m) => m.el?.remove());\n this.popupEl?.remove();\n this.popupEl = null;\n this.hitSet.clear();\n this.lastHitAt.clear();\n }\n\n private normalize(m: MarkerItem, idx: number): NormalizedMarker {\n return {\n idx,\n time: Number(m.time),\n color: m.color,\n label: m.label ?? '',\n pauseOnHit: m.pauseOnHit ?? true,\n once: m.once ?? true,\n tolerance: m.tolerance ?? 0.25,\n cooldownMs: m.cooldownMs ?? 600,\n action: m.action,\n popup: m.popup ?? null,\n pingUrl: m.pingUrl ?? '',\n };\n }\n\n private readonly onLoadedMetadata = (): void => {\n const duration = this.ctx.videoEl.duration;\n if (!Number.isFinite(duration) || duration <= 0) return;\n\n this.markers.forEach((m) => {\n if (m.el) return;\n const el = this.ctx.addSeekBarMarker(m.time / duration);\n if (m.color) el.style.backgroundColor = m.color;\n if (m.label) el.title = m.label;\n m.el = el;\n });\n\n this.lastTime = this.ctx.videoEl.currentTime || 0;\n };\n\n private readonly onSeeking = (): void => {\n this.isSeeking = true;\n this.ignoreUntilTs = Date.now() + this.seekIgnoreWindowMs;\n this.lastTime = this.ctx.videoEl.currentTime || 0;\n };\n\n private readonly onSeeked = (): void => {\n this.lastTime = this.ctx.videoEl.currentTime || 0;\n this.isSeeking = false;\n this.ignoreUntilTs = Date.now() + this.seekIgnoreWindowMs;\n };\n\n private readonly onTimeUpdate = (): void => {\n const now = Date.now();\n if (now < this.ignoreUntilTs) return;\n if (this.isSeeking) return;\n\n const t = this.ctx.videoEl.currentTime;\n if (!Number.isFinite(t)) return;\n\n const jumped = Math.abs(t - this.lastTime) >= this.seekJumpThresholdSec;\n if (jumped && !this.triggerOnSeek) {\n this.lastTime = t;\n return;\n }\n\n for (const m of this.markers) {\n const key = `${m.time}-${m.idx}`;\n if (m.once && this.hitSet.has(key)) continue;\n if (!m.once) {\n const last = this.lastHitAt.get(key) || 0;\n if (now - last < m.cooldownMs) continue;\n }\n\n const crossed = this.lastTime < m.time && t >= m.time - m.tolerance;\n if (!crossed) continue;\n\n if (m.once) this.hitSet.add(key);\n else this.lastHitAt.set(key, now);\n\n if (m.pauseOnHit) this.ctx.videoEl.pause();\n\n this.firePing(m);\n this.fireAction(m);\n\n const popupCfg = m.popup ? { ...this.popupGlobal, ...m.popup } : this.popupGlobal;\n if (popupCfg.enabled) {\n this.ctx.videoEl.pause();\n this.showPopup(popupCfg);\n }\n break;\n }\n\n this.lastTime = t;\n };\n\n private resolveUrlTemplate(url: string, m: NormalizedMarker): string {\n if (!url) return '';\n return url.replaceAll('{time}', encodeURIComponent(String(m.time))).replaceAll('{label}', encodeURIComponent(m.label));\n }\n\n private firePing(m: NormalizedMarker): void {\n const baseUrl = m.pingUrl || this.pingGlobal.url;\n const url = this.resolveUrlTemplate(baseUrl, m);\n if (!this.pingGlobal.enabled || !url) return;\n\n try {\n if (this.pingGlobal.method === 'POST') {\n fetch(url, {\n method: 'POST',\n keepalive: true,\n headers: this.pingGlobal.includeMarker ? { 'Content-Type': 'application/json' } : undefined,\n body: this.pingGlobal.includeMarker ? JSON.stringify({ time: m.time, label: m.label, ts: Date.now() }) : undefined,\n }).catch(() => {});\n } else {\n fetch(url, { method: 'GET', keepalive: true }).catch(() => {});\n }\n } catch {\n /* no-op */\n }\n }\n\n private fireAction(m: NormalizedMarker): void {\n const a = m.action;\n if (!a) return;\n\n if (a.type === 'log') {\n console.log('[HopePlayer markers]', a.name || 'marker_hit', { time: m.time, label: m.label }, a.payload);\n return;\n }\n\n if (a.type === 'datalayer') {\n try {\n const w = window as unknown as { dataLayer?: unknown[] };\n w.dataLayer = w.dataLayer || [];\n w.dataLayer.push({\n event: 'HopePlayerVideoEvents',\n trigger: a.name || 'marker_hit',\n marker: { time: m.time, label: m.label, color: m.color },\n payload: a.payload ?? {},\n ts: Date.now(),\n });\n } catch {\n /* no-op */\n }\n return;\n }\n\n if (a.type === 'custom') {\n const fn = a.name ? (window as unknown as Record<string, unknown>)[a.name] : null;\n if (typeof fn === 'function') {\n try {\n (fn as (ctx: unknown) => void)({ marker: m, payload: a.payload });\n } catch (err) {\n console.warn('[HopePlayer markers] custom action fonksiyonu hata verdi:', err);\n }\n } else {\n console.warn('[HopePlayer markers] custom action fonksiyonu bulunamadı: window.' + a.name);\n }\n }\n }\n\n private ensurePopup(): HTMLElement {\n if (this.popupEl) return this.popupEl;\n\n const overlay = document.createElement('div');\n overlay.setAttribute('part', 'marker-popup');\n overlay.className = 'hp:hidden hp:absolute hp:inset-0 hp:z-30 hp:items-center hp:justify-center hp:bg-black/70';\n\n const panel = document.createElement('div');\n panel.className = 'hp:relative hp:max-w-[85%] hp:bg-surface-elev hp:text-on-surface hp:rounded-lg hp:p-4 hp:text-center hp:shadow-xl';\n panel.setAttribute('role', 'dialog');\n panel.setAttribute('aria-modal', 'true');\n\n const closeBtn = document.createElement('button');\n closeBtn.type = 'button';\n closeBtn.setAttribute('aria-label', this.ctx.i18n.close);\n closeBtn.className = 'hp:absolute hp:top-1 hp:right-1 hp:w-6 hp:h-6 hp:flex hp:items-center hp:justify-center hp:bg-transparent hp:border-0 hp:cursor-pointer hp:text-on-surface';\n closeBtn.appendChild(createIcon('close', 'hp:text-sm'));\n\n const mediaWrap = document.createElement('div');\n mediaWrap.className = 'hp:hidden hp:mb-2';\n const img = document.createElement('img');\n img.className = 'hp:max-w-full hp:rounded';\n mediaWrap.appendChild(img);\n\n const textEl = document.createElement('div');\n textEl.className = 'hp:text-sm hp:mb-2';\n\n const linkEl = document.createElement('a');\n linkEl.target = '_blank';\n linkEl.rel = 'noopener noreferrer';\n linkEl.className = 'hp:hidden hp:text-accent hp:underline hp:text-sm hp:block hp:mb-2';\n\n const continueBtn = document.createElement('button');\n continueBtn.type = 'button';\n continueBtn.className = 'hp:hidden hp:px-4 hp:py-1.5 hp:rounded hp:bg-accent hp:text-on-accent hp:border-0 hp:cursor-pointer hp:text-sm';\n\n panel.append(closeBtn, mediaWrap, textEl, linkEl, continueBtn);\n overlay.appendChild(panel);\n this.ctx.overlayContainerEl.appendChild(overlay);\n this.popupEl = overlay;\n return overlay;\n }\n\n private hidePopup(): void {\n this.popupEl?.classList.add('hp:hidden');\n this.popupEl?.classList.remove('hp:flex');\n }\n\n private safePlay(): void {\n void this.ctx.videoEl.play().catch(() => {});\n }\n\n private showPopup(cfg: Required<MarkerPopupOptions>): void {\n const el = this.ensurePopup();\n const textEl = el.querySelector('div.hp\\\\:text-sm.hp\\\\:mb-2:not(.hp\\\\:hidden)') as HTMLElement | null;\n const mediaWrap = el.querySelector('div.hp\\\\:mb-2') as HTMLElement | null;\n const img = el.querySelector('img') as HTMLImageElement | null;\n const linkEl = el.querySelector('a') as HTMLAnchorElement | null;\n const continueBtn = el.querySelectorAll('button')[1] as HTMLButtonElement | null;\n const closeBtn = el.querySelector('button') as HTMLButtonElement | null;\n\n if (closeBtn) closeBtn.style.display = cfg.showClose === false ? 'none' : '';\n if (textEl) textEl.textContent = cfg.text || '';\n\n const isRich = cfg.mode === 'rich';\n if (mediaWrap && img) {\n if (isRich && cfg.imageUrl) {\n mediaWrap.classList.remove('hp:hidden');\n img.src = cfg.imageUrl;\n img.alt = cfg.imageAlt || '';\n } else {\n mediaWrap.classList.add('hp:hidden');\n img.removeAttribute('src');\n }\n }\n\n if (linkEl) {\n if (isRich && cfg.linkUrl) {\n linkEl.classList.remove('hp:hidden');\n linkEl.href = cfg.linkUrl;\n linkEl.textContent = cfg.linkText || this.ctx.i18n.markerLearnMore;\n } else {\n linkEl.classList.add('hp:hidden');\n linkEl.removeAttribute('href');\n }\n }\n\n if (continueBtn) {\n if (cfg.showContinue) {\n continueBtn.classList.remove('hp:hidden');\n continueBtn.textContent = cfg.continueText || this.ctx.i18n.markerContinue;\n } else {\n continueBtn.classList.add('hp:hidden');\n }\n }\n\n const newClose = closeBtn?.cloneNode(true) as HTMLButtonElement | undefined;\n if (closeBtn && newClose) closeBtn.replaceWith(newClose);\n const newCont = continueBtn?.cloneNode(true) as HTMLButtonElement | undefined;\n if (continueBtn && newCont) continueBtn.replaceWith(newCont);\n\n newClose?.addEventListener('click', () => {\n this.hidePopup();\n if (cfg.autoplayOnClose) this.safePlay();\n });\n newCont?.addEventListener('click', () => {\n this.hidePopup();\n if (cfg.autoplayOnContinue) this.safePlay();\n });\n\n el.classList.remove('hp:hidden');\n el.classList.add('hp:flex');\n }\n}\n","import { MarkProgress, type MarkersPlayerContext } from './MarkProgress';\nimport type { MarkersOptions } from '../../types';\n\nexport function installMarkers(ctx: MarkersPlayerContext, options: MarkersOptions): MarkProgress {\n return new MarkProgress(ctx, options);\n}\n\nexport { MarkProgress };\nexport type { MarkersPlayerContext };\n"],"names":["POPUP_DEFAULTS","PING_DEFAULTS","MarkProgress","ctx","options","__publicField","duration","m","el","now","key","last","popupCfg","idx","a","b","closeBtn","_a","url","baseUrl","w","fn","err","overlay","panel","createIcon","mediaWrap","img","textEl","linkEl","continueBtn","_b","cfg","isRich","newClose","newCont","installMarkers"],"mappings":"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"}