@hopeplayer/core 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/HopePlayerElement.d.ts +11 -2
- package/dist/HopePlayerElement.d.ts.map +1 -1
- package/dist/chunks/{accessibility-CehDBG3h.js → accessibility-DeUIoAda.js} +43 -40
- package/dist/chunks/accessibility-DeUIoAda.js.map +1 -0
- package/dist/chunks/{ads-Cd6ON12M.js → ads-CdWbE9aD.js} +2 -2
- package/dist/chunks/{ads-Cd6ON12M.js.map → ads-CdWbE9aD.js.map} +1 -1
- package/dist/chunks/{cast-Do1ierzb.js → cast-BQ-suTcF.js} +2 -2
- package/dist/chunks/{cast-Do1ierzb.js.map → cast-BQ-suTcF.js.map} +1 -1
- package/dist/chunks/{history-D1nwP4qx.js → history-DAbqEhNB.js} +2 -2
- package/dist/chunks/{history-D1nwP4qx.js.map → history-DAbqEhNB.js.map} +1 -1
- package/dist/chunks/{markers-CUe9BuTY.js → markers-B04NMI79.js} +2 -2
- package/dist/chunks/{markers-CUe9BuTY.js.map → markers-B04NMI79.js.map} +1 -1
- package/dist/chunks/{player-B0p2gi63.js → player-D7WQxMzr.js} +572 -456
- package/dist/chunks/player-D7WQxMzr.js.map +1 -0
- package/dist/chunks/{playlist-jZ5Ek0N9.js → playlist-C6Mh9BE8.js} +2 -2
- package/dist/chunks/{playlist-jZ5Ek0N9.js.map → playlist-C6Mh9BE8.js.map} +1 -1
- package/dist/chunks/pluginHost-DjvLmMYZ.js +376 -0
- package/dist/chunks/pluginHost-DjvLmMYZ.js.map +1 -0
- package/dist/chunks/{redirectScreen-CwQF3ZRc.js → redirectScreen-5HAVRtxe.js} +2 -2
- package/dist/chunks/{redirectScreen-CwQF3ZRc.js.map → redirectScreen-5HAVRtxe.js.map} +1 -1
- package/dist/chunks/{rewardedUnlock-B2CB2JZy.js → rewardedUnlock-CGhQyWOk.js} +2 -2
- package/dist/chunks/{rewardedUnlock-B2CB2JZy.js.map → rewardedUnlock-CGhQyWOk.js.map} +1 -1
- package/dist/chunks/{segments-RC0zYT2a.js → segments-gCPrWRig.js} +2 -2
- package/dist/chunks/{segments-RC0zYT2a.js.map → segments-gCPrWRig.js.map} +1 -1
- package/dist/chunks/{skipSegments-BwMHrQxt.js → skipSegments-BbWzPpXz.js} +55 -42
- package/dist/chunks/{skipSegments-BwMHrQxt.js.map → skipSegments-BbWzPpXz.js.map} +1 -1
- package/dist/chunks/{spriteThumbnails-BaSn9kUY.js → spriteThumbnails-B7oDZFTo.js} +2 -2
- package/dist/chunks/{spriteThumbnails-BaSn9kUY.js.map → spriteThumbnails-B7oDZFTo.js.map} +1 -1
- package/dist/chunks/{story-BVhbvY-4.js → story-BLBij82f.js} +2 -2
- package/dist/chunks/{story-BVhbvY-4.js.map → story-BLBij82f.js.map} +1 -1
- package/dist/controls/ControlBar.d.ts +14 -0
- package/dist/controls/ControlBar.d.ts.map +1 -1
- package/dist/controls/SettingsMenu.d.ts +12 -1
- package/dist/controls/SettingsMenu.d.ts.map +1 -1
- package/dist/hope-player.js +6 -3
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/plugin-api/PluginHost.d.ts +65 -0
- package/dist/plugin-api/PluginHost.d.ts.map +1 -0
- package/dist/plugin-api/registry.d.ts +10 -0
- package/dist/plugin-api/registry.d.ts.map +1 -0
- package/dist/plugin-api/types.d.ts +170 -0
- package/dist/plugin-api/types.d.ts.map +1 -0
- package/dist/plugins/accessibility/Accessibility.d.ts +5 -0
- package/dist/plugins/accessibility/Accessibility.d.ts.map +1 -1
- package/dist/plugins/skip-segments/index.d.ts +2 -0
- package/dist/plugins/skip-segments/index.d.ts.map +1 -1
- package/dist/types/index.d.ts +11 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/chunks/accessibility-CehDBG3h.js.map +0 -1
- package/dist/chunks/player-B0p2gi63.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"player-B0p2gi63.js","sources":["../../src/utils/media-error.ts","../../src/hls/SourceManager.ts","../../src/hls/sourceGroups.ts","../../src/utils/format-time.ts","../../src/utils/seek-by.ts","../../src/controls/SeekBar.ts","../../src/icons/Icon.ts","../../src/controls/VolumePanel.ts","../../src/controls/SettingsMenu.ts","../../src/controls/ControlBar.ts","../../src/controls/Tooltip.ts","../../src/keyboard/KeyboardController.ts","../../src/screens/LoadingSpinner.ts","../../src/screens/ErrorScreen.ts","../../src/subtitles/attachTracks.ts","../../src/subtitles/CaptionRenderer.ts","../../src/controls/MiniProgress.ts","../../src/controls/SeekFeedback.ts","../../src/controls/ContextMenu.ts","../../src/debug/ErrorLog.ts","../../src/icons/injectIconFont.ts","../../src/plugins/ads/generateVastUrl.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":["/**\n * Ses çıkışı açılamadı (Firefox: ses aygıtı yok ya da o an kullanılamıyor — ör. ses kartı olmayan makine, kopan\n * Bluetooth kulaklık). Firefox bunu `MEDIA_ERR_DECODE` (3, mesaj `OnMediaSinkAudioError`) olarak bildiriyor ama video\n * sessiz oynamaya devam ediyor — ölümcül değil: hata ekranı açılmaz, yedek kaynağa / sonraki öğeye geçilmez, aynı kaynak\n * yeniden yüklenmez.\n */\nexport function isAudioOutputError(err: MediaError | null | undefined): boolean {\n return !!err && /MediaSinkAudio/i.test(err.message || '');\n}\n\n/** `video.error` gerçek (ölümcül) bir hata mı — ses çıkışı hatası sayılmaz. */\nexport function hasFatalMediaError(video: HTMLMediaElement): boolean {\n return !!video.error && !isAudioOutputError(video.error);\n}\n","import type { HlsConfig } from 'hls.js';\nimport type { HopeHlsOptions } from '../types';\nimport { hasFatalMediaError } from '../utils/media-error';\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 /** hls.js ile oynarken hangi paket (`options.hls.build`). */\n build?: 'full' | 'light';\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 */\nexport function 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 && !hasFatalMediaError(this.video) && 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. İki paket ayrı parçalarda — biri seçilince öbürü inmez.\n const build = this.hlsOptions.build === 'light' ? 'light' : 'full';\n const { default: Hls } = build === 'light' ? await import('hls.js/light') : 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', build };\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 /** Son `load()` edilen kaynak (playlist/dublaj gibi eklentilerin yüklediği dahil). */\n get currentSrc(): string | null {\n return this.last?.src ?? null;\n }\n\n reload(): Promise<void> {\n return this.last ? this.load(this.last.src, this.last.type) : Promise.resolve();\n }\n\n /** ABR'nin çıkabileceği en yüksek seviye (kalite kilidi); -1 = sınır yok. */\n setMaxLevel(index: number): void {\n if (this.hls && this.hls.autoLevelCapping !== index) this.hls.autoLevelCapping = index;\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","import type { HopeSourceFormat, HopeSourceOption } from '../types';\nimport { detectSourceType } from './SourceManager';\n\n/** Aynı biçimdeki kaynaklar (ör. tüm MP4 kaliteleri) — biri çalınır, menüde yalnızca bunlar görünür. */\nexport interface SourceGroup {\n format: HopeSourceFormat;\n sources: HopeSourceOption[];\n}\n\nconst FILE_MIME: Record<string, string> = {\n mp4: 'video/mp4',\n m4v: 'video/mp4',\n webm: 'video/webm',\n ogv: 'video/ogg',\n ogg: 'video/ogg',\n mov: 'video/quicktime',\n mp3: 'audio/mpeg',\n m4a: 'audio/mp4',\n aac: 'audio/aac',\n wav: 'audio/wav',\n flac: 'audio/flac',\n};\n\n/** `hls`, `mp4` ya da dosya uzantısı (`webm`, `mov`, `mp3`…); belirlenemezse `other`. MIME `type` uzantıdan önce gelir. */\nexport function sourceFormat(s: HopeSourceOption): HopeSourceFormat {\n const detected = detectSourceType(s.src, s.type);\n if (detected !== 'unknown') return detected;\n const mime = s.type?.split(';')[0]?.trim().toLowerCase();\n if (mime) {\n const ext = Object.keys(FILE_MIME).find((k) => FILE_MIME[k] === mime);\n if (ext) return ext;\n }\n const m = /\\.([a-z0-9]{2,5})(?:$|[?#])/i.exec(s.src);\n return m ? m[1]!.toLowerCase() : 'other';\n}\n\n/**\n * Kaynakları biçime göre gruplar: önce `priority` sırası, sonra listede ilk görünme sırası.\n * `priority`'de olmayan biçimler sona eklenir (hiçbiri atılmaz — son çare olarak yine denenir).\n */\nexport function groupSources(sources: HopeSourceOption[], priority?: readonly HopeSourceFormat[]): SourceGroup[] {\n const groups: SourceGroup[] = [];\n for (const s of sources) {\n const format = sourceFormat(s);\n const g = groups.find((x) => x.format === format);\n if (g) g.sources.push(s);\n else groups.push({ format, sources: [s] });\n }\n if (!priority?.length) return groups;\n const rank = (f: HopeSourceFormat): number => {\n const i = priority.findIndex((p) => p.toLowerCase() === f);\n return i === -1 ? priority.length : i;\n };\n // Array.prototype.sort kararlı — aynı sıradakiler listedeki düzenini korur.\n return groups.sort((a, b) => rank(a.format) - rank(b.format));\n}\n\n/**\n * Bu tarayıcı grubu hiç oynatamaz mı (denemeden atlanabilir). Emin olunamayan durumlarda false —\n * atlamak yerine denenir, hata alınırsa zaten sıradaki gruba geçilir.\n */\nexport function cannotPlay(group: SourceGroup, video: HTMLVideoElement): boolean {\n if (group.format === 'hls') {\n const w = window as unknown as { MediaSource?: unknown; ManagedMediaSource?: unknown };\n const mse = typeof w.MediaSource !== 'undefined' || typeof w.ManagedMediaSource !== 'undefined';\n return !mse && video.canPlayType('application/vnd.apple.mpegurl') === '';\n }\n const mime = group.sources.find((s) => s.type)?.type ?? FILE_MIME[group.format];\n return !!mime && video.canPlayType(mime) === '';\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","/**\n * Videonun sonuna sarma hedefi bu kadar geride tutulur. WebKitGTK / WPE (Linux tarayıcıları, WPE'li TV / gömülü cihazlar;\n * GStreamer) `preload=\"metadata\"` ile henüz indirilmemiş sona TAM sarınca konumu 0'a sıfırlıyor — 0.05 sn geride sorun yok.\n * Oynarken video kalan 0.05 sn'yi çalıp doğal olarak biter; gözle fark edilmez.\n */\nexport const END_SEEK_GUARD_SEC = 0.05;\n\n/** Sonlu süreli videoda sarma hedefi: sondan `END_SEEK_GUARD_SEC` öteye geçmez (canlıda / süre bilinmiyorsa dokunulmaz). */\nexport function vodSeekTarget(video: HTMLMediaElement, time: number): number {\n const d = video.duration;\n if (!Number.isFinite(d) || d <= END_SEEK_GUARD_SEC * 2) return time;\n return Math.min(time, d - END_SEEK_GUARD_SEC);\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 = vodSeekTarget(video, Math.max(start, Math.min(end, video.currentTime + delta)));\n}\n","import type { HopeLocaleStrings } from '../i18n/types';\nimport { formatTime } from '../utils/format-time';\nimport { vodSeekTarget } from '../utils/seek-by';\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/**\n * Canlı hedef konumdan bu kadar (sn) gerideyse izleyici hâlâ \"canlıda\" sayılır: thumb sağ uçta, rozet kırmızı. Ağ\n * dalgalanmasıyla oynatma hedefin birkaç saniye gerisine düşebilir — her seferinde \"geride\" görünmesin.\n */\nexport const LIVE_EDGE_TOLERANCE_SEC = 15;\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 * Canlıda oynatıcının hedef konumu (hls.js `liveSyncPosition` — yayını bilerek uçtan ~3 segment geride oynatır).\n * Seek bar'ın sağ ucu burasıdır; verilmezse seekable sonu.\n */\n liveTarget: (() => number | null) | null = null;\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ı hedef konum). 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 seekableEnd = seekable.end(seekable.length - 1);\n // Sağ uç = oynatıcının canlı hedefi: tam uç (seekable sonu) kullanılsaydı canlıda izlerken bile thumb hep\n // birkaç segment geride dururdu.\n const target = this.liveTarget?.();\n const end = target != null && target > start && target <= seekableEnd ? target : seekableEnd;\n return end - start >= MIN_LIVE_WINDOW_SEC ? { start, end, live: true } : null;\n }\n\n /** Canlıda izleyici canlı konumda mı — kontrol çubuğundaki \"● CANLI\" rozetiyle aynı ölçü. */\n private atLiveEdge(tl: { end: number }): boolean {\n return tl.end - this.video.currentTime <= LIVE_EDGE_TOLERANCE_SEC;\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 = vodSeekTarget(this.video, 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) : vodSeekTarget(this.video, 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 // Canlıda, canlı konumdayken thumb sağ uçta — rozet \"canlı\" derken seek bar \"geride\" göstermesin.\n const playedRatio = tl.live && this.atLiveEdge(tl) ? 1 : 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 /** Kilitli kalite (ödüllü reklamla açılır) — satırda kilit işareti; seçilince kilit açma akışı başlar. */\n locked?: boolean;\n}\n\n/** Kilit işareti (ikon fontunda yok). */\nexport const LOCK_SVG =\n '<svg class=\"hp-lock\" viewBox=\"0 0 24 24\" width=\"14\" height=\"14\" aria-hidden=\"true\"><path fill=\"currentColor\" d=\"M12 2a5 5 0 0 0-5 5v3H6a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8a2 2 0 0 0-2-2h-1V7a5 5 0 0 0-5-5Zm-3 8V7a3 3 0 1 1 6 0v3H9Z\"/></svg>';\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 /** Sağdaki değer metni (ör. \"150%\") — verilirse onay işareti yerine gösterilir. */\n value?: string;\n /** Verilirse satır bir alt menü açar (`onSelect` çağrılmaz) — iç içe menüler için (ör. Erişilebilirlik → Filtre). */\n children?: () => SettingsSubmenuDef;\n /** Seçince menü kapanmasın, aynı alt menü yeniden çizilsin (aç/kapa satırları). */\n keepOpen?: boolean;\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\n/**\n * Çözünürlükten rozet metni: kısa kenara göre 720+ → HD, 1440+ → 2K, 2160+ → 4K, 4320+ → 8K; altı → null (rozet yok).\n * Eşikler biraz aşağıda — kırpılmış kaynaklar (ör. 3840×1600 sinema oranı → kısa kenar 1600) bir alt sınıfa düşmesin\n * diye uzun kenar da sayılır.\n */\nfunction escapeHtml(s: string): string {\n return s.replace(/[&<>\"']/g, (c) => `&#${c.charCodeAt(0)};`);\n}\n\nexport function qualityBadgeText(width: number, height: number): string | null {\n if (!width || !height) return null;\n const short = Math.min(width, height);\n const long = Math.max(width, height);\n if (short >= 4000 || long >= 7600) return '8K';\n if (short >= 2000 || long >= 3800) return '4K';\n if (short >= 1400 || long >= 2500) return '2K';\n if (short >= 700 || long >= 1260) return 'HD';\n // HD altı: en yakın standart yükseklik (\"480\", \"360\", \"240\", \"144\") — \"p\" yok, rozet dar kalsın.\n return String(LOW_HEIGHTS.reduce((best, h) => (Math.abs(h - short) < Math.abs(best - short) ? h : best)));\n}\nconst LOW_HEIGHTS = [144, 240, 360, 480, 540, 576];\n\nexport class SettingsMenu {\n readonly el: HTMLDivElement;\n private readonly button: HTMLButtonElement;\n private readonly badge: HTMLSpanElement;\n private readonly quickSlot: HTMLSpanElement;\n /** Paneli en son açan hızlı erişim butonu — aynı butona tekrar basınca kapatmak için. */\n private quickOwner: HTMLButtonElement | null = null;\n private readonly quickObserver: MutationObserver;\n private badgeEnabled = true;\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 // Oynayan görüntünün çözünürlüğüne göre \"HD\" / \"2K\" / \"4K\" / \"8K\" rozeti — ayarlar ikonunun sağ üstünde.\n this.badge = document.createElement('span');\n this.badge.className = 'hp-quality-badge';\n this.badge.setAttribute('part', 'quality-badge');\n this.badge.setAttribute('aria-hidden', 'true');\n this.badge.hidden = true;\n for (const ev of ['resize', 'loadedmetadata', 'emptied']) video.addEventListener(ev, this.updateBadge);\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 // Buton + rozet kendi konumlanmış kutusunda (rozet ona göre köşeye oturur); yanında hızlı erişim butonları,\n // panel ise hepsinin üstünde (sağa hizalı) açılır.\n const buttonWrap = document.createElement('span');\n buttonWrap.className = 'hp:relative hp:flex';\n buttonWrap.appendChild(this.button);\n // Rozet butonun DIŞINDA (kardeş, aynı konumlanmış kapsayıcıda): içinde olsaydı görünen \"HD\" metni butonun adıyla\n // (\"Ayarlar\") çelişirdi (WCAG 2.5.3, axe label-content-name-mismatch). pointer-events: none — tık butona geçer.\n buttonWrap.appendChild(this.badge);\n // Hızlı erişim butonları (ör. açık erişilebilirlik özellikleri) ayarlar butonunun sağında — panel bunların üstünde\n // açılır; aynı kapsayıcıda oldukları için tıklamaları \"menü dışına tıklama\" sayılmaz.\n this.quickSlot = document.createElement('span');\n this.quickSlot.className = 'hp-quick-slot hp:flex hp:items-center hp:gap-1';\n this.quickSlot.hidden = true;\n // Boşken yer kaplamasın (grup aralığı) — buton eklenip çıkarıldıkça.\n this.quickObserver = new MutationObserver(() => {\n this.quickSlot.hidden = this.quickSlot.childElementCount === 0;\n if (this.quickOwner && !this.quickOwner.isConnected) this.quickOwner = null;\n });\n this.quickObserver.observe(this.quickSlot, { childList: true });\n this.el.className = 'hp:relative hp:flex hp:items-center hp:gap-1';\n this.el.append(buttonWrap, this.quickSlot, 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 /**\n * Ayarlar butonunun sağına hızlı erişim butonu ekler; `def` verilen alt menüyü doğrudan açar (aynı butona tekrar\n * basınca kapanır). `parents`: alt menüdeki \"geri\" satırının döneceği üst menüler. Kaldırmak için `btn.remove()`.\n */\n addQuickButton(btn: HTMLButtonElement, getDef: () => SettingsSubmenuDef, getParents: () => SettingsSubmenuDef[] = () => []): void {\n btn.addEventListener('click', (e) => {\n e.stopPropagation();\n const def = getDef();\n if (this.open && this.currentPanel === `custom:${def.key}` && this.quickOwner === btn) {\n this.close();\n return;\n }\n this.openSubmenu(def, getParents());\n this.quickOwner = btn;\n });\n this.quickSlot.appendChild(btn);\n }\n\n /** Menüyü doğrudan bir alt menüde açar (hızlı erişim butonları için). */\n openSubmenu(def: SettingsSubmenuDef, parents: SettingsSubmenuDef[] = []): void {\n if (!this.open) {\n this.open = true;\n this.panel.classList.remove('hp:hidden');\n this.onOpenChange?.(true);\n }\n this.currentPanel = `custom:${def.key}`;\n this.renderSubmenu(def, parents);\n this.fitToPlayer();\n }\n\n /** `options.qualityBadge` — false ise rozet hiç gösterilmez. */\n setQualityBadgeEnabled(enabled: boolean): void {\n this.badgeEnabled = enabled;\n this.updateBadge();\n }\n\n /**\n * Rozet gerçekten oynayan görüntüden okunur (`videoWidth` / `videoHeight`): menüde \"Otomatik\" seçiliyken de ABR'nin\n * o an indirdiği kaliteyi gösterir; MP4, hls.js ve Safari'nin kendi HLS oynatıcısında aynı çalışır. Dikey videoda\n * kısa kenar sayılır (1080×1920 → HD). Ses modu / görüntüsüz kaynakta rozet yok.\n */\n private readonly updateBadge = (): void => {\n const text = this.badgeEnabled ? qualityBadgeText(this.video.videoWidth, this.video.videoHeight) : null;\n this.badge.textContent = text ?? '';\n this.badge.hidden = !text;\n if (text) this.badge.setAttribute('data-quality', text);\n else this.badge.removeAttribute('data-quality');\n this.badge.toggleAttribute('data-low', !!text && /^\\d+$/.test(text));\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 // İnce ses çubuğu (~80 px): menü player'ın içine sığmaz — sayfaya taşarak açılır (yukarı, yer yoksa aşağı).\n if ((this.el.getRootNode() as ShadowRoot).host?.hasAttribute('data-audio-compact')) {\n this.fitToViewport();\n return;\n }\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 private fitToViewport(): void {\n const b = this.button.getBoundingClientRect();\n Object.assign(this.panel.style, { top: '', bottom: '', marginTop: '', marginBottom: '' });\n const content = this.panel.scrollHeight;\n const up = b.top - MENU_GAP_PX - MENU_EDGE_PX;\n const down = window.innerHeight - b.bottom - MENU_GAP_PX - MENU_EDGE_PX;\n const drop = up < Math.min(content, MENU_MAX_HEIGHT_PX) && down > up;\n this.panel.toggleAttribute('data-drop', drop);\n this.panel.style.maxHeight = `${Math.max(MENU_MIN_HEIGHT_PX, Math.min(MENU_MAX_HEIGHT_PX, drop ? down : up))}px`;\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.quickOwner = null;\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 /** İç içe alt menüde geri dönülecek üst menüler (en üstteki = açık olanın bir üstü). */\n private submenuStack: SettingsSubmenuDef[] = [];\n\n private renderSubmenu(def: SettingsSubmenuDef, parents: SettingsSubmenuDef[] = []): void {\n this.submenuStack = parents;\n this.panel.innerHTML = '';\n this.panel.appendChild(\n this.backRow(def.title, () => {\n const parent = parents[parents.length - 1];\n if (parent) this.renderSubmenu(parent, parents.slice(0, -1));\n else this.renderMain();\n })\n );\n for (const item of def.getItems()) {\n const value = item.children ? '<i class=\"hp-icon hp-icon-chevron-left hp-chevron-forward\"></i>' : item.active ? '<i class=\"hp-icon hp-icon-check\"></i>' : '';\n const row = this.row(item.label, item.value !== undefined ? escapeHtml(item.value) + (item.children ? value : '') : value, () => {\n if (item.children) {\n this.renderSubmenu(item.children(), [...parents, def]);\n return;\n }\n item.onSelect();\n if (item.keepOpen) this.renderSubmenu(def, parents);\n else this.close();\n });\n this.panel.appendChild(row);\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 const row = this.row(q.label, q.locked ? LOCK_SVG : active ? '<i class=\"hp-icon hp-icon-check\"></i>' : '', () => {\n q.onSelect();\n this.close();\n });\n if (q.locked) row.setAttribute('data-locked', '');\n this.panel.appendChild(row);\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 for (const ev of ['resize', 'loadedmetadata', 'emptied']) this.video.removeEventListener(ev, this.updateBadge);\n this.panelObserver.disconnect();\n this.quickObserver.disconnect();\n }\n}\n","import { SeekBar, LIVE_EDGE_TOLERANCE_SEC } 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/** 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 /** İnce ses çubuğu (audio.layout: 'compact'): dar ekranda da tek satır — üst bar yok. */\n private forceInline = false;\n /** İnce ses çubuğunda başlık / sanatçı (+ çalarken ekolayzır) — boşluk elemanının içinde. */\n private barMetaEl: HTMLDivElement | null = null;\n private spacerEl!: HTMLDivElement;\n private readonly resizeObserver: ResizeObserver;\n private readonly liveBadge: HTMLButtonElement;\n private readonly liveText: HTMLSpanElement;\n private adMode = false;\n private hideLiveSeekBar = 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 // Canlıda seek bar'ın sağ ucu = canlı rozetinin ölçtüğü hedef (hls.js'in canlı konumu).\n this.seekBar.liveTarget = () => this.callbacks.liveSyncPosition?.() ?? null;\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: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 hp:min-w-0';\n row.appendChild(spacer);\n this.spacerEl = 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 = !this.forceInline && 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 /**\n * İnce ses çubuğu: başlık / sanatçı kontrol satırının ortasında; dar ekranda da kompakt (üst bar) düzene geçilmez.\n * `null` kaldırır.\n */\n setAudioBar(meta: { title: string; subtitle: string } | null): void {\n this.forceInline = !!meta;\n if (meta) {\n if (!this.barMetaEl) {\n const el = document.createElement('div');\n el.className = 'hp-bar-meta';\n el.setAttribute('part', 'audio-bar-meta');\n el.innerHTML =\n '<span class=\"hp-bar-eq\" aria-hidden=\"true\"><i></i><i></i><i></i></span>' +\n '<span class=\"hp-bar-text\"><span class=\"hp-bar-title\"></span><span class=\"hp-bar-sub\"></span></span>';\n this.spacerEl.appendChild(el);\n this.barMetaEl = el;\n }\n this.barMetaEl.querySelector('.hp-bar-title')!.textContent = meta.title;\n this.barMetaEl.querySelector('.hp-bar-sub')!.textContent = meta.subtitle;\n this.barMetaEl.toggleAttribute('data-empty', !meta.title && !meta.subtitle);\n } else {\n this.barMetaEl?.remove();\n this.barMetaEl = null;\n }\n this.renderPlayState();\n this.updateLayout();\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.applySeekBarVisibility();\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 this.barMetaEl?.toggleAttribute('data-playing', !paused && !this.callbacks.isAdActive());\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 /** `options.liveSeekBar: false` — canlı yayında ilerleme çubuğu gizlenir. */\n setLiveSeekBar(show: boolean): void {\n this.hideLiveSeekBar = !show;\n this.applySeekBarVisibility();\n }\n\n /** Reklamda ve (istenirse) canlı yayında seek bar gizli. */\n private applySeekBarVisibility(): void {\n const hidden = this.adMode || (this.hideLiveSeekBar && this.video.duration === Infinity);\n this.seekBar.el.style.display = hidden ? 'none' : '';\n }\n\n private readonly renderTime = (): void => {\n const isLive = this.video.duration === Infinity;\n this.applySeekBarVisibility();\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","import { vodSeekTarget } from '../utils/seek-by';\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 = vodSeekTarget(this.video, 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-loading-spinner 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';\nimport { isAudioOutputError } from '../utils/media-error';\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 /** Ekran gerçekten açıldı (hp:error için) — kurtarılan hatalarda (yedek kaynak, native → hls.js) çağrılmaz. */\n private onShown: ((info: { code: number; message: string }) => 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 setOnShown(fn: (info: { code: number; message: string }) => void): void {\n this.onShown = fn;\n }\n\n private open(): void {\n const wasVisible = this.visible;\n this.render();\n this.el.setAttribute('data-visible', '');\n if (!wasVisible) this.onShown?.({ code: this.video.error?.code ?? this.streamErrorCode, message: this.messageEl.textContent ?? '' });\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.open();\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 // Ses aygıtı yok: video oynamaya devam ediyor — oynayan videonun üstünü hata ekranıyla kapatma.\n if (isAudioOutputError(this.video.error)) return;\n if (!this.shouldShow()) return;\n this.open();\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","/** adTaxonomy.keyValues → GAM cust_params (key=value, & ile; virgül GAM'de aynı key'in çoklu değer ayracı). */\nfunction buildAdTaxonomyKeyValues(): string {\n const w = window as unknown as { adTaxonomy?: { keyValues?: Record<string, unknown> } };\n const kv = w.adTaxonomy?.keyValues;\n if (!kv || typeof kv !== 'object') return '';\n\n const pairs: string[] = [];\n for (const [key, value] of Object.entries(kv)) {\n if (value === undefined || value === null || value === '') continue;\n pairs.push(`${key}=${value}`);\n }\n return pairs.join('&');\n}\n\nexport interface GenerateVastUrlOptions {\n adRefreshCount?: number;\n /** true ise cust_params'a adrefreshCount eklenir (adsRetry.enabled ile aynı anlam). */\n includeRefreshCount?: boolean;\n}\n\n/** [referrer_url]/[description_url]/[timestamp] placeholder'larını doldurur, cust_params'a adrefreshCount + adTaxonomy ekler. */\nexport function generateVastUrl(baseUrl: string, options: GenerateVastUrlOptions = {}): string {\n const referrerUrl = encodeURIComponent(document.referrer || window.location.href);\n const descriptionUrl = encodeURIComponent(window.location.href);\n const timestamp = Date.now();\n\n let url = baseUrl;\n const params: Record<string, string | number> = {\n referrer_url: referrerUrl,\n description_url: descriptionUrl,\n timestamp,\n };\n\n for (const [key, value] of Object.entries(params)) {\n const placeholder = `[${key}]`;\n if (url.includes(placeholder)) {\n url = url.replace(placeholder, String(value));\n } else if (!new URLSearchParams(url.split('?')[1]).has(key)) {\n const delimiter = url.includes('?') ? '&' : '?';\n url += `${delimiter}${key}=${value}`;\n }\n }\n\n try {\n const parsedUrl = new URL(url);\n const isVmap = parsedUrl.pathname.includes('/vmap/');\n if (isVmap) return baseUrl;\n\n const extras: string[] = [];\n if (options.includeRefreshCount) extras.push(`adrefreshCount=${options.adRefreshCount ?? 0}`);\n const taxonomyKeyValues = buildAdTaxonomyKeyValues();\n if (taxonomyKeyValues) extras.push(taxonomyKeyValues);\n\n if (extras.length) {\n const custParams = parsedUrl.searchParams.get('cust_params');\n parsedUrl.searchParams.set('cust_params', custParams ? `${custParams}&${extras.join('&')}` : extras.join('&'));\n }\n\n return parsedUrl.toString();\n } catch {\n return url;\n }\n}\n\ntype CustValue = string | number | boolean | Array<string | number>;\n\n/** `{ k: 'v', etiket: ['a','b'] }` ya da `\"k=v&etiket=a,b\"` → anahtar → değer(ler). Boş değerler atılır. */\nexport function toCustRecord(raw: Record<string, CustValue> | string | undefined): Record<string, string[]> {\n const out: Record<string, string[]> = {};\n if (!raw) return out;\n const entries: Array<[string, unknown]> =\n typeof raw === 'string' ? [...new URLSearchParams(raw.trim().replace(/^\\?/, '')).entries()].map(([k, v]) => [k, v.split(',')]) : Object.entries(raw);\n for (const [k, v] of entries) {\n const list = (Array.isArray(v) ? v : [v]).filter((x) => x !== undefined && x !== null && x !== '').map(String);\n if (k && list.length) out[k] = list;\n }\n return out;\n}\n\n/**\n * Ek key-value'ları tag'in `cust_params`'ına ekler — aynı anahtar varsa eklenen kazanır. `hb_` ile başlayan anahtarlar\n * Prebid'in hedeflemesidir (hb_pb, hb_uuid…), dışarıdan ezilmesin diye atlanır. GAM'in beklediği gibi anahtar ve değer\n * ayrı ayrı kodlanır, birden çok değer virgülle ayrılır.\n */\nexport function mergeCustParams(url: string, extra: Record<string, CustValue> | string | undefined): string {\n const pairs = Object.entries(toCustRecord(extra))\n .filter(([k]) => !k.startsWith('hb_'))\n .map(([k, list]) => `${encodeURIComponent(k)}=${list.map(encodeURIComponent).join(',')}`);\n if (!pairs.length) return url;\n try {\n const parsed = new URL(url);\n const keys = new Set(pairs.map((p) => p.slice(0, p.indexOf('='))));\n const existing = (parsed.searchParams.get('cust_params') ?? '').split('&').filter((p) => p && !keys.has(p.split('=')[0]!));\n parsed.searchParams.set('cust_params', [...existing, ...pairs].join('&'));\n return parsed.toString();\n } catch {\n return url;\n }\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 rewardedButton: '{quality} kilidini aç',\n rewardedTitle: '{quality} kalitesini aç',\n rewardedBody: 'Kısa bir reklam izleyin, {quality} kalitesi {duration} açık kalsın. Vazgeçerseniz video şu anki kalitede devam eder.',\n rewardedWatch: 'Reklamı izle',\n rewardedDecline: 'Vazgeç',\n rewardedLoading: 'Reklam hazırlanıyor…',\n rewardedNoFill: 'Şu an gösterilecek reklam yok. Biraz sonra tekrar deneyin.',\n rewardedOk: 'Tamam',\n rewardedUnlocked: '{quality} açıldı',\n rewardedUnlockedNoAd: 'Şu an reklam yoktu — {quality} yine de açıldı',\n rewardedForVideo: 'bu video boyunca',\n rewardedForSession: 'bu oturum boyunca',\n rewardedForMinutes: '{n} dakika boyunca',\n sponsorPresents: '{name} sunar',\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 redirectUpNext: 'Sıradaki',\n redirectCancelCard: 'Sıradakini iptal et',\n skipIntro: 'İntroyu atla',\n skipRecap: 'Özeti atla',\n skipCredits: 'Jeneriği atla',\n skipSegment: 'Atla',\n a11yMenu: 'Erişilebilirlik',\n a11yZoom: 'Yakınlaştırma',\n a11yFilter: 'Görüntü filtresi',\n a11yFilterNone: 'Doğal',\n a11yFilterGrayscale: 'Siyah-beyaz',\n a11yFilterDaylight: 'Gün ışığı',\n a11yFilterNight: 'Gece ışığı',\n a11yFilterContrast: 'Yüksek kontrast',\n a11yFilterProtanopia: 'Kırmızı körlüğü',\n a11yFilterDeuteranopia: 'Yeşil körlüğü',\n a11yFilterTritanopia: 'Mavi körlüğü',\n a11yMono: 'Mono ses',\n a11yBoost: 'Ses güçlendirme',\n a11yLargeControls: 'Büyük kontroller',\n a11yShortcuts: 'Klavye kısayolları',\n a11yOn: 'Açık',\n a11yOff: 'Kapalı',\n a11yUnavailable: 'Kullanılamaz',\n a11yZoomReset: 'Yakınlaştırmayı sıfırla',\n a11yClose: 'Kapat',\n a11yKeyPlay: 'Oynat / duraklat',\n a11yKeySeek: (seconds) => `${seconds} sn geri / ileri`,\n a11yKeyVolume: 'Sesi aç / kıs',\n a11yKeyMute: 'Sesi kapat / aç',\n a11yKeyFullscreen: 'Tam ekran',\n a11yKeyZoom: 'Yakınlaştır / uzaklaştır, sıfırla',\n a11yKeyPan: 'Yakınlaştırılmış görüntüde gezin',\n a11yKeyShortcuts: 'Bu listeyi aç / kapat',\n historyResumed: (time) => `Kaldığınız yerden devam: ${time}`,\n historyRestart: 'Baştan başla',\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 adTriggerLabel: 'Reklam',\n castButton: \"TV'ye yayınla\",\n airplayButton: 'AirPlay',\n castPlayingOn: '{device} cihazında oynatılıyor',\n castDeviceFallback: 'TV',\n castAdOnTv: \"TV'de reklam oynatılıyor\",\n airplayPlaying: 'AirPlay ile oynatılıyor',\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 rewardedButton: 'Unlock {quality}',\n rewardedTitle: 'Unlock {quality}',\n rewardedBody: 'Watch a short ad to keep {quality} unlocked {duration}. If you skip it, the video keeps playing at the current quality.',\n rewardedWatch: 'Watch ad',\n rewardedDecline: 'No thanks',\n rewardedLoading: 'Loading ad…',\n rewardedNoFill: 'No ad is available right now. Please try again in a moment.',\n rewardedOk: 'OK',\n rewardedUnlocked: '{quality} unlocked',\n rewardedUnlockedNoAd: 'No ad right now — {quality} unlocked anyway',\n rewardedForVideo: 'for this video',\n rewardedForSession: 'for this session',\n rewardedForMinutes: 'for {n} minutes',\n sponsorPresents: 'Presented by {name}',\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 redirectUpNext: 'Up next',\n redirectCancelCard: 'Cancel up next',\n skipIntro: 'Skip intro',\n skipRecap: 'Skip recap',\n skipCredits: 'Skip credits',\n skipSegment: 'Skip',\n a11yMenu: 'Accessibility',\n a11yZoom: 'Zoom',\n a11yFilter: 'Picture filter',\n a11yFilterNone: 'Natural',\n a11yFilterGrayscale: 'Black and white',\n a11yFilterDaylight: 'Daylight',\n a11yFilterNight: 'Night light',\n a11yFilterContrast: 'High contrast',\n a11yFilterProtanopia: 'Red-blind',\n a11yFilterDeuteranopia: 'Green-blind',\n a11yFilterTritanopia: 'Blue-blind',\n a11yMono: 'Mono audio',\n a11yBoost: 'Volume boost',\n a11yLargeControls: 'Large controls',\n a11yShortcuts: 'Keyboard shortcuts',\n a11yOn: 'On',\n a11yOff: 'Off',\n a11yUnavailable: 'Unavailable',\n a11yZoomReset: 'Reset zoom',\n a11yClose: 'Close',\n a11yKeyPlay: 'Play / pause',\n a11yKeySeek: (seconds) => `Back / forward ${seconds} s`,\n a11yKeyVolume: 'Volume up / down',\n a11yKeyMute: 'Mute / unmute',\n a11yKeyFullscreen: 'Fullscreen',\n a11yKeyZoom: 'Zoom in / out, reset',\n a11yKeyPan: 'Move around the zoomed picture',\n a11yKeyShortcuts: 'Open / close this list',\n historyResumed: (time) => `Resumed at ${time}`,\n historyRestart: 'Start over',\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 adTriggerLabel: 'Advertisement',\n castButton: 'Cast to TV',\n airplayButton: 'AirPlay',\n castPlayingOn: 'Playing on {device}',\n castDeviceFallback: 'TV',\n castAdOnTv: 'An ad is playing on the TV',\n airplayPlaying: 'Playing via AirPlay',\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 { HopeSourceOption, AdsOptions, HopePlayerOptions } from './types';\nimport type Hls from 'hls.js';\nimport { SourceManager, type HlsQualityLevel, type PlaybackEngineInfo, type StreamAudioTrack, type StreamTextTrack } from './hls/SourceManager';\nimport { cannotPlay, groupSources, sourceFormat, type SourceGroup } from './hls/sourceGroups';\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 { isAudioOutputError } from './utils/media-error';\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 { SkipSegments } from './plugins/skip-segments';\nimport type { Accessibility } from './plugins/accessibility';\nimport type { PlaybackHistory } from './plugins/history';\nimport type { QrResume } from './plugins/qr-resume';\nimport type { PauseAd } from './plugins/pause-ad';\nimport type { AdTriggers } from './plugins/ad-triggers';\nimport type { CastController, CastMedia } from './plugins/cast';\nimport { generateVastUrl, mergeCustParams, toCustRecord } from './plugins/ads/generateVastUrl';\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\n/** Cast receiver'ın beklediği MIME türleri (biçim → tür). */\nconst CAST_MIME: Record<string, string> = {\n hls: 'application/x-mpegurl',\n mp4: 'video/mp4',\n webm: 'video/webm',\n mp3: 'audio/mpeg',\n m4a: 'audio/mp4',\n aac: 'audio/aac',\n ogg: 'audio/ogg',\n wav: 'audio/wav',\n flac: 'audio/flac',\n};\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 /** Kalite kilidi (rewardedUnlock eklentisi) — kilitliyse yüksek kaliteler menüde kilitli, HLS'te üst sınır var. */\n private qualityGate: { isLocked(height: number | null): boolean; requestUnlock(): void } | null = null;\n private rewardedUnlock: import('./plugins/rewarded').RewardedUnlock | null = null;\n private sponsorship: import('./plugins/sponsorship').SponsorshipLayer | null = null;\n /** Son uygulanan MP4 kaynak listesi ve seçili etiket — kilit açılınca menü yeniden kurulur. */\n /** Çalan biçim grubunun kaynakları (kalite menüsü bunlar) — bkz. `sourceGroups`. */\n private currentSources: HopeSourceOption[] = [];\n /** `sources` biçime göre gruplu, `sourcePriority` sırasıyla; ölümcül hatada sıradakine geçilir. */\n private sourceGroups: SourceGroup[] = [];\n private activeGroup = 0;\n /** Sıradaki gruba geçiş başladı — aynı arızanın ikinci hata olayı hata ekranı açmasın. */\n private fallbackPending = false;\n /** hls.js ölümcül hatasının MediaError karşılığı (video.error oluşmaz) — hp:sourcefallback detayı için. */\n private streamErrorCode: number | undefined;\n private activeSourceLabel = '';\n private lastHlsLevels: HlsQualityLevel[] = [];\n private lastHlsActive = -1;\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 redirectKey = '';\n private skipSegments: SkipSegments | null = null;\n private skipSegmentsKey = '';\n private accessibility: Accessibility | null = null;\n private accessibilityKey = '';\n private playbackHistory: PlaybackHistory | null = null;\n private historyKey = '';\n private qrResume: QrResume | null = null;\n private pauseAd: PauseAd | null = null;\n private adTriggers: AdTriggers | null = null;\n private castController: CastController | null = null;\n /** İçerik Chromecast'te oynuyor (player kumanda) — yerel reklam / otomatik oynatma devre dışı. */\n private casting = false;\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.retrySource());\n // hp:error yalnızca kullanıcı hatayı gerçekten görünce — kurtarılan hatalar (yedek kaynak, native → hls.js) sayılmaz.\n this.errorScreen.setOnShown(({ code, message }) => this.dispatchEvent(new CustomEvent('hp:error', { detail: { message, code } })));\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) => {\n const code = kind === 'network' ? 2 : 3;\n this.streamErrorCode = code;\n this.errorScreen.showStreamError(code);\n },\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 // Her ölümcül hata (video.error ve hls.js) buradan geçer: sıradaki biçim grubuna geçilecekse ekran açılmaz.\n this.errorScreen.setShouldShow(() => !this.sourceManager.isRecovering() && !this.tryNextSourceGroup());\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 // `tabindex` verilmemişse 0 — `this.tabIndex || 0` YAZILMAMALI: attribute'suz öğede tabIndex -1 döner (truthy),\n // host -1 kalır ve negatif tabindex'li shadow host'un içi Tab sırasından tamamen çıkar (kontrollere klavyeyle\n // ulaşılamıyordu). Sayfanın kendi verdiği değere (ör. -1) dokunulmaz.\n if (!this.hasAttribute('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.videoEl.addEventListener('ended', this.onEnded);\n this.videoEl.addEventListener('ratechange', this.onRateChange);\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 // Bir mikro görev sonra: `import '@hopeplayer/core'` element'i senkron upgrade ediyor — hemen ardından\n // `addEventListener('hp:ready', …)` ekleyen sayfa (README örneği) olayı eskiden kaçırıyordu. Önceden bağlanan\n // dinleyiciler (React / Vue wrapper'ları) olayı yine alır.\n queueMicrotask(() => {\n if (this.isConnected) this.dispatchEvent(new CustomEvent('hp:ready'));\n });\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.videoEl.removeEventListener('ended', this.onEnded);\n this.videoEl.removeEventListener('ratechange', this.onRateChange);\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.rewardedUnlock?.destroy();\n this.rewardedUnlock = null;\n this.sponsorship?.destroy();\n this.sponsorship = null;\n this.adTriggers?.destroy();\n this.adTriggers = null;\n this.castController?.destroy();\n this.castController = 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.skipSegments?.destroy();\n this.skipSegments = null;\n this.skipSegmentsKey = '';\n this.accessibility?.destroy();\n this.accessibility = null;\n this.accessibilityKey = '';\n this.playbackHistory?.destroy();\n this.playbackHistory = null;\n this.historyKey = '';\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 // Ses aygıtı yok (Firefox): video sessiz oynamaya devam ediyor — kayda düşer ama ölümcül değil.\n fatal: !isAudioOutputError(err),\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 /**\n * Açık reklam tetikleyici reklamını kapat (adTriggers). `layout: 'none'` kreatifleri kendi kodlarından çağırabilir:\n * `window.top.document.querySelector('hope-player').closeAdTrigger()`.\n */\n closeAdTrigger(): void {\n this.adTriggers?.close('user');\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 // Cast sırasında yerel video kendiliğinden çalmasın (kaynak değişse bile) — CastController dönüşte geri yükler.\n if (!this.casting) 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 this.controlBar.settingsMenu.setQualityBadgeEnabled(options.qualityBadge !== false);\n this.controlBar.setLiveSeekBar(options.liveSeekBar !== false);\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.skipSegments?.refreshLabels();\n this.accessibility?.refreshLabels();\n this.playbackHistory?.refreshLabels();\n this.qrResume?.refreshLabels();\n this.pauseAd?.refreshLabels();\n this.castController?.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.rewardedUnlock?.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 await this.applyRewardedUnlock(options);\n\n const all: HopeSourceOption[] = options.sources?.length ? options.sources : options.src ? [{ src: options.src, label: this.i18n.autoQuality }] : [];\n this.sourceGroups = groupSources(all, options.sourcePriority);\n // O an yüklü kaynak listede varsa (ve kilitli değilse) korunur: seçenekler yeniden uygulanınca (ör. React prop)\n // kullanıcının seçtiği kalite `selected` olana geri dönmesin — yedek gruba düşülmüşse o grupta kalınır.\n const isLive = (s: HopeSourceOption): boolean => this.sourceManager.isLoaded(s.src, s.type) && !this.isSourceLocked(s);\n const loadedGroup = this.sourceGroups.findIndex((g) => g.sources.some(isLive));\n this.activeGroup = loadedGroup !== -1 ? loadedGroup : this.firstPlayableGroup();\n const sources = this.sourceGroups[this.activeGroup]?.sources ?? [];\n this.currentSources = sources;\n this.fallbackPending = false;\n const loaded = sources.find(isLive);\n const initial = loaded ?? this.pickInitialSource(sources);\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 (initial) this.activeSourceLabel = initial.label;\n this.renderSourceQualities();\n\n await this.installAdsOnce(options);\n await this.applySponsorship(options);\n await this.applyAdTriggers(options);\n await this.applyCast(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() || this.casting },\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 // Ayar değişince (ör. playlist'te sıradaki video, mode) yeniden kurulur — eski kart / ekran kalmasın.\n const redirectKey = options.redirectScreen ? JSON.stringify(options.redirectScreen) : '';\n if (redirectKey !== this.redirectKey) {\n this.redirectKey = redirectKey;\n this.redirectScreen?.destroy();\n this.redirectScreen = null;\n if (options.redirectScreen) {\n const { installRedirectScreen } = await import('./plugins/redirect-screen');\n this.redirectScreen = installRedirectScreen(\n { hostEl: this, videoEl: this.videoEl, overlayContainerEl: this.videoArea, isAdActive: () => this.isAdPlaying(), i18n: this.i18n },\n options.redirectScreen\n );\n }\n }\n\n // Erişilebilirlik alt menüsü — ayar değişince yeniden kurulur (izleyicinin seçimleri localStorage'dan geri gelir).\n const a11yKey = options.accessibility ? JSON.stringify(options.accessibility) : '';\n if (a11yKey !== this.accessibilityKey) {\n this.accessibilityKey = a11yKey;\n this.accessibility?.destroy();\n this.accessibility = null;\n if (options.accessibility) {\n const { installAccessibility } = await import('./plugins/accessibility');\n if (this.accessibilityKey === a11yKey) {\n this.accessibility = installAccessibility(\n {\n hostEl: this,\n videoEl: this.videoEl,\n videoAreaEl: this.videoArea,\n i18n: this.i18n,\n registerSubmenu: (def) => this.controlBar.settingsMenu.registerSubmenu(def),\n unregisterSubmenu: (key) => this.controlBar.settingsMenu.unregisterSubmenu(key),\n addQuickButton: (btn, getDef, getParents) => this.controlBar.settingsMenu.addQuickButton(btn, getDef, getParents),\n seekStep: () => this.keyboard.seekStep,\n },\n options.accessibility === true ? {} : options.accessibility\n );\n }\n }\n }\n // Bölümler her içerikte farklı (playlist'te sıradaki bölüm) — değişince yeniden kurulur.\n const skipKey = options.skipSegments?.length ? JSON.stringify(options.skipSegments) : '';\n if (skipKey !== this.skipSegmentsKey) {\n this.skipSegmentsKey = skipKey;\n this.skipSegments?.destroy();\n this.skipSegments = null;\n if (options.skipSegments?.length) {\n const { installSkipSegments } = await import('./plugins/skip-segments');\n if (this.skipSegmentsKey === skipKey) {\n this.skipSegments = installSkipSegments(\n { hostEl: this, videoEl: this.videoEl, overlayContainerEl: this.videoArea, isAdActive: () => this.isAdPlaying(), i18n: this.i18n },\n options.skipSegments\n );\n }\n }\n }\n\n // Zaman ve ses geçmişi — QR ile devamdan (?vtime=) ÖNCE kurulur: o parametreyi uygulayıp adresten siliyor; link\n // ile gelen konum bu açılışta kayıtlı konumu ezer.\n const historyKey = options.history ? JSON.stringify(options.history) : '';\n if (historyKey !== this.historyKey) {\n this.historyKey = historyKey;\n this.playbackHistory?.destroy();\n this.playbackHistory = null;\n if (options.history) {\n const qrParam = options.qrResume ? (options.qrResume.paramName ?? 'vtime') : null;\n const linkTimePresent = !!qrParam && new URL(location.href).searchParams.has(qrParam);\n const { installHistory } = await import('./plugins/history');\n if (this.historyKey === historyKey) {\n this.playbackHistory = installHistory(\n {\n hostEl: this,\n videoEl: this.videoEl,\n overlayContainerEl: this.videoArea,\n i18n: this.i18n,\n currentSrc: () => this.sourceManager.currentSrc,\n isAdActive: () => this.isAdPlaying(),\n mutedRequested: () => !!this._options.muted,\n linkTimePresent,\n },\n options.history === true ? {} : options.history\n );\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 kilidi (ödüllü reklam) ─────────────────────────────────────\n\n /** Kaynağın yüksekliği: `height` ya da etiketten (\"1080p\" → 1080); bilinmiyorsa null. */\n private sourceHeight(s: HopeSourceOption): number | null {\n if (typeof s.height === 'number' && s.height > 0) return s.height;\n const m = /(\\d{3,4})\\s*p\\b/i.exec(s.label);\n return m ? Number(m[1]) : null;\n }\n\n private isSourceLocked(s: HopeSourceOption): boolean {\n return !!this.qualityGate?.isLocked(this.sourceHeight(s));\n }\n\n /** Başlangıç kaynağı: `selected` (ya da ilk); kilitliyse serbest kaynakların en yükseği. */\n private pickInitialSource(sources: HopeSourceOption[]): HopeSourceOption | undefined {\n const preferred = sources.find((s) => s.selected) ?? sources[0];\n if (!preferred || !this.isSourceLocked(preferred)) return preferred;\n const free = sources.filter((s) => !this.isSourceLocked(s));\n if (!free.length) return preferred;\n return free.reduce((a, b) => ((this.sourceHeight(b) ?? 0) > (this.sourceHeight(a) ?? 0) ? b : a));\n }\n\n private renderSourceQualities(): void {\n const sources = this.currentSources;\n if (sources.length <= 1) return;\n this.controlBar.setQualities(\n sources.map((s) => {\n const locked = this.isSourceLocked(s);\n return {\n label: s.label,\n locked,\n onSelect: locked ? () => this.qualityGate?.requestUnlock() : () => void this.switchQualitySource(s),\n };\n }),\n this.activeSourceLabel || sources[0]!.label\n );\n }\n\n /** Kilitli kalite var mı (ödüllü reklam butonu yalnızca o zaman görünür) ve en yükseğinin etiketi. */\n lockedQualityLabel(): string | null {\n if (!this.qualityGate) return null;\n const heights: number[] = [];\n if (this.lastHlsLevels.length > 1) {\n for (const l of this.lastHlsLevels) if (this.qualityGate.isLocked(l.height)) heights.push(l.height);\n } else {\n for (const s of this.currentSources) {\n const h = this.sourceHeight(s);\n if (this.currentSources.length > 1 && this.qualityGate.isLocked(h)) heights.push(h ?? 0);\n }\n }\n if (!heights.length) return null;\n return `${Math.max(...heights)}p`;\n }\n\n /** Kilit durumu değişti: menüleri yeniden kur, HLS üst sınırını güncelle; `upgrade` ise en iyi kaliteye geç. */\n private refreshQualityGate(upgrade: boolean): void {\n if (this.lastHlsLevels.length > 1) {\n this.onHlsLevelsChanged(this.lastHlsLevels, upgrade ? -1 : this.lastHlsActive);\n if (upgrade) this.sourceManager.setLevel(-1);\n } else if (this.currentSources.length > 1) {\n const best = upgrade\n ? this.currentSources\n .filter((s) => !this.isSourceLocked(s))\n .reduce<HopeSourceOption | null>((a, b) => (!a || (this.sourceHeight(b) ?? 0) > (this.sourceHeight(a) ?? 0) ? b : a), null)\n : null;\n const active = this.currentSources.find((s) => s.label === this.activeSourceLabel);\n // Kilit geri geldi ve şu an kilitli bir kalitedeysek serbest olanın en yükseğine in.\n const target = best ?? (active && this.isSourceLocked(active) ? this.pickInitialSource(this.currentSources) : null);\n if (target && target.label !== this.activeSourceLabel) void this.switchQualitySource(target);\n else this.renderSourceQualities();\n }\n this.rewardedUnlock?.onQualitiesChanged();\n }\n\n private async applyRewardedUnlock(options: HopePlayerOptions): Promise<void> {\n const opts = options.rewardedUnlock;\n if (!opts) {\n if (this.rewardedUnlock) {\n this.rewardedUnlock.destroy();\n this.rewardedUnlock = null;\n this.qualityGate = null;\n this.refreshQualityGate(false);\n }\n return;\n }\n if (!this.rewardedUnlock) {\n const { installRewardedUnlock } = await import('./plugins/rewarded');\n this.rewardedUnlock ??= installRewardedUnlock(\n {\n hostEl: this,\n videoEl: this.videoEl,\n overlayEl: this.videoArea,\n chromeEl: this.chromeEl,\n i18n: this.i18n,\n log: (entry) => this.log.add({ source: 'ads', ...entry }),\n play: () => void this.play().catch(() => {}),\n exitFullscreen: () => {\n if (this.isFullscreenActive()) this.exitFullscreenCompat();\n },\n lockedQualityLabel: () => this.lockedQualityLabel(),\n // Kalite dosyası değil içerik: aynı videonun 240p ↔ 720p geçişi (ya da HLS → MP4 yedeği) kilidi kapatmasın.\n contentKey: () => this.contentKey(),\n onLockChange: (upgrade) => this.refreshQualityGate(upgrade),\n },\n opts\n );\n this.qualityGate = this.rewardedUnlock;\n } else {\n this.rewardedUnlock.update(opts);\n }\n }\n\n /**\n * İçerik kimliği: `sources` çalıyorsa tüm kaynakları (kalite değişimi / yedek kaynak aynı içerik), eklentinin\n * yüklediği medya (playlist, hikâye, dublaj) çalıyorsa onun adresi.\n */\n private contentKey(): string {\n const all = this.sourceGroups.flatMap((g) => g.sources.map((s) => s.src));\n const current = this.sourceManager.currentSrc ?? '';\n return !current || all.includes(current) ? all.join('|') : current;\n }\n\n private async applyCast(options: HopePlayerOptions): Promise<void> {\n const opts = options.cast;\n if (!opts?.chromecast && !opts?.airplay && !opts?.remotePlayback) {\n this.castController?.destroy();\n this.castController = null;\n return;\n }\n if (!this.castController) {\n const { installCast } = await import('./plugins/cast');\n this.castController ??= installCast(\n {\n hostEl: this,\n videoEl: this.videoEl,\n overlayEl: this.videoArea,\n i18n: this.i18n,\n log: (entry) => this.log.add({ source: 'player', ...entry }),\n addButton: (label, icon, onClick) => this.controlBar.addButton(label, icon, onClick),\n getMedia: () => this.castMedia(),\n isAdPlaying: () => this.isAdPlaying(),\n isMse: () => this.sourceManager.engine.engine === 'hls.js',\n contentKey: () => this.contentKey(),\n onRemoteChange: (remote) => {\n this.casting = remote;\n this.adsController?.setRemote(remote);\n if (remote) this.prerollGate.release(false);\n },\n },\n opts\n );\n } else {\n this.castController.update(opts);\n }\n }\n\n /** TV'ye gönderilecek içerik: o an çalan kaynak (ya da `cast.source`), başlık / kapak, altyazılar, reklam tag'leri. */\n private castMedia(): CastMedia | null {\n const o = this._options;\n const c = o.cast ?? {};\n const currentSrc = this.sourceManager.currentSrc;\n if (!currentSrc) return null;\n const currentType = this.currentSources.find((s) => s.src === currentSrc)?.type;\n const picked = typeof c.source === 'function' ? c.source({ src: currentSrc, type: currentType }) : (c.source ?? { src: currentSrc, type: currentType });\n const source = typeof picked === 'string' ? { src: picked, type: undefined } : picked;\n const abs = (u: string): string => new URL(u, document.baseURI).href;\n const format = sourceFormat({ src: source.src, type: source.type, label: '' });\n const audio = typeof o.audio === 'object' ? o.audio : null;\n const image = c.metadata?.image ?? audio?.cover ?? o.poster;\n const adsOpts = typeof o.ads === 'object' ? o.ads : null;\n // TV de aynı GAM birimini ister — Prebid custParams'ı (preroll / midroll) TV tag'lerine de eklenir.\n const prebid = adsOpts?.prebid;\n const preCust = prebid?.custParams;\n const midCust = prebid ? { ...toCustRecord(prebid.custParams), ...toCustRecord(prebid.midroll?.custParams) } : undefined;\n const tag = (t: string | string[] | undefined, cust?: Parameters<typeof mergeCustParams>[1]): string | undefined => {\n const first = Array.isArray(t) ? t[0] : t;\n return first ? mergeCustParams(generateVastUrl(first), cust) : undefined;\n };\n const ads =\n c.ads === false\n ? null\n : typeof c.ads === 'object'\n ? {\n vmap: c.ads.vmap ? generateVastUrl(c.ads.vmap) : undefined,\n preroll: tag(c.ads.preroll),\n midroll: tag(c.ads.midroll),\n midrollIntervalSeconds: c.ads.midrollIntervalSeconds,\n postroll: tag(c.ads.postroll),\n }\n : adsOpts\n ? {\n vmap: adsOpts.adTagVmap ? generateVastUrl(adsOpts.adTagVmap) : undefined,\n preroll: tag(adsOpts.adTagPreroll, preCust),\n midroll: tag(adsOpts.adTagMidroll, midCust),\n midrollIntervalSeconds: adsOpts.midrollIntervalSeconds,\n postroll: tag(adsOpts.adTagPostroll),\n }\n : null;\n return {\n src: abs(source.src),\n contentType: source.type || CAST_MIME[format] || 'video/mp4',\n live: this.videoEl.duration === Infinity,\n title: c.metadata?.title ?? audio?.title,\n subtitle: c.metadata?.subtitle ?? audio?.artist,\n image: image ? abs(image) : undefined,\n music: !!o.audio,\n subtitles: (o.subtitles ?? []).map((s) => ({ src: abs(s.src), label: s.label, lang: s.srclang, default: s.default })),\n ads: ads && (ads.vmap || ads.preroll || ads.midroll || ads.postroll) ? ads : null,\n };\n }\n\n private async applyAdTriggers(options: HopePlayerOptions): Promise<void> {\n const opts = options.adTriggers;\n if (!opts?.endpoint && !opts?.config) {\n this.adTriggers?.destroy();\n this.adTriggers = null;\n return;\n }\n if (!this.adTriggers) {\n const { installAdTriggers } = await import('./plugins/ad-triggers');\n this.adTriggers ??= installAdTriggers(\n {\n hostEl: this,\n videoEl: this.videoEl,\n overlayEl: this.videoArea,\n i18n: this.i18n,\n log: (entry) => this.log.add({ source: 'ads', ...entry }),\n isBlocked: () => this.isChromeBlocked || this.isAdPlaying() || this.casting,\n isFullscreen: () => this.isFullscreenActive(),\n isNativeFullscreen: () => !!this.iosVideo.webkitDisplayingFullscreen,\n contentKey: () => this.contentKey(),\n },\n opts\n );\n } else {\n this.adTriggers.update(opts);\n }\n }\n\n private async applySponsorship(options: HopePlayerOptions): Promise<void> {\n const opts = options.sponsorship;\n if (!opts?.endpoint) {\n this.sponsorship?.destroy();\n this.sponsorship = null;\n return;\n }\n if (!this.sponsorship) {\n const { installSponsorship } = await import('./plugins/sponsorship');\n this.sponsorship ??= installSponsorship(\n {\n hostEl: this,\n videoEl: this.videoEl,\n overlayEl: this.videoArea,\n i18n: this.i18n,\n log: (entry) => this.log.add({ source: 'player', ...entry }),\n },\n opts\n );\n } else {\n this.sponsorship.update(opts);\n }\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 this.activeSourceLabel = source.label;\n this.renderSourceQualities();\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 /** `from`'dan itibaren tarayıcının oynatabileceği ilk grup (oynatamadıkları atlanır); hiçbiri yoksa -1 (from 0'sa 0 — yine de dene). */\n private firstPlayableGroup(from = 0): number {\n for (let i = from; i < this.sourceGroups.length; i++) {\n const g = this.sourceGroups[i]!;\n if (!cannotPlay(g, this.videoEl)) {\n if (i > from) {\n const skipped = this.sourceGroups[from]!.format;\n this.dispatchEvent(new CustomEvent('hp:sourcefallback', { detail: { from: skipped, to: g.format, code: 4, skipped: true } }));\n }\n return i;\n }\n this.log.add({ source: 'player', message: `Source format \"${g.format}\" is not playable in this browser — skipped`, details: { src: g.sources[0]?.src } });\n }\n return from === 0 ? 0 : -1;\n }\n\n /**\n * Ölümcül hata: sıradaki biçim grubuna geç (konum ve oynatma durumu korunur).\n * true = geçiliyor, hata ekranı gösterilmez. Hata ekranının `shouldShow`'undan çağrılır.\n */\n private tryNextSourceGroup(): boolean {\n if (this.fallbackPending) return true;\n const group = this.sourceGroups[this.activeGroup];\n // Eklentinin yüklediği başka bir medya (playlist, dublaj, hikâye) çalıyorsa gruplara dönülmez.\n if (!group || this.sourceGroups.length < 2 || !group.sources.some((s) => s.src === this.sourceManager.currentSrc)) return false;\n const code = this.videoEl.error?.code ?? this.streamErrorCode;\n this.streamErrorCode = undefined;\n if (code === 1) return false; // MEDIA_ERR_ABORTED: kullanıcı/kaynak değişimi iptali, arıza değil\n const next = this.firstPlayableGroup(this.activeGroup + 1);\n if (next === -1) return false;\n this.fallbackPending = true;\n const resumeTime = Number.isFinite(this.videoEl.duration) ? this.videoEl.currentTime : 0;\n const play = !this.videoEl.paused || !!this._options.autoplay;\n this.log.add({\n source: 'player',\n message: `Source \"${group.format}\" failed — falling back to \"${this.sourceGroups[next]!.format}\"`,\n details: { code, src: this.sourceManager.currentSrc ?? undefined },\n });\n this.dispatchEvent(new CustomEvent('hp:sourcefallback', { detail: { from: group.format, to: this.sourceGroups[next]!.format, code } }));\n // Hata olayının işlenmesi bitsin, sonra yükle (ErrorScreen/ErrorLog dinleyicileri eski kaynağı görsün).\n queueMicrotask(() => void this.activateSourceGroup(next, resumeTime, play));\n return true;\n }\n\n private async activateSourceGroup(index: number, resumeTime: number, play: boolean): Promise<void> {\n const group = this.sourceGroups[index];\n if (!group) return;\n this.activeGroup = index;\n this.currentSources = group.sources;\n const initial = this.pickInitialSource(group.sources)!;\n this.errorScreen.dismiss();\n this.controlBar.setQualities([], '');\n this.hlsQualitiesShown = false;\n this.activeSourceLabel = initial.label;\n if (resumeTime > 0) {\n this.videoEl.addEventListener('loadedmetadata', () => (this.videoEl.currentTime = resumeTime), { once: true });\n }\n try {\n await this.sourceManager.load(initial.src, initial.type);\n } finally {\n this.fallbackPending = false;\n }\n this.renderSourceQualities();\n this.rewardedUnlock?.onQualitiesChanged();\n if (play) this.videoEl.play().catch(() => {});\n }\n\n /** Hata ekranındaki \"Tekrar dene\": birden fazla grup varsa en öncelikli gruptan baştan başla. */\n private async retrySource(): Promise<void> {\n const owned = this.sourceGroups.some((g) => g.sources.some((s) => s.src === this.sourceManager.currentSrc));\n if (this.sourceGroups.length < 2 || !owned) return this.sourceManager.reload();\n const resumeTime = Number.isFinite(this.videoEl.duration) ? this.videoEl.currentTime : 0;\n this.fallbackPending = true;\n await this.activateSourceGroup(this.firstPlayableGroup(), resumeTime, true);\n }\n\n private readonly onHlsLevelsChanged = (levels: HlsQualityLevel[], activeIndex: number): void => {\n this.lastHlsLevels = levels;\n this.lastHlsActive = activeIndex;\n // Kaynak değişince boş liste gelir — önceki HLS kaynağının seviyeleri menüde (ve kilit hesabında) 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 const gate = this.qualityGate;\n const locked = (l: HlsQualityLevel) => !!gate?.isLocked(l.height);\n // Kilit varsa ABR serbest seviyelerin en yükseğinde durur (hepsi kilitliyse en düşükte).\n if (gate) {\n const free = levels.filter((l) => !locked(l));\n const pool = free.length ? free : [levels.reduce((a, b) => (b.height < a.height ? b : a))];\n this.sourceManager.setMaxLevel(pool.reduce((a, b) => (b.height > a.height ? b : a)).index);\n } else {\n this.sourceManager.setMaxLevel(-1);\n }\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) => ({\n label: label(l),\n locked: locked(l),\n onSelect: locked(l) ? () => gate?.requestUnlock() : () => this.sourceManager.setLevel(l.index),\n })),\n ],\n activeIndex === -1 || !levels[activeIndex] ? this.i18n.autoQuality : label(levels[activeIndex]!)\n );\n this.rewardedUnlock?.onQualitiesChanged();\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 onEnded = (): void => {\n this.dispatchEvent(new CustomEvent('hp:ended'));\n };\n\n private readonly onRateChange = (): void => {\n this.dispatchEvent(new CustomEvent('hp:ratechange', { detail: { rate: this.videoEl.playbackRate } }));\n };\n\n private readonly onPointerDownFocus = (): void => {\n // preventScroll: player ekrana tam sığmıyorken focus() sayfayı kaydırıyordu — basılan butonun altından\n // kayan sayfa yüzünden bırakma başka bir kontrole (ör. seek bar) düşüyor, tıklama kayboluyordu.\n this.focus({ preventScroll: true });\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 // Kontrollerin üstüne binmemek için yer değiştiren katmanlar (ör. sponsor logosu) kontroller gizliyken köşeye döner.\n // Host'a değil video alanına: constructor'da da çağrılıyor ve createElement ile oluşturulan custom element\n // constructor'da kendine attribute ekleyemez (NotSupportedError).\n this.videoArea?.toggleAttribute('data-chrome-hidden', !this.chromeVisible);\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 this.toggleAttribute('data-audio-compact', audio?.layout === 'compact');\n if (!audio) {\n this.controlBar.setAudioBar(null);\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 setBarMeta: (meta) => this.controlBar.setAudioBar(meta),\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 HopeSourceOption,\n HopeSourceFormat,\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 RedirectCardPosition,\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 AudioOptions,\n VinylOptions,\n RewardedUnlockOptions,\n RewardedProvider,\n RewardedResult,\n SponsorshipOptions,\n SponsorshipConfig,\n AdTriggersOptions,\n AdTriggersConfig,\n AdTriggerRule,\n AdTrigger,\n AdTriggerLayout,\n AdTriggerCustParams,\n CustParams,\n CastOptions,\n CastSource,\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":["isAudioOutputError","err","hasFatalMediaError","video","prefersNativeHls","ua","iOS","safari","hasMse","w","detectSourceType","src","type","normalizedType","_a","SourceManager","callbacks","__publicField","options","sourceType","engine","canNative","reason","onMeta","cleanup","onError","unsupported","_b","list","report","tracks","t","index","ev","build","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","FILE_MIME","sourceFormat","s","detected","mime","ext","k","m","groupSources","sources","priority","groups","format","g","x","rank","f","p","a","b","cannotPlay","group","formatTime","seconds","totalSeconds","h","mm","ss","END_SEEK_GUARD_SEC","vodSeekTarget","time","seekBy","delta","start","end","MIN_LIVE_WINDOW_SEC","LIVE_EDGE_SAFETY_SEC","LIVE_EDGE_TOLERANCE_SEC","SeekBar","labels","e","tl","ratio","tick","span","toRatio","playedRatio","bufferedEnd","bufferedRatio","c","local","r","track","duration","seekable","seekableEnd","target","key","suppressed","clientX","next","zoneEnd","ch","ranges","container","el","bufferedEl","playedEl","rect","bar","extraClass","marker","createIcon","name","setIconName","WHEEL_VOLUME_STEP","HIDE_DELAY_MS","VolumePanel","adHooks","current","effectiveVolume","label","playing","clientY","LOCK_SVG","MENU_GAP_PX","MENU_EDGE_PX","MENU_MIN_HEIGHT_PX","MENU_MAX_HEIGHT_PX","escapeHtml","qualityBadgeText","width","height","short","long","LOW_HEIGHTS","best","SettingsMenu","playbackRates","text","area","anchor","drop","content","room","buttonWrap","btn","getDef","getParents","def","parents","enabled","activeLabel","appearance","toggle","up","down","value","onClick","title","onBack","parent","item","row","rate","active","q","divider","dot","color","o","grid","opt","swatch","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","behind","sync","edge","leftGroup","ring","ringMask","play","liveDot","spacer","rightGroup","pip","fullscreen","compact","meta","on","isFullscreen","back","forward","render","display","info","pod","show","pending","loading","buffered","hidden","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","wasVisible","code","messages","pools","ownTracks","generations","isPooledTrack","pooledTrack","scope","lang","pool","clearPooledTracks","cue","attachSubtitleTracks","subtitles","clearSubtitleTracks","generation","attached","loadCues","selectSubtitleTrack","trackLabel","isActive","res","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","y","REPEAT_WINDOW_MS","MAX_ENTRIES","ErrorLog","entry","last","details","v","repeat","STYLE_ID","injectIconFont","style","iconFontFaceCss","buildAdTaxonomyKeyValues","kv","pairs","generateVastUrl","baseUrl","referrerUrl","descriptionUrl","timestamp","params","placeholder","delimiter","parsedUrl","extras","taxonomyKeyValues","custParams","toCustRecord","out","entries","mergeCustParams","extra","keys","existing","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","CAST_MIME","TEMPLATE","normalizeAspectRatio","HopePlayerElement","names","native","taken","trackId","hadNative","fromHls","menu","activeIndex","gate","locked","free","point","isTouch","pointer","singleTap","tailwindCss","wrapper","waiting","message","centerChip","single","open","_g","_h","_i","_j","_k","_l","_m","_n","_o","_p","_q","_r","_s","_t","_u","_v","_w","_x","_y","_z","_A","_B","_C","_D","_E","installDebugPanel","force","installStats","attrOptions","attrs","seekStep","skip","adsOptions","gateCtx","installCountdownScreen","installGeoChecker","all","loadedGroup","initial","gestureOptions","installGesture","loopOptions","installLoopSection","inViewOptions","installInViewAutoplay","stickyOptions","installSticky","installPlaylist","tag","installStory","installMarkers","installSegments","installSpriteThumbnails","redirectKey","installRedirectScreen","a11yKey","installAccessibility","skipKey","installSkipSegments","historyKey","qrParam","linkTimePresent","installHistory","installQrResume","qr","installTapGestures","DEFAULT_TAP_GESTURES","installPauseAd","installDubbing","liveWallClockOptions","installLiveWallClock","ms","installDai","selectCaption","suffix","unique","sizes","buildColorOptions","get","set","preferred","heights","upgrade","opts","installRewardedUnlock","installCast","remote","currentSrc","currentType","picked","source","abs","u","image","adsOpts","prebid","preCust","midCust","cust","first","installAdTriggers","installSponsorship","resumeTime","wasPlaying","from","skipped","owned","videoFallback","doc","showing","mode","reset","fullSize","freeBottom","centerY","shift","shiftX","maxCenterX","togglePlay","installAudioStage","installAds","auto","showCenter"],"mappings":"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"}
|