@hopeplayer/core 1.0.16 → 1.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/README.md +24 -14
  2. package/dist/HopePlayerElement.d.ts +1 -0
  3. package/dist/HopePlayerElement.d.ts.map +1 -1
  4. package/dist/chunks/{index-CWLyz1fp.js → adTriggers-4SueRFgK.js} +2 -2
  5. package/dist/chunks/adTriggers-4SueRFgK.js.map +1 -0
  6. package/dist/chunks/{index-DITXYcHx.js → ads-DPL7m9PV.js} +130 -125
  7. package/dist/chunks/ads-DPL7m9PV.js.map +1 -0
  8. package/dist/chunks/{index-BeJNpAyx.js → audio-LkYgd5Wq.js} +7 -7
  9. package/dist/chunks/audio-LkYgd5Wq.js.map +1 -0
  10. package/dist/chunks/{ScratchSound-0XKHUcJK.js → audioScratchSound-7XkwCCDm.js} +1 -1
  11. package/dist/chunks/audioScratchSound-7XkwCCDm.js.map +1 -0
  12. package/dist/chunks/{index-Miba3PD_.js → cast-DCAT2agI.js} +2 -2
  13. package/dist/chunks/cast-DCAT2agI.js.map +1 -0
  14. package/dist/chunks/{index-rENB3n9O.js → countdownScreen-CI-u6jjA.js} +1 -1
  15. package/dist/chunks/countdownScreen-CI-u6jjA.js.map +1 -0
  16. package/dist/chunks/{index-Q8FMOHj0.js → dai-B9Tth1Iv.js} +1 -1
  17. package/dist/chunks/dai-B9Tth1Iv.js.map +1 -0
  18. package/dist/chunks/{index-DCXX1ZJG.js → debugPanel-Bnc_7GOn.js} +1 -1
  19. package/dist/chunks/debugPanel-Bnc_7GOn.js.map +1 -0
  20. package/dist/chunks/{index-DXWK4EFa.js → dubbing-kNMPpyHl.js} +1 -1
  21. package/dist/chunks/dubbing-kNMPpyHl.js.map +1 -0
  22. package/dist/chunks/{index-BBmuCtKu.js → geoChecker-BRtvHwI-.js} +1 -1
  23. package/dist/chunks/geoChecker-BRtvHwI-.js.map +1 -0
  24. package/dist/chunks/{index-Ca8hocby.js → gesture-BzPCgi87.js} +1 -1
  25. package/dist/chunks/gesture-BzPCgi87.js.map +1 -0
  26. package/dist/chunks/{loadGpt-CmiAy366.js → gpt-CGXHTG_H.js} +1 -1
  27. package/dist/chunks/gpt-CGXHTG_H.js.map +1 -0
  28. package/dist/chunks/{index-3QALpwsf.js → inViewAutoplay-CRJe7GA4.js} +1 -1
  29. package/dist/chunks/inViewAutoplay-CRJe7GA4.js.map +1 -0
  30. package/dist/chunks/{index-7IBf8Y-R.js → liveWallClock-ChUTtzLD.js} +1 -1
  31. package/dist/chunks/liveWallClock-ChUTtzLD.js.map +1 -0
  32. package/dist/chunks/{index-f0vSgRIK.js → loopSection-CvF4l5uf.js} +1 -1
  33. package/dist/chunks/loopSection-CvF4l5uf.js.map +1 -0
  34. package/dist/chunks/{index-e00_M05B.js → markers-DE4O8xbw.js} +2 -2
  35. package/dist/chunks/markers-DE4O8xbw.js.map +1 -0
  36. package/dist/chunks/{index-CDPrkLq0.js → pauseAd-BQQe21X4.js} +2 -2
  37. package/dist/chunks/pauseAd-BQQe21X4.js.map +1 -0
  38. package/dist/chunks/{index-DEv3YqLg.js → player-C886oKP-.js} +884 -856
  39. package/dist/chunks/player-C886oKP-.js.map +1 -0
  40. package/dist/chunks/{index-D3Z7ZDLJ.js → playlist-CI3mRZjo.js} +2 -2
  41. package/dist/chunks/playlist-CI3mRZjo.js.map +1 -0
  42. package/dist/chunks/{VideoPrebid-CpckFzSq.js → prebid-CRY3i2OT.js} +1 -1
  43. package/dist/chunks/prebid-CRY3i2OT.js.map +1 -0
  44. package/dist/chunks/{index-DT8-oMPm.js → qrResume-BNy8XCp_.js} +1 -1
  45. package/dist/chunks/qrResume-BNy8XCp_.js.map +1 -0
  46. package/dist/chunks/redirectScreen-CJ3q9OX4.js +208 -0
  47. package/dist/chunks/redirectScreen-CJ3q9OX4.js.map +1 -0
  48. package/dist/chunks/{index-BbRYOSvk.js → rewardedUnlock-EyGMB9PK.js} +22 -19
  49. package/dist/chunks/rewardedUnlock-EyGMB9PK.js.map +1 -0
  50. package/dist/chunks/{index-CBX7bn-G.js → segments-C2HKU6XK.js} +2 -2
  51. package/dist/chunks/segments-C2HKU6XK.js.map +1 -0
  52. package/dist/chunks/{index-Ch3ep-eJ.js → sponsorship-DyFwGmEb.js} +1 -1
  53. package/dist/chunks/sponsorship-DyFwGmEb.js.map +1 -0
  54. package/dist/chunks/{index-BXSND_xN.js → spriteThumbnails-D0NQ5CCp.js} +2 -2
  55. package/dist/chunks/spriteThumbnails-D0NQ5CCp.js.map +1 -0
  56. package/dist/chunks/{index-DGtpFgHV.js → statsPanel-DSClIwA3.js} +1 -1
  57. package/dist/chunks/statsPanel-DSClIwA3.js.map +1 -0
  58. package/dist/chunks/{index-CDDke5rz.js → sticky-D_eLCNFk.js} +1 -1
  59. package/dist/chunks/sticky-D_eLCNFk.js.map +1 -0
  60. package/dist/chunks/{index-C3BQGcT3.js → story-D5Got6-6.js} +2 -2
  61. package/dist/chunks/{index-C3BQGcT3.js.map → story-D5Got6-6.js.map} +1 -1
  62. package/dist/chunks/{index-C5oGMHF_.js → tapGestures-DrC42DiI.js} +1 -1
  63. package/dist/chunks/tapGestures-DrC42DiI.js.map +1 -0
  64. package/dist/hope-player.js +1 -1
  65. package/dist/i18n/locales/en.d.ts.map +1 -1
  66. package/dist/i18n/locales/tr.d.ts.map +1 -1
  67. package/dist/i18n/types.d.ts +3 -0
  68. package/dist/i18n/types.d.ts.map +1 -1
  69. package/dist/index.d.ts +1 -1
  70. package/dist/index.d.ts.map +1 -1
  71. package/dist/plugins/ads/AdsController.d.ts.map +1 -1
  72. package/dist/plugins/ads/generateVastUrl.d.ts +10 -0
  73. package/dist/plugins/ads/generateVastUrl.d.ts.map +1 -1
  74. package/dist/plugins/redirect-screen/RedirectScreen.d.ts +26 -3
  75. package/dist/plugins/redirect-screen/RedirectScreen.d.ts.map +1 -1
  76. package/dist/plugins/rewarded/RewardedUnlock.d.ts +0 -5
  77. package/dist/plugins/rewarded/RewardedUnlock.d.ts.map +1 -1
  78. package/dist/types/index.d.ts +47 -1
  79. package/dist/types/index.d.ts.map +1 -1
  80. package/package.json +3 -1
  81. package/dist/chunks/ScratchSound-0XKHUcJK.js.map +0 -1
  82. package/dist/chunks/VideoPrebid-CpckFzSq.js.map +0 -1
  83. package/dist/chunks/index-3QALpwsf.js.map +0 -1
  84. package/dist/chunks/index-7IBf8Y-R.js.map +0 -1
  85. package/dist/chunks/index-BBmuCtKu.js.map +0 -1
  86. package/dist/chunks/index-BXSND_xN.js.map +0 -1
  87. package/dist/chunks/index-BbRYOSvk.js.map +0 -1
  88. package/dist/chunks/index-BeJNpAyx.js.map +0 -1
  89. package/dist/chunks/index-C5oGMHF_.js.map +0 -1
  90. package/dist/chunks/index-CBX7bn-G.js.map +0 -1
  91. package/dist/chunks/index-CDDke5rz.js.map +0 -1
  92. package/dist/chunks/index-CDPrkLq0.js.map +0 -1
  93. package/dist/chunks/index-CWLyz1fp.js.map +0 -1
  94. package/dist/chunks/index-Ca8hocby.js.map +0 -1
  95. package/dist/chunks/index-Ch3ep-eJ.js.map +0 -1
  96. package/dist/chunks/index-D3Z7ZDLJ.js.map +0 -1
  97. package/dist/chunks/index-D6r-BGAV.js +0 -77
  98. package/dist/chunks/index-D6r-BGAV.js.map +0 -1
  99. package/dist/chunks/index-DCXX1ZJG.js.map +0 -1
  100. package/dist/chunks/index-DEv3YqLg.js.map +0 -1
  101. package/dist/chunks/index-DGtpFgHV.js.map +0 -1
  102. package/dist/chunks/index-DITXYcHx.js.map +0 -1
  103. package/dist/chunks/index-DT8-oMPm.js.map +0 -1
  104. package/dist/chunks/index-DXWK4EFa.js.map +0 -1
  105. package/dist/chunks/index-Miba3PD_.js.map +0 -1
  106. package/dist/chunks/index-Q8FMOHj0.js.map +0 -1
  107. package/dist/chunks/index-e00_M05B.js.map +0 -1
  108. package/dist/chunks/index-f0vSgRIK.js.map +0 -1
  109. package/dist/chunks/index-rENB3n9O.js.map +0 -1
  110. package/dist/chunks/loadGpt-CmiAy366.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cast-DCAT2agI.js","sources":["../../src/plugins/cast/castSdk.ts","../../src/plugins/cast/RemoteMediaProxy.ts","../../src/plugins/cast/CastController.ts","../../src/plugins/cast/index.ts"],"sourcesContent":["/**\n * Google Cast Web Sender SDK (CAF) — kullanılan yüzeyin minimal tipleri ve yükleyicisi.\n * https://developers.google.com/cast/docs/web_sender\n */\n\nexport interface CastImage {\n url: string;\n}\n\nexport interface CastMediaMetadata {\n metadataType?: number;\n title?: string;\n subtitle?: string;\n artist?: string;\n albumName?: string;\n images?: CastImage[];\n}\n\nexport interface CastTrack {\n trackContentId?: string;\n trackContentType?: string;\n subtype?: string;\n name?: string;\n language?: string;\n}\n\nexport interface CastVastAdsRequest {\n adTagUrl?: string;\n}\n\nexport interface CastBreakClip {\n vastAdsRequest?: CastVastAdsRequest;\n}\n\nexport interface CastMediaInfo {\n contentId: string;\n contentType: string;\n streamType?: string;\n metadata?: CastMediaMetadata;\n tracks?: CastTrack[];\n hlsSegmentFormat?: string;\n hlsVideoSegmentFormat?: string;\n vmapAdsRequest?: CastVastAdsRequest;\n breakClips?: CastBreakClip[];\n breaks?: unknown[];\n}\n\nexport interface CastLoadRequest {\n currentTime?: number;\n autoplay?: boolean;\n activeTrackIds?: number[];\n}\n\nexport interface CastSessionLike {\n loadMedia(request: CastLoadRequest): Promise<unknown>;\n getCastDevice(): { friendlyName?: string };\n getMediaSession(): { media?: { contentId?: string } } | null;\n}\n\nexport interface RemotePlayerLike {\n isConnected: boolean;\n isMediaLoaded: boolean;\n isPaused: boolean;\n currentTime: number;\n duration: number;\n volumeLevel: number;\n isMuted: boolean;\n playerState: string | null;\n isPlayingBreak: boolean;\n}\n\nexport interface RemotePlayerControllerLike {\n addEventListener(type: string, fn: (e: { field: string; value: unknown }) => void): void;\n removeEventListener(type: string, fn: (e: { field: string; value: unknown }) => void): void;\n playOrPause(): void;\n seek(): void;\n setVolumeLevel(): void;\n muteOrUnmute(): void;\n stop(): void;\n}\n\nexport interface CastContextLike {\n setOptions(options: Record<string, unknown>): void;\n addEventListener(type: string, fn: (e: { castState?: string; sessionState?: string; session?: CastSessionLike }) => void): void;\n removeEventListener(type: string, fn: (e: { castState?: string; sessionState?: string; session?: CastSessionLike }) => void): void;\n requestSession(): Promise<unknown>;\n getCurrentSession(): CastSessionLike | null;\n getCastState(): string;\n endCurrentSession(stopCasting: boolean): void;\n}\n\ntype Ctor<T> = new (...args: never[]) => T;\n\n/** `window.cast.framework` + `window.chrome.cast` — yalnızca kullandıklarımız. */\nexport interface CastApi {\n framework: {\n CastContext: { getInstance(): CastContextLike };\n CastContextEventType: { CAST_STATE_CHANGED: string; SESSION_STATE_CHANGED: string };\n RemotePlayer: Ctor<RemotePlayerLike>;\n RemotePlayerController: new (player: RemotePlayerLike) => RemotePlayerControllerLike;\n RemotePlayerEventType: { ANY_CHANGE: string };\n };\n chrome: {\n AutoJoinPolicy: { ORIGIN_SCOPED: string };\n media: {\n DEFAULT_MEDIA_RECEIVER_APP_ID: string;\n MediaInfo: new (contentId: string, contentType: string) => CastMediaInfo;\n GenericMediaMetadata: Ctor<CastMediaMetadata>;\n MusicTrackMediaMetadata: Ctor<CastMediaMetadata>;\n LoadRequest: new (media: CastMediaInfo) => CastLoadRequest;\n Track: new (trackId: number, type: string) => CastTrack;\n TrackType: { TEXT: string };\n TextTrackType: { SUBTITLES: string };\n StreamType: { BUFFERED: string; LIVE: string };\n VastAdsRequest: Ctor<CastVastAdsRequest>;\n BreakClip: new (id: string) => CastBreakClip;\n Break: new (id: string, breakClipIds: string[], position: number) => unknown;\n HlsSegmentFormat?: { TS: string; FMP4: string; AAC: string };\n HlsVideoSegmentFormat?: { MPEG2_TS: string; FMP4: string };\n };\n Image: new (url: string) => CastImage;\n };\n}\n\nconst CAST_SDK_SRC = 'https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1';\nconst LOAD_TIMEOUT_MS = 10_000;\nlet loading: Promise<CastApi | null> | null = null;\n\nfunction current(): CastApi | null {\n const w = window as unknown as { cast?: { framework?: CastApi['framework'] }; chrome?: { cast?: CastApi['chrome'] } };\n return w.cast?.framework && w.chrome?.cast ? { framework: w.cast.framework, chrome: w.chrome.cast } : null;\n}\n\n/**\n * Cast SDK'yı bir kez yükler. Yalnızca Chromium tarayıcılarda (Chrome / Edge) ve güvenli bağlamda (HTTPS) denenir;\n * diğerlerinde ya da SDK \"Cast yok\" derse null — buton hiç görünmez.\n */\nexport function loadCastSdk(): Promise<CastApi | null> {\n if (loading) return loading;\n const w = window as unknown as { chrome?: unknown; __onGCastApiAvailable?: (available: boolean, reason?: string) => void };\n if (current()) return (loading = Promise.resolve(current()));\n if (!w.chrome || !window.isSecureContext) return (loading = Promise.resolve(null));\n loading = new Promise<CastApi | null>((resolve) => {\n const previous = w.__onGCastApiAvailable;\n const timer = setTimeout(() => resolve(null), LOAD_TIMEOUT_MS);\n // SDK hazır olunca bu global geri çağrıyı çağırır — sayfa kendi kurduysa onu da çağır.\n w.__onGCastApiAvailable = (available, reason) => {\n previous?.(available, reason);\n clearTimeout(timer);\n resolve(available ? current() : null);\n };\n if (!document.querySelector('script[src*=\"cast_sender.js\"]')) {\n const s = document.createElement('script');\n s.async = true;\n s.src = CAST_SDK_SRC;\n s.onerror = () => {\n clearTimeout(timer);\n loading = null;\n resolve(null);\n };\n document.head.appendChild(s);\n }\n });\n return loading;\n}\n","/** Uzak oynatıcıya (TV) giden komutlar. */\nexport interface RemoteCommands {\n play(): void;\n pause(): void;\n seek(time: number): void;\n setVolume(volume: number): void;\n setMuted(muted: boolean): void;\n}\n\nexport interface RemoteState {\n paused: boolean;\n currentTime: number;\n duration: number;\n volume: number;\n muted: boolean;\n ended: boolean;\n}\n\nconst PROXIED = ['paused', 'currentTime', 'duration', 'ended', 'volume', 'muted', 'readyState', 'seeking', 'buffered', 'play', 'pause'] as const;\nconst EMPTY_RANGES: TimeRanges = {\n length: 0,\n start: () => {\n throw new DOMException('Index out of range', 'IndexSizeError');\n },\n end: () => {\n throw new DOMException('Index out of range', 'IndexSizeError');\n },\n};\n/** Seek bar sürüklenirken her harekette TV'ye istek gitmesin. */\nconst SEEK_DEBOUNCE_MS = 150;\n\n/** <video>'nun gerçek (prototip) değeri — vekil kuruluyken de. */\nexport function nativeGet<K extends 'currentTime' | 'duration' | 'paused' | 'ended'>(video: HTMLVideoElement, key: K): HTMLMediaElement[K] {\n const d = Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, key);\n return d!.get!.call(video) as HTMLMediaElement[K];\n}\n\n/**\n * Cast sırasında `<video>` örneğinin oynatma yüzeyini (paused, currentTime, play(), volume…) TV'ye bağlar ve TV'den\n * gelen durumu olay olarak (play / pause / timeupdate / volumechange…) yayar. Böylece kontrol çubuğu, seek bar,\n * klavye kısayolları ve eklentiler hiç değişmeden TV'yi yönetir. Kaldırılınca örnek özellikleri silinir, prototip\n * (gerçek video) geri gelir.\n */\nexport class RemoteMediaProxy {\n private state: RemoteState;\n private pendingSeek: number | null = null;\n private seekTimer: ReturnType<typeof setTimeout> | null = null;\n private installed = false;\n\n constructor(\n private readonly video: HTMLVideoElement,\n private readonly commands: RemoteCommands,\n initial: RemoteState\n ) {\n this.state = { ...initial };\n }\n\n get current(): Readonly<RemoteState> {\n return this.state;\n }\n\n install(): void {\n if (this.installed) return;\n this.installed = true;\n const v = this.video;\n const s = (): RemoteState => this.state;\n const define = (key: string, desc: PropertyDescriptor): void => {\n Object.defineProperty(v, key, { configurable: true, enumerable: false, ...desc });\n };\n define('paused', { get: () => s().paused });\n define('ended', { get: () => s().ended });\n define('duration', { get: () => s().duration });\n define('readyState', { get: () => 4 });\n define('seeking', { get: () => this.pendingSeek !== null });\n define('buffered', { get: () => EMPTY_RANGES });\n define('currentTime', {\n get: () => this.pendingSeek ?? s().currentTime,\n set: (t: number) => this.seek(t),\n });\n define('volume', {\n get: () => s().volume,\n set: (vol: number) => {\n const clamped = Math.min(1, Math.max(0, Number(vol) || 0));\n this.state.volume = clamped;\n this.commands.setVolume(clamped);\n this.fire('volumechange');\n },\n });\n define('muted', {\n get: () => s().muted,\n set: (m: boolean) => {\n this.state.muted = !!m;\n this.commands.setMuted(!!m);\n this.fire('volumechange');\n },\n });\n define('play', {\n value: () => {\n if (this.state.ended) this.seek(0);\n this.commands.play();\n return Promise.resolve();\n },\n });\n define('pause', { value: () => this.commands.pause() });\n }\n\n uninstall(): void {\n if (!this.installed) return;\n this.installed = false;\n if (this.seekTimer) clearTimeout(this.seekTimer);\n this.seekTimer = null;\n this.pendingSeek = null;\n for (const key of PROXIED) delete (this.video as unknown as Record<string, unknown>)[key];\n }\n\n /** TV'den gelen durum — değişen alanlar için olay yayar. */\n update(patch: Partial<RemoteState>): void {\n const prev = this.state;\n this.state = { ...prev, ...patch };\n const next = this.state;\n if (patch.duration !== undefined && patch.duration !== prev.duration) this.fire('durationchange');\n if (patch.currentTime !== undefined && patch.currentTime !== prev.currentTime && this.pendingSeek === null) this.fire('timeupdate');\n if (patch.volume !== undefined || patch.muted !== undefined) {\n if (next.volume !== prev.volume || next.muted !== prev.muted) this.fire('volumechange');\n }\n if (patch.paused !== undefined && patch.paused !== prev.paused) {\n if (next.paused) this.fire('pause');\n else {\n this.fire('play');\n this.fire('playing');\n }\n }\n if (patch.ended && !prev.ended) this.fire('ended');\n }\n\n private seek(t: number): void {\n const target = Math.max(0, Number(t) || 0);\n const first = this.pendingSeek === null;\n this.pendingSeek = target;\n if (first) this.fire('seeking');\n this.fire('timeupdate');\n if (this.seekTimer) clearTimeout(this.seekTimer);\n this.seekTimer = setTimeout(() => {\n this.seekTimer = null;\n const to = this.pendingSeek ?? target;\n this.commands.seek(to);\n this.state = { ...this.state, currentTime: to, ended: false };\n this.pendingSeek = null;\n this.fire('seeked');\n this.fire('timeupdate');\n }, SEEK_DEBOUNCE_MS);\n }\n\n private fire(type: string): void {\n this.video.dispatchEvent(new Event(type));\n }\n}\n","import type { CastOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\nimport { setIconName } from '../../icons/Icon';\nimport { loadCastSdk, type CastApi, type CastContextLike, type CastMediaInfo, type CastSessionLike, type RemotePlayerControllerLike, type RemotePlayerLike } from './castSdk';\nimport { RemoteMediaProxy, nativeGet } from './RemoteMediaProxy';\n\n/** TV'ye gönderilecek içerik — player o anki duruma göre hazırlar. */\nexport interface CastMedia {\n src: string;\n contentType: string;\n live: boolean;\n title?: string;\n subtitle?: string;\n image?: string;\n /** Ses modu: TV'de müzik parçası olarak (kapak, sanatçı). */\n music: boolean;\n subtitles: Array<{ src: string; label: string; lang: string; default?: boolean }>;\n /** TV'de oynatılacak reklamlar (makroları doldurulmuş tag'ler); null = reklamsız. */\n ads: { vmap?: string; preroll?: string; midroll?: string; midrollIntervalSeconds?: number; postroll?: string } | null;\n}\n\nexport interface CastPlayerContext {\n hostEl: HTMLElement;\n videoEl: HTMLVideoElement;\n overlayEl: HTMLElement;\n i18n: HopeLocaleStrings;\n log(entry: { message: string; fatal?: boolean; details?: Record<string, string | number | boolean | undefined> }): void;\n addButton(label: string, icon: string, onClick: () => void): { btn: HTMLButtonElement; icon: HTMLElement };\n getMedia(): CastMedia | null;\n /** Yerelde video reklamı oynuyor — bu sırada yayın başlatılmaz. */\n isAdPlaying(): boolean;\n /** hls.js (MSE) ile oynatılıyor — AirPlay / Remote Playback bu kaynağı TV'ye veremez. */\n isMse(): boolean;\n /** İçerik kimliği — kalite / yedek kaynak değişimi aynı içerik sayılır (TV'de konum korunur). */\n contentKey(): string;\n /** İçerik TV'de mi (Chromecast) — player yerel reklamları askıya alır, otomatik oynatmayı keser. */\n onRemoteChange(remote: boolean): void;\n}\n\ntype Via = 'chromecast' | 'airplay' | 'remote';\ntype CastState = 'available' | 'unavailable' | 'connecting' | 'connected' | 'disconnected';\n\n/** Aynı sayfada birden çok player: Cast oturumu, butonuna basılan player'ındır. */\nlet requester: CastController | null = null;\nlet owner: CastController | null = null;\n/** Midroll aralığından üretilecek en fazla ara. */\nconst MAX_INTERVAL_BREAKS = 20;\nconst MIDROLL_END_MARGIN_S = 5;\n\n/**\n * TV'ye yayın: Google Cast (Chromecast / Google TV), AirPlay ve Remote Playback API. Her biri ayrı ayrı açılır;\n * butonlar yalnızca uygun cihaz varken görünür. Chromecast'te içerik TV'de oynar, player kumandaya dönüşür\n * (RemoteMediaProxy); bağlantı bitince yerelde TV'deki saniyeden devam eder.\n */\nexport class CastController {\n private options: CastOptions;\n private api: CastApi | null = null;\n private context: CastContextLike | null = null;\n private session: CastSessionLike | null = null;\n private player: RemotePlayerLike | null = null;\n private controller: RemotePlayerControllerLike | null = null;\n private proxy: RemoteMediaProxy | null = null;\n private castBtn: HTMLButtonElement | null = null;\n private castIcon: HTMLElement | null = null;\n private airplayBtn: HTMLButtonElement | null = null;\n private remoteBtn: HTMLButtonElement | null = null;\n private overlay: HTMLDivElement | null = null;\n private loadedSrc = '';\n private loadedContent = '';\n private savedAutoplay = false;\n private airplayActive = false;\n private destroyed = false;\n private remoteWatchId: number | null = null;\n\n constructor(\n private readonly ctx: CastPlayerContext,\n options: CastOptions\n ) {\n this.options = options;\n if (options.chromecast) void this.initChromecast();\n if (options.airplay) this.initAirPlay();\n if (options.remotePlayback) this.initRemotePlayback();\n }\n\n update(options: CastOptions): void {\n const prev = this.options;\n this.options = options;\n if (options.chromecast && !prev.chromecast) void this.initChromecast();\n if (options.airplay && !prev.airplay) this.initAirPlay();\n if (options.remotePlayback && !prev.remotePlayback) this.initRemotePlayback();\n if (this.castBtn) this.castBtn.hidden = !options.chromecast || this.castBtn.hidden;\n if (this.airplayBtn && !options.airplay) this.airplayBtn.hidden = true;\n if (this.remoteBtn && !options.remotePlayback) this.remoteBtn.hidden = true;\n }\n\n /** İçerik şu an TV'de mi (herhangi bir yoldan). */\n get casting(): boolean {\n return !!this.proxy || this.airplayActive || this.ctx.videoEl.remote?.state === 'connected';\n }\n\n private emit(state: CastState, via: Via, device?: string): void {\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:cast', { detail: { state, via, device } }));\n }\n\n private button(label: string, icon: string, onClick: () => void): { btn: HTMLButtonElement; icon: HTMLElement } {\n const b = this.ctx.addButton(label, icon, onClick);\n b.btn.hidden = true;\n return b;\n }\n\n // ── Google Cast ─────────────────────────────────────────────────────────\n\n private async initChromecast(): Promise<void> {\n if (this.castBtn) return;\n const { btn, icon } = this.button(this.ctx.i18n.castButton, 'cast', () => this.requestCast());\n btn.setAttribute('part', 'cast-button');\n this.castBtn = btn;\n this.castIcon = icon;\n const api = await loadCastSdk();\n if (!api || this.destroyed) {\n if (!api) this.ctx.log({ message: 'Google Cast is not available in this browser (Chrome / Edge over HTTPS needed)' });\n return;\n }\n this.api = api;\n const context = api.framework.CastContext.getInstance();\n this.context = context;\n context.setOptions({\n receiverApplicationId: this.options.receiverAppId || api.chrome.media.DEFAULT_MEDIA_RECEIVER_APP_ID,\n autoJoinPolicy: api.chrome.AutoJoinPolicy.ORIGIN_SCOPED,\n });\n const types = api.framework.CastContextEventType;\n context.addEventListener(types.CAST_STATE_CHANGED, this.onCastState);\n context.addEventListener(types.SESSION_STATE_CHANGED, this.onSessionState);\n this.onCastState({ castState: context.getCastState() });\n // Sayfa yenilendi ve oturum sürüyor (TV aynı içeriği oynatıyor) → kumandayı yeniden bağla.\n const existing = context.getCurrentSession();\n if (existing && !owner) this.tryResume(existing);\n }\n\n private readonly onCastState = (e: { castState?: string }): void => {\n const state = e.castState ?? 'NO_DEVICES_AVAILABLE';\n if (this.castBtn) this.castBtn.hidden = state === 'NO_DEVICES_AVAILABLE';\n this.castBtn?.toggleAttribute('data-connecting', state === 'CONNECTING');\n if (!this.proxy) this.emit(state === 'NO_DEVICES_AVAILABLE' ? 'unavailable' : state === 'CONNECTING' ? 'connecting' : 'available', 'chromecast');\n };\n\n private readonly onSessionState = (e: { sessionState?: string; session?: CastSessionLike }): void => {\n const s = e.sessionState;\n if ((s === 'SESSION_STARTED' || s === 'SESSION_RESUMED') && e.session) {\n if (requester === this) {\n requester = null;\n void this.attach(e.session, true);\n } else if (s === 'SESSION_RESUMED' && !owner) {\n this.tryResume(e.session);\n }\n } else if (s === 'SESSION_ENDED' || s === 'SESSION_START_FAILED') {\n if (requester === this) requester = null;\n if (owner === this) this.detach();\n }\n };\n\n private requestCast(): void {\n if (!this.context) return;\n if (this.ctx.isAdPlaying()) {\n this.ctx.log({ message: 'Cast: wait for the ad to finish' });\n return;\n }\n requester = this;\n // Bağlıyken Chrome'un seçicisi \"yayını durdur\"u da sunar.\n this.context.requestSession().catch((err: unknown) => {\n if (requester === this) requester = null;\n // Kullanıcı seçiciyi kapattı ('cancel') — hata değil.\n if (String(err) !== 'cancel') this.ctx.log({ message: `Cast session failed: ${String(err)}` });\n });\n }\n\n private tryResume(session: CastSessionLike): void {\n const media = this.ctx.getMedia();\n const remoteId = session.getMediaSession()?.media?.contentId;\n if (media && remoteId && remoteId === media.src) void this.attach(session, false);\n }\n\n private async attach(session: CastSessionLike, load: boolean): Promise<void> {\n const api = this.api;\n if (!api || this.destroyed) return;\n if (owner && owner !== this) owner.detach();\n owner = this;\n this.session = session;\n const v = this.ctx.videoEl;\n const startAt = nativeGet(v, 'currentTime');\n const duration = nativeGet(v, 'duration');\n HTMLMediaElement.prototype.pause.call(v);\n // Cast sırasında kaynak değişirse (playlist / kalite) yerel video kendiliğinden çalmasın.\n this.savedAutoplay = v.autoplay;\n v.autoplay = false;\n\n const player = new api.framework.RemotePlayer();\n const controller = new api.framework.RemotePlayerController(player);\n this.player = player;\n this.controller = controller;\n this.proxy = new RemoteMediaProxy(\n v,\n {\n play: () => player.isPaused && controller.playOrPause(),\n pause: () => !player.isPaused && controller.playOrPause(),\n seek: (t) => {\n player.currentTime = t;\n controller.seek();\n },\n setVolume: (vol) => {\n player.volumeLevel = vol;\n controller.setVolumeLevel();\n },\n setMuted: (m) => player.isMuted !== m && controller.muteOrUnmute(),\n },\n { paused: false, currentTime: startAt, duration, volume: v.volume, muted: v.muted, ended: false }\n );\n this.proxy.install();\n controller.addEventListener(api.framework.RemotePlayerEventType.ANY_CHANGE, this.onRemoteChange);\n v.addEventListener('loadstart', this.onLocalSourceChange);\n this.ctx.onRemoteChange(true);\n const device = session.getCastDevice()?.friendlyName || this.ctx.i18n.castDeviceFallback;\n this.showOverlay(this.ctx.i18n.castPlayingOn.replace('{device}', device));\n this.castBtn?.setAttribute('aria-pressed', 'true');\n if (this.castIcon) setIconName(this.castIcon, 'cast-connected');\n this.emit('connected', 'chromecast', device);\n if (load) await this.loadMedia(startAt, true);\n else {\n this.loadedSrc = session.getMediaSession()?.media?.contentId ?? '';\n this.loadedContent = this.ctx.contentKey();\n }\n }\n\n /** O an çalan içeriği TV'ye yükler (reklam araları ve altyazılarla). */\n private async loadMedia(currentTime: number, autoplay: boolean): Promise<void> {\n const api = this.api;\n const session = this.session;\n const media = this.ctx.getMedia();\n if (!api || !session || !media) {\n this.ctx.log({ message: 'Cast: nothing to send (no playable source)' });\n return;\n }\n const m = api.chrome.media;\n const info: CastMediaInfo = new m.MediaInfo(media.src, media.contentType);\n info.streamType = media.live ? m.StreamType.LIVE : m.StreamType.BUFFERED;\n const md = media.music ? new m.MusicTrackMediaMetadata() : new m.GenericMediaMetadata();\n md.title = media.title;\n if (media.music) md.artist = media.subtitle;\n else md.subtitle = media.subtitle;\n if (media.image) md.images = [new api.chrome.Image(media.image)];\n info.metadata = md;\n if (/mpegurl/i.test(media.contentType) && this.options.hlsSegmentFormat === 'fmp4') {\n if (m.HlsSegmentFormat) info.hlsSegmentFormat = m.HlsSegmentFormat.FMP4;\n if (m.HlsVideoSegmentFormat) info.hlsVideoSegmentFormat = m.HlsVideoSegmentFormat.FMP4;\n }\n const activeTrackIds: number[] = [];\n info.tracks = media.subtitles.map((s, i) => {\n const t = new m.Track(i + 1, m.TrackType.TEXT);\n t.trackContentId = s.src;\n t.trackContentType = 'text/vtt';\n t.subtype = m.TextTrackType.SUBTITLES;\n t.name = s.label;\n t.language = s.lang;\n if (s.default) activeTrackIds.push(i + 1);\n return t;\n });\n this.applyAds(info, media);\n const req = new m.LoadRequest(info);\n req.currentTime = media.live ? undefined : currentTime;\n req.autoplay = autoplay;\n if (activeTrackIds.length) req.activeTrackIds = activeTrackIds;\n this.loadedSrc = media.src;\n this.loadedContent = this.ctx.contentKey();\n try {\n await session.loadMedia(req);\n this.ctx.log({ message: 'Cast: media loaded on the TV', details: { src: media.src, ads: media.ads ? (media.ads.vmap ? 'vmap' : 'vast') : 'none' } });\n } catch (err) {\n this.ctx.log({ message: `Cast: the TV could not load the media: ${String(err)}`, fatal: true, details: { src: media.src } });\n }\n }\n\n /**\n * Reklamlar TV'de: VMAP verilmişse receiver tüm araları kendisi planlar (vmapAdsRequest); yoksa VAST tag'leri\n * ara olarak eklenir — preroll (0), aralıklı midroll'lar, postroll (-1). Reklamları receiver oynatır ve sayar.\n */\n private applyAds(info: CastMediaInfo, media: CastMedia): void {\n const ads = media.ads;\n const m = this.api!.chrome.media;\n if (!ads) return;\n if (ads.vmap) {\n const req = new m.VastAdsRequest();\n req.adTagUrl = ads.vmap;\n info.vmapAdsRequest = req;\n return;\n }\n const clips: unknown[] = [];\n const breaks: unknown[] = [];\n const add = (id: string, tag: string, position: number): void => {\n const clip = new m.BreakClip(`clip-${id}`);\n const req = new m.VastAdsRequest();\n req.adTagUrl = tag;\n clip.vastAdsRequest = req;\n clips.push(clip);\n breaks.push(new m.Break(`break-${id}`, [`clip-${id}`], position));\n };\n if (ads.preroll) add('pre', ads.preroll, 0);\n const every = ads.midrollIntervalSeconds ?? 0;\n const duration = this.proxy?.current.duration ?? NaN;\n if (ads.midroll && every > 0 && !media.live && Number.isFinite(duration)) {\n // Bitişe çok yakın midroll olmasın (orada postroll var).\n for (let t = every, i = 1; t < duration - MIDROLL_END_MARGIN_S && i <= MAX_INTERVAL_BREAKS; t += every, i++) add(`mid-${i}`, ads.midroll, t);\n }\n if (ads.postroll && !media.live) add('post', ads.postroll, -1);\n if (clips.length) {\n info.breakClips = clips as CastMediaInfo['breakClips'];\n info.breaks = breaks;\n }\n }\n\n private readonly onRemoteChange = (e: { field: string; value: unknown }): void => {\n const p = this.player;\n const proxy = this.proxy;\n if (!p || !proxy) return;\n switch (e.field) {\n case 'isPaused':\n proxy.update({ paused: !!e.value });\n break;\n case 'currentTime':\n proxy.update({ currentTime: Number(e.value) || 0 });\n break;\n case 'duration':\n proxy.update({ duration: Number(e.value) > 0 ? Number(e.value) : proxy.current.duration });\n break;\n case 'volumeLevel':\n proxy.update({ volume: Number(e.value) });\n break;\n case 'isMuted':\n proxy.update({ muted: !!e.value });\n break;\n case 'playerState':\n // İçerik TV'de bitti (IDLE + daha önce oynuyordu) → ended.\n if (e.value === 'IDLE' && p.isMediaLoaded === false && proxy.current.currentTime > 0) proxy.update({ ended: true, paused: true });\n else if (e.value === 'PLAYING') proxy.update({ ended: false, paused: false });\n break;\n case 'isPlayingBreak':\n this.overlay?.toggleAttribute('data-break', !!e.value);\n break;\n case 'isConnected':\n if (!e.value && owner === this) this.detach();\n break;\n }\n };\n\n /** Cast sırasında player başka bir kaynağa geçti (playlist sonraki öğe, kalite, yedek kaynak) → TV'ye de gönder. */\n private readonly onLocalSourceChange = (): void => {\n if (!this.proxy) return;\n HTMLMediaElement.prototype.pause.call(this.ctx.videoEl);\n const media = this.ctx.getMedia();\n if (!media || media.src === this.loadedSrc) return;\n // Aynı içeriğin başka kalitesi / yedeği ise kaldığı yerden, yeni bir içerikse (playlist) baştan.\n const same = this.ctx.contentKey() === this.loadedContent;\n void this.loadMedia(same ? this.proxy.current.currentTime : 0, true);\n };\n\n private detach(): void {\n const proxy = this.proxy;\n if (!proxy) return;\n if (owner === this) owner = null;\n const { currentTime, paused, ended } = proxy.current;\n const v = this.ctx.videoEl;\n this.controller?.removeEventListener(this.api!.framework.RemotePlayerEventType.ANY_CHANGE, this.onRemoteChange);\n v.removeEventListener('loadstart', this.onLocalSourceChange);\n proxy.uninstall();\n this.proxy = null;\n this.player = null;\n this.controller = null;\n this.session = null;\n this.loadedSrc = '';\n v.autoplay = this.savedAutoplay;\n this.ctx.onRemoteChange(false);\n this.hideOverlay();\n this.castBtn?.setAttribute('aria-pressed', 'false');\n if (this.castIcon) setIconName(this.castIcon, 'cast');\n // TV'deki saniyeden yerelde devam (bittiyse olduğu yerde kalır).\n if (Number.isFinite(currentTime) && currentTime > 0 && !ended) v.currentTime = currentTime;\n if (!paused && !ended) void v.play().catch(() => {});\n this.emit('disconnected', 'chromecast');\n }\n\n // ── AirPlay (Safari) ────────────────────────────────────────────────────\n\n private initAirPlay(): void {\n if (this.airplayBtn || !('WebKitPlaybackTargetAvailabilityEvent' in window)) return;\n const v = this.ctx.videoEl as HTMLVideoElement & { webkitShowPlaybackTargetPicker?: () => void; webkitCurrentPlaybackTargetIsWireless?: boolean };\n v.setAttribute('x-webkit-airplay', 'allow');\n const { btn } = this.button(this.ctx.i18n.airplayButton, 'airplay', () => {\n if (this.ctx.isMse()) {\n this.ctx.log({ message: 'AirPlay: this source plays through hls.js (MSE) — use hls.engine: \"auto\" / \"native\" on Safari for AirPlay' });\n return;\n }\n v.webkitShowPlaybackTargetPicker?.();\n });\n btn.setAttribute('part', 'airplay-button');\n this.airplayBtn = btn;\n v.addEventListener('webkitplaybacktargetavailabilitychanged', ((e: Event & { availability?: string }) => {\n const available = e.availability === 'available';\n btn.hidden = !available || !this.options.airplay;\n if (!this.airplayActive) this.emit(available ? 'available' : 'unavailable', 'airplay');\n }) as EventListener);\n v.addEventListener('webkitcurrentplaybacktargetiswirelesschanged', () => {\n const on = !!v.webkitCurrentPlaybackTargetIsWireless;\n if (on === this.airplayActive) return;\n this.airplayActive = on;\n btn.setAttribute('aria-pressed', String(on));\n if (on) this.showOverlay(this.ctx.i18n.airplayPlaying);\n else this.hideOverlay();\n this.emit(on ? 'connected' : 'disconnected', 'airplay');\n });\n }\n\n // ── Remote Playback API ─────────────────────────────────────────────────\n\n private initRemotePlayback(): void {\n const v = this.ctx.videoEl;\n const remote = v.remote;\n if (this.remoteBtn || !remote) return;\n v.disableRemotePlayback = false;\n const { btn } = this.button(this.ctx.i18n.castButton, 'cast', () => {\n if (this.ctx.isMse()) {\n this.ctx.log({ message: 'Remote playback: hls.js (MSE) sources cannot be sent to the device' });\n return;\n }\n remote.prompt().catch((err: unknown) => this.ctx.log({ message: `Remote playback: ${String(err)}` }));\n });\n btn.setAttribute('part', 'remote-playback-button');\n this.remoteBtn = btn;\n remote\n .watchAvailability((available) => {\n // Google Cast butonu görünüyorsa aynı işi yapan ikinci butonu gösterme.\n btn.hidden = !available || this.ctx.isMse() || !!(this.castBtn && !this.castBtn.hidden);\n if (remote.state === 'disconnected') this.emit(available ? 'available' : 'unavailable', 'remote');\n })\n .then((id) => (this.remoteWatchId = id))\n .catch(() => (btn.hidden = true));\n remote.addEventListener('connecting', () => this.emit('connecting', 'remote'));\n remote.addEventListener('connect', () => {\n btn.setAttribute('aria-pressed', 'true');\n this.showOverlay(this.ctx.i18n.castPlayingOn.replace('{device}', this.ctx.i18n.castDeviceFallback));\n this.emit('connected', 'remote');\n });\n remote.addEventListener('disconnect', () => {\n btn.setAttribute('aria-pressed', 'false');\n this.hideOverlay();\n this.emit('disconnected', 'remote');\n });\n }\n\n // ── \"TV'de oynatılıyor\" katmanı ─────────────────────────────────────────\n\n private showOverlay(text: string): void {\n if (!this.overlay) {\n const el = document.createElement('div');\n el.className = 'hp-cast-overlay';\n el.setAttribute('part', 'cast-overlay');\n el.setAttribute('role', 'status');\n const icon = document.createElement('i');\n icon.className = 'hp-icon hp-icon-cast-connected';\n icon.setAttribute('aria-hidden', 'true');\n const label = document.createElement('span');\n label.className = 'hp-cast-overlay-text';\n const ad = document.createElement('span');\n ad.className = 'hp-cast-overlay-ad';\n el.append(icon, label, ad);\n this.ctx.overlayEl.appendChild(el);\n this.overlay = el;\n }\n this.overlay.querySelector('.hp-cast-overlay-text')!.textContent = text;\n this.overlay.querySelector('.hp-cast-overlay-ad')!.textContent = this.ctx.i18n.castAdOnTv;\n this.overlay.removeAttribute('data-break');\n this.overlay.setAttribute('data-open', '');\n this.ctx.overlayEl.setAttribute('data-casting', '');\n }\n\n private hideOverlay(): void {\n this.overlay?.removeAttribute('data-open');\n this.ctx.overlayEl.removeAttribute('data-casting');\n }\n\n refreshLabels(): void {\n this.castBtn?.setAttribute('aria-label', this.ctx.i18n.castButton);\n this.airplayBtn?.setAttribute('aria-label', this.ctx.i18n.airplayButton);\n this.remoteBtn?.setAttribute('aria-label', this.ctx.i18n.castButton);\n }\n\n destroy(): void {\n this.destroyed = true;\n if (owner === this) {\n // Player sayfadan kalkıyor: TV'deki yayın sürsün (Cast'in olağan davranışı), kumanda bağı kopsun.\n this.detach();\n }\n if (requester === this) requester = null;\n if (this.context && this.api) {\n const types = this.api.framework.CastContextEventType;\n this.context.removeEventListener(types.CAST_STATE_CHANGED, this.onCastState);\n this.context.removeEventListener(types.SESSION_STATE_CHANGED, this.onSessionState);\n }\n if (this.remoteWatchId !== null) void this.ctx.videoEl.remote?.cancelWatchAvailability(this.remoteWatchId).catch(() => {});\n this.castBtn?.remove();\n this.airplayBtn?.remove();\n this.remoteBtn?.remove();\n this.overlay?.remove();\n }\n}\n","import { CastController, type CastMedia, type CastPlayerContext } from './CastController';\nimport type { CastOptions } from '../../types';\n\n/** TV'ye yayını kurar (Google Cast / AirPlay / Remote Playback — her biri seçenekle açılır). */\nexport function installCast(ctx: CastPlayerContext, options: CastOptions): CastController {\n return new CastController(ctx, options);\n}\n\nexport { CastController };\nexport type { CastMedia, CastPlayerContext };\n"],"names":["CAST_SDK_SRC","LOAD_TIMEOUT_MS","loading","current","w","_a","_b","loadCastSdk","resolve","previous","timer","available","reason","s","PROXIED","EMPTY_RANGES","SEEK_DEBOUNCE_MS","nativeGet","video","key","RemoteMediaProxy","commands","initial","__publicField","v","define","desc","t","vol","clamped","m","patch","prev","next","target","first","to","type","requester","owner","MAX_INTERVAL_BREAKS","MIDROLL_END_MARGIN_S","CastController","ctx","options","e","state","p","proxy","media","same","via","device","label","icon","onClick","b","btn","api","context","types","existing","err","session","remoteId","load","startAt","duration","player","controller","setIconName","_d","_c","currentTime","autoplay","info","md","activeTrackIds","i","req","ads","clips","breaks","add","id","tag","position","clip","every","paused","ended","on","remote","text","el","ad","_e","installCast"],"mappings":"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"}
@@ -71,4 +71,4 @@ export {
71
71
  o as CountdownScreen,
72
72
  p as installCountdownScreen
73
73
  };
74
- //# sourceMappingURL=index-rENB3n9O.js.map
74
+ //# sourceMappingURL=countdownScreen-CI-u6jjA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"countdownScreen-CI-u6jjA.js","sources":["../../src/plugins/countdown-screen/CountdownScreen.ts","../../src/plugins/countdown-screen/index.ts"],"sourcesContent":["import type { CountdownScreenOptions } from '../../types';\nimport type { GatePlayerContext } from '../shared/GatePlayerContext';\n\n/** Hedef tarihe kadar içeriği engelleyen geri sayım ekranı (blockChrome ile). */\nexport class CountdownScreen {\n private readonly wrapper: HTMLElement;\n private readonly timerLabel: HTMLElement;\n private readonly timerEl: HTMLElement;\n private interval: ReturnType<typeof setInterval> | null = null;\n private bgInterval: ReturnType<typeof setInterval> | null = null;\n private imageIndex = 0;\n private readonly targetTime: number;\n private resolved = false;\n private readonly completeCallbacks: Array<() => void> = [];\n\n constructor(\n private readonly ctx: GatePlayerContext,\n private readonly options: CountdownScreenOptions\n ) {\n this.targetTime = new Date(options.time).getTime();\n\n this.wrapper = document.createElement('div');\n this.wrapper.setAttribute('part', 'countdown-screen');\n this.wrapper.className =\n 'hp:absolute hp:inset-0 hp:z-40 hp:flex hp:items-end hp:bg-cover hp:bg-center hp:bg-surface hp:text-on-surface';\n\n const info = document.createElement('div');\n info.className = 'hp:p-4 hp:w-full hp:bg-gradient-to-t hp:from-black/80 hp:to-transparent';\n\n if (options.title) {\n const title = document.createElement('h3');\n title.className = 'hp:text-lg hp:font-semibold hp:m-0';\n title.textContent = options.title;\n info.appendChild(title);\n }\n if (options.spot) {\n const spot = document.createElement('p');\n spot.className = 'hp:text-sm hp:opacity-80 hp:m-0 hp:mt-1';\n spot.textContent = options.spot;\n info.appendChild(spot);\n }\n if (options.description) {\n const desc = document.createElement('p');\n desc.className = 'hp:text-xs hp:opacity-70 hp:m-0 hp:mt-1';\n desc.textContent = options.description;\n info.appendChild(desc);\n }\n\n this.timerLabel = document.createElement('span');\n this.timerLabel.className = 'hp:text-xs hp:opacity-70 hp:block hp:mt-2';\n this.timerLabel.textContent = ctx.i18n.countdownRemaining;\n info.appendChild(this.timerLabel);\n\n this.timerEl = document.createElement('div');\n this.timerEl.className = 'hp:text-2xl hp:font-mono hp:tabular-nums';\n info.appendChild(this.timerEl);\n\n this.wrapper.appendChild(info);\n this.updateBackground();\n ctx.overlayContainerEl.appendChild(this.wrapper);\n\n ctx.blockChrome();\n ctx.videoEl.addEventListener('play', this.onPlayWhileBlocked);\n\n if (Array.isArray(options.coverImage) && options.coverImage.length > 0) {\n this.bgInterval = setInterval(() => {\n this.imageIndex = (this.imageIndex + 1) % (options.coverImage as string[]).length;\n this.updateBackground();\n }, options.imageChangeInterval ?? 5000);\n }\n\n this.start();\n }\n\n refreshLabels(): void {\n this.timerLabel.textContent = this.ctx.i18n.countdownRemaining;\n }\n\n isComplete(): boolean {\n return this.resolved;\n }\n\n /** Geri sayım bitince çağrılır (zaten bittiyse anında). */\n onComplete(cb: () => void): void {\n if (this.resolved) cb();\n else this.completeCallbacks.push(cb);\n }\n\n destroy(): void {\n if (this.interval) clearInterval(this.interval);\n if (this.bgInterval) clearInterval(this.bgInterval);\n this.ctx.videoEl.removeEventListener('play', this.onPlayWhileBlocked);\n if (!this.resolved) this.ctx.unblockChrome();\n this.wrapper.remove();\n this.completeCallbacks.length = 0;\n }\n\n private readonly onPlayWhileBlocked = (): void => {\n if (!this.resolved) this.ctx.videoEl.pause();\n };\n\n private updateBackground(): void {\n const img = Array.isArray(this.options.coverImage) ? this.options.coverImage[this.imageIndex] : this.options.coverImage;\n this.wrapper.style.backgroundImage = img ? `url(\"${img}\")` : 'none';\n }\n\n private start(): void {\n const tick = () => {\n const diff = Math.max(this.targetTime - Date.now(), 0);\n const h = Math.floor(diff / 3600000);\n const m = Math.floor((diff / 60000) % 60);\n const s = Math.floor((diff / 1000) % 60);\n this.timerEl.textContent = `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`;\n\n if (diff <= 0) this.complete();\n };\n\n tick();\n if (this.targetTime - Date.now() > 0) {\n this.interval = setInterval(tick, 1000);\n } else {\n this.complete();\n }\n }\n\n private complete(): void {\n if (this.resolved) return;\n this.resolved = true;\n if (this.interval) clearInterval(this.interval);\n if (this.bgInterval) clearInterval(this.bgInterval);\n this.ctx.videoEl.removeEventListener('play', this.onPlayWhileBlocked);\n this.wrapper.remove();\n this.ctx.unblockChrome();\n const callbacks = this.completeCallbacks.splice(0);\n for (const cb of callbacks) cb();\n }\n}\n","import { CountdownScreen } from './CountdownScreen';\nimport type { GatePlayerContext } from '../shared/GatePlayerContext';\nimport type { CountdownScreenOptions } from '../../types';\n\nexport function installCountdownScreen(ctx: GatePlayerContext, options: CountdownScreenOptions): CountdownScreen {\n return new CountdownScreen(ctx, options);\n}\n\nexport { CountdownScreen };\nexport type { GatePlayerContext };\n"],"names":["CountdownScreen","ctx","options","__publicField","info","title","spot","desc","cb","img","tick","diff","h","m","callbacks","installCountdownScreen"],"mappings":"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"}
@@ -107,4 +107,4 @@ export {
107
107
  E as DaiController,
108
108
  v as installDai
109
109
  };
110
- //# sourceMappingURL=index-Q8FMOHj0.js.map
110
+ //# sourceMappingURL=dai-B9Tth1Iv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dai-B9Tth1Iv.js","sources":["../../src/plugins/dai/loadDaiSdk.ts","../../src/plugins/dai/DaiController.ts","../../src/plugins/dai/index.ts"],"sourcesContent":["const DAI_SDK_URL = 'https://imasdk.googleapis.com/js/sdkloader/ima3_dai.js';\n\n// Window.google loadImaSdk.ts'de zaten augment edildi — burada tekrar tanımlanmıyor.\nfunction getLoadedDai(): typeof google.ima.dai | undefined {\n return (window as unknown as { google?: { ima?: { dai?: typeof google.ima.dai } } }).google?.ima?.dai;\n}\n\nlet loadPromise: Promise<typeof google.ima.dai> | null = null;\n\n/** DAI SDK, normal IMA SDK'dan (loadImaSdk.ts) AYRI bir script — ima3_dai.js. */\nexport function loadDaiSdk(): Promise<typeof google.ima.dai> {\n const existing = getLoadedDai();\n if (existing) return Promise.resolve(existing);\n if (loadPromise) return loadPromise;\n\n loadPromise = new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.src = DAI_SDK_URL;\n script.async = true;\n script.onload = () => {\n const dai = getLoadedDai();\n if (dai) resolve(dai);\n else reject(new Error('DAI SDK yüklendi ama window.google.ima.dai yok'));\n };\n script.onerror = () => reject(new Error('DAI SDK yüklenemedi (reklam engelleyici olabilir)'));\n document.head.appendChild(script);\n });\n return loadPromise;\n}\n","import { loadDaiSdk } from './loadDaiSdk';\nimport type { DaiOptions } from '../../types';\n\nexport interface DaiPlayerContext {\n videoEl: HTMLVideoElement;\n hostEl: HTMLElement;\n /** IMA DAI'nin kendi ad UI'ını (skip/countdown/clickthrough) çizdiği katman — plugins/ads'teki adLayerEl ile aynı fikir. */\n adUiEl: HTMLElement;\n loadStreamUrl(url: string): Promise<void>;\n /** Reklam arası boyunca kullanıcı canlı reklamın İÇİNE seek edemesin diye. */\n disableSeeking(): void;\n enableSeeking(): void;\n}\n\n/** Google IMA DAI: stream StreamManager üzerinden istenir; reklam araları sırasında seek kilitlenir. */\nexport class DaiController {\n private dai: typeof google.ima.dai | null = null;\n private streamManager: google.ima.dai.api.StreamManager | null = null;\n private readonly metadataTrackListeners = new Map<TextTrack, () => void>();\n\n constructor(\n private readonly ctx: DaiPlayerContext,\n private readonly options: DaiOptions\n ) {}\n\n async install(): Promise<void> {\n let dai: typeof google.ima.dai;\n try {\n dai = await loadDaiSdk();\n } catch (err) {\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:aderror', { detail: { message: String(err) } }));\n if (this.options.fallbackStreamUrl) void this.ctx.loadStreamUrl(this.options.fallbackStreamUrl);\n return;\n }\n this.dai = dai;\n\n this.streamManager = new dai.api.StreamManager(this.ctx.videoEl, this.ctx.adUiEl);\n this.streamManager.addEventListener(\n [\n dai.api.StreamEvent.Type.LOADED,\n dai.api.StreamEvent.Type.ERROR,\n dai.api.StreamEvent.Type.AD_BREAK_STARTED,\n dai.api.StreamEvent.Type.AD_BREAK_ENDED,\n ],\n this.onStreamEvent\n );\n\n const request = new dai.api.LiveStreamRequest();\n request.assetKey = this.options.assetKey;\n if (this.options.apiKey) request.apiKey = this.options.apiKey;\n if (this.options.adTagParameters) request.adTagParameters = this.options.adTagParameters;\n\n this.attachMetadataForwarding();\n this.streamManager.requestStream(request);\n }\n\n destroy(): void {\n this.ctx.videoEl.textTracks.removeEventListener('addtrack', this.onAddTrack);\n for (const [track, listener] of this.metadataTrackListeners) track.removeEventListener('cuechange', listener);\n this.metadataTrackListeners.clear();\n this.streamManager?.reset();\n }\n\n private readonly onStreamEvent = (event: google.ima.dai.api.StreamEvent): void => {\n if (!this.dai) return;\n const Type = this.dai.api.StreamEvent.Type;\n\n switch (event.type) {\n case Type.LOADED: {\n const { url } = event.getStreamData();\n void this.ctx.loadStreamUrl(url).then(() => void this.ctx.videoEl.play().catch(() => {}));\n break;\n }\n case Type.ERROR: {\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:aderror', { detail: { message: 'DAI stream error' } }));\n if (this.options.fallbackStreamUrl) void this.ctx.loadStreamUrl(this.options.fallbackStreamUrl);\n break;\n }\n case Type.AD_BREAK_STARTED:\n this.ctx.disableSeeking();\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:adstart', { detail: { type: 'midroll' } }));\n break;\n case Type.AD_BREAK_ENDED:\n this.ctx.enableSeeking();\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:adend', { detail: { type: 'midroll' } }));\n break;\n default:\n break;\n }\n };\n\n /** HLS live DAI reklam zamanlaması ID3/timed-metadata ile gelir — StreamManager.processMetadata()'ya iletilir. */\n private attachMetadataForwarding(): void {\n for (let i = 0; i < this.ctx.videoEl.textTracks.length; i++) {\n this.listenMetadataTrack(this.ctx.videoEl.textTracks[i]!);\n }\n this.ctx.videoEl.textTracks.addEventListener('addtrack', this.onAddTrack);\n }\n\n private readonly onAddTrack = (e: TrackEvent): void => {\n if (e.track instanceof TextTrack) this.listenMetadataTrack(e.track);\n };\n\n private listenMetadataTrack(track: TextTrack): void {\n if (track.kind !== 'metadata' || this.metadataTrackListeners.has(track)) return;\n track.mode = 'hidden';\n\n const listener = () => {\n const cues = track.activeCues;\n if (!cues || !this.streamManager) return;\n for (let i = 0; i < cues.length; i++) {\n const cue = cues[i] as unknown as { value?: unknown; startTime?: number };\n if (cue.value === undefined) continue;\n try {\n this.streamManager.processMetadata('ID3', cue.value as Uint8Array | string, cue.startTime);\n } catch {\n /* DAI akışla ilgisiz bir metadata cue'su olabilir — yoksay */\n }\n }\n };\n track.addEventListener('cuechange', listener);\n this.metadataTrackListeners.set(track, listener);\n }\n}\n","import { DaiController, type DaiPlayerContext } from './DaiController';\nimport type { DaiOptions } from '../../types';\n\nexport async function installDai(ctx: DaiPlayerContext, options: DaiOptions): Promise<DaiController> {\n const controller = new DaiController(ctx, options);\n await controller.install();\n return controller;\n}\n\nexport { DaiController };\nexport type { DaiPlayerContext };\n"],"names":["DAI_SDK_URL","getLoadedDai","_a","_b","loadPromise","loadDaiSdk","existing","resolve","reject","script","dai","DaiController","ctx","options","__publicField","event","Type","url","e","err","request","track","listener","i","cues","cue","installDai","controller"],"mappings":"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"}
@@ -105,4 +105,4 @@ export {
105
105
  x as DebugPanel,
106
106
  f as installDebugPanel
107
107
  };
108
- //# sourceMappingURL=index-DCXX1ZJG.js.map
108
+ //# sourceMappingURL=debugPanel-Bnc_7GOn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debugPanel-Bnc_7GOn.js","sources":["../../src/plugins/debug/DebugPanel.ts","../../src/plugins/debug/index.ts"],"sourcesContent":["import type { HopeLocaleStrings } from '../../i18n/types';\nimport type { ErrorLog, PlayerLogEntry, PlayerLogSource } from '../../debug/ErrorLog';\n\nexport interface DebugPanelContext {\n containerEl: HTMLElement;\n i18n: HopeLocaleStrings;\n log: ErrorLog;\n version: string;\n}\n\nconst CLOSE_ICON =\n '<svg viewBox=\"0 0 24 24\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.4\" stroke-linecap=\"round\" aria-hidden=\"true\"><path d=\"M6 6l12 12M18 6L6 18\"/></svg>';\n\n/**\n * Sağ tık menüsündeki \"Hata ayıklama\" — player'ın tüm hatalarını (medya, yayın, reklam, altyazı) zaman sırasıyla,\n * ayrıntılarıyla gösteren ve tüm player alanını kaplayan pencere. Uzun satırlar (URL'ler) kırılır, liste kendi içinde\n * kayar; yeni hata gelince açık pencere canlı güncellenir.\n */\nexport class DebugPanel {\n private readonly el: HTMLDivElement;\n private readonly titleEl: HTMLSpanElement;\n private readonly countEl: HTMLSpanElement;\n private readonly copyBtn: HTMLButtonElement;\n private readonly clearBtn: HTMLButtonElement;\n private readonly closeBtn: HTMLButtonElement;\n private readonly list: HTMLOListElement;\n private readonly emptyEl: HTMLParagraphElement;\n private copiedTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(private readonly ctx: DebugPanelContext) {\n this.el = document.createElement('div');\n this.el.className = 'hp-debug';\n this.el.setAttribute('part', 'debug-panel');\n this.el.setAttribute('role', 'dialog');\n // Odak pencerenin kendisinde (ESC ile kapanır) — butona odaklanınca ipucu kendiliğinden açılıyordu.\n this.el.tabIndex = -1;\n\n const header = document.createElement('div');\n header.className = 'hp-debug-header';\n const title = document.createElement('div');\n title.className = 'hp-debug-title';\n this.titleEl = document.createElement('span');\n this.countEl = document.createElement('span');\n this.countEl.className = 'hp-debug-count';\n title.append(this.titleEl, this.countEl);\n\n const actions = document.createElement('div');\n actions.className = 'hp-debug-actions';\n this.copyBtn = this.button('hp-debug-btn', () => void this.copy());\n this.clearBtn = this.button('hp-debug-btn', () => this.ctx.log.clear());\n this.closeBtn = this.button('hp-stats-close', () => this.hide());\n this.closeBtn.innerHTML = CLOSE_ICON;\n actions.append(this.copyBtn, this.clearBtn, this.closeBtn);\n header.append(title, actions);\n\n this.list = document.createElement('ol');\n this.list.className = 'hp-debug-list';\n this.emptyEl = document.createElement('p');\n this.emptyEl.className = 'hp-debug-empty';\n\n this.el.append(header, this.list, this.emptyEl);\n // Panel tıklamaları / kaydırma videoyu oynat-duraklat yapmasın, klavye kısayolları tetiklenmesin.\n this.el.addEventListener('pointerdown', (e) => e.stopPropagation());\n this.el.addEventListener('click', (e) => e.stopPropagation());\n this.el.addEventListener('dblclick', (e) => e.stopPropagation());\n this.el.addEventListener('keydown', (e) => {\n if (e.key === 'Escape') this.hide();\n e.stopPropagation();\n });\n this.refreshLabels();\n }\n\n get isVisible(): boolean {\n return this.el.isConnected;\n }\n\n show(): void {\n if (!this.isVisible) this.ctx.containerEl.appendChild(this.el);\n this.ctx.log.onChange = () => this.render();\n this.render();\n this.el.focus({ preventScroll: true });\n }\n\n hide(): void {\n if (this.ctx.log.onChange) this.ctx.log.onChange = null;\n this.el.remove();\n }\n\n refreshLabels(): void {\n const t = this.ctx.i18n;\n this.titleEl.textContent = t.debugTitle;\n this.copyBtn.textContent = t.debugCopy;\n this.clearBtn.textContent = t.debugClear;\n this.closeBtn.setAttribute('aria-label', t.debugClose);\n this.emptyEl.textContent = t.debugEmpty;\n if (this.isVisible) this.render();\n }\n\n destroy(): void {\n if (this.copiedTimer) clearTimeout(this.copiedTimer);\n this.hide();\n }\n\n private button(className: string, onClick: () => void): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = className;\n btn.addEventListener('click', onClick);\n return btn;\n }\n\n private sourceLabel(source: PlayerLogSource): string {\n const t = this.ctx.i18n;\n return { media: t.debugSourceMedia, stream: t.debugSourceStream, ads: t.debugSourceAds, subtitles: t.debugSourceSubtitles, player: t.debugSourcePlayer }[source];\n }\n\n private render(): void {\n const entries = this.ctx.log.entries;\n this.countEl.textContent = entries.length ? String(entries.length) : '';\n this.emptyEl.hidden = entries.length > 0;\n this.clearBtn.disabled = entries.length === 0;\n this.copyBtn.disabled = entries.length === 0;\n // En yeni en üstte.\n this.list.replaceChildren(...[...entries].reverse().map((e) => this.row(e)));\n }\n\n private row(entry: PlayerLogEntry): HTMLLIElement {\n const li = document.createElement('li');\n li.className = 'hp-debug-row';\n if (entry.fatal) li.setAttribute('data-fatal', '');\n\n const head = document.createElement('div');\n head.className = 'hp-debug-row-head';\n const time = document.createElement('time');\n time.className = 'hp-debug-time';\n const d = new Date(entry.time);\n time.textContent = `${d.toLocaleTimeString([], { hour12: false })}.${String(d.getMilliseconds()).padStart(3, '0')}`;\n const source = document.createElement('span');\n source.className = 'hp-debug-source';\n source.setAttribute('data-source', entry.source);\n source.textContent = this.sourceLabel(entry.source);\n head.append(time, source);\n if (entry.fatal) {\n const fatal = document.createElement('span');\n fatal.className = 'hp-debug-fatal';\n fatal.textContent = this.ctx.i18n.debugFatal;\n head.appendChild(fatal);\n }\n\n const message = document.createElement('div');\n message.className = 'hp-debug-message';\n message.textContent = entry.message;\n if (entry.count && entry.count > 1) {\n const repeat = document.createElement('span');\n repeat.className = 'hp-debug-repeat';\n repeat.textContent = ` ×${entry.count}`;\n message.appendChild(repeat);\n }\n li.append(head, message);\n\n const details = Object.entries(entry.details ?? {}).filter(([, v]) => v !== undefined && v !== '');\n if (details.length) {\n const dl = document.createElement('dl');\n dl.className = 'hp-debug-details';\n for (const [k, v] of details) {\n const dt = document.createElement('dt');\n dt.textContent = k;\n const dd = document.createElement('dd');\n dd.textContent = String(v);\n dl.append(dt, dd);\n }\n li.appendChild(dl);\n }\n return li;\n }\n\n private async copy(): Promise<void> {\n const text = `HopeCorePlayer ${this.ctx.version} · ${navigator.userAgent}\\n${this.ctx.log.toText()}`;\n try {\n await navigator.clipboard.writeText(text);\n } catch {\n return;\n }\n this.copyBtn.textContent = this.ctx.i18n.debugCopied;\n if (this.copiedTimer) clearTimeout(this.copiedTimer);\n this.copiedTimer = setTimeout(() => {\n this.copiedTimer = null;\n this.copyBtn.textContent = this.ctx.i18n.debugCopy;\n }, 1500);\n }\n}\n","import { DebugPanel, type DebugPanelContext } from './DebugPanel';\n\nexport function installDebugPanel(ctx: DebugPanelContext): DebugPanel {\n return new DebugPanel(ctx);\n}\n\nexport { DebugPanel };\nexport type { DebugPanelContext };\n"],"names":["CLOSE_ICON","DebugPanel","ctx","__publicField","header","title","actions","e","className","onClick","btn","source","t","entries","entry","li","head","time","d","fatal","message","repeat","details","v","dl","k","dt","dd","text","installDebugPanel"],"mappings":"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"}
@@ -49,4 +49,4 @@ export {
49
49
  u as Dubbing,
50
50
  d as installDubbing
51
51
  };
52
- //# sourceMappingURL=index-DXWK4EFa.js.map
52
+ //# sourceMappingURL=dubbing-kNMPpyHl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dubbing-kNMPpyHl.js","sources":["../../src/plugins/dubbing/Dubbing.ts","../../src/plugins/dubbing/index.ts"],"sourcesContent":["import type { SettingsSubmenuDef } from '../../controls/SettingsMenu';\nimport type { DubbingOptions, DubbingTrack } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\n\nexport interface DubbingPlayerContext {\n videoEl: HTMLVideoElement;\n loadSource(src: string, type?: string): Promise<void>;\n registerSubmenu(def: SettingsSubmenuDef): void;\n unregisterSubmenu(key: string): void;\n i18n: HopeLocaleStrings;\n}\n\nconst SUBMENU_KEY = 'dubbing';\n\nfunction dubLangCode(track: DubbingTrack): string {\n return (track.srclang || track.label || '').toUpperCase().slice(0, 3);\n}\n\n/** Ayarlar menüsüne \"Ses/Dil\" alt menüsü ekler (registerSubmenu). */\nexport class Dubbing {\n private activeIndex: number;\n\n constructor(\n private readonly ctx: DubbingPlayerContext,\n private readonly options: DubbingOptions\n ) {\n const defaultIdx = options.tracks.findIndex((t) => t.default);\n this.activeIndex = defaultIdx >= 0 ? defaultIdx : 0;\n\n this.registerMenu();\n }\n\n /** Dil sonradan değişince başlığı güncel `ctx.i18n.dubbingTitle`'la yeniden kaydeder — `registerSubmenu` aynı key'i replace eder. */\n refreshLabels(): void {\n this.registerMenu();\n }\n\n private registerMenu(): void {\n this.ctx.registerSubmenu({\n key: SUBMENU_KEY,\n title: this.ctx.i18n.dubbingTitle,\n getValueLabel: () => dubLangCode(this.options.tracks[this.activeIndex]!),\n getItems: () =>\n this.options.tracks.map((track, i) => ({\n label: track.label,\n active: i === this.activeIndex,\n onSelect: () => this.select(i),\n })),\n });\n }\n\n destroy(): void {\n this.ctx.unregisterSubmenu(SUBMENU_KEY);\n }\n\n private select(index: number): void {\n if (index === this.activeIndex) return;\n const track = this.options.tracks[index];\n if (!track) return;\n\n const resumeTime = this.ctx.videoEl.currentTime;\n const wasPlaying = !this.ctx.videoEl.paused;\n this.activeIndex = index;\n\n void this.ctx.loadSource(track.src, track.type).then(() => {\n this.ctx.videoEl.currentTime = resumeTime;\n if (wasPlaying) void this.ctx.videoEl.play().catch(() => {});\n });\n }\n}\n","import { Dubbing, type DubbingPlayerContext } from './Dubbing';\nimport type { DubbingOptions } from '../../types';\n\nexport function installDubbing(ctx: DubbingPlayerContext, options: DubbingOptions): Dubbing {\n return new Dubbing(ctx, options);\n}\n\nexport { Dubbing };\nexport type { DubbingPlayerContext };\n"],"names":["SUBMENU_KEY","dubLangCode","track","Dubbing","ctx","options","__publicField","defaultIdx","t","i","index","resumeTime","wasPlaying","installDubbing"],"mappings":";;;AAYA,MAAMA,IAAc;AAEpB,SAASC,EAAYC,GAA6B;AAC9C,UAAQA,EAAM,WAAWA,EAAM,SAAS,IAAI,cAAc,MAAM,GAAG,CAAC;AACxE;AAGO,MAAMC,EAAQ;AAAA,EAGjB,YACqBC,GACAC,GACnB;AALM,IAAAC,EAAA;AAGa,SAAA,MAAAF,GACA,KAAA,UAAAC;AAEjB,UAAME,IAAaF,EAAQ,OAAO,UAAU,CAACG,MAAMA,EAAE,OAAO;AAC5D,SAAK,cAAcD,KAAc,IAAIA,IAAa,GAElD,KAAK,aAAA;AAAA,EACT;AAAA;AAAA,EAGA,gBAAsB;AAClB,SAAK,aAAA;AAAA,EACT;AAAA,EAEQ,eAAqB;AACzB,SAAK,IAAI,gBAAgB;AAAA,MACrB,KAAKP;AAAA,MACL,OAAO,KAAK,IAAI,KAAK;AAAA,MACrB,eAAe,MAAMC,EAAY,KAAK,QAAQ,OAAO,KAAK,WAAW,CAAE;AAAA,MACvE,UAAU,MACN,KAAK,QAAQ,OAAO,IAAI,CAACC,GAAOO,OAAO;AAAA,QACnC,OAAOP,EAAM;AAAA,QACb,QAAQO,MAAM,KAAK;AAAA,QACnB,UAAU,MAAM,KAAK,OAAOA,CAAC;AAAA,MAAA,EAC/B;AAAA,IAAA,CACT;AAAA,EACL;AAAA,EAEA,UAAgB;AACZ,SAAK,IAAI,kBAAkBT,CAAW;AAAA,EAC1C;AAAA,EAEQ,OAAOU,GAAqB;AAChC,QAAIA,MAAU,KAAK,YAAa;AAChC,UAAMR,IAAQ,KAAK,QAAQ,OAAOQ,CAAK;AACvC,QAAI,CAACR,EAAO;AAEZ,UAAMS,IAAa,KAAK,IAAI,QAAQ,aAC9BC,IAAa,CAAC,KAAK,IAAI,QAAQ;AACrC,SAAK,cAAcF,GAEd,KAAK,IAAI,WAAWR,EAAM,KAAKA,EAAM,IAAI,EAAE,KAAK,MAAM;AACvD,WAAK,IAAI,QAAQ,cAAcS,GAC3BC,KAAiB,KAAK,IAAI,QAAQ,KAAA,EAAO,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IAC/D,CAAC;AAAA,EACL;AACJ;AClEO,SAASC,EAAeT,GAA2BC,GAAkC;AACxF,SAAO,IAAIF,EAAQC,GAAKC,CAAO;AACnC;"}
@@ -136,4 +136,4 @@ export {
136
136
  g as GeoChecker,
137
137
  m as installGeoChecker
138
138
  };
139
- //# sourceMappingURL=index-BBmuCtKu.js.map
139
+ //# sourceMappingURL=geoChecker-BRtvHwI-.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"geoChecker-BRtvHwI-.js","sources":["../../src/plugins/geo-checker/GeoChecker.ts","../../src/plugins/geo-checker/index.ts"],"sourcesContent":["import type { GeoCheckerOptions } from '../../types';\nimport type { GatePlayerContext } from '../shared/GatePlayerContext';\n\nconst EU_COUNTRIES = [\n 'EU', 'AD', 'AL', 'AT', 'BA', 'BE', 'BG', 'BY', 'CH', 'CS', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FO', 'FR', 'FX', 'GB', 'GI',\n 'GR', 'HR', 'HU', 'IE', 'IS', 'IT', 'LI', 'LT', 'LU', 'LV', 'MC', 'MD', 'MK', 'MT', 'NL', 'NO', 'PL', 'PT', 'RO', 'SE', 'SI',\n 'SJ', 'SK', 'SM', 'UA', 'VA',\n];\nconst MENA_COUNTRIES = [\n 'DZ', 'BH', 'EG', 'IR', 'IQ', 'JO', 'KW', 'LB', 'LY', 'MA', 'OM', 'QA', 'SA', 'PS', 'SD', 'SY', 'TN', 'AE', 'YE',\n 'IL', 'DJ', 'TD', 'SO', 'MR', 'NL',\n];\n\n/** Ücretsiz, API anahtarı gerektirmeyen, CORS'a açık IP-coğrafya servisi. */\nconst DEFAULT_API_URL = 'https://get.geojs.io/v1/ip/geo.json';\n/** geojs'te ülke KODU (`\"TR\"`) — `country` alanı ülke ADI (`\"Türkiye\"`). */\nconst DEFAULT_PARAMETER = 'country_code';\n\n/**\n * IP-coğrafyasına göre erişim kontrolü. API'ye ulaşılamazsa erişime izin verir (fail-open) —\n * güvenlik değil, lisans/yayın bölgesi uyumluluğu.\n */\nexport class GeoChecker {\n private readonly loadingEl: HTMLElement;\n private destroyed = false;\n\n constructor(\n private readonly ctx: GatePlayerContext,\n private readonly options: GeoCheckerOptions\n ) {\n ctx.blockChrome();\n ctx.videoEl.addEventListener('play', this.onPlayWhileBlocked);\n\n this.loadingEl = document.createElement('div');\n this.loadingEl.setAttribute('part', 'geo-loading');\n this.loadingEl.className = 'hp:absolute hp:inset-0 hp:z-40 hp:flex hp:items-center hp:justify-center hp:bg-surface';\n this.loadingEl.innerHTML =\n '<div class=\"hp:w-8 hp:h-8 hp:rounded-full hp:border-2 hp:border-on-surface/30 hp:border-t-accent hp:animate-spin\"></div>';\n ctx.overlayContainerEl.appendChild(this.loadingEl);\n\n void this.check();\n }\n\n /** Uyarı ekranı bir kez (kalıcı olarak) render ediliyor — burada tazelenecek reaktif bir etiket yok, diğer gate plugin'leriyle TUTARLI bir çağrı yüzeyi için var. */\n refreshLabels(): void {\n /* no-op */\n }\n\n destroy(): void {\n this.destroyed = true;\n this.ctx.videoEl.removeEventListener('play', this.onPlayWhileBlocked);\n this.loadingEl.remove();\n }\n\n private readonly onPlayWhileBlocked = (): void => {\n this.ctx.videoEl.pause();\n };\n\n /** Varsayılan geojs: ülke kodu country_code'da (country alanı ülke adı). */\n private async resolveCountry(): Promise<string> {\n if (this.options.getCountry) return String((await this.options.getCountry()) ?? '');\n\n const response = await fetch(this.options.apiUrl || DEFAULT_API_URL);\n if (!response.ok) throw new Error(`HTTP ${response.status}`);\n const data: unknown = await response.json();\n const value = (this.options.parameter || DEFAULT_PARAMETER)\n .split('.')\n .reduce<unknown>((obj, key) => (obj && typeof obj === 'object' ? (obj as Record<string, unknown>)[key] : undefined), data);\n return typeof value === 'string' ? value : '';\n }\n\n private async check(): Promise<void> {\n let allowed = true;\n let userCountry = '';\n\n try {\n userCountry = (await this.resolveCountry()).trim().toUpperCase();\n\n let allowList = this.options.allowedCountries || [];\n if (this.options.region === 'EU') allowList = EU_COUNTRIES;\n else if (this.options.region === 'MENA') allowList = MENA_COUNTRIES;\n\n allowed = allowList.some((code) => code.trim().toUpperCase() === userCountry);\n } catch (err) {\n console.warn('[HopePlayer geo-checker] IP sorgusu başarısız, erişime izin veriliyor:', err);\n allowed = true;\n }\n\n if (this.destroyed) return;\n this.loadingEl.remove();\n\n if (allowed) {\n this.ctx.videoEl.removeEventListener('play', this.onPlayWhileBlocked);\n this.ctx.unblockChrome();\n return;\n }\n\n this.showWarning(userCountry);\n }\n\n private showWarning(country: string): void {\n const el = document.createElement('div');\n el.setAttribute('part', 'geo-warning');\n el.className = 'hp:absolute hp:inset-0 hp:z-40 hp:flex hp:flex-col hp:items-center hp:justify-center hp:gap-2 hp:bg-surface hp:text-on-surface hp:text-center hp:p-4';\n\n const messages = this.options.warningMessages?.length ? this.options.warningMessages : [this.ctx.i18n.geoDefaultWarning];\n for (const msg of messages) {\n const p = document.createElement('p');\n p.className = 'hp:text-sm hp:m-0';\n p.textContent = msg;\n el.appendChild(p);\n }\n\n const countryEl = document.createElement('span');\n countryEl.className = 'hp:text-xs hp:opacity-60';\n countryEl.textContent = country || this.ctx.i18n.geoUnknownCountry;\n el.appendChild(countryEl);\n\n this.ctx.overlayContainerEl.appendChild(el);\n // Erişim kalıcı olarak kapalı — unblockChrome() ÇAĞRILMIYOR.\n }\n}\n","import { GeoChecker } from './GeoChecker';\nimport type { GatePlayerContext } from '../shared/GatePlayerContext';\nimport type { GeoCheckerOptions } from '../../types';\n\nexport function installGeoChecker(ctx: GatePlayerContext, options: GeoCheckerOptions): GeoChecker {\n return new GeoChecker(ctx, options);\n}\n\nexport { GeoChecker };\nexport type { GatePlayerContext };\n"],"names":["EU_COUNTRIES","MENA_COUNTRIES","DEFAULT_API_URL","DEFAULT_PARAMETER","GeoChecker","ctx","options","__publicField","response","data","value","obj","key","allowed","userCountry","allowList","code","err","country","_a","el","messages","msg","p","countryEl","installGeoChecker"],"mappings":"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"}
@@ -65,4 +65,4 @@ export {
65
65
  h as GestureControls,
66
66
  d as installGesture
67
67
  };
68
- //# sourceMappingURL=index-Ca8hocby.js.map
68
+ //# sourceMappingURL=gesture-BzPCgi87.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gesture-BzPCgi87.js","sources":["../../src/plugins/gesture/GestureControls.ts","../../src/plugins/gesture/index.ts"],"sourcesContent":["import type { GestureOptions } from '../../types';\n\nexport interface GesturePlayerContext {\n videoEl: HTMLVideoElement;\n /** Basılı tutma göstergesinin (hız/sarma overlay'i) ekleneceği katman. */\n overlayContainerEl: HTMLElement;\n isAdActive(): boolean;\n}\n\nfunction isMobileDevice(): boolean {\n if (typeof navigator === 'undefined') return false;\n return /Android|iPhone|iPad|iPod/i.test(navigator.userAgent);\n}\n\n/** Basılı tutma: mobilde adım adım ileri sarma, masaüstünde playbackRate hızlandırma. */\nexport class GestureControls {\n private readonly options: Required<GestureOptions>;\n private readonly overlayEl: HTMLElement;\n\n private isHolding = false;\n private holdTimeout: ReturnType<typeof setTimeout> | null = null;\n private holdInterval: ReturnType<typeof setInterval> | null = null;\n private wasPaused = false;\n\n constructor(\n private readonly ctx: GesturePlayerContext,\n options: GestureOptions = {}\n ) {\n this.options = {\n holdRate: options.holdRate ?? 2,\n holdIntervalMs: options.holdIntervalMs ?? 200,\n holdDelayMs: options.holdDelayMs ?? 300,\n };\n\n this.overlayEl = document.createElement('div');\n this.overlayEl.setAttribute('part', 'gesture-overlay');\n this.overlayEl.className =\n 'hp:hidden hp:absolute hp:inset-0 hp:z-20 hp:items-center hp:justify-center hp:gap-2 ' +\n 'hp:bg-black/30 hp:text-white hp:text-xl hp:font-semibold hp:pointer-events-none';\n ctx.overlayContainerEl.appendChild(this.overlayEl);\n\n ctx.videoEl.addEventListener('touchstart', this.onPressStart, { passive: false });\n ctx.videoEl.addEventListener('touchend', this.onPressEnd);\n ctx.videoEl.addEventListener('touchcancel', this.onPressLeave);\n ctx.videoEl.addEventListener('mousedown', this.onPressStart);\n ctx.videoEl.addEventListener('mouseup', this.onPressEnd);\n ctx.videoEl.addEventListener('mouseleave', this.onPressLeave);\n }\n\n /** HopePlayerElement'in kendi \"ekrana tıkla → oynat/duraklat\" tetikleyicisinin bir hold sırasında devre dışı kalması için — tek doğruluk kaynağı burası, ayrı bir zamanlayıcı tekrarlanmıyor. */\n isCurrentlyHolding(): boolean {\n return this.isHolding;\n }\n\n destroy(): void {\n this.ctx.videoEl.removeEventListener('touchstart', this.onPressStart);\n this.ctx.videoEl.removeEventListener('touchend', this.onPressEnd);\n this.ctx.videoEl.removeEventListener('touchcancel', this.onPressLeave);\n this.ctx.videoEl.removeEventListener('mousedown', this.onPressStart);\n this.ctx.videoEl.removeEventListener('mouseup', this.onPressEnd);\n this.ctx.videoEl.removeEventListener('mouseleave', this.onPressLeave);\n if (this.holdTimeout) clearTimeout(this.holdTimeout);\n if (this.holdInterval) clearInterval(this.holdInterval);\n this.overlayEl.remove();\n }\n\n private readonly onPressStart = (e: Event): void => {\n if (this.ctx.isAdActive()) return;\n if (this.ctx.videoEl.ended) return;\n this.wasPaused = this.ctx.videoEl.paused;\n\n this.holdTimeout = setTimeout(() => this.startHold(), this.options.holdDelayMs);\n e.preventDefault();\n };\n\n private startHold(): void {\n if (this.isHolding) return;\n this.isHolding = true;\n\n if (isMobileDevice()) {\n const step = (this.options.holdRate * this.options.holdIntervalMs) / 1000;\n this.holdInterval = setInterval(() => {\n const video = this.ctx.videoEl;\n video.currentTime = Math.min(video.duration || video.currentTime + step, video.currentTime + step);\n }, this.options.holdIntervalMs);\n } else {\n this.ctx.videoEl.playbackRate = this.options.holdRate;\n }\n\n this.showOverlay(`${this.options.holdRate}x »`);\n if (this.ctx.videoEl.paused) void this.ctx.videoEl.play().catch(() => {});\n }\n\n private readonly onPressEnd = (): void => {\n this.endHold();\n };\n\n private readonly onPressLeave = (): void => {\n this.endHold();\n };\n\n private endHold(): void {\n if (this.holdTimeout) {\n clearTimeout(this.holdTimeout);\n this.holdTimeout = null;\n }\n\n // Kısa dokunuş: oynat/duraklat HopePlayerElement'in kendi dinleyicisinde.\n if (!this.isHolding) return;\n\n this.isHolding = false;\n this.ctx.videoEl.playbackRate = 1;\n if (this.holdInterval) {\n clearInterval(this.holdInterval);\n this.holdInterval = null;\n }\n this.hideOverlay();\n\n if (this.wasPaused) this.ctx.videoEl.pause();\n }\n\n private showOverlay(text: string): void {\n this.overlayEl.textContent = text;\n this.overlayEl.classList.remove('hp:hidden');\n this.overlayEl.classList.add('hp:flex');\n }\n\n private hideOverlay(): void {\n this.overlayEl.classList.add('hp:hidden');\n this.overlayEl.classList.remove('hp:flex');\n }\n}\n","import { GestureControls, type GesturePlayerContext } from './GestureControls';\nimport type { GestureOptions } from '../../types';\n\nexport function installGesture(ctx: GesturePlayerContext, options: GestureOptions): GestureControls {\n return new GestureControls(ctx, options);\n}\n\nexport { GestureControls };\nexport type { GesturePlayerContext };\n"],"names":["isMobileDevice","GestureControls","ctx","options","__publicField","step","video","text","installGesture"],"mappings":"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"}
@@ -15,4 +15,4 @@ function d() {
15
15
  export {
16
16
  d as l
17
17
  };
18
- //# sourceMappingURL=loadGpt-CmiAy366.js.map
18
+ //# sourceMappingURL=gpt-CGXHTG_H.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gpt-CGXHTG_H.js","sources":["../../src/plugins/pause-ad/loadGpt.ts"],"sourcesContent":["/** Google Publisher Tag (GPT) için kullanılan minimal yüzey. */\nexport interface GptSlot {\n addService(service: unknown): GptSlot;\n setTargeting(key: string, value: string | string[]): GptSlot;\n getSlotElementId(): string;\n}\n\nexport interface GptSlotRenderEndedEvent {\n slot: GptSlot;\n isEmpty: boolean;\n size: [number, number] | number[] | null;\n}\n\nexport interface GptPubAds {\n addEventListener(type: 'slotRenderEnded', listener: (e: GptSlotRenderEndedEvent) => void): void;\n removeEventListener?(type: 'slotRenderEnded', listener: (e: GptSlotRenderEndedEvent) => void): void;\n refresh(slots: GptSlot[]): void;\n isInitialLoadDisabled(): boolean;\n}\n\nexport interface GoogleTag {\n cmd: Array<() => void> | { push(fn: () => void): void };\n defineSlot(adUnitPath: string, sizes: Array<[number, number]>, divId: string): GptSlot | null;\n /** Out-of-page slot: boyutsuz; içerik (ör. özel HTML, tam sayfa kreatif) Ad Manager'da belirlenir. */\n defineOutOfPageSlot(adUnitPath: string, divId: string): GptSlot | null;\n pubads(): GptPubAds;\n enableServices(): void;\n display(divId: string): void;\n destroySlots(slots?: GptSlot[]): boolean;\n}\n\ndeclare global {\n interface Window {\n googletag?: GoogleTag;\n }\n}\n\nconst GPT_SRC = 'https://securepubads.g.doubleclick.net/tag/js/gpt.js';\nlet loading: Promise<GoogleTag> | null = null;\n\n/** GPT'yi bir kez yükler; sayfada zaten varsa onu kullanır. Komutlar googletag.cmd kuyruğuyla çalışır. */\nexport function loadGpt(): Promise<GoogleTag> {\n if (loading) return loading;\n window.googletag = window.googletag || ({ cmd: [] } as unknown as GoogleTag);\n loading = new Promise((resolve, reject) => {\n const ready = (): void => {\n window.googletag!.cmd.push(() => resolve(window.googletag!));\n };\n if (document.querySelector(`script[src=\"${GPT_SRC}\"]`)) return ready();\n const script = document.createElement('script');\n script.async = true;\n script.src = GPT_SRC;\n script.onload = ready;\n script.onerror = () => {\n loading = null;\n reject(new Error('GPT yüklenemedi'));\n };\n document.head.appendChild(script);\n });\n return loading;\n}\n"],"names":["GPT_SRC","loading","loadGpt","resolve","reject","ready","script"],"mappings":"AAqCA,MAAMA,IAAU;AAChB,IAAIC,IAAqC;AAGlC,SAASC,IAA8B;AAC1C,SAAID,MACJ,OAAO,YAAY,OAAO,aAAc,EAAE,KAAK,CAAA,EAAC,GAChDA,IAAU,IAAI,QAAQ,CAACE,GAASC,MAAW;AACvC,UAAMC,IAAQ,MAAY;AACtB,aAAO,UAAW,IAAI,KAAK,MAAMF,EAAQ,OAAO,SAAU,CAAC;AAAA,IAC/D;AACA,QAAI,SAAS,cAAc,eAAeH,CAAO,IAAI,UAAUK,EAAA;AAC/D,UAAMC,IAAS,SAAS,cAAc,QAAQ;AAC9C,IAAAA,EAAO,QAAQ,IACfA,EAAO,MAAMN,GACbM,EAAO,SAASD,GAChBC,EAAO,UAAU,MAAM;AACnB,MAAAL,IAAU,MACVG,EAAO,IAAI,MAAM,iBAAiB,CAAC;AAAA,IACvC,GACA,SAAS,KAAK,YAAYE,CAAM;AAAA,EACpC,CAAC,GACML;AACX;"}
@@ -36,4 +36,4 @@ export {
36
36
  o as InViewAutoplay,
37
37
  d as installInViewAutoplay
38
38
  };
39
- //# sourceMappingURL=index-3QALpwsf.js.map
39
+ //# sourceMappingURL=inViewAutoplay-CRJe7GA4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inViewAutoplay-CRJe7GA4.js","sources":["../../src/plugins/in-view-autoplay/InViewAutoplay.ts","../../src/plugins/in-view-autoplay/index.ts"],"sourcesContent":["import type { InViewAutoplayOptions } from '../../types';\n\nexport interface InViewAutoplayPlayerContext {\n videoEl: HTMLVideoElement;\n /** IntersectionObserver'ın izlediği kök element — genelde player'ın host custom element'i. */\n observeEl: Element;\n isAdActive(): boolean;\n}\n\n/** Viewport dışına çıkınca duraklat; yalnızca bu plugin duraklattıysa geri girince devam et. */\nexport class InViewAutoplay {\n private readonly threshold: number;\n private readonly onlyIfMuted: boolean;\n private readonly observer: IntersectionObserver;\n private pausedByThis = false;\n\n constructor(\n private readonly ctx: InViewAutoplayPlayerContext,\n options: InViewAutoplayOptions = {}\n ) {\n this.threshold = options.threshold ?? 0.3;\n this.onlyIfMuted = options.onlyIfMuted ?? true;\n\n this.observer = new IntersectionObserver(this.onIntersect, { threshold: [this.threshold] });\n this.observer.observe(ctx.observeEl);\n }\n\n destroy(): void {\n this.observer.disconnect();\n }\n\n private readonly onIntersect = (entries: IntersectionObserverEntry[]): void => {\n if (this.ctx.isAdActive()) return;\n\n for (const entry of entries) {\n if (entry.isIntersecting && entry.intersectionRatio >= this.threshold) {\n this.resumeIfPausedByThis();\n } else {\n this.pauseIfPlaying();\n }\n }\n };\n\n private pauseIfPlaying(): void {\n const video = this.ctx.videoEl;\n if (video.paused || video.ended) return;\n this.pausedByThis = true;\n video.pause();\n }\n\n private resumeIfPausedByThis(): void {\n if (!this.pausedByThis) return;\n this.pausedByThis = false;\n const video = this.ctx.videoEl;\n if (this.onlyIfMuted && !video.muted) return;\n void video.play().catch(() => {});\n }\n}\n","import { InViewAutoplay, type InViewAutoplayPlayerContext } from './InViewAutoplay';\nimport type { InViewAutoplayOptions } from '../../types';\n\nexport function installInViewAutoplay(ctx: InViewAutoplayPlayerContext, options: InViewAutoplayOptions): InViewAutoplay {\n return new InViewAutoplay(ctx, options);\n}\n\nexport { InViewAutoplay };\nexport type { InViewAutoplayPlayerContext };\n"],"names":["InViewAutoplay","ctx","options","__publicField","entries","entry","video","installInViewAutoplay"],"mappings":";;;AAUO,MAAMA,EAAe;AAAA,EAMxB,YACqBC,GACjBC,IAAiC,IACnC;AARe,IAAAC,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACT,IAAAA,EAAA,sBAAe;AAiBN,IAAAA,EAAA,qBAAc,CAACC,MAA+C;AAC3E,UAAI,MAAK,IAAI;AAEb,mBAAWC,KAASD;AAChB,UAAIC,EAAM,kBAAkBA,EAAM,qBAAqB,KAAK,YACxD,KAAK,qBAAA,IAEL,KAAK,eAAA;AAAA,IAGjB;AAxBqB,SAAA,MAAAJ,GAGjB,KAAK,YAAYC,EAAQ,aAAa,KACtC,KAAK,cAAcA,EAAQ,eAAe,IAE1C,KAAK,WAAW,IAAI,qBAAqB,KAAK,aAAa,EAAE,WAAW,CAAC,KAAK,SAAS,GAAG,GAC1F,KAAK,SAAS,QAAQD,EAAI,SAAS;AAAA,EACvC;AAAA,EAEA,UAAgB;AACZ,SAAK,SAAS,WAAA;AAAA,EAClB;AAAA,EAcQ,iBAAuB;AAC3B,UAAMK,IAAQ,KAAK,IAAI;AACvB,IAAIA,EAAM,UAAUA,EAAM,UAC1B,KAAK,eAAe,IACpBA,EAAM,MAAA;AAAA,EACV;AAAA,EAEQ,uBAA6B;AACjC,QAAI,CAAC,KAAK,aAAc;AACxB,SAAK,eAAe;AACpB,UAAMA,IAAQ,KAAK,IAAI;AACvB,IAAI,KAAK,eAAe,CAACA,EAAM,SAC1BA,EAAM,OAAO,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EACpC;AACJ;ACtDO,SAASC,EAAsBN,GAAkCC,GAAgD;AACpH,SAAO,IAAIF,EAAeC,GAAKC,CAAO;AAC1C;"}
@@ -142,4 +142,4 @@ export {
142
142
  u as LiveWallClock,
143
143
  k as installLiveWallClock
144
144
  };
145
- //# sourceMappingURL=index-7IBf8Y-R.js.map
145
+ //# sourceMappingURL=liveWallClock-ChUTtzLD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"liveWallClock-ChUTtzLD.js","sources":["../../src/plugins/live/LiveWallClock.ts","../../src/plugins/live/index.ts"],"sourcesContent":["import type { LiveWallClockOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\n\nexport interface LiveWallClockPlayerContext {\n videoEl: HTMLVideoElement;\n seekBarEl: HTMLElement;\n addControlElement(el: HTMLElement): void;\n /** UI dili (chrome metinleri) — `options.locale` (Intl saat biçimlendirme locale'i, ör. 'tr-TR') ile KARIŞTIRILMASIN, ayrı bir kavram. */\n i18n: HopeLocaleStrings;\n /**\n * Şu an oynatılan anın gerçek tarihi — HLS `EXT-X-PROGRAM-DATE-TIME`'dan (hls.js `playingDate`, Safari `getStartDate()`).\n * Yoksa null; saat o zaman \"canlı uçtan geride kalınan süre\"den tahmin edilir.\n */\n getPlayingDate?(): Date | null;\n}\n\nconst DEFAULTS: Required<LiveWallClockOptions> = {\n locale: 'tr-TR',\n timeZone: 'UTC',\n showSeconds: true,\n tooltipMode: 'clock',\n};\n\n/**\n * Canlı yayında duvar saati + seek bar hover tooltip'i. Yayında PROGRAM-DATE-TIME varsa saat doğrudan oradan okunur\n * (encoder/CDN gecikmesi dahil doğru); yoksa canlı uç (seekable, yoksa buffered sonu) anının şu anki saat olduğu varsayılır.\n */\nexport class LiveWallClock {\n private readonly clockEl: HTMLElement;\n private readonly tooltipEl: HTMLElement;\n private readonly options: Required<LiveWallClockOptions>;\n\n private clockTimer: ReturnType<typeof setTimeout> | null = null;\n private tooltipTimer: ReturnType<typeof setTimeout> | null = null;\n private isHovering = false;\n private lastSeekBarPoint: number | null = null;\n\n constructor(\n private readonly ctx: LiveWallClockPlayerContext,\n options: LiveWallClockOptions = {}\n ) {\n this.options = { ...DEFAULTS, ...options };\n\n this.clockEl = document.createElement('span');\n this.clockEl.setAttribute('part', 'live-clock');\n this.clockEl.setAttribute('role', 'status');\n this.clockEl.setAttribute('aria-label', ctx.i18n.liveClock);\n this.clockEl.className = 'hp:hidden hp:text-xs hp:text-on-surface hp:opacity-90 hp:tabular-nums hp:whitespace-nowrap hp:ml-1';\n ctx.addControlElement(this.clockEl);\n\n this.tooltipEl = document.createElement('div');\n this.tooltipEl.setAttribute('part', 'live-tooltip');\n this.tooltipEl.className =\n 'hp:hidden hp:absolute hp:bottom-full hp:mb-2 hp-center-x hp:px-2 hp:py-1 hp:rounded hp:bg-surface-elev hp:text-on-surface hp:text-xs hp:tabular-nums hp:whitespace-nowrap hp:pointer-events-none hp:z-20';\n ctx.seekBarEl.appendChild(this.tooltipEl);\n\n ctx.seekBarEl.addEventListener('mouseenter', this.onSeekEnter);\n ctx.seekBarEl.addEventListener('mouseleave', this.onSeekLeave);\n ctx.seekBarEl.addEventListener('mousemove', this.onSeekMove);\n\n this.startClockTick();\n }\n\n refreshLabels(): void {\n this.clockEl.setAttribute('aria-label', this.ctx.i18n.liveClock);\n }\n\n destroy(): void {\n this.stopClockTick();\n this.stopTooltipTick();\n this.ctx.seekBarEl.removeEventListener('mouseenter', this.onSeekEnter);\n this.ctx.seekBarEl.removeEventListener('mouseleave', this.onSeekLeave);\n this.ctx.seekBarEl.removeEventListener('mousemove', this.onSeekMove);\n this.clockEl.remove();\n this.tooltipEl.remove();\n }\n\n /** Canlılık için duration === Infinity yeterli — native HLS'te DVR'sız canlıda seekable boş kalabiliyor. */\n private isLive(): boolean {\n return this.ctx.videoEl.duration === Infinity;\n }\n\n /** Canlı edge'in media-time'ı (saniye) — seekable aralığının sonu; seekable boşsa (bkz. isLive notu) buffered aralığının sonu. */\n private liveEdge(): number | null {\n const { seekable, buffered } = this.ctx.videoEl;\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 /** Geri sarılabilir pencerenin başı — kayan pencereli canlıda 0 değil (ör. 3600). */\n private windowStart(): number {\n const { seekable, buffered } = this.ctx.videoEl;\n if (seekable.length) return seekable.start(0);\n if (buffered.length) return buffered.start(0);\n return 0;\n }\n\n /** `mediaTime` anının duvar saati (ms) — PROGRAM-DATE-TIME varsa ondan, yoksa canlı uca göre tahmin. */\n private wallClockAt(mediaTime: number, liveEdge: number): number {\n const playing = this.ctx.getPlayingDate?.();\n if (playing && Number.isFinite(playing.getTime())) return playing.getTime() + (mediaTime - this.ctx.videoEl.currentTime) * 1000;\n return Date.now() - Math.max(0, liveEdge - mediaTime) * 1000;\n }\n\n // ── saat ──\n\n private startClockTick(): void {\n const tick = () => {\n this.renderClock();\n const delay = 1000 - (Date.now() % 1000);\n this.clockTimer = setTimeout(tick, delay);\n };\n tick();\n }\n\n private stopClockTick(): void {\n if (this.clockTimer) {\n clearTimeout(this.clockTimer);\n this.clockTimer = null;\n }\n }\n\n private renderClock(): void {\n if (!this.isLive()) {\n this.clockEl.classList.add('hp:hidden');\n return;\n }\n\n const liveNow = this.liveEdge();\n const ct = this.ctx.videoEl.currentTime;\n if (liveNow === null || !Number.isFinite(ct)) {\n this.clockEl.textContent = '--:--:--';\n this.clockEl.classList.remove('hp:hidden');\n return;\n }\n\n this.clockEl.textContent = this.formatClock(new Date(this.wallClockAt(ct, liveNow)));\n this.clockEl.classList.remove('hp:hidden');\n }\n\n // ── seekbar hover tooltip ──\n\n private readonly onSeekEnter = (): void => {\n this.isHovering = true;\n this.renderTooltip();\n this.startTooltipTick();\n };\n\n private readonly onSeekLeave = (): void => {\n this.isHovering = false;\n this.lastSeekBarPoint = null;\n this.stopTooltipTick();\n this.hideTooltip();\n };\n\n private readonly onSeekMove = (e: MouseEvent): void => {\n const rect = this.ctx.seekBarEl.getBoundingClientRect();\n const ratio = rect.width > 0 ? (e.clientX - rect.left) / rect.width : null;\n this.lastSeekBarPoint = ratio === null ? null : Math.max(0, Math.min(1, ratio));\n this.renderTooltip();\n this.startTooltipTick();\n };\n\n private startTooltipTick(): void {\n if (this.tooltipTimer) return;\n const tick = () => {\n if (!this.isHovering || this.lastSeekBarPoint == null) {\n this.tooltipTimer = null;\n return;\n }\n this.renderTooltip();\n const delay = 1000 - (Date.now() % 1000);\n this.tooltipTimer = setTimeout(tick, delay);\n };\n tick();\n }\n\n private stopTooltipTick(): void {\n if (this.tooltipTimer) {\n clearTimeout(this.tooltipTimer);\n this.tooltipTimer = null;\n }\n }\n\n private renderTooltip(): void {\n if (!this.isLive() || this.lastSeekBarPoint == null) {\n this.hideTooltip();\n return;\n }\n\n const liveEdge = this.liveEdge();\n if (liveEdge === null || liveEdge <= 0) {\n this.hideTooltip();\n return;\n }\n\n // Seek bar canlıda geri sarılabilir pencereyi (başı → canlı uç) temsil eder.\n const start = Math.min(this.windowStart(), liveEdge);\n const hoveredTime = start + this.lastSeekBarPoint * (liveEdge - start);\n const secondsBehind = Math.max(0, liveEdge - hoveredTime);\n const wallClock = this.formatClock(new Date(this.wallClockAt(hoveredTime, liveEdge)));\n const minus = `-${this.formatDuration(secondsBehind)}`;\n\n this.tooltipEl.innerHTML = '';\n if (this.options.tooltipMode === 'behind') {\n this.tooltipEl.textContent = minus;\n } else if (this.options.tooltipMode === 'both') {\n const line1 = document.createElement('div');\n line1.textContent = wallClock;\n const line2 = document.createElement('div');\n line2.textContent = minus;\n line2.className = 'hp:opacity-70';\n this.tooltipEl.append(line1, line2);\n } else {\n this.tooltipEl.textContent = wallClock;\n }\n\n this.tooltipEl.style.left = `${this.lastSeekBarPoint * 100}%`;\n this.tooltipEl.classList.remove('hp:hidden');\n }\n\n private hideTooltip(): void {\n this.tooltipEl.classList.add('hp:hidden');\n }\n\n // ── format ──\n\n private formatClock(date: Date): string {\n const fmtOpts: Intl.DateTimeFormatOptions = this.options.showSeconds\n ? { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false, timeZone: this.options.timeZone }\n : { hour: '2-digit', minute: '2-digit', hour12: false, timeZone: this.options.timeZone };\n try {\n return new Intl.DateTimeFormat(this.options.locale, fmtOpts).format(date);\n } catch {\n const pad = (n: number) => String(n).padStart(2, '0');\n const base = `${pad(date.getHours())}:${pad(date.getMinutes())}`;\n return this.options.showSeconds ? `${base}:${pad(date.getSeconds())}` : base;\n }\n }\n\n private formatDuration(totalSeconds: number): string {\n const s = Math.floor(totalSeconds);\n const hh = Math.floor(s / 3600);\n const mm = Math.floor((s % 3600) / 60);\n const ss = s % 60;\n const pad = (n: number) => String(n).padStart(2, '0');\n return hh > 0 ? `${pad(hh)}:${pad(mm)}:${pad(ss)}` : `${pad(mm)}:${pad(ss)}`;\n }\n}\n","import { LiveWallClock, type LiveWallClockPlayerContext } from './LiveWallClock';\nimport type { LiveWallClockOptions } from '../../types';\n\nexport function installLiveWallClock(ctx: LiveWallClockPlayerContext, options: LiveWallClockOptions): LiveWallClock {\n return new LiveWallClock(ctx, options);\n}\n\nexport { LiveWallClock };\nexport type { LiveWallClockPlayerContext };\n"],"names":["DEFAULTS","LiveWallClock","ctx","options","__publicField","e","rect","ratio","seekable","buffered","mediaTime","liveEdge","_a","_b","playing","tick","delay","liveNow","ct","start","hoveredTime","secondsBehind","wallClock","minus","line1","line2","date","fmtOpts","pad","n","base","totalSeconds","s","hh","mm","ss","installLiveWallClock"],"mappings":"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"}
@@ -72,4 +72,4 @@ export {
72
72
  E as LoopSection,
73
73
  S as installLoopSection
74
74
  };
75
- //# sourceMappingURL=index-f0vSgRIK.js.map
75
+ //# sourceMappingURL=loopSection-CvF4l5uf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loopSection-CvF4l5uf.js","sources":["../../src/plugins/loop-section/LoopSection.ts","../../src/plugins/loop-section/index.ts"],"sourcesContent":["import type { LoopSectionOptions } from '../../types';\n\nexport interface LoopSeekBarMarkers {\n addMarker(ratio: number, extraClass?: string): HTMLDivElement;\n clearMarkers(): void;\n}\n\nexport interface LoopSectionState {\n active: boolean;\n loopStart: number | null;\n loopEnd: number | null;\n}\n\n/** A/B döngü motoru. */\nexport class LoopSection {\n private readonly seconds: number;\n loopStart: number | null = null;\n loopEnd: number | null = null;\n active = false;\n\n constructor(\n private readonly video: HTMLVideoElement,\n private readonly markers: LoopSeekBarMarkers,\n options: LoopSectionOptions = {}\n ) {\n this.seconds = options.seconds || 10;\n }\n\n /** currentTime'dan geriye doğru tam N saniyelik bir aralığı döngüye alır (video başına yakınsa ileri doğru taşar). */\n enableLastN(secs?: number): void {\n const now = this.video.currentTime;\n const duration = this.video.duration;\n const s = secs || this.seconds;\n this.loopStart = Math.max(0, now - s);\n this.loopEnd = Math.min(Number.isFinite(duration) ? duration : Infinity, this.loopStart + s);\n this.activate();\n this.updateMarkers();\n }\n\n setStart(time?: number): void {\n this.loopStart = time ?? this.video.currentTime;\n this.updateMarkers();\n }\n\n setEnd(time?: number): void {\n this.loopEnd = time ?? this.video.currentTime;\n if (this.loopStart !== null && this.loopEnd > this.loopStart) {\n this.activate();\n this.updateMarkers();\n }\n }\n\n toggle(): void {\n if (this.active) this.disable();\n else this.enableLastN();\n }\n\n disable(): void {\n this.active = false;\n this.loopStart = null;\n this.loopEnd = null;\n this.video.removeEventListener('timeupdate', this.onTimeUpdate);\n this.markers.clearMarkers();\n }\n\n getState(): LoopSectionState {\n return { active: this.active, loopStart: this.loopStart, loopEnd: this.loopEnd };\n }\n\n /** `installLoopSection` bunu gerçek buton etiketini tazeleyen bir implementasyonla override eder (bkz. index.ts) — `destroy`'un üzerine yazılma deseniyle aynı. */\n refreshLabels(): void {\n /* no-op varsayılan */\n }\n\n destroy(): void {\n this.disable();\n }\n\n private activate(): void {\n this.active = true;\n this.video.removeEventListener('timeupdate', this.onTimeUpdate);\n this.video.addEventListener('timeupdate', this.onTimeUpdate);\n }\n\n private readonly onTimeUpdate = (): void => {\n if (this.loopEnd !== null && this.video.currentTime >= this.loopEnd) {\n this.video.currentTime = this.loopStart ?? 0;\n }\n };\n\n private updateMarkers(): void {\n this.markers.clearMarkers();\n const duration = this.video.duration;\n if (!duration || !Number.isFinite(duration)) return;\n\n if (this.loopStart !== null) {\n this.markers.addMarker(this.loopStart / duration, 'hp:bg-accent');\n }\n if (this.loopEnd !== null) {\n this.markers.addMarker(this.loopEnd / duration, 'hp:bg-accent');\n }\n }\n}\n","import { LoopSection, type LoopSeekBarMarkers } from './LoopSection';\nimport type { LoopSectionOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\n\nexport interface LoopSectionPlayerContext {\n videoEl: HTMLVideoElement;\n seekBarEl: HTMLElement;\n markers: LoopSeekBarMarkers;\n addControlButton(label: string, iconName: string, onClick: () => void): { btn: HTMLButtonElement; icon: HTMLElement };\n i18n: HopeLocaleStrings;\n}\n\n/** Döngü motorunu kurar: kontrol çubuğuna toggle butonu, seek bar'da orta-tık ile A → B → kapat. */\nexport function installLoopSection(ctx: LoopSectionPlayerContext, options: LoopSectionOptions): LoopSection {\n const engine = new LoopSection(ctx.videoEl, ctx.markers, options);\n\n const { btn } = ctx.addControlButton(ctx.i18n.loop, 'loop', () => {\n engine.toggle();\n refresh();\n });\n\n const refresh = (): void => {\n btn.classList.toggle('hp:text-accent', engine.active);\n };\n\n engine.refreshLabels = () => {\n btn.setAttribute('aria-label', ctx.i18n.loop);\n };\n\n const onSeekBarMiddleClick = (e: MouseEvent): void => {\n if (e.button !== 1) return;\n e.preventDefault();\n\n const rect = ctx.seekBarEl.getBoundingClientRect();\n const ratio = Math.min(1, Math.max(0, (e.clientX - rect.left) / rect.width));\n const duration = ctx.videoEl.duration;\n const clickTime = Number.isFinite(duration) ? ratio * duration : undefined;\n\n const state = engine.getState();\n if (state.active) engine.disable();\n else if (state.loopStart === null) engine.setStart(clickTime);\n else engine.setEnd(clickTime);\n\n refresh();\n };\n ctx.seekBarEl.addEventListener('mousedown', onSeekBarMiddleClick);\n\n const originalDestroy = engine.destroy.bind(engine);\n engine.destroy = () => {\n ctx.seekBarEl.removeEventListener('mousedown', onSeekBarMiddleClick);\n originalDestroy();\n };\n\n return engine;\n}\n\nexport { LoopSection };\nexport type { LoopSeekBarMarkers };\n"],"names":["LoopSection","video","markers","options","__publicField","secs","now","duration","s","time","installLoopSection","ctx","engine","btn","refresh","onSeekBarMiddleClick","e","rect","ratio","clickTime","state","originalDestroy"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  var u = Object.defineProperty;
2
2
  var m = (p, e, t) => e in p ? u(p, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : p[e] = t;
3
3
  var o = (p, e, t) => m(p, typeof e != "symbol" ? e + "" : e, t);
4
- import { c as b } from "./index-DEv3YqLg.js";
4
+ import { c as b } from "./player-C886oKP-.js";
5
5
  const f = {
6
6
  enabled: !1,
7
7
  mode: "rich",
@@ -202,4 +202,4 @@ export {
202
202
  v as MarkProgress,
203
203
  y as installMarkers
204
204
  };
205
- //# sourceMappingURL=index-e00_M05B.js.map
205
+ //# sourceMappingURL=markers-DE4O8xbw.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markers-DE4O8xbw.js","sources":["../../src/plugins/markers/MarkProgress.ts","../../src/plugins/markers/index.ts"],"sourcesContent":["import { createIcon } from '../../icons/Icon';\nimport type { MarkerItem, MarkerPingOptions, MarkerPopupOptions, MarkersOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\n\nexport interface MarkersPlayerContext {\n videoEl: HTMLVideoElement;\n /** Popup overlay'in ekleneceği katman (shadow root içinde, video üzerinde). */\n overlayContainerEl: HTMLElement;\n /** Seek bar üzerinde işaretçi çizmek için — SeekBar.addMarker ile aynı imza. */\n addSeekBarMarker(ratio: number, extraClass?: string): HTMLDivElement;\n i18n: HopeLocaleStrings;\n}\n\ninterface NormalizedMarker extends Required<Pick<MarkerItem, 'time'>> {\n idx: number;\n color?: string;\n label: string;\n pauseOnHit: boolean;\n once: boolean;\n tolerance: number;\n cooldownMs: number;\n action?: MarkerItem['action'];\n popup: MarkerPopupOptions | null;\n pingUrl: string;\n el?: HTMLElement;\n}\n\nconst POPUP_DEFAULTS: Required<MarkerPopupOptions> = {\n enabled: false,\n mode: 'rich',\n text: '',\n imageUrl: '',\n imageAlt: '',\n linkUrl: '',\n // Boş bırakılıyor (sentinel) — gerçek varsayılan metin showPopup()'ta\n // `ctx.i18n.markerLearnMore`/`markerContinue`'dan okunuyor, dil\n // değişimini takip edebilsin diye burada SABİT bir dilde gömülü değil.\n linkText: '',\n continueText: '',\n showContinue: true,\n showClose: true,\n autoplayOnClose: true,\n autoplayOnContinue: true,\n};\n\nconst PING_DEFAULTS: Required<MarkerPingOptions> = { enabled: false, url: '', method: 'GET', includeMarker: false };\n\n/** Zaman tabanlı seek bar işaretçileri — seek/jump koruması, once/cooldown, popup/ping/aksiyon. */\nexport class MarkProgress {\n private readonly markers: NormalizedMarker[];\n private readonly popupGlobal: Required<MarkerPopupOptions>;\n private readonly pingGlobal: Required<MarkerPingOptions>;\n private readonly triggerOnSeek: boolean;\n private readonly seekJumpThresholdSec: number;\n private readonly seekIgnoreWindowMs: number;\n\n private hitSet = new Set<string>();\n private lastHitAt = new Map<string, number>();\n private lastTime = 0;\n private isSeeking = false;\n private ignoreUntilTs = 0;\n private popupEl: HTMLElement | null = null;\n\n constructor(\n private readonly ctx: MarkersPlayerContext,\n options: MarkersOptions\n ) {\n this.triggerOnSeek = options.triggerOnSeek === true;\n this.seekJumpThresholdSec = options.seekJumpThresholdSec ?? 1;\n this.seekIgnoreWindowMs = options.seekIgnoreWindowMs ?? 250;\n this.popupGlobal = { ...POPUP_DEFAULTS, ...options.popup };\n this.pingGlobal = { ...PING_DEFAULTS, ...options.ping };\n\n this.markers = (options.items || [])\n .map((m, idx) => this.normalize(m, idx))\n .filter((m) => Number.isFinite(m.time) && m.time >= 0)\n .sort((a, b) => a.time - b.time);\n\n ctx.videoEl.addEventListener('loadedmetadata', this.onLoadedMetadata);\n ctx.videoEl.addEventListener('timeupdate', this.onTimeUpdate);\n ctx.videoEl.addEventListener('seeking', this.onSeeking);\n ctx.videoEl.addEventListener('seeked', this.onSeeked);\n\n if (ctx.videoEl.readyState >= 1) this.onLoadedMetadata();\n }\n\n /** Popup lazy oluşturulup yeniden kullanılıyor (`ensurePopup`) — zaten açıksa close butonunun statik etiketini tazeler. */\n refreshLabels(): void {\n const closeBtn = this.popupEl?.querySelector('button') as HTMLButtonElement | null;\n if (closeBtn) {\n closeBtn.setAttribute('aria-label', this.ctx.i18n.close);\n }\n }\n\n destroy(): void {\n this.ctx.videoEl.removeEventListener('loadedmetadata', this.onLoadedMetadata);\n this.ctx.videoEl.removeEventListener('timeupdate', this.onTimeUpdate);\n this.ctx.videoEl.removeEventListener('seeking', this.onSeeking);\n this.ctx.videoEl.removeEventListener('seeked', this.onSeeked);\n this.markers.forEach((m) => m.el?.remove());\n this.popupEl?.remove();\n this.popupEl = null;\n this.hitSet.clear();\n this.lastHitAt.clear();\n }\n\n private normalize(m: MarkerItem, idx: number): NormalizedMarker {\n return {\n idx,\n time: Number(m.time),\n color: m.color,\n label: m.label ?? '',\n pauseOnHit: m.pauseOnHit ?? true,\n once: m.once ?? true,\n tolerance: m.tolerance ?? 0.25,\n cooldownMs: m.cooldownMs ?? 600,\n action: m.action,\n popup: m.popup ?? null,\n pingUrl: m.pingUrl ?? '',\n };\n }\n\n private readonly onLoadedMetadata = (): void => {\n const duration = this.ctx.videoEl.duration;\n if (!Number.isFinite(duration) || duration <= 0) return;\n\n this.markers.forEach((m) => {\n if (m.el) return;\n const el = this.ctx.addSeekBarMarker(m.time / duration);\n if (m.color) el.style.backgroundColor = m.color;\n if (m.label) el.title = m.label;\n m.el = el;\n });\n\n this.lastTime = this.ctx.videoEl.currentTime || 0;\n };\n\n private readonly onSeeking = (): void => {\n this.isSeeking = true;\n this.ignoreUntilTs = Date.now() + this.seekIgnoreWindowMs;\n this.lastTime = this.ctx.videoEl.currentTime || 0;\n };\n\n private readonly onSeeked = (): void => {\n this.lastTime = this.ctx.videoEl.currentTime || 0;\n this.isSeeking = false;\n this.ignoreUntilTs = Date.now() + this.seekIgnoreWindowMs;\n };\n\n private readonly onTimeUpdate = (): void => {\n const now = Date.now();\n if (now < this.ignoreUntilTs) return;\n if (this.isSeeking) return;\n\n const t = this.ctx.videoEl.currentTime;\n if (!Number.isFinite(t)) return;\n\n const jumped = Math.abs(t - this.lastTime) >= this.seekJumpThresholdSec;\n if (jumped && !this.triggerOnSeek) {\n this.lastTime = t;\n return;\n }\n\n for (const m of this.markers) {\n const key = `${m.time}-${m.idx}`;\n if (m.once && this.hitSet.has(key)) continue;\n if (!m.once) {\n const last = this.lastHitAt.get(key) || 0;\n if (now - last < m.cooldownMs) continue;\n }\n\n const crossed = this.lastTime < m.time && t >= m.time - m.tolerance;\n if (!crossed) continue;\n\n if (m.once) this.hitSet.add(key);\n else this.lastHitAt.set(key, now);\n\n if (m.pauseOnHit) this.ctx.videoEl.pause();\n\n this.firePing(m);\n this.fireAction(m);\n\n const popupCfg = m.popup ? { ...this.popupGlobal, ...m.popup } : this.popupGlobal;\n if (popupCfg.enabled) {\n this.ctx.videoEl.pause();\n this.showPopup(popupCfg);\n }\n break;\n }\n\n this.lastTime = t;\n };\n\n private resolveUrlTemplate(url: string, m: NormalizedMarker): string {\n if (!url) return '';\n return url.replaceAll('{time}', encodeURIComponent(String(m.time))).replaceAll('{label}', encodeURIComponent(m.label));\n }\n\n private firePing(m: NormalizedMarker): void {\n const baseUrl = m.pingUrl || this.pingGlobal.url;\n const url = this.resolveUrlTemplate(baseUrl, m);\n if (!this.pingGlobal.enabled || !url) return;\n\n try {\n if (this.pingGlobal.method === 'POST') {\n fetch(url, {\n method: 'POST',\n keepalive: true,\n headers: this.pingGlobal.includeMarker ? { 'Content-Type': 'application/json' } : undefined,\n body: this.pingGlobal.includeMarker ? JSON.stringify({ time: m.time, label: m.label, ts: Date.now() }) : undefined,\n }).catch(() => {});\n } else {\n fetch(url, { method: 'GET', keepalive: true }).catch(() => {});\n }\n } catch {\n /* no-op */\n }\n }\n\n private fireAction(m: NormalizedMarker): void {\n const a = m.action;\n if (!a) return;\n\n if (a.type === 'log') {\n console.log('[HopePlayer markers]', a.name || 'marker_hit', { time: m.time, label: m.label }, a.payload);\n return;\n }\n\n if (a.type === 'datalayer') {\n try {\n const w = window as unknown as { dataLayer?: unknown[] };\n w.dataLayer = w.dataLayer || [];\n w.dataLayer.push({\n event: 'HopePlayerVideoEvents',\n trigger: a.name || 'marker_hit',\n marker: { time: m.time, label: m.label, color: m.color },\n payload: a.payload ?? {},\n ts: Date.now(),\n });\n } catch {\n /* no-op */\n }\n return;\n }\n\n if (a.type === 'custom') {\n const fn = a.name ? (window as unknown as Record<string, unknown>)[a.name] : null;\n if (typeof fn === 'function') {\n try {\n (fn as (ctx: unknown) => void)({ marker: m, payload: a.payload });\n } catch (err) {\n console.warn('[HopePlayer markers] custom action fonksiyonu hata verdi:', err);\n }\n } else {\n console.warn('[HopePlayer markers] custom action fonksiyonu bulunamadı: window.' + a.name);\n }\n }\n }\n\n private ensurePopup(): HTMLElement {\n if (this.popupEl) return this.popupEl;\n\n const overlay = document.createElement('div');\n overlay.setAttribute('part', 'marker-popup');\n overlay.className = 'hp:hidden hp:absolute hp:inset-0 hp:z-30 hp:items-center hp:justify-center hp:bg-black/70';\n\n const panel = document.createElement('div');\n panel.className = 'hp:relative hp:max-w-[85%] hp:bg-surface-elev hp:text-on-surface hp:rounded-lg hp:p-4 hp:text-center hp:shadow-xl';\n panel.setAttribute('role', 'dialog');\n panel.setAttribute('aria-modal', 'true');\n\n const closeBtn = document.createElement('button');\n closeBtn.type = 'button';\n closeBtn.setAttribute('aria-label', this.ctx.i18n.close);\n closeBtn.className = 'hp:absolute hp:top-1 hp:right-1 hp:w-6 hp:h-6 hp:flex hp:items-center hp:justify-center hp:bg-transparent hp:border-0 hp:cursor-pointer hp:text-on-surface';\n closeBtn.appendChild(createIcon('close', 'hp:text-sm'));\n\n const mediaWrap = document.createElement('div');\n mediaWrap.className = 'hp:hidden hp:mb-2';\n const img = document.createElement('img');\n img.className = 'hp:max-w-full hp:rounded';\n mediaWrap.appendChild(img);\n\n const textEl = document.createElement('div');\n textEl.className = 'hp:text-sm hp:mb-2';\n\n const linkEl = document.createElement('a');\n linkEl.target = '_blank';\n linkEl.rel = 'noopener noreferrer';\n linkEl.className = 'hp:hidden hp:text-accent hp:underline hp:text-sm hp:block hp:mb-2';\n\n const continueBtn = document.createElement('button');\n continueBtn.type = 'button';\n continueBtn.className = 'hp:hidden hp:px-4 hp:py-1.5 hp:rounded hp:bg-accent hp:text-on-accent hp:border-0 hp:cursor-pointer hp:text-sm';\n\n panel.append(closeBtn, mediaWrap, textEl, linkEl, continueBtn);\n overlay.appendChild(panel);\n this.ctx.overlayContainerEl.appendChild(overlay);\n this.popupEl = overlay;\n return overlay;\n }\n\n private hidePopup(): void {\n this.popupEl?.classList.add('hp:hidden');\n this.popupEl?.classList.remove('hp:flex');\n }\n\n private safePlay(): void {\n void this.ctx.videoEl.play().catch(() => {});\n }\n\n private showPopup(cfg: Required<MarkerPopupOptions>): void {\n const el = this.ensurePopup();\n const textEl = el.querySelector('div.hp\\\\:text-sm.hp\\\\:mb-2:not(.hp\\\\:hidden)') as HTMLElement | null;\n const mediaWrap = el.querySelector('div.hp\\\\:mb-2') as HTMLElement | null;\n const img = el.querySelector('img') as HTMLImageElement | null;\n const linkEl = el.querySelector('a') as HTMLAnchorElement | null;\n const continueBtn = el.querySelectorAll('button')[1] as HTMLButtonElement | null;\n const closeBtn = el.querySelector('button') as HTMLButtonElement | null;\n\n if (closeBtn) closeBtn.style.display = cfg.showClose === false ? 'none' : '';\n if (textEl) textEl.textContent = cfg.text || '';\n\n const isRich = cfg.mode === 'rich';\n if (mediaWrap && img) {\n if (isRich && cfg.imageUrl) {\n mediaWrap.classList.remove('hp:hidden');\n img.src = cfg.imageUrl;\n img.alt = cfg.imageAlt || '';\n } else {\n mediaWrap.classList.add('hp:hidden');\n img.removeAttribute('src');\n }\n }\n\n if (linkEl) {\n if (isRich && cfg.linkUrl) {\n linkEl.classList.remove('hp:hidden');\n linkEl.href = cfg.linkUrl;\n linkEl.textContent = cfg.linkText || this.ctx.i18n.markerLearnMore;\n } else {\n linkEl.classList.add('hp:hidden');\n linkEl.removeAttribute('href');\n }\n }\n\n if (continueBtn) {\n if (cfg.showContinue) {\n continueBtn.classList.remove('hp:hidden');\n continueBtn.textContent = cfg.continueText || this.ctx.i18n.markerContinue;\n } else {\n continueBtn.classList.add('hp:hidden');\n }\n }\n\n const newClose = closeBtn?.cloneNode(true) as HTMLButtonElement | undefined;\n if (closeBtn && newClose) closeBtn.replaceWith(newClose);\n const newCont = continueBtn?.cloneNode(true) as HTMLButtonElement | undefined;\n if (continueBtn && newCont) continueBtn.replaceWith(newCont);\n\n newClose?.addEventListener('click', () => {\n this.hidePopup();\n if (cfg.autoplayOnClose) this.safePlay();\n });\n newCont?.addEventListener('click', () => {\n this.hidePopup();\n if (cfg.autoplayOnContinue) this.safePlay();\n });\n\n el.classList.remove('hp:hidden');\n el.classList.add('hp:flex');\n }\n}\n","import { MarkProgress, type MarkersPlayerContext } from './MarkProgress';\nimport type { MarkersOptions } from '../../types';\n\nexport function installMarkers(ctx: MarkersPlayerContext, options: MarkersOptions): MarkProgress {\n return new MarkProgress(ctx, options);\n}\n\nexport { MarkProgress };\nexport type { MarkersPlayerContext };\n"],"names":["POPUP_DEFAULTS","PING_DEFAULTS","MarkProgress","ctx","options","__publicField","duration","m","el","now","key","last","popupCfg","idx","a","b","closeBtn","_a","url","baseUrl","w","fn","err","overlay","panel","createIcon","mediaWrap","img","textEl","linkEl","continueBtn","_b","cfg","isRich","newClose","newCont","installMarkers"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  var u = Object.defineProperty;
2
2
  var c = (o, e, t) => e in o ? u(o, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : o[e] = t;
3
3
  var s = (o, e, t) => c(o, typeof e != "symbol" ? e + "" : e, t);
4
- import { l as m } from "./loadGpt-CmiAy366.js";
4
+ import { l as m } from "./gpt-CGXHTG_H.js";
5
5
  const v = [
6
6
  [300, 250],
7
7
  [336, 280],
@@ -128,4 +128,4 @@ export {
128
128
  g as PauseAd,
129
129
  T as installPauseAd
130
130
  };
131
- //# sourceMappingURL=index-CDPrkLq0.js.map
131
+ //# sourceMappingURL=pauseAd-BQQe21X4.js.map