@hopeplayer/core 1.0.11 → 1.0.13

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 (72) hide show
  1. package/dist/HopePlayerElement.d.ts +34 -0
  2. package/dist/HopePlayerElement.d.ts.map +1 -1
  3. package/dist/chunks/ScratchSound-0XKHUcJK.js +174 -0
  4. package/dist/chunks/ScratchSound-0XKHUcJK.js.map +1 -0
  5. package/dist/chunks/{index-BHO8Gbrj.js → index-01P9jpUY.js} +819 -418
  6. package/dist/chunks/index-01P9jpUY.js.map +1 -0
  7. package/dist/chunks/{index-BeBmx35F.js → index-048h1-5X.js} +2 -2
  8. package/dist/chunks/{index-BeBmx35F.js.map → index-048h1-5X.js.map} +1 -1
  9. package/dist/chunks/{index-C6ONQXlF.js → index-9NzklChR.js} +2 -2
  10. package/dist/chunks/{index-C6ONQXlF.js.map → index-9NzklChR.js.map} +1 -1
  11. package/dist/chunks/index-BCMVXNL0.js +845 -0
  12. package/dist/chunks/index-BCMVXNL0.js.map +1 -0
  13. package/dist/chunks/{index-d_U9dcN6.js → index-BO0tjMR6.js} +2 -2
  14. package/dist/chunks/{index-d_U9dcN6.js.map → index-BO0tjMR6.js.map} +1 -1
  15. package/dist/chunks/index-BgJJr55r.js +311 -0
  16. package/dist/chunks/index-BgJJr55r.js.map +1 -0
  17. package/dist/chunks/{index-lwFM1iPV.js → index-CP1Y6U0c.js} +2 -2
  18. package/dist/chunks/{index-lwFM1iPV.js.map → index-CP1Y6U0c.js.map} +1 -1
  19. package/dist/chunks/index-DCXX1ZJG.js +108 -0
  20. package/dist/chunks/index-DCXX1ZJG.js.map +1 -0
  21. package/dist/chunks/{index-DGSYKljQ.js → index-n-1IIClr.js} +2 -2
  22. package/dist/chunks/{index-DGSYKljQ.js.map → index-n-1IIClr.js.map} +1 -1
  23. package/dist/controls/ControlBar.d.ts +32 -0
  24. package/dist/controls/ControlBar.d.ts.map +1 -1
  25. package/dist/controls/SeekBar.d.ts +8 -0
  26. package/dist/controls/SeekBar.d.ts.map +1 -1
  27. package/dist/controls/SettingsMenu.d.ts +3 -0
  28. package/dist/controls/SettingsMenu.d.ts.map +1 -1
  29. package/dist/controls/VolumePanel.d.ts +0 -2
  30. package/dist/controls/VolumePanel.d.ts.map +1 -1
  31. package/dist/debug/ErrorLog.d.ts +29 -0
  32. package/dist/debug/ErrorLog.d.ts.map +1 -0
  33. package/dist/hls/SourceManager.d.ts +11 -0
  34. package/dist/hls/SourceManager.d.ts.map +1 -1
  35. package/dist/hope-player.js +1 -1
  36. package/dist/i18n/locales/en.d.ts.map +1 -1
  37. package/dist/i18n/locales/tr.d.ts.map +1 -1
  38. package/dist/i18n/types.d.ts +19 -0
  39. package/dist/i18n/types.d.ts.map +1 -1
  40. package/dist/index.d.ts +2 -1
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/keyboard/KeyboardController.d.ts +2 -0
  43. package/dist/keyboard/KeyboardController.d.ts.map +1 -1
  44. package/dist/plugins/ads/AdSurfaceGuard.d.ts +39 -0
  45. package/dist/plugins/ads/AdSurfaceGuard.d.ts.map +1 -0
  46. package/dist/plugins/ads/AdsController.d.ts +103 -1
  47. package/dist/plugins/ads/AdsController.d.ts.map +1 -1
  48. package/dist/plugins/ads/PrerollGate.d.ts +51 -0
  49. package/dist/plugins/ads/PrerollGate.d.ts.map +1 -0
  50. package/dist/plugins/ads/preconnect.d.ts +2 -0
  51. package/dist/plugins/ads/preconnect.d.ts.map +1 -0
  52. package/dist/plugins/audio/AudioStage.d.ts +80 -0
  53. package/dist/plugins/audio/AudioStage.d.ts.map +1 -0
  54. package/dist/plugins/audio/ScratchSound.d.ts +48 -0
  55. package/dist/plugins/audio/ScratchSound.d.ts.map +1 -0
  56. package/dist/plugins/audio/index.d.ts +7 -0
  57. package/dist/plugins/audio/index.d.ts.map +1 -0
  58. package/dist/plugins/audio/vinylSvg.d.ts +12 -0
  59. package/dist/plugins/audio/vinylSvg.d.ts.map +1 -0
  60. package/dist/plugins/debug/DebugPanel.d.ts +37 -0
  61. package/dist/plugins/debug/DebugPanel.d.ts.map +1 -0
  62. package/dist/plugins/debug/index.d.ts +5 -0
  63. package/dist/plugins/debug/index.d.ts.map +1 -0
  64. package/dist/subtitles/CaptionRenderer.d.ts +6 -0
  65. package/dist/subtitles/CaptionRenderer.d.ts.map +1 -1
  66. package/dist/subtitles/attachTracks.d.ts.map +1 -1
  67. package/dist/types/index.d.ts +108 -1
  68. package/dist/types/index.d.ts.map +1 -1
  69. package/package.json +1 -1
  70. package/dist/chunks/index-BHO8Gbrj.js.map +0 -1
  71. package/dist/chunks/index-glxDu2eJ.js +0 -531
  72. package/dist/chunks/index-glxDu2eJ.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-01P9jpUY.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/utils/seek-by.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/controls/ContextMenu.ts","../../src/debug/ErrorLog.ts","../../src/icons/injectIconFont.ts","../../src/i18n/locales/tr.ts","../../src/i18n/locales/en.ts","../../src/i18n/index.ts","../../src/plugins/ads/PrerollGate.ts","../../src/plugins/ads/preconnect.ts","../../src/HopePlayerElement.ts","../../src/index.ts"],"sourcesContent":["import type { HlsConfig } from 'hls.js';\nimport type { HopeHlsOptions } from '../types';\n\n\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 /** `option` = `options.hls.engine: 'native'` ile istendi. */\n reason?: 'apple-native' | 'no-mse' | 'hlsjs-failed' | 'option';\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\n/** Yayının kendi altyazı/kapalı altyazı izi (HLS manifest altyazıları, CEA-608). */\nexport interface StreamTextTrack {\n /** `sub:<hls.js id>` (manifest altyazısı) ya da `cc:<textTrackN>` (CEA-608). */\n id: string;\n kind: 'subtitles' | 'captions';\n label: string;\n lang: string;\n}\n\n/** Yayının alternatif ses izi (HLS EXT-X-MEDIA TYPE=AUDIO ya da Safari native `audioTracks`). */\nexport interface StreamAudioTrack {\n index: number;\n label: string;\n lang: string;\n}\n\nexport interface SourceManagerCallbacks {\n onLevelsChanged(levels: HlsQualityLevel[], activeIndex: number): void;\n /** Boş liste = kaynak değişti, önceki izler kalmasın. */\n onAudioTracksChanged(tracks: StreamAudioTrack[], activeIndex: number): void;\n /** hls.js yayın altyazıları — boş liste = sıfırla. Liste büyüyebilir (CEA-608 izleri oynarken bulunur). */\n onTextTracksFound(tracks: StreamTextTrack[]): void;\n onCues(trackId: string, cues: VTTCue[]): void;\n /** hls.js kurtarılamayan bir hata verdi (video.error oluşmaz) — `network` = yayın/segment indirilemiyor, `media` = çözümlenemiyor. */\n onFatalError(kind: 'network' | 'media'): void;\n /** hls.js'in her hatası (kurtarılanlar dahil) — hata ayıklama kaydı için. */\n onStreamError?(info: { type: string; details: string; fatal: boolean; url?: string; httpStatus?: number; reason?: string }): void;\n}\n\ninterface NativeAudioTrack {\n label: string;\n language: string;\n enabled: boolean;\n}\ntype NativeAudioTrackList = EventTarget & ArrayLike<NativeAudioTrack>;\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 private hlsOptions: HopeHlsOptions = {};\n private streamTextTracks = new Map<string, StreamTextTrack>();\n /** Safari native HLS ses izi dinleyicilerini kaldırır. */\n private nativeAudioCleanup: (() => void) | null = null;\n\n constructor(\n video: HTMLVideoElement,\n private readonly callbacks: SourceManagerCallbacks\n ) {\n this.video = video;\n }\n\n /** `options.hls` — sonraki `load()`'da uygulanır. */\n configure(options: HopeHlsOptions | undefined): void {\n this.hlsOptions = options ?? {};\n }\n\n /** Bu kaynak zaten yüklü ve hatasız mı — aynı kaynak için yeniden yükleme (başa sarma) gerekmez. */\n isLoaded(src: string, type?: string): boolean {\n return !!this.last && this.last.src === src && this.last.type === type && !this.video.error && this.video.readyState > 0;\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 kalite / ses / altyazı listeleri kalmasın.\n this.callbacks.onLevelsChanged([], -1);\n this.callbacks.onAudioTracksChanged([], -1);\n this.streamTextTracks.clear();\n this.callbacks.onTextTracksFound([]);\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 engine = this.hlsOptions.engine ?? 'auto';\n const canNative = this.video.canPlayType('application/vnd.apple.mpegurl') !== '';\n if (engine === 'native' && canNative) {\n this.loadNativeHls(src, 'option');\n return;\n }\n // Safari / iOS: native HLS (başarısız olursa probeNativeHls hls.js'e geçer). MSE yoksa da tek yol native.\n // `engine: 'hls.js'` bunu atlar — Safari'de de kalite/ses menüsü için hls.js (iOS 17.1+ ManagedMediaSource).\n if (engine !== 'hls.js' && 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 /** hls.js ile oynatılıyorsa instance (gelişmiş kullanım: olaylar, istatistik); değilse null. */\n get hlsInstance(): HlsInstance | null {\n return this.hls;\n }\n\n private loadNativeHls(src: string, reason: PlaybackEngineInfo['reason']): void {\n this.engineInfo = { engine: 'native-hls', reason };\n this.probeNativeHls(src);\n this.watchNativeAudioTracks();\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.) ya da native özellikle istendiyse hls.js'e dönme.\n if (!hasMse() || this.engineInfo.reason === 'hlsjs-failed' || this.engineInfo.reason === 'option') return;\n const onMeta = (): void => cleanup();\n const onError = (): void => {\n const unsupported = this.video.error?.code === 4;\n cleanup();\n if (unsupported) {\n this.nativeAudioCleanup?.();\n void this.attachHlsJs(src);\n }\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 /** Safari native HLS: alternatif ses izleri `video.audioTracks`'te (diğer tarayıcılarda bu API yok). */\n private watchNativeAudioTracks(): void {\n const list = (this.video as unknown as { audioTracks?: NativeAudioTrackList }).audioTracks;\n if (!list) return;\n const report = (): void => {\n const tracks: StreamAudioTrack[] = Array.from(list, (t, index) => ({ index, label: t.label || t.language || `${index + 1}`, lang: t.language }));\n this.callbacks.onAudioTracksChanged(tracks, Array.from(list).findIndex((t) => t.enabled));\n };\n for (const ev of ['addtrack', 'removetrack', 'change']) list.addEventListener(ev, report);\n this.nativeAudioCleanup = () => {\n for (const ev of ['addtrack', 'removetrack', 'change']) list.removeEventListener(ev, report);\n this.nativeAudioCleanup = null;\n };\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(this.buildHlsConfig());\n\n this.hls = hls;\n this.engineInfo = { engine: 'hls.js' };\n let parsed = false;\n let mediaRecoveryTried = 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 (this.hls === hls) {\n const d = data as unknown as { url?: string; frag?: { url?: string }; context?: { url?: string }; response?: { code?: number }; reason?: string; error?: Error };\n this.callbacks.onStreamError?.({\n type: String(data.type),\n details: String(data.details),\n fatal: !!data.fatal,\n url: d.url ?? d.frag?.url ?? d.context?.url,\n httpStatus: d.response?.code,\n reason: d.reason ?? d.error?.message,\n });\n }\n if (!data.fatal || 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 (!parsed && loadFailed && this.video.canPlayType('application/vnd.apple.mpegurl') !== '') {\n hls.destroy();\n this.hls = null;\n this.loadNativeHls(src, 'hlsjs-failed');\n return;\n }\n // Medya hatası: hls.js'in önerdiği gibi bir kez kurtarmayı dene (decoder/MSE takılması çoğu zaman düzelir).\n if (data.type === Hls.ErrorTypes.MEDIA_ERROR && !mediaRecoveryTried) {\n mediaRecoveryTried = true;\n hls.recoverMediaError();\n return;\n }\n // Ağ hataları zaten hls.js'in kendi retry ayarlarıyla denendi — kurtarılamadı.\n hls.stopLoad();\n this.callbacks.onFatalError(data.type === Hls.ErrorTypes.NETWORK_ERROR ? 'network' : 'media');\n });\n\n const levels = (): HlsQualityLevel[] => hls.levels.map((level, index) => ({ index, height: level.height, bitrate: level.bitrate }));\n\n hls.on(Hls.Events.MANIFEST_PARSED, () => {\n parsed = true;\n this.callbacks.onLevelsChanged(levels(), hls.currentLevel);\n });\n\n hls.on(Hls.Events.LEVEL_SWITCHED, (_event, data) => {\n // Otomatik (ABR) modda menü \"Otomatik\"i seçili göstersin, o anki seviyeyi değil.\n this.callbacks.onLevelsChanged(levels(), hls.autoLevelEnabled ? -1 : data.level);\n });\n\n const audio = (): StreamAudioTrack[] =>\n hls.audioTracks.map((t, index) => ({ index, label: t.name || t.lang || `${index + 1}`, lang: t.lang ?? '' }));\n hls.on(Hls.Events.AUDIO_TRACKS_UPDATED, () => this.callbacks.onAudioTracksChanged(audio(), hls.audioTrack));\n hls.on(Hls.Events.AUDIO_TRACK_SWITCHED, (_event, data) => this.callbacks.onAudioTracksChanged(audio(), data.id));\n\n // Yayın altyazıları: renderTextTracksNatively:false ile hls.js <track> oluşturmaz (iOS'ta <track> videoyu\n // kod 4 ile düşürüyor), izleri ve cue'ları olayla verir — player kendi addTextTrack havuzuna koyar.\n hls.on(Hls.Events.NON_NATIVE_TEXT_TRACKS_FOUND, (_event, data) => {\n for (const t of data.tracks) {\n const sub = t.subtitleTrack;\n const id = sub ? `sub:${sub.id}` : `cc:${(t as { _id?: string })._id ?? t.label}`;\n const kind = t.kind === 'captions' ? 'captions' : 'subtitles';\n this.streamTextTracks.set(id, { id, kind, label: t.label, lang: sub?.lang ?? t.closedCaptions?.lang ?? '' });\n }\n this.callbacks.onTextTracksFound([...this.streamTextTracks.values()]);\n });\n hls.on(Hls.Events.CUES_PARSED, (_event, data) => {\n const id = data.type === 'subtitles' && data.subtitleTrack ? `sub:${data.subtitleTrack.id}` : `cc:${data.track}`;\n this.callbacks.onCues(id, data.cues as VTTCue[]);\n });\n\n hls.attachMedia(this.video);\n hls.loadSource(src);\n }\n\n private buildHlsConfig(): Partial<HlsConfig> {\n const user = this.hlsOptions.config ?? {};\n // liveDurationInfinity: hls.js canlıda varsayılan olarak SONLU bir duration verir (kayan pencere sonu) — player\n // canlıyı duration === Infinity ile tanıdığı için canlı rozeti/duvar saati açılmıyor, süre \"0:35 / 0:54\" görünüyordu.\n const config: Partial<HlsConfig> = { enableWorker: true, renderTextTracksNatively: false, liveDurationInfinity: true, ...user };\n if (this.hlsOptions.withCredentials) {\n const { xhrSetup, fetchSetup } = user;\n config.xhrSetup = (xhr, url, context) => {\n xhr.withCredentials = true;\n return xhrSetup?.(xhr, url, context);\n };\n config.fetchSetup = (context, init) => {\n const withCreds = { ...init, credentials: 'include' as RequestCredentials };\n return fetchSetup ? fetchSetup(context, withCreds) : new Request(context.url, withCreds);\n };\n }\n return config;\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 setAudioTrack(index: number): void {\n if (this.hls) {\n this.hls.audioTrack = index;\n return;\n }\n const list = (this.video as unknown as { audioTracks?: NativeAudioTrackList }).audioTracks;\n if (!list) return;\n // Önce yeniyi aç, sonra diğerlerini kapat — Safari tüm izler kapalı kalınca sesi kesiyor.\n if (list[index]) list[index]!.enabled = true;\n Array.from(list).forEach((t, i) => {\n if (i !== index) t.enabled = false;\n });\n }\n\n /**\n * Yayın altyazısı seçildi (null = yayın altyazısı yok). hls.js manifest altyazısının segmentlerini yalnızca\n * seçili `subtitleTrack` için indirir; CEA-608 cue'ları zaten video segmentlerinden sürekli gelir.\n */\n selectTextTrack(id: string | null): void {\n if (!this.hls) return;\n const hlsId = id?.startsWith('sub:') ? Number(id.slice(4)) : NaN;\n this.hls.subtitleTrack = Number.isNaN(hlsId) ? -1 : this.hls.subtitleTracks.findIndex((t) => t.id === hlsId);\n }\n\n destroy(): void {\n this.nativeHlsProbe?.();\n this.nativeAudioCleanup?.();\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\n/** Canlıda geri sarılabilir pencere bundan kısaysa (sn) yayın DVR'sız sayılır — seek bar pasif. */\nconst MIN_LIVE_WINDOW_SEC = 10;\n/** Canlıda seek bar'ın en sağına tıklanınca canlı ucun bu kadar gerisine gidilir (sn). */\nconst LIVE_EDGE_SAFETY_SEC = 1;\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.layoutWidth();\n this.measureChapters();\n this.render();\n });\n this.resizeObserver.observe(this.el);\n this.trackWidth = this.layoutWidth();\n }\n\n /** Canlıda hover zamanını başka bir bileşen gösteriyor mu (live-wall-clock tooltip'i) — üst üste binmesin. */\n liveHoverHandled = false;\n\n /**\n * Seek bar'ın temsil ettiği zaman aralığı: VOD'da 0 → süre; canlıda (duration Infinity) yayının izin verdiği\n * geri sarma penceresi (seekable başı → canlı uç). Pencere çok kısaysa (DVR yok) ya da süre bilinmiyorsa null.\n */\n private timeline(): { start: number; end: number; live: boolean } | null {\n const duration = this.video.duration;\n if (Number.isFinite(duration) && duration > 0) return { start: 0, end: duration, live: false };\n if (duration !== Infinity) return null;\n const { seekable } = this.video;\n if (!seekable.length) return null;\n const start = seekable.start(0);\n const end = seekable.end(seekable.length - 1);\n return end - start >= MIN_LIVE_WINDOW_SEC ? { start, end, live: true } : null;\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 tl = this.timeline();\n const ratio = this.ratioAtClientX(e.clientX);\n\n // Hover noktası: sürüklerken gösterilmez (thumb zaten imlecin altında); geri sarılamayan canlıda konum yok.\n if (tl && !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 if (this.hoverTimeSuppressors.size || !tl || (tl.live && this.liveHoverHandled)) {\n this.hoverTimeEl.removeAttribute('data-visible');\n return;\n }\n const time = tl.start + ratio * (tl.end - tl.start);\n // Canlıda mutlak zaman anlamsız — canlı uçtan ne kadar geride (\"-1:24\").\n this.hoverTimeEl.textContent = tl.live ? `-${formatTime(tl.end - time)}` : formatTime(time);\n this.hoverTimeEl.setAttribute('data-visible', '');\n // İmleci ortala, seek bar kenarlarından taşma.\n const w = this.hoverTimeEl.offsetWidth;\n const x = Math.min(Math.max(this.layoutXAtClientX(e.clientX) - w / 2, 0), Math.max(this.trackWidth - 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 x = this.layoutXAtClientX(clientX);\n if (!this.chapters.length) return this.trackWidth > 0 ? Math.min(1, Math.max(0, x / this.trackWidth)) : 0;\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 /**\n * Seek bar'ın DÜZEN genişliği (px). getBoundingClientRect() ata elementlerin CSS transform'undan etkilenir: player\n * ölçekli bir giriş animasyonuyla (ör. scale(0.985)) gösterilirken ölçülürse genişlik küçük kalıyor, animasyon\n * bitince düzen boyutu değişmediği için ResizeObserver tekrar tetiklenmiyor ve thumb dolu kısmın gerisinde kalıyordu.\n */\n /** Ekran x koordinatının seek bar içindeki DÜZEN px'i (ata transform'u ölçekliyorsa ona göre düzeltilmiş). */\n private layoutXAtClientX(clientX: number): number {\n const rect = this.el.getBoundingClientRect();\n return rect.width > 0 ? ((clientX - rect.left) * this.trackWidth) / rect.width : 0;\n }\n\n private layoutWidth(): number {\n return parseFloat(getComputedStyle(this.el).width) || this.el.offsetWidth;\n }\n\n private measureChapters(): void {\n if (!this.chapters.length) return;\n const bar = this.el.getBoundingClientRect();\n // Ekran px'ini düzen px'ine çevir (ata transform'u varsa) — thumb `translate` düzen px'inde konumlanıyor.\n const k = bar.width > 0 ? this.trackWidth / bar.width : 1;\n for (const c of this.chapters) {\n const r = c.el.getBoundingClientRect();\n c.left = (r.left - bar.left) * k;\n c.width = r.width * k;\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 tl = this.timeline();\n if (!tl) return;\n\n if (e.key === 'ArrowRight') {\n this.video.currentTime = Math.min(tl.end, 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(tl.start, this.video.currentTime - this.keyboardStep);\n this.onKeyboardSeek?.(-this.keyboardStep);\n e.preventDefault();\n }\n };\n\n private seekToRatio(ratio: number): void {\n const tl = this.timeline();\n if (!tl) return;\n const time = tl.start + ratio * (tl.end - tl.start);\n // Canlıda tam uca değil biraz gerisine — en son segmentin sonuna seek edince oynatma takılabiliyor.\n this.video.currentTime = tl.live ? Math.min(time, tl.end - LIVE_EDGE_SAFETY_SEC) : time;\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 tl = this.timeline();\n // Zaman aralığı yoksa (geri sarılamayan canlı / henüz metadata yok) thumb gizlenir — CSS `.hp-seekbar[data-no-duration]`.\n this.el.toggleAttribute('data-no-duration', !tl);\n this.el.toggleAttribute('data-live', !!tl?.live);\n if (!tl) {\n this.hoverTimeEl.removeAttribute('data-visible');\n this.hoverDotEl.removeAttribute('data-visible');\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 const span = tl.end - tl.start;\n const toRatio = (t: number): number => Math.min(1, Math.max(0, (t - tl.start) / span));\n\n const playedRatio = toRatio(this.video.currentTime);\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 = toRatio(bufferedEnd);\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-valuemin', String(Math.floor(tl.start)));\n this.el.setAttribute('aria-valuemax', String(Math.floor(tl.end)));\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 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 =\n | 'main'\n | 'speed'\n | 'quality'\n | 'captions'\n | 'captions-settings'\n | 'captions-size'\n | 'captions-bg'\n | 'captions-text'\n | `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-settings' ||\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-settings') this.renderCaptionSettings();\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 // Görünüm ayarları ayrı bir (3.) panelde — dil listesi sade kalsın. Altyazı KAPALIYKEN anlamsız, gizli.\n if (this.captionAppearance && this.activeCaptionLabel !== this.labels.captionsOff) {\n const divider = document.createElement('div');\n divider.className = 'hp:my-1 hp:border-t hp:border-on-surface/10';\n divider.setAttribute('role', 'separator');\n this.panel.appendChild(divider);\n this.panel.appendChild(\n this.row(this.labels.captionSettings, '', () => {\n this.currentPanel = 'captions-settings';\n this.renderCaptionSettings();\n })\n );\n }\n }\n\n /** Altyazı → Altyazı ayarları: boyut, arka plan / yazı rengi, konumu sıfırla — her satırda o anki değer. */\n private renderCaptionSettings(): void {\n this.panel.innerHTML = '';\n this.panel.appendChild(\n this.backRow(this.labels.captionSettings, () => {\n this.currentPanel = 'captions';\n this.renderCaptions();\n })\n );\n const appearance = this.captionAppearance;\n if (!appearance) return;\n const dot = (color: string | undefined): string =>\n color\n ? `<span class=\"hp:inline-block hp:w-3 hp:h-3 hp:rounded-full hp:border hp:border-on-surface/30\" style=\"background:${color}\"></span>`\n : '';\n this.panel.appendChild(\n this.row(appearance.sizeLabel, appearance.getSizeOptions().find((o) => o.active)?.label ?? '', () => {\n this.currentPanel = 'captions-size';\n this.renderCaptionsSize();\n })\n );\n this.panel.appendChild(\n this.row(appearance.bgColorLabel, dot(appearance.getBgColorOptions().find((o) => o.active)?.value), () => {\n this.currentPanel = 'captions-bg';\n this.renderCaptionColorPanel('bg');\n })\n );\n this.panel.appendChild(\n this.row(appearance.textColorLabel, dot(appearance.getTextColorOptions().find((o) => o.active)?.value), () => {\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 private backToCaptionSettings = (): void => {\n this.currentPanel = 'captions-settings';\n this.renderCaptionSettings();\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.backToCaptionSettings));\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.backToCaptionSettings));\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","/** `delta` saniye sar; videonun başını/sonunu aşmaz, canlı yayında (duration Infinity) seekable aralıkta kalır. */\nexport function seekBy(video: HTMLVideoElement, delta: number): void {\n const start = video.seekable.length ? video.seekable.start(0) : 0;\n const end = Number.isFinite(video.duration)\n ? video.duration\n : video.seekable.length\n ? video.seekable.end(video.seekable.length - 1)\n : video.currentTime;\n video.currentTime = Math.max(start, Math.min(end, video.currentTime + delta));\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 { seekBy } from '../utils/seek-by';\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/** Bundan kısa beklemelerde (ms) yükleme halkası hiç görünmez — kısa takılmalarda yanıp sönmesin. */\nconst LOADING_RING_DELAY_MS = 150;\n\n/** Sarma butonu: yuvarlak ok ikonu + ortasında süre. */\nconst LOADING_START_EVENTS = ['waiting', 'seeking'] as const;\nconst LOADING_END_EVENTS = ['playing', 'canplay', 'canplaythrough', 'seeked', 'pause', 'error', 'emptied'] as const;\n\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 /** hls.js'in hedef canlı konumu (canlı ucun ~3 segment gerisi) — rozet \"geride\" kararı ve \"canlıya dön\" için. */\n liveSyncPosition?(): number | null;\n /**\n * Oynat/duraklat butonu ve klavyeden önce sorulur — true dönerse tıklama orada işlenmiştir.\n * Preroll beklenirken basılan \"duraklat\" beklemeyi iptal eder (video zaten duraklatılmış durumda).\n */\n interceptTogglePlay?(): boolean;\n /** Yükleme halkası (medya takılması ya da preroll beklemesi) açıldı / kapandı — kontroller bu sırada gizlenmesin. */\n onLoadingChange?(loading: boolean): void;\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 private readonly leftGroup: HTMLDivElement;\n private loadingTimer: ReturnType<typeof setTimeout> | null = null;\n /** Halkayı açık tutan sebepler: 'media' (buffer bekleniyor) ve player'ın verdikleri (ör. 'preroll'). */\n private readonly loadingReasons = new Set<string>();\n /** Preroll beklenirken video duraklatılmış olsa da kullanıcı oynatmak istedi — buton \"duraklat\" görünür. */\n private pendingPlay = false;\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 /** Reklam sırasında süre etiketinin yerinde: \"Reklam 2/3 · 0:12\". */\n private readonly adInfoEl: HTMLSpanElement;\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 /** Ses modu: tam ekran / PiP yok — dar düzende tam ekran kutusu da boş kalmasın. */\n private audioMode = 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-group-left 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 this.leftGroup = leftGroup;\n\n // Yükleme halkası: medya beklenirken grubun kenarında dolaşan ışık (tailwind.css `.hp-loading-ring`).\n const ring = document.createElement('span');\n ring.className = 'hp-loading-ring';\n ring.setAttribute('aria-hidden', 'true');\n // Dış katman parıltı (filter), iç katman kenara kırpan maske — filter maskeden önce uygulandığı için ayrı.\n const ringMask = document.createElement('span');\n ringMask.className = 'hp-loading-ring-mask';\n ringMask.appendChild(document.createElement('span'));\n ring.appendChild(ringMask);\n leftGroup.appendChild(ring);\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 this.adInfoEl = document.createElement('span');\n this.adInfoEl.setAttribute('part', 'ad-countdown');\n this.adInfoEl.className = 'hp:text-xs hp:text-on-surface hp:tabular-nums hp:whitespace-nowrap hp:px-1 hp:select-none';\n this.adInfoEl.setAttribute('aria-live', 'off');\n this.adInfoEl.style.display = 'none';\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 // Süre etiketi / canlı rozetinden sonra (reklam sırasında ikisi de gizli, gösterge onların yerinde görünür).\n leftGroup.appendChild(this.adInfoEl);\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 // Kaynak değişince süre NaN'a döner ama durationchange gelmez — önceki videonun \"0:00 / 0:15\"u kalmasın.\n video.addEventListener('emptied', this.renderTime);\n for (const ev of LOADING_START_EVENTS) video.addEventListener(ev, this.onLoadingStart);\n for (const ev of LOADING_END_EVENTS) video.addEventListener(ev, this.onLoadingEnd);\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 || this.audioMode ? '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 /** Ses modu: görüntü olmadığı için tam ekran ve PiP butonları gizlenir. */\n setAudioMode(on: boolean): void {\n this.audioMode = on;\n this.fullscreenButton.style.display = on ? 'none' : '';\n if (this.compact) this.fullscreenSlot.style.display = on || this.adMode ? 'none' : 'flex';\n this.pipButton.style.display = on || !document.pictureInPictureEnabled ? 'none' : '';\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 seekBy(this.video, 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 || this.audioMode ? '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 if (!active) this.setAdInfo(null);\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 /**\n * Reklam geri sayımı + pod göstergesi (\"Reklam 2/3 · 0:12\"). `null` → gizle. Pod tek reklamsa yalnızca \"Reklam · 0:12\";\n * kalan süre bilinmiyorsa (bazı VPAID reklamları) yalnızca etiket.\n */\n setAdInfo(info: { remaining: number; position: number; total: number } | null): void {\n if (!info || !this.adMode) {\n this.adInfoEl.style.display = 'none';\n this.adInfoEl.textContent = '';\n return;\n }\n const pod = info.total > 1 ? ` ${info.position}/${info.total}` : '';\n const time = info.remaining >= 0 ? ` · ${formatTime(Math.ceil(info.remaining))}` : '';\n this.adInfoEl.textContent = `${this.labels.adLabel}${pod}${time}`;\n this.adInfoEl.style.display = '';\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.interceptTogglePlay?.()) {\n this.renderPlayState();\n return;\n }\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 /** Preroll beklemesi: video duraklatılmış ama oynatma istendi — buton \"duraklat\" görünsün. */\n setPendingPlay(pending: boolean): void {\n this.pendingPlay = pending;\n this.renderPlayState();\n }\n\n /** Player'ın kendi bekleme durumları (ör. 'preroll') için yükleme halkası — medya takılmasından bağımsız. */\n setLoading(reason: string, on: boolean): void {\n if (on) this.loadingReasons.add(reason);\n else this.loadingReasons.delete(reason);\n this.renderLoading();\n }\n\n get isLoading(): boolean {\n return this.loadingReasons.size > 0;\n }\n\n private renderLoading(): void {\n const loading = this.loadingReasons.size > 0;\n if (loading === this.leftGroup.hasAttribute('data-loading')) return;\n this.leftGroup.toggleAttribute('data-loading', loading);\n this.callbacks.onLoadingChange?.(loading);\n }\n\n private readonly renderPlayState = (): void => {\n const paused = this.callbacks.isAdActive() ? this.callbacks.adIsPaused() : this.video.paused && !this.pendingPlay;\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ı konumdan LIVE_EDGE_TOLERANCE_SEC'ten fazla gerideyse \"geride\" (gri nokta, tıklanınca uca döner). hls.js\n // yayını bilerek uçtan ~3 segment geride oynatır — ölçü onun hedef konumu, yoksa seekable sonu.\n const target = this.callbacks.liveSyncPosition?.() ?? this.liveEdge();\n const behind = target !== null && target - this.video.currentTime > LIVE_EDGE_TOLERANCE_SEC;\n this.liveBadge.toggleAttribute('data-behind', behind);\n };\n\n /** Buffer bekleniyor (oynarken takılma ya da buffer'lanmamış bir yere atlama). */\n private readonly onLoadingStart = (e: Event): void => {\n // Buffer'lı bir yere atlarken (veri hazır) halka gösterilmez.\n if (e.type === 'seeking' && this.video.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA) return;\n if (this.loadingTimer || this.loadingReasons.has('media')) return;\n this.loadingTimer = setTimeout(() => {\n this.loadingTimer = null;\n this.setLoading('media', true);\n }, LOADING_RING_DELAY_MS);\n };\n\n private readonly onLoadingEnd = (e: Event): void => {\n // seeked geldiğinde veri hâlâ yoksa bekleme sürüyor (waiting/canplay kararı verir).\n if (e.type === 'seeked' && this.video.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !this.video.paused) return;\n if (this.loadingTimer) clearTimeout(this.loadingTimer);\n this.loadingTimer = null;\n this.setLoading('media', false);\n };\n\n private readonly goToLive = (): void => {\n const sync = this.callbacks.liveSyncPosition?.();\n const edge = this.liveEdge();\n if (edge === null && sync == null) return;\n // hls.js'in hedef canlı konumu; yoksa tam uca değil biraz gerisine — en sona seek edince oynatma takılabiliyor.\n this.video.currentTime = sync ?? 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.video.removeEventListener('emptied', this.renderTime);\n for (const ev of LOADING_START_EVENTS) this.video.removeEventListener(ev, this.onLoadingStart);\n for (const ev of LOADING_END_EVENTS) this.video.removeEventListener(ev, this.onLoadingEnd);\n if (this.loadingTimer) clearTimeout(this.loadingTimer);\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 /** Space/K'den önce sorulur — true dönerse işlenmiştir (ör. preroll beklemesini iptal). */\n interceptTogglePlay: (() => boolean) | 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.interceptTogglePlay?.()) {\n e.preventDefault();\n break;\n }\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.dismiss();\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 /**\n * hls.js'in ölümcül hataları `video.error` üretmez — player donmuş görünmesin diye ekran elle açılır.\n * `code`: MediaError kodu (2 = ağ, 3 = çözümleme).\n */\n showStreamError(code: 2 | 3): void {\n if (!this.shouldShow()) return;\n this.streamErrorCode = code;\n this.render();\n this.el.setAttribute('data-visible', '');\n }\n\n /** Yeni kaynak yüklenirken önceki hatayı kapat. */\n dismiss(): void {\n this.streamErrorCode = 0;\n this.hide();\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 /** showStreamError ile açılan hatanın kodu (video.error yokken). */\n private streamErrorCode = 0;\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 ?? this.streamErrorCode;\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';\r\n\r\nexport interface AttachedTrack {\r\n label: string;\r\n track: TextTrack;\r\n}\r\n\r\ninterface ParsedCue {\r\n start: number;\r\n end: number;\r\n settings: string;\r\n text: string;\r\n}\r\n\r\n/** Havuz kapsamı: `options.subtitles` izleri ile yayının (HLS manifest / CEA-608) izleri birbirini temizlemesin. */\r\nexport type TrackScope = 'options' | 'stream';\r\n\r\n/** addTextTrack ile eklenen izler kaldırılamıyor — video başına havuz; aynı kapsam+tür+label+dil tekrar kullanılır. */\r\nconst pools = new WeakMap<HTMLVideoElement, Map<string, TextTrack>>();\r\n/** Bizim oluşturduğumuz izler — tarayıcının kendi (native HLS in-band) izlerinden ayırmak için. */\r\nconst ownTracks = new WeakSet<TextTrack>();\r\n/** Her attach'te artar — önceki kaynağın geç gelen fetch'i yeni izlere cue eklemesin. */\r\nconst generations = new WeakMap<HTMLVideoElement, number>();\r\n\r\nexport function isPooledTrack(track: TextTrack): boolean {\r\n return ownTracks.has(track);\r\n}\r\n\r\n/** Havuzdan iz al (yoksa oluştur) — kapalı ve boş döner. */\r\nexport function pooledTrack(video: HTMLVideoElement, scope: TrackScope, kind: TextTrackKind, label: string, lang: string): TextTrack {\r\n let pool = pools.get(video);\r\n if (!pool) pools.set(video, (pool = new Map()));\r\n const key = `${scope}\u0000${kind}\u0000${label}\u0000${lang}`;\r\n let track = pool.get(key);\r\n if (!track) {\r\n track = video.addTextTrack(kind, label, lang);\r\n ownTracks.add(track);\r\n pool.set(key, track);\r\n }\r\n return track;\r\n}\r\n\r\n/** Bir kapsamdaki tüm havuz izlerini kapatıp boşaltır. */\r\nexport function clearPooledTracks(video: HTMLVideoElement, scope: TrackScope): void {\r\n for (const [key, track] of pools.get(video) ?? []) {\r\n if (!key.startsWith(`${scope}\u0000`)) continue;\r\n // Kapalı izde track.cues null döner — boşaltmak için geçici olarak hidden.\r\n track.mode = 'hidden';\r\n for (const cue of Array.from(track.cues ?? [])) track.removeCue(cue);\r\n track.mode = 'disabled';\r\n }\r\n}\r\n\r\n/**\r\n * Altyazıları <track> elementi yerine VTT'yi kendimiz indirip addTextTrack + VTTCue ile ekliyoruz.\r\n * iOS WebKit <track>'leri \"out-of-band\" iz olarak AVFoundation'a veriyor ve bu, geçerli bir VTT'de bile\r\n * videonun tamamını MEDIA_ERR_SRC_NOT_SUPPORTED (kod 4) ile düşürebiliyor. Mode 'hidden' — cue'lar akar\r\n * ama tarayıcı çizmez (CaptionRenderer çizer).\r\n */\r\nexport function attachSubtitleTracks(video: HTMLVideoElement, subtitles: HopeSubtitleOption[]): AttachedTrack[] {\r\n clearSubtitleTracks(video);\r\n const generation = generations.get(video)!;\r\n const attached: AttachedTrack[] = [];\r\n for (const sub of subtitles) {\r\n const track = pooledTrack(video, 'options', 'subtitles', sub.label, sub.srclang);\r\n track.mode = sub.default ? 'hidden' : 'disabled';\r\n attached.push({ label: sub.label, track });\r\n void loadCues(video, track, sub.src, generation);\r\n }\r\n return attached;\r\n}\r\n\r\n/** `options.subtitles` izlerini kapatıp boşaltır (altyazısız kaynağa geçiş). */\r\nexport function clearSubtitleTracks(video: HTMLVideoElement): void {\r\n generations.set(video, (generations.get(video) ?? 0) + 1);\r\n clearPooledTracks(video, 'options');\r\n}\r\n\r\n/** Yalnızca seçilen track'i 'hidden' yapar, diğerlerini kapatır (null = hepsini kapat). */\r\nexport function selectSubtitleTrack(tracks: AttachedTrack[], label: string | null): TextTrack | null {\r\n let active: TextTrack | null = null;\r\n for (const { label: trackLabel, track } of tracks) {\r\n const isActive = trackLabel === label;\r\n track.mode = isActive ? 'hidden' : 'disabled';\r\n if (isActive) active = track;\r\n }\r\n return active;\r\n}\r\n\r\nasync function loadCues(video: HTMLVideoElement, track: TextTrack, src: string, generation: number): Promise<void> {\r\n let text: string;\r\n try {\r\n const res = await fetch(src);\r\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\r\n text = await res.text();\r\n } catch (err) {\r\n console.warn('[HopePlayer] altyazı yüklenemedi:', src, err);\r\n // Player'ın hata kaydına (hata ayıklama penceresi) — video shadow DOM içinde, olay dışarı sızmaz.\r\n video.dispatchEvent(new CustomEvent('hp-internal:subtitle-error', { detail: { src, message: String(err) } }));\r\n return;\r\n }\r\n if (generations.get(video) !== generation || typeof VTTCue !== 'function') return;\r\n for (const c of parseVttCues(text)) {\r\n const cue = new VTTCue(c.start, c.end, c.text);\r\n applyCueSettings(cue, c.settings);\r\n track.addCue(cue);\r\n }\r\n}\r\n\r\nconst TIMESTAMP = '(?:\\\\d+:)?\\\\d{1,2}:\\\\d{2}(?:[.,]\\\\d{1,3})?';\r\nconst TIMING_LINE = new RegExp(`^(${TIMESTAMP})\\\\s+-->\\\\s+(${TIMESTAMP})(.*)$`);\r\n\r\nfunction toSeconds(value: string): number {\r\n return value\r\n .replace(',', '.')\r\n .split(':')\r\n .reduce((acc, part) => acc * 60 + Number(part), 0);\r\n}\r\n\r\n/** WebVTT gövdesinden cue'ları çıkarır — NOTE/STYLE/REGION blokları zamanlama satırı içermediği için atlanır. */\r\nexport function parseVttCues(text: string): ParsedCue[] {\r\n const cues: ParsedCue[] = [];\r\n const blocks = text.replace(/^/, '').replace(/\\r\\n?/g, '\\n').split(/\\n{2,}/);\r\n for (const block of blocks) {\r\n const lines = block.split('\\n');\r\n const timingIndex = lines.findIndex((l) => l.includes('-->'));\r\n if (timingIndex < 0) continue;\r\n const m = TIMING_LINE.exec(lines[timingIndex]!.trim());\r\n if (!m) continue;\r\n const body = lines.slice(timingIndex + 1).join('\\n');\r\n if (!body.trim()) continue;\r\n cues.push({ start: toSeconds(m[1]!), end: toSeconds(m[2]!), settings: m[3]!.trim(), text: body });\r\n }\r\n return cues;\r\n}\r\n\r\n/** \"line:-2 position:50% align:center\" gibi cue ayarları — geçersiz değerleri tarayıcı reddeder, yok sayıyoruz. */\r\nfunction applyCueSettings(cue: VTTCue, settings: string): void {\r\n for (const token of settings.split(/\\s+/)) {\r\n const [key, raw] = token.split(':');\r\n if (!key || !raw) continue;\r\n const [value] = raw.split(',');\r\n try {\r\n if (key === 'align') cue.align = value as AlignSetting;\r\n else if (key === 'vertical') cue.vertical = value as DirectionSetting;\r\n else if (key === 'size') cue.size = parseFloat(value!);\r\n else if (key === 'position') cue.position = parseFloat(value!);\r\n else if (key === 'line') {\r\n cue.snapToLines = !value!.endsWith('%');\r\n cue.line = parseFloat(value!);\r\n }\r\n } catch {\r\n // Desteklenmeyen ayar — cue ayarsız gösterilir.\r\n }\r\n }\r\n}\r\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 /**\n * Balonun EKRANDA şu an durduğu konum (bottom, px): yazılı `bottom` + o anki transform'un dikey kayması.\n * Sürükleme her karede bir kez çiziliyor — hızlı fırlatmada son hareket çizilmeden bırakılınca, son fare konumundan\n * başlayan animasyon balonu önce oraya ışınlıyordu (zıplama). Süren bir kayma animasyonunun ortası da böyle okunur.\n */\n private visualBottomPx(): number {\n const bottom = parseFloat(this.bubbleEl.style.bottom || '0');\n try {\n const transform = getComputedStyle(this.bubbleEl).transform;\n if (!transform || transform === 'none') return bottom;\n // translateY pozitif = aşağı = daha küçük bottom.\n return bottom - new DOMMatrixReadOnly(transform).m42;\n } catch {\n return bottom;\n }\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): void {\n this.rowIndex = Math.min(ROWS - 1, Math.max(0, rowIndex));\n const targetPx = this.pxForRow(this.rowIndex);\n const prevPx = this.visualBottomPx();\n\n if (animate && Math.abs(prevPx - targetPx) > 0.5) {\n this.bubbleEl.classList.add('hp-caption-no-transition');\n this.bubbleEl.style.bottom = `${targetPx}px`;\n // bottom azalınca balon aşağı iner — eski yerinde görünmesi için o kadar YUKARI (negatif Y) kaydırılır.\n // (İşaret ters olunca balon önce iki kat aşağı sıçrayıp sonra geri kayıyordu.)\n this.bubbleEl.style.transform = `translateX(-50%) translateY(${targetPx - prevPx}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 // Anında konumlanma da geçişsiz yazılır: sürükleme bitince transition yeniden açık — transform'u sıfırlamak\n // 240 ms'lik bir kaymaya dönüşüyor, balon (bottom zaten yeni yerindeyken) önce ters yöne fırlıyordu.\n this.bubbleEl.classList.add('hp-caption-no-transition');\n this.bubbleEl.style.transform = 'translateX(-50%)';\n this.bubbleEl.style.bottom = `${targetPx}px`;\n void this.bubbleEl.offsetHeight;\n this.bubbleEl.classList.remove('hp-caption-no-transition');\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 // Sınıfı kaldırmak transform'u değiştirmez — animasyon yine balonun ekrandaki yerinden başlar (bkz. visualBottomPx).\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);\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","export interface ContextMenuItem {\n label: string;\n /** Sağda soluk yazı (ör. sürüm). */\n meta?: string;\n /** Verilmezse satır yalnızca bilgi (tıklanmaz). */\n onSelect?: () => void;\n}\n\n/** Player'a sağ tıklayınca açılan menü — tarayıcının kendi menüsünün yerine (options.contextMenu). */\nexport class ContextMenu {\n readonly el: HTMLDivElement;\n private open = false;\n\n constructor(private readonly container: HTMLElement) {\n this.el = document.createElement('div');\n this.el.className = 'hp-context-menu';\n this.el.setAttribute('part', 'context-menu');\n this.el.setAttribute('role', 'menu');\n // Menünün kendi içindeki sağ tık da tarayıcı menüsünü açmasın.\n this.el.addEventListener('contextmenu', (e) => e.preventDefault());\n container.appendChild(this.el);\n }\n\n get isOpen(): boolean {\n return this.open;\n }\n\n /** `clientX/Y` ekran koordinatı — menü player'ın içinde kalacak şekilde kaydırılır. */\n show(clientX: number, clientY: number, items: ContextMenuItem[]): void {\n this.el.replaceChildren(\n ...items.map((item) => {\n const row = document.createElement(item.onSelect ? 'button' : 'div');\n row.className = 'hp-context-menu-item';\n if (item.onSelect) {\n (row as HTMLButtonElement).type = 'button';\n row.setAttribute('role', 'menuitem');\n row.addEventListener('click', () => {\n this.close();\n item.onSelect!();\n });\n } else {\n row.setAttribute('data-info', '');\n }\n const label = document.createElement('span');\n label.textContent = item.label;\n row.appendChild(label);\n if (item.meta) {\n const meta = document.createElement('span');\n meta.className = 'hp-context-menu-meta';\n meta.textContent = item.meta;\n row.appendChild(meta);\n }\n return row;\n })\n );\n this.el.setAttribute('data-open', '');\n this.open = true;\n\n const area = this.container.getBoundingClientRect();\n const { width, height } = this.el.getBoundingClientRect();\n const x = Math.max(4, Math.min(clientX - area.left, area.width - width - 4));\n const y = Math.max(4, Math.min(clientY - area.top, area.height - height - 4));\n this.el.style.left = `${x}px`;\n this.el.style.top = `${y}px`;\n this.el.querySelector<HTMLButtonElement>('button')?.focus({ preventScroll: true });\n\n document.addEventListener('pointerdown', this.onOutside, true);\n document.addEventListener('keydown', this.onKeyDown, true);\n window.addEventListener('blur', this.close);\n window.addEventListener('resize', this.close);\n window.addEventListener('scroll', this.close, true);\n }\n\n readonly close = (): void => {\n if (!this.open) return;\n this.open = false;\n this.el.removeAttribute('data-open');\n document.removeEventListener('pointerdown', this.onOutside, true);\n document.removeEventListener('keydown', this.onKeyDown, true);\n window.removeEventListener('blur', this.close);\n window.removeEventListener('resize', this.close);\n window.removeEventListener('scroll', this.close, true);\n };\n\n private readonly onOutside = (e: PointerEvent): void => {\n if (!e.composedPath().includes(this.el)) this.close();\n };\n\n private readonly onKeyDown = (e: KeyboardEvent): void => {\n if (e.key !== 'Escape') return;\n e.stopPropagation();\n this.close();\n };\n\n destroy(): void {\n this.close();\n this.el.remove();\n }\n}\n","/** Hata kaydının kaynağı — hata ayıklama ekranında etiket olarak görünür. */\nexport type PlayerLogSource = 'media' | 'stream' | 'ads' | 'subtitles' | 'player';\n\nexport interface PlayerLogEntry {\n /** `Date.now()` */\n time: number;\n source: PlayerLogSource;\n message: string;\n /** Oynatmayı durduran (kurtarılamayan) hata. */\n fatal?: boolean;\n /** Teknik ayrıntılar (hata kodu, URL, HTTP durumu…) — tanımsız değerler gösterilmez. */\n details?: Record<string, string | number | boolean | undefined>;\n /** Aynı hata kısa sürede tekrarlandıysa kaç kez (ör. hls.js buffer takılması) — tek satırda \"×3\". */\n count?: number;\n}\n\n/** Bu süre içinde tekrarlanan aynı hata yeni satır açmaz, sayacı artar. */\nconst REPEAT_WINDOW_MS = 3000;\n\nconst MAX_ENTRIES = 200;\n\n/**\n * Player'ın tüm hatalarının (medya, yayın/hls.js, reklam, altyazı) anlık kaydı. Her zaman tutulur (birkaç yüz bayt);\n * hata ayıklama ekranı ve sağ tık menüsündeki giriş yalnızca `options.debug` açıkken görünür.\n */\nexport class ErrorLog {\n private readonly list: PlayerLogEntry[] = [];\n /** Kayıt eklenince / temizlenince (açık panel canlı güncellenir). */\n onChange: (() => void) | null = null;\n\n get entries(): readonly PlayerLogEntry[] {\n return this.list;\n }\n\n add(entry: Omit<PlayerLogEntry, 'time' | 'count'>): void {\n const now = Date.now();\n const last = this.list[this.list.length - 1];\n if (\n last &&\n now - last.time < REPEAT_WINDOW_MS &&\n last.source === entry.source &&\n last.message === entry.message &&\n JSON.stringify(last.details ?? {}) === JSON.stringify(entry.details ?? {})\n ) {\n last.count = (last.count ?? 1) + 1;\n last.time = now;\n this.onChange?.();\n return;\n }\n this.list.push({ time: now, ...entry });\n if (this.list.length > MAX_ENTRIES) this.list.splice(0, this.list.length - MAX_ENTRIES);\n this.onChange?.();\n }\n\n clear(): void {\n this.list.length = 0;\n this.onChange?.();\n }\n\n /** Destek ekibine yapıştırılabilir düz metin. */\n toText(): string {\n return this.list\n .map((e) => {\n const details = Object.entries(e.details ?? {})\n .filter(([, v]) => v !== undefined && v !== '')\n .map(([k, v]) => `${k}=${v}`)\n .join(' ');\n const repeat = e.count && e.count > 1 ? ` (x${e.count})` : '';\n return `${new Date(e.time).toISOString()} [${e.source}]${e.fatal ? ' [fatal]' : ''} ${e.message}${repeat}${details ? ` | ${details}` : ''}`;\n })\n .join('\\n');\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 audioTrack: 'Ses',\n statsTitle: 'İstatistikler',\n statsClose: 'İstatistikleri kapat',\n statsEngine: 'Motor',\n statsResolution: 'Video / ekran',\n statsQuality: 'Kalite',\n statsCodecs: 'Codec',\n statsBandwidth: 'Bant genişliği',\n statsBuffer: 'Buffer (ileri)',\n statsDropped: 'Düşen kare',\n statsLatency: 'Canlı gecikme',\n statsSpeedVolume: 'Hız / ses',\n statsSource: 'Kaynak',\n statsVersion: 'Sürüm',\n debugTitle: 'Hata ayıklama',\n debugClose: 'Hata ayıklamayı kapat',\n debugCopy: 'Kopyala',\n debugCopied: 'Kopyalandı',\n debugClear: 'Temizle',\n debugEmpty: 'Kayıtlı hata yok.',\n debugFatal: 'Oynatmayı durdurdu',\n debugSourceMedia: 'Medya',\n debugSourceStream: 'Yayın',\n debugSourceAds: 'Reklam',\n debugSourceSubtitles: 'Altyazı',\n debugSourcePlayer: 'Player',\n adLabel: 'Reklam',\n adReturnFullscreen: 'Tam ekrana dön',\n adReturnPip: 'Küçük pencereye dön',\n audioVinyl: 'Plak — ileri / geri sarmak için çevirin',\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 captionSettings: 'Altyazı ayarları',\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 audioTrack: 'Audio',\n statsTitle: 'Stats',\n statsClose: 'Close stats',\n statsEngine: 'Engine',\n statsResolution: 'Video / viewport',\n statsQuality: 'Quality',\n statsCodecs: 'Codecs',\n statsBandwidth: 'Bandwidth',\n statsBuffer: 'Buffer (ahead)',\n statsDropped: 'Dropped frames',\n statsLatency: 'Live latency',\n statsSpeedVolume: 'Speed / volume',\n statsSource: 'Source',\n statsVersion: 'Version',\n debugTitle: 'Debug log',\n debugClose: 'Close debug log',\n debugCopy: 'Copy',\n debugCopied: 'Copied',\n debugClear: 'Clear',\n debugEmpty: 'No errors logged.',\n debugFatal: 'Stopped playback',\n debugSourceMedia: 'Media',\n debugSourceStream: 'Stream',\n debugSourceAds: 'Ads',\n debugSourceSubtitles: 'Subtitles',\n debugSourcePlayer: 'Player',\n adLabel: 'Ad',\n adReturnFullscreen: 'Back to full screen',\n adReturnPip: 'Back to picture-in-picture',\n audioVinyl: 'Record — turn it to scrub',\n fullscreenEnter: 'Fullscreen',\n fullscreenExit: 'Exit fullscreen',\n playbackSpeed: 'Playback speed',\n normal: 'Normal',\n quality: 'Quality',\n captions: 'Captions',\n captionsOff: 'Off',\n captionSettings: 'Subtitle settings',\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 type { AdsOptions } from '../../types';\n\n/** Preroll beklenirken içeriğin en fazla ne kadar bekletileceği — sonra reklamsız başlar. */\nexport const DEFAULT_PREROLL_TIMEOUT_MS = 8000;\n\n/** Bu reklam ayarlarıyla içerik başlamadan önce bir preroll bekleniyor mu (VMAP'in 0 noktası da olabilir). */\nexport function expectsPreroll(ads: AdsOptions): boolean {\n if (ads.live?.scte35 && !ads.adTagPreroll && !ads.adTagVmap) return false;\n return !!(ads.adTagPreroll || ads.adTagVmap);\n}\n\n/**\n * Preroll kapısı: preroll sonuçlanana kadar (reklam başladı / gelmedi / hata / zaman aşımı) içeriğin oynamasını\n * engeller — içerik 1-2 sn oynayıp reklamla kesilmesin, ilk karesini reklamdan SONRA göstersin.\n *\n * Elementin constructor'ında, video'nun diğer tüm 'play'/'pause' dinleyicilerinden ÖNCE kurulur: kapı açıkken gelen\n * 'play' olayını yutar (UI, hp:play ve IMA görmez), videoyu hemen duraklatır ve bunu \"oynatma isteği\" olarak saklar.\n * Reklam plugin'i daha sonra dinamik yüklendiği için kapı plugin'den bağımsız, çekirdekte yaşar.\n */\nexport class PrerollGate {\n /** Kapı kurulu (preroll bekleniyor) mu. */\n private armed = false;\n /** Kapı kuruluyken kullanıcı / autoplay oynatmak istedi mi. */\n private playIntent = false;\n /** Kapının kendi pause() çağrısının ürettiği 'pause' olayı yutulsun. */\n private swallowNextPause = false;\n private timeoutMs = DEFAULT_PREROLL_TIMEOUT_MS;\n private timer: ReturnType<typeof setTimeout> | null = null;\n\n /** İlk oynatma isteği (reklam plugin'i bekleyen preroll'u başlatır). */\n onPlayIntent: (() => void) | null = null;\n /** Zaman aşımı — reklam plugin'i geç gelecek cevabı iptal eder. Kapı bundan sonra içeriği başlatarak açılır. */\n onTimeout: (() => void) | null = null;\n /** \"Preroll bekleniyor\" durumu değişti (UI: yükleme halkası, merkez buton). */\n onWaitChange: ((waiting: boolean) => void) | null = null;\n\n constructor(private readonly video: HTMLVideoElement) {\n video.addEventListener('play', this.onPlay);\n video.addEventListener('pause', this.onPause);\n }\n\n get isArmed(): boolean {\n return this.armed;\n }\n\n /** Kapı kurulu ve oynatma istendi — kullanıcı preroll'u bekliyor. */\n get isWaiting(): boolean {\n return this.armed && this.playIntent;\n }\n\n get hasPlayIntent(): boolean {\n return this.playIntent;\n }\n\n arm(timeoutMs = DEFAULT_PREROLL_TIMEOUT_MS): void {\n this.clearTimer();\n this.armed = true;\n this.playIntent = false;\n this.timeoutMs = timeoutMs;\n }\n\n /**\n * Elementin `play()`'i için: kapı kuruluysa videoya dokunmadan oynatma isteği kaydedilir (play() promise'i\n * pause() ile reddedilip konsola \"interrupted by a call to pause()\" düşmesin). true → istek kapıda.\n */\n interceptPlay(): boolean {\n if (!this.armed) return false;\n this.registerIntent();\n return true;\n }\n\n /** Bekleme sırasında kullanıcı vazgeçti (duraklat'a bastı). Kapı kurulu kalır; preroll geri döner ama başlatılmaz. */\n cancelIntent(): void {\n if (!this.isWaiting) return;\n this.playIntent = false;\n this.clearTimer();\n this.onWaitChange?.(false);\n }\n\n /** Preroll sonuçlandı. `resume`: oynatma istenmişse içerik şimdi başlasın (reklam yok / hata / zaman aşımı). */\n release(resume: boolean): void {\n if (!this.armed) return;\n const wanted = this.playIntent;\n this.armed = false;\n this.playIntent = false;\n this.clearTimer();\n if (wanted) this.onWaitChange?.(false);\n if (resume && wanted) this.video.play().catch(() => {});\n }\n\n destroy(): void {\n this.clearTimer();\n this.video.removeEventListener('play', this.onPlay);\n this.video.removeEventListener('pause', this.onPause);\n }\n\n private registerIntent(): void {\n if (this.playIntent) return;\n this.playIntent = true;\n this.onWaitChange?.(true);\n this.timer = setTimeout(() => {\n this.timer = null;\n this.onTimeout?.();\n this.release(true);\n }, this.timeoutMs);\n this.onPlayIntent?.();\n }\n\n private readonly onPlay = (e: Event): void => {\n if (!this.armed) return;\n e.stopImmediatePropagation();\n this.swallowNextPause = true;\n this.video.pause();\n this.registerIntent();\n };\n\n private readonly onPause = (e: Event): void => {\n if (!this.swallowNextPause) return;\n this.swallowNextPause = false;\n e.stopImmediatePropagation();\n };\n\n private clearTimer(): void {\n if (this.timer) clearTimeout(this.timer);\n this.timer = null;\n }\n}\n","/**\n * IMA SDK'nın ve reklam isteklerinin gittiği sunuculara bağlantıyı önceden açar (DNS + TCP + TLS). Reklam plugin'i\n * dinamik yüklenip ima3.js'i isteyene kadar geçen sürede bağlantılar hazır olur — preroll beklemesi kısalır.\n * Sayfa başına bir kez; çekirdekte (plugin chunk'ı beklenmeden) çağrılır.\n */\nconst AD_HOSTS = [\n 'https://imasdk.googleapis.com',\n 'https://pubads.g.doubleclick.net',\n 'https://securepubads.g.doubleclick.net',\n 'https://pagead2.googlesyndication.com',\n];\n\nlet done = false;\n\nexport function preconnectAdHosts(): void {\n if (done || typeof document === 'undefined') return;\n done = true;\n for (const href of AD_HOSTS) {\n if (document.head.querySelector(`link[rel=\"preconnect\"][href=\"${href}\"]`)) continue;\n const link = document.createElement('link');\n link.rel = 'preconnect';\n link.href = href;\n document.head.appendChild(link);\n }\n}\n","import tailwindCss from './theme/tailwind.css?inline';\nimport type { AdsOptions, HopePlayerOptions } from './types';\nimport type Hls from 'hls.js';\nimport { SourceManager, type HlsQualityLevel, type PlaybackEngineInfo, type StreamAudioTrack, type StreamTextTrack } 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 {\n attachSubtitleTracks,\n clearPooledTracks,\n clearSubtitleTracks,\n isPooledTrack,\n pooledTrack,\n selectSubtitleTrack,\n type AttachedTrack,\n} from './subtitles/attachTracks';\nimport { CaptionRenderer, type CaptionFontSize } from './subtitles/CaptionRenderer';\nimport { MiniProgress } from './controls/MiniProgress';\nimport { SeekFeedback } from './controls/SeekFeedback';\nimport { ContextMenu } from './controls/ContextMenu';\nimport { seekBy } from './utils/seek-by';\nimport type { TapGestures } from './plugins/tap-gestures';\nimport type { StatsPanel } from './plugins/stats';\nimport type { DebugPanel } from './plugins/debug';\nimport { ErrorLog } from './debug/ErrorLog';\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 { AudioStage } from './plugins/audio';\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 { PrerollGate, expectsPreroll, DEFAULT_PREROLL_TIMEOUT_MS } from './plugins/ads/PrerollGate';\nimport { preconnectAdHosts } from './plugins/ads/preconnect';\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/** Dokunmayla açılan kontroller en az bu kadar (ms) açık kalır — fare süresi (1,2 sn) parmak için çok kısa. */\nconst TOUCH_AUTO_HIDE_DELAY_MS = 3000;\n/** options.cursorHideDelayMs verilmezse — fare bu kadar kıpırdamazsa imleç gizlenir. */\nconst DEFAULT_CURSOR_HIDE_DELAY_MS = 5000;\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/** Yayının alternatif ses izleri için ayarlar alt menüsü. */\nconst STREAM_AUDIO_SUBMENU_KEY = 'stream-audio';\n/** Paket sürümü — build sırasında package.json'dan gömülür. */\nexport const HOPE_PLAYER_VERSION = __HOPE_VERSION__;\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/** options.aspectRatio → CSS değeri: '21:9' / '21 / 9' → '21 / 9', 2.35 → '2.35'; geçersizse null. */\nfunction normalizeAspectRatio(value: string | number | undefined): string | null {\n if (typeof value === 'number') return Number.isFinite(value) && value > 0 ? String(value) : null;\n if (typeof value !== 'string') return null;\n const m = value.trim().match(/^(\\d+(?:\\.\\d+)?)\\s*(?:[:/]\\s*(\\d+(?:\\.\\d+)?))?$/);\n if (!m || Number(m[1]) <= 0 || (m[2] !== undefined && Number(m[2]) <= 0)) return null;\n return m[2] !== undefined ? `${m[1]} / ${m[2]}` : m[1]!;\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 /**\n * Preroll kapısı — reklam plugin'i yüklenmeden önce kurulur ki autoplay / ilk play araya kaçmasın.\n * Video'nun 'play'/'pause' dinleyicilerinin İLKİ olmalı (yuttuğu olayları UI ve hp:play görmesin).\n */\n private readonly prerollGate: PrerollGate;\n /** Ads plugin kurulumu sürüyor — erken başlatılan kurulum ile sonraki bekleme aynı promise'i paylaşır. */\n private adsInstall: Promise<void> | null = null;\n /** Yükleme halkası açık (medya takıldı / preroll bekleniyor) — kontroller bu sırada otomatik gizlenmez. */\n private loadingActive = false;\n private readonly errorScreen: ErrorScreen;\n /** İleri/geri sarmada sağda/solda beliren anlık bildirim. */\n private readonly seekFeedback: SeekFeedback;\n private readonly contextMenu: ContextMenu;\n /** options.contextMenu çözülmüş hali — null = kapalı (tarayıcının kendi menüsü). */\n private contextMenuConfig: { stats: boolean } | null = { stats: false };\n /** İlk açılışta yüklenir (plugins/stats). */\n private statsPanel: StatsPanel | null = null;\n private debugPanel: DebugPanel | null = null;\n /** options.debug — sağ tık menüsündeki \"Hata ayıklama\" girişini açar. */\n private debugEnabled = false;\n /** Player'ın tüm hataları (medya, yayın, reklam, altyazı) — her zaman tutulur; bkz. `errorLog`. */\n private readonly log = new ErrorLog();\n /** Son basılan işaretçi türü — sağ tık menüsü yalnızca fareyle (dokunmatikte uzun basma gesture'a ait). */\n private lastPointerType = 'mouse';\n /** options.tapGestures kuruluysa (plugins/tap-gestures). */\n private tapGestures: TapGestures | null = null;\n /** Dokunmadan sonra tarayıcının ürettiği uyumluluk mouse olayları ikinci bir dokunuş sayılmasın. */\n private lastTouchEndAt = 0;\n /** Video alanı boyutu değişince merkez play butonunun yerini yeniden hesaplar. */\n private centerPlayObserver: ResizeObserver | null = null;\n private tapToPlay: 'auto' | boolean = 'auto';\n private adsController: AdsController | null = null;\n private gestureControls: GestureControls | null = null;\n private loopSection: LoopSection | null = null;\n private audioStage: AudioStage | null = null;\n /** options.audio — kapak + plak sahnesi, kontroller hep görünür, tam ekran yok. */\n private audioMode = false;\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 /** `options.subtitles` izleri. */\n private optionTracks: AttachedTrack[] = [];\n /** Yayının izleri: hls.js'ten (havuzda, `sub:`/`cc:`) ya da tarayıcının native HLS in-band izleri (`native:`). */\n private streamTracks: (AttachedTrack & { id: string })[] = [];\n /** hls.js aynı cue'yu (seek sonrası) yeniden gönderebilir — iz başına eklenenler. */\n private streamCueKeys = new Map<TextTrack, Set<string>>();\n /** Seçili altyazı — yayın izleri sonradan gelince seçim korunur. */\n private activeCaptionLabel: string | null = null;\n private streamAudio: { tracks: StreamAudioTrack[]; active: number } = { tracks: [], active: -1 };\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 /**\n * Son uygulanan `.options` nesnesi + attribute'lar. `.options` element sayfaya eklenmeden önce verilince\n * connectedCallback AYNI seçenekleri yeniden uyguluyordu; değişen bir şey yoksa bu ikinci geçiş atlanır.\n */\n private lastSynced: { options: HopePlayerOptions; attrs: string } | null = null;\n /**\n * applyOptions'ın asenkron kısmı (plugin kurulumu + kaynak yükleme) aynı anda tek kez çalışır. İki geçiş\n * üst üste binince `!this.adsController` gibi kontroller ikisinde de geçiyor, plugin (ör. IMA) iki kez kuruluyordu.\n * Çalışırken gelen seçenekler bekletilir; bitince yalnızca en sonuncusu uygulanır.\n */\n private pluginApplyRun: Promise<void> | null = null;\n private pendingPluginOptions: HopePlayerOptions | null = null;\n private _options: HopePlayerOptions = {};\n private hideTimer: ReturnType<typeof setTimeout> | null = null;\n private cursorTimer: ReturnType<typeof setTimeout> | null = null;\n /** null = imleç hiç gizlenmez (options.cursorHideDelayMs: false). */\n private cursorHideDelayMs: number | null = DEFAULT_CURSOR_HIDE_DELAY_MS;\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.prerollGate = new PrerollGate(this.videoEl);\n this.prerollGate.onWaitChange = (waiting) => this.onPrerollWaitChange(waiting);\n this.videoEl.addEventListener('error', this.onMediaError);\n this.videoEl.addEventListener('hp-internal:subtitle-error', this.onSubtitleError);\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', (e) => {\n const play = (): void => {\n if (this.videoEl.paused) void this.videoEl.play();\n };\n const pointer = this.lastPointerType === 'pen' ? 'pen' : this.lastPointerType === 'touch' ? 'touch' : null;\n // Duraklatılmışken bu buton tüm alanı kaplar; yuvarlak butonun DIŞINA dokunmak \"videoya dokunmak\" sayılır.\n const onChip = e.composedPath().includes(centerChip);\n const single = onChip ? play : (): void => this.onBackgroundTap(pointer ?? 'mouse', play);\n // Dokunuşlar çift dokunma hareketlerinden (tapGestures) geçsin.\n if (pointer && this.tapGestures?.handleTap(e.clientX, pointer, single)) return;\n single();\n });\n this.videoArea.appendChild(this.centerPlayButton);\n // Kompakt düzen ControlBar'ın kendi ResizeObserver'ında değişiyor — bir kare sonra ölç.\n this.centerPlayObserver = new ResizeObserver(() => requestAnimationFrame(() => this.layoutCenterPlay()));\n this.centerPlayObserver.observe(this.videoArea);\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, {\n onLevelsChanged: this.onHlsLevelsChanged,\n onAudioTracksChanged: this.onStreamAudioTracks,\n onTextTracksFound: this.onStreamTextTracks,\n onCues: this.onStreamCues,\n onFatalError: (kind) => this.errorScreen.showStreamError(kind === 'network' ? 2 : 3),\n onStreamError: (e) =>\n this.log.add({\n source: 'stream',\n message: `${e.type}: ${e.details}`,\n fatal: e.fatal,\n details: { url: e.url, httpStatus: e.httpStatus, reason: e.reason, engine: 'hls.js' },\n }),\n });\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 liveSyncPosition: () => this.sourceManager.hlsInstance?.liveSyncPosition ?? null,\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 interceptTogglePlay: () => this.cancelPrerollWait(),\n onLoadingChange: (loading) => this.onLoadingChange(loading),\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.contextMenu = new ContextMenu(this.videoArea);\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.keyboard.interceptTogglePlay = () => this.cancelPrerollWait();\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 this.addEventListener('contextmenu', this.onContextMenu);\n this.addEventListener('pointerdown', this.onPointerTypeTrack, true);\n // Safari native HLS manifest altyazılarını kendisi textTracks'e ekler — menüye bunları da al.\n this.videoEl.textTracks.addEventListener('addtrack', this.onNativeTextTracksChanged);\n this.videoEl.textTracks.addEventListener('removetrack', this.onNativeTextTracksChanged);\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.centerPlayObserver?.disconnect();\n this.showCursor();\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.removeEventListener('contextmenu', this.onContextMenu);\n this.removeEventListener('pointerdown', this.onPointerTypeTrack, true);\n this.videoEl.textTracks.removeEventListener('addtrack', this.onNativeTextTracksChanged);\n this.videoEl.textTracks.removeEventListener('removetrack', this.onNativeTextTracksChanged);\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.contextMenu.destroy();\n this.statsPanel?.destroy();\n this.debugPanel?.destroy();\n this.videoEl.removeEventListener('error', this.onMediaError);\n this.videoEl.removeEventListener('hp-internal:subtitle-error', this.onSubtitleError);\n this.tapGestures?.destroy();\n this.sourceManager.destroy();\n this.adsController?.destroy();\n this.gestureControls?.destroy();\n this.loopSection?.destroy();\n this.audioStage?.destroy();\n this.audioStage = null;\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 this.prerollGate.release(false);\n if (this.hideTimer) clearTimeout(this.hideTimer);\n if (this.bootGraceTimer) clearTimeout(this.bootGraceTimer);\n // Tekrar sayfaya eklenirse seçenekler baştan uygulansın.\n this.lastSynced = null;\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 // Açık atama her zaman uygulanır (aynı nesne değiştirilip yeniden atanmış olabilir).\n this.lastSynced = null;\n this.syncFromAttributes();\n }\n\n play(): Promise<void> {\n // Preroll bekleniyorsa istek kapıda tutulur; reklam (ya da reklamsız içerik) kapı açılınca başlar.\n if (this.prerollGate.interceptPlay()) return Promise.resolve();\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 /** Paket sürümü (ör. \"1.0.4\"). */\n static readonly version = HOPE_PLAYER_VERSION;\n\n /** Player'ın hata kaydı (medya, yayın, reklam, altyazı) — `options.debug` kapalıyken de tutulur. */\n get errorLog(): ErrorLog {\n return this.log;\n }\n\n /** Hata ayıklama penceresini aç (sağ tık menüsündeki \"Hata ayıklama\" ile aynı). */\n async showDebugLog(): Promise<void> {\n if (!this.debugPanel) {\n const { installDebugPanel } = await import('./plugins/debug');\n this.debugPanel ??= installDebugPanel({ containerEl: this.videoArea, i18n: this.i18n, log: this.log, version: HOPE_PLAYER_VERSION });\n }\n this.debugPanel.show();\n }\n\n private readonly onMediaError = (): void => {\n const err = this.videoEl.error;\n if (!err) return;\n const names: Record<number, string> = { 1: 'MEDIA_ERR_ABORTED', 2: 'MEDIA_ERR_NETWORK', 3: 'MEDIA_ERR_DECODE', 4: 'MEDIA_ERR_SRC_NOT_SUPPORTED' };\n const src = this.videoEl.currentSrc;\n this.log.add({\n source: 'media',\n message: err.message || names[err.code] || `MediaError ${err.code}`,\n fatal: true,\n details: { code: err.code, name: names[err.code], src: src && !src.startsWith('blob:') ? src : src ? 'MediaSource (hls.js)' : undefined },\n });\n };\n\n private readonly onSubtitleError = (e: Event): void => {\n const d = (e as CustomEvent<{ src: string; message: string }>).detail;\n this.log.add({ source: 'subtitles', message: `Subtitle file could not be loaded: ${d.message}`, details: { src: d.src } });\n };\n\n /** Teknik istatistik panelini aç/kapat (`force`: true = aç, false = kapat). Sağ tık menüsündeki \"İstatistikler\" ile aynı. */\n async toggleStats(force?: boolean): Promise<void> {\n if (!this.statsPanel) {\n if (force === false) return;\n const { installStats } = await import('./plugins/stats');\n this.statsPanel ??= installStats({\n videoEl: this.videoEl,\n containerEl: this.videoArea,\n i18n: this.i18n,\n version: HOPE_PLAYER_VERSION,\n getEngine: () => this.sourceManager.engine,\n getHls: () => this.sourceManager.hlsInstance,\n });\n }\n this.statsPanel.toggle(force);\n }\n\n private readonly onPointerTypeTrack = (e: PointerEvent): void => {\n this.lastPointerType = e.pointerType;\n };\n\n /** Sağ tık: tarayıcı menüsü yerine player adı + sürüm (options.contextMenu). */\n private readonly onContextMenu = (e: MouseEvent): void => {\n const config = this.contextMenuConfig;\n if (!config || this.lastPointerType !== 'mouse') return;\n e.preventDefault();\n this.contextMenu.show(e.clientX, e.clientY, [\n { label: 'HopeCorePlayer', meta: `v${HOPE_PLAYER_VERSION}` },\n ...(config.stats ? [{ label: this.i18n.statsTitle, onSelect: () => void this.toggleStats(true) }] : []),\n // Yalnızca debug açıkken ve kayıtlı bir hata varsa.\n ...(this.debugEnabled && this.log.entries.length\n ? [{ label: this.i18n.debugTitle, meta: String(this.log.entries.length), onSelect: () => void this.showDebugLog() }]\n : []),\n ]);\n };\n\n /** hls.js ile oynatılıyorsa hls.js instance'ı (olaylar, `bandwidthEstimate`, `levels`...); değilse `null`. */\n get hls(): Hls | null {\n return this.sourceManager.hlsInstance;\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 const attrs = JSON.stringify(attrOptions);\n if (this.bootResolved) {\n if (this.lastSynced?.options === this._options && this.lastSynced.attrs === attrs) return;\n this.lastSynced = { options: this._options, attrs };\n }\n void this.applyOptions({ ...attrOptions, ...this._options });\n }\n\n private queuePluginApply(options: HopePlayerOptions): Promise<void> {\n this.pendingPluginOptions = options;\n if (!this.pluginApplyRun) {\n this.pluginApplyRun = (async () => {\n while (this.pendingPluginOptions) {\n const next = this.pendingPluginOptions;\n this.pendingPluginOptions = null;\n try {\n await this.applyPluginsAndPlayback(next);\n } catch (err) {\n console.error('[hope-player] options could not be applied:', err);\n }\n }\n })().finally(() => {\n this.pluginApplyRun = null;\n });\n }\n return this.pluginApplyRun;\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 this.tapToPlay = options.tapToPlay ?? 'auto';\n this.cursorHideDelayMs = options.cursorHideDelayMs === false ? null : (options.cursorHideDelayMs ?? DEFAULT_CURSOR_HIDE_DELAY_MS);\n if (this.cursorHideDelayMs === null) this.showCursor();\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 this.debugEnabled = !!options.debug;\n if (!this.debugEnabled) this.debugPanel?.hide();\n this.contextMenuConfig =\n options.contextMenu === false ? null : { stats: typeof options.contextMenu === 'object' && options.contextMenu.stats === true };\n if (!this.contextMenuConfig) this.contextMenu.close();\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 const ratio = normalizeAspectRatio(options.aspectRatio);\n if (ratio) this.style.setProperty('--hp-aspect-ratio', ratio);\n else this.style.removeProperty('--hp-aspect-ratio');\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.onStreamAudioTracks(this.streamAudio.tracks, this.streamAudio.active);\n this.statsPanel?.refreshLabels();\n this.debugPanel?.refreshLabels();\n this.liveWallClock?.refreshLabels();\n this.loopSection?.refreshLabels();\n this.audioStage?.refreshLabels();\n this.markProgress?.refreshLabels();\n this.unregisterSticky?.refreshLabels?.();\n\n if (!this.bootResolved) {\n return;\n }\n await this.queuePluginApply(options);\n }\n\n /** applyOptions'ın asenkron kısmı — yalnızca queuePluginApply üzerinden, sırayla çalışır. */\n private async applyPluginsAndPlayback(options: HopePlayerOptions): Promise<void> {\n if (options.ads && !this.adsController) {\n const adsOptions: AdsOptions = options.ads === true ? {} : options.ads;\n // Kapı kaynak yüklenmeden / autoplay denenmeden önce kurulur — içerik preroll'dan önce oynamasın.\n if (expectsPreroll(adsOptions) && !this.prerollGate.isArmed) {\n this.prerollGate.arm(adsOptions.prerollTimeoutMs ?? DEFAULT_PREROLL_TIMEOUT_MS);\n }\n preconnectAdHosts();\n // IMA SDK + reklam isteği kaynak yüklemesiyle PARALEL başlasın (countdown varken reklam sonra istenir).\n if (!options.countdownScreen) void this.installAdsOnce(options);\n }\n\n await this.applyAudioMode(options);\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 this.sourceManager.configure(options.hls);\n this.errorScreen.dismiss();\n const sources = options.sources?.length ? options.sources : options.src ? [{ src: options.src, label: this.i18n.autoQuality }] : [];\n const initial = sources.find((s) => s.selected) ?? sources[0];\n // Kaynak değişmediyse yeniden yükleme: başka bir seçenek değişince (ör. React'te prop) çalan medya başa sarılmasın.\n if (initial && !this.sourceManager.isLoaded(initial.src, initial.type)) {\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 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 await this.installAdsOnce(options);\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.tapGestures && !this.tapGestures) {\n const { installTapGestures } = await import('./plugins/tap-gestures');\n this.tapGestures = installTapGestures(\n {\n areaEl: this.videoArea,\n seekBy: (delta) => {\n if (this.controlBar.seekBar.el.style.pointerEvents === 'none') return; // DAI reklam arası\n seekBy(this.videoEl, delta);\n this.seekFeedback.show(delta);\n },\n togglePlay: () => (this.videoEl.paused ? void this.videoEl.play().catch(() => {}) : this.videoEl.pause()),\n toggleFullscreen: () => (this.isFullscreenActive() ? this.exitFullscreenCompat() : this.requestFullscreenCompat()),\n toggleMute: () => {\n this.videoEl.muted = !this.videoEl.muted;\n },\n },\n []\n );\n }\n if (this.tapGestures) {\n const { DEFAULT_TAP_GESTURES } = await import('./plugins/tap-gestures');\n this.tapGestures.setGestures(options.tapGestures === true ? DEFAULT_TAP_GESTURES : options.tapGestures || []);\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 getPlayingDate: () => {\n const playing = this.sourceManager.hlsInstance?.playingDate;\n if (playing) return playing;\n // Safari native HLS: yayının başlangıç tarihi + konum.\n const start = (this.videoEl as HTMLVideoElement & { getStartDate?: () => Date }).getStartDate?.();\n const ms = start?.getTime() ?? NaN;\n return Number.isFinite(ms) && ms > 0 ? new Date(ms + this.videoEl.currentTime * 1000) : null;\n },\n },\n liveWallClockOptions\n );\n // Canlıda seek bar hover'ında duvar saati tooltip'i gösterilir, varsayılan \"-1:24\" değil.\n this.controlBar.seekBar.liveHoverHandled = true;\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.optionTracks = attachSubtitleTracks(this.videoEl, options.subtitles);\n } else {\n clearSubtitleTracks(this.videoEl);\n this.optionTracks = [];\n }\n this.rebuildCaptions(options.subtitles?.find((s) => s.default)?.label ?? null);\n }\n\n /** Altyazı menüsünü `options.subtitles` + yayın izlerinden kurar; `activeLabel` varsa onu seçer. */\n private rebuildCaptions(activeLabel: string | null): void {\n this.subtitleTracks = [...this.optionTracks, ...this.streamTracks];\n if (!this.subtitleTracks.length) {\n this.selectCaption = null;\n this.activeCaptionLabel = null;\n this.controlBar.setCaptions([], this.i18n.captionsOff);\n this.captionRenderer.setActiveTrack(null);\n this.captionTrackActive = false;\n this.controlBar.settingsMenu.setCaptionAppearance(null);\n this.sourceManager.selectTextTrack(null);\n return;\n }\n // selectCaption: altyazı seçiminin tek doğruluk kaynağı (track mode + renderer + ayarlar menüsü + hls.js).\n const selectCaption = (label: string | null): void => {\n const track = selectSubtitleTrack(this.subtitleTracks, label);\n this.activeCaptionLabel = track ? label : null;\n this.sourceManager.selectTextTrack(this.streamTracks.find((t) => t.label === label)?.id ?? null);\n this.captionRenderer.setActiveTrack(track);\n this.captionTrackActive = track !== null;\n this.controlBar.settingsMenu.setActiveCaption(track ? label! : this.i18n.captionsOff);\n this.controlBar.settingsMenu.setCaptionAppearance(track !== null ? this.buildCaptionAppearance() : null);\n };\n this.selectCaption = selectCaption;\n const active = activeLabel && this.subtitleTracks.some((t) => t.label === activeLabel) ? activeLabel : null;\n this.controlBar.setCaptions(\n [\n { label: this.i18n.captionsOff, onSelect: () => selectCaption(null) },\n ...this.subtitleTracks.map(({ label }) => ({ label, onSelect: () => selectCaption(label) })),\n ],\n active ?? this.i18n.captionsOff\n );\n selectCaption(active);\n }\n\n /**\n * Yayın izinin menü adı: manifestteki ad teknik/boşsa (\"stream_5\", \"und\", dil kodunun kendisi) dil kodundan\n * player diliyle dil adı üretilir (\"en\" → \"İngilizce\" / \"English\").\n */\n private streamTrackLabel(name: string, lang: string): string {\n const generic = !name || name.toLowerCase() === lang.toLowerCase() || /^(stream|audio|track|text|sub|subtitle|und)[\\s_-]*\\d*$/i.test(name);\n if (!generic || !lang || lang === 'und') return name || lang;\n try {\n const display = new Intl.DisplayNames([this.localeCode], { type: 'language' }).of(lang);\n if (display) return display.charAt(0).toLocaleUpperCase(this.localeCode) + display.slice(1);\n } catch {\n // Geçersiz dil kodu — ham adı kullan.\n }\n return name || lang;\n }\n\n /** Aynı adlı iz varsa (ör. options.subtitles'ta da \"English\") dil/sırayla ayırt edilir. */\n private uniqueLabel(label: string, suffix: string, taken: Set<string>): string {\n const unique = taken.has(label) ? `${label} (${suffix})` : label;\n taken.add(unique);\n return unique;\n }\n\n private readonly onStreamTextTracks = (tracks: StreamTextTrack[]): void => {\n const native = this.streamTracks.filter((t) => t.id.startsWith('native:'));\n if (!tracks.length) {\n clearPooledTracks(this.videoEl, 'stream');\n this.streamCueKeys.clear();\n this.streamTracks = native;\n } else {\n const taken = new Set([...this.optionTracks, ...native].map((t) => t.label));\n this.streamTracks = [\n ...native,\n ...tracks.map((t) => {\n // CEA-608 genelde manifest altyazısıyla aynı adı taşır (\"English\") — \"(CC)\" ile ayırt edilir.\n const label = this.uniqueLabel(this.streamTrackLabel(t.label, t.lang) || t.id, t.kind === 'captions' ? 'CC' : t.lang || t.kind, taken);\n return { id: t.id, label, track: pooledTrack(this.videoEl, 'stream', t.kind, label, t.lang) };\n }),\n ];\n }\n this.rebuildCaptions(this.activeCaptionLabel);\n };\n\n private readonly onStreamCues = (trackId: string, cues: VTTCue[]): void => {\n const track = this.streamTracks.find((t) => t.id === trackId)?.track;\n if (!track) return;\n let keys = this.streamCueKeys.get(track);\n if (!keys) this.streamCueKeys.set(track, (keys = new Set()));\n for (const cue of cues) {\n const key = `${cue.startTime}|${cue.endTime}|${cue.text}`;\n if (keys.has(key)) continue;\n keys.add(key);\n track.addCue(cue);\n }\n };\n\n /** Tarayıcının kendi (native HLS) altyazı izleri — bizim havuz izlerimiz ve metadata izleri hariç. */\n private readonly onNativeTextTracksChanged = (): void => {\n const list = Array.from(this.videoEl.textTracks).filter((t) => (t.kind === 'subtitles' || t.kind === 'captions') && !isPooledTrack(t));\n const hadNative = this.streamTracks.some((t) => t.id.startsWith('native:'));\n if (!list.length && !hadNative) return;\n const fromHls = this.streamTracks.filter((t) => !t.id.startsWith('native:'));\n const taken = new Set([...this.optionTracks, ...fromHls].map((t) => t.label));\n this.streamTracks = [\n ...fromHls,\n ...list.map((track, i) => ({\n id: `native:${i}`,\n label: this.uniqueLabel(track.label || track.language || `${this.i18n.captions} ${i + 1}`, track.language || String(i + 1), taken),\n track,\n })),\n ];\n this.rebuildCaptions(this.activeCaptionLabel);\n };\n\n /** Yayında birden fazla ses izi varsa ayarlarda \"Ses\" alt menüsü (HLS alternatif ses / Safari audioTracks). */\n private readonly onStreamAudioTracks = (tracks: StreamAudioTrack[], active: number): void => {\n this.streamAudio = { tracks, active };\n const menu = this.controlBar.settingsMenu;\n const taken = new Set<string>();\n const labels = new Map(tracks.map((t) => [t.index, this.uniqueLabel(this.streamTrackLabel(t.label, t.lang), String(t.index + 1), taken)]));\n if (tracks.length <= 1) {\n menu.unregisterSubmenu(STREAM_AUDIO_SUBMENU_KEY);\n return;\n }\n menu.registerSubmenu({\n key: STREAM_AUDIO_SUBMENU_KEY,\n title: this.i18n.audioTrack,\n getValueLabel: () => labels.get(active) ?? '',\n getItems: () => tracks.map((t) => ({ label: labels.get(t.index)!, active: t.index === active, onSelect: () => this.sourceManager.setAudioTrack(t.index) })),\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 if (this.audioMode) return; // ses modunda görüntü yok\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 // Oynat'a tıklayıp fareyi kıpırdatmayan kullanıcı için de imleç sayacı başlasın.\n if (this.matches(':hover')) this.scheduleCursorHide();\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 this.showCursor();\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 isTouch = 'changedTouches' in e;\n // Dokunmadan hemen sonra gelen uyumluluk mouse olayları — dokunuş zaten işlendi.\n if (!isTouch && Date.now() - this.lastTouchEndAt < 800) return;\n if (isTouch) this.lastTouchEndAt = Date.now();\n const point = isTouch ? 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) {\n // Dokunuş değil kaydırma — dokunmatikte kontrolleri göster (pointermove artık açmıyor).\n if (isTouch && !this.isChromeBlocked) this.scheduleAutoHide();\n return;\n }\n }\n const pointer = isTouch ? 'touch' : (this.lastPointerType as 'mouse' | 'pen');\n const singleTap = (): void =>\n this.onBackgroundTap(pointer, () => {\n if (this.videoEl.paused) void this.videoEl.play().catch(() => {});\n else this.videoEl.pause();\n });\n // Bu bölgede çift dokunma hareketi varsa tek dokunuş, ikinci dokunuş gelmezse uygulanır.\n if (point && this.tapGestures?.handleTap(point.clientX, pointer === 'pen' ? 'pen' : pointer, singleTap)) return;\n singleTap();\n };\n\n /**\n * Dar player'da kontrol çubuğu (alt satır + seek bar) yüksekliğin yarısını kaplıyor ve seek bar ortadaki play\n * butonunun içinden geçiyordu — butonun ortasına dokunmak videoyu sarıyordu. Buton seek bar'ın üstündeki boş\n * alanın ortasına alınır, sığmazsa küçülür (en az 40px).\n */\n private layoutCenterPlay(): void {\n const area = this.videoArea;\n const areaRect = area.getBoundingClientRect();\n const seekRect = this.controlBar.seekBar.el.getBoundingClientRect();\n const reset = (): void => {\n area.removeAttribute('data-center-play-shifted');\n area.style.removeProperty('--hp-center-play-size');\n area.style.removeProperty('--hp-center-play-shift');\n area.style.removeProperty('--hp-center-play-shift-x');\n };\n if (!areaRect.height || !seekRect.height || !area.hasAttribute('data-compact')) return reset();\n const fullSize = 64;\n const freeBottom = seekRect.top - areaRect.top - 8;\n // Ortada zaten sığıyorsa dokunma.\n if (areaRect.height / 2 + fullSize / 2 <= freeBottom) return reset();\n const size = Math.max(40, Math.min(56, freeBottom - 12));\n // Seek bar'ın hemen üstü — görsel merkeze olabildiğince yakın (en tepeye yapışmasın).\n const centerY = Math.max(size / 2 + 6, freeBottom - size / 2);\n const shift = Math.round(centerY - areaRect.height / 2);\n // En dar ekranda (≈320px) buton üst bara (ayarlar/PiP) değebiliyor — o zaman üst barın soluna kaydır.\n let shiftX = 0;\n const top = this.controlBar.topEl.getBoundingClientRect();\n if (top.width > 0 && centerY - size / 2 < top.bottom - areaRect.top) {\n const maxCenterX = top.left - areaRect.left - 8 - size / 2;\n if (areaRect.width / 2 > maxCenterX) shiftX = Math.round(Math.max(size / 2 + 8, maxCenterX) - areaRect.width / 2);\n }\n area.setAttribute('data-center-play-shifted', '');\n area.style.setProperty('--hp-center-play-shift-x', `${shiftX}px`);\n area.style.setProperty('--hp-center-play-size', `${size}px`);\n area.style.setProperty('--hp-center-play-shift', `${shift}px`);\n }\n\n /** Dar player'da dokunmatikte oynat/duraklat yerine kontrolleri göster/gizle (options.tapToPlay). */\n private tapTogglesPlay(pointer: string): boolean {\n if (this.tapToPlay !== 'auto') return this.tapToPlay;\n if (pointer === 'mouse') return true;\n return !this.videoArea.hasAttribute('data-compact') || this.isFullscreenActive();\n }\n\n /** Videonun boş alanına tek dokunuş/tık: ya `togglePlay` ya da (dar player'da) kontrolleri aç/kapa. */\n private onBackgroundTap(pointer: string, togglePlay: () => void): void {\n if (this.tapTogglesPlay(pointer)) {\n togglePlay();\n return;\n }\n // YouTube mobil gibi: kontroller açık ve video oynuyorsa gizle, değilse göster (gizleme sayacıyla).\n if (this.chromeVisible && !this.videoEl.paused) {\n if (this.hideTimer) clearTimeout(this.hideTimer);\n this.setChromeOpacity('0');\n } else {\n this.scheduleAutoHide();\n }\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 // Dokunmatikte pointermove kontrolleri AÇMAZ, yalnızca açıksa süresini uzatır: Android'de (ör. Honor/Magic OS)\n // parmak dokunurken 1-2px kayıp pointermove üretiyor — kontroller açılıp hemen ardından gelen dokunuş\n // (\"açıksa gizle\") onları kapatıyor, toolbar yanıp sönüyordu. Dokunmada aç/kapa kararı onBackgroundTap'te.\n if (e.pointerType !== 'mouse') {\n if (this.chromeVisible) this.scheduleAutoHide();\n return;\n }\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.composedPath().includes(this.chromeEl);\n this.scheduleAutoHide();\n if (e.pointerType === 'mouse') this.scheduleCursorHide();\n };\n\n private readonly onPointerLeave = (e: PointerEvent): void => {\n if (e.pointerType !== 'mouse') return;\n this.pointerOverControls = false;\n this.scheduleAutoHide();\n this.showCursor();\n };\n\n /** Fare kıpırdadı: imleci göster, hareketsiz kalırsa gizlemek için sayacı yeniden kur (tailwind.css `:host([data-cursor-hidden])`). */\n private scheduleCursorHide(): void {\n this.showCursor();\n if (this.cursorHideDelayMs === null) return;\n this.cursorTimer = setTimeout(() => {\n this.cursorTimer = null;\n // Duraklatılmışken, menü açıkken ya da imleç bir kontrolün üzerindeyken gizleme (YouTube gibi).\n if (this.videoEl.paused || this.pointerOverControls || this.controlBar.settingsMenu.isOpen) return;\n this.setAttribute('data-cursor-hidden', '');\n }, this.cursorHideDelayMs);\n }\n\n private showCursor(): void {\n if (this.cursorTimer) clearTimeout(this.cursorTimer);\n this.cursorTimer = null;\n this.removeAttribute('data-cursor-hidden');\n }\n\n /** options.audio: sahneyi kurar, günceller (konum / boyut / devir canlı değişebilir) ya da kaldırır. */\n private async applyAudioMode(options: HopePlayerOptions): Promise<void> {\n const audio = options.audio ? (options.audio === true ? {} : options.audio) : null;\n this.audioMode = !!audio;\n this.toggleAttribute('data-audio', !!audio);\n this.controlBar.setAudioMode(!!audio);\n if (!audio) {\n this.audioStage?.destroy();\n this.audioStage = null;\n return;\n }\n // Ses modunda kontroller hiç gizlenmez.\n if (this.hideTimer) clearTimeout(this.hideTimer);\n this.hideTimer = null;\n if (!this.isChromeBlocked) this.showChrome();\n if (!this.audioStage) {\n const { installAudioStage } = await import('./plugins/audio');\n if (!this.audioMode) return; // import sırasında ses modu kapatıldı\n this.audioStage ??= installAudioStage(\n {\n videoEl: this.videoEl,\n layerEl: this.root.querySelector<HTMLDivElement>('.media-layer')!,\n poster: () => this._options.poster ?? this.getAttribute('poster') ?? undefined,\n togglePlay: () => (this.videoEl.paused ? void this.play().catch(() => {}) : this.videoEl.pause()),\n play: () => void this.play().catch(() => {}),\n i18n: this.i18n,\n },\n audio\n );\n } else {\n this.audioStage.update(audio);\n }\n }\n\n /** Ads plugin'ini bir kez kurar; erken (paralel) başlatılan kurulum varsa onu bekler. */\n private installAdsOnce(options: HopePlayerOptions): Promise<void> {\n if (!options.ads || this.adsController) return Promise.resolve();\n if (!this.adsInstall) {\n const adsOptions: AdsOptions = options.ads === true ? {} : options.ads;\n this.adsInstall = (async () => {\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 prerollGate: this.prerollGate,\n log: (entry) => this.log.add({ source: 'ads', ...entry }),\n onAdProgress: (info) => this.controlBar.setAdInfo(info),\n // Sürekli oynatma (vconp): playlist / story bir sonraki içeriği kendiliğinden başlatıyorsa.\n isContinuousPlayback: () => {\n const o = this._options;\n const auto = (v: unknown) => !!v && (v as { autoplayNext?: boolean }).autoplayNext !== false;\n return auto(o.playlist) || auto(o.story);\n },\n audioPoster: (() => {\n if (!options.audio) return undefined;\n const a = options.audio === true ? {} : options.audio;\n return a.adPoster ? new URL(a.adPoster, document.baseURI).href : undefined;\n })(),\n surface: {\n videoEl: this.videoEl,\n containerEl: this.videoArea,\n enterFullscreen: () => this.requestFullscreenCompat(),\n labels: () => this.i18n,\n },\n },\n adsOptions\n );\n })().catch((err) => {\n // Plugin parçası yüklenemedi — içerik reklamsız oynar, bekleyen oynatma isteği başlar.\n this.prerollGate.release(true);\n this.adsInstall = null;\n this.dispatchEvent(new CustomEvent('hp:aderror', { detail: { message: String(err) } }));\n });\n }\n return this.adsInstall;\n }\n\n /** Preroll beklemesi başladı / bitti: halka döner, toolbar görünür kalır, oynat butonu \"duraklat\" görünür. */\n private onPrerollWaitChange(waiting: boolean): void {\n this.controlBar.setPendingPlay(waiting);\n this.controlBar.setLoading('preroll', waiting);\n if (this.isChromeBlocked) return;\n // Bekleme sırasında merkez \"oynat\" butonu görünmesin (video teknik olarak duraklatılmış durumda).\n const showCenter = !waiting && this.videoEl.paused;\n this.centerPlayButton.style.opacity = showCenter ? '1' : '0';\n this.centerPlayButton.style.pointerEvents = showCenter ? 'auto' : 'none';\n }\n\n /** Preroll beklenirken basılan oynat/duraklat (buton, Space/K) beklemeyi iptal eder. */\n private cancelPrerollWait(): boolean {\n if (!this.prerollGate.isWaiting) return false;\n this.prerollGate.cancelIntent();\n return true;\n }\n\n /** Yükleme halkası açılınca kontroller görünür kalır ve gizlenmez; kapanınca normal otomatik gizleme sürer. */\n private onLoadingChange(loading: boolean): void {\n this.loadingActive = loading;\n if (loading) {\n if (this.hideTimer) clearTimeout(this.hideTimer);\n this.hideTimer = null;\n if (!this.isChromeFullyHidden) this.showChrome();\n } else if (!this.videoEl.paused && !this.isChromeBlocked) {\n this.scheduleAutoHide();\n }\n }\n\n private readonly scheduleAutoHide = (): void => {\n this.showChrome();\n if (this.hideTimer) clearTimeout(this.hideTimer);\n if (this.videoEl.paused || this.loadingActive) return;\n // Ses modunda kontroller hep görünür.\n if (this.audioMode) return;\n this.hideTimer = setTimeout(() => {\n // Duraklatılmışken, yüklenirken, fare kontrollerin üzerindeyken ya da ayarlar menüsü açıkken gizleme.\n if (this.audioMode || this.videoEl.paused || this.loadingActive || this.pointerOverControls || this.controlBar.settingsMenu.isOpen) return;\n this.setChromeOpacity('0');\n }, this.lastPointerType === 'mouse' ? this.autoHideDelayMs : Math.max(this.autoHideDelayMs, TOUCH_AUTO_HIDE_DELAY_MS));\n };\n}\n","import { HopePlayerElement, HOPE_PLAYER_VERSION } from './HopePlayerElement';\n\nif (typeof window !== 'undefined' && !customElements.get('hope-player')) {\n customElements.define('hope-player', HopePlayerElement);\n}\n\nexport { HopePlayerElement, HOPE_PLAYER_VERSION };\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 HopeHlsOptions,\n ContextMenuOptions,\n TapGesture,\n TapGestureType,\n TapRegion,\n TapPointer,\n TapAction,\n DubbingTrack,\n DubbingOptions,\n LiveWallClockOptions,\n DaiOptions,\n LiveAdsOptions,\n OmidAccessMode,\n OmidVendor,\n} from './types';\nexport type { SettingsSubmenuDef, SettingsSubmenuItem } from './controls/SettingsMenu';\nexport type { ErrorLog, PlayerLogEntry, PlayerLogSource } from './debug/ErrorLog';\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","callbacks","__publicField","options","sourceType","engine","canNative","reason","onMeta","cleanup","onError","unsupported","_b","list","report","tracks","t","index","ev","Hls","hls","parsed","mediaRecoveryTried","_event","data","d","_f","_e","_c","_d","loadFailed","levels","level","audio","sub","id","kind","user","config","xhrSetup","fetchSetup","xhr","url","context","init","withCreds","i","hlsId","formatTime","seconds","totalSeconds","h","m","s","mm","ss","MIN_LIVE_WINDOW_SEC","LIVE_EDGE_SAFETY_SEC","SeekBar","labels","e","tl","ratio","time","x","tick","span","toRatio","playedRatio","bufferedEnd","bufferedRatio","c","local","r","track","duration","seekable","start","end","key","suppressed","clientX","next","zoneEnd","ch","ranges","container","el","bufferedEl","playedEl","rect","bar","k","extraClass","marker","createIcon","name","setIconName","WHEEL_VOLUME_STEP","HIDE_DELAY_MS","VolumePanel","adHooks","current","effectiveVolume","label","playing","clientY","MENU_GAP_PX","MENU_EDGE_PX","MENU_MIN_HEIGHT_PX","MENU_MAX_HEIGHT_PX","SettingsMenu","playbackRates","area","a","b","anchor","drop","content","room","activeLabel","appearance","toggle","def","value","onClick","btn","title","onBack","item","rate","active","q","divider","dot","color","o","grid","opt","swatch","seekBy","delta","LIVE_EDGE_TOLERANCE_SEC","COMPACT_MAX_WIDTH","LOADING_RING_DELAY_MS","LOADING_START_EVENTS","LOADING_END_EVENTS","skipButton","direction","part","iconButton","num","setButtonLabel","iconName","shortcut","icon","ControlBar","paused","isLive","total","remaining","target","behind","sync","edge","row","leftGroup","ring","ringMask","play","liveDot","spacer","rightGroup","pip","fullscreen","width","compact","on","isFullscreen","back","forward","enabled","render","display","info","pod","show","pending","loading","buffered","SHOW_DELAY_MS","GAP_PX","EDGE_PADDING_PX","EXCLUDE_PARTS","canHover","TooltipController","mountEl","related","check","fromEl","mountRect","targetRect","ttRect","top","left","maxLeft","KeyboardController","host","toggleFullscreen","LoadingSpinner","RETRY_ICON","ErrorScreen","card","fn","code","messages","pools","ownTracks","generations","isPooledTrack","pooledTrack","scope","lang","pool","clearPooledTracks","cue","attachSubtitleTracks","subtitles","clearSubtitleTracks","generation","attached","loadCues","selectSubtitleTrack","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","bottom","transform","animate","targetPx","prevPx","visible","MiniProgress","hasDuration","ACCUMULATE_WINDOW_MS","HIDE_AFTER_MS","CHEVRON","SeekFeedback","chevrons","now","sameDirection","ContextMenu","items","meta","height","y","REPEAT_WINDOW_MS","MAX_ENTRIES","ErrorLog","entry","last","details","v","repeat","STYLE_ID","injectIconFont","style","iconFontFaceCss","tr","en","BUILTIN_LOCALES","createLocaleStrings","locale","overrides","applyLocale","DEFAULT_PREROLL_TIMEOUT_MS","expectsPreroll","ads","PrerollGate","timeoutMs","resume","wanted","AD_HOSTS","done","preconnectAdHosts","href","link","DEFAULT_PLAYBACK_RATES","DEFAULT_AUTO_HIDE_DELAY_MS","TOUCH_AUTO_HIDE_DELAY_MS","DEFAULT_CURSOR_HIDE_DELAY_MS","TAP_MAX_MOVE_PX","DEFAULT_SKIP_SECONDS","DEFAULT_KEYBOARD_SEEK_STEP","STREAM_AUDIO_SUBMENU_KEY","HOPE_PLAYER_VERSION","TEMPLATE","normalizeAspectRatio","HopePlayerElement","names","native","taken","trackId","keys","hadNative","fromHls","menu","activeIndex","point","isTouch","pointer","singleTap","tailwindCss","wrapper","waiting","centerChip","single","open","p","_g","_h","_i","_j","_k","_l","_m","_n","_o","_p","_q","_r","_s","_t","_u","_v","_w","_x","installDebugPanel","force","installStats","attrOptions","attrs","seekStep","skip","adsOptions","gateCtx","installCountdownScreen","installGeoChecker","sources","initial","gestureOptions","installGesture","loopOptions","installLoopSection","inViewOptions","installInViewAutoplay","stickyOptions","installSticky","installPlaylist","tag","installStory","installMarkers","installSegments","installSpriteThumbnails","installRedirectScreen","installQrResume","qr","installTapGestures","DEFAULT_TAP_GESTURES","installPauseAd","installDubbing","liveWallClockOptions","installLiveWallClock","ms","installDai","selectCaption","suffix","unique","sizes","buildColorOptions","get","set","source","resumeTime","wasPlaying","videoFallback","doc","showing","mode","reset","fullSize","freeBottom","centerY","shift","shiftX","maxCenterX","togglePlay","installAudioStage","installAds","auto","showCenter"],"mappings":"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"}