@hopeplayer/core 1.0.3 → 1.0.4

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 (37) hide show
  1. package/dist/HopePlayerElement.d.ts +16 -3
  2. package/dist/HopePlayerElement.d.ts.map +1 -1
  3. package/dist/chunks/{index-CgkX9qaH.js → index-C2LLloqz.js} +2 -2
  4. package/dist/chunks/{index-CgkX9qaH.js.map → index-C2LLloqz.js.map} +1 -1
  5. package/dist/chunks/{index-C6xzBfNn.js → index-CoUeJvsG.js} +2 -2
  6. package/dist/chunks/{index-C6xzBfNn.js.map → index-CoUeJvsG.js.map} +1 -1
  7. package/dist/chunks/{index-TQsycon_.js → index-DSOoIVgQ.js} +2 -2
  8. package/dist/chunks/{index-TQsycon_.js.map → index-DSOoIVgQ.js.map} +1 -1
  9. package/dist/chunks/{index-IcJCsJYH.js → index-DXgJitsr.js} +2 -2
  10. package/dist/chunks/{index-IcJCsJYH.js.map → index-DXgJitsr.js.map} +1 -1
  11. package/dist/chunks/{index-Xf3PnlMU.js → index-DrFrsAJ-.js} +2 -2
  12. package/dist/chunks/{index-Xf3PnlMU.js.map → index-DrFrsAJ-.js.map} +1 -1
  13. package/dist/chunks/{index-BvFMYXAE.js → index-QJhB8dCl.js} +446 -316
  14. package/dist/chunks/index-QJhB8dCl.js.map +1 -0
  15. package/dist/controls/ControlBar.d.ts +13 -0
  16. package/dist/controls/ControlBar.d.ts.map +1 -1
  17. package/dist/controls/SeekBar.d.ts +4 -0
  18. package/dist/controls/SeekBar.d.ts.map +1 -1
  19. package/dist/controls/SeekFeedback.d.ts +20 -0
  20. package/dist/controls/SeekFeedback.d.ts.map +1 -0
  21. package/dist/controls/SettingsMenu.d.ts +4 -0
  22. package/dist/controls/SettingsMenu.d.ts.map +1 -1
  23. package/dist/controls/Tooltip.d.ts +8 -0
  24. package/dist/controls/Tooltip.d.ts.map +1 -1
  25. package/dist/hope-player.js +1 -1
  26. package/dist/i18n/locales/en.d.ts.map +1 -1
  27. package/dist/i18n/locales/tr.d.ts.map +1 -1
  28. package/dist/i18n/types.d.ts +4 -0
  29. package/dist/i18n/types.d.ts.map +1 -1
  30. package/dist/index.d.ts +1 -1
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/keyboard/KeyboardController.d.ts +4 -0
  33. package/dist/keyboard/KeyboardController.d.ts.map +1 -1
  34. package/dist/types/index.d.ts +10 -0
  35. package/dist/types/index.d.ts.map +1 -1
  36. package/package.json +1 -1
  37. package/dist/chunks/index-BvFMYXAE.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-QJhB8dCl.js","sources":["../../src/hls/SourceManager.ts","../../src/utils/format-time.ts","../../src/controls/SeekBar.ts","../../src/icons/Icon.ts","../../src/controls/VolumePanel.ts","../../src/controls/SettingsMenu.ts","../../src/controls/ControlBar.ts","../../src/controls/Tooltip.ts","../../src/keyboard/KeyboardController.ts","../../src/screens/LoadingSpinner.ts","../../src/screens/ErrorScreen.ts","../../src/subtitles/attachTracks.ts","../../src/subtitles/CaptionRenderer.ts","../../src/controls/MiniProgress.ts","../../src/controls/SeekFeedback.ts","../../src/icons/injectIconFont.ts","../../src/i18n/locales/tr.ts","../../src/i18n/locales/en.ts","../../src/i18n/index.ts","../../src/HopePlayerElement.ts","../../src/index.ts"],"sourcesContent":["\n/**\n * MP4: HTML5 video üzerinden doğrudan oynatılır.\n * M3U8: Safari/iOS'ta native HLS; diğer tarayıcılarda gerektiğinde hls.js.\n */\nexport interface HlsQualityLevel {\n index: number;\n height: number;\n bitrate: number;\n}\n\ntype HlsModule = typeof import('hls.js');\ntype HlsInstance = InstanceType<HlsModule['default']>;\n\ntype MediaSourceType = 'hls' | 'mp4' | 'unknown';\n\n/** Hangi yoldan oynatılıyor — `reason` native'e neden düşüldüğünü açıklar (ör. CORS). */\nexport interface PlaybackEngineInfo {\n engine: 'native' | 'native-hls' | 'hls.js';\n reason?: 'apple-native' | 'no-mse' | 'hlsjs-failed';\n}\n\n/**\n * Safari (macOS) ve iOS/iPadOS'ta native HLS tercih edilir (AirPlay, pil, iPhone video tam ekranı).\n * Diğerlerinde (Chrome artık native HLS'e \"maybe\" diyor) hls.js — native oynatıcı kalite seviyelerini vermez.\n */\nfunction prefersNativeHls(): boolean {\n if (typeof navigator === 'undefined') return false;\n const ua = navigator.userAgent;\n const iOS = /iP(hone|od|ad)/.test(ua) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1);\n const safari = /^((?!chrome|chromium|android|crios|fxios|edg|opr).)*safari/i.test(ua);\n return iOS || safari;\n}\n\nfunction hasMse(): boolean {\n const w = window as unknown as { MediaSource?: unknown; ManagedMediaSource?: unknown };\n return typeof w.MediaSource !== 'undefined' || typeof w.ManagedMediaSource !== 'undefined';\n}\n\n/**\n * Kaynak türünü MIME type veya URL uzantısından belirler.\n * URL'deki query string ve fragment değerlerini de destekler.\n */\nfunction detectSourceType(src: string, type?: string): MediaSourceType {\n const normalizedType = type\n ?.split(';')[0]\n ?.trim()\n .toLowerCase();\n\n // HLS / M3U8\n if (\n normalizedType === 'application/vnd.apple.mpegurl' ||\n normalizedType === 'application/x-mpegurl' ||\n /\\.m3u8(?:$|[?#])/i.test(src)\n ) {\n return 'hls';\n }\n\n // MP4\n if (\n normalizedType === 'video/mp4' ||\n /\\.mp4(?:$|[?#])/i.test(src)\n ) {\n return 'mp4';\n }\n\n return 'unknown';\n}\n\nexport class SourceManager {\n private hls: HlsInstance | null = null;\n\n private readonly video: HTMLVideoElement;\n\n /** Son yüklenen kaynak — `reload()` (hata ekranındaki \"Tekrar dene\") için. */\n private last: { src: string; type?: string } | null = null;\n /** Native HLS denemesi sürerken (ilk loadedmetadata'ya kadar) — başarısız olursa hls.js'e geçilir. */\n private nativeHlsProbe: (() => void) | null = null;\n private engineInfo: PlaybackEngineInfo = { engine: 'native' };\n\n private readonly onLevelsChanged: (\n levels: HlsQualityLevel[],\n activeIndex: number\n ) => void;\n\n constructor(\n video: HTMLVideoElement,\n onLevelsChanged: (\n levels: HlsQualityLevel[],\n activeIndex: number\n ) => void\n ) {\n this.video = video;\n this.onLevelsChanged = onLevelsChanged;\n }\n\n async load(src: string, type?: string): Promise<void> {\n this.last = { src, type };\n // Önce önceki HLS instance'ını kapat (hls.js kendi blob kaynağını media'dan ayırır).\n this.destroy();\n this.video.pause();\n // Kaynağı boşaltıp load() ÇAĞIRMA: Safari/iOS kaynaksız load()'da MEDIA_ERR_SRC_NOT_SUPPORTED (kod 4)\n // fırlatıyor ve hata ekranı gerçek kaynak yüklenirken açılıyordu. Yeni `src` ataması yükleme\n // algoritmasını zaten baştan başlatıyor (önceki kaynak iptal edilir).\n\n const sourceType = detectSourceType(src, type);\n // Önceki kaynağın HLS kalite listesi kalmasın.\n this.onLevelsChanged([], -1);\n\n // MP4 veya uzantısı belirlenemeyen doğrudan video kaynağı.\n if (sourceType !== 'hls') {\n this.engineInfo = { engine: 'native' };\n this.video.src = src;\n return;\n }\n\n const canNative = this.video.canPlayType('application/vnd.apple.mpegurl') !== '';\n // Safari / iOS: native HLS (başarısız olursa probeNativeHls hls.js'e geçer). MSE yoksa da tek yol native.\n if (canNative && (prefersNativeHls() || !hasMse())) {\n this.loadNativeHls(src, prefersNativeHls() ? 'apple-native' : 'no-mse');\n return;\n }\n\n await this.attachHlsJs(src);\n }\n\n /** Şu anki oynatma yolu — docs demosu/entegratör teşhisi için (ör. CORS yüzünden native'e düşüldü mü). */\n get engine(): PlaybackEngineInfo {\n return this.engineInfo;\n }\n\n private loadNativeHls(src: string, reason: PlaybackEngineInfo['reason']): void {\n this.engineInfo = { engine: 'native-hls', reason };\n this.probeNativeHls(src);\n this.video.src = src;\n }\n\n /** Native HLS denemesi sürüyor mu — ErrorScreen bu sırada gelen hatayı göstermez (hls.js'e geçilecek). */\n isRecovering(): boolean {\n return this.nativeHlsProbe !== null;\n }\n\n /**\n * Bazı ortamlar canPlayType'a \"maybe\" deyip HLS'i native oynatamıyor (bazı Android tarayıcıları/WebView'lar).\n * İlk metadata'dan önce kod 4 gelirse ve MSE varsa hls.js'e geç.\n */\n private probeNativeHls(src: string): void {\n // hls.js zaten denenip başarısız olduysa (CORS vb.) tekrar hls.js'e dönme.\n if (!hasMse() || this.engineInfo.reason === 'hlsjs-failed') return;\n const onMeta = (): void => cleanup();\n const onError = (): void => {\n const unsupported = this.video.error?.code === 4;\n cleanup();\n if (unsupported) void this.attachHlsJs(src);\n };\n const cleanup = (): void => {\n this.video.removeEventListener('loadedmetadata', onMeta);\n this.video.removeEventListener('error', onError);\n this.nativeHlsProbe = null;\n };\n this.video.addEventListener('loadedmetadata', onMeta);\n this.video.addEventListener('error', onError);\n this.nativeHlsProbe = cleanup;\n }\n\n private async attachHlsJs(src: string): Promise<void> {\n // Diğer tarayıcılar: hls.js'i yalnızca gerektiğinde yükle.\n const { default: Hls } = await import('hls.js');\n // import sırasında başka bir kaynak yüklenmiş olabilir.\n if (this.last?.src !== src) return;\n\n // hls.js desteklenmiyorsa native oynatmayı dene.\n if (!Hls.isSupported()) {\n this.engineInfo = { engine: 'native-hls', reason: 'no-mse' };\n this.video.src = src;\n return;\n }\n\n const hls = new Hls({\n enableWorker: true,\n });\n\n this.hls = hls;\n this.engineInfo = { engine: 'hls.js' };\n let parsed = false;\n\n // Manifest indirilemezse (çoğunlukla CDN'in CORS izni yok — hls.js fetch kullanır, native oynatıcı\n // CORS'a tabi değil) ve tarayıcı native HLS oynatabiliyorsa ona düş: yayın oynar, kalite menüsü olmaz.\n hls.on(Hls.Events.ERROR, (_event, data) => {\n if (!data.fatal || parsed || this.hls !== hls) return;\n // Yalnızca İNDİREMEME (CORS/ağ/zaman aşımı) — bozuk manifest'i native de oynatamaz.\n const loadFailed = [Hls.ErrorDetails.MANIFEST_LOAD_ERROR, Hls.ErrorDetails.MANIFEST_LOAD_TIMEOUT].includes(data.details);\n if (!loadFailed) return;\n if (this.video.canPlayType('application/vnd.apple.mpegurl') === '') return;\n hls.destroy();\n this.hls = null;\n this.loadNativeHls(src, 'hlsjs-failed');\n });\n\n hls.on(Hls.Events.MANIFEST_PARSED, () => {\n parsed = true;\n const levels: HlsQualityLevel[] = hls.levels.map(\n (level, index) => ({\n index,\n height: level.height,\n bitrate: level.bitrate,\n })\n );\n\n this.onLevelsChanged(levels, hls.currentLevel);\n });\n\n hls.on(Hls.Events.LEVEL_SWITCHED, (_event, data) => {\n const levels: HlsQualityLevel[] = hls.levels.map(\n (level, index) => ({\n index,\n height: level.height,\n bitrate: level.bitrate,\n })\n );\n\n // Otomatik (ABR) modda menü \"Otomatik\"i seçili göstersin, o anki seviyeyi değil.\n this.onLevelsChanged(levels, hls.autoLevelEnabled ? -1 : data.level);\n });\n\n hls.attachMedia(this.video);\n hls.loadSource(src);\n }\n\n /** Son kaynağı baştan yükler — hls.js ile oynayan kaynakta da çalışır (çıplak video.load() blob'u yeniden açamaz). */\n reload(): Promise<void> {\n return this.last ? this.load(this.last.src, this.last.type) : Promise.resolve();\n }\n\n /** -1 = otomatik kalite (ABR). */\n setLevel(index: number): void {\n if (this.hls) {\n this.hls.currentLevel = index;\n }\n }\n\n destroy(): void {\n this.nativeHlsProbe?.();\n if (this.hls) {\n this.hls.destroy();\n this.hls = null;\n }\n }\n}\n","/** 83 → \"1:23\", 3661 → \"1:01:01\". NaN/Infinity (henüz metadata yoksa) → \"0:00\". */\nexport function formatTime(seconds: number): string {\n if (!Number.isFinite(seconds) || seconds < 0) return '0:00';\n\n const totalSeconds = Math.floor(seconds);\n const h = Math.floor(totalSeconds / 3600);\n const m = Math.floor((totalSeconds % 3600) / 60);\n const s = totalSeconds % 60;\n\n const mm = h > 0 ? String(m).padStart(2, '0') : String(m);\n const ss = String(s).padStart(2, '0');\n\n return h > 0 ? `${h}:${mm}:${ss}` : `${mm}:${ss}`;\n}\n","import type { HopeLocaleStrings } from '../i18n/types';\nimport { formatTime } from '../utils/format-time';\n\n/**\n * Div tabanlı scrubber (role=\"slider\"). Çizim transform ile (layout tetiklemez), oynarken rAF döngüsü.\n * Chapter modunda zaman ↔ piksel eşlemesi parçaların ölçülmüş geometrisinden.\n */\nexport interface SeekBarChapterRange {\n /** 0–1 arası oran. */\n start: number;\n end: number;\n /** Bu bölümün oynatılmış dolgusunun rengi — verilmezse tema accent'i. */\n color?: string;\n}\n\ninterface ChapterState extends SeekBarChapterRange {\n el: HTMLDivElement;\n bufferedEl: HTMLDivElement;\n playedEl: HTMLDivElement;\n /** seek bar'ın sol kenarına göre px — measureChapters() dolduruyor. */\n left: number;\n width: number;\n}\n\nexport class SeekBar {\n readonly el: HTMLDivElement;\n private readonly trackEl: HTMLDivElement;\n private chaptersEl: HTMLDivElement | null = null;\n private chapters: ChapterState[] = [];\n /** İmlecin üstündeki zaman (varsayılan, plugin gerektirmez) — kendi zamanını gösteren plugin'ler `suppressHoverTime` ile gizler. */\n private readonly hoverTimeEl: HTMLDivElement;\n private readonly hoverTimeSuppressors = new Set<string>();\n private readonly playedEl: HTMLDivElement;\n private readonly bufferedEl: HTMLDivElement;\n private readonly thumbEl: HTMLDivElement;\n private readonly hoverDotEl: HTMLDivElement;\n private readonly video: HTMLVideoElement;\n private readonly labels: HopeLocaleStrings;\n private dragging = false;\n private readonly markerEls: HTMLDivElement[] = [];\n private trackWidth = 0;\n private readonly resizeObserver: ResizeObserver;\n private rafId: number | null = null;\n\n constructor(video: HTMLVideoElement, labels: HopeLocaleStrings) {\n this.video = video;\n this.labels = labels;\n\n this.el = document.createElement('div');\n this.el.setAttribute('part', 'seek-bar');\n // Tıklama alanı (--hp-seek-hit-h) görünür track'ten büyük.\n this.el.className =\n 'hp-seekbar hp:relative hp:h-[var(--hp-seek-hit-h)] hp:flex hp:items-center hp:cursor-pointer hp:group hp:touch-none';\n this.el.setAttribute('role', 'slider');\n this.el.setAttribute('tabindex', '0');\n this.el.setAttribute('aria-label', labels.seekBar);\n this.el.setAttribute('aria-valuemin', '0');\n\n const track = document.createElement('div');\n track.className =\n 'hp:absolute hp:inset-x-0 hp:h-[var(--hp-seek-track-h)] hp:rounded-full hp:bg-on-surface/25 ' +\n 'hp:group-hover:h-[var(--hp-seek-track-h-hover)] hp:transition-[height] hp:duration-150';\n this.el.appendChild(track);\n this.trackEl = track;\n\n this.bufferedEl = document.createElement('div');\n this.bufferedEl.className = 'hp:absolute hp:inset-0 hp:rounded-full hp:bg-on-surface/40';\n this.bufferedEl.style.transformOrigin = 'left';\n this.bufferedEl.style.willChange = 'transform';\n track.appendChild(this.bufferedEl);\n\n this.playedEl = document.createElement('div');\n this.playedEl.className = 'hp:absolute hp:inset-0 hp:rounded-full hp:bg-accent';\n this.playedEl.style.transformOrigin = 'left';\n this.playedEl.style.willChange = 'transform';\n track.appendChild(this.playedEl);\n\n // Boyut/ölçek tailwind.css'te (.hp-seek-thumb): her zaman görünür ve küçük, seek bar hover'ında büyür.\n this.thumbEl = document.createElement('div');\n this.thumbEl.className = 'hp-seek-thumb';\n this.thumbEl.setAttribute('part', 'seek-thumb');\n this.el.appendChild(this.thumbEl);\n\n // İmlecin altındaki küçük nokta — nereye tıklanacağını gösterir.\n this.hoverDotEl = document.createElement('div');\n this.hoverDotEl.className = 'hp-seek-hover-dot';\n this.hoverDotEl.setAttribute('part', 'seek-hover-dot');\n this.el.appendChild(this.hoverDotEl);\n\n this.hoverTimeEl = document.createElement('div');\n this.hoverTimeEl.className = 'hp-seek-time';\n this.hoverTimeEl.setAttribute('part', 'seek-time');\n this.el.appendChild(this.hoverTimeEl);\n\n this.el.addEventListener('pointerdown', this.onPointerDown);\n this.el.addEventListener('pointermove', this.onHoverMove);\n this.el.addEventListener('pointerleave', this.onHoverLeave);\n this.el.addEventListener('keydown', this.onKeyDown);\n video.addEventListener('play', this.startLoop);\n video.addEventListener('pause', this.stopLoop);\n video.addEventListener('ended', this.stopLoop);\n // rAF döngüsü yalnızca OYNARKEN çalışır — duraklıyken/scrub ederken\n // (ör. seek sonrası henüz play tetiklenmeden) konum hâlâ güncel\n // kalsın diye timeupdate/progress/loadedmetadata da dinleniyor.\n video.addEventListener('timeupdate', this.render);\n video.addEventListener('progress', this.render);\n video.addEventListener('loadedmetadata', this.render);\n if (!video.paused) this.startLoop();\n\n this.resizeObserver = new ResizeObserver(() => {\n this.trackWidth = this.el.getBoundingClientRect().width;\n this.measureChapters();\n this.render();\n });\n this.resizeObserver.observe(this.el);\n this.trackWidth = this.el.getBoundingClientRect().width;\n }\n\n /** Kendi zamanını gösteren plugin'ler (sprite/segments) varsayılan hover zamanını gizler — keyed set. */\n suppressHoverTime(key: string, suppressed: boolean): void {\n if (suppressed) this.hoverTimeSuppressors.add(key);\n else this.hoverTimeSuppressors.delete(key);\n if (suppressed) this.hoverTimeEl.removeAttribute('data-visible');\n }\n\n private readonly onHoverMove = (e: PointerEvent): void => {\n const duration = this.video.duration;\n const hasDuration = Number.isFinite(duration) && duration > 0;\n const ratio = this.ratioAtClientX(e.clientX);\n\n // Hover noktası: sürüklerken gösterilmez (thumb zaten imlecin altında); canlıda sarılacak konum yok.\n if (hasDuration && !this.dragging) {\n this.hoverDotEl.style.transform = `translate(${this.xAtRatio(ratio)}px, -50%) translateX(-50%)`;\n this.hoverDotEl.setAttribute('data-visible', '');\n } else {\n this.hoverDotEl.removeAttribute('data-visible');\n }\n\n // Canlı yayında (Infinity) süre yok — live-wall-clock'un kendi tooltip'i var.\n if (this.hoverTimeSuppressors.size || !hasDuration) {\n this.hoverTimeEl.removeAttribute('data-visible');\n return;\n }\n this.hoverTimeEl.textContent = formatTime(ratio * duration);\n this.hoverTimeEl.setAttribute('data-visible', '');\n // İmleci ortala, seek bar kenarlarından taşma.\n const rect = this.el.getBoundingClientRect();\n const w = this.hoverTimeEl.offsetWidth;\n const x = Math.min(Math.max(e.clientX - rect.left - w / 2, 0), Math.max(rect.width - w, 0));\n this.hoverTimeEl.style.transform = `translateX(${x}px)`;\n };\n\n private readonly onHoverLeave = (): void => {\n this.hoverTimeEl.removeAttribute('data-visible');\n this.hoverDotEl.removeAttribute('data-visible');\n };\n\n private ratioFromEvent(e: PointerEvent): number {\n return this.ratioAtClientX(e.clientX);\n }\n\n /** Ekran x koordinatını 0–1 zaman oranına çevirir — chapter modunda parça boşluklarını hesaba katar (segments plugin'inin hover popup'ı da bunu kullanıyor). */\n ratioAtClientX(clientX: number): number {\n const rect = this.el.getBoundingClientRect();\n const x = clientX - rect.left;\n if (!this.chapters.length) return Math.min(1, Math.max(0, x / rect.width));\n\n for (let i = 0; i < this.chapters.length; i++) {\n const c = this.chapters[i]!;\n const next = this.chapters[i + 1];\n // Parçanın kendisi + ardından gelen boşluk bu parçaya ait sayılıyor.\n const zoneEnd = next ? next.left : Infinity;\n if (x < zoneEnd || !next) {\n const local = c.width > 0 ? Math.min(1, Math.max(0, (x - c.left) / c.width)) : 0;\n return c.start + local * (c.end - c.start);\n }\n }\n return 1;\n }\n\n /** 0–1 zaman oranının seek bar üzerindeki px konumu (thumb için). */\n private xAtRatio(ratio: number): number {\n if (!this.chapters.length) return ratio * this.trackWidth;\n const c = this.chapters.find((ch) => ratio < ch.end) ?? this.chapters[this.chapters.length - 1]!;\n const span = c.end - c.start;\n const local = span > 0 ? Math.min(1, Math.max(0, (ratio - c.start) / span)) : 0;\n return c.left + local * c.width;\n }\n\n /** Track'i sıralı, 0→1'i kesintisiz kapsayan oran aralıklarına göre ayrı parçalara böler. */\n setChapters(ranges: SeekBarChapterRange[]): HTMLDivElement[] {\n this.clearChapters();\n if (!ranges.length) return [];\n\n const container = document.createElement('div');\n container.className = 'hp-chapters';\n this.chapters = ranges.map((r) => {\n const el = document.createElement('div');\n el.className = 'hp-chapter';\n el.setAttribute('part', 'segment-band');\n el.style.flex = `${Math.max(r.end - r.start, 0)} 1 0px`;\n\n const bufferedEl = document.createElement('div');\n bufferedEl.className = 'hp-chapter-fill hp-chapter-buffered';\n const playedEl = document.createElement('div');\n playedEl.className = 'hp-chapter-fill hp-chapter-played';\n if (r.color) playedEl.style.background = r.color;\n el.append(bufferedEl, playedEl);\n container.appendChild(el);\n return { ...r, el, bufferedEl, playedEl, left: 0, width: 0 };\n });\n\n // Tek track gizleniyor, parçalar onun yerini alıyor (thumb/marker'lar üstte kalsın diye track'ten hemen sonra).\n this.trackEl.style.display = 'none';\n this.trackEl.after(container);\n this.chaptersEl = container;\n this.measureChapters();\n this.render();\n return this.chapters.map((c) => c.el);\n }\n\n clearChapters(): void {\n this.chaptersEl?.remove();\n this.chaptersEl = null;\n this.chapters = [];\n this.trackEl.style.display = '';\n this.render();\n }\n\n private measureChapters(): void {\n if (!this.chapters.length) return;\n const base = this.el.getBoundingClientRect().left;\n for (const c of this.chapters) {\n const r = c.el.getBoundingClientRect();\n c.left = r.left - base;\n c.width = r.width;\n }\n }\n\n private readonly onPointerDown = (e: PointerEvent): void => {\n this.dragging = true;\n this.hoverDotEl.removeAttribute('data-visible');\n this.el.setPointerCapture(e.pointerId);\n this.seekToRatio(this.ratioFromEvent(e));\n this.el.addEventListener('pointermove', this.onPointerMove);\n this.el.addEventListener('pointerup', this.onPointerUp);\n };\n\n private readonly onPointerMove = (e: PointerEvent): void => {\n if (!this.dragging) return;\n this.seekToRatio(this.ratioFromEvent(e));\n };\n\n private readonly onPointerUp = (e: PointerEvent): void => {\n this.dragging = false;\n this.el.releasePointerCapture(e.pointerId);\n this.el.removeEventListener('pointermove', this.onPointerMove);\n this.el.removeEventListener('pointerup', this.onPointerUp);\n };\n\n /** Odaktayken ←/→ sarma süresi (sn) — player'ın klavye kısayoluyla aynı (options.keyboardSeekStep). */\n keyboardStep = 5;\n /** Odaktayken ok tuşuyla sarıldığında (sn, negatif = geri) — sarma bildirimi için. */\n onKeyboardSeek: ((delta: number) => void) | null = null;\n\n private readonly onKeyDown = (e: KeyboardEvent): void => {\n const duration = this.video.duration || 0;\n if (!Number.isFinite(duration) || duration <= 0) return;\n\n if (e.key === 'ArrowRight') {\n this.video.currentTime = Math.min(duration, this.video.currentTime + this.keyboardStep);\n this.onKeyboardSeek?.(this.keyboardStep);\n e.preventDefault();\n } else if (e.key === 'ArrowLeft') {\n this.video.currentTime = Math.max(0, this.video.currentTime - this.keyboardStep);\n this.onKeyboardSeek?.(-this.keyboardStep);\n e.preventDefault();\n }\n };\n\n private seekToRatio(ratio: number): void {\n const duration = this.video.duration;\n if (!Number.isFinite(duration) || duration <= 0) return;\n this.video.currentTime = ratio * duration;\n // video'nun kendi 'timeupdate'i asenkron/gecikmeli olabilir —\n // sürüklerken parmak/imleçle thumb arasında gecikme hissi\n // bırakmamak için konumu HEMEN, burada çiziyoruz.\n this.render();\n }\n\n private readonly startLoop = (): void => {\n if (this.rafId !== null) return;\n const tick = (): void => {\n this.render();\n this.rafId = requestAnimationFrame(tick);\n };\n this.rafId = requestAnimationFrame(tick);\n };\n\n private readonly stopLoop = (): void => {\n if (this.rafId !== null) {\n cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n this.render();\n };\n\n private readonly render = (): void => {\n const duration = this.video.duration;\n // Süre yoksa (canlı yayın / henüz metadata yok) thumb gizlenir — CSS `.hp-seekbar[data-no-duration]`.\n this.el.toggleAttribute('data-no-duration', !Number.isFinite(duration) || duration <= 0);\n if (!Number.isFinite(duration) || duration <= 0) {\n this.playedEl.style.transform = 'scaleX(0)';\n this.thumbEl.style.translate = '-50% 0';\n this.bufferedEl.style.transform = 'scaleX(0)';\n return;\n }\n\n const playedRatio = this.video.currentTime / duration;\n // `translate` (transform DEĞİL): CSS'teki `scale` transform'u da ölçekleyip konumu kaydırırdı.\n this.thumbEl.style.translate = `calc(${this.xAtRatio(playedRatio)}px - 50%) 0`;\n\n let bufferedEnd = 0;\n for (let i = 0; i < this.video.buffered.length; i++) {\n if (this.video.buffered.start(i) <= this.video.currentTime) {\n bufferedEnd = Math.max(bufferedEnd, this.video.buffered.end(i));\n }\n }\n const bufferedRatio = bufferedEnd / duration;\n\n if (this.chapters.length) {\n // Her parça kendi yerel oranıyla dolar: önceki parçalar tam, sonrakiler boş.\n for (const c of this.chapters) {\n const span = c.end - c.start;\n const local = (r: number): number => (span > 0 ? Math.min(1, Math.max(0, (r - c.start) / span)) : 0);\n c.playedEl.style.transform = `scaleX(${local(playedRatio)})`;\n c.bufferedEl.style.transform = `scaleX(${local(bufferedRatio)})`;\n }\n } else {\n this.playedEl.style.transform = `scaleX(${playedRatio})`;\n this.bufferedEl.style.transform = `scaleX(${bufferedRatio})`;\n }\n\n this.el.setAttribute('aria-valuemax', String(Math.floor(duration)));\n this.el.setAttribute('aria-valuenow', String(Math.floor(this.video.currentTime)));\n };\n\n /** 0–1 arası oranda, seek bar üzerine ince bir işaret çizgisi ekler (ör. loop A/B noktaları). */\n addMarker(ratio: number, extraClass = ''): HTMLDivElement {\n const marker = document.createElement('div');\n marker.className = `hp:absolute hp:top-0 hp:bottom-0 hp:w-0.5 hp:bg-on-surface hp:pointer-events-none ${extraClass}`;\n marker.style.left = `${Math.min(1, Math.max(0, ratio)) * 100}%`;\n this.el.appendChild(marker);\n this.markerEls.push(marker);\n return marker;\n }\n\n clearMarkers(): void {\n this.markerEls.forEach((m) => m.remove());\n this.markerEls.length = 0;\n }\n\n refreshLabels(): void {\n this.el.setAttribute('aria-label', this.labels.seekBar);\n }\n\n destroy(): void {\n if (this.rafId !== null) cancelAnimationFrame(this.rafId);\n this.resizeObserver.disconnect();\n this.el.removeEventListener('pointermove', this.onHoverMove);\n this.el.removeEventListener('pointerleave', this.onHoverLeave);\n this.video.removeEventListener('play', this.startLoop);\n this.video.removeEventListener('pause', this.stopLoop);\n this.video.removeEventListener('ended', this.stopLoop);\n this.video.removeEventListener('timeupdate', this.render);\n this.video.removeEventListener('progress', this.render);\n this.video.removeEventListener('loadedmetadata', this.render);\n this.clearMarkers();\n this.chaptersEl?.remove();\n }\n}\n","/** <i class=\"hp-icon hp-icon-NAME\"> oluşturur — font yüklemesi theme/icons/hope-icons.css'de. */\nexport function createIcon(name: string, extraClass = ''): HTMLElement {\n const el = document.createElement('i');\n el.className = `hp-icon hp-icon-${name}${extraClass ? ` ${extraClass}` : ''}`;\n el.setAttribute('aria-hidden', 'true');\n return el;\n}\n\n/** Var olan bir <i class=\"hp-icon ...\"> elementinin glyph'ini değiştirir (hp-icon-X -> hp-icon-Y). */\nexport function setIconName(el: HTMLElement, name: string): void {\n el.className = el.className.replace(/hp-icon-[\\w-]+/, `hp-icon-${name}`);\n}\n","import { createIcon, setIconName } from '../icons/Icon';\nimport type { HopeLocaleStrings } from '../i18n/types';\n\n/** Scroll ile ses adımı (tekerlek/trackpad cihazları arası tutarlılık için deltaY'in BÜYÜKLÜĞÜ değil YÖNÜ kullanılıyor — her \"tık\" sabit bir adım). */\nconst WHEEL_VOLUME_STEP = 0.05;\n/** Butondan panele geçerken gerçek (0px) bir boşluk olmasa bile, fare bir an için ikisinin de dışına çıkarsa paneli hemen kapatmamak için kısa bir tolerans. */\nconst HIDE_DELAY_MS = 150;\n\n/** Reklam sırasında ses reklamın sesini yönetir — IMA reklamı içerikten ayrı bir video'da oynatır. */\nexport interface VolumePanelAdHooks {\n isAdActive(): boolean;\n getVolume(): number;\n setVolume(volume: number): void;\n toggleMute(): void;\n}\n\n/** Mute toggle + hover'da açılan dikey ses çubuğu. */\nexport class VolumePanel {\n readonly el: HTMLDivElement;\n /** Dokunmatikte ses butonu gizli; sessiz oynarken görünen \"Sesi aç\" rozeti (chrome dışında monte edilir, otomatik gizlenmez). */\n readonly unmuteBadge: HTMLButtonElement;\n private readonly unmuteText: HTMLSpanElement;\n private readonly button: HTMLButtonElement;\n private readonly iconEl: HTMLElement;\n private readonly slider: HTMLDivElement;\n private readonly sliderFill: HTMLDivElement;\n private readonly video: HTMLVideoElement;\n private readonly labels: HopeLocaleStrings;\n private readonly adHooks: VolumePanelAdHooks;\n private dragging = false;\n private hideTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(video: HTMLVideoElement, labels: HopeLocaleStrings, adHooks: VolumePanelAdHooks) {\n this.video = video;\n this.labels = labels;\n this.adHooks = adHooks;\n\n this.el = document.createElement('div');\n this.el.className = 'hp-volume hp:relative hp:flex hp:items-center';\n\n this.unmuteBadge = document.createElement('button');\n this.unmuteBadge.type = 'button';\n this.unmuteBadge.className = 'hp-unmute-badge';\n this.unmuteBadge.setAttribute('part', 'unmute-badge');\n this.unmuteBadge.appendChild(createIcon('volume-muted', 'hp:text-base'));\n this.unmuteText = document.createElement('span');\n this.unmuteText.textContent = labels.unmute;\n this.unmuteBadge.appendChild(this.unmuteText);\n // Videoya dokunma = oynat/duraklat (HopePlayerElement) — rozete dokunmak onu tetiklemesin.\n this.unmuteBadge.addEventListener('pointerdown', (e) => e.stopPropagation());\n this.unmuteBadge.addEventListener('click', (e) => {\n e.stopPropagation();\n this.unmute();\n });\n\n this.button = document.createElement('button');\n this.button.type = 'button';\n this.button.setAttribute('part', 'volume-button');\n this.button.className =\n 'hp-chip hp:flex hp:items-center hp:justify-center hp:w-[var(--hp-ctrl-btn-size)] hp:h-[var(--hp-ctrl-btn-size)] hp:cursor-pointer';\n this.button.setAttribute('aria-label', labels.mute);\n this.button.dataset.shortcut = 'M';\n\n this.iconEl = createIcon('volume-high', 'hp:text-[length:var(--hp-ctrl-icon-size)]');\n this.button.appendChild(this.iconEl);\n this.el.appendChild(this.button);\n\n // Dikey panel butonun hemen üstünde, arada boşluk yok; görünürlük JS (mouseenter/mouseleave + kısa gecikme) —\n // CSS :hover'da aradaki boşluk paneli kapatıyordu.\n this.slider = document.createElement('div');\n this.slider.setAttribute('part', 'volume-slider');\n this.slider.className =\n 'hp-chip hp:absolute hp:bottom-full hp:left-1/2 hp-center-x hp:mb-2 ' +\n 'hp:w-7 hp:h-20 hp:rounded-full hp:cursor-pointer ' +\n 'hp:flex hp:items-end hp:justify-center hp:p-1.5 ' +\n 'hp:pointer-events-none hp:transition-opacity hp:duration-150 hp:will-change-[opacity]';\n this.slider.style.opacity = '0';\n // .hp-chip'in kendi --hp-chip-radius'u (plain CSS, Tailwind utility'lerinden\n // SONRA derleniyor) rounded-full'u ezer — tam pil şekli için inline override.\n this.slider.style.borderRadius = '9999px';\n this.slider.setAttribute('role', 'slider');\n this.slider.setAttribute('tabindex', '0');\n this.slider.setAttribute('aria-label', labels.volume);\n this.slider.setAttribute('aria-orientation', 'vertical');\n this.slider.setAttribute('aria-valuemin', '0');\n this.slider.setAttribute('aria-valuemax', '100');\n\n const track = document.createElement('div');\n track.className = 'hp:relative hp:w-1.5 hp:h-full hp:rounded-full hp:bg-on-surface/25 hp:overflow-hidden';\n this.slider.appendChild(track);\n\n this.sliderFill = document.createElement('div');\n this.sliderFill.className = 'hp:absolute hp:inset-x-0 hp:bottom-0 hp:bg-accent';\n track.appendChild(this.sliderFill);\n\n this.el.appendChild(this.slider);\n\n this.button.addEventListener('click', this.onToggleMute);\n this.slider.addEventListener('pointerdown', this.onSliderPointerDown);\n this.slider.addEventListener('keydown', this.onSliderKeyDown);\n this.el.addEventListener('mouseenter', this.openNow);\n this.el.addEventListener('mouseleave', this.scheduleHide);\n this.el.addEventListener('focusin', this.openNow);\n this.el.addEventListener('focusout', this.scheduleHide);\n // Buton VEYA panelin üzerindeyken tekerlek/trackpad ile ses ayarı —\n // sayfanın kendisinin kaymasını önlemek için preventDefault.\n this.el.addEventListener('wheel', this.onWheel, { passive: false });\n video.addEventListener('volumechange', this.render);\n video.addEventListener('play', this.render);\n video.addEventListener('pause', this.render);\n\n this.render();\n }\n\n private readonly openNow = (): void => {\n if (this.hideTimer) {\n clearTimeout(this.hideTimer);\n this.hideTimer = null;\n }\n this.slider.style.opacity = '1';\n this.slider.style.pointerEvents = 'auto';\n };\n\n private readonly scheduleHide = (): void => {\n if (this.hideTimer) clearTimeout(this.hideTimer);\n this.hideTimer = setTimeout(() => {\n this.hideTimer = null;\n this.slider.style.opacity = '0';\n this.slider.style.pointerEvents = 'none';\n }, HIDE_DELAY_MS);\n };\n\n private readonly onWheel = (e: WheelEvent): void => {\n e.preventDefault();\n if (this.adHooks.isAdActive()) {\n const current = this.adHooks.getVolume();\n this.adHooks.setVolume(Math.min(1, Math.max(0, current + (e.deltaY < 0 ? WHEEL_VOLUME_STEP : -WHEEL_VOLUME_STEP))));\n this.render();\n return;\n }\n const current = this.video.muted ? 0 : this.video.volume;\n const next = Math.min(1, Math.max(0, current + (e.deltaY < 0 ? WHEEL_VOLUME_STEP : -WHEEL_VOLUME_STEP)));\n this.video.volume = next;\n this.video.muted = next === 0;\n };\n\n /** \"Sesi aç\" rozeti: yalnızca AÇAR (toggle değil) — reklam sırasında reklamın sesini. */\n private unmute(): void {\n if (this.adHooks.isAdActive()) {\n if (this.adHooks.getVolume() === 0) this.adHooks.toggleMute();\n this.render();\n return;\n }\n this.video.muted = false;\n if (this.video.volume === 0) this.video.volume = 0.5;\n }\n\n private readonly onToggleMute = (): void => {\n if (this.adHooks.isAdActive()) {\n this.adHooks.toggleMute();\n this.render();\n return;\n }\n this.video.muted = !this.video.muted;\n if (!this.video.muted && this.video.volume === 0) this.video.volume = 0.5;\n };\n\n /** Dikey çubukta: üst = tam ses (1), alt = sessiz (0) — Y ekseni ters çevrilir. */\n private setFromClientY(clientY: number): void {\n const rect = this.slider.getBoundingClientRect();\n const ratio = rect.height > 0 ? 1 - Math.min(1, Math.max(0, (clientY - rect.top) / rect.height)) : 0;\n if (this.adHooks.isAdActive()) {\n this.adHooks.setVolume(ratio);\n this.render();\n return;\n }\n this.video.volume = ratio;\n this.video.muted = ratio === 0;\n }\n\n private readonly onSliderPointerDown = (e: PointerEvent): void => {\n this.dragging = true;\n this.slider.setPointerCapture(e.pointerId);\n this.setFromClientY(e.clientY);\n this.slider.addEventListener('pointermove', this.onSliderPointerMove);\n this.slider.addEventListener('pointerup', this.onSliderPointerUp);\n };\n\n private readonly onSliderPointerMove = (e: PointerEvent): void => {\n if (this.dragging) this.setFromClientY(e.clientY);\n };\n\n private readonly onSliderPointerUp = (e: PointerEvent): void => {\n this.dragging = false;\n this.slider.releasePointerCapture(e.pointerId);\n this.slider.removeEventListener('pointermove', this.onSliderPointerMove);\n this.slider.removeEventListener('pointerup', this.onSliderPointerUp);\n };\n\n private readonly onSliderKeyDown = (e: KeyboardEvent): void => {\n if (this.adHooks.isAdActive()) {\n if (e.key === 'ArrowUp') {\n this.adHooks.setVolume(Math.min(1, this.adHooks.getVolume() + 0.1));\n e.preventDefault();\n } else if (e.key === 'ArrowDown') {\n this.adHooks.setVolume(Math.max(0, this.adHooks.getVolume() - 0.1));\n e.preventDefault();\n } else {\n return;\n }\n this.render();\n return;\n }\n if (e.key === 'ArrowUp') {\n this.video.volume = Math.min(1, this.video.volume + 0.1);\n this.video.muted = false;\n e.preventDefault();\n } else if (e.key === 'ArrowDown') {\n this.video.volume = Math.max(0, this.video.volume - 0.1);\n e.preventDefault();\n }\n };\n\n private readonly render = (): void => {\n const effectiveVolume = this.adHooks.isAdActive() ? this.adHooks.getVolume() : this.video.muted ? 0 : this.video.volume;\n this.sliderFill.style.height = `${effectiveVolume * 100}%`;\n this.slider.setAttribute('aria-valuenow', String(Math.round(effectiveVolume * 100)));\n\n const label = effectiveVolume === 0 ? this.labels.unmute : this.labels.mute;\n this.button.setAttribute('aria-label', label);\n // Rozet: sessizken ve oynarken (ya da reklam varken) — duraklatılmış bir kapak karesinde kalabalık etmesin.\n const playing = this.adHooks.isAdActive() || !this.video.paused;\n this.unmuteBadge.toggleAttribute('data-visible', effectiveVolume === 0 && playing);\n this.unmuteText.textContent = this.labels.unmute;\n if (effectiveVolume === 0) setIconName(this.iconEl, 'volume-muted');\n else if (effectiveVolume < 0.5) setIconName(this.iconEl, 'volume-low');\n else setIconName(this.iconEl, 'volume-high');\n };\n\n refreshLabels(): void {\n this.slider.setAttribute('aria-label', this.labels.volume);\n this.render();\n }\n\n /** Reklam modu açılıp/kapanınca (`ControlBar.setAdMode`) görüntüyü hemen ad/içerik ses kaynağına göre tazeler — `volumechange` event'i beklemeden. */\n refreshForAdMode(): void {\n this.render();\n }\n\n setIconColor(color: string): void {\n this.iconEl.style.color = color;\n }\n\n setSliderFillColor(color: string): void {\n this.sliderFill.style.background = color;\n }\n\n destroy(): void {\n if (this.hideTimer) clearTimeout(this.hideTimer);\n this.el.removeEventListener('mouseenter', this.openNow);\n this.el.removeEventListener('mouseleave', this.scheduleHide);\n this.el.removeEventListener('focusin', this.openNow);\n this.el.removeEventListener('focusout', this.scheduleHide);\n this.el.removeEventListener('wheel', this.onWheel);\n this.video.removeEventListener('volumechange', this.render);\n this.video.removeEventListener('play', this.render);\n this.video.removeEventListener('pause', this.render);\n this.unmuteBadge.remove();\n }\n}\n","import { createIcon } from '../icons/Icon';\nimport type { HopeLocaleStrings } from '../i18n/types';\n\nexport interface SettingsQualityOption {\n label: string;\n onSelect: () => void;\n}\n\nexport interface SettingsCaptionOption {\n label: string;\n onSelect: () => void;\n}\n\nexport interface SettingsSubmenuItem {\n label: string;\n active: boolean;\n onSelect: () => void;\n}\n\n/** Bir renk paleti satırındaki tek bir swatch — `value` hem swatch'ın KENDİ arkaplanı hem de uygulanacak CSS rengi. */\nexport interface SettingsColorOption {\n value: string;\n active: boolean;\n ariaLabel: string;\n onSelect: () => void;\n}\n\n/** Altyazı açıkken \"Altyazı\" alt menüsüne eklenen görünüm ayarları (boyut, renkler, konumu sıfırla). */\nexport interface SettingsCaptionAppearance {\n sizeLabel: string;\n getSizeOptions: () => SettingsSubmenuItem[];\n bgColorLabel: string;\n getBgColorOptions: () => SettingsColorOption[];\n textColorLabel: string;\n getTextColorOptions: () => SettingsColorOption[];\n resetPositionLabel: string;\n onResetPosition: () => void;\n}\n\n/** Plugin'lerin ana menüye kendi satır + alt menüsünü eklemesi için. */\nexport interface SettingsSubmenuDef {\n key: string;\n title: string;\n getValueLabel: () => string;\n getItems: () => SettingsSubmenuItem[];\n}\n\n/** Ana menüde tek bir aç/kapa satırı — alt menüye inmez. */\nexport interface SettingsToggleRow {\n label: string;\n getValueLabel: () => string;\n onToggle: () => void;\n}\n\ntype PanelId = 'main' | 'speed' | 'quality' | 'captions' | 'captions-size' | 'captions-bg' | 'captions-text' | `custom:${string}`;\n\n/** Ayarlar butonu + popup: ana liste (Hız/Kalite/Altyazı) → alt liste. */\n/** Menü ile buton arası boşluk ve player kenarına bırakılan pay (px). */\nconst MENU_GAP_PX = 8;\nconst MENU_EDGE_PX = 8;\n/** Panel yüksekliği: buton yanında bundan az yer varsa menü player kenarından açılır; üst sınır eski max-h-64. */\nconst MENU_MIN_HEIGHT_PX = 100;\nconst MENU_MAX_HEIGHT_PX = 256;\n\nexport class SettingsMenu {\n readonly el: HTMLDivElement;\n private readonly button: HTMLButtonElement;\n private readonly panel: HTMLDivElement;\n private readonly video: HTMLVideoElement;\n private readonly playbackRates: number[];\n private readonly labels: HopeLocaleStrings;\n\n private qualities: SettingsQualityOption[] = [];\n private activeQualityLabel: string;\n private captions: SettingsCaptionOption[] = [];\n private activeCaptionLabel: string;\n private captionAppearance: SettingsCaptionAppearance | null = null;\n private qrResumeToggle: SettingsToggleRow | null = null;\n private open = false;\n /** Menü açılıp kapanınca — HopePlayerElement açıkken kontrolleri otomatik gizlemez. */\n onOpenChange: ((open: boolean) => void) | null = null;\n private readonly panelObserver: MutationObserver;\n private currentPanel: PanelId = 'main';\n private submenus: SettingsSubmenuDef[] = [];\n\n constructor(video: HTMLVideoElement, playbackRates: number[], labels: HopeLocaleStrings) {\n this.video = video;\n this.playbackRates = playbackRates;\n this.labels = labels;\n this.activeQualityLabel = labels.autoQuality;\n this.activeCaptionLabel = labels.captionsOff;\n\n this.el = document.createElement('div');\n this.el.className = 'hp:relative';\n\n this.button = document.createElement('button');\n this.button.type = 'button';\n this.button.setAttribute('aria-label', labels.settings);\n this.button.className =\n 'hp-chip hp:flex hp:items-center hp:justify-center hp:w-[var(--hp-ctrl-btn-size)] hp:h-[var(--hp-ctrl-btn-size)] hp:cursor-pointer';\n this.button.appendChild(createIcon('settings', 'hp:text-[length:var(--hp-ctrl-icon-size)]'));\n\n this.panel = document.createElement('div');\n this.panel.className =\n 'hp-chip hp-chip-panel hp:hidden hp:absolute hp:bottom-full hp:right-0 hp:mb-2 hp:w-48 hp:max-h-64 hp:overflow-y-auto hp:text-sm hp:py-1';\n // Alt menüye geçince içerik yüksekliği değişir — yerleşimi yeniden hesapla.\n this.panelObserver = new MutationObserver(this.fitToPlayer);\n this.panelObserver.observe(this.panel, { childList: true });\n\n this.el.appendChild(this.button);\n this.el.appendChild(this.panel);\n\n this.button.addEventListener('click', (e) => {\n e.stopPropagation();\n this.toggle();\n });\n document.addEventListener('click', this.onDocumentClick, true);\n\n this.renderMain();\n }\n\n setQualities(options: SettingsQualityOption[], activeLabel: string): void {\n this.qualities = options;\n this.activeQualityLabel = activeLabel;\n if (this.currentPanel === 'main' || this.currentPanel === 'quality') this.render();\n }\n\n setCaptions(options: SettingsCaptionOption[], activeLabel: string): void {\n this.captions = options;\n this.activeCaptionLabel = activeLabel;\n if (this.currentPanel === 'main' || this.currentPanel === 'captions') this.render();\n }\n\n /** Seçili altyazıyı dışarıdan günceller (ör. iOS native tam ekranda yapılan seçim) — seçenekler aynı kalır. */\n setActiveCaption(label: string): void {\n if (this.activeCaptionLabel === label) return;\n this.activeCaptionLabel = label;\n if (this.currentPanel === 'main' || this.currentPanel === 'captions') this.render();\n }\n\n /** Altyazı AÇIKKEN \"Altyazı\" alt menüsüne eklenecek Boyut/Renk/Konum satırları — `null` kaldırır. */\n setCaptionAppearance(appearance: SettingsCaptionAppearance | null): void {\n this.captionAppearance = appearance;\n if (\n this.currentPanel === 'captions' ||\n this.currentPanel === 'captions-size' ||\n this.currentPanel === 'captions-bg' ||\n this.currentPanel === 'captions-text'\n ) {\n this.render();\n }\n }\n\n /** Ana menüye tek aç/kapa satırı ekler (ör. QrResume). */\n setQrResumeToggle(toggle: SettingsToggleRow | null): void {\n this.qrResumeToggle = toggle;\n if (this.currentPanel === 'main') this.renderMain();\n }\n\n /** Plugin'lerin (ör. dubbing) ana menüye kendi satır + alt menüsünü eklemesi için. */\n registerSubmenu(def: SettingsSubmenuDef): void {\n this.submenus = this.submenus.filter((s) => s.key !== def.key);\n this.submenus.push(def);\n if (this.currentPanel === 'main') this.renderMain();\n }\n\n unregisterSubmenu(key: string): void {\n this.submenus = this.submenus.filter((s) => s.key !== key);\n if (this.currentPanel === 'main') this.renderMain();\n else if (this.currentPanel === `custom:${key}`) this.renderMain();\n }\n\n private toggle(): void {\n this.open ? this.close() : this.openMenu();\n }\n\n private openMenu(): void {\n this.open = true;\n this.currentPanel = 'main';\n this.panel.classList.remove('hp:hidden');\n this.renderMain();\n this.fitToPlayer();\n this.onOpenChange?.(true);\n }\n\n get isOpen(): boolean {\n return this.open;\n }\n\n /** Açıksa menü panelinin ekran dikdörtgeni (tooltip çakışma kontrolü için). */\n get panelRect(): DOMRect | null {\n return this.open ? this.panel.getBoundingClientRect() : null;\n }\n\n /**\n * Yön + yükseklik player'a göre: kompakt düzende (buton üst bardaysa) aşağı açılır; her iki yönde de\n * yükseklik player içinde kalan alanla sınırlı — küçük player'da menü dışarı taşmaz, kendi içinde kayar.\n */\n private readonly fitToPlayer = (): void => {\n if (!this.open) return;\n const area = this.el.closest('.video-area');\n if (!area) return;\n const a = area.getBoundingClientRect();\n const b = this.button.getBoundingClientRect();\n const anchor = this.el.getBoundingClientRect();\n const drop = !!this.el.closest('.hp-top-bar');\n this.panel.toggleAttribute('data-drop', drop);\n Object.assign(this.panel.style, { top: '', bottom: '', marginTop: '', marginBottom: '' });\n\n const content = this.panel.scrollHeight;\n const room = (drop ? a.bottom - b.bottom : b.top - a.top) - MENU_GAP_PX - MENU_EDGE_PX;\n if (content <= room || room >= MENU_MIN_HEIGHT_PX) {\n this.panel.style.maxHeight = `${Math.min(MENU_MAX_HEIGHT_PX, room)}px`;\n return;\n }\n // Butonun yanında yer yok (küçük player) — menü player'ın kenarından başlayıp tüm yüksekliği kullanır.\n this.panel.style.maxHeight = `${Math.min(MENU_MAX_HEIGHT_PX, a.height - 2 * MENU_EDGE_PX)}px`;\n if (drop) Object.assign(this.panel.style, { top: `${a.top + MENU_EDGE_PX - anchor.top}px`, marginTop: '0' });\n else Object.assign(this.panel.style, { bottom: `${anchor.bottom - (a.bottom - MENU_EDGE_PX)}px`, marginBottom: '0' });\n };\n\n /** Düzen değişince (ör. kompakt ↔ normal) açık menüyü kapat — eski konumunda asılı kalmasın. */\n closeMenu(): void {\n if (this.open) this.close();\n }\n\n private close(): void {\n this.open = false;\n this.panel.classList.add('hp:hidden');\n this.onOpenChange?.(false);\n }\n\n private readonly onDocumentClick = (e: MouseEvent): void => {\n // composedPath(): Shadow DOM'da e.target host'a retarget edilir; contains() menünün kendi satırlarını \"dışarı tıklama\" sanardı.\n if (this.open && !e.composedPath().includes(this.el)) this.close();\n };\n\n private row(label: string, value: string, onClick: () => void): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className =\n 'hp:flex hp:items-center hp:justify-between hp:w-full hp:px-3 hp:py-2 hp:text-left hp:bg-transparent hp:border-0 hp:cursor-pointer hp:text-on-surface hp:hover:bg-on-surface/10';\n btn.innerHTML = `<span>${label}</span><span class=\"hp:text-on-surface-muted hp:text-xs hp:flex hp:items-center hp:gap-1\">${value}</span>`;\n btn.addEventListener('click', onClick);\n return btn;\n }\n\n private backRow(title: string, onBack: () => void): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className =\n 'hp:flex hp:items-center hp:gap-2 hp:w-full hp:px-3 hp:py-2 hp:text-left hp:bg-transparent hp:border-0 hp:cursor-pointer hp:text-on-surface hp:font-medium hp:hover:bg-on-surface/10';\n btn.appendChild(createIcon('chevron-left', 'hp:text-sm'));\n const span = document.createElement('span');\n span.textContent = title;\n btn.appendChild(span);\n btn.addEventListener('click', onBack);\n return btn;\n }\n\n private render(): void {\n if (this.currentPanel === 'main') this.renderMain();\n else if (this.currentPanel === 'speed') this.renderSpeed();\n else if (this.currentPanel === 'quality') this.renderQuality();\n else if (this.currentPanel === 'captions') this.renderCaptions();\n else if (this.currentPanel === 'captions-size') this.renderCaptionsSize();\n else if (this.currentPanel === 'captions-bg') this.renderCaptionColorPanel('bg');\n else if (this.currentPanel === 'captions-text') this.renderCaptionColorPanel('text');\n else {\n const key = this.currentPanel.slice('custom:'.length);\n const def = this.submenus.find((s) => s.key === key);\n if (def) this.renderSubmenu(def);\n else this.renderMain();\n }\n }\n\n private renderMain(): void {\n this.currentPanel = 'main';\n this.panel.innerHTML = '';\n this.panel.appendChild(\n this.row(this.labels.playbackSpeed, this.video.playbackRate === 1 ? this.labels.normal : `${this.video.playbackRate}x`, () => {\n this.currentPanel = 'speed';\n this.renderSpeed();\n })\n );\n if (this.qualities.length > 0) {\n this.panel.appendChild(\n this.row(this.labels.quality, this.activeQualityLabel, () => {\n this.currentPanel = 'quality';\n this.renderQuality();\n })\n );\n }\n if (this.captions.length > 0) {\n this.panel.appendChild(\n this.row(this.labels.captions, this.activeCaptionLabel, () => {\n this.currentPanel = 'captions';\n this.renderCaptions();\n })\n );\n }\n for (const def of this.submenus) {\n this.panel.appendChild(\n this.row(def.title, def.getValueLabel(), () => {\n this.currentPanel = `custom:${def.key}`;\n this.renderSubmenu(def);\n })\n );\n }\n if (this.qrResumeToggle) {\n const toggle = this.qrResumeToggle;\n // Menü kapanmadan durumu değiştirip yeniden render eder.\n this.panel.appendChild(\n this.row(toggle.label, toggle.getValueLabel(), () => {\n toggle.onToggle();\n this.renderMain();\n })\n );\n }\n }\n\n private renderSubmenu(def: SettingsSubmenuDef): void {\n this.panel.innerHTML = '';\n this.panel.appendChild(this.backRow(def.title, () => this.renderMain()));\n for (const item of def.getItems()) {\n this.panel.appendChild(\n this.row(item.label, item.active ? '<i class=\"hp-icon hp-icon-check\"></i>' : '', () => {\n item.onSelect();\n this.close();\n })\n );\n }\n }\n\n private renderSpeed(): void {\n this.panel.innerHTML = '';\n this.panel.appendChild(this.backRow(this.labels.playbackSpeed, () => this.renderMain()));\n for (const rate of this.playbackRates) {\n const active = this.video.playbackRate === rate;\n const btn = this.row(rate === 1 ? this.labels.normal : `${rate}x`, active ? '<i class=\"hp-icon hp-icon-check\"></i>' : '', () => {\n this.video.playbackRate = rate;\n this.close();\n });\n this.panel.appendChild(btn);\n }\n }\n\n private renderQuality(): void {\n this.panel.innerHTML = '';\n this.panel.appendChild(this.backRow(this.labels.quality, () => this.renderMain()));\n for (const q of this.qualities) {\n const active = q.label === this.activeQualityLabel;\n this.panel.appendChild(\n this.row(q.label, active ? '<i class=\"hp-icon hp-icon-check\"></i>' : '', () => {\n q.onSelect();\n this.close();\n })\n );\n }\n }\n\n private renderCaptions(): void {\n this.panel.innerHTML = '';\n this.panel.appendChild(this.backRow(this.labels.captions, () => this.renderMain()));\n for (const c of this.captions) {\n const active = c.label === this.activeCaptionLabel;\n this.panel.appendChild(\n this.row(c.label, active ? '<i class=\"hp-icon hp-icon-check\"></i>' : '', () => {\n c.onSelect();\n this.close();\n })\n );\n }\n // Boyut/Renk/Konum satırları altyazı KAPALIYKEN anlamsız — yalnızca bir dil seçiliyken gösteriliyor.\n if (this.captionAppearance && this.activeCaptionLabel !== this.labels.captionsOff) {\n const appearance = this.captionAppearance;\n this.panel.appendChild(\n this.row(appearance.sizeLabel, '', () => {\n this.currentPanel = 'captions-size';\n this.renderCaptionsSize();\n })\n );\n this.panel.appendChild(\n this.row(appearance.bgColorLabel, '', () => {\n this.currentPanel = 'captions-bg';\n this.renderCaptionColorPanel('bg');\n })\n );\n this.panel.appendChild(\n this.row(appearance.textColorLabel, '', () => {\n this.currentPanel = 'captions-text';\n this.renderCaptionColorPanel('text');\n })\n );\n this.panel.appendChild(\n this.row(appearance.resetPositionLabel, '', () => {\n appearance.onResetPosition();\n this.close();\n })\n );\n }\n }\n\n private renderCaptionsSize(): void {\n this.panel.innerHTML = '';\n const appearance = this.captionAppearance;\n this.panel.appendChild(this.backRow(appearance?.sizeLabel ?? this.labels.captionSize, () => this.renderCaptions()));\n if (!appearance) return;\n for (const item of appearance.getSizeOptions()) {\n this.panel.appendChild(\n this.row(item.label, item.active ? '<i class=\"hp-icon hp-icon-check\"></i>' : '', () => {\n item.onSelect();\n this.close();\n })\n );\n }\n }\n\n /** \"Arka Plan Rengi\" / \"Yazı Rengi\" — düz metin satırları yerine renkli swatch grid'i (YouTube'un kendi altyazı renk seçici deseni). */\n private renderCaptionColorPanel(kind: 'bg' | 'text'): void {\n this.panel.innerHTML = '';\n const appearance = this.captionAppearance;\n const title = kind === 'bg' ? (appearance?.bgColorLabel ?? this.labels.captionBgColor) : (appearance?.textColorLabel ?? this.labels.captionTextColor);\n this.panel.appendChild(this.backRow(title, () => this.renderCaptions()));\n if (!appearance) return;\n\n const grid = document.createElement('div');\n grid.className = 'hp:flex hp:flex-wrap hp:gap-2 hp:px-3 hp:py-2';\n const options = kind === 'bg' ? appearance.getBgColorOptions() : appearance.getTextColorOptions();\n for (const opt of options) {\n const swatch = document.createElement('button');\n swatch.type = 'button';\n swatch.setAttribute('aria-label', opt.ariaLabel);\n swatch.className = 'hp:w-7 hp:h-7 hp:rounded-full hp:cursor-pointer hp:flex-shrink-0 hp:border hp:border-on-surface/20';\n swatch.style.background = opt.value;\n swatch.style.outline = opt.active ? '2px solid currentColor' : '2px solid transparent';\n swatch.style.outlineOffset = '2px';\n swatch.addEventListener('click', () => {\n opt.onSelect();\n this.render();\n });\n grid.appendChild(swatch);\n }\n this.panel.appendChild(grid);\n }\n\n /** Dil sonradan değişince statik buton etiketini tazeler + mevcut panel zaten güncel `this.labels`'ı okuyarak yeniden render edilir. */\n refreshLabels(): void {\n this.button.setAttribute('aria-label', this.labels.settings);\n this.render();\n }\n\n destroy(): void {\n document.removeEventListener('click', this.onDocumentClick, true);\n this.panelObserver.disconnect();\n }\n}\n","import { SeekBar } from './SeekBar';\nimport { VolumePanel, type VolumePanelAdHooks } from './VolumePanel';\nimport { SettingsMenu, type SettingsCaptionOption, type SettingsQualityOption } from './SettingsMenu';\nimport { formatTime } from '../utils/format-time';\nimport { createIcon, setIconName } from '../icons/Icon';\nimport type { HopeLocaleStrings } from '../i18n/types';\n\n/** `title` bilerek set edilmiyor — tooltip'i Tooltip.ts gösteriyor, native tooltip üstüne binmesin. */\n/** Canlı uçtan bu kadar saniyeden fazla gerideyse rozet \"geride\" (gri) sayılır — HLS'in doğal gecikmesi (birkaç segment) bunun altında kalır. */\nconst LIVE_EDGE_TOLERANCE_SEC = 15;\n/** Player bu genişliğin (px) altındaysa kompakt (mobil) düzen: sağ grup üst sağa, tam ekran altta. */\nconst COMPACT_MAX_WIDTH = 480;\n\n/** Sarma butonu: yuvarlak ok ikonu + ortasında süre. */\nfunction skipButton(direction: 'back' | 'forward', part: string): { btn: HTMLButtonElement; num: HTMLSpanElement } {\n const { btn } = iconButton('', `skip-${direction}`);\n btn.classList.add('hp-skip-btn');\n btn.setAttribute('part', part);\n const num = document.createElement('span');\n num.className = 'hp-skip-num';\n num.setAttribute('aria-hidden', 'true');\n btn.appendChild(num);\n btn.style.display = 'none';\n return { btn, num };\n}\n\nfunction setButtonLabel(btn: HTMLButtonElement, label: string): void {\n btn.setAttribute('aria-label', label);\n}\n\n/** `shortcut`: Tooltip.ts'in gösterdiği küçük \"pill\" (ör. \"F\") — yalnızca `KeyboardController`'daki GERÇEK bir tuşla birebir eşleşiyorsa veriliyor, uydurma değil. */\nfunction iconButton(label: string, iconName: string, shortcut?: string): { btn: HTMLButtonElement; icon: HTMLElement } {\n const btn = document.createElement('button');\n btn.type = 'button';\n setButtonLabel(btn, label);\n if (shortcut) btn.dataset.shortcut = shortcut;\n // hp-chip: tema yüzeyi; boyut --hp-ctrl-* token'larından (fullscreen/dokunmatikte büyür).\n btn.className =\n 'hp-chip hp:flex hp:items-center hp:justify-center hp:w-[var(--hp-ctrl-btn-size)] hp:h-[var(--hp-ctrl-btn-size)] hp:cursor-pointer hp:shrink-0';\n const icon = createIcon(iconName, 'hp:text-[length:var(--hp-ctrl-icon-size)]');\n btn.appendChild(icon);\n return { btn, icon };\n}\n\nexport interface ControlBarCallbacks {\n onRequestFullscreen: () => void;\n onExitFullscreen: () => void;\n isFullscreen: () => boolean;\n /** Reklam modunda oynat/duraklat reklamı yönetir — IMA reklamı içerikten ayrı bir video'da oynatır. */\n isAdActive: () => boolean;\n adTogglePlay: () => void;\n adIsPaused: () => boolean;\n adVolume: VolumePanelAdHooks;\n}\n\n/** Alt kontrol çubuğunu kurar; alt bileşenleri (SeekBar/VolumePanel/SettingsMenu) birleştirir. */\nexport class ControlBar {\n readonly el: HTMLDivElement;\n readonly seekBar: SeekBar;\n readonly volumePanel: VolumePanel;\n readonly settingsMenu: SettingsMenu;\n\n private readonly video: HTMLVideoElement;\n private readonly labels: HopeLocaleStrings;\n private readonly playButton: HTMLButtonElement;\n private readonly playIcon: HTMLElement;\n private readonly pipButton: HTMLButtonElement;\n private readonly skipBack: { btn: HTMLButtonElement; num: HTMLSpanElement };\n private readonly skipForward: { btn: HTMLButtonElement; num: HTMLSpanElement };\n /** Etkin sarma süreleri (sn); null = buton gizli. */\n private skipSeconds: { back: number | null; forward: number | null } = { back: null, forward: null };\n private seekingEnabled = true;\n /** Sarma butonuyla sarıldığında (sn, negatif = geri) — sarma bildirimi için. */\n onSkip: ((delta: number) => void) | null = null;\n private readonly fullscreenButton: HTMLButtonElement;\n private readonly fullscreenIcon: HTMLElement;\n private readonly timeLabel: HTMLButtonElement;\n private showRemaining = false;\n /** Kompakt düzende (player < 480px) sağ grubun taşındığı üst bar; tam ekran altta kalır. */\n readonly topEl: HTMLDivElement;\n private readonly bottomRow: HTMLDivElement;\n private readonly rightGroup: HTMLDivElement;\n private readonly fullscreenSlot: HTMLDivElement;\n private compact = false;\n private readonly resizeObserver: ResizeObserver;\n private readonly liveBadge: HTMLButtonElement;\n private readonly liveText: HTMLSpanElement;\n private adMode = false;\n private readonly callbacks: ControlBarCallbacks;\n private row!: HTMLDivElement;\n private extraButtonAnchor!: HTMLElement;\n\n constructor(video: HTMLVideoElement, playbackRates: number[], callbacks: ControlBarCallbacks, labels: HopeLocaleStrings) {\n this.video = video;\n this.callbacks = callbacks;\n this.labels = labels;\n\n this.el = document.createElement('div');\n this.el.setAttribute('part', 'control-bar');\n // pointer-events-none: kapsayıcı alt şeridin tamamını kaplıyor; açık olsaydı boş alanlar reklamın\n // \"Reklamı Geç\" butonu dahil alttaki tıklamaları yutardı. Yalnızca gerçek yüzeyler pointer-events-auto.\n this.el.className =\n 'hp:absolute hp:inset-x-0 hp:bottom-0 hp:flex hp:flex-col hp:gap-1 hp:px-3 hp:pb-2 hp:pt-6 hp:pointer-events-none ' +\n 'hp:transition-opacity hp:duration-200';\n\n this.seekBar = new SeekBar(video, labels);\n this.seekBar.el.classList.add('hp:pointer-events-auto');\n this.el.appendChild(this.seekBar.el);\n\n const row = document.createElement('div');\n row.className = 'hp:flex hp:items-center hp:gap-2';\n this.el.appendChild(row);\n this.bottomRow = row;\n\n // Sol küme: oynat/duraklat + ses + süre — kendi transparan \"pill\"\n // yüzeyini paylaşıyor (`.hp-group`, theme/tailwind.css).\n const leftGroup = document.createElement('div');\n leftGroup.className = 'hp-group hp:flex hp:items-center hp:gap-1 hp:px-1.5 hp:py-1 hp:shrink-0 hp:pointer-events-auto';\n row.appendChild(leftGroup);\n\n const play = iconButton(labels.play, 'play', 'K');\n this.playButton = play.btn;\n this.playIcon = play.icon;\n this.playButton.setAttribute('part', 'play-pause-button');\n this.playButton.addEventListener('click', () => this.togglePlay());\n leftGroup.appendChild(this.playButton);\n\n this.skipBack = skipButton('back', 'skip-back-button');\n this.skipBack.btn.addEventListener('click', () => this.skip(-(this.skipSeconds.back ?? 0)));\n this.skipForward = skipButton('forward', 'skip-forward-button');\n this.skipForward.btn.addEventListener('click', () => this.skip(this.skipSeconds.forward ?? 0));\n leftGroup.append(this.skipBack.btn, this.skipForward.btn);\n\n this.volumePanel = new VolumePanel(video, labels, callbacks.adVolume);\n leftGroup.appendChild(this.volumePanel.el);\n\n this.timeLabel = document.createElement('button');\n this.timeLabel.type = 'button';\n this.timeLabel.setAttribute('part', 'time-display');\n this.timeLabel.className =\n 'hp:text-xs hp:text-on-surface hp:tabular-nums hp:whitespace-nowrap hp:px-1 hp:bg-transparent hp:border-0 hp:cursor-pointer hp:select-none hp:p-0 hp:hover:opacity-80 hp:transition-opacity hp:focus-visible:outline-none hp:focus-visible:ring-1 hp:focus-visible:ring-accent hp:rounded';\n this.timeLabel.textContent = '0:00 / 0:00';\n this.timeLabel.addEventListener('click', this.onTimeClick);\n leftGroup.appendChild(this.timeLabel);\n\n // Canlı yayında (duration === Infinity) süre etiketinin YERİNE —\n // YouTube tarzı \"● CANLI\": canlı uçtayken nokta kırmızı, geriye\n // sarılmışsa gri ve tıklayınca canlı uca döner.\n this.liveBadge = document.createElement('button');\n this.liveBadge.type = 'button';\n this.liveBadge.className = 'hp-live-badge';\n this.liveBadge.setAttribute('part', 'live-badge');\n this.liveBadge.setAttribute('aria-label', labels.goToLive);\n const liveDot = document.createElement('span');\n liveDot.className = 'hp-live-dot';\n this.liveText = document.createElement('span');\n this.liveText.textContent = labels.live;\n this.liveBadge.append(liveDot, this.liveText);\n this.liveBadge.style.display = 'none';\n this.liveBadge.addEventListener('click', this.goToLive);\n leftGroup.appendChild(this.liveBadge);\n\n const spacer = document.createElement('div');\n spacer.className = 'hp:flex-1';\n row.appendChild(spacer);\n\n // Sağ küme: ayarlar + plugin'lerin addButton/addElement ile eklediği\n // kendi butonları (ayarlardan ÖNCE eklenir) + PIP + tam ekran — aynı\n // pill yüzeyi.\n const rightGroup = document.createElement('div');\n rightGroup.className = 'hp-group hp:flex hp:items-center hp:gap-1 hp:px-1.5 hp:py-1 hp:shrink-0 hp:pointer-events-auto';\n row.appendChild(rightGroup);\n this.rightGroup = rightGroup;\n\n this.settingsMenu = new SettingsMenu(video, playbackRates, labels);\n rightGroup.appendChild(this.settingsMenu.el);\n this.extraButtonAnchor = this.settingsMenu.el;\n this.row = rightGroup;\n\n const pip = iconButton(labels.pip, 'pip');\n this.pipButton = pip.btn;\n this.pipButton.addEventListener('click', () => this.togglePip());\n if (!document.pictureInPictureEnabled) this.pipButton.style.display = 'none';\n rightGroup.appendChild(this.pipButton);\n\n const fullscreen = iconButton(labels.fullscreenEnter, 'fullscreen-enter', 'F');\n this.fullscreenButton = fullscreen.btn;\n this.fullscreenIcon = fullscreen.icon;\n this.fullscreenButton.addEventListener('click', () => this.toggleFullscreen());\n rightGroup.appendChild(this.fullscreenButton);\n\n this.topEl = document.createElement('div');\n this.topEl.className = 'hp-top-bar';\n this.topEl.setAttribute('part', 'top-bar');\n this.fullscreenSlot = document.createElement('div');\n this.fullscreenSlot.className = 'hp-group hp:items-center hp:px-1.5 hp:py-1 hp:shrink-0 hp:pointer-events-auto';\n this.fullscreenSlot.style.display = 'none';\n row.appendChild(this.fullscreenSlot);\n\n this.resizeObserver = new ResizeObserver(() => this.updateLayout());\n this.resizeObserver.observe(this.el);\n\n video.addEventListener('play', this.renderPlayState);\n video.addEventListener('pause', this.renderPlayState);\n video.addEventListener('timeupdate', this.renderTime);\n video.addEventListener('loadedmetadata', this.renderTime);\n video.addEventListener('durationchange', this.renderTime);\n video.addEventListener('progress', this.renderTime);\n this.renderPlayState();\n this.renderTime();\n }\n\n /** Player genişliğine göre normal / kompakt (mobil) düzen arasında geçiş — yalnızca eşik geçilince DOM taşınır. */\n private updateLayout(): void {\n const width = this.el.getBoundingClientRect().width;\n if (width === 0) return;\n const compact = width < COMPACT_MAX_WIDTH;\n if (compact === this.compact) return;\n this.compact = compact;\n this.settingsMenu.closeMenu();\n this.el.toggleAttribute('data-compact', compact);\n // Video alanı da bilsin — altyazı boyutu küçük player'da küçülüyor (tailwind.css `.video-area[data-compact]`).\n this.el.closest('.video-area')?.toggleAttribute('data-compact', compact);\n if (compact) {\n this.fullscreenSlot.appendChild(this.fullscreenButton);\n this.fullscreenSlot.style.display = this.adMode ? 'none' : 'flex';\n this.topEl.appendChild(this.rightGroup);\n } else {\n this.rightGroup.appendChild(this.fullscreenButton);\n this.bottomRow.insertBefore(this.rightGroup, this.fullscreenSlot);\n this.fullscreenSlot.style.display = 'none';\n }\n }\n\n setFullscreenState(isFullscreen: boolean): void {\n setIconName(this.fullscreenIcon, isFullscreen ? 'fullscreen-exit' : 'fullscreen-enter');\n setButtonLabel(this.fullscreenButton, isFullscreen ? this.labels.fullscreenExit : this.labels.fullscreenEnter);\n }\n\n /** Dil sonradan değişince (`options.locale`/`labels`) statik (reaktif olarak yeniden render edilmeyen) etiketleri tazeler. */\n /** Geri/ileri sarma butonları — `null` süre o butonu gizler. */\n setSkipButtons(back: number | null, forward: number | null): void {\n this.skipSeconds = { back, forward };\n this.renderSkipButtons();\n }\n\n /** DAI reklam arasında seek kapalıyken sarma butonları da devre dışı. */\n setSeekingEnabled(enabled: boolean): void {\n this.seekingEnabled = enabled;\n this.skipBack.btn.disabled = !enabled;\n this.skipForward.btn.disabled = !enabled;\n }\n\n private renderSkipButtons(): void {\n const render = (b: { btn: HTMLButtonElement; num: HTMLSpanElement }, seconds: number | null, label: (s: number) => string): void => {\n b.btn.style.display = seconds === null || this.adMode ? 'none' : '';\n if (seconds === null) return;\n b.num.textContent = String(seconds);\n b.num.toggleAttribute('data-long', String(seconds).length > 2);\n setButtonLabel(b.btn, label(seconds));\n };\n render(this.skipBack, this.skipSeconds.back, this.labels.skipBack);\n render(this.skipForward, this.skipSeconds.forward, this.labels.skipForward);\n }\n\n private skip(delta: number): void {\n if (!delta || !this.seekingEnabled) return;\n const v = this.video;\n // Canlı yayında (duration Infinity) seekable aralığın içinde kal.\n const start = v.seekable.length ? v.seekable.start(0) : 0;\n const end = Number.isFinite(v.duration) ? v.duration : v.seekable.length ? v.seekable.end(v.seekable.length - 1) : v.currentTime;\n v.currentTime = Math.max(start, Math.min(end, v.currentTime + delta));\n this.onSkip?.(delta);\n }\n\n refreshLabels(): void {\n this.renderPlayState();\n this.renderSkipButtons();\n setButtonLabel(this.pipButton, this.labels.pip);\n setButtonLabel(this.liveBadge, this.labels.goToLive);\n this.liveText.textContent = this.labels.live;\n this.setFullscreenState(this.callbacks.isFullscreen());\n this.seekBar.refreshLabels();\n this.volumePanel.refreshLabels();\n this.settingsMenu.refreshLabels();\n }\n\n /** Reklam modu: seek bar, süre ve sağ grup gizlenir; oynat/duraklat + ses kalır. */\n setAdMode(active: boolean): void {\n const display = active ? 'none' : '';\n this.adMode = active;\n this.renderSkipButtons();\n this.seekBar.el.style.display = display;\n this.row.style.display = display;\n if (this.compact) this.fullscreenSlot.style.display = active ? 'none' : 'flex';\n // Süre etiketi / canlı rozeti hangisinin görüneceğine renderTime karar veriyor (ad modunda ikisi de gizli).\n this.renderTime();\n const iconColor = active ? '#202020' : '';\n this.playIcon.style.color = iconColor;\n this.volumePanel.setIconColor(iconColor);\n this.volumePanel.setSliderFillColor(iconColor);\n // Oynat/duraklat ikonu + ses göstergesi, ad moduna girer/çıkarken\n // doğru kaynağı (reklam ya da içerik) hemen yansıtsın.\n this.renderPlayState();\n this.volumePanel.refreshForAdMode();\n }\n\n /** `AdsController`'ın IMA'nın KENDİ UI'ı üzerinden (ör. reklam video'suna tıklama) gelen PAUSED/RESUMED event'leri için — oynat/duraklat ikonunu tazeler. */\n refreshAdPlayState(): void {\n this.renderPlayState();\n }\n\n setQualities(options: SettingsQualityOption[], activeLabel: string): void {\n this.settingsMenu.setQualities(options, activeLabel);\n }\n\n setCaptions(options: SettingsCaptionOption[], activeLabel: string): void {\n this.settingsMenu.setCaptions(options, activeLabel);\n }\n\n /** Plugin'lerin (loop-section vb.) kontrol çubuğuna kendi butonlarını eklemesi için — ayarlar menüsünden önce yerleştirilir. */\n addButton(label: string, iconName: string, onClick: () => void): { btn: HTMLButtonElement; icon: HTMLElement } {\n const { btn, icon } = iconButton(label, iconName);\n btn.addEventListener('click', onClick);\n this.row.insertBefore(btn, this.extraButtonAnchor);\n return { btn, icon };\n }\n\n /** Süre etiketine tıklama: geçen süre ↔ kalan süre. */\n private readonly onTimeClick = (e: MouseEvent): void => {\n e.stopPropagation();\n this.toggleTimeMode();\n };\n\n toggleTimeMode(): void {\n this.showRemaining = !this.showRemaining;\n this.renderTime();\n }\n\n setShowRemaining(show: boolean): void {\n if (this.showRemaining === show) return;\n this.showRemaining = show;\n this.renderTime();\n }\n\n getShowRemaining(): boolean {\n return this.showRemaining;\n }\n\n /** Plugin'lerin (live-wall-clock vb.) kontrol çubuğuna buton olmayan bir element (ör. saat göstergesi) eklemesi için. */\n addElement(el: HTMLElement): void {\n this.row.insertBefore(el, this.extraButtonAnchor);\n }\n\n private togglePlay(): void {\n if (this.callbacks.isAdActive()) {\n this.callbacks.adTogglePlay();\n this.renderPlayState();\n return;\n }\n if (this.video.paused) void this.video.play();\n else this.video.pause();\n }\n\n private async togglePip(): Promise<void> {\n try {\n if (document.pictureInPictureElement) {\n await document.exitPictureInPicture();\n } else {\n await this.video.requestPictureInPicture();\n }\n } catch {\n // PIP desteklenmiyor/izin verilmedi — sessizce yoksay.\n }\n }\n\n private toggleFullscreen(): void {\n if (this.callbacks.isFullscreen()) this.callbacks.onExitFullscreen();\n else this.callbacks.onRequestFullscreen();\n }\n\n private readonly renderPlayState = (): void => {\n const paused = this.callbacks.isAdActive() ? this.callbacks.adIsPaused() : this.video.paused;\n setIconName(this.playIcon, paused ? 'play' : 'pause');\n setButtonLabel(this.playButton, paused ? this.labels.play : this.labels.pause);\n };\n\n /** Canlı uç (media-time) — seekable sonu; native HLS'te DVR'sız canlıda seekable boş kalabildiği için buffered sonu (bkz. LiveWallClock.isLive notu). */\n private liveEdge(): number | null {\n const { seekable, buffered } = this.video;\n if (seekable.length) return seekable.end(seekable.length - 1);\n if (buffered.length) return buffered.end(buffered.length - 1);\n return null;\n }\n\n private readonly renderTime = (): void => {\n const isLive = this.video.duration === Infinity;\n this.timeLabel.style.display = this.adMode || isLive ? 'none' : '';\n this.liveBadge.style.display = !this.adMode && isLive ? '' : 'none';\n\n if (!isLive) {\n const duration = this.video.duration;\n const current = this.video.currentTime;\n if (this.showRemaining) {\n // Görünen tam saniyelerden: ⌊süre⌋ − ⌊geçen⌋ — iki modda gösterilen değerlerin toplamı her zaman görünen süreyi tutar.\n const total = Number.isFinite(duration) ? Math.floor(duration) : 0;\n const remaining = Math.max(0, total - Math.floor(current));\n this.timeLabel.textContent = `-${formatTime(remaining)} / ${formatTime(duration)}`;\n } else {\n this.timeLabel.textContent = `${formatTime(current)} / ${formatTime(duration)}`;\n }\n return;\n }\n // Canlı uçtan LIVE_EDGE_TOLERANCE_SEC'ten fazla gerideyse \"geride\" (gri nokta, tıklanınca uca döner).\n const edge = this.liveEdge();\n const behind = edge !== null && edge - this.video.currentTime > LIVE_EDGE_TOLERANCE_SEC;\n this.liveBadge.toggleAttribute('data-behind', behind);\n };\n\n private readonly goToLive = (): void => {\n const edge = this.liveEdge();\n if (edge === null) return;\n // Tam uca değil, biraz gerisine — buffered'ın en sonuna seek edince oynatma takılabiliyor.\n this.video.currentTime = Math.max(0, edge - 1);\n if (this.video.paused) void this.video.play().catch(() => {});\n this.renderTime();\n };\n\n destroy(): void {\n this.timeLabel.removeEventListener('click', this.onTimeClick);\n this.video.removeEventListener('play', this.renderPlayState);\n this.video.removeEventListener('pause', this.renderPlayState);\n this.video.removeEventListener('timeupdate', this.renderTime);\n this.video.removeEventListener('loadedmetadata', this.renderTime);\n this.video.removeEventListener('durationchange', this.renderTime);\n this.video.removeEventListener('progress', this.renderTime);\n this.resizeObserver.disconnect();\n this.topEl.remove();\n this.seekBar.destroy();\n this.settingsMenu.destroy();\n }\n}\n","/**\n * Tema uyumlu hover tooltip — tek delegasyon dinleyicisi; aria-label'lı her button/slider için otomatik.\n * Kısayol pill'i data-shortcut'tan. Yalnızca hover yapabilen cihazlarda.\n */\nconst SHOW_DELAY_MS = 450;\nconst HIDE_DELAY_MS = 60;\nconst GAP_PX = 8;\nconst EDGE_PADDING_PX = 6;\n/** Bu selector'a uyan ama tooltip İSTEMEYEN elementler (ör. seek bar — sürekli üzerinde gezinilen bir kontrol, tooltip rahatsız eder). */\nconst EXCLUDE_PARTS = new Set(['seek-bar', 'time-display']);\n\n/** Birincil giriş hover yapabiliyor mu (fare/trackpad) — dokunmatik telefon/tablette false. */\nfunction canHover(): boolean {\n return typeof window.matchMedia !== 'function' || window.matchMedia('(hover: hover)').matches;\n}\n\nexport class TooltipController {\n private readonly el: HTMLDivElement;\n private readonly labelEl: HTMLSpanElement;\n private readonly keyEl: HTMLSpanElement;\n private showTimer: ReturnType<typeof setTimeout> | null = null;\n private hideTimer: ReturnType<typeof setTimeout> | null = null;\n private currentTarget: HTMLElement | null = null;\n private isOccluded: ((rect: DOMRect) => boolean) | null = null;\n /** Gösterim gecikmesi (SHOW_DELAY_MS) içinde bekleyen hedef — `currentTarget` yalnızca gerçekten gösterilince set ediliyor. */\n private pendingTarget: HTMLElement | null = null;\n\n constructor(private readonly mountEl: HTMLElement) {\n this.el = document.createElement('div');\n this.el.setAttribute('part', 'tooltip');\n this.el.setAttribute('role', 'tooltip');\n this.el.className =\n 'hp-tooltip hp:absolute hp:z-40 hp:flex hp:items-center hp:gap-1.5 hp:px-2 hp:py-1 hp:rounded hp:text-xs ' +\n 'hp:whitespace-nowrap hp:pointer-events-none hp:opacity-0 hp:transition-opacity hp:duration-100';\n this.el.style.visibility = 'hidden';\n\n this.labelEl = document.createElement('span');\n this.el.appendChild(this.labelEl);\n\n this.keyEl = document.createElement('span');\n this.keyEl.className = 'hp-tooltip-key';\n this.el.appendChild(this.keyEl);\n\n mountEl.appendChild(this.el);\n\n mountEl.addEventListener('mouseover', this.onMouseOver);\n mountEl.addEventListener('mouseout', this.onMouseOut);\n mountEl.addEventListener('focusin', this.onFocusIn);\n mountEl.addEventListener('focusout', this.onFocusOut);\n mountEl.addEventListener('pointerdown', this.hideNow);\n }\n\n destroy(): void {\n if (this.showTimer) clearTimeout(this.showTimer);\n if (this.hideTimer) clearTimeout(this.hideTimer);\n this.mountEl.removeEventListener('mouseover', this.onMouseOver);\n this.mountEl.removeEventListener('mouseout', this.onMouseOut);\n this.mountEl.removeEventListener('focusin', this.onFocusIn);\n this.mountEl.removeEventListener('focusout', this.onFocusOut);\n this.mountEl.removeEventListener('pointerdown', this.hideNow);\n this.el.remove();\n }\n\n /**\n * Tooltip'i örten bir katman (ör. açık ayarlar menüsü) varsa çakışan tooltip gösterilmez — menü kontrol katmanının\n * (z-20) içinde olduğundan tooltip'i z-index ile menünün altına almak mümkün değil.\n */\n setOcclusionCheck(check: ((rect: DOMRect) => boolean) | null): void {\n this.isOccluded = check;\n this.recheckOcclusion();\n }\n\n /** Örten katman açıldı/kapandı — görünen tooltip artık çakışıyorsa gizle. */\n recheckOcclusion(): void {\n if (this.currentTarget && this.el.style.visibility === 'visible' && this.isOccluded?.(this.el.getBoundingClientRect())) this.hideNow();\n }\n\n private matchTarget(fromEl: EventTarget | null): HTMLElement | null {\n const el = fromEl as HTMLElement | null;\n const target = el?.closest?.('button[aria-label], [role=\"slider\"][aria-label]') as HTMLElement | null;\n if (!target) return null;\n const part = target.getAttribute('part');\n if (part && EXCLUDE_PARTS.has(part)) return null;\n // Görünür değilse (ör. display:none pip butonu, kapalı bir panel) ölç/konumlandırma anlamsız.\n if (target.offsetParent === null && target !== document.activeElement) return null;\n return target;\n }\n\n private readonly onMouseOver = (e: MouseEvent): void => {\n const target = this.matchTarget(e.target);\n if (!target || target === this.currentTarget) return;\n this.scheduleShow(target);\n };\n\n private readonly onMouseOut = (e: MouseEvent): void => {\n const target = this.matchTarget(e.target);\n // Gecikme içinde çıkılırsa bekleyen gösterimi de iptal et — currentTarget yalnızca gösterimden sonra set ediliyor.\n if (!target || (target !== this.currentTarget && target !== this.pendingTarget)) return;\n const related = e.relatedTarget as Node | null;\n if (related && target.contains(related)) return;\n this.scheduleHide();\n };\n\n private readonly onFocusIn = (e: FocusEvent): void => {\n const target = this.matchTarget(e.target);\n if (!target) return;\n this.show(target);\n };\n\n private readonly onFocusOut = (e: FocusEvent): void => {\n const target = this.matchTarget(e.target);\n if (!target || target !== this.currentTarget) return;\n this.hideNow();\n };\n\n private scheduleShow(target: HTMLElement): void {\n if (this.hideTimer) {\n clearTimeout(this.hideTimer);\n this.hideTimer = null;\n }\n if (this.showTimer) clearTimeout(this.showTimer);\n this.pendingTarget = target;\n this.showTimer = setTimeout(() => {\n this.showTimer = null;\n this.pendingTarget = null;\n this.show(target);\n }, SHOW_DELAY_MS);\n }\n\n private scheduleHide(): void {\n if (this.showTimer) {\n clearTimeout(this.showTimer);\n this.showTimer = null;\n }\n this.pendingTarget = null;\n if (this.hideTimer) clearTimeout(this.hideTimer);\n this.hideTimer = setTimeout(() => this.hideNow(), HIDE_DELAY_MS);\n }\n\n private readonly hideNow = (): void => {\n if (this.showTimer) {\n clearTimeout(this.showTimer);\n this.showTimer = null;\n }\n this.pendingTarget = null;\n if (this.hideTimer) {\n clearTimeout(this.hideTimer);\n this.hideTimer = null;\n }\n if (!this.currentTarget) return;\n this.currentTarget = null;\n this.el.style.opacity = '0';\n this.el.style.visibility = 'hidden';\n };\n\n private show(target: HTMLElement): void {\n // Dokunmatikte (hover yeteneği yok) gösterme — butona dokunmak hem\n // mouseover hem focusin tetikliyor, tooltip boşuna açılıyordu (istek\n // üzerine: \"mobilde buton tooltiplerini gizle\").\n if (!canHover()) return;\n const label = target.getAttribute('aria-label');\n if (!label) return;\n this.currentTarget = target;\n\n this.labelEl.textContent = label;\n const shortcut = target.dataset.shortcut;\n if (shortcut) {\n this.keyEl.textContent = shortcut;\n this.keyEl.style.display = '';\n } else {\n this.keyEl.textContent = '';\n this.keyEl.style.display = 'none';\n }\n\n // Ölçülebilmesi için önce (görünmez ama layout'ta) render ediliyor.\n this.el.style.visibility = 'hidden';\n this.el.style.opacity = '0';\n this.el.style.left = '0px';\n this.el.style.top = '0px';\n\n requestAnimationFrame(() => {\n if (this.currentTarget !== target) return;\n this.position(target);\n if (this.isOccluded?.(this.el.getBoundingClientRect())) return;\n this.el.style.visibility = 'visible';\n this.el.style.opacity = '1';\n });\n }\n\n private position(target: HTMLElement): void {\n const mountRect = this.mountEl.getBoundingClientRect();\n const targetRect = target.getBoundingClientRect();\n const ttRect = this.el.getBoundingClientRect();\n\n let top = targetRect.top - mountRect.top - ttRect.height - GAP_PX;\n if (top < EDGE_PADDING_PX) {\n top = targetRect.bottom - mountRect.top + GAP_PX;\n }\n\n let left = targetRect.left - mountRect.left + targetRect.width / 2 - ttRect.width / 2;\n const maxLeft = mountRect.width - ttRect.width - EDGE_PADDING_PX;\n left = Math.max(EDGE_PADDING_PX, Math.min(left, maxLeft));\n\n this.el.style.top = `${top}px`;\n this.el.style.left = `${left}px`;\n }\n}\n","/** Host'a bağlı klavye kısayolları; SeekBar/VolumePanel odaktayken kendi ok tuşlarını işler. */\nexport class KeyboardController {\n private readonly host: HTMLElement;\n private readonly video: HTMLVideoElement;\n private readonly toggleFullscreen: () => void;\n /** ←/→ ve J/L ile sarma süresi (sn) — options.keyboardSeekStep. */\n seekStep = 5;\n /** Klavyeyle sarıldığında (sn, negatif = geri) — sarma bildirimi için. */\n onSeek: ((delta: number) => void) | null = null;\n\n constructor(host: HTMLElement, video: HTMLVideoElement, toggleFullscreen: () => void) {\n this.host = host;\n this.video = video;\n this.toggleFullscreen = toggleFullscreen;\n this.host.addEventListener('keydown', this.onKeyDown);\n }\n\n private readonly onKeyDown = (e: KeyboardEvent): void => {\n if (e.defaultPrevented) return;\n // Odaktaki bir butonda Space/Enter butonun kendisini çalıştırsın (ör. süre etiketi, ayarlar) — oynat/durdur değil.\n const target = e.composedPath()[0];\n if ((e.key === ' ' || e.key === 'Enter') && target instanceof HTMLButtonElement) return;\n const duration = this.video.duration;\n\n switch (e.key) {\n case ' ':\n case 'k':\n if (this.video.paused) void this.video.play();\n else this.video.pause();\n e.preventDefault();\n break;\n case 'ArrowRight':\n case 'l':\n if (Number.isFinite(duration)) {\n this.video.currentTime = Math.min(duration, this.video.currentTime + this.seekStep);\n this.onSeek?.(this.seekStep);\n }\n e.preventDefault();\n break;\n case 'ArrowLeft':\n case 'j':\n this.video.currentTime = Math.max(0, this.video.currentTime - this.seekStep);\n this.onSeek?.(-this.seekStep);\n e.preventDefault();\n break;\n case 'ArrowUp':\n this.video.volume = Math.min(1, this.video.volume + 0.1);\n this.video.muted = false;\n e.preventDefault();\n break;\n case 'ArrowDown':\n this.video.volume = Math.max(0, this.video.volume - 0.1);\n e.preventDefault();\n break;\n case 'm':\n this.video.muted = !this.video.muted;\n e.preventDefault();\n break;\n case 'f':\n this.toggleFullscreen();\n e.preventDefault();\n break;\n }\n };\n\n destroy(): void {\n this.host.removeEventListener('keydown', this.onKeyDown);\n }\n}\n","/** video 'waiting' olayında görünür, 'playing'/'canplay'de gizlenir. */\nexport class LoadingSpinner {\n readonly el: HTMLDivElement;\n private readonly video: HTMLVideoElement;\n\n constructor(video: HTMLVideoElement) {\n this.video = video;\n\n this.el = document.createElement('div');\n this.el.className = 'hp:absolute hp:inset-0 hp:flex hp:items-center hp:justify-center hp:pointer-events-none hp:hidden';\n this.el.innerHTML =\n '<div class=\"hp:w-10 hp:h-10 hp:border-[3px] hp:border-on-surface/30 hp:border-t-accent hp:rounded-full hp:animate-spin\"></div>';\n\n video.addEventListener('waiting', this.show);\n video.addEventListener('playing', this.hide);\n video.addEventListener('canplay', this.hide);\n video.addEventListener('pause', this.hide);\n }\n\n private readonly show = (): void => this.el.classList.remove('hp:hidden');\n private readonly hide = (): void => this.el.classList.add('hp:hidden');\n\n destroy(): void {\n this.video.removeEventListener('waiting', this.show);\n this.video.removeEventListener('playing', this.hide);\n this.video.removeEventListener('canplay', this.hide);\n this.video.removeEventListener('pause', this.hide);\n }\n}\n","import { createIcon } from '../icons/Icon';\nimport type { HopeLocaleStrings } from '../i18n/types';\n\nconst RETRY_ICON =\n '<svg viewBox=\"0 0 24 24\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">' +\n '<path d=\"M20 11a8 8 0 1 0-2.3 5.7\"/><path d=\"M20 4v7h-7\"/></svg>';\n\n/**\n * Video 'error' olayında görünen minimal hata ekranı (stiller tailwind.css `.hp-error-*`).\n * Video alanına chrome'un (z-20) üstünde monte edilir — merkez play butonu ve kontroller üstüne binmesin.\n */\nexport class ErrorScreen {\n readonly el: HTMLDivElement;\n private readonly video: HTMLVideoElement;\n private readonly labels: HopeLocaleStrings;\n private readonly messageEl: HTMLParagraphElement;\n private readonly codeEl: HTMLParagraphElement;\n private readonly retryBtn: HTMLButtonElement;\n private readonly retryText: HTMLSpanElement;\n private onRetry: (() => void) | null = null;\n private shouldShow: () => boolean = () => true;\n\n constructor(video: HTMLVideoElement, labels: HopeLocaleStrings) {\n this.video = video;\n this.labels = labels;\n\n this.el = document.createElement('div');\n this.el.setAttribute('part', 'error-screen');\n this.el.setAttribute('role', 'alert');\n this.el.className = 'hp-error-screen';\n\n const card = document.createElement('div');\n card.className = 'hp-error-card';\n\n const icon = document.createElement('div');\n icon.className = 'hp-error-icon';\n icon.appendChild(createIcon('warning'));\n card.appendChild(icon);\n\n this.messageEl = document.createElement('p');\n this.messageEl.className = 'hp-error-message';\n card.appendChild(this.messageEl);\n\n this.codeEl = document.createElement('p');\n this.codeEl.className = 'hp-error-code';\n card.appendChild(this.codeEl);\n\n this.retryBtn = document.createElement('button');\n this.retryBtn.type = 'button';\n this.retryBtn.className = 'hp-error-retry';\n this.retryBtn.innerHTML = RETRY_ICON;\n this.retryText = document.createElement('span');\n this.retryText.textContent = labels.retry;\n this.retryBtn.appendChild(this.retryText);\n this.retryBtn.addEventListener('click', () => {\n this.hide();\n this.onRetry?.();\n });\n card.appendChild(this.retryBtn);\n\n this.el.appendChild(card);\n video.addEventListener('error', this.show);\n }\n\n setOnRetry(fn: () => void): void {\n this.onRetry = fn;\n }\n\n /** false dönerse hata gösterilmez (ör. SourceManager native HLS'ten hls.js'e geçerken). */\n setShouldShow(fn: () => boolean): void {\n this.shouldShow = fn;\n }\n\n get visible(): boolean {\n return this.el.hasAttribute('data-visible');\n }\n\n refreshLabels(): void {\n this.retryText.textContent = this.labels.retry;\n if (this.visible) this.render();\n }\n\n private readonly show = (): void => {\n // Kaynak yokken gelen hata (kaynak değişimi/temizliği sırasında) kullanıcıya gösterilmez —\n // Safari/iOS bu durumda kod 4 üretebiliyor.\n if (!this.video.getAttribute('src') && !this.video.querySelector('source')) return;\n if (!this.shouldShow()) return;\n this.render();\n this.el.setAttribute('data-visible', '');\n };\n\n private render(): void {\n const code = this.video.error?.code ?? 0;\n const messages: Record<number, string> = {\n 1: this.labels.errorAborted,\n 2: this.labels.errorNetwork,\n 3: this.labels.errorDecode,\n 4: this.labels.errorSrcNotSupported,\n };\n this.messageEl.textContent = messages[code] ?? this.labels.errorGeneric;\n this.codeEl.textContent = code ? `${this.labels.errorCode} ${code}` : '';\n this.codeEl.style.display = code ? '' : 'none';\n }\n\n private hide(): void {\n this.el.removeAttribute('data-visible');\n }\n\n destroy(): void {\n this.video.removeEventListener('error', this.show);\n }\n}\n","import type { HopeSubtitleOption } from '../types';\n\nexport interface AttachedTrack {\n label: string;\n track: TextTrack;\n}\n\ninterface ParsedCue {\n start: number;\n end: number;\n settings: string;\n text: string;\n}\n\n/** addTextTrack ile eklenen izler kaldırılamıyor — video başına havuz; aynı label+dil tekrar kullanılır. */\nconst pools = new WeakMap<HTMLVideoElement, Map<string, TextTrack>>();\n/** Her attach'te artar — önceki kaynağın geç gelen fetch'i yeni izlere cue eklemesin. */\nconst generations = new WeakMap<HTMLVideoElement, number>();\n\n/**\n * Altyazıları <track> elementi yerine VTT'yi kendimiz indirip addTextTrack + VTTCue ile ekliyoruz.\n * iOS WebKit <track>'leri \"out-of-band\" iz olarak AVFoundation'a veriyor ve bu, geçerli bir VTT'de bile\n * videonun tamamını MEDIA_ERR_SRC_NOT_SUPPORTED (kod 4) ile düşürebiliyor. Mode 'hidden' — cue'lar akar\n * ama tarayıcı çizmez (CaptionRenderer çizer).\n */\nexport function attachSubtitleTracks(video: HTMLVideoElement, subtitles: HopeSubtitleOption[]): AttachedTrack[] {\n video.querySelectorAll('track').forEach((t) => t.remove());\n clearSubtitleTracks(video);\n const generation = generations.get(video)!;\n let pool = pools.get(video);\n if (!pool) pools.set(video, (pool = new Map()));\n\n const attached: AttachedTrack[] = [];\n for (const sub of subtitles) {\n const key = `${sub.label}\\u0000${sub.srclang}`;\n let track = pool.get(key);\n if (!track) {\n track = video.addTextTrack('subtitles', sub.label, sub.srclang);\n pool.set(key, track);\n }\n track.mode = sub.default ? 'hidden' : 'disabled';\n attached.push({ label: sub.label, track });\n void loadCues(video, track, sub.src, generation);\n }\n return attached;\n}\n\n/** Tüm havuz izlerini kapatıp boşaltır (altyazısız kaynağa geçiş). */\nexport function clearSubtitleTracks(video: HTMLVideoElement): void {\n generations.set(video, (generations.get(video) ?? 0) + 1);\n for (const track of pools.get(video)?.values() ?? []) {\n // Kapalı izde track.cues null döner — boşaltmak için geçici olarak hidden.\n track.mode = 'hidden';\n for (const cue of Array.from(track.cues ?? [])) track.removeCue(cue);\n track.mode = 'disabled';\n }\n}\n\n/** Yalnızca seçilen track'i 'hidden' yapar, diğerlerini kapatır (null = hepsini kapat). */\nexport function selectSubtitleTrack(tracks: AttachedTrack[], label: string | null): TextTrack | null {\n let active: TextTrack | null = null;\n for (const { label: trackLabel, track } of tracks) {\n const isActive = trackLabel === label;\n track.mode = isActive ? 'hidden' : 'disabled';\n if (isActive) active = track;\n }\n return active;\n}\n\nasync function loadCues(video: HTMLVideoElement, track: TextTrack, src: string, generation: number): Promise<void> {\n let text: string;\n try {\n const res = await fetch(src);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n text = await res.text();\n } catch (err) {\n console.warn('[HopePlayer] altyazı yüklenemedi:', src, err);\n return;\n }\n if (generations.get(video) !== generation || typeof VTTCue !== 'function') return;\n for (const c of parseVttCues(text)) {\n const cue = new VTTCue(c.start, c.end, c.text);\n applyCueSettings(cue, c.settings);\n track.addCue(cue);\n }\n}\n\nconst TIMESTAMP = '(?:\\\\d+:)?\\\\d{1,2}:\\\\d{2}(?:[.,]\\\\d{1,3})?';\nconst TIMING_LINE = new RegExp(`^(${TIMESTAMP})\\\\s+-->\\\\s+(${TIMESTAMP})(.*)$`);\n\nfunction toSeconds(value: string): number {\n return value\n .replace(',', '.')\n .split(':')\n .reduce((acc, part) => acc * 60 + Number(part), 0);\n}\n\n/** WebVTT gövdesinden cue'ları çıkarır — NOTE/STYLE/REGION blokları zamanlama satırı içermediği için atlanır. */\nexport function parseVttCues(text: string): ParsedCue[] {\n const cues: ParsedCue[] = [];\n const blocks = text.replace(/^/, '').replace(/\\r\\n?/g, '\\n').split(/\\n{2,}/);\n for (const block of blocks) {\n const lines = block.split('\\n');\n const timingIndex = lines.findIndex((l) => l.includes('-->'));\n if (timingIndex < 0) continue;\n const m = TIMING_LINE.exec(lines[timingIndex]!.trim());\n if (!m) continue;\n const body = lines.slice(timingIndex + 1).join('\\n');\n if (!body.trim()) continue;\n cues.push({ start: toSeconds(m[1]!), end: toSeconds(m[2]!), settings: m[3]!.trim(), text: body });\n }\n return cues;\n}\n\n/** \"line:-2 position:50% align:center\" gibi cue ayarları — geçersiz değerleri tarayıcı reddeder, yok sayıyoruz. */\nfunction applyCueSettings(cue: VTTCue, settings: string): void {\n for (const token of settings.split(/\\s+/)) {\n const [key, raw] = token.split(':');\n if (!key || !raw) continue;\n const [value] = raw.split(',');\n try {\n if (key === 'align') cue.align = value as AlignSetting;\n else if (key === 'vertical') cue.vertical = value as DirectionSetting;\n else if (key === 'size') cue.size = parseFloat(value!);\n else if (key === 'position') cue.position = parseFloat(value!);\n else if (key === 'line') {\n cue.snapToLines = !value!.endsWith('%');\n cue.line = parseFloat(value!);\n }\n } catch {\n // Desteklenmeyen ayar — cue ayarsız gösterilir.\n }\n }\n}\n","import type { HopeLocaleStrings } from '../i18n/types';\n\nexport type CaptionFontSize = 'small' | 'normal' | 'large';\n\nconst ROWS = 6;\n/** En üst satırla video tepesi arasındaki boşluk (balon yüksekliğine eklenir). */\nconst TOP_GAP_PX = 20;\nconst GAP_ABOVE_SEEKBAR_PX = 14;\n/** Kompakt (küçük player) düzende seek bar üstü boşluk — dikey alan kıt, altyazı üst bara binmesin. */\nconst GAP_ABOVE_SEEKBAR_COMPACT_PX = 6;\n/** Kontroller gizliyken en alt satırın video altından boşluğu — video yüksekliğinin %4'ü, en az bu kadar px. */\nconst BOTTOM_GAP_MIN_PX = 10;\nconst DRAG_TAP_THRESHOLD_PX = 3;\nconst STORAGE_KEY_ROW = 'hope-caption-row';\nconst STORAGE_KEY_SIZE = 'hope-caption-font-size';\nconst STORAGE_KEY_BG_COLOR = 'hope-caption-bg-color';\nconst STORAGE_KEY_TEXT_COLOR = 'hope-caption-text-color';\n\nconst FONT_SIZE_MULTIPLIER: Record<CaptionFontSize, number> = {\n small: 0.78,\n normal: 1,\n large: 1.35,\n};\n\n/** YouTube tarzı hazır renk paleti — her ikisi de ayarlar menüsünde swatch grid'i olarak gösteriliyor (bkz. SettingsMenu.renderCaptionColorPanel). İlk eleman her zaman varsayılan. */\nconst BG_COLOR_PRESETS = [\n 'rgba(0, 0, 0, 0.75)',\n 'rgba(0, 0, 0, 0)',\n 'rgba(255, 255, 255, 0.85)',\n 'rgba(183, 28, 28, 0.8)',\n 'rgba(13, 71, 161, 0.8)',\n 'rgba(27, 94, 32, 0.8)',\n];\nconst TEXT_COLOR_PRESETS = ['#ffffff', '#000000', '#ffeb3b', '#ff5252', '#18ffff', '#69f0ae'];\n\ninterface CueWithHtml extends TextTrackCue {\n getCueAsHTML?(): DocumentFragment;\n text?: string;\n}\n\nfunction readStoredRow(): number {\n try {\n const raw = window.localStorage.getItem(STORAGE_KEY_ROW);\n const n = raw === null ? 0 : Number(raw);\n return Number.isFinite(n) && n >= 0 && n < ROWS ? n : 0;\n } catch {\n return 0;\n }\n}\n\nfunction readStoredFontSize(): CaptionFontSize {\n try {\n const raw = window.localStorage.getItem(STORAGE_KEY_SIZE);\n return raw === 'small' || raw === 'normal' || raw === 'large' ? raw : 'normal';\n } catch {\n return 'normal';\n }\n}\n\nfunction readStoredColor(key: string, presets: readonly string[]): string {\n const fallback = presets[0] ?? '';\n try {\n const raw = window.localStorage.getItem(key);\n return raw !== null && presets.includes(raw) ? raw : fallback;\n } catch {\n return fallback;\n }\n}\n\n/** Altyazıyı native render yerine kendi <div>'imizde çizer — YouTube tarzı sürükle-bırak, boyut/renk ayarları. */\nexport class CaptionRenderer {\n static readonly BG_COLOR_PRESETS: readonly string[] = BG_COLOR_PRESETS;\n static readonly TEXT_COLOR_PRESETS: readonly string[] = TEXT_COLOR_PRESETS;\n\n readonly layerEl: HTMLDivElement;\n private readonly bubbleEl: HTMLDivElement;\n private readonly videoArea: HTMLElement;\n private readonly seekBarEl: HTMLElement;\n private labels: HopeLocaleStrings;\n\n private activeTrack: TextTrack | null = null;\n private fontSize: CaptionFontSize = readStoredFontSize();\n private bgColor: string = readStoredColor(STORAGE_KEY_BG_COLOR, BG_COLOR_PRESETS);\n private textColor: string = readStoredColor(STORAGE_KEY_TEXT_COLOR, TEXT_COLOR_PRESETS);\n private rowIndex = readStoredRow();\n private dragging = false;\n /** Kontrol çubuğu görünür mü — görünürken altyazı seek bar'ın üstünde, değilken en altta. */\n private chromeVisible = true;\n private dragStartClientY = 0;\n private dragStartBottomPx = 0;\n private dragMoved = false;\n private rafId: number | null = null;\n private pendingDeltaPx = 0;\n private readonly resizeObserver: ResizeObserver;\n\n constructor(video: HTMLVideoElement, videoArea: HTMLElement, seekBarEl: HTMLElement, labels: HopeLocaleStrings) {\n void video;\n this.videoArea = videoArea;\n this.seekBarEl = seekBarEl;\n this.labels = labels;\n\n this.layerEl = document.createElement('div');\n this.layerEl.className = 'hp-caption-layer';\n this.layerEl.setAttribute('part', 'caption-layer');\n\n this.bubbleEl = document.createElement('div');\n this.bubbleEl.className = 'hp-caption-bubble';\n this.bubbleEl.setAttribute('part', 'caption-bubble');\n this.bubbleEl.setAttribute('role', 'note');\n this.bubbleEl.setAttribute('aria-label', labels.captionDragHandle);\n this.bubbleEl.tabIndex = -1;\n this.applyFontSizeVar();\n this.bubbleEl.style.setProperty('--hp-caption-bg', this.bgColor);\n this.bubbleEl.style.setProperty('--hp-caption-text', this.textColor);\n this.layerEl.appendChild(this.bubbleEl);\n\n this.bubbleEl.addEventListener('pointerdown', this.onPointerDown);\n\n this.resizeObserver = new ResizeObserver(() => this.recomputePosition());\n this.resizeObserver.observe(this.videoArea);\n\n this.recomputePosition();\n }\n\n /** `applyOptions()`'tan — hangi track aktif (ya da null = kapalı). */\n setActiveTrack(track: TextTrack | null): void {\n if (this.activeTrack) this.activeTrack.removeEventListener('cuechange', this.onCueChange);\n this.activeTrack = track;\n if (this.activeTrack) this.activeTrack.addEventListener('cuechange', this.onCueChange);\n this.onCueChange();\n }\n\n getFontSize(): CaptionFontSize {\n return this.fontSize;\n }\n\n setFontSize(size: CaptionFontSize): void {\n this.fontSize = size;\n this.applyFontSizeVar();\n // Boyut büyüyünce balon da büyür — en üst satırdaysa `bounds()`'un\n // tepe boşluğu (bkz. aşağıdaki not) YENİ yüksekliğe göre yeniden\n // hesaplanmazsa balon video'nun tepesinden TAŞABİLİRDİ.\n this.recomputePosition();\n try {\n window.localStorage.setItem(STORAGE_KEY_SIZE, size);\n } catch {\n /* gizli mod vb. — sessizce yoksay */\n }\n }\n\n getBgColor(): string {\n return this.bgColor;\n }\n\n setBgColor(color: string): void {\n this.bgColor = color;\n this.bubbleEl.style.setProperty('--hp-caption-bg', color);\n try {\n window.localStorage.setItem(STORAGE_KEY_BG_COLOR, color);\n } catch {\n /* gizli mod vb. — sessizce yoksay */\n }\n }\n\n getTextColor(): string {\n return this.textColor;\n }\n\n setTextColor(color: string): void {\n this.textColor = color;\n this.bubbleEl.style.setProperty('--hp-caption-text', color);\n try {\n window.localStorage.setItem(STORAGE_KEY_TEXT_COLOR, color);\n } catch {\n /* gizli mod vb. — sessizce yoksay */\n }\n }\n\n /** Ayarlar menüsündeki \"Konumu sıfırla\". */\n resetPosition(): void {\n this.setRowIndex(0, true);\n }\n\n /** Dil sonradan değişince aria-label'ı tazeler. */\n refreshLabels(labels: HopeLocaleStrings): void {\n this.labels = labels;\n this.bubbleEl.setAttribute('aria-label', labels.captionDragHandle);\n }\n\n private applyFontSizeVar(): void {\n this.bubbleEl.style.setProperty('--hp-caption-size-multiplier', String(FONT_SIZE_MULTIPLIER[this.fontSize]));\n }\n\n private readonly onCueChange = (): void => {\n const cues = this.activeTrack?.activeCues;\n if (!this.activeTrack || !cues || cues.length === 0) {\n this.bubbleEl.classList.remove('hp-caption-visible');\n this.bubbleEl.textContent = '';\n return;\n }\n this.bubbleEl.textContent = '';\n for (let i = 0; i < cues.length; i++) {\n if (i > 0) this.bubbleEl.appendChild(document.createElement('br'));\n const cue = cues[i] as CueWithHtml;\n if (typeof cue.getCueAsHTML === 'function') {\n this.bubbleEl.appendChild(cue.getCueAsHTML());\n } else {\n this.bubbleEl.appendChild(document.createTextNode(cue.text ?? ''));\n }\n }\n this.bubbleEl.classList.add('hp-caption-visible');\n };\n\n private bounds(): { min: number; max: number } {\n const areaRect = this.videoArea.getBoundingClientRect();\n const seekRect = this.seekBarEl.getBoundingClientRect();\n // Tepe boşluğu balonun kendi yüksekliği + sabit boşluk.\n const bubbleHeight = this.bubbleEl.getBoundingClientRect().height || 32;\n const topMargin = bubbleHeight + TOP_GAP_PX;\n // Kontroller görünürken seek bar'ın üstü, gizliyken (ya da seek bar gizliyse) videonun en altı.\n const bottomGap = Math.max(BOTTOM_GAP_MIN_PX, Math.round(areaRect.height * 0.04));\n const min =\n this.chromeVisible && seekRect.height > 0\n ? Math.max(0, Math.round(areaRect.bottom - seekRect.top + (this.videoArea.hasAttribute('data-compact') ? GAP_ABOVE_SEEKBAR_COMPACT_PX : GAP_ABOVE_SEEKBAR_PX)))\n : bottomGap;\n const max = Math.max(min, Math.round(areaRect.height - topMargin));\n return { min, max };\n }\n\n private pxForRow(rowIndex: number): number {\n const { min, max } = this.bounds();\n if (ROWS <= 1) return min;\n const ratio = rowIndex / (ROWS - 1);\n return Math.round(min + ratio * (max - min));\n }\n\n /** FLIP: bottom anında yazılır, yalnızca transform animasyonlanır — bottom'u animasyonlamak bırakınca zıplatıyordu. */\n private setRowIndex(rowIndex: number, animate: boolean, fromPx?: number): void {\n this.rowIndex = Math.min(ROWS - 1, Math.max(0, rowIndex));\n const targetPx = this.pxForRow(this.rowIndex);\n const prevPx = fromPx ?? parseFloat(this.bubbleEl.style.bottom || `${targetPx}`);\n\n if (animate && prevPx !== targetPx) {\n this.bubbleEl.classList.add('hp-caption-no-transition');\n this.bubbleEl.style.bottom = `${targetPx}px`;\n this.bubbleEl.style.transform = `translateX(-50%) translateY(${prevPx - targetPx}px)`;\n void this.bubbleEl.offsetHeight; // reflow'u zorla — sıradaki transform değişikliği animasyonlansın\n this.bubbleEl.classList.remove('hp-caption-no-transition');\n this.bubbleEl.style.transform = 'translateX(-50%)';\n } else {\n this.bubbleEl.style.transform = 'translateX(-50%)';\n this.bubbleEl.style.bottom = `${targetPx}px`;\n }\n\n try {\n window.localStorage.setItem(STORAGE_KEY_ROW, String(this.rowIndex));\n } catch {\n /* gizli mod vb. — sessizce yoksay */\n }\n }\n\n /** Boyut değişimi (ör. fullscreen'e giriş) sonrası AYNI satıra, YENİ sınırlara göre yeniden konumlan — animasyonsuz (boyut değişimi anlık olmalı). */\n /** HopePlayerElement.setChromeOpacity'den — kontroller açılıp kapanınca balon yumuşakça yukarı/aşağı kayar (satır korunur). */\n setChromeVisible(visible: boolean): void {\n if (visible === this.chromeVisible) return;\n this.chromeVisible = visible;\n if (!this.dragging) this.setRowIndex(this.rowIndex, true);\n }\n\n recomputePosition(): void {\n if (this.dragging) return;\n this.setRowIndex(this.rowIndex, false);\n }\n\n private readonly onPointerDown = (e: PointerEvent): void => {\n if (e.button !== 0 && e.pointerType === 'mouse') return;\n e.preventDefault();\n this.dragging = true;\n this.dragMoved = false;\n this.dragStartClientY = e.clientY;\n this.dragStartBottomPx = this.pxForRow(this.rowIndex);\n this.bubbleEl.setPointerCapture(e.pointerId);\n this.bubbleEl.classList.add('hp-caption-dragging');\n this.bubbleEl.addEventListener('pointermove', this.onPointerMove);\n this.bubbleEl.addEventListener('pointerup', this.onPointerUp);\n this.bubbleEl.addEventListener('pointercancel', this.onPointerUp);\n };\n\n private readonly onPointerMove = (e: PointerEvent): void => {\n if (!this.dragging) return;\n this.pendingDeltaPx = e.clientY - this.dragStartClientY;\n if (Math.abs(this.pendingDeltaPx) > DRAG_TAP_THRESHOLD_PX) this.dragMoved = true;\n if (this.rafId === null) this.rafId = requestAnimationFrame(this.applyPendingDrag);\n };\n\n private readonly applyPendingDrag = (): void => {\n this.rafId = null;\n if (!this.dragging) return;\n const { min, max } = this.bounds();\n // Aşağı sürüklemek (deltaPx pozitif) effective bottom'u AZALTMALI.\n const targetBottom = Math.min(max, Math.max(min, this.dragStartBottomPx - this.pendingDeltaPx));\n const translatePx = this.dragStartBottomPx - targetBottom;\n this.bubbleEl.style.transform = `translateX(-50%) translateY(${translatePx}px)`;\n };\n\n private readonly onPointerUp = (e: PointerEvent): void => {\n if (!this.dragging) return;\n this.dragging = false;\n this.bubbleEl.releasePointerCapture(e.pointerId);\n this.bubbleEl.removeEventListener('pointermove', this.onPointerMove);\n this.bubbleEl.removeEventListener('pointerup', this.onPointerUp);\n this.bubbleEl.removeEventListener('pointercancel', this.onPointerUp);\n if (this.rafId !== null) {\n cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n this.bubbleEl.classList.remove('hp-caption-dragging');\n if (!this.dragMoved) return;\n const { min, max } = this.bounds();\n const finalBottom = Math.min(max, Math.max(min, this.dragStartBottomPx - this.pendingDeltaPx));\n const ratio = max > min ? (finalBottom - min) / (max - min) : 0;\n const snappedIndex = Math.round(ratio * (ROWS - 1));\n this.setRowIndex(snappedIndex, true, finalBottom);\n };\n\n destroy(): void {\n if (this.activeTrack) this.activeTrack.removeEventListener('cuechange', this.onCueChange);\n this.resizeObserver.disconnect();\n if (this.rafId !== null) cancelAnimationFrame(this.rafId);\n this.bubbleEl.removeEventListener('pointerdown', this.onPointerDown);\n }\n}\n","/**\n * Kontroller gizliyken video alanının en altında, kenardan kenara ince\n * ilerleme çizgisi (`options.miniProgress`). Görünürlüğü HopePlayerElement\n * belirler (chrome gizli + reklam/giriş ekranı yok + canlı değil); çizim\n * yalnızca görünürken ve oynarken rAF ile yapılır.\n */\nexport class MiniProgress {\n readonly el: HTMLDivElement;\n private readonly bufferedEl: HTMLDivElement;\n private readonly playedEl: HTMLDivElement;\n private visible = false;\n private rafId: number | null = null;\n\n constructor(private readonly video: HTMLVideoElement) {\n this.el = document.createElement('div');\n this.el.className = 'hp-mini-progress';\n this.el.setAttribute('part', 'mini-progress');\n this.el.setAttribute('aria-hidden', 'true');\n this.bufferedEl = document.createElement('div');\n this.bufferedEl.className = 'hp-mini-progress-fill hp-mini-progress-buffered';\n this.playedEl = document.createElement('div');\n this.playedEl.className = 'hp-mini-progress-fill hp-mini-progress-played';\n this.el.append(this.bufferedEl, this.playedEl);\n\n video.addEventListener('play', this.sync);\n video.addEventListener('pause', this.sync);\n video.addEventListener('timeupdate', this.render);\n video.addEventListener('progress', this.render);\n video.addEventListener('durationchange', this.render);\n }\n\n setVisible(visible: boolean): void {\n if (visible === this.visible) return;\n this.visible = visible;\n this.el.toggleAttribute('data-visible', visible);\n this.sync();\n }\n\n destroy(): void {\n this.stop();\n this.video.removeEventListener('play', this.sync);\n this.video.removeEventListener('pause', this.sync);\n this.video.removeEventListener('timeupdate', this.render);\n this.video.removeEventListener('progress', this.render);\n this.video.removeEventListener('durationchange', this.render);\n this.el.remove();\n }\n\n private readonly sync = (): void => {\n this.render();\n if (this.visible && !this.video.paused) this.start();\n else this.stop();\n };\n\n private start(): void {\n if (this.rafId !== null) return;\n const tick = (): void => {\n this.render();\n this.rafId = requestAnimationFrame(tick);\n };\n this.rafId = requestAnimationFrame(tick);\n }\n\n private stop(): void {\n if (this.rafId !== null) cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n\n private readonly render = (): void => {\n const duration = this.video.duration;\n // Canlı yayın (Infinity) ya da süre henüz bilinmiyor — boş bir çizgi gösterme.\n const hasDuration = Number.isFinite(duration) && duration > 0;\n this.el.toggleAttribute('data-disabled', !hasDuration);\n if (!this.visible || !hasDuration) return;\n this.playedEl.style.transform = `scaleX(${Math.min(1, this.video.currentTime / duration)})`;\n const { buffered } = this.video;\n let end = 0;\n for (let i = 0; i < buffered.length; i++) {\n if (buffered.start(i) <= this.video.currentTime) end = Math.max(end, buffered.end(i));\n }\n this.bufferedEl.style.transform = `scaleX(${Math.min(1, end / duration)})`;\n };\n}\n","import type { HopeLocaleStrings } from '../i18n/types';\n\n/** Bu süre (ms) içinde aynı yöne tekrar sarılırsa süreler toplanır (+5 → +10 → +15). */\nconst ACCUMULATE_WINDOW_MS = 1000;\n/** Son sarmadan bu kadar sonra bildirim kaybolur. */\nconst HIDE_AFTER_MS = 800;\n\nconst CHEVRON =\n '<svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9.3 5.3a1.2 1.2 0 0 1 1.7 0l5.8 5.8a1.2 1.2 0 0 1 0 1.8l-5.8 5.8a1.2 1.2 0 0 1-1.7-1.7l4.9-5-4.9-5a1.2 1.2 0 0 1 0-1.7z\"/></svg>';\n\n/**\n * İleri/geri sarmada videonun sağında (ileri) ya da solunda (geri) beliren anlık bildirim.\n * Sarma butonları ve klavye kısayolları tetikler; ard arda sarmalar toplanıp tek sayı olarak gösterilir.\n */\nexport class SeekFeedback {\n readonly el: HTMLDivElement;\n private readonly valueEl: HTMLSpanElement;\n private readonly unitEl: HTMLSpanElement;\n private readonly liveEl: HTMLSpanElement;\n private total = 0;\n private lastAt = 0;\n private hideTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(private readonly labels: HopeLocaleStrings) {\n this.el = document.createElement('div');\n this.el.className = 'hp-seek-fb';\n this.el.setAttribute('part', 'seek-feedback');\n\n const chevrons = document.createElement('span');\n chevrons.className = 'hp-seek-fb-chevrons';\n chevrons.innerHTML = CHEVRON.repeat(3);\n\n const value = document.createElement('span');\n value.className = 'hp-seek-fb-value';\n this.valueEl = document.createElement('span');\n this.valueEl.className = 'hp-seek-fb-num';\n this.unitEl = document.createElement('span');\n this.unitEl.className = 'hp-seek-fb-unit';\n value.append(this.valueEl, this.unitEl);\n\n // Ekran okuyucu için ayrı, görünmez metin (\"15 saniye ileri\").\n this.liveEl = document.createElement('span');\n this.liveEl.className = 'hp-sr-only';\n this.liveEl.setAttribute('aria-live', 'polite');\n\n this.el.append(chevrons, value, this.liveEl);\n }\n\n /** `delta` saniye sarıldı (negatif = geri). */\n show(delta: number): void {\n if (!delta) return;\n const now = Date.now();\n const sameDirection = Math.sign(delta) === Math.sign(this.total);\n this.total = sameDirection && now - this.lastAt < ACCUMULATE_WINDOW_MS ? this.total + delta : delta;\n this.lastAt = now;\n\n const seconds = Math.round(Math.abs(this.total) * 10) / 10;\n const forward = this.total > 0;\n this.el.dataset.side = forward ? 'forward' : 'back';\n this.valueEl.textContent = `${forward ? '+' : '−'}${seconds}`;\n this.unitEl.textContent = this.labels.secondsShort;\n this.liveEl.textContent = (forward ? this.labels.skipForward : this.labels.skipBack)(seconds);\n\n // Sayı her artışta \"zıplasın\" — animasyonu yeniden başlat.\n this.valueEl.classList.remove('hp-seek-fb-bump');\n void this.valueEl.offsetWidth;\n this.valueEl.classList.add('hp-seek-fb-bump');\n\n this.el.setAttribute('data-visible', '');\n if (this.hideTimer) clearTimeout(this.hideTimer);\n this.hideTimer = setTimeout(() => {\n this.el.removeAttribute('data-visible');\n this.total = 0;\n }, HIDE_AFTER_MS);\n }\n\n destroy(): void {\n if (this.hideTimer) clearTimeout(this.hideTimer);\n this.el.remove();\n }\n}\n","import iconFontFaceCss from '../theme/icons/hope-icons-font-face.css?inline';\n\nconst STYLE_ID = 'hope-player-icon-font';\n\n/** @font-face Shadow DOM içinde uygulanmadığı için (crbug.com/41085401) document.head'e bir kez enjekte edilir. */\nexport function injectIconFont(): void {\n if (typeof document === 'undefined' || document.getElementById(STYLE_ID)) return;\n const style = document.createElement('style');\n style.id = STYLE_ID;\n style.textContent = iconFontFaceCss;\n document.head.appendChild(style);\n}\n","import type { HopeLocaleStrings } from '../types';\n\n/** Varsayılan dil — mevcut (çeviri öncesi) sabit kodlanmış metinlerle birebir aynı, davranış değişikliği yok. */\nexport const tr: HopeLocaleStrings = {\n play: 'Oynat',\n pause: 'Duraklat',\n mute: 'Sessize al',\n unmute: 'Sesi aç',\n volume: 'Ses seviyesi',\n seekBar: 'Video konumu',\n settings: 'Ayarlar',\n pip: 'Resim içinde resim',\n skipBack: (seconds) => `${seconds} saniye geri`,\n skipForward: (seconds) => `${seconds} saniye ileri`,\n secondsShort: 'sn',\n fullscreenEnter: 'Tam ekran',\n fullscreenExit: 'Tam ekrandan çık',\n playbackSpeed: 'Oynatma Hızı',\n normal: 'Normal',\n quality: 'Kalite',\n captions: 'Altyazı',\n captionsOff: 'Kapalı',\n captionSize: 'Yazı Boyutu',\n captionSizeSmall: 'Küçük',\n captionSizeNormal: 'Normal',\n captionSizeLarge: 'Büyük',\n captionResetPosition: 'Konumu sıfırla',\n captionBgColor: 'Arka Plan Rengi',\n captionTextColor: 'Yazı Rengi',\n captionDragHandle: 'Altyazı konumu — tutup sürükleyin',\n autoQuality: 'Oto',\n loop: 'Döngü',\n close: 'Kapat',\n retry: 'Tekrar Dene',\n errorAborted: 'Video yüklemesi iptal edildi.',\n errorNetwork: 'Ağ hatası — video yüklenemedi.',\n errorDecode: 'Video kodu çözülemedi.',\n errorSrcNotSupported: 'Bu video kaynağı desteklenmiyor.',\n errorGeneric: 'Video oynatılırken bir hata oluştu.',\n errorCode: 'Hata kodu',\n countdownRemaining: 'Kalan süre',\n geoDefaultWarning: 'Erişim engellendi.',\n geoUnknownCountry: 'Ülke bilgisi bulunamadı.',\n redirectCancel: 'İptal',\n redirectPlayNow: 'Şimdi Oynat',\n redirectCountdown: (seconds) => `Sıradaki video ${seconds} saniye içinde oynatılacak.`,\n redirectNowPlaying: 'Video oynatılıyor...',\n qrResumeTitle: 'Devam etmek için kodu telefonunuzla okutun',\n qrResumeDontShowAgain: 'Bir daha gösterme',\n qrResumeContinue: 'Devam Et',\n qrResumeMenuLabel: 'QR ile Devam Et',\n qrResumeOn: 'Açık',\n qrResumeOff: 'Kapalı',\n pauseAdLabel: 'Sponsorlu',\n pauseAdClose: 'Reklamı kapat',\n pauseAdResume: 'Videoya devam et',\n markerLearnMore: 'Daha fazla bilgi',\n markerContinue: 'Devam et',\n playlistTitle: 'Oynatma Listesi',\n playlistPrev: 'Önceki',\n playlistNext: 'Sonraki',\n videoFallbackTitle: (index) => `Video ${index + 1}`,\n storyPrev: 'Önceki video',\n storyNext: 'Sonraki video',\n storyAllVideos: 'Tüm videolar',\n dubbingTitle: 'Ses / Dil',\n liveClock: 'Canlı saat',\n live: 'CANLI',\n goToLive: 'Canlıya git',\n};\n","import type { HopeLocaleStrings } from '../types';\n\nexport const en: HopeLocaleStrings = {\n play: 'Play',\n pause: 'Pause',\n mute: 'Mute',\n unmute: 'Unmute',\n volume: 'Volume',\n seekBar: 'Seek',\n settings: 'Settings',\n pip: 'Picture-in-picture',\n skipBack: (seconds) => `Back ${seconds} seconds`,\n skipForward: (seconds) => `Forward ${seconds} seconds`,\n secondsShort: 's',\n fullscreenEnter: 'Fullscreen',\n fullscreenExit: 'Exit fullscreen',\n playbackSpeed: 'Playback speed',\n normal: 'Normal',\n quality: 'Quality',\n captions: 'Captions',\n captionsOff: 'Off',\n captionSize: 'Font Size',\n captionSizeSmall: 'Small',\n captionSizeNormal: 'Normal',\n captionSizeLarge: 'Large',\n captionResetPosition: 'Reset position',\n captionBgColor: 'Background Color',\n captionTextColor: 'Text Color',\n captionDragHandle: 'Caption position — drag to move',\n autoQuality: 'Auto',\n loop: 'Loop',\n close: 'Close',\n retry: 'Retry',\n errorAborted: 'Video loading was aborted.',\n errorNetwork: 'Network error — the video could not load.',\n errorDecode: 'The video could not be decoded.',\n errorSrcNotSupported: 'This video source is not supported.',\n errorGeneric: 'An error occurred while playing the video.',\n errorCode: 'Error code',\n countdownRemaining: 'Time remaining',\n geoDefaultWarning: 'Access denied.',\n geoUnknownCountry: 'No country information found.',\n redirectCancel: 'Cancel',\n redirectPlayNow: 'Play now',\n redirectCountdown: (seconds) => `Next video will play in ${seconds} seconds.`,\n redirectNowPlaying: 'Now playing...',\n qrResumeTitle: 'Scan to continue watching on your phone',\n qrResumeDontShowAgain: \"Don't show again\",\n qrResumeContinue: 'Continue',\n qrResumeMenuLabel: 'Continue via QR',\n qrResumeOn: 'On',\n qrResumeOff: 'Off',\n pauseAdLabel: 'Sponsored',\n pauseAdClose: 'Close ad',\n pauseAdResume: 'Resume video',\n markerLearnMore: 'Learn more',\n markerContinue: 'Continue',\n playlistTitle: 'Playlist',\n playlistPrev: 'Previous',\n playlistNext: 'Next',\n videoFallbackTitle: (index) => `Video ${index + 1}`,\n storyPrev: 'Previous video',\n storyNext: 'Next video',\n storyAllVideos: 'All videos',\n dubbingTitle: 'Audio / Language',\n liveClock: 'Live clock',\n live: 'LIVE',\n goToLive: 'Go to live',\n};\n","import { tr } from './locales/tr';\nimport { en } from './locales/en';\nimport type { HopeLocale, HopeLocaleStrings } from './types';\n\nconst BUILTIN_LOCALES: Record<string, HopeLocaleStrings> = { tr, en };\n\n/** Paylaşılan, mutable dil sözlüğü üretir (bkz. HopePlayerElement.i18n). */\nexport function createLocaleStrings(locale?: HopeLocale, overrides?: Partial<HopeLocaleStrings>): HopeLocaleStrings {\n const base = BUILTIN_LOCALES[locale ?? 'tr'] ?? tr;\n return { ...base, ...overrides };\n}\n\n/** Var olan (mutable, paylaşılan) bir i18n objesinin alanlarını YERİNDE günceller — referansı korur. */\nexport function applyLocale(target: HopeLocaleStrings, locale?: HopeLocale, overrides?: Partial<HopeLocaleStrings>): void {\n Object.assign(target, createLocaleStrings(locale, overrides));\n}\n\nexport { tr, en };\nexport type { HopeLocale, HopeLocaleStrings };\n","import tailwindCss from './theme/tailwind.css?inline';\nimport type { AdsOptions, HopePlayerOptions } from './types';\nimport { SourceManager, type HlsQualityLevel, type PlaybackEngineInfo } from './hls/SourceManager';\nimport { ControlBar } from './controls/ControlBar';\nimport { TooltipController } from './controls/Tooltip';\nimport { KeyboardController } from './keyboard/KeyboardController';\nimport { LoadingSpinner } from './screens/LoadingSpinner';\nimport { ErrorScreen } from './screens/ErrorScreen';\nimport { attachSubtitleTracks, clearSubtitleTracks, selectSubtitleTrack, type AttachedTrack } from './subtitles/attachTracks';\nimport { CaptionRenderer, type CaptionFontSize } from './subtitles/CaptionRenderer';\nimport { MiniProgress } from './controls/MiniProgress';\nimport { SeekFeedback } from './controls/SeekFeedback';\nimport type { SettingsCaptionAppearance, SettingsColorOption } from './controls/SettingsMenu';\nimport { createIcon } from './icons/Icon';\nimport { injectIconFont } from './icons/injectIconFont';\nimport type { AdsController, AdsPlayerContext } from './plugins/ads';\nimport type { GestureControls } from './plugins/gesture';\nimport type { LoopSection } from './plugins/loop-section';\nimport type { InViewAutoplay } from './plugins/in-view-autoplay';\nimport type { StickyUnregister } from './plugins/sticky';\nimport type { PlaylistRunner } from './plugins/playlist';\nimport type { HopeStory } from './plugins/story';\nimport type { MarkProgress } from './plugins/markers';\nimport type { Segments } from './plugins/segments';\nimport type { SpriteThumbnails } from './plugins/sprite-thumbnails';\nimport type { CountdownScreen } from './plugins/countdown-screen';\nimport type { GeoChecker } from './plugins/geo-checker';\nimport type { RedirectScreen } from './plugins/redirect-screen';\nimport type { QrResume } from './plugins/qr-resume';\nimport type { PauseAd } from './plugins/pause-ad';\nimport type { Dubbing } from './plugins/dubbing';\nimport type { LiveWallClock } from './plugins/live';\nimport type { DaiController } from './plugins/dai';\nimport { createLocaleStrings, applyLocale } from './i18n';\nimport type { HopeLocaleStrings } from './i18n/types';\n\nconst DEFAULT_PLAYBACK_RATES = [0.5, 0.75, 1, 1.25, 1.5, 2];\n/** options.autoHideDelayMs verilmezse kullanılan varsayılan. */\nconst DEFAULT_AUTO_HIDE_DELAY_MS = 1200;\n/** Basış ile kalkış arasındaki imleç/parmak hareketi bu eşiği aşarsa \"tık\" değil sürükleme sayılır — toggle tetiklenmez. */\nconst TAP_MAX_MOVE_PX = 10;\n/** options.skipButtons'ta süre verilmezse. */\nconst DEFAULT_SKIP_SECONDS = 10;\n/** options.keyboardSeekStep verilmezse ←/→ ve J/L ile sarma süresi (sn). */\nconst DEFAULT_KEYBOARD_SEEK_STEP = 5;\n\nconst TEMPLATE = /* html */ `\n <div class=\"video-area\">\n <div class=\"media-layer\">\n <video part=\"video\" playsinline webkit-playsinline preload=\"metadata\"></video>\n <div part=\"ad-layer\" class=\"hp:absolute hp:inset-0 hp:z-10 hp:hidden\"></div>\n </div>\n </div>\n`;\n\n/** <hope-player> — çekirdek oynatma ve kontroller; plugin'ler ilgili option verilince dinamik import edilir. */\nexport class HopePlayerElement extends HTMLElement {\n static get observedAttributes(): string[] {\n return ['src', 'poster', 'autoplay', 'muted', 'loop', 'theme', 'locale'];\n }\n\n private readonly root: ShadowRoot;\n private readonly videoArea: HTMLDivElement;\n private readonly videoEl: HTMLVideoElement;\n private readonly adLayerEl: HTMLDivElement;\n private readonly chromeEl: HTMLDivElement;\n private readonly centerPlayButton: HTMLButtonElement;\n private readonly captionRenderer: CaptionRenderer;\n /** options.miniProgress açıkken kurulur. */\n private miniProgress: MiniProgress | null = null;\n private chromeVisible = true;\n\n private readonly sourceManager: SourceManager;\n private readonly controlBar: ControlBar;\n private readonly tooltip: TooltipController;\n private readonly keyboard: KeyboardController;\n private readonly loadingSpinner: LoadingSpinner;\n private readonly errorScreen: ErrorScreen;\n /** İleri/geri sarmada sağda/solda beliren anlık bildirim. */\n private readonly seekFeedback: SeekFeedback;\n private adsController: AdsController | null = null;\n private gestureControls: GestureControls | null = null;\n private loopSection: LoopSection | null = null;\n private inViewAutoplay: InViewAutoplay | null = null;\n private unregisterSticky: StickyUnregister | null = null;\n private playlistRunner: PlaylistRunner | null = null;\n private hopeStory: HopeStory | null = null;\n private markProgress: MarkProgress | null = null;\n private segments: Segments | null = null;\n private spriteThumbnails: SpriteThumbnails | null = null;\n private countdownScreen: CountdownScreen | null = null;\n private geoChecker: GeoChecker | null = null;\n private redirectScreen: RedirectScreen | null = null;\n private qrResume: QrResume | null = null;\n private pauseAd: PauseAd | null = null;\n private dubbing: Dubbing | null = null;\n private liveWallClock: LiveWallClock | null = null;\n private daiController: DaiController | null = null;\n private readonly instanceKey: string;\n\n private subtitleTracks: AttachedTrack[] = [];\n /** Altyazı seçiminin tek giriş noktası — iOS native tam ekrandan dönüşte de kullanılır. */\n private selectCaption: ((label: string | null) => void) | null = null;\n /** `applyOptions()`'ta aktif bir altyazı track'i seçiliyken `true` — dil değişince Boyut/Konum görünümünü tazelemek için. */\n private captionTrackActive = false;\n /**\n * countdownScreen varken gerçek init (kaynak + içerik plugin'leri) ertelenir; en güncel options snapshot'ı.\n * onComplete kaydı tek sefer yapılır (bkz. playbackInitRegistered) — init birden fazla kez tetiklenmesin.\n */\n private pendingPlaybackOptions: HopePlayerOptions | null = null;\n private playbackInitRegistered = false;\n /**\n * countdownScreen gibi alanlar yalnızca .options ile gelir. connectedCallback'teki ilk (options'suz) geçiş chrome'u\n * bir an açıp player'ı gösteriyordu; 'boot' bloklayıcısı gerçek options gelene kadar bekletir.\n */\n private bootResolved = false;\n private bootGraceTimer: ReturnType<typeof setTimeout> | null = null;\n private _options: HopePlayerOptions = {};\n private hideTimer: ReturnType<typeof setTimeout> | null = null;\n /** Fare kontrollerin (buton/seek bar) üzerinde mi — üzerindeyken otomatik gizlenmez; videonun üstünde hareketsizse gizlenir. */\n private pointerOverControls = false;\n /** Kalite menüsünde şu an HLS seviyeleri mi var (kaynak değişince temizlemek için). */\n private hlsQualitiesShown = false;\n /** Son uygulanan options.showRemainingTime — bkz. applyOptions. */\n private appliedShowRemaining: boolean | undefined;\n private autoHideDelayMs = DEFAULT_AUTO_HIDE_DELAY_MS;\n private tapCandidate = false;\n private tapStartX = 0;\n private tapStartY = 0;\n /** Tüm UI'ın paylaştığı tek, mutable sözlük — dil değişince referans değil alanlar güncellenir. */\n private readonly i18n: HopeLocaleStrings = createLocaleStrings('tr');\n /** IMA SDK'nın kendi ad-UI dili (skip butonu/sayaç metni) de aynı dili takip etsin diye — bkz. plugins/ads/AdsController. */\n private localeCode = 'tr';\n\n constructor() {\n super();\n injectIconFont();\n this.root = this.attachShadow({ mode: 'open' });\n\n const style = document.createElement('style');\n style.textContent = tailwindCss;\n this.root.appendChild(style);\n\n const wrapper = document.createElement('div');\n // Tam ekranda yüksekliği zincirlemek için sınıflı (tailwind.css `:host(:fullscreen) .hp-root`).\n wrapper.className = 'hp-root';\n wrapper.innerHTML = TEMPLATE;\n this.root.appendChild(wrapper);\n\n this.videoArea = this.root.querySelector('.video-area')!;\n this.videoEl = this.root.querySelector('video')!;\n this.adLayerEl = this.root.querySelector('[part=\"ad-layer\"]')!;\n this.instanceKey = `hp-${Math.random().toString(36).slice(2, 10)}`;\n\n this.loadingSpinner = new LoadingSpinner(this.videoEl);\n this.root.querySelector('.media-layer')!.appendChild(this.loadingSpinner.el);\n\n this.errorScreen = new ErrorScreen(this.videoEl, this.i18n);\n this.errorScreen.setOnRetry(() => void this.sourceManager.reload());\n // Chrome'un (z-20) üstünde — merkez play butonu ve kontroller hata ekranına binmesin.\n this.videoArea.appendChild(this.errorScreen.el);\n\n this.centerPlayButton = document.createElement('button');\n this.centerPlayButton.type = 'button';\n this.centerPlayButton.setAttribute('part', 'center-play-button');\n this.centerPlayButton.setAttribute('aria-label', this.i18n.play);\n // Tıklama alanı tüm video alanı; görsel olarak yalnızca ortadaki yuvarlak buton.\n this.centerPlayButton.className =\n 'hp-center-play hp:absolute hp:inset-0 hp:flex hp:items-center hp:justify-center hp:bg-transparent hp:border-0 hp:cursor-pointer hp:text-on-surface hp:transition-opacity';\n const centerChip = document.createElement('span');\n centerChip.className = 'hp-chip hp:flex hp:items-center hp:justify-center hp:w-16 hp:h-16';\n // .hp-chip'in kendi --hp-chip-radius'u rounded-full utility'sini ezer\n // (bkz. VolumePanel'deki aynı not) — tam daire için inline override.\n centerChip.style.borderRadius = '9999px';\n centerChip.appendChild(createIcon('play', 'hp:text-2xl'));\n this.centerPlayButton.appendChild(centerChip);\n this.centerPlayButton.addEventListener('click', () => {\n if (this.videoEl.paused) void this.videoEl.play();\n });\n this.videoArea.appendChild(this.centerPlayButton);\n\n this.chromeEl = document.createElement('div');\n // pointer-events-none: tüm video alanını kaplıyor; açık olsaydı alttaki video/reklam tıklamalarını yutardı.\n this.chromeEl.className = 'hp-chrome hp:absolute hp:inset-0 hp:z-20 hp:pointer-events-none';\n this.videoArea.appendChild(this.chromeEl);\n\n this.sourceManager = new SourceManager(this.videoEl, this.onHlsLevelsChanged);\n this.errorScreen.setShouldShow(() => !this.sourceManager.isRecovering());\n\n this.controlBar = new ControlBar(\n this.videoEl,\n DEFAULT_PLAYBACK_RATES,\n {\n onRequestFullscreen: () => this.requestFullscreenCompat(),\n onExitFullscreen: () => this.exitFullscreenCompat(),\n isFullscreen: () => this.isFullscreenActive(),\n // adsController sonradan kurulur — closure'lar her çağrıda güncel this.adsController'ı okur.\n isAdActive: () => this.isAdPlaying(),\n adTogglePlay: () => this.adsController?.toggleAdPlayPause(),\n adIsPaused: () => this.adsController?.isAdPaused() ?? true,\n adVolume: {\n isAdActive: () => this.isAdPlaying(),\n getVolume: () => this.adsController?.getAdVolume() ?? 1,\n setVolume: (v) => this.adsController?.setAdVolume(v),\n toggleMute: () => this.adsController?.toggleAdMute(),\n },\n },\n this.i18n\n );\n this.chromeEl.appendChild(this.controlBar.el);\n // Kompakt (küçük player) düzende sağ grubun taşındığı üst bar — chrome'la birlikte otomatik gizlenir.\n this.chromeEl.appendChild(this.controlBar.topEl);\n // \"Sesi aç\" rozeti chrome'un DIŞINDA: kontroller gizlense de sessiz videoda görünür kalmalı.\n this.videoArea.appendChild(this.controlBar.volumePanel.unmuteBadge);\n\n // z-index: video < caption(5) < ad-layer(10) < chrome(20) — reklam altyazıyı kendiliğinden örter.\n this.captionRenderer = new CaptionRenderer(this.videoEl, this.videoArea, this.controlBar.seekBar.el, this.i18n);\n this.videoArea.appendChild(this.captionRenderer.layerEl);\n\n this.keyboard = new KeyboardController(this, this.videoEl, () =>\n this.isFullscreenActive() ? this.exitFullscreenCompat() : this.requestFullscreenCompat()\n );\n\n // Tek bir delegasyon dinleyicisi, TÜM butonlar için (bkz. Tooltip.ts'teki\n // mimari not) — videoArea zaten position:relative (bkz. tailwind.css),\n // bu yüzden tooltip'in konum hesaplaması bu kapsayıcıya göre doğru çalışır.\n this.tooltip = new TooltipController(this.videoArea);\n\n this.seekFeedback = new SeekFeedback(this.i18n);\n this.videoArea.appendChild(this.seekFeedback.el);\n this.controlBar.onSkip = (delta) => this.seekFeedback.show(delta);\n this.keyboard.onSeek = (delta) => this.seekFeedback.show(delta);\n this.controlBar.seekBar.onKeyboardSeek = (delta) => this.seekFeedback.show(delta);\n\n // 'boot': gerçek `.options` (ör. countdownScreen) gelene kadar chrome\n // HİÇ görünmesin diye — bkz. `bootResolved` alanındaki mimari not.\n this.blockChrome('boot');\n }\n\n connectedCallback(): void {\n // tabIndex constructor'da değil burada: tabindex attribute'una yansır ve Custom Elements spec'i\n // constructor'da attribute eklemeyi yasaklar (createElement \"must not have attributes\" hatası).\n this.tabIndex = this.tabIndex || 0;\n\n this.syncFromAttributes();\n\n // Yalnızca HTML attribute'larıyla kullanım için güvenlik ağı — .options set edilirse bu zamanlayıcı iptal edilir.\n if (!this.bootResolved) {\n this.bootGraceTimer = setTimeout(() => {\n this.bootGraceTimer = null;\n if (!this.bootResolved) {\n this.bootResolved = true;\n this.syncFromAttributes();\n }\n }, 80);\n }\n\n this.videoEl.addEventListener('play', this.onPlay);\n this.videoEl.addEventListener('pause', this.onPause);\n this.addEventListener('pointermove', this.onPointerMove);\n this.addEventListener('pointerleave', this.onPointerLeave);\n this.addEventListener('pointerdown', this.onPointerDownFocus);\n document.addEventListener('fullscreenchange', this.onFullscreenChange);\n document.addEventListener('webkitfullscreenchange', this.onFullscreenChange);\n // iPhone video tam ekranı (webkitEnterFullscreen) kendi olaylarını yayınlar.\n this.videoEl.addEventListener('webkitbeginfullscreen', this.onFullscreenChange);\n this.videoEl.addEventListener('webkitendfullscreen', this.onFullscreenChange);\n // Ayarlar menüsü açıkken kontroller gizlenmesin (mobilde menü de onlarla kayboluyordu).\n this.controlBar.settingsMenu.onOpenChange = (open) => {\n if (open && this.hideTimer) clearTimeout(this.hideTimer);\n if (!open) this.scheduleAutoHide();\n this.tooltip.recheckOcclusion();\n };\n // Açık menüyle çakışan tooltip menünün \"altında\" kalır (gösterilmez).\n this.tooltip.setOcclusionCheck((r) => {\n const p = this.controlBar.settingsMenu.panelRect;\n return !!p && r.left < p.right && r.right > p.left && r.top < p.bottom && r.bottom > p.top;\n });\n\n // \"Ekrana dokun → oynat/duraklat\": doğrudan videoEl'e bağlı, kontrol çubuğu tıklamaları tetiklemez.\n this.videoEl.addEventListener('mousedown', this.onVideoPressStart);\n this.videoEl.addEventListener('mouseup', this.onVideoPressEnd);\n this.videoEl.addEventListener('mouseleave', this.onVideoPressCancel);\n this.videoEl.addEventListener('touchstart', this.onVideoPressStart, { passive: true });\n this.videoEl.addEventListener('touchend', this.onVideoPressEnd);\n this.videoEl.addEventListener('touchcancel', this.onVideoPressCancel);\n\n this.dispatchEvent(new CustomEvent('hp:ready'));\n }\n\n disconnectedCallback(): void {\n this.miniProgress?.destroy();\n this.miniProgress = null;\n this.videoEl.removeEventListener('play', this.onPlay);\n this.videoEl.removeEventListener('pause', this.onPause);\n this.removeEventListener('pointermove', this.onPointerMove);\n this.removeEventListener('pointerleave', this.onPointerLeave);\n this.removeEventListener('pointerdown', this.onPointerDownFocus);\n this.controlBar.settingsMenu.onOpenChange = null;\n document.removeEventListener('fullscreenchange', this.onFullscreenChange);\n document.removeEventListener('webkitfullscreenchange', this.onFullscreenChange);\n this.videoEl.removeEventListener('webkitbeginfullscreen', this.onFullscreenChange);\n this.videoEl.removeEventListener('webkitendfullscreen', this.onFullscreenChange);\n this.videoEl.removeEventListener('mousedown', this.onVideoPressStart);\n this.videoEl.removeEventListener('mouseup', this.onVideoPressEnd);\n this.videoEl.removeEventListener('mouseleave', this.onVideoPressCancel);\n this.videoEl.removeEventListener('touchstart', this.onVideoPressStart);\n this.videoEl.removeEventListener('touchend', this.onVideoPressEnd);\n this.videoEl.removeEventListener('touchcancel', this.onVideoPressCancel);\n this.controlBar.destroy();\n this.captionRenderer.destroy();\n this.keyboard.destroy();\n this.tooltip.destroy();\n this.loadingSpinner.destroy();\n this.errorScreen.destroy();\n this.seekFeedback.destroy();\n this.sourceManager.destroy();\n this.adsController?.destroy();\n this.gestureControls?.destroy();\n this.loopSection?.destroy();\n this.inViewAutoplay?.destroy();\n this.unregisterSticky?.();\n this.playlistRunner?.destroy();\n this.hopeStory?.destroy();\n this.markProgress?.destroy();\n this.segments?.destroy();\n this.spriteThumbnails?.destroy();\n this.countdownScreen?.destroy();\n this.geoChecker?.destroy();\n this.redirectScreen?.destroy();\n this.qrResume?.destroy();\n this.pauseAd?.destroy();\n this.pauseAd = null;\n this.dubbing?.destroy();\n this.liveWallClock?.destroy();\n this.daiController?.destroy();\n if (this.hideTimer) clearTimeout(this.hideTimer);\n if (this.bootGraceTimer) clearTimeout(this.bootGraceTimer);\n }\n\n /** Reklam/consent-farkında plugin'lerin (gesture/sticky/in-view-autoplay) ortak sorgusu. */\n isAdPlaying(): boolean {\n return this.chromeBlockers.has('ads');\n }\n\n attributeChangedCallback(): void {\n this.syncFromAttributes();\n }\n\n get options(): HopePlayerOptions {\n return this._options;\n }\n\n set options(value: HopePlayerOptions) {\n this._options = value ?? {};\n // Attribute'larla birleştir — aksi halde theme alanı olmayan bir .options ataması attribute'tan gelen temayı silerdi.\n if (this.bootGraceTimer) {\n clearTimeout(this.bootGraceTimer);\n this.bootGraceTimer = null;\n }\n this.bootResolved = true;\n this.syncFromAttributes();\n }\n\n play(): Promise<void> {\n return this.videoEl.play();\n }\n\n pause(): void {\n this.videoEl.pause();\n }\n\n /** Şu anki oynatma yolu: `native` (MP4/WebM), `native-hls` (tarayıcının HLS'i) ya da `hls.js` — teşhis için. */\n get playbackEngine(): PlaybackEngineInfo {\n return this.sourceManager.engine;\n }\n\n /** `options.qrResume` kuruluysa \"telefonundan devam et\" QR ekranını manuel göster (ör. entegratörün kendi \"telefona gönder\" butonu) — otomatik gösterim kuralları (minElapsed/minRemaining) burada uygulanmaz. */\n showQrResume(): void {\n this.qrResume?.show();\n }\n\n get showRemainingTime(): boolean {\n return this.controlBar.getShowRemaining();\n }\n\n set showRemainingTime(value: boolean) {\n this.controlBar.setShowRemaining(value);\n }\n\n toggleTimeDisplay(): void {\n this.controlBar.toggleTimeMode();\n }\n\n private syncFromAttributes(): void {\n const attrOptions: HopePlayerOptions = {\n src: this.getAttribute('src') ?? undefined,\n poster: this.getAttribute('poster') ?? undefined,\n autoplay: this.hasAttribute('autoplay'),\n muted: this.hasAttribute('muted'),\n loop: this.hasAttribute('loop'),\n theme: this.getAttribute('theme') ?? undefined,\n locale: this.getAttribute('locale') ?? undefined,\n };\n void this.applyOptions({ ...attrOptions, ...this._options });\n }\n\n private async applyOptions(options: HopePlayerOptions): Promise<void> {\n if (options.poster) this.videoEl.poster = options.poster;\n this.videoEl.autoplay = !!options.autoplay;\n this.videoEl.muted = !!options.muted;\n this.videoEl.loop = !!options.loop;\n this.videoEl.preload = options.preload ?? 'metadata';\n // iOS: inline oynatma (aksi halde play() videoyu zorla tam ekrana alır). Eski iOS/WebView'lar için webkit- adı.\n this.videoEl.playsInline = true;\n this.videoEl.setAttribute('webkit-playsinline', '');\n this.autoHideDelayMs = options.autoHideDelayMs ?? DEFAULT_AUTO_HIDE_DELAY_MS;\n if (options.miniProgress && !this.miniProgress) {\n this.miniProgress = new MiniProgress(this.videoEl);\n this.videoArea.appendChild(this.miniProgress.el);\n this.updateMiniProgress();\n } else if (!options.miniProgress && this.miniProgress) {\n this.miniProgress.destroy();\n this.miniProgress = null;\n }\n // Yalnızca DEĞER değişince uygula — başka bir option güncellemesi kullanıcının tıklayarak seçtiği modu sıfırlamasın.\n const seekStep = options.keyboardSeekStep && options.keyboardSeekStep > 0 ? options.keyboardSeekStep : DEFAULT_KEYBOARD_SEEK_STEP;\n this.keyboard.seekStep = seekStep;\n this.controlBar.seekBar.keyboardStep = seekStep;\n const skip = options.skipButtons === true ? {} : options.skipButtons || null;\n this.controlBar.setSkipButtons(\n skip && skip.back !== false ? (skip.back ?? DEFAULT_SKIP_SECONDS) : null,\n skip && skip.forward !== false ? (skip.forward ?? DEFAULT_SKIP_SECONDS) : null\n );\n if (options.showRemainingTime !== undefined && options.showRemainingTime !== this.appliedShowRemaining) {\n this.appliedShowRemaining = options.showRemainingTime;\n this.controlBar.setShowRemaining(options.showRemainingTime);\n }\n if (options.theme) this.setAttribute('data-theme', options.theme);\n else this.removeAttribute('data-theme');\n\n this.localeCode = options.locale ?? 'tr';\n applyLocale(this.i18n, options.locale, options.labels);\n this.centerPlayButton.setAttribute('aria-label', this.i18n.play);\n this.controlBar.refreshLabels();\n this.captionRenderer.refreshLabels(this.i18n);\n if (this.captionTrackActive) this.controlBar.settingsMenu.setCaptionAppearance(this.buildCaptionAppearance());\n this.errorScreen.refreshLabels();\n this.playlistRunner?.refreshLabels();\n this.hopeStory?.refreshLabels();\n this.countdownScreen?.refreshLabels();\n this.geoChecker?.refreshLabels();\n this.redirectScreen?.refreshLabels();\n this.qrResume?.refreshLabels();\n this.pauseAd?.refreshLabels();\n this.dubbing?.refreshLabels();\n this.liveWallClock?.refreshLabels();\n this.loopSection?.refreshLabels();\n this.markProgress?.refreshLabels();\n this.unregisterSticky?.refreshLabels?.();\n\n if (!this.bootResolved) {\n return;\n }\n\n // Gate plugin'leri (countdown/geo) KAYNAK YÜKLENMEDEN/autoplay denenmeden\n // ÖNCE kuruluyor ki blockChrome() + 'play' dinleyicisi zaten takılı olsun\n // — aksi halde autoplay bir an için gerçekten oynamaya başlayabilirdi.\n const gateCtx = () => ({\n videoEl: this.videoEl,\n overlayContainerEl: this.videoArea,\n blockChrome: () => this.blockChrome('countdown-geo'),\n unblockChrome: () => this.unblockChrome('countdown-geo'),\n i18n: this.i18n,\n });\n\n if (options.countdownScreen && !this.countdownScreen) {\n const { installCountdownScreen } = await import('./plugins/countdown-screen');\n this.countdownScreen = installCountdownScreen(gateCtx(), options.countdownScreen);\n }\n\n if (options.geoChecker && !this.geoChecker) {\n const { installGeoChecker } = await import('./plugins/geo-checker');\n this.geoChecker = installGeoChecker(gateCtx(), options.geoChecker);\n }\n\n this.unblockChrome('boot');\n\n if (this.countdownScreen && !this.countdownScreen.isComplete()) {\n this.pendingPlaybackOptions = options;\n if (!this.playbackInitRegistered) {\n this.playbackInitRegistered = true;\n this.countdownScreen.onComplete(() => {\n const pending = this.pendingPlaybackOptions;\n this.pendingPlaybackOptions = null;\n if (pending) void this.initPlayback(pending);\n });\n }\n } else {\n await this.initPlayback(options);\n }\n }\n\n private async initPlayback(options: HopePlayerOptions): Promise<void> {\n const sources = options.sources?.length ? options.sources : options.src ? [{ src: options.src, label: this.i18n.autoQuality }] : [];\n // Tek kaynakta önceki kaynağın (MP4 sources) kalite listesi kalmasın — yüklemeden ÖNCE temizle,\n // ki hls.js'in birazdan bildireceği seviyeler silinmesin.\n if (sources.length <= 1) {\n this.controlBar.setQualities([], '');\n this.hlsQualitiesShown = false;\n }\n if (sources.length > 0) {\n const initial = sources.find((s) => s.selected) ?? sources[0]!;\n await this.sourceManager.load(initial.src, initial.type);\n if (options.autoplay) this.videoEl.play().catch(() => {});\n }\n\n if (sources.length > 1) {\n this.controlBar.setQualities(\n sources.map((s) => ({\n label: s.label,\n onSelect: () => void this.switchQualitySource(s),\n })),\n sources.find((s) => s.selected)?.label ?? sources[0]!.label\n );\n }\n\n if (options.ads && !this.adsController) {\n const adsOptions: AdsOptions = options.ads === true ? {} : options.ads;\n // Reklamsız entegrasyonlarda bu import hiç tetiklenmez — bkz. plan:\n // \"eklenmeyen plugin yük bindirmemeli\" (dinamik import = ayrı chunk).\n const { installAds } = await import('./plugins/ads');\n this.adsController = await installAds(\n {\n videoEl: this.videoEl,\n hostEl: this,\n adLayerEl: this.adLayerEl,\n hideChrome: () => this.blockChrome('ads', 'reduced'),\n showChrome: () => this.unblockChrome('ads'),\n // IMA'nın KENDİ UI'ı üzerinden (ör. reklam video'suna\n // tıklama) duraklatılır/devam ettirilirse toolbar'ımızın\n // ikonu da senkron kalsın diye.\n onAdPlayStateChange: () => this.controlBar.refreshAdPlayState(),\n locale: this.localeCode,\n },\n adsOptions\n );\n }\n\n if (options.gesture && !this.gestureControls) {\n const gestureOptions = options.gesture === true ? {} : options.gesture;\n const { installGesture } = await import('./plugins/gesture');\n this.gestureControls = installGesture(\n { videoEl: this.videoEl, overlayContainerEl: this.videoArea, isAdActive: () => this.isAdPlaying() },\n gestureOptions\n );\n }\n\n if (options.loopSection && !this.loopSection) {\n const loopOptions = options.loopSection === true ? {} : options.loopSection;\n const { installLoopSection } = await import('./plugins/loop-section');\n this.loopSection = installLoopSection(\n {\n videoEl: this.videoEl,\n seekBarEl: this.controlBar.seekBar.el,\n markers: this.controlBar.seekBar,\n addControlButton: (label, icon, onClick) => this.controlBar.addButton(label, icon, onClick),\n i18n: this.i18n,\n },\n loopOptions\n );\n }\n\n if (options.inViewAutoplay && !this.inViewAutoplay) {\n const inViewOptions = options.inViewAutoplay === true ? {} : options.inViewAutoplay;\n const { installInViewAutoplay } = await import('./plugins/in-view-autoplay');\n this.inViewAutoplay = installInViewAutoplay(\n { videoEl: this.videoEl, observeEl: this, isAdActive: () => this.isAdPlaying() },\n inViewOptions\n );\n }\n\n if (options.sticky && !this.unregisterSticky) {\n const stickyOptions = options.sticky === true ? {} : options.sticky;\n const { installSticky } = await import('./plugins/sticky');\n this.unregisterSticky = installSticky(\n {\n key: this.instanceKey,\n videoEl: this.videoEl,\n hostEl: this,\n wrapperEl: this,\n closeButtonMountEl: this.videoArea,\n isAdActive: () => this.isAdPlaying(),\n i18n: this.i18n,\n },\n stickyOptions\n );\n }\n\n if (options.playlist && !this.playlistRunner) {\n const { installPlaylist } = await import('./plugins/playlist');\n this.playlistRunner = installPlaylist(\n {\n videoEl: this.videoEl,\n hostEl: this,\n panelEl: this.getOrCreatePanelContainer(),\n loadSource: (src, type) => this.sourceManager.load(src, type),\n setPoster: (url) => {\n this.videoEl.poster = url;\n },\n requestFreshAd: (tag) => this.adsController?.resetForNewItem(tag),\n i18n: this.i18n,\n },\n options.playlist\n );\n }\n\n if (options.story && !this.hopeStory) {\n const { installStory } = await import('./plugins/story');\n this.hopeStory = installStory(\n {\n videoEl: this.videoEl,\n hostEl: this,\n videoAreaEl: this.videoArea,\n playerBodyEls: [this.root.querySelector<HTMLDivElement>('.media-layer')!, this.chromeEl, this.centerPlayButton],\n loadSource: (src, type) => this.sourceManager.load(src, type),\n setPoster: (url) => {\n this.videoEl.poster = url;\n },\n requestFreshAd: (tag) => this.adsController?.resetForNewItem(tag),\n i18n: this.i18n,\n },\n options.story\n );\n }\n\n if (options.markers && !this.markProgress) {\n const { installMarkers } = await import('./plugins/markers');\n this.markProgress = installMarkers(\n {\n videoEl: this.videoEl,\n overlayContainerEl: this.videoArea,\n addSeekBarMarker: (ratio, extraClass) => this.controlBar.seekBar.addMarker(ratio, extraClass),\n i18n: this.i18n,\n },\n options.markers\n );\n }\n\n if (options.segments?.length && !this.segments) {\n const { installSegments } = await import('./plugins/segments');\n this.segments = installSegments({ videoEl: this.videoEl, seekBar: this.controlBar.seekBar }, options.segments);\n }\n\n if (options.spriteThumbnails && !this.spriteThumbnails) {\n const { installSpriteThumbnails } = await import('./plugins/sprite-thumbnails');\n this.spriteThumbnails = installSpriteThumbnails(\n {\n videoEl: this.videoEl,\n seekBar: this.controlBar.seekBar,\n playerWidth: () => this.videoArea.clientWidth,\n },\n options.spriteThumbnails\n );\n }\n\n if (options.redirectScreen && !this.redirectScreen) {\n const { installRedirectScreen } = await import('./plugins/redirect-screen');\n this.redirectScreen = installRedirectScreen(\n { videoEl: this.videoEl, overlayContainerEl: this.videoArea, isAdActive: () => this.isAdPlaying(), i18n: this.i18n },\n options.redirectScreen\n );\n }\n\n if (options.qrResume && !this.qrResume) {\n const { installQrResume } = await import('./plugins/qr-resume');\n this.qrResume = installQrResume({ videoEl: this.videoEl, overlayContainerEl: this.videoArea, i18n: this.i18n }, options.qrResume);\n }\n if (this.qrResume) {\n // QrResume aç/kapa satırı her initPlayback'te yeniden eklenir (dil değişimi vb.).\n const qr = this.qrResume;\n this.controlBar.settingsMenu.setQrResumeToggle({\n label: this.i18n.qrResumeMenuLabel,\n getValueLabel: () => (qr.isEnabled() ? this.i18n.qrResumeOn : this.i18n.qrResumeOff),\n onToggle: () => qr.setEnabled(!qr.isEnabled()),\n });\n }\n\n if (options.pauseAd?.adUnitPath && !this.pauseAd) {\n const { installPauseAd } = await import('./plugins/pause-ad');\n this.pauseAd = installPauseAd(\n { videoEl: this.videoEl, hostEl: this, videoArea: this.videoArea, i18n: this.i18n, isBlocked: () => this.isChromeBlocked },\n options.pauseAd\n );\n }\n\n if (options.dubbing && !this.dubbing) {\n const { installDubbing } = await import('./plugins/dubbing');\n this.dubbing = installDubbing(\n {\n videoEl: this.videoEl,\n loadSource: (src, type) => this.sourceManager.load(src, type),\n registerSubmenu: (def) => this.controlBar.settingsMenu.registerSubmenu(def),\n unregisterSubmenu: (key) => this.controlBar.settingsMenu.unregisterSubmenu(key),\n i18n: this.i18n,\n },\n options.dubbing\n );\n }\n\n if (options.liveWallClock && !this.liveWallClock) {\n const liveWallClockOptions = options.liveWallClock === true ? {} : options.liveWallClock;\n const { installLiveWallClock } = await import('./plugins/live');\n this.liveWallClock = installLiveWallClock(\n {\n videoEl: this.videoEl,\n seekBarEl: this.controlBar.seekBar.el,\n addControlElement: (el) => this.controlBar.addElement(el),\n i18n: this.i18n,\n },\n liveWallClockOptions\n );\n }\n\n if (options.dai && !this.daiController) {\n const { installDai } = await import('./plugins/dai');\n this.daiController = await installDai(\n {\n videoEl: this.videoEl,\n hostEl: this,\n adUiEl: this.adLayerEl,\n loadStreamUrl: (url) => this.sourceManager.load(url),\n disableSeeking: () => this.disableSeeking(),\n enableSeeking: () => this.enableSeeking(),\n },\n options.dai\n );\n }\n\n if (options.subtitles?.length) {\n this.subtitleTracks = attachSubtitleTracks(this.videoEl, options.subtitles);\n const defaultTrack = options.subtitles.find((s) => s.default);\n // selectCaption: altyazı seçiminin tek doğruluk kaynağı (track mode + renderer + ayarlar menüsü).\n const selectCaption = (label: string | null): void => {\n const track = selectSubtitleTrack(this.subtitleTracks, label);\n this.captionRenderer.setActiveTrack(track);\n this.captionTrackActive = track !== null;\n this.controlBar.settingsMenu.setActiveCaption(label ?? this.i18n.captionsOff);\n this.controlBar.settingsMenu.setCaptionAppearance(track !== null ? this.buildCaptionAppearance() : null);\n };\n this.selectCaption = selectCaption;\n this.controlBar.setCaptions(\n [\n { label: this.i18n.captionsOff, onSelect: () => selectCaption(null) },\n ...this.subtitleTracks.map(({ label }) => ({\n label,\n onSelect: () => selectCaption(label),\n })),\n ],\n defaultTrack?.label ?? this.i18n.captionsOff\n );\n selectCaption(defaultTrack?.label ?? null);\n } else {\n clearSubtitleTracks(this.videoEl);\n this.subtitleTracks = [];\n this.selectCaption = null;\n this.captionRenderer.setActiveTrack(null);\n this.captionTrackActive = false;\n this.controlBar.settingsMenu.setCaptionAppearance(null);\n }\n }\n\n /** Ayarlar menüsünün \"Altyazı\" alt menüsüne eklenen Boyut/Renk/Konum satırları — her zaman GÜNCEL `this.i18n`'i okur (dil sonradan değişse bile). */\n private buildCaptionAppearance(): SettingsCaptionAppearance {\n const sizes: CaptionFontSize[] = ['small', 'normal', 'large'];\n const buildColorOptions = (\n presets: readonly string[],\n get: () => string,\n set: (value: string) => void,\n label: string\n ): SettingsColorOption[] =>\n presets.map((value, i) => ({\n value,\n active: get() === value,\n ariaLabel: `${label} ${i + 1}`,\n onSelect: () => set(value),\n }));\n return {\n sizeLabel: this.i18n.captionSize,\n getSizeOptions: () =>\n sizes.map((size) => ({\n label:\n size === 'small'\n ? this.i18n.captionSizeSmall\n : size === 'large'\n ? this.i18n.captionSizeLarge\n : this.i18n.captionSizeNormal,\n active: this.captionRenderer.getFontSize() === size,\n onSelect: () => this.captionRenderer.setFontSize(size),\n })),\n bgColorLabel: this.i18n.captionBgColor,\n getBgColorOptions: () =>\n buildColorOptions(\n CaptionRenderer.BG_COLOR_PRESETS,\n () => this.captionRenderer.getBgColor(),\n (v) => this.captionRenderer.setBgColor(v),\n this.i18n.captionBgColor\n ),\n textColorLabel: this.i18n.captionTextColor,\n getTextColorOptions: () =>\n buildColorOptions(\n CaptionRenderer.TEXT_COLOR_PRESETS,\n () => this.captionRenderer.getTextColor(),\n (v) => this.captionRenderer.setTextColor(v),\n this.i18n.captionTextColor\n ),\n resetPositionLabel: this.i18n.captionResetPosition,\n onResetPosition: () => this.captionRenderer.resetPosition(),\n };\n }\n\n /** Playlist panelinin monte edileceği, .video-area'nın ALTINDAKİ (shadow root içi) kapsayıcı — ilk ihtiyaçta oluşturulur. */\n private panelContainer: HTMLDivElement | null = null;\n private getOrCreatePanelContainer(): HTMLDivElement {\n if (!this.panelContainer) {\n this.panelContainer = document.createElement('div');\n this.root.appendChild(this.panelContainer);\n }\n return this.panelContainer;\n }\n\n /** Kalite değişirken oynatma konumunu ve play/pause durumunu korur. */\n private async switchQualitySource(source: NonNullable<HopePlayerOptions['sources']>[number]): Promise<void> {\n const resumeTime = this.videoEl.currentTime;\n const wasPlaying = !this.videoEl.paused;\n await this.sourceManager.load(source.src, source.type);\n this.videoEl.currentTime = resumeTime;\n if (wasPlaying) this.videoEl.play().catch(() => {});\n this.dispatchEvent(new CustomEvent('hp:qualitychange', { detail: { label: source.label } }));\n }\n\n private readonly onHlsLevelsChanged = (levels: HlsQualityLevel[], activeIndex: number): void => {\n // Kaynak değişince boş liste gelir — önceki HLS kaynağının seviyeleri menüde kalmasın.\n if (levels.length === 0 && this.hlsQualitiesShown) {\n this.hlsQualitiesShown = false;\n this.controlBar.setQualities([], '');\n return;\n }\n if (levels.length <= 1) return;\n this.hlsQualitiesShown = true;\n const label = (l: HlsQualityLevel) => `${l.height}p`;\n this.controlBar.setQualities(\n [\n { label: this.i18n.autoQuality, onSelect: () => this.sourceManager.setLevel(-1) },\n // Yüksekten düşüğe (hls.js artan sıralıyor) — l.index hls.js'teki gerçek seviye numarası, sıradan bağımsız.\n ...[...levels]\n .sort((x, y) => y.height - x.height)\n .map((l) => ({ label: label(l), onSelect: () => this.sourceManager.setLevel(l.index) })),\n ],\n activeIndex === -1 ? this.i18n.autoQuality : label(levels[activeIndex]!)\n );\n };\n\n // ── Fullscreen (vendor-prefix uyumlu) ───────────────────────────────\n\n /** iPhone Safari element tam ekranını desteklemiyor — yalnızca <video>'nun kendi (native kontrollü) tam ekranı. */\n private get iosVideo(): HTMLVideoElement & {\n webkitEnterFullscreen?: () => void;\n webkitExitFullscreen?: () => void;\n webkitDisplayingFullscreen?: boolean;\n } {\n return this.videoEl;\n }\n\n private requestFullscreenCompat(): void {\n const el = this as unknown as {\n requestFullscreen?: () => Promise<void>;\n webkitRequestFullscreen?: () => void;\n };\n const videoFallback = (): void => this.iosVideo.webkitEnterFullscreen?.();\n if (el.requestFullscreen) el.requestFullscreen().catch(videoFallback);\n else if (el.webkitRequestFullscreen) el.webkitRequestFullscreen();\n else videoFallback();\n }\n\n private exitFullscreenCompat(): void {\n if (this.iosVideo.webkitDisplayingFullscreen) {\n this.iosVideo.webkitExitFullscreen?.();\n return;\n }\n const doc = document as unknown as { webkitExitFullscreen?: () => void };\n if (document.exitFullscreen) void document.exitFullscreen();\n else if (doc.webkitExitFullscreen) doc.webkitExitFullscreen();\n }\n\n private isFullscreenActive(): boolean {\n const doc = document as unknown as { webkitFullscreenElement?: Element | null };\n return document.fullscreenElement === this || doc.webkitFullscreenElement === this || !!this.iosVideo.webkitDisplayingFullscreen;\n }\n\n private readonly onFullscreenChange = (e?: Event): void => {\n this.controlBar.setFullscreenState(this.isFullscreenActive());\n if (e?.type === 'webkitbeginfullscreen') this.showCaptionsNatively();\n else if (e?.type === 'webkitendfullscreen') this.syncCaptionsFromNative();\n };\n\n /**\n * iPhone native tam ekranında bizim altyazı katmanımız görünmez — seçili izi 'showing' yapıp iOS'un çizmesine bırakırız.\n */\n private showCaptionsNatively(): void {\n for (const { track } of this.subtitleTracks) if (track.mode === 'hidden') track.mode = 'showing';\n }\n\n /**\n * Native tam ekrandan dönüş: iOS menüsünde seçilen iz 'showing' kalır ve kendi katmanımızla çift altyazı çizilir.\n * Seçimi bizim tarafa aktarıp izi tekrar 'hidden' yaparız (hiçbiri showing değilse kullanıcı kapatmıştır).\n */\n private syncCaptionsFromNative(): void {\n if (!this.selectCaption) return;\n const showing = this.subtitleTracks.find(({ track }) => track.mode === 'showing');\n this.selectCaption(showing?.label ?? null);\n }\n\n // ── Oynatma durumuna göre merkez buton + otomatik gizlenme ──\n\n // Değer: 'hidden' (tamamen gizle — countdown/geo) ya da 'reduced' (yalnızca oynat/duraklat + ses — ads).\n private readonly chromeBlockers = new Map<string, 'hidden' | 'reduced'>();\n private get isChromeBlocked(): boolean {\n return this.chromeBlockers.size > 0;\n }\n private get isChromeFullyHidden(): boolean {\n for (const mode of this.chromeBlockers.values()) if (mode === 'hidden') return true;\n return false;\n }\n\n private readonly onPlay = (): void => {\n if (!this.isChromeBlocked) {\n this.centerPlayButton.style.opacity = '0';\n this.centerPlayButton.style.pointerEvents = 'none';\n this.scheduleAutoHide();\n }\n this.dispatchEvent(new CustomEvent('hp:play'));\n };\n\n private readonly onPause = (): void => {\n // Oynarken kurulan gizleme zamanlayıcısını iptal et — yoksa duraklatınca kontroller birazdan kayboluyordu.\n if (this.hideTimer) clearTimeout(this.hideTimer);\n if (!this.isChromeBlocked) {\n this.centerPlayButton.style.opacity = '1';\n this.centerPlayButton.style.pointerEvents = 'auto';\n this.showChrome();\n }\n this.dispatchEvent(new CustomEvent('hp:pause'));\n };\n\n private readonly onPointerDownFocus = (): void => {\n this.focus();\n // AdDisplayContainer.initialize() bir kullanıcı jestinde çağrılmalı (IMA) — player'a ilk dokunuşta.\n this.adsController?.initializeDisplayContainerOnce();\n };\n\n private readonly onVideoPressStart = (e: MouseEvent | TouchEvent): void => {\n this.tapCandidate = true;\n const point = 'touches' in e ? e.touches[0] : e;\n if (!point) return;\n this.tapStartX = point.clientX;\n this.tapStartY = point.clientY;\n };\n\n private readonly onVideoPressEnd = (e: MouseEvent | TouchEvent): void => {\n if (!this.tapCandidate) return;\n this.tapCandidate = false;\n if (this.isChromeBlocked) return;\n if (this.gestureControls?.isCurrentlyHolding()) return;\n\n const point = 'changedTouches' in e ? e.changedTouches[0] : e;\n if (point) {\n const moved = Math.hypot(point.clientX - this.tapStartX, point.clientY - this.tapStartY);\n if (moved > TAP_MAX_MOVE_PX) return;\n }\n if (this.videoEl.paused) void this.videoEl.play().catch(() => {});\n else this.videoEl.pause();\n };\n\n private readonly onVideoPressCancel = (): void => {\n this.tapCandidate = false;\n };\n\n private showChrome(): void {\n this.setChromeOpacity('1');\n }\n\n /** Chrome görünürlüğünün tek giriş noktası — altyazı da haberdar olur (kontroller gizlenince en alta iner). */\n private setChromeOpacity(value: '0' | '1'): void {\n this.chromeEl.style.opacity = value;\n this.chromeVisible = value === '1';\n // captionRenderer constructor'da chrome'dan SONRA kuruluyor — o ana kadarki çağrılar için güvenli.\n this.captionRenderer?.setChromeVisible(this.chromeVisible);\n this.updateMiniProgress();\n }\n\n /** İnce ilerleme çizgisi: yalnızca kontroller gizliyken; reklam/giriş ekranı (chrome bloklu) sırasında değil. */\n private updateMiniProgress(): void {\n this.miniProgress?.setVisible(!this.chromeVisible && !this.isChromeBlocked);\n }\n\n /**\n * Plugin (ads/countdown/geo) chrome'u kendi key'iyle gizler; unblockChrome aynı key'le açar.\n * 'reduced' (ads): yalnızca oynat/duraklat + ses kalır. Merkez buton her modda gizli.\n */\n blockChrome(key: string, mode: 'hidden' | 'reduced' = 'hidden'): void {\n this.chromeBlockers.set(key, mode);\n this.updateMiniProgress();\n if (this.hideTimer) clearTimeout(this.hideTimer);\n this.centerPlayButton.style.opacity = '0';\n this.centerPlayButton.style.pointerEvents = 'none';\n if (this.isChromeFullyHidden) {\n this.setChromeOpacity('0');\n this.chromeEl.style.pointerEvents = 'none';\n } else {\n // pointerEvents'e inline dokunma — CSS'teki pointer-events-none'ı ezip reklamın \"Reklamı Geç\" butonunu kapatırdı.\n this.setChromeOpacity('1');\n }\n this.controlBar.setAdMode(this.chromeBlockers.get('ads') === 'reduced');\n }\n\n /** Bloklayan plugin işini bitirince çağırır — başka bir blocker hâlâ aktifse chrome açılmaz. */\n unblockChrome(key: string): void {\n this.chromeBlockers.delete(key);\n this.updateMiniProgress();\n this.controlBar.setAdMode(this.chromeBlockers.get('ads') === 'reduced');\n if (this.isChromeBlocked) {\n if (this.isChromeFullyHidden) {\n this.setChromeOpacity('0');\n this.chromeEl.style.pointerEvents = 'none';\n } else {\n // bkz. blockChrome'daki not — pointerEvents'a KASITLI dokunulmuyor.\n this.setChromeOpacity('1');\n this.chromeEl.style.pointerEvents = '';\n }\n return;\n }\n\n this.chromeEl.style.pointerEvents = '';\n if (this.videoEl.paused) {\n this.centerPlayButton.style.opacity = '1';\n this.centerPlayButton.style.pointerEvents = 'auto';\n this.showChrome();\n } else {\n this.scheduleAutoHide();\n }\n }\n\n /** DAI reklam arası boyunca kullanıcı reklamın İÇİNE seek edemesin diye (sunucu taraflı eklenen reklamlar seekable aralığın parçası). */\n disableSeeking(): void {\n this.controlBar.setSeekingEnabled(false);\n this.controlBar.seekBar.el.style.pointerEvents = 'none';\n this.controlBar.seekBar.el.style.opacity = '0.5';\n }\n\n enableSeeking(): void {\n this.controlBar.setSeekingEnabled(true);\n this.controlBar.seekBar.el.style.pointerEvents = '';\n this.controlBar.seekBar.el.style.opacity = '';\n }\n\n private readonly onPointerMove = (e: PointerEvent): void => {\n // chromeEl pointer-events-none; olay yolunda yalnızca imleç bir kontrolün (pointer-events-auto) üzerindeyse görünür.\n this.pointerOverControls = e.pointerType === 'mouse' && e.composedPath().includes(this.chromeEl);\n this.scheduleAutoHide();\n };\n\n private readonly onPointerLeave = (e: PointerEvent): void => {\n if (e.pointerType !== 'mouse') return;\n this.pointerOverControls = false;\n this.scheduleAutoHide();\n };\n\n private readonly scheduleAutoHide = (): void => {\n this.showChrome();\n if (this.hideTimer) clearTimeout(this.hideTimer);\n if (this.videoEl.paused) return;\n this.hideTimer = setTimeout(() => {\n // Duraklatılmışken, fare kontrollerin üzerindeyken ya da ayarlar menüsü açıkken gizleme.\n if (this.videoEl.paused || this.pointerOverControls || this.controlBar.settingsMenu.isOpen) return;\n this.setChromeOpacity('0');\n }, this.autoHideDelayMs);\n };\n}\n","import { HopePlayerElement } from './HopePlayerElement';\n\nif (typeof window !== 'undefined' && !customElements.get('hope-player')) {\n customElements.define('hope-player', HopePlayerElement);\n}\n\nexport { HopePlayerElement };\nexport type { PlaybackEngineInfo } from './hls/SourceManager';\nexport type {\n HopeThemePreset,\n HopeLocale,\n HopeLocaleStrings,\n HopePlayerOptions,\n HopePlayerEventMap,\n AdsOptions,\n AdsRetryOptions,\n PrebidOptions,\n PrebidBreakOptions,\n PrebidBidderConfig,\n GestureOptions,\n LoopSectionOptions,\n InViewAutoplayOptions,\n StickyOptions,\n StickyCorner,\n PlayableItem,\n PlaylistOptions,\n PlaylistUiOptions,\n StoryOptions,\n StoryUiOptions,\n StoryGestureOptions,\n MarkerPopupOptions,\n MarkerPingOptions,\n MarkerAction,\n MarkerItem,\n MarkersOptions,\n SegmentItem,\n SpriteThumbnailsOptions,\n CountdownScreenOptions,\n GeoCheckerOptions,\n RedirectScreenSuggestion,\n RedirectScreenOptions,\n QrResumeOptions,\n PauseAdOptions,\n SkipButtonsOptions,\n DubbingTrack,\n DubbingOptions,\n LiveWallClockOptions,\n DaiOptions,\n LiveAdsOptions,\n} from './types';\nexport type { SettingsSubmenuDef, SettingsSubmenuItem } from './controls/SettingsMenu';\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hope-player': HopePlayerElement;\n }\n}\n"],"names":["prefersNativeHls","ua","iOS","safari","hasMse","w","detectSourceType","src","type","normalizedType","_a","SourceManager","video","onLevelsChanged","__publicField","sourceType","reason","onMeta","cleanup","onError","unsupported","Hls","hls","parsed","_event","data","levels","level","index","formatTime","seconds","totalSeconds","h","m","mm","ss","SeekBar","labels","duration","hasDuration","ratio","rect","x","_b","tick","playedRatio","bufferedEnd","i","bufferedRatio","c","span","local","r","track","key","suppressed","clientX","next","zoneEnd","ch","ranges","container","el","bufferedEl","playedEl","base","extraClass","marker","createIcon","name","setIconName","WHEEL_VOLUME_STEP","HIDE_DELAY_MS","VolumePanel","adHooks","current","effectiveVolume","label","playing","e","clientY","color","MENU_GAP_PX","MENU_EDGE_PX","MENU_MIN_HEIGHT_PX","MENU_MAX_HEIGHT_PX","SettingsMenu","playbackRates","area","a","b","anchor","drop","content","room","options","activeLabel","appearance","toggle","def","s","value","onClick","btn","title","onBack","item","rate","active","q","kind","grid","opt","swatch","LIVE_EDGE_TOLERANCE_SEC","COMPACT_MAX_WIDTH","skipButton","direction","part","iconButton","num","setButtonLabel","iconName","shortcut","icon","ControlBar","callbacks","paused","isLive","total","remaining","edge","behind","row","leftGroup","play","liveDot","spacer","rightGroup","pip","fullscreen","width","compact","isFullscreen","back","forward","enabled","render","delta","v","start","end","display","iconColor","show","seekable","buffered","SHOW_DELAY_MS","GAP_PX","EDGE_PADDING_PX","EXCLUDE_PARTS","canHover","TooltipController","mountEl","target","related","check","fromEl","mountRect","targetRect","ttRect","top","left","maxLeft","KeyboardController","host","toggleFullscreen","LoadingSpinner","RETRY_ICON","ErrorScreen","card","fn","code","messages","pools","generations","attachSubtitleTracks","subtitles","t","clearSubtitleTracks","generation","pool","attached","sub","loadCues","cue","selectSubtitleTrack","tracks","trackLabel","isActive","text","res","err","parseVttCues","applyCueSettings","TIMESTAMP","TIMING_LINE","toSeconds","acc","cues","blocks","block","lines","timingIndex","l","body","settings","token","raw","ROWS","TOP_GAP_PX","GAP_ABOVE_SEEKBAR_PX","GAP_ABOVE_SEEKBAR_COMPACT_PX","BOTTOM_GAP_MIN_PX","DRAG_TAP_THRESHOLD_PX","STORAGE_KEY_ROW","STORAGE_KEY_SIZE","STORAGE_KEY_BG_COLOR","STORAGE_KEY_TEXT_COLOR","FONT_SIZE_MULTIPLIER","BG_COLOR_PRESETS","TEXT_COLOR_PRESETS","readStoredRow","n","readStoredFontSize","readStoredColor","presets","fallback","CaptionRenderer","videoArea","seekBarEl","min","max","targetBottom","translatePx","finalBottom","snappedIndex","size","areaRect","seekRect","topMargin","bottomGap","rowIndex","animate","fromPx","targetPx","prevPx","visible","MiniProgress","ACCUMULATE_WINDOW_MS","HIDE_AFTER_MS","CHEVRON","SeekFeedback","chevrons","now","sameDirection","STYLE_ID","injectIconFont","style","iconFontFaceCss","tr","en","BUILTIN_LOCALES","createLocaleStrings","locale","overrides","applyLocale","DEFAULT_PLAYBACK_RATES","DEFAULT_AUTO_HIDE_DELAY_MS","TAP_MAX_MOVE_PX","DEFAULT_SKIP_SECONDS","DEFAULT_KEYBOARD_SEEK_STEP","TEMPLATE","HopePlayerElement","activeIndex","y","point","tailwindCss","wrapper","centerChip","open","p","_c","_d","_e","_f","_g","_h","_i","_j","_k","_l","_m","_n","_o","_p","_q","_r","_s","attrOptions","seekStep","skip","gateCtx","installCountdownScreen","installGeoChecker","pending","sources","initial","adsOptions","installAds","gestureOptions","installGesture","loopOptions","installLoopSection","inViewOptions","installInViewAutoplay","stickyOptions","installSticky","installPlaylist","url","tag","installStory","installMarkers","installSegments","installSpriteThumbnails","installRedirectScreen","installQrResume","qr","installPauseAd","installDubbing","liveWallClockOptions","installLiveWallClock","installDai","defaultTrack","selectCaption","sizes","buildColorOptions","get","set","source","resumeTime","wasPlaying","videoFallback","doc","showing","mode"],"mappings":"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"}