@hopeplayer/core 1.4.0 → 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 (88) hide show
  1. package/dist/HopePlayerElement.d.ts +18 -2
  2. package/dist/HopePlayerElement.d.ts.map +1 -1
  3. package/dist/chunks/NativeEme-CXosVcw8.js +80 -0
  4. package/dist/chunks/NativeEme-CXosVcw8.js.map +1 -0
  5. package/dist/chunks/{accessibility-DeUIoAda.js → accessibility-DFx4CE0H.js} +9 -8
  6. package/dist/chunks/{accessibility-DeUIoAda.js.map → accessibility-DFx4CE0H.js.map} +1 -1
  7. package/dist/chunks/{ads-CdWbE9aD.js → ads-C4tDPsUs.js} +3 -3
  8. package/dist/chunks/ads-C4tDPsUs.js.map +1 -0
  9. package/dist/chunks/analytics-DEjTAJO9.js +281 -0
  10. package/dist/chunks/analytics-DEjTAJO9.js.map +1 -0
  11. package/dist/chunks/{cast-BQ-suTcF.js → cast-Baxvu76A.js} +2 -2
  12. package/dist/chunks/{cast-BQ-suTcF.js.map → cast-Baxvu76A.js.map} +1 -1
  13. package/dist/chunks/dash-CWjy-y7B.js +22 -0
  14. package/dist/chunks/dash-CWjy-y7B.js.map +1 -0
  15. package/dist/chunks/{history-DAbqEhNB.js → history-CvydU0aN.js} +2 -2
  16. package/dist/chunks/{history-DAbqEhNB.js.map → history-CvydU0aN.js.map} +1 -1
  17. package/dist/chunks/keySystems-CNzjRq6e.js +70 -0
  18. package/dist/chunks/keySystems-CNzjRq6e.js.map +1 -0
  19. package/dist/chunks/{markers-B04NMI79.js → markers-Dr4-CCxE.js} +2 -2
  20. package/dist/chunks/{markers-B04NMI79.js.map → markers-Dr4-CCxE.js.map} +1 -1
  21. package/dist/chunks/{player-D7WQxMzr.js → player-DV4Hf5Cw.js} +1230 -997
  22. package/dist/chunks/player-DV4Hf5Cw.js.map +1 -0
  23. package/dist/chunks/{playlist-C6Mh9BE8.js → playlist-DJsdK6xm.js} +29 -21
  24. package/dist/chunks/playlist-DJsdK6xm.js.map +1 -0
  25. package/dist/chunks/pluginHost-GxNfyP5E.js +566 -0
  26. package/dist/chunks/pluginHost-GxNfyP5E.js.map +1 -0
  27. package/dist/chunks/{redirectScreen-5HAVRtxe.js → redirectScreen-BT_26-5g.js} +2 -2
  28. package/dist/chunks/{redirectScreen-5HAVRtxe.js.map → redirectScreen-BT_26-5g.js.map} +1 -1
  29. package/dist/chunks/{rewardedUnlock-CGhQyWOk.js → rewardedUnlock-jFOdzfSq.js} +2 -2
  30. package/dist/chunks/{rewardedUnlock-CGhQyWOk.js.map → rewardedUnlock-jFOdzfSq.js.map} +1 -1
  31. package/dist/chunks/{segments-gCPrWRig.js → segments--hl_QVrI.js} +2 -2
  32. package/dist/chunks/{segments-gCPrWRig.js.map → segments--hl_QVrI.js.map} +1 -1
  33. package/dist/chunks/{skipSegments-BbWzPpXz.js → skipSegments-vJMhdiJn.js} +2 -2
  34. package/dist/chunks/{skipSegments-BbWzPpXz.js.map → skipSegments-vJMhdiJn.js.map} +1 -1
  35. package/dist/chunks/{spriteThumbnails-B7oDZFTo.js → spriteThumbnails-BoxVY--_.js} +76 -53
  36. package/dist/chunks/spriteThumbnails-BoxVY--_.js.map +1 -0
  37. package/dist/chunks/{statsPanel-DSClIwA3.js → statsPanel-D0DtoFgS.js} +2 -2
  38. package/dist/chunks/statsPanel-D0DtoFgS.js.map +1 -0
  39. package/dist/chunks/{story-BLBij82f.js → story-BRkhSDhR.js} +2 -2
  40. package/dist/chunks/{story-BLBij82f.js.map → story-BRkhSDhR.js.map} +1 -1
  41. package/dist/controls/SeekBar.d.ts.map +1 -1
  42. package/dist/drm/NativeEme.d.ts +23 -0
  43. package/dist/drm/NativeEme.d.ts.map +1 -0
  44. package/dist/drm/keySystems.d.ts +18 -0
  45. package/dist/drm/keySystems.d.ts.map +1 -0
  46. package/dist/hls/SourceManager.d.ts +31 -5
  47. package/dist/hls/SourceManager.d.ts.map +1 -1
  48. package/dist/hls/dashEngine.d.ts +85 -0
  49. package/dist/hls/dashEngine.d.ts.map +1 -0
  50. package/dist/hls/sourceGroups.d.ts.map +1 -1
  51. package/dist/hope-player.js +1 -1
  52. package/dist/i18n/locales/en.d.ts.map +1 -1
  53. package/dist/i18n/locales/tr.d.ts.map +1 -1
  54. package/dist/i18n/types.d.ts +3 -0
  55. package/dist/i18n/types.d.ts.map +1 -1
  56. package/dist/index.d.ts +2 -2
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/keyboard/KeyboardController.d.ts +14 -0
  59. package/dist/keyboard/KeyboardController.d.ts.map +1 -1
  60. package/dist/plugin-api/PluginAds.d.ts +61 -0
  61. package/dist/plugin-api/PluginAds.d.ts.map +1 -0
  62. package/dist/plugin-api/PluginHost.d.ts +6 -0
  63. package/dist/plugin-api/PluginHost.d.ts.map +1 -1
  64. package/dist/plugin-api/types.d.ts +39 -0
  65. package/dist/plugin-api/types.d.ts.map +1 -1
  66. package/dist/plugins/accessibility/Accessibility.d.ts.map +1 -1
  67. package/dist/plugins/ads/AdsController.d.ts +2 -0
  68. package/dist/plugins/ads/AdsController.d.ts.map +1 -1
  69. package/dist/plugins/analytics/QoeTracker.d.ts +71 -0
  70. package/dist/plugins/analytics/QoeTracker.d.ts.map +1 -0
  71. package/dist/plugins/analytics/index.d.ts +6 -0
  72. package/dist/plugins/analytics/index.d.ts.map +1 -0
  73. package/dist/plugins/playlist/PlaylistRunner.d.ts +2 -0
  74. package/dist/plugins/playlist/PlaylistRunner.d.ts.map +1 -1
  75. package/dist/plugins/sprite-thumbnails/SpriteThumbnails.d.ts +8 -0
  76. package/dist/plugins/sprite-thumbnails/SpriteThumbnails.d.ts.map +1 -1
  77. package/dist/screens/ErrorScreen.d.ts +1 -1
  78. package/dist/screens/ErrorScreen.d.ts.map +1 -1
  79. package/dist/types/index.d.ts +156 -4
  80. package/dist/types/index.d.ts.map +1 -1
  81. package/package.json +2 -1
  82. package/dist/chunks/ads-CdWbE9aD.js.map +0 -1
  83. package/dist/chunks/player-D7WQxMzr.js.map +0 -1
  84. package/dist/chunks/playlist-C6Mh9BE8.js.map +0 -1
  85. package/dist/chunks/pluginHost-DjvLmMYZ.js +0 -376
  86. package/dist/chunks/pluginHost-DjvLmMYZ.js.map +0 -1
  87. package/dist/chunks/spriteThumbnails-B7oDZFTo.js.map +0 -1
  88. package/dist/chunks/statsPanel-DSClIwA3.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"skipSegments-BbWzPpXz.js","sources":["../../src/plugins/skip-segments/SkipSegments.ts","../../src/plugins/skip-segments/index.ts"],"sourcesContent":["import type { SkipSegment, SkipSegmentType } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\nimport { createIcon } from '../../icons/Icon';\nimport { vodSeekTarget } from '../../utils/seek-by';\n\nexport interface SkipSegmentsPlayerContext {\n hostEl: HTMLElement;\n videoEl: HTMLVideoElement;\n overlayContainerEl: HTMLElement;\n isAdActive(): boolean;\n i18n: HopeLocaleStrings;\n}\n\n/** Bölüm sonuna bu kadar kala buton kalkar — sona yaklaşırken bir an görünüp kaybolmasın. */\nconst END_MARGIN_SEC = 0.25;\n\ninterface Active {\n index: number;\n segment: SkipSegment;\n end: number;\n /** Butonun göründüğü video zamanı — `hideAfter` / `autoSkip` geri sayımı video zamanıyla işler (duraklatınca durur). */\n shownAt: number;\n /** Kullanıcı bölüme sararak girdi ya da bölüm içinde geri sardı → bu gösterimde otomatik atlama yok. */\n autoCancelled: boolean;\n}\n\n/**\n * \"İntroyu atla\" / \"Özeti atla\" / \"Jeneriği atla\": bölüm oynarken köşede bir buton, basınca bölümün sonuna atlar.\n * `autoSkip` ile basılmadan (isteğe bağlı geri sayımla) atlar; `hideAfter` ile bir süre sonra çekilir, kontroller\n * açılınca geri gelir. Reklam sırasında görünmez. `hp:skip` (`skip`) iptal edilebilir.\n */\nexport class SkipSegments {\n private active: Active | null = null;\n private button: HTMLButtonElement | null = null;\n private labelEl: HTMLSpanElement | null = null;\n /** Kullanıcının (bizim değil) yaptığı sarma — bir sonraki timeupdate'te işlenir. */\n private userSeeked = false;\n private ownSeek = false;\n\n constructor(\n private readonly ctx: SkipSegmentsPlayerContext,\n private readonly segments: SkipSegment[]\n ) {\n const v = ctx.videoEl;\n v.addEventListener('timeupdate', this.update);\n v.addEventListener('seeking', this.onSeeking);\n v.addEventListener('seeked', this.update);\n v.addEventListener('loadstart', this.onSourceChange);\n ctx.hostEl.addEventListener('hp:adstart', this.update);\n ctx.hostEl.addEventListener('hp:adend', this.update);\n this.update();\n }\n\n destroy(): void {\n const v = this.ctx.videoEl;\n v.removeEventListener('timeupdate', this.update);\n v.removeEventListener('seeking', this.onSeeking);\n v.removeEventListener('seeked', this.update);\n v.removeEventListener('loadstart', this.onSourceChange);\n this.ctx.hostEl.removeEventListener('hp:adstart', this.update);\n this.ctx.hostEl.removeEventListener('hp:adend', this.update);\n this.hide();\n }\n\n refreshLabels(): void {\n if (this.active && this.labelEl) this.labelEl.textContent = this.label(this.active.segment);\n }\n\n private label(s: SkipSegment): string {\n if (s.label) return s.label;\n const t = this.ctx.i18n;\n const byType: Record<SkipSegmentType, string> = { intro: t.skipIntro, recap: t.skipRecap, credits: t.skipCredits, custom: t.skipSegment };\n return byType[s.type ?? 'intro'] ?? t.skipSegment;\n }\n\n /** Bölümün sonu: `end` yoksa videonun sonu (süre bilinmiyorsa bölüm yok sayılır). */\n private endOf(s: SkipSegment): number | null {\n if (Number.isFinite(s.end)) return s.end!;\n const d = this.ctx.videoEl.duration;\n return Number.isFinite(d) && d > 0 ? d : null;\n }\n\n private readonly onSeeking = (): void => {\n if (this.ownSeek) this.ownSeek = false;\n else this.userSeeked = true;\n };\n\n private readonly onSourceChange = (): void => {\n this.hide();\n this.userSeeked = false;\n };\n\n private readonly update = (): void => {\n const v = this.ctx.videoEl;\n const t = v.currentTime;\n const seeked = this.userSeeked;\n this.userSeeked = false;\n\n let found: { index: number; segment: SkipSegment; end: number } | null = null;\n if (!this.ctx.isAdActive()) {\n for (let i = 0; i < this.segments.length; i++) {\n const s = this.segments[i]!;\n const end = this.endOf(s);\n if (end === null || !Number.isFinite(s.start)) continue;\n const from = Math.max(s.start, Number.isFinite(s.showFrom) ? s.showFrom! : s.start);\n const until = Number.isFinite(s.showUntil) ? Math.min(s.showUntil!, end) : end;\n if (t >= from && t < until - END_MARGIN_SEC) {\n found = { index: i, segment: s, end };\n break;\n }\n }\n }\n\n if (!found) {\n this.hide();\n return;\n }\n if (this.active?.index !== found.index) {\n this.hide();\n this.active = { ...found, shownAt: t, autoCancelled: seeked };\n this.show();\n this.emit('shown');\n } else if (seeked) {\n // Bölüm içinde sarma: geri sardıysa (kullanıcı bölümü izlemek istiyor) otomatik atlama bu gösterimde kapanır.\n this.active.autoCancelled = true;\n this.active.shownAt = Math.min(this.active.shownAt, t);\n }\n this.tick(t);\n };\n\n /** `hideAfter` (çekilme) ve `autoSkip` geri sayımı. */\n private tick(t: number): void {\n const a = this.active;\n if (!a || !this.button) return;\n const elapsed = Math.max(0, t - a.shownAt);\n const hideAfter = a.segment.hideAfter ?? 0;\n this.button.toggleAttribute('data-faded', hideAfter > 0 && elapsed >= hideAfter);\n\n const auto = a.segment.autoSkip;\n if (!auto || a.autoCancelled) {\n this.button.removeAttribute('data-auto');\n return;\n }\n const delay = auto === true ? 0 : Math.max(0, auto);\n if (elapsed >= delay) {\n this.skip('auto');\n return;\n }\n this.button.setAttribute('data-auto', '');\n this.button.style.setProperty('--hp-skip-progress', String(delay ? elapsed / delay : 1));\n }\n\n private show(): void {\n const a = this.active!;\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'hp-skip-segment';\n btn.setAttribute('part', 'skip-segment');\n btn.setAttribute('data-position', a.segment.position ?? 'bottom-right');\n btn.setAttribute('data-type', a.segment.type ?? 'intro');\n const label = document.createElement('span');\n label.className = 'hp-skip-segment-label';\n label.textContent = this.label(a.segment);\n btn.append(label, createIcon('skip-forward', 'hp-skip-segment-icon'));\n btn.addEventListener('click', () => this.skip('click'));\n // Oynat/duraklat ve çift tık tam ekran alttaki video alanına geçmesin.\n for (const ev of ['pointerdown', 'pointerup', 'click', 'dblclick'] as const) btn.addEventListener(ev, (e) => e.stopPropagation());\n this.ctx.overlayContainerEl.appendChild(btn);\n this.button = btn;\n this.labelEl = label;\n }\n\n private hide(): void {\n this.button?.remove();\n this.button = null;\n this.labelEl = null;\n this.active = null;\n }\n\n private emit(state: 'shown' | 'skip', reason?: 'click' | 'auto'): boolean {\n const a = this.active!;\n return this.ctx.hostEl.dispatchEvent(\n new CustomEvent('hp:skip', {\n detail: { state, type: a.segment.type ?? 'intro', start: a.segment.start, end: a.end, reason },\n cancelable: state === 'skip',\n })\n );\n }\n\n private skip(reason: 'click' | 'auto'): void {\n const a = this.active;\n if (!a) return;\n const focused = !!this.button?.matches(':focus');\n if (!this.emit('skip', reason)) {\n // Entegratör kendisi halletti — bu gösterim için otomatik atlama tekrar tetiklenmesin.\n a.autoCancelled = true;\n this.button?.removeAttribute('data-auto');\n return;\n }\n const v = this.ctx.videoEl;\n this.hide();\n this.ownSeek = true;\n v.currentTime = vodSeekTarget(v, a.end);\n // Klavyeyle basıldıysa odak kaybolmasın — player'a dön (kısayollar çalışmaya devam etsin).\n if (focused) this.ctx.hostEl.focus({ preventScroll: true });\n }\n}\n","import { SkipSegments, type SkipSegmentsPlayerContext } from './SkipSegments';\nimport type { SkipSegment } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\nimport { definePlugin } from '../../plugin-api/registry';\n\nexport function installSkipSegments(ctx: SkipSegmentsPlayerContext, segments: SkipSegment[]): SkipSegments {\n return new SkipSegments(ctx, segments);\n}\n\n/** \"İntroyu atla\", herkese açık eklenti API'si üzerinden. */\nexport const skipSegmentsPlugin = definePlugin<SkipSegment[]>({\n name: 'hope:skip-segments',\n setup(player, segments) {\n const layer = player.ui.addLayer({ position: 'fill' });\n const skip = new SkipSegments(\n {\n hostEl: player.element,\n videoEl: player.video,\n overlayContainerEl: layer.el,\n isAdActive: () => player.isAdPlaying,\n i18n: player.labels as unknown as HopeLocaleStrings,\n },\n segments\n );\n player.onLocaleChange(() => skip.refreshLabels());\n return () => skip.destroy();\n },\n});\n\nexport { SkipSegments };\nexport type { SkipSegmentsPlayerContext };\n"],"names":["END_MARGIN_SEC","SkipSegments","ctx","segments","__publicField","seeked","found","i","s","end","from","until","_a","v","d","t","a","elapsed","hideAfter","auto","delay","btn","label","createIcon","ev","e","state","reason","focused","_b","vodSeekTarget","skipSegmentsPlugin","definePlugin","player","layer","skip"],"mappings":"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"}
1
+ {"version":3,"file":"skipSegments-vJMhdiJn.js","sources":["../../src/plugins/skip-segments/SkipSegments.ts","../../src/plugins/skip-segments/index.ts"],"sourcesContent":["import type { SkipSegment, SkipSegmentType } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\nimport { createIcon } from '../../icons/Icon';\nimport { vodSeekTarget } from '../../utils/seek-by';\n\nexport interface SkipSegmentsPlayerContext {\n hostEl: HTMLElement;\n videoEl: HTMLVideoElement;\n overlayContainerEl: HTMLElement;\n isAdActive(): boolean;\n i18n: HopeLocaleStrings;\n}\n\n/** Bölüm sonuna bu kadar kala buton kalkar — sona yaklaşırken bir an görünüp kaybolmasın. */\nconst END_MARGIN_SEC = 0.25;\n\ninterface Active {\n index: number;\n segment: SkipSegment;\n end: number;\n /** Butonun göründüğü video zamanı — `hideAfter` / `autoSkip` geri sayımı video zamanıyla işler (duraklatınca durur). */\n shownAt: number;\n /** Kullanıcı bölüme sararak girdi ya da bölüm içinde geri sardı → bu gösterimde otomatik atlama yok. */\n autoCancelled: boolean;\n}\n\n/**\n * \"İntroyu atla\" / \"Özeti atla\" / \"Jeneriği atla\": bölüm oynarken köşede bir buton, basınca bölümün sonuna atlar.\n * `autoSkip` ile basılmadan (isteğe bağlı geri sayımla) atlar; `hideAfter` ile bir süre sonra çekilir, kontroller\n * açılınca geri gelir. Reklam sırasında görünmez. `hp:skip` (`skip`) iptal edilebilir.\n */\nexport class SkipSegments {\n private active: Active | null = null;\n private button: HTMLButtonElement | null = null;\n private labelEl: HTMLSpanElement | null = null;\n /** Kullanıcının (bizim değil) yaptığı sarma — bir sonraki timeupdate'te işlenir. */\n private userSeeked = false;\n private ownSeek = false;\n\n constructor(\n private readonly ctx: SkipSegmentsPlayerContext,\n private readonly segments: SkipSegment[]\n ) {\n const v = ctx.videoEl;\n v.addEventListener('timeupdate', this.update);\n v.addEventListener('seeking', this.onSeeking);\n v.addEventListener('seeked', this.update);\n v.addEventListener('loadstart', this.onSourceChange);\n ctx.hostEl.addEventListener('hp:adstart', this.update);\n ctx.hostEl.addEventListener('hp:adend', this.update);\n this.update();\n }\n\n destroy(): void {\n const v = this.ctx.videoEl;\n v.removeEventListener('timeupdate', this.update);\n v.removeEventListener('seeking', this.onSeeking);\n v.removeEventListener('seeked', this.update);\n v.removeEventListener('loadstart', this.onSourceChange);\n this.ctx.hostEl.removeEventListener('hp:adstart', this.update);\n this.ctx.hostEl.removeEventListener('hp:adend', this.update);\n this.hide();\n }\n\n refreshLabels(): void {\n if (this.active && this.labelEl) this.labelEl.textContent = this.label(this.active.segment);\n }\n\n private label(s: SkipSegment): string {\n if (s.label) return s.label;\n const t = this.ctx.i18n;\n const byType: Record<SkipSegmentType, string> = { intro: t.skipIntro, recap: t.skipRecap, credits: t.skipCredits, custom: t.skipSegment };\n return byType[s.type ?? 'intro'] ?? t.skipSegment;\n }\n\n /** Bölümün sonu: `end` yoksa videonun sonu (süre bilinmiyorsa bölüm yok sayılır). */\n private endOf(s: SkipSegment): number | null {\n if (Number.isFinite(s.end)) return s.end!;\n const d = this.ctx.videoEl.duration;\n return Number.isFinite(d) && d > 0 ? d : null;\n }\n\n private readonly onSeeking = (): void => {\n if (this.ownSeek) this.ownSeek = false;\n else this.userSeeked = true;\n };\n\n private readonly onSourceChange = (): void => {\n this.hide();\n this.userSeeked = false;\n };\n\n private readonly update = (): void => {\n const v = this.ctx.videoEl;\n const t = v.currentTime;\n const seeked = this.userSeeked;\n this.userSeeked = false;\n\n let found: { index: number; segment: SkipSegment; end: number } | null = null;\n if (!this.ctx.isAdActive()) {\n for (let i = 0; i < this.segments.length; i++) {\n const s = this.segments[i]!;\n const end = this.endOf(s);\n if (end === null || !Number.isFinite(s.start)) continue;\n const from = Math.max(s.start, Number.isFinite(s.showFrom) ? s.showFrom! : s.start);\n const until = Number.isFinite(s.showUntil) ? Math.min(s.showUntil!, end) : end;\n if (t >= from && t < until - END_MARGIN_SEC) {\n found = { index: i, segment: s, end };\n break;\n }\n }\n }\n\n if (!found) {\n this.hide();\n return;\n }\n if (this.active?.index !== found.index) {\n this.hide();\n this.active = { ...found, shownAt: t, autoCancelled: seeked };\n this.show();\n this.emit('shown');\n } else if (seeked) {\n // Bölüm içinde sarma: geri sardıysa (kullanıcı bölümü izlemek istiyor) otomatik atlama bu gösterimde kapanır.\n this.active.autoCancelled = true;\n this.active.shownAt = Math.min(this.active.shownAt, t);\n }\n this.tick(t);\n };\n\n /** `hideAfter` (çekilme) ve `autoSkip` geri sayımı. */\n private tick(t: number): void {\n const a = this.active;\n if (!a || !this.button) return;\n const elapsed = Math.max(0, t - a.shownAt);\n const hideAfter = a.segment.hideAfter ?? 0;\n this.button.toggleAttribute('data-faded', hideAfter > 0 && elapsed >= hideAfter);\n\n const auto = a.segment.autoSkip;\n if (!auto || a.autoCancelled) {\n this.button.removeAttribute('data-auto');\n return;\n }\n const delay = auto === true ? 0 : Math.max(0, auto);\n if (elapsed >= delay) {\n this.skip('auto');\n return;\n }\n this.button.setAttribute('data-auto', '');\n this.button.style.setProperty('--hp-skip-progress', String(delay ? elapsed / delay : 1));\n }\n\n private show(): void {\n const a = this.active!;\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'hp-skip-segment';\n btn.setAttribute('part', 'skip-segment');\n btn.setAttribute('data-position', a.segment.position ?? 'bottom-right');\n btn.setAttribute('data-type', a.segment.type ?? 'intro');\n const label = document.createElement('span');\n label.className = 'hp-skip-segment-label';\n label.textContent = this.label(a.segment);\n btn.append(label, createIcon('skip-forward', 'hp-skip-segment-icon'));\n btn.addEventListener('click', () => this.skip('click'));\n // Oynat/duraklat ve çift tık tam ekran alttaki video alanına geçmesin.\n for (const ev of ['pointerdown', 'pointerup', 'click', 'dblclick'] as const) btn.addEventListener(ev, (e) => e.stopPropagation());\n this.ctx.overlayContainerEl.appendChild(btn);\n this.button = btn;\n this.labelEl = label;\n }\n\n private hide(): void {\n this.button?.remove();\n this.button = null;\n this.labelEl = null;\n this.active = null;\n }\n\n private emit(state: 'shown' | 'skip', reason?: 'click' | 'auto'): boolean {\n const a = this.active!;\n return this.ctx.hostEl.dispatchEvent(\n new CustomEvent('hp:skip', {\n detail: { state, type: a.segment.type ?? 'intro', start: a.segment.start, end: a.end, reason },\n cancelable: state === 'skip',\n })\n );\n }\n\n private skip(reason: 'click' | 'auto'): void {\n const a = this.active;\n if (!a) return;\n const focused = !!this.button?.matches(':focus');\n if (!this.emit('skip', reason)) {\n // Entegratör kendisi halletti — bu gösterim için otomatik atlama tekrar tetiklenmesin.\n a.autoCancelled = true;\n this.button?.removeAttribute('data-auto');\n return;\n }\n const v = this.ctx.videoEl;\n this.hide();\n this.ownSeek = true;\n v.currentTime = vodSeekTarget(v, a.end);\n // Klavyeyle basıldıysa odak kaybolmasın — player'a dön (kısayollar çalışmaya devam etsin).\n if (focused) this.ctx.hostEl.focus({ preventScroll: true });\n }\n}\n","import { SkipSegments, type SkipSegmentsPlayerContext } from './SkipSegments';\nimport type { SkipSegment } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\nimport { definePlugin } from '../../plugin-api/registry';\n\nexport function installSkipSegments(ctx: SkipSegmentsPlayerContext, segments: SkipSegment[]): SkipSegments {\n return new SkipSegments(ctx, segments);\n}\n\n/** \"İntroyu atla\", herkese açık eklenti API'si üzerinden. */\nexport const skipSegmentsPlugin = definePlugin<SkipSegment[]>({\n name: 'hope:skip-segments',\n setup(player, segments) {\n const layer = player.ui.addLayer({ position: 'fill' });\n const skip = new SkipSegments(\n {\n hostEl: player.element,\n videoEl: player.video,\n overlayContainerEl: layer.el,\n isAdActive: () => player.isAdPlaying,\n i18n: player.labels as unknown as HopeLocaleStrings,\n },\n segments\n );\n player.onLocaleChange(() => skip.refreshLabels());\n return () => skip.destroy();\n },\n});\n\nexport { SkipSegments };\nexport type { SkipSegmentsPlayerContext };\n"],"names":["END_MARGIN_SEC","SkipSegments","ctx","segments","__publicField","seeked","found","i","s","end","from","until","_a","v","d","t","a","elapsed","hideAfter","auto","delay","btn","label","createIcon","ev","e","state","reason","focused","_b","vodSeekTarget","skipSegmentsPlugin","definePlugin","player","layer","skip"],"mappings":";;;;AAcA,MAAMA,IAAiB;AAiBhB,MAAMC,EAAa;AAAA,EAQtB,YACqBC,GACAC,GACnB;AAVM,IAAAC,EAAA,gBAAwB;AACxB,IAAAA,EAAA,gBAAmC;AACnC,IAAAA,EAAA,iBAAkC;AAElC;AAAA,IAAAA,EAAA,oBAAa;AACb,IAAAA,EAAA,iBAAU;AA6CD,IAAAA,EAAA,mBAAY,MAAY;AACrC,MAAI,KAAK,UAAS,KAAK,UAAU,UACvB,aAAa;AAAA,IAC3B;AAEiB,IAAAA,EAAA,wBAAiB,MAAY;AAC1C,WAAK,KAAA,GACL,KAAK,aAAa;AAAA,IACtB;AAEiB,IAAAA,EAAA,gBAAS,MAAY;;AAElC,YAAM,IADI,KAAK,IAAI,QACP,aACNC,IAAS,KAAK;AACpB,WAAK,aAAa;AAElB,UAAIC,IAAqE;AACzE,UAAI,CAAC,KAAK,IAAI;AACV,iBAASC,IAAI,GAAGA,IAAI,KAAK,SAAS,QAAQA,KAAK;AAC3C,gBAAMC,IAAI,KAAK,SAASD,CAAC,GACnBE,IAAM,KAAK,MAAMD,CAAC;AACxB,cAAIC,MAAQ,QAAQ,CAAC,OAAO,SAASD,EAAE,KAAK,EAAG;AAC/C,gBAAME,IAAO,KAAK,IAAIF,EAAE,OAAO,OAAO,SAASA,EAAE,QAAQ,IAAIA,EAAE,WAAYA,EAAE,KAAK,GAC5EG,IAAQ,OAAO,SAASH,EAAE,SAAS,IAAI,KAAK,IAAIA,EAAE,WAAYC,CAAG,IAAIA;AAC3E,cAAI,KAAKC,KAAQ,IAAIC,IAAQX,GAAgB;AACzC,YAAAM,IAAQ,EAAE,OAAOC,GAAG,SAASC,GAAG,KAAAC,EAAA;AAChC;AAAA,UACJ;AAAA,QACJ;AAGJ,UAAI,CAACH,GAAO;AACR,aAAK,KAAA;AACL;AAAA,MACJ;AACA,QAAIM,IAAA,KAAK,WAAL,gBAAAA,EAAa,WAAUN,EAAM,SAC7B,KAAK,KAAA,GACL,KAAK,SAAS,EAAE,GAAGA,GAAO,SAAS,GAAG,eAAeD,EAAA,GACrD,KAAK,KAAA,GACL,KAAK,KAAK,OAAO,KACVA,MAEP,KAAK,OAAO,gBAAgB,IAC5B,KAAK,OAAO,UAAU,KAAK,IAAI,KAAK,OAAO,SAAS,CAAC,IAEzD,KAAK,KAAK,CAAC;AAAA,IACf;AAxFqB,SAAA,MAAAH,GACA,KAAA,WAAAC;AAEjB,UAAMU,IAAIX,EAAI;AACd,IAAAW,EAAE,iBAAiB,cAAc,KAAK,MAAM,GAC5CA,EAAE,iBAAiB,WAAW,KAAK,SAAS,GAC5CA,EAAE,iBAAiB,UAAU,KAAK,MAAM,GACxCA,EAAE,iBAAiB,aAAa,KAAK,cAAc,GACnDX,EAAI,OAAO,iBAAiB,cAAc,KAAK,MAAM,GACrDA,EAAI,OAAO,iBAAiB,YAAY,KAAK,MAAM,GACnD,KAAK,OAAA;AAAA,EACT;AAAA,EAEA,UAAgB;AACZ,UAAMW,IAAI,KAAK,IAAI;AACnB,IAAAA,EAAE,oBAAoB,cAAc,KAAK,MAAM,GAC/CA,EAAE,oBAAoB,WAAW,KAAK,SAAS,GAC/CA,EAAE,oBAAoB,UAAU,KAAK,MAAM,GAC3CA,EAAE,oBAAoB,aAAa,KAAK,cAAc,GACtD,KAAK,IAAI,OAAO,oBAAoB,cAAc,KAAK,MAAM,GAC7D,KAAK,IAAI,OAAO,oBAAoB,YAAY,KAAK,MAAM,GAC3D,KAAK,KAAA;AAAA,EACT;AAAA,EAEA,gBAAsB;AAClB,IAAI,KAAK,UAAU,KAAK,YAAS,KAAK,QAAQ,cAAc,KAAK,MAAM,KAAK,OAAO,OAAO;AAAA,EAC9F;AAAA,EAEQ,MAAML,GAAwB;AAClC,QAAIA,EAAE,MAAO,QAAOA,EAAE;AACtB,UAAM,IAAI,KAAK,IAAI;AAEnB,WADgD,EAAE,OAAO,EAAE,WAAW,OAAO,EAAE,WAAW,SAAS,EAAE,aAAa,QAAQ,EAAE,YAAA,EAC9GA,EAAE,QAAQ,OAAO,KAAK,EAAE;AAAA,EAC1C;AAAA;AAAA,EAGQ,MAAMA,GAA+B;AACzC,QAAI,OAAO,SAASA,EAAE,GAAG,UAAUA,EAAE;AACrC,UAAMM,IAAI,KAAK,IAAI,QAAQ;AAC3B,WAAO,OAAO,SAASA,CAAC,KAAKA,IAAI,IAAIA,IAAI;AAAA,EAC7C;AAAA;AAAA,EAmDQ,KAAKC,GAAiB;AAC1B,UAAMC,IAAI,KAAK;AACf,QAAI,CAACA,KAAK,CAAC,KAAK,OAAQ;AACxB,UAAMC,IAAU,KAAK,IAAI,GAAGF,IAAIC,EAAE,OAAO,GACnCE,IAAYF,EAAE,QAAQ,aAAa;AACzC,SAAK,OAAO,gBAAgB,cAAcE,IAAY,KAAKD,KAAWC,CAAS;AAE/E,UAAMC,IAAOH,EAAE,QAAQ;AACvB,QAAI,CAACG,KAAQH,EAAE,eAAe;AAC1B,WAAK,OAAO,gBAAgB,WAAW;AACvC;AAAA,IACJ;AACA,UAAMI,IAAQD,MAAS,KAAO,IAAI,KAAK,IAAI,GAAGA,CAAI;AAClD,QAAIF,KAAWG,GAAO;AAClB,WAAK,KAAK,MAAM;AAChB;AAAA,IACJ;AACA,SAAK,OAAO,aAAa,aAAa,EAAE,GACxC,KAAK,OAAO,MAAM,YAAY,sBAAsB,OAAOA,IAAQH,IAAUG,IAAQ,CAAC,CAAC;AAAA,EAC3F;AAAA,EAEQ,OAAa;AACjB,UAAMJ,IAAI,KAAK,QACTK,IAAM,SAAS,cAAc,QAAQ;AAC3C,IAAAA,EAAI,OAAO,UACXA,EAAI,YAAY,mBAChBA,EAAI,aAAa,QAAQ,cAAc,GACvCA,EAAI,aAAa,iBAAiBL,EAAE,QAAQ,YAAY,cAAc,GACtEK,EAAI,aAAa,aAAaL,EAAE,QAAQ,QAAQ,OAAO;AACvD,UAAMM,IAAQ,SAAS,cAAc,MAAM;AAC3C,IAAAA,EAAM,YAAY,yBAClBA,EAAM,cAAc,KAAK,MAAMN,EAAE,OAAO,GACxCK,EAAI,OAAOC,GAAOC,EAAW,gBAAgB,sBAAsB,CAAC,GACpEF,EAAI,iBAAiB,SAAS,MAAM,KAAK,KAAK,OAAO,CAAC;AAEtD,eAAWG,KAAM,CAAC,eAAe,aAAa,SAAS,UAAU,EAAY,CAAAH,EAAI,iBAAiBG,GAAI,CAACC,MAAMA,EAAE,iBAAiB;AAChI,SAAK,IAAI,mBAAmB,YAAYJ,CAAG,GAC3C,KAAK,SAASA,GACd,KAAK,UAAUC;AAAA,EACnB;AAAA,EAEQ,OAAa;;AACjB,KAAAV,IAAA,KAAK,WAAL,QAAAA,EAAa,UACb,KAAK,SAAS,MACd,KAAK,UAAU,MACf,KAAK,SAAS;AAAA,EAClB;AAAA,EAEQ,KAAKc,GAAyBC,GAAoC;AACtE,UAAMX,IAAI,KAAK;AACf,WAAO,KAAK,IAAI,OAAO;AAAA,MACnB,IAAI,YAAY,WAAW;AAAA,QACvB,QAAQ,EAAE,OAAAU,GAAO,MAAMV,EAAE,QAAQ,QAAQ,SAAS,OAAOA,EAAE,QAAQ,OAAO,KAAKA,EAAE,KAAK,QAAAW,EAAA;AAAA,QACtF,YAAYD,MAAU;AAAA,MAAA,CACzB;AAAA,IAAA;AAAA,EAET;AAAA,EAEQ,KAAKC,GAAgC;;AACzC,UAAMX,IAAI,KAAK;AACf,QAAI,CAACA,EAAG;AACR,UAAMY,IAAU,CAAC,GAAChB,IAAA,KAAK,WAAL,QAAAA,EAAa,QAAQ;AACvC,QAAI,CAAC,KAAK,KAAK,QAAQe,CAAM,GAAG;AAE5B,MAAAX,EAAE,gBAAgB,KAClBa,IAAA,KAAK,WAAL,QAAAA,EAAa,gBAAgB;AAC7B;AAAA,IACJ;AACA,UAAMhB,IAAI,KAAK,IAAI;AACnB,SAAK,KAAA,GACL,KAAK,UAAU,IACfA,EAAE,cAAciB,EAAcjB,GAAGG,EAAE,GAAG,GAElCY,UAAc,IAAI,OAAO,MAAM,EAAE,eAAe,IAAM;AAAA,EAC9D;AACJ;ACpMO,MAAMG,IAAqBC,EAA4B;AAAA,EAC1D,MAAM;AAAA,EACN,MAAMC,GAAQ9B,GAAU;AACpB,UAAM+B,IAAQD,EAAO,GAAG,SAAS,EAAE,UAAU,QAAQ,GAC/CE,IAAO,IAAIlC;AAAA,MACb;AAAA,QACI,QAAQgC,EAAO;AAAA,QACf,SAASA,EAAO;AAAA,QAChB,oBAAoBC,EAAM;AAAA,QAC1B,YAAY,MAAMD,EAAO;AAAA,QACzB,MAAMA,EAAO;AAAA,MAAA;AAAA,MAEjB9B;AAAA,IAAA;AAEJ,WAAA8B,EAAO,eAAe,MAAME,EAAK,cAAA,CAAe,GACzC,MAAMA,EAAK,QAAA;AAAA,EACtB;AACJ,CAAC;"}
@@ -1,9 +1,9 @@
1
- var E = Object.defineProperty;
2
- var y = (a, t, e) => t in a ? E(a, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : a[t] = e;
3
- var l = (a, t, e) => y(a, typeof t != "symbol" ? t + "" : t, e);
4
- import { f as x } from "./player-D7WQxMzr.js";
5
- const w = 8, f = /%(0(\d+))?d/;
6
- class M {
1
+ var w = Object.defineProperty;
2
+ var E = (u, t, e) => t in u ? w(u, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : u[t] = e;
3
+ var l = (u, t, e) => E(u, typeof t != "symbol" ? t + "" : t, e);
4
+ import { f as y } from "./player-DV4Hf5Cw.js";
5
+ const x = 8, v = /%(0(\d+))?d/;
6
+ class S {
7
7
  constructor(t, e) {
8
8
  l(this, "tooltip");
9
9
  l(this, "imageEl");
@@ -13,6 +13,10 @@ class M {
13
13
  l(this, "vttLoading", null);
14
14
  /** Çok parçalı modda otomatik hesaplanan sheet süresi (ilk sheet yüklenince). */
15
15
  l(this, "derivedSheetDuration", null);
16
+ /** `lowRes` sheet'i — LRU dışında, hep bellekte. */
17
+ l(this, "lowSheet", null);
18
+ /** Son çizilen asıl karenin genişliği (VTT'de `width` yok). */
19
+ l(this, "lastFrameWidth", 0);
16
20
  l(this, "warmed", !1);
17
21
  l(this, "hovering", !1);
18
22
  l(this, "lastClientX", 0);
@@ -30,8 +34,9 @@ class M {
30
34
  });
31
35
  /** İlk ihtiyaç anında (hover / oynatma) kaynağı hazırla — kurulumda hiçbir şey indirilmiyor. */
32
36
  l(this, "warm", () => {
37
+ var i;
33
38
  if (this.warmed || this.destroyed) return;
34
- if (this.warmed = !0, this.options.vtt) {
39
+ if (this.warmed = !0, (i = this.options.lowRes) != null && i.url && (this.lowSheet = this.createSheet(this.options.lowRes.url, () => this.hovering && this.scheduleRender())), this.options.vtt) {
35
40
  this.loadVtt();
36
41
  return;
37
42
  }
@@ -43,7 +48,7 @@ class M {
43
48
  destroy() {
44
49
  this.destroyed = !0, this.rafId !== null && cancelAnimationFrame(this.rafId), this.ctx.seekBar.el.removeEventListener("pointerenter", this.onPointerEnter), this.ctx.seekBar.el.removeEventListener("pointermove", this.onPointerMove), this.ctx.seekBar.el.removeEventListener("pointerleave", this.onPointerLeave), this.ctx.videoEl.removeEventListener("play", this.warm), this.tooltip.remove(), this.ctx.seekBar.suppressHoverTime("sprite", !1);
45
50
  for (const t of this.sheets.values()) t.img.src = "";
46
- this.sheets.clear();
51
+ this.lowSheet && (this.lowSheet.img.src = ""), this.sheets.clear();
47
52
  }
48
53
  scheduleRender() {
49
54
  this.rafId === null && (this.rafId = requestAnimationFrame(() => {
@@ -52,19 +57,22 @@ class M {
52
57
  }
53
58
  // ── çizim ──
54
59
  render() {
60
+ var h;
55
61
  if (!this.hovering || this.destroyed) return;
56
62
  const t = this.ctx.videoEl.duration;
57
63
  if (!Number.isFinite(t) || t <= 0) return;
58
64
  const e = this.ctx.seekBar.ratioAtClientX(this.lastClientX) * t;
59
- this.timeEl.textContent = x(e);
60
- const i = this.isNetworkEligible() ? this.frameAt(e, t) : null, s = this.scale();
61
- if (i) {
62
- const u = this.sheets.get(i.url), { naturalWidth: o, naturalHeight: d } = u.img;
63
- this.imageEl.style.display = "", this.imageEl.style.width = `${i.w * s}px`, this.imageEl.style.height = `${i.h * s}px`, this.imageEl.style.backgroundImage = `url("${i.url}")`, this.imageEl.style.backgroundSize = `${o * s}px ${d * s}px`, this.imageEl.style.backgroundPosition = `${-i.x * s}px ${-i.y * s}px`;
65
+ this.timeEl.textContent = y(e);
66
+ const i = this.isNetworkEligible() ? this.frameAt(e, t) : null;
67
+ i && (this.lastFrameWidth = i.w);
68
+ const s = i ?? this.lowResFrameAt(e, t), n = i ? this.sheets.get(i.url).img : (h = this.lowSheet) == null ? void 0 : h.img;
69
+ if (s && n) {
70
+ const d = (this.options.displayWidth ?? (i ? i.w : this.options.width || this.lastFrameWidth || s.w)) * this.scale(), c = d / s.w;
71
+ this.imageEl.style.display = "", this.imageEl.toggleAttribute("data-lowres", !i), this.imageEl.style.width = `${d}px`, this.imageEl.style.height = `${s.h * c}px`, this.imageEl.style.backgroundImage = `url("${s.url}")`, this.imageEl.style.backgroundSize = `${n.naturalWidth * c}px ${n.naturalHeight * c}px`, this.imageEl.style.backgroundPosition = `${-s.x * c}px ${-s.y * c}px`;
64
72
  } else this.imageEl.style.backgroundImage || (this.imageEl.style.display = "none");
65
73
  this.tooltip.setAttribute("data-visible", "");
66
- const n = this.ctx.seekBar.el.getBoundingClientRect(), r = this.tooltip.offsetWidth, h = Math.min(Math.max(this.lastClientX - n.left - r / 2, 0), Math.max(n.width - r, 0));
67
- this.tooltip.style.transform = `translateX(${h}px)`;
74
+ const r = this.ctx.seekBar.el.getBoundingClientRect(), o = this.tooltip.offsetWidth, a = Math.min(Math.max(this.lastClientX - r.left - o / 2, 0), Math.max(r.width - o, 0));
75
+ this.tooltip.style.transform = `translateX(${a}px)`;
68
76
  }
69
77
  scale() {
70
78
  const t = this.options.responsive, e = this.ctx.playerWidth();
@@ -76,13 +84,21 @@ class M {
76
84
  return e === void 0 || e >= (this.options.downlink ?? 2) || i;
77
85
  }
78
86
  // ── kare çözümleme ──
87
+ /** `lowRes` sheet'inden saniyedeki kare (hazır değilse null). */
88
+ lowResFrameAt(t, e) {
89
+ var h;
90
+ const i = this.options.lowRes, s = (h = this.lowSheet) != null && h.ready ? this.lowSheet.img : null;
91
+ if (!i || !s || !i.width || !i.height) return null;
92
+ const n = Math.max(1, Math.floor(s.naturalWidth / i.width)), r = n * Math.max(1, Math.floor(s.naturalHeight / i.height)), o = i.interval || e / r, a = Math.min(r - 1, Math.max(0, Math.floor(t / o)));
93
+ return { url: i.url, x: a % n * i.width, y: Math.floor(a / n) * i.height, w: i.width, h: i.height };
94
+ }
79
95
  /** Saniyedeki kareyi döner; gereken sheet hazır değilse yüklemeyi başlatıp null döner (yüklenince render tekrar çağrılır). */
80
96
  frameAt(t, e) {
81
97
  return this.options.vtt ? this.vttFrameAt(t) : this.gridFrameAt(t, e);
82
98
  }
83
99
  isMultiSheet() {
84
100
  var t;
85
- return !!((t = this.options.sheets) != null && t.length) || f.test(this.options.url ?? "");
101
+ return !!((t = this.options.sheets) != null && t.length) || v.test(this.options.url ?? "");
86
102
  }
87
103
  /** Tek sheet → Infinity (tüm video); çok parçalı → verilen ya da ilk sheet'ten hesaplanan süre; henüz bilinmiyorsa null. */
88
104
  sheetDuration() {
@@ -100,7 +116,7 @@ class M {
100
116
  var s;
101
117
  if ((s = this.options.sheets) != null && s.length) return this.options.sheets[Math.min(t, this.options.sheets.length - 1)];
102
118
  const e = this.options.url ?? "", i = t + (this.options.firstSheetIndex ?? 1);
103
- return e.replace(f, (n, r, h) => String(i).padStart(h ? Number(h) : 0, "0"));
119
+ return e.replace(v, (n, r, o) => String(i).padStart(o ? Number(o) : 0, "0"));
104
120
  }
105
121
  gridFrameAt(t, e) {
106
122
  const { width: i, height: s } = this.options;
@@ -108,14 +124,14 @@ class M {
108
124
  const n = this.options.interval || 1, r = this.sheetDuration();
109
125
  if (r === null)
110
126
  return this.ensureSheet(this.sheetUrl(0)), null;
111
- const h = r === 1 / 0 ? 0 : this.sheetIndexAt(Math.max(0, e - 1e-3)), u = Math.min(this.sheetIndexAt(t), h), o = this.sheetUrl(u);
112
- this.preloadAround(u, h);
113
- const d = this.sheets.get(o);
127
+ const o = r === 1 / 0 ? 0 : this.sheetIndexAt(Math.max(0, e - 1e-3)), a = Math.min(this.sheetIndexAt(t), o), h = this.sheetUrl(a);
128
+ this.preloadAround(a, o);
129
+ const d = this.sheets.get(h);
114
130
  if (!(d != null && d.ready))
115
- return this.ensureSheet(o), null;
116
- this.touch(o);
117
- const m = Math.max(1, Math.floor(d.img.naturalWidth / i)), p = Math.max(1, Math.floor(d.img.naturalHeight / s)), c = r === 1 / 0 ? t : t - u * r, v = Math.min(Math.max(0, Math.floor(c / n)), m * p - 1);
118
- return { url: o, x: v % m * i, y: Math.floor(v / m) * s, w: i, h: s };
131
+ return this.ensureSheet(h), null;
132
+ this.touch(h);
133
+ const c = Math.max(1, Math.floor(d.img.naturalWidth / i)), p = Math.max(1, Math.floor(d.img.naturalHeight / s)), m = r === 1 / 0 ? t : t - a * r, f = Math.min(Math.max(0, Math.floor(m / n)), c * p - 1);
134
+ return { url: h, x: f % c * i, y: Math.floor(f / c) * s, w: i, h: s };
119
135
  }
120
136
  preloadAround(t, e) {
121
137
  const i = this.options.preloadSheets ?? 1;
@@ -129,23 +145,30 @@ class M {
129
145
  if (!e.length) return null;
130
146
  let i = 0, s = e.length - 1;
131
147
  for (; i < s; ) {
132
- const o = i + s + 1 >> 1;
133
- e[o].start <= t ? i = o : s = o - 1;
148
+ const h = i + s + 1 >> 1;
149
+ e[h].start <= t ? i = h : s = h - 1;
134
150
  }
135
151
  const n = e[i];
136
- [e[i + 1], e[i - 1]].filter((o) => !!o && o.url !== n.url).forEach((o) => void this.ensureSheet(o.url));
137
- const h = this.sheets.get(n.url);
138
- if (!(h != null && h.ready))
152
+ [e[i + 1], e[i - 1]].filter((h) => !!h && h.url !== n.url).forEach((h) => void this.ensureSheet(h.url));
153
+ const o = this.sheets.get(n.url);
154
+ if (!(o != null && o.ready))
139
155
  return this.ensureSheet(n.url), null;
140
156
  this.touch(n.url);
141
- const u = n.rect ?? { x: 0, y: 0, w: h.img.naturalWidth, h: h.img.naturalHeight };
142
- return { url: n.url, ...u };
157
+ const a = n.rect ?? { x: 0, y: 0, w: o.img.naturalWidth, h: o.img.naturalHeight };
158
+ return { url: n.url, ...a };
143
159
  }
144
160
  // ── yükleme / cache ──
145
161
  ensureSheet(t) {
146
162
  if (!t) return Promise.resolve();
147
163
  const e = this.sheets.get(t);
148
164
  if (e) return e.promise;
165
+ const i = this.createSheet(t, (s) => {
166
+ this.learnSheetDuration(s), this.hovering && this.scheduleRender();
167
+ });
168
+ return this.sheets.set(t, i), this.evict(), i.promise;
169
+ }
170
+ /** Görseli yükler; decode bitmeden hazır sayılmaz (sheet geçişinde titreme olmasın). */
171
+ createSheet(t, e) {
149
172
  const i = new Image();
150
173
  i.decoding = "async";
151
174
  const s = { img: i, ready: !1, failed: !1, promise: Promise.resolve() };
@@ -153,13 +176,13 @@ class M {
153
176
  i.onload = () => {
154
177
  const r = () => {
155
178
  if (this.destroyed) return n();
156
- s.ready = !0, this.learnSheetDuration(i), this.hovering && this.scheduleRender(), n();
179
+ s.ready = !0, e(i), n();
157
180
  };
158
181
  i.decode ? i.decode().then(r, r) : r();
159
182
  }, i.onerror = () => {
160
183
  s.failed = !0, n();
161
184
  };
162
- }), i.src = t, this.sheets.set(t, s), this.evict(), s.promise;
185
+ }), i.src = t, s;
163
186
  }
164
187
  /** Çok parçalı modda `sheetDuration` verilmediyse ilk yüklenen sheet'in ızgara kapasitesinden hesapla. */
165
188
  learnSheetDuration(t) {
@@ -175,7 +198,7 @@ class M {
175
198
  e && (this.sheets.delete(t), this.sheets.set(t, e));
176
199
  }
177
200
  evict() {
178
- for (; this.sheets.size > w; ) {
201
+ for (; this.sheets.size > x; ) {
179
202
  const t = this.sheets.keys().next().value, e = this.sheets.get(t);
180
203
  e.img.onload = null, e.img.onerror = null, this.sheets.delete(t);
181
204
  }
@@ -187,39 +210,39 @@ class M {
187
210
  if (!e.ok) throw new Error(`HTTP ${e.status}`);
188
211
  return e.text();
189
212
  }).then((e) => {
190
- this.destroyed || (this.vttCues = S(e, new URL(t, document.baseURI).href), this.vttCues.length && this.ensureSheet(this.vttCues[0].url), this.hovering && this.scheduleRender());
213
+ this.destroyed || (this.vttCues = M(e, new URL(t, document.baseURI).href), this.vttCues.length && this.ensureSheet(this.vttCues[0].url), this.hovering && this.scheduleRender());
191
214
  }).catch((e) => {
192
215
  console.warn("[HopePlayer sprite-thumbnails] VTT yüklenemedi:", e), this.vttCues = [];
193
216
  }), this.vttLoading;
194
217
  }
195
218
  }
196
- function g(a) {
197
- return a.trim().split(":").map(Number).reduce((e, i) => e * 60 + i, 0);
219
+ function g(u) {
220
+ return u.trim().split(":").map(Number).reduce((e, i) => e * 60 + i, 0);
198
221
  }
199
- function S(a, t) {
222
+ function M(u, t) {
200
223
  var s;
201
- const e = [], i = a.replace(/\r/g, "").split(/\n\n+/);
224
+ const e = [], i = u.replace(/\r/g, "").split(/\n\n+/);
202
225
  for (const n of i) {
203
226
  const r = n.split(`
204
- `).filter(Boolean), h = r.findIndex((v) => v.includes("-->"));
205
- if (h === -1) continue;
206
- const [u, o] = r[h].split("-->"), d = (s = r[h + 1]) == null ? void 0 : s.trim();
207
- if (!u || !o || !d) continue;
208
- const [m, p] = d.split("#"), c = p == null ? void 0 : p.match(/xywh=(\d+),(\d+),(\d+),(\d+)/);
227
+ `).filter(Boolean), o = r.findIndex((f) => f.includes("-->"));
228
+ if (o === -1) continue;
229
+ const [a, h] = r[o].split("-->"), d = (s = r[o + 1]) == null ? void 0 : s.trim();
230
+ if (!a || !h || !d) continue;
231
+ const [c, p] = d.split("#"), m = p == null ? void 0 : p.match(/xywh=(\d+),(\d+),(\d+),(\d+)/);
209
232
  e.push({
210
- start: g(u),
211
- end: g(o.trim().split(/\s+/)[0]),
212
- url: new URL(m, t).href,
213
- rect: c ? { x: +c[1], y: +c[2], w: +c[3], h: +c[4] } : null
233
+ start: g(a),
234
+ end: g(h.trim().split(/\s+/)[0]),
235
+ url: new URL(c, t).href,
236
+ rect: m ? { x: +m[1], y: +m[2], w: +m[3], h: +m[4] } : null
214
237
  });
215
238
  }
216
239
  return e.sort((n, r) => n.start - r.start);
217
240
  }
218
- function I(a, t) {
219
- return new M(a, t);
241
+ function A(u, t) {
242
+ return new S(u, t);
220
243
  }
221
244
  export {
222
- M as SpriteThumbnails,
223
- I as installSpriteThumbnails
245
+ S as SpriteThumbnails,
246
+ A as installSpriteThumbnails
224
247
  };
225
- //# sourceMappingURL=spriteThumbnails-B7oDZFTo.js.map
248
+ //# sourceMappingURL=spriteThumbnails-BoxVY--_.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spriteThumbnails-BoxVY--_.js","sources":["../../src/plugins/sprite-thumbnails/SpriteThumbnails.ts","../../src/plugins/sprite-thumbnails/index.ts"],"sourcesContent":["import type { SpriteThumbnailsOptions } from '../../types';\nimport { formatTime } from '../../utils/format-time';\n\nexport interface SpriteThumbnailsPlayerContext {\n videoEl: HTMLVideoElement;\n /** Önizlemenin bağlandığı seek bar — zaman eşlemesi (chapter boşlukları dahil) onun `ratioAtClientX`'inden. */\n seekBar: {\n readonly el: HTMLElement;\n ratioAtClientX(clientX: number): number;\n suppressHoverTime(key: string, suppressed: boolean): void;\n };\n /** Responsive ölçekleme için referans genişlik — genelde player/video alanının genişliği. */\n playerWidth(): number;\n}\n\n/** Bir önizleme karesi: hangi görselin hangi dikdörtgeni. */\ninterface Frame {\n url: string;\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\ninterface Sheet {\n img: HTMLImageElement;\n ready: boolean;\n failed: boolean;\n promise: Promise<void>;\n}\n\nexport interface VttCue {\n start: number;\n end: number;\n url: string;\n /** `#xywh` yoksa null → görselin tamamı. */\n rect: { x: number; y: number; w: number; h: number } | null;\n}\n\n/** Aynı anda bellekte (decode edilmiş) tutulan en fazla sheet — uzun videolarda bellek sınırsız büyümesin. */\nconst MAX_CACHED_SHEETS = 8;\n/** Sheet numarası şablonu: `%d` ya da sıfır dolgulu `%03d`. */\nconst SHEET_TEMPLATE = /%(0(\\d+))?d/;\n\n/**\n * Seek bar hover önizlemesi. Kaynak: tek görsel, çok parçalı (%d / %03d şablonu ya da sheets) veya WebVTT (#xywh).\n * sheetDuration verilmezse ilk sheet'in ızgarasından hesaplanır. Kurulumda hiçbir şey indirilmez; yalnızca imlecin\n * altındaki sheet + komşuları yüklenir, decode bitmeden gösterilmez, LRU cache.\n */\nexport class SpriteThumbnails {\n private readonly tooltip: HTMLElement;\n private readonly imageEl: HTMLElement;\n private readonly timeEl: HTMLElement;\n private readonly sheets = new Map<string, Sheet>();\n private vttCues: VttCue[] | null = null;\n private vttLoading: Promise<void> | null = null;\n /** Çok parçalı modda otomatik hesaplanan sheet süresi (ilk sheet yüklenince). */\n private derivedSheetDuration: number | null = null;\n /** `lowRes` sheet'i — LRU dışında, hep bellekte. */\n private lowSheet: Sheet | null = null;\n /** Son çizilen asıl karenin genişliği (VTT'de `width` yok). */\n private lastFrameWidth = 0;\n private warmed = false;\n private hovering = false;\n private lastClientX = 0;\n private rafId: number | null = null;\n private destroyed = false;\n\n constructor(\n private readonly ctx: SpriteThumbnailsPlayerContext,\n private readonly options: SpriteThumbnailsOptions\n ) {\n this.tooltip = document.createElement('div');\n this.tooltip.setAttribute('part', 'sprite-tooltip');\n this.tooltip.className = 'hp-sprite-tooltip';\n this.imageEl = document.createElement('div');\n this.imageEl.className = 'hp-sprite-image';\n this.timeEl = document.createElement('div');\n this.timeEl.className = 'hp-sprite-time';\n this.tooltip.append(this.imageEl, this.timeEl);\n ctx.seekBar.el.appendChild(this.tooltip);\n // Önizlemenin altında zaman zaten yazıyor — varsayılan hover zamanı ikinci kez göstermesin.\n ctx.seekBar.suppressHoverTime('sprite', true);\n\n ctx.seekBar.el.addEventListener('pointerenter', this.onPointerEnter);\n ctx.seekBar.el.addEventListener('pointermove', this.onPointerMove);\n ctx.seekBar.el.addEventListener('pointerleave', this.onPointerLeave);\n ctx.videoEl.addEventListener('play', this.warm);\n }\n\n destroy(): void {\n this.destroyed = true;\n if (this.rafId !== null) cancelAnimationFrame(this.rafId);\n this.ctx.seekBar.el.removeEventListener('pointerenter', this.onPointerEnter);\n this.ctx.seekBar.el.removeEventListener('pointermove', this.onPointerMove);\n this.ctx.seekBar.el.removeEventListener('pointerleave', this.onPointerLeave);\n this.ctx.videoEl.removeEventListener('play', this.warm);\n this.tooltip.remove();\n this.ctx.seekBar.suppressHoverTime('sprite', false);\n for (const sheet of this.sheets.values()) sheet.img.src = '';\n if (this.lowSheet) this.lowSheet.img.src = '';\n this.sheets.clear();\n }\n\n // ── olaylar ──\n\n private readonly onPointerEnter = (e: PointerEvent): void => {\n this.hovering = true;\n this.lastClientX = e.clientX;\n this.warm();\n this.scheduleRender();\n };\n\n private readonly onPointerMove = (e: PointerEvent): void => {\n this.hovering = true;\n this.lastClientX = e.clientX;\n this.scheduleRender();\n };\n\n private readonly onPointerLeave = (): void => {\n this.hovering = false;\n this.tooltip.removeAttribute('data-visible');\n };\n\n /** İlk ihtiyaç anında (hover / oynatma) kaynağı hazırla — kurulumda hiçbir şey indirilmiyor. */\n private readonly warm = (): void => {\n if (this.warmed || this.destroyed) return;\n this.warmed = true;\n // Küçük sheet bağlantı hızından bağımsız hemen iner.\n if (this.options.lowRes?.url) this.lowSheet = this.createSheet(this.options.lowRes.url, () => this.hovering && this.scheduleRender());\n if (this.options.vtt) {\n void this.loadVtt();\n return;\n }\n const duration = this.ctx.videoEl.duration;\n const t = Number.isFinite(duration) ? this.ctx.videoEl.currentTime : 0;\n // Şablonlu/çok parçalı modda sheet süresi henüz bilinmiyorsa ilk sheet'ten öğrenilecek.\n void this.ensureSheet(this.sheetUrl(this.isMultiSheet() && this.sheetDuration() === null ? 0 : this.sheetIndexAt(t)));\n };\n\n private scheduleRender(): void {\n if (this.rafId !== null) return;\n this.rafId = requestAnimationFrame(() => {\n this.rafId = null;\n this.render();\n });\n }\n\n // ── çizim ──\n\n private render(): void {\n if (!this.hovering || this.destroyed) return;\n const duration = this.ctx.videoEl.duration;\n if (!Number.isFinite(duration) || duration <= 0) return;\n\n const seconds = this.ctx.seekBar.ratioAtClientX(this.lastClientX) * duration;\n this.timeEl.textContent = formatTime(seconds);\n\n // Asıl kare hazır değilse küçük sheet'ten doğru zamanın karesi; o da yoksa son kare ekranda kalır.\n const hi = this.isNetworkEligible() ? this.frameAt(seconds, duration) : null;\n if (hi) this.lastFrameWidth = hi.w;\n const frame = hi ?? this.lowResFrameAt(seconds, duration);\n const img = hi ? this.sheets.get(hi.url)!.img : this.lowSheet?.img;\n if (frame && img) {\n // Hedef genişlik: displayWidth → kare genişliği; küçük kare aynı boyuta büyütülür.\n const target = (this.options.displayWidth ?? (hi ? hi.w : this.options.width || this.lastFrameWidth || frame.w)) * this.scale();\n const k = target / frame.w;\n this.imageEl.style.display = '';\n this.imageEl.toggleAttribute('data-lowres', !hi);\n this.imageEl.style.width = `${target}px`;\n this.imageEl.style.height = `${frame.h * k}px`;\n this.imageEl.style.backgroundImage = `url(\"${frame.url}\")`;\n this.imageEl.style.backgroundSize = `${img.naturalWidth * k}px ${img.naturalHeight * k}px`;\n this.imageEl.style.backgroundPosition = `${-frame.x * k}px ${-frame.y * k}px`;\n } else if (!this.imageEl.style.backgroundImage) {\n // Henüz hiçbir kare yüklenmedi — yalnızca zaman (yükleme bitince yeniden çizilir).\n this.imageEl.style.display = 'none';\n }\n\n // Kenarlarda taşmasın: imleci ortala ama seek bar sınırlarında kal.\n this.tooltip.setAttribute('data-visible', '');\n const barRect = this.ctx.seekBar.el.getBoundingClientRect();\n const tipWidth = this.tooltip.offsetWidth;\n const x = Math.min(Math.max(this.lastClientX - barRect.left - tipWidth / 2, 0), Math.max(barRect.width - tipWidth, 0));\n this.tooltip.style.transform = `translateX(${x}px)`;\n }\n\n private scale(): number {\n const responsive = this.options.responsive;\n const playerWidth = this.ctx.playerWidth();\n return responsive && playerWidth && playerWidth < responsive ? playerWidth / responsive : 1;\n }\n\n private isNetworkEligible(): boolean {\n const nav = navigator as Navigator & { connection?: { downlink?: number } };\n const downlink = nav.connection?.downlink;\n const anyReady = Array.from(this.sheets.values()).some((s) => s.ready);\n return downlink === undefined || downlink >= (this.options.downlink ?? 2) || anyReady;\n }\n\n // ── kare çözümleme ──\n\n /** `lowRes` sheet'inden saniyedeki kare (hazır değilse null). */\n private lowResFrameAt(seconds: number, duration: number): Frame | null {\n const o = this.options.lowRes;\n const img = this.lowSheet?.ready ? this.lowSheet.img : null;\n if (!o || !img || !o.width || !o.height) return null;\n const columns = Math.max(1, Math.floor(img.naturalWidth / o.width));\n const count = columns * Math.max(1, Math.floor(img.naturalHeight / o.height));\n const interval = o.interval || duration / count;\n const i = Math.min(count - 1, Math.max(0, Math.floor(seconds / interval)));\n return { url: o.url, x: (i % columns) * o.width, y: Math.floor(i / columns) * o.height, w: o.width, h: o.height };\n }\n\n /** Saniyedeki kareyi döner; gereken sheet hazır değilse yüklemeyi başlatıp null döner (yüklenince render tekrar çağrılır). */\n private frameAt(seconds: number, duration: number): Frame | null {\n return this.options.vtt ? this.vttFrameAt(seconds) : this.gridFrameAt(seconds, duration);\n }\n\n private isMultiSheet(): boolean {\n return !!this.options.sheets?.length || SHEET_TEMPLATE.test(this.options.url ?? '');\n }\n\n /** Tek sheet → Infinity (tüm video); çok parçalı → verilen ya da ilk sheet'ten hesaplanan süre; henüz bilinmiyorsa null. */\n private sheetDuration(): number | null {\n if (!this.isMultiSheet()) return Infinity;\n return this.options.sheetDuration ?? this.derivedSheetDuration;\n }\n\n private sheetIndexAt(seconds: number): number {\n const d = this.sheetDuration();\n if (d === null || d === Infinity) return 0;\n // floor (ceil DEĞİL): tam sınırda (ör. 60. sn) bir SONRAKİ sheet'in ilk karesi.\n let index = Math.floor(Math.max(0, seconds) / d);\n if (this.options.sheets?.length) index = Math.min(index, this.options.sheets.length - 1);\n return index;\n }\n\n /** 0 tabanlı sheet index'inden URL. */\n private sheetUrl(index: number): string {\n if (this.options.sheets?.length) return this.options.sheets[Math.min(index, this.options.sheets.length - 1)]!;\n const url = this.options.url ?? '';\n const number = index + (this.options.firstSheetIndex ?? 1);\n return url.replace(SHEET_TEMPLATE, (_m, _p, width?: string) => String(number).padStart(width ? Number(width) : 0, '0'));\n }\n\n private gridFrameAt(seconds: number, duration: number): Frame | null {\n const { width, height } = this.options;\n if (!width || !height) return null;\n const interval = this.options.interval || 1;\n\n const sheetDuration = this.sheetDuration();\n if (sheetDuration === null) {\n // Çok parçalı ama süre bilinmiyor — ilk sheet yüklenince hesaplanacak.\n void this.ensureSheet(this.sheetUrl(0));\n return null;\n }\n\n const lastIndex = sheetDuration === Infinity ? 0 : this.sheetIndexAt(Math.max(0, duration - 0.001));\n const index = Math.min(this.sheetIndexAt(seconds), lastIndex);\n const url = this.sheetUrl(index);\n this.preloadAround(index, lastIndex);\n\n const sheet = this.sheets.get(url);\n if (!sheet?.ready) {\n void this.ensureSheet(url);\n return null;\n }\n this.touch(url);\n\n // Her sheet'in KENDİ boyutu (son sheet daha kısa olabilir).\n const columns = Math.max(1, Math.floor(sheet.img.naturalWidth / width));\n const rows = Math.max(1, Math.floor(sheet.img.naturalHeight / height));\n const local = sheetDuration === Infinity ? seconds : seconds - index * sheetDuration;\n const frameIndex = Math.min(Math.max(0, Math.floor(local / interval)), columns * rows - 1);\n return { url, x: (frameIndex % columns) * width, y: Math.floor(frameIndex / columns) * height, w: width, h: height };\n }\n\n private preloadAround(index: number, lastIndex: number): void {\n const n = this.options.preloadSheets ?? 1;\n for (let d = 1; d <= n; d++) {\n if (index + d <= lastIndex) void this.ensureSheet(this.sheetUrl(index + d));\n if (index - d >= 0) void this.ensureSheet(this.sheetUrl(index - d));\n }\n }\n\n private vttFrameAt(seconds: number): Frame | null {\n if (!this.vttCues) {\n void this.loadVtt();\n return null;\n }\n const cues = this.vttCues;\n if (!cues.length) return null;\n // İkili arama — saatlerce süren videolarda binlerce cue olabilir.\n let lo = 0;\n let hi = cues.length - 1;\n while (lo < hi) {\n const mid = (lo + hi + 1) >> 1;\n if (cues[mid]!.start <= seconds) lo = mid;\n else hi = mid - 1;\n }\n const cue = cues[lo]!;\n const neighbours = [cues[lo + 1], cues[lo - 1]].filter((c): c is VttCue => !!c && c.url !== cue.url);\n neighbours.forEach((c) => void this.ensureSheet(c.url));\n\n const sheet = this.sheets.get(cue.url);\n if (!sheet?.ready) {\n void this.ensureSheet(cue.url);\n return null;\n }\n this.touch(cue.url);\n const rect = cue.rect ?? { x: 0, y: 0, w: sheet.img.naturalWidth, h: sheet.img.naturalHeight };\n return { url: cue.url, ...rect };\n }\n\n // ── yükleme / cache ──\n\n private ensureSheet(url: string): Promise<void> {\n if (!url) return Promise.resolve();\n const existing = this.sheets.get(url);\n if (existing) return existing.promise;\n\n const sheet = this.createSheet(url, (img) => {\n this.learnSheetDuration(img);\n if (this.hovering) this.scheduleRender();\n });\n this.sheets.set(url, sheet);\n this.evict();\n return sheet.promise;\n }\n\n /** Görseli yükler; decode bitmeden hazır sayılmaz (sheet geçişinde titreme olmasın). */\n private createSheet(url: string, onReady: (img: HTMLImageElement) => void): Sheet {\n const img = new Image();\n img.decoding = 'async';\n const sheet: Sheet = { img, ready: false, failed: false, promise: Promise.resolve() };\n sheet.promise = new Promise<void>((resolve) => {\n img.onload = () => {\n const done = () => {\n if (this.destroyed) return resolve();\n sheet.ready = true;\n onReady(img);\n resolve();\n };\n img.decode ? img.decode().then(done, done) : done();\n };\n img.onerror = () => {\n sheet.failed = true;\n resolve();\n };\n });\n img.src = url;\n return sheet;\n }\n\n /** Çok parçalı modda `sheetDuration` verilmediyse ilk yüklenen sheet'in ızgara kapasitesinden hesapla. */\n private learnSheetDuration(img: HTMLImageElement): void {\n if (this.derivedSheetDuration !== null || this.options.vtt || !this.isMultiSheet() || this.options.sheetDuration) return;\n const { width, height } = this.options;\n if (!width || !height) return;\n const capacity = Math.max(1, Math.floor(img.naturalWidth / width)) * Math.max(1, Math.floor(img.naturalHeight / height));\n this.derivedSheetDuration = capacity * (this.options.interval || 1);\n }\n\n /** LRU: kullanılan sheet'i sona taşı. */\n private touch(url: string): void {\n const sheet = this.sheets.get(url);\n if (!sheet) return;\n this.sheets.delete(url);\n this.sheets.set(url, sheet);\n }\n\n private evict(): void {\n while (this.sheets.size > MAX_CACHED_SHEETS) {\n const oldest = this.sheets.keys().next().value as string;\n const sheet = this.sheets.get(oldest)!;\n sheet.img.onload = null;\n sheet.img.onerror = null;\n this.sheets.delete(oldest);\n }\n }\n\n private loadVtt(): Promise<void> {\n if (this.vttLoading) return this.vttLoading;\n const vttUrl = this.options.vtt!;\n this.vttLoading = fetch(vttUrl)\n .then((r) => {\n if (!r.ok) throw new Error(`HTTP ${r.status}`);\n return r.text();\n })\n .then((text) => {\n if (this.destroyed) return;\n this.vttCues = parseThumbnailVtt(text, new URL(vttUrl, document.baseURI).href);\n if (this.vttCues.length) void this.ensureSheet(this.vttCues[0]!.url);\n if (this.hovering) this.scheduleRender();\n })\n .catch((err) => {\n console.warn('[HopePlayer sprite-thumbnails] VTT yüklenemedi:', err);\n this.vttCues = [];\n });\n return this.vttLoading;\n }\n}\n\n/** \"01:02:03.500\" / \"02:03.500\" → saniye. */\nfunction parseVttTime(value: string): number {\n const parts = value.trim().split(':').map(Number);\n return parts.reduce((acc, n) => acc * 60 + n, 0);\n}\n\n/** WebVTT thumbnail dosyası → sıralı cue listesi. Görsel yolları VTT dosyasına göre çözümlenir. */\nexport function parseThumbnailVtt(text: string, baseUrl: string): VttCue[] {\n const cues: VttCue[] = [];\n const blocks = text.replace(/\\r/g, '').split(/\\n\\n+/);\n for (const block of blocks) {\n const lines = block.split('\\n').filter(Boolean);\n const timingIndex = lines.findIndex((l) => l.includes('-->'));\n if (timingIndex === -1) continue;\n const [startStr, endStr] = lines[timingIndex]!.split('-->');\n const target = lines[timingIndex + 1]?.trim();\n if (!startStr || !endStr || !target) continue;\n\n const [path, hash] = target.split('#');\n const match = hash?.match(/xywh=(\\d+),(\\d+),(\\d+),(\\d+)/);\n cues.push({\n start: parseVttTime(startStr),\n end: parseVttTime(endStr.trim().split(/\\s+/)[0]!),\n url: new URL(path!, baseUrl).href,\n rect: match ? { x: +match[1]!, y: +match[2]!, w: +match[3]!, h: +match[4]! } : null,\n });\n }\n return cues.sort((a, b) => a.start - b.start);\n}\n","import { SpriteThumbnails, type SpriteThumbnailsPlayerContext } from './SpriteThumbnails';\nimport type { SpriteThumbnailsOptions } from '../../types';\n\nexport function installSpriteThumbnails(ctx: SpriteThumbnailsPlayerContext, options: SpriteThumbnailsOptions): SpriteThumbnails {\n return new SpriteThumbnails(ctx, options);\n}\n\nexport { SpriteThumbnails };\nexport type { SpriteThumbnailsPlayerContext };\n"],"names":["MAX_CACHED_SHEETS","SHEET_TEMPLATE","SpriteThumbnails","ctx","options","__publicField","e","_a","duration","t","sheet","seconds","formatTime","hi","frame","img","target","k","barRect","tipWidth","x","responsive","playerWidth","downlink","anyReady","s","o","columns","count","interval","i","d","index","url","number","_m","_p","width","height","sheetDuration","lastIndex","rows","local","frameIndex","n","cues","lo","mid","cue","c","rect","existing","onReady","resolve","done","capacity","oldest","vttUrl","r","text","parseThumbnailVtt","err","parseVttTime","value","acc","baseUrl","blocks","block","lines","timingIndex","l","startStr","endStr","path","hash","match","a","b","installSpriteThumbnails"],"mappings":"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"}
@@ -37,7 +37,7 @@ class x {
37
37
  for (let r = 0; r < t.buffered.length; r++)
38
38
  t.buffered.start(r) <= t.currentTime + 0.5 && t.buffered.end(r) > t.currentTime && (u = t.buffered.end(r) - t.currentTime);
39
39
  const f = [
40
- [e.statsEngine, l.engine + (l.reason ? ` (${l.reason})` : "")],
40
+ [e.statsEngine, l.engine + (l.drm ? ` · ${l.drm}` : "") + (l.reason ? ` (${l.reason})` : "")],
41
41
  [e.statsResolution, `${t.videoWidth}×${t.videoHeight} / ${Math.round(h.width * c)}×${Math.round(h.height * c)}`],
42
42
  [e.statsQuality, i ? `${i.height}p · ${Math.round(i.bitrate / 1e3)} kbps${s.autoLevelEnabled ? " · auto" : ""}` : "—"],
43
43
  [e.statsCodecs, i && [i.videoCodec, i.audioCodec].filter(Boolean).join(", ") || "—"],
@@ -67,4 +67,4 @@ export {
67
67
  x as StatsPanel,
68
68
  $ as installStats
69
69
  };
70
- //# sourceMappingURL=statsPanel-DSClIwA3.js.map
70
+ //# sourceMappingURL=statsPanel-D0DtoFgS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statsPanel-D0DtoFgS.js","sources":["../../src/plugins/stats/StatsPanel.ts","../../src/plugins/stats/index.ts"],"sourcesContent":["import type { HopeLocaleStrings } from '../../i18n/types';\nimport type { PlaybackEngineInfo } from '../../hls/SourceManager';\n\n/** hls.js instance'ından okunan alanlar — tam tipi içe aktarmamak için. */\ninterface HlsStatsSource {\n currentLevel: number;\n autoLevelEnabled: boolean;\n levels: { height: number; width: number; bitrate: number; videoCodec?: string; audioCodec?: string; details?: { live: boolean } }[];\n bandwidthEstimate: number;\n latency: number;\n config: { maxBufferLength: number };\n}\n\nexport interface StatsPlayerContext {\n videoEl: HTMLVideoElement;\n containerEl: HTMLElement;\n i18n: HopeLocaleStrings;\n version: string;\n getEngine(): PlaybackEngineInfo;\n getHls(): HlsStatsSource | null;\n}\n\nconst REFRESH_MS = 500;\n\n/** Sağ tık menüsündeki \"İstatistikler\" — player üstünde canlı teknik bilgi paneli (YouTube'daki \"Stats for nerds\" gibi). */\nexport class StatsPanel {\n private readonly el: HTMLDivElement;\n private readonly titleEl: HTMLSpanElement;\n private readonly closeBtn: HTMLButtonElement;\n private readonly body: HTMLDListElement;\n private timer: ReturnType<typeof setInterval> | null = null;\n\n constructor(private readonly ctx: StatsPlayerContext) {\n this.el = document.createElement('div');\n this.el.className = 'hp-stats';\n this.el.setAttribute('part', 'stats-panel');\n this.el.setAttribute('role', 'dialog');\n\n const header = document.createElement('div');\n header.className = 'hp-stats-header';\n this.titleEl = document.createElement('span');\n this.closeBtn = document.createElement('button');\n this.closeBtn.type = 'button';\n this.closeBtn.className = 'hp-stats-close';\n this.closeBtn.innerHTML =\n '<svg viewBox=\"0 0 24 24\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.4\" stroke-linecap=\"round\" aria-hidden=\"true\"><path d=\"M6 6l12 12M18 6L6 18\"/></svg>';\n this.closeBtn.addEventListener('click', () => this.hide());\n header.append(this.titleEl, this.closeBtn);\n\n this.body = document.createElement('dl');\n this.body.className = 'hp-stats-body';\n this.el.append(header, this.body);\n // Panel tıklamaları videoyu oynat/duraklat yapmasın.\n this.el.addEventListener('pointerdown', (e) => e.stopPropagation());\n this.el.addEventListener('click', (e) => e.stopPropagation());\n this.refreshLabels();\n }\n\n get isVisible(): boolean {\n return this.el.isConnected;\n }\n\n show(): void {\n if (!this.isVisible) this.ctx.containerEl.appendChild(this.el);\n this.render();\n if (!this.timer) this.timer = setInterval(() => this.render(), REFRESH_MS);\n }\n\n hide(): void {\n if (this.timer) clearInterval(this.timer);\n this.timer = null;\n this.el.remove();\n }\n\n toggle(force?: boolean): void {\n if (force ?? !this.isVisible) this.show();\n else this.hide();\n }\n\n refreshLabels(): void {\n this.titleEl.textContent = this.ctx.i18n.statsTitle;\n this.closeBtn.setAttribute('aria-label', this.ctx.i18n.statsClose);\n if (this.isVisible) this.render();\n }\n\n destroy(): void {\n this.hide();\n }\n\n private render(): void {\n const { videoEl: v, i18n: t } = this.ctx;\n const hls = this.ctx.getHls();\n const engine = this.ctx.getEngine();\n const level = hls && hls.currentLevel >= 0 ? hls.levels[hls.currentLevel] : undefined;\n const quality = v.getVideoPlaybackQuality?.();\n const rect = v.getBoundingClientRect();\n const dpr = window.devicePixelRatio || 1;\n\n let ahead = 0;\n for (let i = 0; i < v.buffered.length; i++) {\n if (v.buffered.start(i) <= v.currentTime + 0.5 && v.buffered.end(i) > v.currentTime) ahead = v.buffered.end(i) - v.currentTime;\n }\n\n const rows: [string, string][] = [\n [t.statsEngine, engine.engine + (engine.drm ? ` · ${engine.drm}` : '') + (engine.reason ? ` (${engine.reason})` : '')],\n [t.statsResolution, `${v.videoWidth}×${v.videoHeight} / ${Math.round(rect.width * dpr)}×${Math.round(rect.height * dpr)}`],\n [t.statsQuality, level ? `${level.height}p · ${Math.round(level.bitrate / 1000)} kbps${hls!.autoLevelEnabled ? ' · auto' : ''}` : '—'],\n [t.statsCodecs, level ? [level.videoCodec, level.audioCodec].filter(Boolean).join(', ') || '—' : '—'],\n [t.statsBandwidth, hls ? `${(hls.bandwidthEstimate / 1e6).toFixed(2)} Mbps` : '—'],\n [t.statsBuffer, `${ahead.toFixed(1)} s`],\n [t.statsDropped, quality ? `${quality.droppedVideoFrames} / ${quality.totalVideoFrames}` : '—'],\n // hls.js `latency`'yi VOD'da da hesaplıyor (süre - konum) — yalnızca canlı yayında anlamlı.\n [t.statsLatency, level?.details?.live && Number.isFinite(hls!.latency) ? `${hls!.latency.toFixed(1)} s` : '—'],\n [t.statsSpeedVolume, `${v.playbackRate}× · ${v.muted ? 0 : Math.round(v.volume * 100)}%`],\n [t.statsSource, v.currentSrc && !v.currentSrc.startsWith('blob:') ? v.currentSrc : v.currentSrc ? 'MediaSource (hls.js)' : '—'],\n [t.statsVersion, `HopeCorePlayer ${this.ctx.version}`],\n ];\n this.body.replaceChildren(\n ...rows.flatMap(([k, val]) => {\n const dt = document.createElement('dt');\n dt.textContent = k;\n const dd = document.createElement('dd');\n dd.textContent = val;\n dd.title = val;\n return [dt, dd];\n })\n );\n }\n}\n","import { StatsPanel, type StatsPlayerContext } from './StatsPanel';\n\nexport function installStats(ctx: StatsPlayerContext): StatsPanel {\n return new StatsPanel(ctx);\n}\n\nexport { StatsPanel };\nexport type { StatsPlayerContext };\n"],"names":["StatsPanel","ctx","__publicField","header","e","force","_a","_b","v","t","hls","engine","level","quality","rect","dpr","ahead","i","rows","k","val","dt","dd","installStats"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  var A = Object.defineProperty;
2
2
  var N = (h, t, e) => t in h ? A(h, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : h[t] = e;
3
3
  var r = (h, t, e) => N(h, typeof t != "symbol" ? t + "" : t, e);
4
- import { c as b } from "./player-D7WQxMzr.js";
4
+ import { c as b } from "./player-DV4Hf5Cw.js";
5
5
  const P = {
6
6
  startIndex: 0,
7
7
  loop: !0,
@@ -331,4 +331,4 @@ export {
331
331
  L as HopeStory,
332
332
  M as installStory
333
333
  };
334
- //# sourceMappingURL=story-BLBij82f.js.map
334
+ //# sourceMappingURL=story-BRkhSDhR.js.map