@hopeplayer/core 1.0.16 → 1.0.18

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 (135) hide show
  1. package/README.md +24 -14
  2. package/dist/HopePlayerElement.d.ts +3 -0
  3. package/dist/HopePlayerElement.d.ts.map +1 -1
  4. package/dist/chunks/{index-CWLyz1fp.js → adTriggers-DXmtF4t2.js} +113 -118
  5. package/dist/chunks/adTriggers-DXmtF4t2.js.map +1 -0
  6. package/dist/chunks/{index-DITXYcHx.js → ads-MCG5a6eK.js} +130 -125
  7. package/dist/chunks/ads-MCG5a6eK.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-bMrkGGuD.js} +70 -66
  13. package/dist/chunks/cast-bMrkGGuD.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-BhMJLPqj.js} +2 -2
  35. package/dist/chunks/markers-BhMJLPqj.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-DW5iWvPs.js} +939 -880
  39. package/dist/chunks/player-DW5iWvPs.js.map +1 -0
  40. package/dist/chunks/{index-D3Z7ZDLJ.js → playlist-DYGbJ5wz.js} +24 -24
  41. package/dist/chunks/playlist-DYGbJ5wz.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-DXwD3oSA.js} +29 -30
  45. package/dist/chunks/qrResume-DXwD3oSA.js.map +1 -0
  46. package/dist/chunks/redirectScreen-CSjrS8Kg.js +208 -0
  47. package/dist/chunks/redirectScreen-CSjrS8Kg.js.map +1 -0
  48. package/dist/chunks/{index-BbRYOSvk.js → rewardedUnlock-DZ_qPcDG.js} +22 -19
  49. package/dist/chunks/rewardedUnlock-DZ_qPcDG.js.map +1 -0
  50. package/dist/chunks/seekWhenReady-Clzne3-S.js +32 -0
  51. package/dist/chunks/seekWhenReady-Clzne3-S.js.map +1 -0
  52. package/dist/chunks/{index-CBX7bn-G.js → segments-LsZPlbYi.js} +2 -2
  53. package/dist/chunks/segments-LsZPlbYi.js.map +1 -0
  54. package/dist/chunks/{index-Ch3ep-eJ.js → sponsorship-BT21uwN5.js} +36 -41
  55. package/dist/chunks/sponsorship-BT21uwN5.js.map +1 -0
  56. package/dist/chunks/{index-BXSND_xN.js → spriteThumbnails-BQkEBRu-.js} +2 -2
  57. package/dist/chunks/spriteThumbnails-BQkEBRu-.js.map +1 -0
  58. package/dist/chunks/{index-DGtpFgHV.js → statsPanel-DSClIwA3.js} +1 -1
  59. package/dist/chunks/statsPanel-DSClIwA3.js.map +1 -0
  60. package/dist/chunks/{index-CDDke5rz.js → sticky-D_eLCNFk.js} +1 -1
  61. package/dist/chunks/sticky-D_eLCNFk.js.map +1 -0
  62. package/dist/chunks/{index-C3BQGcT3.js → story-H6f7gSoX.js} +27 -15
  63. package/dist/chunks/story-H6f7gSoX.js.map +1 -0
  64. package/dist/chunks/{index-C5oGMHF_.js → tapGestures-DrC42DiI.js} +1 -1
  65. package/dist/chunks/tapGestures-DrC42DiI.js.map +1 -0
  66. package/dist/chunks/trackingPixel-D2wxdCEz.js +20 -0
  67. package/dist/chunks/trackingPixel-D2wxdCEz.js.map +1 -0
  68. package/dist/controls/SeekBar.d.ts.map +1 -1
  69. package/dist/hls/SourceManager.d.ts.map +1 -1
  70. package/dist/hope-player.js +1 -1
  71. package/dist/i18n/locales/en.d.ts.map +1 -1
  72. package/dist/i18n/locales/tr.d.ts.map +1 -1
  73. package/dist/i18n/types.d.ts +3 -0
  74. package/dist/i18n/types.d.ts.map +1 -1
  75. package/dist/index.d.ts +1 -1
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/keyboard/KeyboardController.d.ts.map +1 -1
  78. package/dist/plugins/ad-triggers/AdTriggers.d.ts.map +1 -1
  79. package/dist/plugins/ads/AdsController.d.ts.map +1 -1
  80. package/dist/plugins/ads/generateVastUrl.d.ts +10 -0
  81. package/dist/plugins/ads/generateVastUrl.d.ts.map +1 -1
  82. package/dist/plugins/cast/CastController.d.ts.map +1 -1
  83. package/dist/plugins/playlist/PlaylistRunner.d.ts.map +1 -1
  84. package/dist/plugins/qr-resume/QrResume.d.ts.map +1 -1
  85. package/dist/plugins/redirect-screen/RedirectScreen.d.ts +26 -3
  86. package/dist/plugins/redirect-screen/RedirectScreen.d.ts.map +1 -1
  87. package/dist/plugins/rewarded/RewardedUnlock.d.ts +0 -5
  88. package/dist/plugins/rewarded/RewardedUnlock.d.ts.map +1 -1
  89. package/dist/plugins/shared/seekWhenReady.d.ts +22 -0
  90. package/dist/plugins/shared/seekWhenReady.d.ts.map +1 -0
  91. package/dist/plugins/shared/trackingPixel.d.ts +8 -0
  92. package/dist/plugins/shared/trackingPixel.d.ts.map +1 -0
  93. package/dist/plugins/sponsorship/SponsorshipLayer.d.ts.map +1 -1
  94. package/dist/plugins/story/HopeStory.d.ts +2 -0
  95. package/dist/plugins/story/HopeStory.d.ts.map +1 -1
  96. package/dist/screens/ErrorScreen.d.ts +7 -0
  97. package/dist/screens/ErrorScreen.d.ts.map +1 -1
  98. package/dist/types/index.d.ts +49 -1
  99. package/dist/types/index.d.ts.map +1 -1
  100. package/dist/utils/media-error.d.ts +10 -0
  101. package/dist/utils/media-error.d.ts.map +1 -0
  102. package/dist/utils/seek-by.d.ts +8 -0
  103. package/dist/utils/seek-by.d.ts.map +1 -1
  104. package/package.json +4 -1
  105. package/dist/chunks/ScratchSound-0XKHUcJK.js.map +0 -1
  106. package/dist/chunks/VideoPrebid-CpckFzSq.js.map +0 -1
  107. package/dist/chunks/index-3QALpwsf.js.map +0 -1
  108. package/dist/chunks/index-7IBf8Y-R.js.map +0 -1
  109. package/dist/chunks/index-BBmuCtKu.js.map +0 -1
  110. package/dist/chunks/index-BXSND_xN.js.map +0 -1
  111. package/dist/chunks/index-BbRYOSvk.js.map +0 -1
  112. package/dist/chunks/index-BeJNpAyx.js.map +0 -1
  113. package/dist/chunks/index-C3BQGcT3.js.map +0 -1
  114. package/dist/chunks/index-C5oGMHF_.js.map +0 -1
  115. package/dist/chunks/index-CBX7bn-G.js.map +0 -1
  116. package/dist/chunks/index-CDDke5rz.js.map +0 -1
  117. package/dist/chunks/index-CDPrkLq0.js.map +0 -1
  118. package/dist/chunks/index-CWLyz1fp.js.map +0 -1
  119. package/dist/chunks/index-Ca8hocby.js.map +0 -1
  120. package/dist/chunks/index-Ch3ep-eJ.js.map +0 -1
  121. package/dist/chunks/index-D3Z7ZDLJ.js.map +0 -1
  122. package/dist/chunks/index-D6r-BGAV.js +0 -77
  123. package/dist/chunks/index-D6r-BGAV.js.map +0 -1
  124. package/dist/chunks/index-DCXX1ZJG.js.map +0 -1
  125. package/dist/chunks/index-DEv3YqLg.js.map +0 -1
  126. package/dist/chunks/index-DGtpFgHV.js.map +0 -1
  127. package/dist/chunks/index-DITXYcHx.js.map +0 -1
  128. package/dist/chunks/index-DT8-oMPm.js.map +0 -1
  129. package/dist/chunks/index-DXWK4EFa.js.map +0 -1
  130. package/dist/chunks/index-Miba3PD_.js.map +0 -1
  131. package/dist/chunks/index-Q8FMOHj0.js.map +0 -1
  132. package/dist/chunks/index-e00_M05B.js.map +0 -1
  133. package/dist/chunks/index-f0vSgRIK.js.map +0 -1
  134. package/dist/chunks/index-rENB3n9O.js.map +0 -1
  135. package/dist/chunks/loadGpt-CmiAy366.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"VideoPrebid-CpckFzSq.js","sources":["../../src/plugins/prebid/VideoPrebid.ts"],"sourcesContent":["import type { PrebidBidderConfig, PrebidBreakOptions, PrebidOptions } from '../../types';\n\n/** window.pbjs yüzeyi — Prebid.js sayfaya <script> ile yüklenir, npm bağımlılığı değil. */\ninterface PbjsBid {\n bidder: string;\n cpm?: number;\n vastUrl?: string;\n vastXml?: string;\n videoCacheKey?: string;\n responseTimestamp?: number;\n ttl?: number;\n}\n\ninterface Pbjs {\n que: Array<() => void>;\n requestBids(params: { adUnits: unknown[]; timeout: number; bidsBackHandler: () => void }): void;\n addAdUnits(units: unknown[]): void;\n removeAdUnit(code: string): void;\n setConfig(config: Record<string, unknown>): void;\n getConfig?(key: string): { url?: string } | undefined;\n installedModules?: string[];\n aliasRegistry?: Record<string, string>;\n getHighestCpmBids?(adUnitCode: string): PbjsBid[];\n getBidResponsesForAdUnitCode?(adUnitCode: string): { bids: PbjsBid[] };\n adServers?: {\n gam?: { buildVideoUrl(args: { adUnit: unknown; params: Record<string, string> }): string | null };\n dfp?: { buildVideoUrl(args: { adUnit: unknown; params: Record<string, string> }): string | null };\n };\n __hopeConsentApplied?: boolean;\n}\n\ndeclare global {\n interface Window {\n pbjs?: Pbjs;\n }\n}\n\n/** Prebid.js instream video header bidding (GAM ve direkt-VAST modları). */\nexport class VideoPrebid {\n private readonly timeout: number;\n private readonly adUnitCode: string;\n private readonly sizes: Array<[number, number]>;\n private readonly bidders: PrebidBidderConfig[];\n private readonly gamAdUnit: string | null;\n private readonly gpid: string | null;\n private readonly playbackMethod: number;\n private readonly skip: 0 | 1;\n private readonly skipafter: number;\n private readonly maxduration: number;\n private readonly minduration: number;\n private readonly api: number[];\n private readonly protocols: number[];\n private readonly mimes: string[];\n private readonly applyLossFactor: boolean;\n private readonly lossFactors: Record<string, number>;\n private readonly consentManagement: PrebidOptions['consentManagement'];\n\n private cacheWarned = false;\n private gamWarned = false;\n private cacheKeyWarned = false;\n\n constructor(opts: PrebidBreakOptions & { consentManagement?: PrebidOptions['consentManagement'] } = {}) {\n this.timeout = opts.timeout ?? 1500;\n this.adUnitCode = opts.adUnitCode || 'hope-video-preroll';\n this.sizes = opts.sizes || [[640, 360]];\n this.bidders = opts.bidders || [];\n this.gamAdUnit = opts.gamAdUnit ?? null;\n this.gpid = opts.gpid ?? this.gamAdUnit ?? null;\n this.playbackMethod = opts.playbackMethod ?? 2;\n this.skip = opts.skip ?? 0;\n this.skipafter = opts.skipafter ?? 5;\n this.maxduration = opts.maxduration ?? 30;\n this.minduration = opts.minduration ?? 1;\n this.api = opts.api || [2, 7];\n this.protocols = opts.protocols || [2, 3, 5, 6, 7, 8];\n this.mimes = opts.mimes || (this.api.includes(2)\n ? ['video/mp4', 'video/webm', 'application/javascript']\n : ['video/mp4', 'video/webm']);\n this.applyLossFactor = opts.applyLossFactor ?? false;\n this.lossFactors = opts.lossFactors || {};\n this.consentManagement = opts.consentManagement ?? null;\n }\n\n private applyConsentConfig(): void {\n const pbjs = window.pbjs;\n if (!this.consentManagement || !pbjs || pbjs.__hopeConsentApplied) return;\n try {\n pbjs.setConfig({ consentManagement: this.consentManagement });\n pbjs.__hopeConsentApplied = true;\n } catch (err) {\n console.warn('[VideoPrebid] consentManagement setConfig hatası:', err);\n }\n }\n\n isAvailable(): boolean {\n const pbjs = window.pbjs;\n if (!pbjs || typeof pbjs.requestBids !== 'function') return false;\n\n if (!this.cacheWarned) {\n const cacheUrl = pbjs.getConfig?.('cache')?.url;\n if (!cacheUrl) {\n console.warn(`[VideoPrebid] pbjs.setConfig({cache:{url}}) tanımlı değil. ${this.gamAdUnit ? 'GAM isteğinde hb_uuid boş kalacak, creative reklam döndüremeyecek.' : 'vastUrl boş dönecek, fallback tag kullanılacak.'}`);\n }\n this.cacheWarned = true;\n }\n\n const installed = pbjs.installedModules || [];\n if (!installed.length) return true;\n\n const aliasRegistry = pbjs.aliasRegistry || {};\n return this.bidders.some((b) => {\n if (installed.includes(`${b.bidder}BidAdapter`)) return true;\n const canonical = aliasRegistry[b.bidder];\n return canonical ? installed.includes(`${canonical}BidAdapter`) : false;\n });\n }\n\n runAuction(fallbackVastUrl: string): Promise<string> {\n return new Promise((resolve) => {\n if (!this.isAvailable()) {\n resolve(fallbackVastUrl);\n return;\n }\n const pbjs = window.pbjs!;\n\n const adUnit = this.buildAdUnit();\n const cleanup = () => {\n try {\n pbjs.removeAdUnit(adUnit.code);\n } catch {\n /* no-op */\n }\n };\n\n let settled = false;\n const done = (url: string) => {\n if (settled) return;\n settled = true;\n cleanup();\n resolve(url);\n };\n\n pbjs.que = pbjs.que || [];\n pbjs.que.push(() => {\n this.applyConsentConfig();\n pbjs.removeAdUnit(adUnit.code);\n pbjs.addAdUnits([adUnit]);\n\n // Prebid'in kendi timeoutBuffer default'u 400ms, +300 bidsBackHandler'dan\n // önce ateşleyebiliyordu — +500ms tampon bu yüzden.\n const failsafe = setTimeout(() => done(fallbackVastUrl), this.timeout + 500);\n\n pbjs.requestBids({\n adUnits: [adUnit],\n timeout: this.timeout,\n bidsBackHandler: () => {\n clearTimeout(failsafe);\n done(this.resolveVastUrl(adUnit, fallbackVastUrl));\n },\n });\n });\n });\n }\n\n private buildAdUnit(): { code: string; ortb2Imp: unknown; mediaTypes: unknown; bids: PrebidBidderConfig[] } {\n const bids: PrebidBidderConfig[] = typeof structuredClone === 'function'\n ? structuredClone(this.bidders)\n : (JSON.parse(JSON.stringify(this.bidders)) as PrebidBidderConfig[]);\n\n const stableId = this.gpid || this.adUnitCode;\n\n return {\n code: this.adUnitCode,\n ortb2Imp: {\n ext: {\n gpid: stableId,\n data: { pbadslot: stableId },\n },\n },\n mediaTypes: {\n video: {\n context: 'instream',\n playerSize: this.sizes,\n mimes: this.mimes,\n protocols: this.protocols,\n api: this.api,\n minduration: this.minduration,\n maxduration: this.maxduration,\n startdelay: 0,\n playbackmethod: [this.playbackMethod],\n linearity: 1,\n plcmt: 1,\n placement: 1,\n skip: this.skip,\n ...(this.skip ? { skipafter: this.skipafter } : {}),\n pos: 1,\n },\n },\n bids,\n };\n }\n\n private getGamAdServer(): {\n buildVideoUrl(args: { adUnit: unknown; params: Record<string, string | Record<string, string>> }): string | null;\n } | null {\n const adServers = window.pbjs?.adServers;\n const gam = adServers?.gam || adServers?.dfp;\n return typeof gam?.buildVideoUrl === 'function' ? gam : null;\n }\n\n /** Fallback tag'in cust_params'ını objeye çevirir — buildVideoUrl URL'i sıfırdan kurduğu için ayrıca geçilmeli. */\n private extractCustParams(url: string): Record<string, string> {\n const result: Record<string, string> = {};\n try {\n const raw = new URL(url).searchParams.get('cust_params');\n if (!raw) return result;\n for (const pair of raw.split('&')) {\n const idx = pair.indexOf('=');\n if (idx <= 0) continue;\n const key = pair.slice(0, idx);\n if (key.startsWith('hb_')) continue;\n result[key] = pair.slice(idx + 1);\n }\n } catch (err) {\n console.warn('[VideoPrebid] fallback cust_params okunamadı:', err);\n }\n return result;\n }\n\n private pickWinningBid(adUnitCode: string): PbjsBid | undefined {\n const pbjs = window.pbjs!;\n if (!this.applyLossFactor) {\n return (pbjs.getHighestCpmBids?.(adUnitCode) || [])[0];\n }\n\n const responses = pbjs.getBidResponsesForAdUnitCode?.(adUnitCode)?.bids || [];\n if (!responses.length) return undefined;\n\n const now = Date.now();\n const valid = responses.filter((b) => !b.responseTimestamp || !b.ttl || b.responseTimestamp + b.ttl * 1000 > now);\n if (!valid.length) return undefined;\n\n let best: PbjsBid | undefined;\n let bestWeighted = -Infinity;\n for (const bid of valid) {\n const factor = this.lossFactors[bid.bidder] ?? 1;\n const weighted = (bid.cpm || 0) * factor;\n if (weighted > bestWeighted) {\n bestWeighted = weighted;\n best = bid;\n }\n }\n return best;\n }\n\n private resolveVastUrl(adUnit: { code: string }, fallback: string): string {\n const gam = this.gamAdUnit ? this.getGamAdServer() : null;\n\n if (this.gamAdUnit && !gam && !this.gamWarned) {\n console.warn('[VideoPrebid] pbjs.adServers.gam.buildVideoUrl bulunamadı — Prebid build\\'inde \"Google Ad Manager Video\" (dfpAdServerVideo) modülü yok. GAM atlanıyor, kazanan bid\\'in vastUrl\\'i kullanılacak.');\n this.gamWarned = true;\n }\n\n const winner = this.pickWinningBid(adUnit.code);\n\n if (gam && !winner) {\n console.warn(`[VideoPrebid] Auction'dan kazanan bid çıkmadı — GAM isteği hb_pb/hb_bidder olmadan gidiyor, cust_params'ta hb_uuid=undefined görünecek. pbjs.getBidResponsesForAdUnitCode('${adUnit.code}') ve pbjs.getEvents() ile no-bid/timeout sebebine bakın.`);\n }\n\n if (gam && winner && !winner.videoCacheKey && !this.cacheKeyWarned) {\n console.warn(`[VideoPrebid] Kazanan bid'de videoCacheKey yok — GAM isteğine hb_uuid=undefined gidecek. VAST cache'e yazılmamış: pbjs.setConfig({cache:{url}}) auction'dan önce çalışıyor mu ve cache POST'u başarılı mı kontrol edin. (bidder: ${winner.bidder})`);\n this.cacheKeyWarned = true;\n }\n\n if (gam) {\n try {\n const url = gam.buildVideoUrl({\n adUnit,\n params: {\n iu: this.gamAdUnit!,\n output: 'vast',\n description_url: window.location.href,\n url: window.location.href,\n cust_params: this.extractCustParams(fallback),\n },\n });\n if (url) return url;\n } catch (err) {\n console.warn('[VideoPrebid] buildVideoUrl failed:', err);\n }\n }\n\n if (winner) {\n if (winner.vastUrl) return winner.vastUrl;\n if (winner.vastXml) {\n console.warn('[VideoPrebid] Kazanan bid vastXml içeriyor ancak Prebid cache yapılandırılmamış. pbjs.setConfig({cache:{url}}) ekleyin. Fallback\\'e düşülüyor.');\n }\n }\n\n return fallback;\n }\n}\n\nexport default VideoPrebid;\n"],"names":["VideoPrebid","opts","__publicField","pbjs","err","_a","_b","installed","aliasRegistry","b","canonical","fallbackVastUrl","resolve","adUnit","cleanup","settled","done","url","failsafe","bids","stableId","adServers","gam","result","raw","pair","idx","key","adUnitCode","_c","responses","now","valid","best","bestWeighted","bid","factor","weighted","fallback","winner"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-3QALpwsf.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;"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-7IBf8Y-R.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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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-BBmuCtKu.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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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-BXSND_xN.js","sources":["../../src/plugins/sprite-thumbnails/SpriteThumbnails.ts","../../src/plugins/sprite-thumbnails/index.ts"],"sourcesContent":["import type { SpriteThumbnailsOptions } from '../../types';\nimport { formatTime } from '../../utils/format-time';\n\nexport interface SpriteThumbnailsPlayerContext {\n videoEl: HTMLVideoElement;\n /** Önizlemenin bağlandığı seek bar — zaman eşlemesi (chapter boşlukları dahil) onun `ratioAtClientX`'inden. */\n seekBar: {\n readonly el: HTMLElement;\n ratioAtClientX(clientX: number): number;\n suppressHoverTime(key: string, suppressed: boolean): void;\n };\n /** Responsive ölçekleme için referans genişlik — genelde player/video alanının genişliği. */\n playerWidth(): number;\n}\n\n/** Bir önizleme karesi: hangi görselin hangi dikdörtgeni. */\ninterface Frame {\n url: string;\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\ninterface Sheet {\n img: HTMLImageElement;\n ready: boolean;\n failed: boolean;\n promise: Promise<void>;\n}\n\nexport interface VttCue {\n start: number;\n end: number;\n url: string;\n /** `#xywh` yoksa null → görselin tamamı. */\n rect: { x: number; y: number; w: number; h: number } | null;\n}\n\n/** Aynı anda bellekte (decode edilmiş) tutulan en fazla sheet — uzun videolarda bellek sınırsız büyümesin. */\nconst MAX_CACHED_SHEETS = 8;\n/** Sheet numarası şablonu: `%d` ya da sıfır dolgulu `%03d`. */\nconst SHEET_TEMPLATE = /%(0(\\d+))?d/;\n\n/**\n * Seek bar hover önizlemesi. Kaynak: tek görsel, çok parçalı (%d / %03d şablonu ya da sheets) veya WebVTT (#xywh).\n * sheetDuration verilmezse ilk sheet'in ızgarasından hesaplanır. Kurulumda hiçbir şey indirilmez; yalnızca imlecin\n * altındaki sheet + komşuları yüklenir, decode bitmeden gösterilmez, LRU cache.\n */\nexport class SpriteThumbnails {\n private readonly tooltip: HTMLElement;\n private readonly imageEl: HTMLElement;\n private readonly timeEl: HTMLElement;\n private readonly sheets = new Map<string, Sheet>();\n private vttCues: VttCue[] | null = null;\n private vttLoading: Promise<void> | null = null;\n /** Çok parçalı modda otomatik hesaplanan sheet süresi (ilk sheet yüklenince). */\n private derivedSheetDuration: number | null = null;\n private warmed = false;\n private hovering = false;\n private lastClientX = 0;\n private rafId: number | null = null;\n private destroyed = false;\n\n constructor(\n private readonly ctx: SpriteThumbnailsPlayerContext,\n private readonly options: SpriteThumbnailsOptions\n ) {\n this.tooltip = document.createElement('div');\n this.tooltip.setAttribute('part', 'sprite-tooltip');\n this.tooltip.className = 'hp-sprite-tooltip';\n this.imageEl = document.createElement('div');\n this.imageEl.className = 'hp-sprite-image';\n this.timeEl = document.createElement('div');\n this.timeEl.className = 'hp-sprite-time';\n this.tooltip.append(this.imageEl, this.timeEl);\n ctx.seekBar.el.appendChild(this.tooltip);\n // Önizlemenin altında zaman zaten yazıyor — varsayılan hover zamanı ikinci kez göstermesin.\n ctx.seekBar.suppressHoverTime('sprite', true);\n\n ctx.seekBar.el.addEventListener('pointerenter', this.onPointerEnter);\n ctx.seekBar.el.addEventListener('pointermove', this.onPointerMove);\n ctx.seekBar.el.addEventListener('pointerleave', this.onPointerLeave);\n ctx.videoEl.addEventListener('play', this.warm);\n }\n\n destroy(): void {\n this.destroyed = true;\n if (this.rafId !== null) cancelAnimationFrame(this.rafId);\n this.ctx.seekBar.el.removeEventListener('pointerenter', this.onPointerEnter);\n this.ctx.seekBar.el.removeEventListener('pointermove', this.onPointerMove);\n this.ctx.seekBar.el.removeEventListener('pointerleave', this.onPointerLeave);\n this.ctx.videoEl.removeEventListener('play', this.warm);\n this.tooltip.remove();\n this.ctx.seekBar.suppressHoverTime('sprite', false);\n for (const sheet of this.sheets.values()) sheet.img.src = '';\n this.sheets.clear();\n }\n\n // ── olaylar ──\n\n private readonly onPointerEnter = (e: PointerEvent): void => {\n this.hovering = true;\n this.lastClientX = e.clientX;\n this.warm();\n this.scheduleRender();\n };\n\n private readonly onPointerMove = (e: PointerEvent): void => {\n this.hovering = true;\n this.lastClientX = e.clientX;\n this.scheduleRender();\n };\n\n private readonly onPointerLeave = (): void => {\n this.hovering = false;\n this.tooltip.removeAttribute('data-visible');\n };\n\n /** İlk ihtiyaç anında (hover / oynatma) kaynağı hazırla — kurulumda hiçbir şey indirilmiyor. */\n private readonly warm = (): void => {\n if (this.warmed || this.destroyed) return;\n this.warmed = true;\n if (this.options.vtt) {\n void this.loadVtt();\n return;\n }\n const duration = this.ctx.videoEl.duration;\n const t = Number.isFinite(duration) ? this.ctx.videoEl.currentTime : 0;\n // Şablonlu/çok parçalı modda sheet süresi henüz bilinmiyorsa ilk sheet'ten öğrenilecek.\n void this.ensureSheet(this.sheetUrl(this.isMultiSheet() && this.sheetDuration() === null ? 0 : this.sheetIndexAt(t)));\n };\n\n private scheduleRender(): void {\n if (this.rafId !== null) return;\n this.rafId = requestAnimationFrame(() => {\n this.rafId = null;\n this.render();\n });\n }\n\n // ── çizim ──\n\n private render(): void {\n if (!this.hovering || this.destroyed) return;\n const duration = this.ctx.videoEl.duration;\n if (!Number.isFinite(duration) || duration <= 0) return;\n\n const seconds = this.ctx.seekBar.ratioAtClientX(this.lastClientX) * duration;\n this.timeEl.textContent = formatTime(seconds);\n\n const frame = this.isNetworkEligible() ? this.frameAt(seconds, duration) : null;\n const scale = this.scale();\n if (frame) {\n const sheet = this.sheets.get(frame.url)!;\n const { naturalWidth, naturalHeight } = sheet.img;\n this.imageEl.style.display = '';\n this.imageEl.style.width = `${frame.w * scale}px`;\n this.imageEl.style.height = `${frame.h * scale}px`;\n this.imageEl.style.backgroundImage = `url(\"${frame.url}\")`;\n this.imageEl.style.backgroundSize = `${naturalWidth * scale}px ${naturalHeight * scale}px`;\n this.imageEl.style.backgroundPosition = `${-frame.x * scale}px ${-frame.y * scale}px`;\n } else if (!this.imageEl.style.backgroundImage) {\n // Henüz hiçbir kare yüklenmedi — yalnızca zaman (yükleme bitince yeniden çizilir).\n this.imageEl.style.display = 'none';\n }\n\n // Kenarlarda taşmasın: imleci ortala ama seek bar sınırlarında kal.\n this.tooltip.setAttribute('data-visible', '');\n const barRect = this.ctx.seekBar.el.getBoundingClientRect();\n const tipWidth = this.tooltip.offsetWidth;\n const x = Math.min(Math.max(this.lastClientX - barRect.left - tipWidth / 2, 0), Math.max(barRect.width - tipWidth, 0));\n this.tooltip.style.transform = `translateX(${x}px)`;\n }\n\n private scale(): number {\n const responsive = this.options.responsive;\n const playerWidth = this.ctx.playerWidth();\n return responsive && playerWidth && playerWidth < responsive ? playerWidth / responsive : 1;\n }\n\n private isNetworkEligible(): boolean {\n const nav = navigator as Navigator & { connection?: { downlink?: number } };\n const downlink = nav.connection?.downlink;\n const anyReady = Array.from(this.sheets.values()).some((s) => s.ready);\n return downlink === undefined || downlink >= (this.options.downlink ?? 2) || anyReady;\n }\n\n // ── kare çözümleme ──\n\n /** Saniyedeki kareyi döner; gereken sheet hazır değilse yüklemeyi başlatıp null döner (yüklenince render tekrar çağrılır). */\n private frameAt(seconds: number, duration: number): Frame | null {\n return this.options.vtt ? this.vttFrameAt(seconds) : this.gridFrameAt(seconds, duration);\n }\n\n private isMultiSheet(): boolean {\n return !!this.options.sheets?.length || SHEET_TEMPLATE.test(this.options.url ?? '');\n }\n\n /** Tek sheet → Infinity (tüm video); çok parçalı → verilen ya da ilk sheet'ten hesaplanan süre; henüz bilinmiyorsa null. */\n private sheetDuration(): number | null {\n if (!this.isMultiSheet()) return Infinity;\n return this.options.sheetDuration ?? this.derivedSheetDuration;\n }\n\n private sheetIndexAt(seconds: number): number {\n const d = this.sheetDuration();\n if (d === null || d === Infinity) return 0;\n // floor (ceil DEĞİL): tam sınırda (ör. 60. sn) bir SONRAKİ sheet'in ilk karesi.\n let index = Math.floor(Math.max(0, seconds) / d);\n if (this.options.sheets?.length) index = Math.min(index, this.options.sheets.length - 1);\n return index;\n }\n\n /** 0 tabanlı sheet index'inden URL. */\n private sheetUrl(index: number): string {\n if (this.options.sheets?.length) return this.options.sheets[Math.min(index, this.options.sheets.length - 1)]!;\n const url = this.options.url ?? '';\n const number = index + (this.options.firstSheetIndex ?? 1);\n return url.replace(SHEET_TEMPLATE, (_m, _p, width?: string) => String(number).padStart(width ? Number(width) : 0, '0'));\n }\n\n private gridFrameAt(seconds: number, duration: number): Frame | null {\n const { width, height } = this.options;\n if (!width || !height) return null;\n const interval = this.options.interval || 1;\n\n const sheetDuration = this.sheetDuration();\n if (sheetDuration === null) {\n // Çok parçalı ama süre bilinmiyor — ilk sheet yüklenince hesaplanacak.\n void this.ensureSheet(this.sheetUrl(0));\n return null;\n }\n\n const lastIndex = sheetDuration === Infinity ? 0 : this.sheetIndexAt(Math.max(0, duration - 0.001));\n const index = Math.min(this.sheetIndexAt(seconds), lastIndex);\n const url = this.sheetUrl(index);\n this.preloadAround(index, lastIndex);\n\n const sheet = this.sheets.get(url);\n if (!sheet?.ready) {\n void this.ensureSheet(url);\n return null;\n }\n this.touch(url);\n\n // Her sheet'in KENDİ boyutu (son sheet daha kısa olabilir).\n const columns = Math.max(1, Math.floor(sheet.img.naturalWidth / width));\n const rows = Math.max(1, Math.floor(sheet.img.naturalHeight / height));\n const local = sheetDuration === Infinity ? seconds : seconds - index * sheetDuration;\n const frameIndex = Math.min(Math.max(0, Math.floor(local / interval)), columns * rows - 1);\n return { url, x: (frameIndex % columns) * width, y: Math.floor(frameIndex / columns) * height, w: width, h: height };\n }\n\n private preloadAround(index: number, lastIndex: number): void {\n const n = this.options.preloadSheets ?? 1;\n for (let d = 1; d <= n; d++) {\n if (index + d <= lastIndex) void this.ensureSheet(this.sheetUrl(index + d));\n if (index - d >= 0) void this.ensureSheet(this.sheetUrl(index - d));\n }\n }\n\n private vttFrameAt(seconds: number): Frame | null {\n if (!this.vttCues) {\n void this.loadVtt();\n return null;\n }\n const cues = this.vttCues;\n if (!cues.length) return null;\n // İkili arama — saatlerce süren videolarda binlerce cue olabilir.\n let lo = 0;\n let hi = cues.length - 1;\n while (lo < hi) {\n const mid = (lo + hi + 1) >> 1;\n if (cues[mid]!.start <= seconds) lo = mid;\n else hi = mid - 1;\n }\n const cue = cues[lo]!;\n const neighbours = [cues[lo + 1], cues[lo - 1]].filter((c): c is VttCue => !!c && c.url !== cue.url);\n neighbours.forEach((c) => void this.ensureSheet(c.url));\n\n const sheet = this.sheets.get(cue.url);\n if (!sheet?.ready) {\n void this.ensureSheet(cue.url);\n return null;\n }\n this.touch(cue.url);\n const rect = cue.rect ?? { x: 0, y: 0, w: sheet.img.naturalWidth, h: sheet.img.naturalHeight };\n return { url: cue.url, ...rect };\n }\n\n // ── yükleme / cache ──\n\n private ensureSheet(url: string): Promise<void> {\n if (!url) return Promise.resolve();\n const existing = this.sheets.get(url);\n if (existing) return existing.promise;\n\n const img = new Image();\n img.decoding = 'async';\n const sheet: Sheet = { img, ready: false, failed: false, promise: Promise.resolve() };\n sheet.promise = new Promise<void>((resolve) => {\n img.onload = () => {\n // decode() bitmeden gösterme — yeni sheet'e geçerken boş/yanlış kare titremesi olmasın.\n const done = () => {\n if (this.destroyed) return resolve();\n sheet.ready = true;\n this.learnSheetDuration(img);\n if (this.hovering) this.scheduleRender();\n resolve();\n };\n img.decode ? img.decode().then(done, done) : done();\n };\n img.onerror = () => {\n sheet.failed = true;\n resolve();\n };\n });\n img.src = url;\n this.sheets.set(url, sheet);\n this.evict();\n return sheet.promise;\n }\n\n /** Çok parçalı modda `sheetDuration` verilmediyse ilk yüklenen sheet'in ızgara kapasitesinden hesapla. */\n private learnSheetDuration(img: HTMLImageElement): void {\n if (this.derivedSheetDuration !== null || this.options.vtt || !this.isMultiSheet() || this.options.sheetDuration) return;\n const { width, height } = this.options;\n if (!width || !height) return;\n const capacity = Math.max(1, Math.floor(img.naturalWidth / width)) * Math.max(1, Math.floor(img.naturalHeight / height));\n this.derivedSheetDuration = capacity * (this.options.interval || 1);\n }\n\n /** LRU: kullanılan sheet'i sona taşı. */\n private touch(url: string): void {\n const sheet = this.sheets.get(url);\n if (!sheet) return;\n this.sheets.delete(url);\n this.sheets.set(url, sheet);\n }\n\n private evict(): void {\n while (this.sheets.size > MAX_CACHED_SHEETS) {\n const oldest = this.sheets.keys().next().value as string;\n const sheet = this.sheets.get(oldest)!;\n sheet.img.onload = null;\n sheet.img.onerror = null;\n this.sheets.delete(oldest);\n }\n }\n\n private loadVtt(): Promise<void> {\n if (this.vttLoading) return this.vttLoading;\n const vttUrl = this.options.vtt!;\n this.vttLoading = fetch(vttUrl)\n .then((r) => {\n if (!r.ok) throw new Error(`HTTP ${r.status}`);\n return r.text();\n })\n .then((text) => {\n if (this.destroyed) return;\n this.vttCues = parseThumbnailVtt(text, new URL(vttUrl, document.baseURI).href);\n if (this.vttCues.length) void this.ensureSheet(this.vttCues[0]!.url);\n if (this.hovering) this.scheduleRender();\n })\n .catch((err) => {\n console.warn('[HopePlayer sprite-thumbnails] VTT yüklenemedi:', err);\n this.vttCues = [];\n });\n return this.vttLoading;\n }\n}\n\n/** \"01:02:03.500\" / \"02:03.500\" → saniye. */\nfunction parseVttTime(value: string): number {\n const parts = value.trim().split(':').map(Number);\n return parts.reduce((acc, n) => acc * 60 + n, 0);\n}\n\n/** WebVTT thumbnail dosyası → sıralı cue listesi. Görsel yolları VTT dosyasına göre çözümlenir. */\nexport function parseThumbnailVtt(text: string, baseUrl: string): VttCue[] {\n const cues: VttCue[] = [];\n const blocks = text.replace(/\\r/g, '').split(/\\n\\n+/);\n for (const block of blocks) {\n const lines = block.split('\\n').filter(Boolean);\n const timingIndex = lines.findIndex((l) => l.includes('-->'));\n if (timingIndex === -1) continue;\n const [startStr, endStr] = lines[timingIndex]!.split('-->');\n const target = lines[timingIndex + 1]?.trim();\n if (!startStr || !endStr || !target) continue;\n\n const [path, hash] = target.split('#');\n const match = hash?.match(/xywh=(\\d+),(\\d+),(\\d+),(\\d+)/);\n cues.push({\n start: parseVttTime(startStr),\n end: parseVttTime(endStr.trim().split(/\\s+/)[0]!),\n url: new URL(path!, baseUrl).href,\n rect: match ? { x: +match[1]!, y: +match[2]!, w: +match[3]!, h: +match[4]! } : null,\n });\n }\n return cues.sort((a, b) => a.start - b.start);\n}\n","import { SpriteThumbnails, type SpriteThumbnailsPlayerContext } from './SpriteThumbnails';\nimport type { SpriteThumbnailsOptions } from '../../types';\n\nexport function installSpriteThumbnails(ctx: SpriteThumbnailsPlayerContext, options: SpriteThumbnailsOptions): SpriteThumbnails {\n return new SpriteThumbnails(ctx, options);\n}\n\nexport { SpriteThumbnails };\nexport type { SpriteThumbnailsPlayerContext };\n"],"names":["MAX_CACHED_SHEETS","SHEET_TEMPLATE","SpriteThumbnails","ctx","options","__publicField","e","duration","t","sheet","seconds","formatTime","frame","scale","naturalWidth","naturalHeight","barRect","tipWidth","x","responsive","playerWidth","downlink","_a","anyReady","s","d","index","url","number","_m","_p","width","height","interval","sheetDuration","lastIndex","columns","rows","local","frameIndex","n","cues","lo","hi","mid","cue","c","rect","existing","img","resolve","done","capacity","oldest","vttUrl","r","text","parseThumbnailVtt","err","parseVttTime","value","acc","baseUrl","blocks","block","lines","timingIndex","l","startStr","endStr","target","path","hash","match","a","b","installSpriteThumbnails"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-BbRYOSvk.js","sources":["../../src/plugins/rewarded/gpt.ts","../../src/plugins/rewarded/RewardedUnlock.ts","../../src/plugins/rewarded/index.ts"],"sourcesContent":["import type { RewardedResult } from '../../types';\n\n/** Google Publisher Tag'in kullanılan yüzeyi (minimal tipler). */\ninterface GptSlot {\n addService(service: unknown): GptSlot;\n}\ninterface GptEvent {\n slot: GptSlot;\n isEmpty?: boolean;\n makeRewardedVisible?: () => boolean | void;\n}\ninterface GptPubAds {\n addEventListener(type: string, listener: (e: GptEvent) => void): void;\n removeEventListener?(type: string, listener: (e: GptEvent) => void): void;\n}\ninterface GoogleTag {\n cmd: Array<() => void> | { push(fn: () => void): void };\n apiReady?: boolean;\n enums: { OutOfPageFormat: { REWARDED: unknown } };\n pubads(): GptPubAds;\n defineOutOfPageSlot(path: string, format: unknown): GptSlot | null;\n enableServices(): void;\n display(slot: GptSlot): void;\n destroySlots(slots: GptSlot[]): void;\n}\n\n/** Google'ın güncel örneklerindeki adres (eski securepagead2 adresi bazı ağlarda sertifika hatası veriyordu). */\nconst GPT_SRC = 'https://securepubads.g.doubleclick.net/tag/js/gpt.js';\nlet gptLoading: Promise<void> | null = null;\n\n/** GPT sayfada yoksa yükler; sayfa GPT'yi (hangi adresten olursa olsun) zaten yüklüyorsa onu paylaşır. */\nfunction loadGpt(): Promise<void> {\n const w = window as unknown as { googletag?: Partial<GoogleTag> };\n w.googletag ??= { cmd: [] } as Partial<GoogleTag>;\n w.googletag.cmd ??= [];\n if (w.googletag.apiReady || document.querySelector('script[src*=\"/tag/js/gpt.js\"]')) return Promise.resolve();\n gptLoading ??= new Promise<void>((resolve, reject) => {\n const s = document.createElement('script');\n s.async = true;\n s.src = GPT_SRC;\n s.onload = () => resolve();\n s.onerror = () => {\n gptLoading = null;\n s.remove();\n reject(new Error('gpt.js could not be loaded (ad blocker / network / certificate)'));\n };\n document.head.appendChild(s);\n });\n return gptLoading;\n}\n\n/**\n * GPT web rewarded akışı (Google'ın örneğiyle aynı): slot tanımla → display → `rewardedSlotReady` gelince göster →\n * `rewardedSlotGranted` ödül → `rewardedSlotClosed` kapandı → slotu yok et. Kullanıcı onayı bu fonksiyon çağrılmadan\n * ÖNCE alınmış olmalı (player'ın onay penceresi).\n *\n * `timeoutMs` betiğin yüklenmesi DAHİL en baştan sayar: GPT hiç yüklenemez ya da çalışmazsa (engelleyici, ağ,\n * sertifika) da 'nofill' döner — bekleme ekranı asla takılı kalmaz. `signal` iptal edilirse (kullanıcı \"Vazgeç\") slot\n * temizlenip 'closed' döner. Reklam görünür olduktan sonra zaman aşımı işlemez; kapanışı GPT bildirir.\n */\nexport function showGptRewarded(adUnitPath: string, timeoutMs: number, signal?: AbortSignal): Promise<RewardedResult> {\n return new Promise<RewardedResult>((resolve) => {\n let done = false;\n let granted = false;\n let videoCompleted = false;\n let slot: GptSlot | null = null;\n let googletag: GoogleTag | null = null;\n const listeners: Array<[string, (e: GptEvent) => void]> = [];\n\n const finish = (result: RewardedResult): void => {\n if (done) return;\n done = true;\n clearTimeout(timer);\n signal?.removeEventListener('abort', onAbort);\n if (googletag) {\n const pubads = googletag.pubads();\n for (const [type, fn] of listeners) pubads.removeEventListener?.(type, fn);\n if (slot) {\n try {\n googletag.destroySlots([slot]);\n } catch {\n /* zaten yok edildi */\n }\n }\n }\n resolve(result);\n };\n const onAbort = (): void => finish('closed');\n const timer = setTimeout(() => finish('nofill'), timeoutMs);\n if (signal?.aborted) {\n finish('closed');\n return;\n }\n signal?.addEventListener('abort', onAbort);\n\n loadGpt()\n .then(() => {\n if (done) return;\n const gt = (window as unknown as { googletag: GoogleTag }).googletag;\n gt.cmd.push(() => {\n if (done) return;\n googletag = gt;\n slot = gt.defineOutOfPageSlot(adUnitPath, gt.enums.OutOfPageFormat.REWARDED);\n // null: sayfa formatı desteklemiyor (ör. mobil uyumlu viewport yok) — reklam yok sayılır.\n if (!slot) {\n finish('nofill');\n return;\n }\n slot.addService(gt.pubads());\n const pubads = gt.pubads();\n const on = (type: string, fn: (e: GptEvent) => void): void => {\n listeners.push([type, fn]);\n pubads.addEventListener(type, fn);\n };\n on('rewardedSlotReady', (e) => {\n if (e.slot !== slot || done) return;\n // Reklam hazır: artık bekleme yok — kapanışı GPT bildirecek.\n clearTimeout(timer);\n signal?.removeEventListener('abort', onAbort);\n e.makeRewardedVisible?.();\n });\n // Google: \"You need to close out ads rather than relying on GPT to do so.\" — ödül verilip video reklam\n // sonuna kadar oynayınca reklam player tarafından kapatılır (slot yok edilir); kullanıcı X'e basmak\n // zorunda kalmaz. Ödülü video bitmeden veren reklamlarda kapanış video bitince olur.\n on('rewardedSlotGranted', (e) => {\n if (e.slot !== slot) return;\n granted = true;\n if (videoCompleted) finish('granted');\n });\n on('rewardedSlotVideoCompleted', (e) => {\n if (e.slot !== slot) return;\n videoCompleted = true;\n if (granted) finish('granted');\n });\n on('rewardedSlotClosed', (e) => {\n if (e.slot === slot) finish(granted ? 'granted' : 'closed');\n });\n on('slotRenderEnded', (e) => {\n if (e.slot === slot && e.isEmpty) finish('nofill');\n });\n gt.enableServices();\n gt.display(slot);\n });\n })\n .catch(() => finish('nofill'));\n });\n}\n","import type { RewardedResult, RewardedUnlockOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\nimport { LOCK_SVG } from '../../controls/SettingsMenu';\nimport { showGptRewarded } from './gpt';\n\nexport interface RewardedUnlockContext {\n hostEl: HTMLElement;\n videoEl: HTMLVideoElement;\n /** Onay penceresinin ekleneceği alan (video alanı). */\n overlayEl: HTMLElement;\n /** Buton kontrollerle birlikte görünüp gizlensin diye kontrol katmanına eklenir. */\n chromeEl: HTMLElement;\n i18n: HopeLocaleStrings;\n log(entry: { message: string; details?: Record<string, string | number | boolean | undefined> }): void;\n play(): void;\n exitFullscreen(): void;\n /** Kilitli kalitelerin en yükseği (ör. \"1080p\") — yoksa null (buton gizlenir). */\n lockedQualityLabel(): string | null;\n /** İçeriğin kimliği (kaynak listesi) — kalite değişince değişmez, başka video yüklenince değişir. */\n contentKey(): string;\n /** Kilit açıldı / geri geldi: player menüleri yeniden kurar; `upgrade` → en iyi kaliteye geç. */\n onLockChange(upgrade: boolean): void;\n}\n\nconst DEFAULT_MAX_FREE_HEIGHT = 480;\nconst DEFAULT_STORAGE_KEY = 'hope-rewarded-unlock';\nconst DEFAULT_GPT_TIMEOUT_MS = 8000;\nconst TOAST_MS = 2600;\n\ntype Phase = 'idle' | 'prompt' | 'loading' | 'nofill';\n\n/**\n * Ödüllü reklamla kalite kilidi. Akış (Google'ın ödüllü reklam politikasına göre): kullanıcı kilitli bir kaliteye ya da\n * \"Yüksek kaliteyi aç\" butonuna dokunur → ödülü açıkça yazan onay penceresi → yalnızca \"Reklamı izle\" ile reklam istenir\n * → ödül verildiyse kilit açılır. Vazgeçmek videoyu izlemeyi engellemez (düşük kalitede devam eder).\n */\nexport class RewardedUnlock {\n private options: RewardedUnlockOptions;\n private readonly button: HTMLButtonElement;\n private dialog: HTMLDivElement | null = null;\n private toast: HTMLDivElement | null = null;\n private toastTimer: ReturnType<typeof setTimeout> | null = null;\n private phase: Phase = 'idle';\n /** 'video' modunda kilidin açık olduğu içerik (kaynak listesi — kalite dosyası değil). */\n private videoUnlockedKey: string | null = null;\n private lastKey = '';\n\n constructor(\n private readonly ctx: RewardedUnlockContext,\n options: RewardedUnlockOptions\n ) {\n this.options = options;\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'hp-rw-button';\n btn.setAttribute('part', 'rewarded-button');\n btn.addEventListener('click', (e) => {\n e.stopPropagation();\n this.requestUnlock();\n });\n btn.addEventListener('pointerdown', (e) => e.stopPropagation());\n ctx.chromeEl.appendChild(btn);\n this.button = btn;\n ctx.videoEl.addEventListener('loadstart', this.onSourceChange);\n this.refreshLabels();\n this.onQualitiesChanged();\n }\n\n update(options: RewardedUnlockOptions): void {\n const before = this.unlocked;\n this.options = options;\n if (before !== this.unlocked) this.ctx.onLockChange(false);\n this.onQualitiesChanged();\n }\n\n // ── Kilit durumu ────────────────────────────────────────────────────\n\n private get maxFreeHeight(): number {\n const h = this.options.maxFreeHeight;\n return typeof h === 'number' && h > 0 ? h : DEFAULT_MAX_FREE_HEIGHT;\n }\n\n private get storageKey(): string {\n return this.options.storageKey || DEFAULT_STORAGE_KEY;\n }\n\n private get unlockFor(): 'video' | 'session' | number {\n const u = this.options.unlockFor;\n return typeof u === 'number' && u > 0 ? u : u === 'video' ? 'video' : 'session';\n }\n\n get unlocked(): boolean {\n const mode = this.unlockFor;\n if (mode === 'video') return !!this.videoUnlockedKey && this.videoUnlockedKey === this.ctx.contentKey();\n try {\n if (mode === 'session') return sessionStorage.getItem(this.storageKey) === '1';\n const until = Number(localStorage.getItem(this.storageKey));\n return Number.isFinite(until) && until > Date.now();\n } catch {\n return false; // depolama kapalı (gizli mod vb.)\n }\n }\n\n private grant(): void {\n const mode = this.unlockFor;\n if (mode === 'video') this.videoUnlockedKey = this.ctx.contentKey();\n try {\n if (mode === 'session') sessionStorage.setItem(this.storageKey, '1');\n else if (typeof mode === 'number') localStorage.setItem(this.storageKey, String(Date.now() + mode * 60_000));\n } catch {\n // Depolama yoksa yalnızca bu video için açık kalır.\n this.videoUnlockedKey = this.ctx.contentKey();\n }\n }\n\n /** Player için: bu yükseklikteki kalite kilitli mi? */\n isLocked(height: number | null): boolean {\n if (this.unlocked) return false;\n return height !== null && height > this.maxFreeHeight;\n }\n\n /** Kaynak değişti: 'video' modunda kilit yeniden kapanır; süreli kilit dolduysa menüler güncellenir. */\n private readonly onSourceChange = (): void => {\n const key = this.ctx.contentKey();\n if (key === this.lastKey) return;\n this.lastKey = key;\n this.onQualitiesChanged();\n };\n\n /** Player kalite listesi değişince çağırır: buton yalnızca kilitli kalite varken görünür. */\n onQualitiesChanged(): void {\n const label = this.ctx.lockedQualityLabel();\n const show = this.options.button !== false && !!label && !this.unlocked;\n this.button.hidden = !show;\n if (show) this.button.innerHTML = `${LOCK_SVG}<span>${escapeHtml(this.fill(this.ctx.i18n.rewardedButton, label!))}</span>`;\n }\n\n // ── Akış ────────────────────────────────────────────────────────────\n\n /** Kilitli kaliteye ya da butona dokunuldu: onay penceresi. */\n requestUnlock(): void {\n if (this.unlocked || this.phase !== 'idle') return;\n const label = this.ctx.lockedQualityLabel() ?? 'HD';\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:rewardedprompt', { detail: { quality: label } }));\n this.showDialog('prompt', label);\n }\n\n private async watch(label: string): Promise<void> {\n const v = this.ctx.videoEl;\n const wasPlaying = !v.paused;\n v.pause();\n // GPT reklamı sayfanın kendi katmanında açılır — player tam ekrandaysa görünmez.\n this.ctx.exitFullscreen();\n this.abort = new AbortController();\n const signal = this.abort.signal;\n this.showDialog('loading', label);\n let result: RewardedResult;\n try {\n result = await this.runProvider(signal);\n } catch (err) {\n this.ctx.log({ message: `Rewarded ad failed: ${String(err)}` });\n result = 'nofill';\n }\n this.abort = null;\n // Kullanıcı hazırlanırken \"Vazgeç\" dedi — sonuç ne olursa olsun ödül yok, video devam eder.\n if (signal.aborted) {\n this.closeDialog();\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:rewardedclosed', { detail: { granted: false, cancelled: true } }));\n if (wasPlaying) this.ctx.play();\n return;\n }\n // Reklam yok / boş / hata: kusur kullanıcıda değil — varsayılan olarak kilit yine de açılır (grantOnNoFill: false kapatır).\n let noAd = false;\n if (result === 'nofill' && this.options.grantOnNoFill !== false) {\n this.ctx.log({ message: 'Rewarded ad: no ad available (no fill / error / timeout) — unlocked anyway (grantOnNoFill)' });\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:rewardednofill', { detail: { granted: true } }));\n result = 'granted';\n noAd = true;\n }\n if (result === 'granted') {\n this.grant();\n this.closeDialog();\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:rewardedgranted', { detail: { quality: label, noAd } }));\n this.ctx.onLockChange(true);\n this.onQualitiesChanged();\n this.showToast(this.fill(noAd ? this.ctx.i18n.rewardedUnlockedNoAd : this.ctx.i18n.rewardedUnlocked, label));\n if (wasPlaying) this.ctx.play();\n return;\n }\n if (result === 'nofill') {\n this.ctx.log({ message: 'Rewarded ad: no ad available (no fill / unsupported page / timeout)' });\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:rewardednofill', { detail: { granted: false } }));\n this.showDialog('nofill', label);\n this.resumeAfterDialog = wasPlaying;\n return;\n }\n // Kullanıcı reklamı ödül kazanmadan kapattı — video kaldığı kalitede devam eder.\n this.closeDialog();\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:rewardedclosed', { detail: { granted: false } }));\n if (wasPlaying) this.ctx.play();\n }\n\n private resumeAfterDialog = false;\n /** Reklam hazırlanırken \"Vazgeç\" — sağlayıcıya iletilir (GPT slotu temizlenir). */\n private abort: AbortController | null = null;\n\n private async runProvider(signal: AbortSignal): Promise<RewardedResult> {\n const p = this.options.provider;\n if (p?.type === 'gpt') return showGptRewarded(p.adUnitPath, p.timeoutMs ?? DEFAULT_GPT_TIMEOUT_MS, signal);\n if (p?.type === 'custom') {\n // İptal edilirse kendi reklam sisteminizin sonucu beklenmez (sinyali kendi tarafınızda da dinleyebilirsiniz).\n const aborted = new Promise<RewardedResult>((resolve) => signal.addEventListener('abort', () => resolve('closed'), { once: true }));\n const r = await Promise.race([p.show({ signal }), aborted]);\n return r === true ? 'granted' : r === false ? 'closed' : r;\n }\n throw new Error('rewardedUnlock.provider is missing');\n }\n\n // ── Arayüz ─────────────────────────────────────────────────────────\n\n private fill(template: string, quality: string): string {\n const mode = this.unlockFor;\n const i = this.ctx.i18n;\n const duration =\n mode === 'video' ? i.rewardedForVideo : mode === 'session' ? i.rewardedForSession : i.rewardedForMinutes.replace('{n}', String(mode));\n return template.replace('{quality}', quality).replace('{duration}', duration);\n }\n\n private showDialog(phase: Exclude<Phase, 'idle'>, label: string): void {\n this.phase = phase;\n const i = this.ctx.i18n;\n if (!this.dialog) {\n const d = document.createElement('div');\n d.className = 'hp-rw-dialog';\n d.setAttribute('part', 'rewarded-dialog');\n d.setAttribute('role', 'dialog');\n d.setAttribute('aria-modal', 'true');\n for (const t of ['click', 'pointerdown', 'dblclick'] as const) d.addEventListener(t, (e) => e.stopPropagation());\n d.addEventListener('keydown', (e) => {\n e.stopPropagation();\n if (e.key !== 'Escape') return;\n if (this.phase === 'loading') this.abort?.abort();\n else this.dismiss();\n });\n this.ctx.overlayEl.appendChild(d);\n this.dialog = d;\n }\n const d = this.dialog;\n d.setAttribute('data-phase', phase);\n d.innerHTML = '';\n const card = document.createElement('div');\n card.className = 'hp-rw-card';\n const icon = document.createElement('div');\n icon.className = 'hp-rw-icon';\n icon.innerHTML = LOCK_SVG;\n const title = document.createElement('div');\n title.className = 'hp-rw-title';\n const text = document.createElement('div');\n text.className = 'hp-rw-text';\n const actions = document.createElement('div');\n actions.className = 'hp-rw-actions';\n card.append(icon, title, text, actions);\n d.appendChild(card);\n\n const button = (labelText: string, primary: boolean, onClick: () => void): HTMLButtonElement => {\n const b = document.createElement('button');\n b.type = 'button';\n b.className = primary ? 'hp-rw-btn hp-rw-btn-primary' : 'hp-rw-btn';\n b.textContent = labelText;\n b.addEventListener('click', onClick);\n actions.appendChild(b);\n return b;\n };\n\n if (phase === 'prompt') {\n title.textContent = this.fill(i.rewardedTitle, label);\n // Ödül, reklamdan ÖNCE açıkça yazılır (politika şartı).\n text.textContent = this.fill(i.rewardedBody, label);\n button(i.rewardedDecline, false, () => this.dismiss());\n button(i.rewardedWatch, true, () => void this.watch(label)).focus();\n } else if (phase === 'loading') {\n title.textContent = i.rewardedLoading;\n const spin = document.createElement('div');\n spin.className = 'hp-rw-spinner';\n text.appendChild(spin);\n // Hazırlanma ne kadar sürerse sürsün kullanıcı takılı kalmaz.\n button(i.rewardedDecline, false, () => this.abort?.abort());\n } else {\n title.textContent = this.fill(i.rewardedTitle, label);\n text.textContent = i.rewardedNoFill;\n button(i.rewardedOk, true, () => this.dismiss()).focus();\n }\n }\n\n private dismiss(): void {\n const wasNoFill = this.phase === 'nofill';\n this.closeDialog();\n if (!wasNoFill) this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:rewardedclosed', { detail: { granted: false, declined: true } }));\n if (this.resumeAfterDialog) this.ctx.play();\n this.resumeAfterDialog = false;\n }\n\n private closeDialog(): void {\n this.phase = 'idle';\n this.dialog?.remove();\n this.dialog = null;\n }\n\n private showToast(message: string): void {\n if (this.toastTimer) clearTimeout(this.toastTimer);\n this.toast?.remove();\n const t = document.createElement('div');\n t.className = 'hp-rw-toast';\n t.setAttribute('part', 'rewarded-toast');\n t.setAttribute('role', 'status');\n t.textContent = message;\n this.ctx.overlayEl.appendChild(t);\n this.toast = t;\n this.toastTimer = setTimeout(() => {\n this.toast?.remove();\n this.toast = null;\n }, TOAST_MS);\n }\n\n refreshLabels(): void {\n this.button.setAttribute('aria-label', this.ctx.i18n.rewardedButton.replace('{quality}', 'HD'));\n this.onQualitiesChanged();\n }\n\n destroy(): void {\n this.abort?.abort();\n this.ctx.videoEl.removeEventListener('loadstart', this.onSourceChange);\n if (this.toastTimer) clearTimeout(this.toastTimer);\n this.toast?.remove();\n this.closeDialog();\n this.button.remove();\n }\n}\n\nfunction escapeHtml(s: string): string {\n return s.replace(/[&<>\"']/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;', \"'\": '&#39;' })[c]!);\n}\n","import { RewardedUnlock, type RewardedUnlockContext } from './RewardedUnlock';\nimport type { RewardedUnlockOptions } from '../../types';\n\n/** Ödüllü reklamla kalite kilidini kurar. */\nexport function installRewardedUnlock(ctx: RewardedUnlockContext, options: RewardedUnlockOptions): RewardedUnlock {\n return new RewardedUnlock(ctx, options);\n}\n\nexport { RewardedUnlock };\nexport type { RewardedUnlockContext };\n"],"names":["GPT_SRC","gptLoading","loadGpt","w","_a","resolve","reject","showGptRewarded","adUnitPath","timeoutMs","signal","done","granted","videoCompleted","slot","googletag","listeners","finish","result","timer","onAbort","pubads","type","fn","gt","on","e","DEFAULT_MAX_FREE_HEIGHT","DEFAULT_STORAGE_KEY","DEFAULT_GPT_TIMEOUT_MS","TOAST_MS","RewardedUnlock","ctx","options","__publicField","key","btn","before","h","u","mode","until","height","label","show","LOCK_SVG","escapeHtml","v","wasPlaying","err","noAd","p","aborted","r","template","quality","i","duration","phase","d","t","card","icon","title","text","actions","button","labelText","primary","onClick","b","spin","wasNoFill","message","_b","s","c","installRewardedUnlock"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-BeJNpAyx.js","sources":["../../src/plugins/audio/vinylSvg.ts","../../src/plugins/audio/AudioStage.ts","../../src/plugins/audio/index.ts"],"sourcesContent":["/**\n * Plak ve pikap kolu — elle çizilmiş SVG (dış görsel yok). Disk döner; ışık yansıması ayrı bir katmanda sabit kalır,\n * böylece dönüş gerçek bir plaktaki gibi okunur. Oluklar tam simetrik olduğundan etikette dönüşü gösteren bir işaret var.\n */\n\nconst SVG_NS = 'http://www.w3.org/2000/svg';\nlet uid = 0;\n\nfunction grooves(): string {\n let out = '';\n // Kayıt alanı r=40..95; iki şarkı arası boşluk gibi birkaç koyu halka.\n for (let r = 40; r <= 95; r += 1.25) {\n const gap = Math.abs(r - 58) < 0.7 || Math.abs(r - 74) < 0.7;\n const alpha = gap ? 0 : 0.035 + ((r * 7) % 5) * 0.008;\n out += `<circle cx=\"100\" cy=\"100\" r=\"${r}\" fill=\"none\" stroke=\"rgba(255,255,255,${alpha.toFixed(3)})\" stroke-width=\"0.45\"/>`;\n }\n return out;\n}\n\n/** Dönen disk: oluklar, etiket (kapak ya da düz renk), merkez deliği. */\nexport function createDisc(): { el: SVGSVGElement; setLabel(cover: string | null, text: string): void } {\n const id = `hp-vinyl-${++uid}`;\n const wrap = document.createElement('div');\n wrap.innerHTML = `\n<svg xmlns=\"${SVG_NS}\" viewBox=\"0 0 200 200\" aria-hidden=\"true\" focusable=\"false\">\n <defs>\n <radialGradient id=\"${id}-disc\" cx=\"50%\" cy=\"50%\" r=\"50%\">\n <stop offset=\"0\" stop-color=\"#1c1c1f\"/>\n <stop offset=\"0.45\" stop-color=\"#101012\"/>\n <stop offset=\"0.97\" stop-color=\"#151518\"/>\n <stop offset=\"1\" stop-color=\"#2a2a2e\"/>\n </radialGradient>\n <clipPath id=\"${id}-label\"><circle cx=\"100\" cy=\"100\" r=\"34\"/></clipPath>\n </defs>\n <circle cx=\"100\" cy=\"100\" r=\"99.5\" fill=\"url(#${id}-disc)\"/>\n ${grooves()}\n <circle cx=\"100\" cy=\"100\" r=\"96.5\" fill=\"none\" stroke=\"rgba(255,255,255,0.10)\" stroke-width=\"0.6\"/>\n <circle cx=\"100\" cy=\"100\" r=\"38\" fill=\"none\" stroke=\"#050506\" stroke-width=\"3\"/>\n <g class=\"hp-vinyl-label\">\n <circle cx=\"100\" cy=\"100\" r=\"34\" fill=\"var(--hp-color-accent, #e5484d)\"/>\n <image class=\"hp-vinyl-cover\" x=\"66\" y=\"66\" width=\"68\" height=\"68\" preserveAspectRatio=\"xMidYMid slice\" clip-path=\"url(#${id}-label)\"/>\n <circle cx=\"100\" cy=\"100\" r=\"34\" fill=\"none\" stroke=\"rgba(0,0,0,0.35)\" stroke-width=\"1\"/>\n <text class=\"hp-vinyl-text\" x=\"100\" y=\"80\" text-anchor=\"middle\" font-size=\"6.5\" font-weight=\"700\" fill=\"rgba(0,0,0,0.72)\" font-family=\"system-ui, sans-serif\"></text>\n <circle cx=\"100\" cy=\"122\" r=\"2.2\" fill=\"rgba(255,255,255,0.85)\"/>\n </g>\n <circle cx=\"100\" cy=\"100\" r=\"3.6\" fill=\"#0b0b0c\"/>\n <circle cx=\"100\" cy=\"100\" r=\"3.6\" fill=\"none\" stroke=\"rgba(255,255,255,0.35)\" stroke-width=\"0.6\"/>\n</svg>`;\n const svg = wrap.firstElementChild as SVGSVGElement;\n const image = svg.querySelector('.hp-vinyl-cover') as SVGImageElement;\n const text = svg.querySelector('.hp-vinyl-text') as SVGTextElement;\n return {\n el: svg,\n setLabel(cover, label) {\n if (cover) {\n image.setAttribute('href', cover);\n image.style.display = '';\n } else {\n image.removeAttribute('href');\n image.style.display = 'none';\n }\n // Kapak varsa yazı kapağın üstüne binmesin.\n text.textContent = cover ? '' : label.slice(0, 22);\n },\n };\n}\n\n/** Pikap kolu: sağ üstteki mile bağlı; çalarken plağın üzerine iner. */\nexport function createTonearm(): SVGSVGElement {\n const wrap = document.createElement('div');\n wrap.innerHTML = `\n<svg xmlns=\"${SVG_NS}\" viewBox=\"0 0 100 200\" aria-hidden=\"true\" focusable=\"false\">\n <circle cx=\"70\" cy=\"22\" r=\"15\" fill=\"#2b2b30\" stroke=\"rgba(255,255,255,0.18)\" stroke-width=\"1\"/>\n <circle cx=\"70\" cy=\"22\" r=\"7\" fill=\"#9a9aa2\"/>\n <path d=\"M70 22 L66 120 L40 162\" fill=\"none\" stroke=\"#c9c9cf\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <rect x=\"26\" y=\"156\" width=\"20\" height=\"28\" rx=\"3\" transform=\"rotate(32 36 170)\" fill=\"#3a3a40\" stroke=\"rgba(255,255,255,0.25)\" stroke-width=\"1\"/>\n</svg>`;\n return wrap.firstElementChild as SVGSVGElement;\n}\n","import type { AudioOptions, VinylOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\nimport { createDisc, createTonearm } from './vinylSvg';\nimport type { ScratchSound } from './ScratchSound';\n\nexport interface AudioStageContext {\n videoEl: HTMLVideoElement;\n /** Sahnenin ekleneceği katman (video ile reklam katmanı arasında). */\n layerEl: HTMLElement;\n /** Kapak verilmezse kullanılan görsel (options.poster). */\n poster(): string | undefined;\n /** Player'ın oynat / duraklat yolu (preroll kapısına uyar). */\n togglePlay(): void;\n play(): void;\n i18n: HopeLocaleStrings;\n /** İnce çubuk (layout: 'compact'): başlık / sanatçıyı kontrol çubuğuna yazar; `null` kaldırır. */\n setBarMeta(meta: { title: string; subtitle: string } | null): void;\n}\n\nconst DEFAULT_SIZE = 0.78;\nconst DEFAULT_RPM = 100 / 3;\n/** Kontrol çubuğunun üstündeki alan bundan kısaysa başlık gizlenir, plağa yer kalır (ör. mobilde 16:9). */\nconst SHORT_STAGE_PX = 230;\n\n/** Bu kadar dereceden az çevirme \"dokunuş\" sayılır: oynat / duraklat. */\nconst TAP_DEGREES = 4;\n/** Bundan kısa, çevirmesiz basış \"dokunuş\"tur (oynat / duraklat); daha uzunu \"tutuş\" (bırakınca çalmaya devam). */\nconst TAP_MS = 250;\nconst MEDIA_SESSION_SEEK_SECONDS = 10;\n\ntype ResolvedVinyl = Required<VinylOptions>;\n\nfunction resolveVinyl(v: AudioOptions['vinyl']): ResolvedVinyl | null {\n if (v === false) return null;\n const o = v === true || v === undefined ? {} : v;\n const size = typeof o.size === 'number' && Number.isFinite(o.size) ? Math.min(1, Math.max(0.3, o.size)) : DEFAULT_SIZE;\n const rpm = typeof o.rpm === 'number' && o.rpm > 0 ? o.rpm : DEFAULT_RPM;\n return {\n position: o.position === 'center' || o.position === 'left' ? o.position : 'right',\n size,\n rpm,\n scratch: o.scratch !== false,\n scratchSound: o.scratchSound === true,\n tonearm: o.tonearm !== false,\n };\n}\n\n/** -180..180 aralığına indirger (açı farkı). */\nfunction wrapDegrees(d: number): number {\n return ((((d + 180) % 360) + 360) % 360) - 180;\n}\n\n/**\n * Ses modunun sahnesi: bulanık kapak zemini, kapak (plak kılıfı), dönen plak, pikap kolu, başlık / sanatçı.\n * Plağın açısı doğrudan çalma zamanından hesaplanır (açı = zaman / tur süresi × 360): sarınca, atlayınca, scratch\n * yapınca plak her zaman sesle aynı yerde durur.\n */\nexport class AudioStage {\n readonly el: HTMLDivElement;\n private readonly backdropImg: HTMLImageElement;\n private readonly sleeve: HTMLDivElement;\n private readonly sleeveImg: HTMLImageElement;\n private readonly vinylEl: HTMLDivElement;\n private readonly discEl: HTMLDivElement;\n private readonly armHolder: HTMLDivElement;\n private readonly titleEl: HTMLDivElement;\n private readonly artistEl: HTMLDivElement;\n private readonly areaEl: HTMLDivElement;\n private readonly resizeObserver: ResizeObserver | null;\n private readonly disc: ReturnType<typeof createDisc>;\n\n private options: AudioOptions = {};\n private vinyl: ResolvedVinyl | null = null;\n private frame = 0;\n private lastAriaSecond = -1;\n private lastPositionState = 0;\n\n // Scratch durumu\n private dragging = false;\n private dragPointer = -1;\n private center = { x: 0, y: 0 };\n private lastPointerAngle = 0;\n private accum = 0;\n private dragStartTime = 0;\n private dragStartAngle = 0;\n private moved = false;\n private wasPlaying = false;\n private downAt = 0;\n private seekFrame = 0;\n private pendingSeek: number | null = null;\n /** vinyl.scratchSound — ayrı parça olarak yalnızca açıksa yüklenir. */\n private sound: ScratchSound | null = null;\n private soundImport: Promise<ScratchSound | null> | null = null;\n private prepareTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(private readonly ctx: AudioStageContext) {\n const el = document.createElement('div');\n el.className = 'hp-audio';\n el.setAttribute('part', 'audio-stage');\n el.innerHTML = `\n <div class=\"hp-audio-backdrop\"><img alt=\"\" decoding=\"async\"></div>\n <div class=\"hp-audio-meta\"><div class=\"hp-audio-title\" part=\"audio-title\"></div><div class=\"hp-audio-artist\" part=\"audio-artist\"></div></div>\n <div class=\"hp-audio-area\">\n <div class=\"hp-audio-deck\">\n <div class=\"hp-audio-sleeve\" part=\"audio-cover\"><img alt=\"\" decoding=\"async\"></div>\n <div class=\"hp-vinyl\" part=\"vinyl\" role=\"slider\" tabindex=\"-1\" aria-valuemin=\"0\">\n <div class=\"hp-vinyl-disc\"></div>\n <div class=\"hp-vinyl-sheen\"></div>\n <div class=\"hp-tonearm-holder\"><div class=\"hp-tonearm\"></div></div>\n </div>\n </div>\n </div>`;\n this.el = el;\n this.backdropImg = el.querySelector('.hp-audio-backdrop img')!;\n this.sleeve = el.querySelector('.hp-audio-sleeve')!;\n this.sleeveImg = this.sleeve.querySelector('img')!;\n this.vinylEl = el.querySelector('.hp-vinyl')!;\n this.discEl = el.querySelector('.hp-vinyl-disc')!;\n this.armHolder = el.querySelector('.hp-tonearm-holder')!;\n this.titleEl = el.querySelector('.hp-audio-title')!;\n this.artistEl = el.querySelector('.hp-audio-artist')!;\n this.disc = createDisc();\n this.discEl.appendChild(this.disc.el);\n el.querySelector('.hp-tonearm')!.appendChild(createTonearm());\n // Kırık kapak bağlantısı: görseli gizle, zemin temaya düşsün.\n for (const img of [this.backdropImg, this.sleeveImg]) {\n img.addEventListener('error', () => img.removeAttribute('src'));\n }\n\n const v = ctx.videoEl;\n v.addEventListener('play', this.onPlay);\n v.addEventListener('pause', this.onPause);\n v.addEventListener('ended', this.onPause);\n v.addEventListener('seeked', this.render);\n v.addEventListener('timeupdate', this.onTimeUpdate);\n v.addEventListener('durationchange', this.onDurationChange);\n v.addEventListener('ratechange', this.updatePositionState);\n v.addEventListener('emptied', this.render);\n\n this.vinylEl.addEventListener('pointerdown', this.onPointerDown);\n this.vinylEl.addEventListener('pointermove', this.onPointerMove);\n this.vinylEl.addEventListener('pointerup', this.onPointerUp);\n this.vinylEl.addEventListener('pointercancel', this.onPointerUp);\n this.vinylEl.addEventListener('lostpointercapture', this.onPointerUp);\n // Plağa tık / dokunuş videonun \"boş alana tık\" işleyicilerine düşmesin (oynat/duraklat'ı kendimiz yapıyoruz).\n for (const type of ['click', 'mousedown', 'mouseup', 'touchstart', 'touchend', 'dblclick'] as const) {\n this.vinylEl.addEventListener(type, (e) => e.stopPropagation());\n }\n\n // Videonun hemen üstü: yükleme halkası ve reklam katmanı sahnenin üstünde kalır.\n ctx.layerEl.insertBefore(el, ctx.videoEl.nextSibling);\n this.areaEl = el.querySelector('.hp-audio-area')!;\n // Plak / kapak boyutu JS ile (px): CSS konteyner sorgu birimleri (cqh/cqw) iOS 16 öncesi Safari'de yok, orada\n // boyut kuralı düşüp kapak dev boyutta sola taşıyordu.\n this.resizeObserver = typeof ResizeObserver !== 'undefined' ? new ResizeObserver(() => this.layout()) : null;\n this.resizeObserver?.observe(el);\n this.resizeObserver?.observe(this.areaEl);\n this.refreshLabels();\n }\n\n update(options: AudioOptions): void {\n this.options = options;\n const compact = options.layout === 'compact';\n this.el.setAttribute('data-layout', compact ? 'compact' : 'full');\n // İnce çubukta kapak / plak yok — başlık ve sanatçı kontrol çubuğunda.\n this.ctx.setBarMeta(\n compact ? { title: options.title ?? '', subtitle: [options.artist, options.album].filter(Boolean).join(' · ') } : null\n );\n this.vinyl = compact ? null : resolveVinyl(options.vinyl);\n const cover = options.cover || this.ctx.poster() || '';\n for (const img of [this.backdropImg, this.sleeveImg]) {\n if (cover) img.src = cover;\n else img.removeAttribute('src');\n }\n this.el.toggleAttribute('data-cover', !!cover);\n this.titleEl.textContent = options.title ?? '';\n this.artistEl.textContent = [options.artist, options.album].filter(Boolean).join(' · ');\n this.el.toggleAttribute('data-meta', !!(options.title || options.artist || options.album));\n\n const vinyl = this.vinyl;\n this.el.setAttribute('data-position', vinyl ? vinyl.position : 'none');\n this.el.style.setProperty('--hp-vinyl-size', String(vinyl?.size ?? DEFAULT_SIZE));\n this.vinylEl.hidden = !vinyl;\n // 'center': kılıf yok. Plak kapalıysa yalnızca kapak. Etikette her zaman kapak (yoksa düz renk + başlık).\n this.sleeve.hidden = !!vinyl && vinyl.position === 'center';\n this.disc.setLabel(cover || null, options.title || 'HopeCore');\n this.armHolder.hidden = !vinyl?.tonearm;\n this.vinylEl.toggleAttribute('data-scratch', !!vinyl?.scratch);\n this.vinylEl.tabIndex = vinyl ? 0 : -1;\n\n if (!vinyl?.scratchSound) this.disableSound();\n else if (!this.ctx.videoEl.paused) this.schedulePrepareSound();\n\n this.applyMediaSession();\n this.onDurationChange();\n this.layout();\n this.render();\n if (!this.ctx.videoEl.paused) this.onPlay();\n }\n\n /** Kapak / plak yüksekliği: alan yüksekliğinin `size` katı, genişliğe sığacak kadar (kılıf + yarım plak ≈ 1,46 H). */\n private layout(): void {\n if (!this.el.isConnected) return;\n const w = this.areaEl.clientWidth;\n const h = this.areaEl.clientHeight;\n const size = this.vinyl?.size ?? resolveVinyl(this.options.vinyl)?.size ?? DEFAULT_SIZE;\n const withSleeveAndVinyl = !!this.vinyl && this.vinyl.position !== 'center';\n const deck = Math.max(0, Math.min(size * h, (withSleeveAndVinyl ? 0.62 : 0.9) * w));\n this.el.style.setProperty('--hp-deck-h', `${Math.round(deck * 10) / 10}px`);\n // İlk yerleşim animasyonsuz: plak 0'dan yerine kayarak gelmesin (kayma yalnızca çal / duraklat geçişinde).\n if (deck > 0 && !this.el.hasAttribute('data-laid-out')) {\n requestAnimationFrame(() => requestAnimationFrame(() => this.el.setAttribute('data-laid-out', '')));\n }\n this.el.toggleAttribute('data-short', this.el.clientHeight > 0 && this.el.clientHeight < SHORT_STAGE_PX);\n }\n\n // ── Scratch sesi ────────────────────────────────────────────────────\n\n private loadSound(): Promise<ScratchSound | null> {\n if (this.sound) return Promise.resolve(this.sound);\n this.soundImport ??= import('./ScratchSound')\n .then(({ ScratchSound }) => {\n if (!this.vinyl?.scratchSound || !ScratchSound.isSupported()) {\n this.el.setAttribute('data-scratch-sound', 'unsupported');\n return null;\n }\n this.sound ??= new ScratchSound(this.ctx.videoEl);\n this.sound.onStateChange = (state) => this.el.setAttribute('data-scratch-sound', state);\n return this.sound;\n })\n .catch(() => null)\n .finally(() => {\n this.soundImport = null;\n });\n return this.soundImport;\n }\n\n /** Çalma başlayınca, boşta: sesi önceden çöz ki ilk scratch gecikmesin. */\n private schedulePrepareSound(): void {\n if (!this.vinyl?.scratchSound || this.prepareTimer || this.sound?.ready) return;\n this.prepareTimer = setTimeout(() => {\n this.prepareTimer = null;\n const run = () => void this.loadSound().then((s) => s?.prepare());\n if ('requestIdleCallback' in window) window.requestIdleCallback(run, { timeout: 2000 });\n else run();\n }, 300);\n }\n\n private disableSound(): void {\n if (this.prepareTimer) clearTimeout(this.prepareTimer);\n this.prepareTimer = null;\n this.sound?.destroy();\n this.sound = null;\n this.el.removeAttribute('data-scratch-sound');\n }\n\n refreshLabels(): void {\n this.vinylEl.setAttribute('aria-label', this.ctx.i18n.audioVinyl);\n }\n\n // ── Dönüş ────────────────────────────────────────────────────────────\n\n private get secondsPerTurn(): number {\n return 60 / (this.vinyl?.rpm ?? DEFAULT_RPM);\n }\n\n private angleForTime(t: number): number {\n return ((t / this.secondsPerTurn) * 360) % 360;\n }\n\n private readonly render = (): void => {\n if (!this.vinyl || this.dragging) return;\n this.discEl.style.transform = `rotate(${this.angleForTime(this.ctx.videoEl.currentTime || 0)}deg)`;\n };\n\n private readonly loop = (): void => {\n this.render();\n this.frame = requestAnimationFrame(this.loop);\n };\n\n private readonly onPlay = (): void => {\n this.el.setAttribute('data-playing', '');\n this.schedulePrepareSound();\n cancelAnimationFrame(this.frame);\n if (this.vinyl) this.frame = requestAnimationFrame(this.loop);\n if (this.options.mediaSession !== false && 'mediaSession' in navigator) {\n // Sayfada birden fazla player varsa son çalan sistemin medya kontrollerini alır.\n this.applyMediaSession();\n navigator.mediaSession.playbackState = 'playing';\n }\n };\n\n private readonly onPause = (): void => {\n // Scratch sırasında plak elde tutuluyor — pikap kolu kalkmasın.\n if (!this.dragging) this.el.removeAttribute('data-playing');\n cancelAnimationFrame(this.frame);\n this.render();\n if (this.ownsMediaSession()) navigator.mediaSession.playbackState = 'paused';\n };\n\n private readonly onTimeUpdate = (): void => {\n const v = this.ctx.videoEl;\n if (v.paused) this.render();\n const second = Math.floor(v.currentTime || 0);\n if (second !== this.lastAriaSecond) {\n this.lastAriaSecond = second;\n this.vinylEl.setAttribute('aria-valuenow', String(second));\n }\n const now = performance.now();\n if (now - this.lastPositionState > 1000) this.updatePositionState();\n };\n\n private readonly onDurationChange = (): void => {\n const d = this.ctx.videoEl.duration;\n const finite = Number.isFinite(d) && d > 0;\n if (finite) this.vinylEl.setAttribute('aria-valuemax', String(Math.floor(d)));\n else this.vinylEl.removeAttribute('aria-valuemax');\n // Canlı yayında (süre sonsuz) sarma yok — plak yalnızca döner.\n this.vinylEl.toggleAttribute('data-live', !finite && d === Infinity);\n this.updatePositionState();\n };\n\n // ── Scratch ──────────────────────────────────────────────────────────\n\n private canScratch(): boolean {\n const d = this.ctx.videoEl.duration;\n return !!this.vinyl?.scratch && Number.isFinite(d) && d > 0;\n }\n\n private pointerAngle(e: PointerEvent): number {\n return (Math.atan2(e.clientY - this.center.y, e.clientX - this.center.x) * 180) / Math.PI;\n }\n\n private readonly onPointerDown = (e: PointerEvent): void => {\n if (!this.vinyl || this.dragging) return;\n if (e.pointerType === 'mouse' && e.button !== 0) return;\n e.stopPropagation();\n e.preventDefault();\n const rect = this.vinylEl.getBoundingClientRect();\n this.center = { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 };\n this.dragging = true;\n this.dragPointer = e.pointerId;\n this.lastPointerAngle = this.pointerAngle(e);\n this.accum = 0;\n this.moved = false;\n this.dragStartTime = this.ctx.videoEl.currentTime || 0;\n this.dragStartAngle = this.angleForTime(this.dragStartTime);\n this.wasPlaying = !this.ctx.videoEl.paused;\n this.downAt = performance.now();\n // Gerçek plak gibi: elle tutulan plak anında susar (çevirmeye başlamayı beklemeden).\n if (this.wasPlaying && this.canScratch()) this.ctx.videoEl.pause();\n if (this.vinyl.scratchSound && this.canScratch()) {\n // AudioContext yalnızca kullanıcı etkileşimi içinde başlatılabilir — pointerdown'da.\n if (this.sound?.ready) this.sound.start(this.dragStartTime);\n else void this.loadSound().then((s) => s?.prepare());\n }\n try {\n this.vinylEl.setPointerCapture(e.pointerId);\n } catch {\n /* eski tarayıcı */\n }\n };\n\n private readonly onPointerMove = (e: PointerEvent): void => {\n if (!this.dragging || e.pointerId !== this.dragPointer) return;\n e.stopPropagation();\n const angle = this.pointerAngle(e);\n const delta = wrapDegrees(angle - this.lastPointerAngle);\n this.lastPointerAngle = angle;\n if (!this.canScratch()) {\n this.accum += delta;\n if (Math.abs(this.accum) > TAP_DEGREES) this.moved = true;\n return;\n }\n // Başa / sona dayanınca plak daha fazla dönmez.\n const spt = this.secondsPerTurn;\n const duration = this.ctx.videoEl.duration;\n const minAccum = (-this.dragStartTime / spt) * 360;\n const maxAccum = ((duration - this.dragStartTime) / spt) * 360;\n this.accum = Math.min(maxAccum, Math.max(minAccum, this.accum + delta));\n if (!this.moved && Math.abs(this.accum) > TAP_DEGREES) {\n this.moved = true;\n this.el.setAttribute('data-scratching', '');\n }\n if (!this.moved) return;\n this.discEl.style.transform = `rotate(${this.dragStartAngle + this.accum}deg)`;\n this.pendingSeek = this.dragStartTime + (this.accum / 360) * spt;\n this.sound?.setTarget(this.pendingSeek);\n if (!this.seekFrame) this.seekFrame = requestAnimationFrame(this.flushSeek);\n };\n\n private readonly flushSeek = (): void => {\n this.seekFrame = 0;\n if (this.pendingSeek === null) return;\n this.ctx.videoEl.currentTime = this.pendingSeek;\n this.pendingSeek = null;\n };\n\n private readonly onPointerUp = (e: PointerEvent): void => {\n if (!this.dragging || e.pointerId !== this.dragPointer) return;\n e.stopPropagation();\n this.dragging = false;\n this.dragPointer = -1;\n this.el.removeAttribute('data-scratching');\n this.sound?.stop();\n if (this.seekFrame) {\n cancelAnimationFrame(this.seekFrame);\n this.flushSeek();\n }\n if (!this.moved && this.canScratch() && this.wasPlaying) {\n // Çalarken basıldı (ve basınca sustu): kısa dokunuş = duraklat (öyle kalır); tutup bırakmak = devam.\n const held = performance.now() - this.downAt >= TAP_MS;\n // Basış iptal olduysa (ör. dokunmatikte sayfa kaydırması) kullanıcı duraklatmak istememiştir — devam.\n if (held || e.type !== 'pointerup') this.ctx.play();\n else {\n this.el.removeAttribute('data-playing'); // basılıyken inik tutulan pikap kolu kalksın\n this.render();\n }\n return;\n }\n if (!this.moved) {\n if (e.type === 'pointerup') this.ctx.togglePlay();\n return;\n }\n if (this.wasPlaying) this.ctx.play();\n else this.render();\n };\n\n // ── Media Session ───────────────────────────────────────────────────\n\n private ownsMediaSession(): boolean {\n return this.options.mediaSession !== false && 'mediaSession' in navigator && AudioStage.sessionOwner === this;\n }\n\n private static sessionOwner: AudioStage | null = null;\n\n private applyMediaSession(): void {\n if (this.options.mediaSession === false || !('mediaSession' in navigator) || typeof MediaMetadata === 'undefined') return;\n // Başka bir player çalıyorsa onun bilgilerini ezme — bu player çalmaya başlayınca alır.\n const owner = AudioStage.sessionOwner;\n if (owner && owner !== this && !owner.ctx.videoEl.paused && this.ctx.videoEl.paused) return;\n AudioStage.sessionOwner = this;\n const o = this.options;\n const cover = o.cover || this.ctx.poster();\n const ms = navigator.mediaSession;\n ms.metadata = new MediaMetadata({\n title: o.title ?? '',\n artist: o.artist ?? '',\n album: o.album ?? '',\n artwork: cover ? [{ src: new URL(cover, document.baseURI).href }] : [],\n });\n const v = this.ctx.videoEl;\n const set = (action: MediaSessionAction, handler: MediaSessionActionHandler | null): void => {\n try {\n ms.setActionHandler(action, handler);\n } catch {\n /* tarayıcı bu eylemi desteklemiyor */\n }\n };\n set('play', () => this.ctx.play());\n set('pause', () => v.pause());\n set('seekbackward', (d) => (v.currentTime = Math.max(0, v.currentTime - (d.seekOffset ?? MEDIA_SESSION_SEEK_SECONDS))));\n set('seekforward', (d) => (v.currentTime = Math.min(v.duration || Infinity, v.currentTime + (d.seekOffset ?? MEDIA_SESSION_SEEK_SECONDS))));\n set('seekto', (d) => {\n if (typeof d.seekTime === 'number') v.currentTime = d.seekTime;\n });\n this.updatePositionState();\n }\n\n private readonly updatePositionState = (): void => {\n if (!this.ownsMediaSession()) return;\n this.lastPositionState = performance.now();\n const v = this.ctx.videoEl;\n const duration = v.duration;\n if (!Number.isFinite(duration) || duration <= 0) return;\n try {\n navigator.mediaSession.setPositionState({\n duration,\n playbackRate: v.playbackRate || 1,\n position: Math.min(duration, Math.max(0, v.currentTime || 0)),\n });\n } catch {\n /* geçersiz durum (ör. kaynak değişirken) */\n }\n };\n\n private releaseMediaSession(): void {\n if (AudioStage.sessionOwner !== this) return;\n AudioStage.sessionOwner = null;\n if (!('mediaSession' in navigator)) return;\n const ms = navigator.mediaSession;\n ms.metadata = null;\n for (const action of ['play', 'pause', 'seekbackward', 'seekforward', 'seekto'] as MediaSessionAction[]) {\n try {\n ms.setActionHandler(action, null);\n } catch {\n /* desteklenmiyor */\n }\n }\n }\n\n destroy(): void {\n cancelAnimationFrame(this.frame);\n cancelAnimationFrame(this.seekFrame);\n const v = this.ctx.videoEl;\n v.removeEventListener('play', this.onPlay);\n v.removeEventListener('pause', this.onPause);\n v.removeEventListener('ended', this.onPause);\n v.removeEventListener('seeked', this.render);\n v.removeEventListener('timeupdate', this.onTimeUpdate);\n v.removeEventListener('durationchange', this.onDurationChange);\n v.removeEventListener('ratechange', this.updatePositionState);\n v.removeEventListener('emptied', this.render);\n this.releaseMediaSession();\n this.disableSound();\n this.resizeObserver?.disconnect();\n this.ctx.setBarMeta(null);\n this.el.remove();\n }\n}\n","import { AudioStage, type AudioStageContext } from './AudioStage';\nimport type { AudioOptions } from '../../types';\n\n/** Ses modu sahnesini kurar (kapak, plak, scratch, sistem medya kontrolleri). */\nexport function installAudioStage(ctx: AudioStageContext, options: AudioOptions): AudioStage {\n const stage = new AudioStage(ctx);\n stage.update(options);\n return stage;\n}\n\nexport { AudioStage };\nexport type { AudioStageContext };\n"],"names":["SVG_NS","uid","grooves","out","r","alpha","createDisc","id","wrap","svg","image","text","cover","label","createTonearm","DEFAULT_SIZE","DEFAULT_RPM","SHORT_STAGE_PX","TAP_DEGREES","TAP_MS","MEDIA_SESSION_SEEK_SECONDS","resolveVinyl","v","o","size","rpm","wrapDegrees","d","_AudioStage","ctx","__publicField","second","finite","e","_a","rect","s","angle","delta","spt","duration","minAccum","maxAccum","_b","el","img","type","options","compact","vinyl","w","h","withSleeveAndVinyl","deck","ScratchSound","state","run","owner","ms","set","action","handler","AudioStage","installAudioStage","stage"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-C3BQGcT3.js","sources":["../../src/plugins/story/HopeStory.ts","../../src/plugins/story/index.ts"],"sourcesContent":["import { createIcon } from '../../icons/Icon';\nimport type { PlayableItem, StoryOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\n\nexport interface StoryPlayerContext {\n videoEl: HTMLVideoElement;\n hostEl: HTMLElement;\n /** .video-area — story aktifken 9:16'ya çevrilir (data-story attribute ile), destroy'da geri alınır. */\n videoAreaEl: HTMLElement;\n /** Gerçek player gövdesi (.media-layer + chrome + center-play-button) — orta pane'e taşınır, destroy'da geri alınır. */\n playerBodyEls: HTMLElement[];\n loadSource(src: string, type?: string): Promise<void>;\n setPoster(url: string): void;\n requestFreshAd(prerollTag?: string): void;\n i18n: HopeLocaleStrings;\n}\n\ntype Dir = 'next' | 'prev';\n\nconst DEFAULTS: Required<Omit<StoryOptions, 'items' | 'adTagPreroll' | 'gestures' | 'ui'>> = {\n startIndex: 0,\n loop: true,\n autoplayNext: true,\n preferHls: true,\n transitionMs: 380,\n adsOnItemChange: true,\n};\n\n/** Dikey video akışı (Shorts/Story): tek <video>, item değişiminde kaynak değişir. */\nexport class HopeStory {\n private readonly options: Required<Omit<StoryOptions, 'items' | 'adTagPreroll' | 'gestures' | 'ui'>>;\n private readonly gestureOpts: Required<NonNullable<StoryOptions['gestures']>>;\n private readonly uiOpts: Required<NonNullable<StoryOptions['ui']>>;\n private readonly items: PlayableItem[];\n\n private index: number;\n private destroyed = false;\n private switching = false;\n private listOpen = false;\n private userHasStartedPlayback = false;\n private lastAdsIndex: number | null = null;\n private wheelAccum = 0;\n private lastNavAt = 0;\n private drag: { startY: number; startX: number; dy: number; active: boolean; id: number } | null = null;\n\n private readonly els: {\n viewport: HTMLElement;\n track: HTMLElement;\n panePrev: HTMLElement;\n paneCurrent: HTMLElement;\n paneNext: HTMLElement;\n overlay: HTMLElement;\n counter: HTMLElement;\n titleEl: HTMLElement;\n spotEl: HTMLElement;\n dots: HTMLElement;\n progressBar: HTMLElement;\n upBtn: HTMLButtonElement;\n downBtn: HTMLButtonElement;\n listBtn: HTMLButtonElement;\n panel: HTMLElement;\n grid: HTMLElement;\n };\n\n constructor(\n private readonly ctx: StoryPlayerContext,\n private readonly rawOptions: StoryOptions\n ) {\n this.options = { ...DEFAULTS, ...rawOptions };\n this.gestureOpts = {\n swipe: true,\n swipeThreshold: 0.12,\n wheel: true,\n wheelThreshold: 42,\n wheelCooldownMs: 620,\n keyboard: true,\n ...rawOptions.gestures,\n };\n this.uiOpts = { counter: true, title: true, spot: true, dots: true, progress: true, ...rawOptions.ui };\n this.items = Array.isArray(rawOptions.items) ? rawOptions.items : [];\n this.index = this.clamp(this.options.startIndex);\n\n this.els = this.buildDom();\n this.bindEvents();\n this.syncUi();\n this.preloadNeighbours();\n\n if (this.items.length) void this.loadItem(this.index, { isStart: true });\n }\n\n refreshLabels(): void {\n this.els.upBtn.setAttribute('aria-label', this.ctx.i18n.storyPrev);\n this.els.downBtn.setAttribute('aria-label', this.ctx.i18n.storyNext);\n this.els.listBtn.setAttribute('aria-label', this.ctx.i18n.storyAllVideos);\n this.renderList(this.els.grid);\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n\n this.ctx.videoEl.removeEventListener('ended', this.onEnded);\n this.ctx.videoEl.removeEventListener('playing', this.onPlaying);\n this.ctx.videoEl.removeEventListener('play', this.onFirstPlay);\n this.ctx.videoEl.removeEventListener('timeupdate', this.onTimeUpdate);\n this.els.viewport.removeEventListener('wheel', this.onWheel);\n this.els.viewport.removeEventListener('pointerdown', this.onPointerDown);\n window.removeEventListener('pointermove', this.onPointerMove);\n window.removeEventListener('pointerup', this.onPointerUp);\n document.removeEventListener('keydown', this.onKeyDown);\n\n // player gövdesini .video-area'ya geri taşı, story DOM'unu kaldır.\n this.ctx.playerBodyEls.forEach((el) => this.ctx.videoAreaEl.appendChild(el));\n this.ctx.videoAreaEl.removeAttribute('data-story');\n this.els.viewport.remove();\n this.els.panel.remove();\n }\n\n // ── public api ──\n\n next(userInitiated = true): void {\n const target = this.index + 1;\n if (target >= this.items.length) {\n if (!this.options.loop) return;\n void this.goTo(0, 'next', userInitiated);\n return;\n }\n void this.goTo(target, 'next', userInitiated);\n }\n\n prev(userInitiated = true): void {\n const target = this.index - 1;\n if (target < 0) {\n if (!this.options.loop) return;\n void this.goTo(this.items.length - 1, 'prev', userInitiated);\n return;\n }\n void this.goTo(target, 'prev', userInitiated);\n }\n\n async goTo(target: number, direction: Dir | null = null, userInitiated = true): Promise<void> {\n if (this.destroyed || this.switching) return;\n const i = this.clamp(target);\n if (i === this.index) return;\n\n const dir = direction || (i > this.index ? 'next' : 'prev');\n this.switching = true;\n try {\n this.fillPane(dir, this.items[i]);\n await this.animate(dir);\n this.index = i;\n this.syncUi();\n await this.loadItem(i, { userInitiated });\n this.preloadNeighbours();\n } finally {\n this.switching = false;\n }\n }\n\n toggleList(force?: boolean): void {\n this.listOpen = typeof force === 'boolean' ? force : !this.listOpen;\n this.els.panel.setAttribute('aria-hidden', this.listOpen ? 'false' : 'true');\n this.els.listBtn.setAttribute('aria-expanded', this.listOpen ? 'true' : 'false');\n // translate-x/-y utility yerine inline transform: Shadow DOM'da tek eksenli Tailwind translate 'none' oluyor.\n this.els.panel.style.transform = this.listOpen ? 'translateX(0)' : 'translateX(100%)';\n }\n\n // ── dom ──\n\n private buildDom() {\n this.ctx.videoAreaEl.setAttribute('data-story', '1');\n\n const viewport = document.createElement('div');\n viewport.className = 'hp:absolute hp:inset-0 hp:overflow-hidden hp:touch-none';\n viewport.setAttribute('tabindex', '0');\n\n const track = document.createElement('div');\n track.className = 'hp:relative hp:w-full';\n track.style.height = '300%';\n track.style.transform = 'translate3d(0,-33.3333%,0)';\n track.style.transition = `transform ${this.options.transitionMs}ms ease`;\n\n const panePrev = this.createPane();\n const paneCurrent = document.createElement('div');\n paneCurrent.className = 'hp:absolute hp:inset-x-0 hp:h-1/3';\n paneCurrent.style.top = '33.3333%';\n const paneNext = this.createPane();\n paneNext.style.top = '66.6667%';\n\n // Gerçek player gövdesini orta pane'e taşı.\n this.ctx.playerBodyEls.forEach((el) => paneCurrent.appendChild(el));\n\n track.append(panePrev, paneCurrent, paneNext);\n viewport.appendChild(track);\n\n const overlay = document.createElement('div');\n overlay.className = 'hp:absolute hp:inset-0 hp:z-20 hp:pointer-events-none hp:flex hp:flex-col hp:justify-between hp:p-3';\n\n const progressBar = document.createElement('div');\n progressBar.className = 'hp:h-0.5 hp:bg-white/30 hp:rounded-full hp:overflow-hidden';\n const progressFill = document.createElement('div');\n progressFill.className = 'hp:h-full hp:bg-accent hp:w-0';\n progressBar.appendChild(progressFill);\n\n const meta = document.createElement('div');\n meta.className = 'hp:flex hp:flex-col hp:gap-0.5 hp:text-white hp:drop-shadow hp:mt-2 hp:pointer-events-auto';\n const counter = document.createElement('span');\n counter.setAttribute('part', 'story-counter');\n counter.className = 'hp:text-xs hp:opacity-80';\n const titleEl = document.createElement('strong');\n titleEl.className = 'hp:text-sm';\n const spotEl = document.createElement('span');\n spotEl.className = 'hp:text-xs hp:opacity-80';\n meta.append(counter, titleEl, spotEl);\n\n const dots = document.createElement('div');\n dots.className = 'hp:absolute hp:right-2 hp:top-1/2 hp-center-y hp:flex hp:flex-col hp:gap-1 hp:pointer-events-none';\n\n const navWrap = document.createElement('div');\n navWrap.className = 'hp:flex hp:flex-col hp:gap-2 hp:self-end hp:pointer-events-auto hp:mb-16';\n const upBtn = this.navBtn('chevron-left', this.ctx.i18n.storyPrev);\n upBtn.style.transform = 'rotate(90deg)';\n const downBtn = this.navBtn('chevron-left', this.ctx.i18n.storyNext);\n downBtn.style.transform = 'rotate(-90deg)';\n navWrap.append(upBtn, downBtn);\n\n const listBtn = document.createElement('button');\n listBtn.type = 'button';\n listBtn.setAttribute('aria-label', this.ctx.i18n.storyAllVideos);\n listBtn.setAttribute('aria-expanded', 'false');\n // Konum tailwind.css `.hp-story-list-btn` — dar (dikey) player'da üst bara (ayarlar/PiP) taşınan butonların altında.\n listBtn.className =\n 'hp-story-list-btn hp:absolute hp:flex hp:items-center hp:justify-center hp:w-9 hp:h-9 hp:rounded-full ' +\n 'hp:bg-black/40 hp:text-white hp:border-0 hp:cursor-pointer hp:pointer-events-auto';\n listBtn.setAttribute('part', 'story-list-button');\n listBtn.appendChild(createIcon('grid', 'hp:text-base'));\n\n overlay.append(progressBar, meta, dots, navWrap, listBtn);\n\n const panel = document.createElement('aside');\n panel.className =\n 'hp:absolute hp:inset-y-0 hp:right-0 hp:w-72 hp:max-w-[80%] hp:bg-surface-elev hp:z-30 hp:overflow-y-auto hp:p-3 ' +\n 'hp:transition-transform hp:duration-300';\n panel.style.transform = 'translateX(100%)';\n panel.setAttribute('aria-hidden', 'true');\n const grid = document.createElement('div');\n grid.className = 'hp:flex hp:flex-col hp:gap-2 hp:mt-8';\n panel.appendChild(grid);\n\n this.ctx.videoAreaEl.append(viewport, overlay, panel);\n\n this.renderList(grid);\n\n return {\n viewport, track, panePrev, paneCurrent, paneNext, overlay,\n counter, titleEl, spotEl, dots, progressBar: progressFill,\n upBtn, downBtn, listBtn, panel, grid,\n };\n }\n\n private createPane(): HTMLElement {\n const pane = document.createElement('div');\n pane.className = 'hp:absolute hp:inset-x-0 hp:h-1/3 hp:bg-cover hp:bg-center hp:bg-black';\n return pane;\n }\n\n private navBtn(iconName: string, label: string): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.setAttribute('aria-label', label);\n btn.className =\n 'hp:flex hp:items-center hp:justify-center hp:w-8 hp:h-8 hp:rounded-full hp:bg-black/40 hp:text-white hp:border-0 hp:cursor-pointer';\n btn.appendChild(createIcon(iconName, 'hp:text-sm'));\n return btn;\n }\n\n private fillPane(dir: Dir, item: PlayableItem | undefined): void {\n const pane = dir === 'next' ? this.els.paneNext : this.els.panePrev;\n const img = item?.image || '';\n pane.style.backgroundImage = img ? `url(\"${img}\")` : 'none';\n }\n\n private animate(dir: Dir): Promise<void> {\n const track = this.els.track;\n return new Promise((resolve) => {\n let done = false;\n const finish = () => {\n if (done) return;\n done = true;\n track.removeEventListener('transitionend', finish);\n clearTimeout(timer);\n track.style.transition = 'none';\n track.style.transform = 'translate3d(0,-33.3333%,0)';\n void track.offsetHeight;\n track.style.transition = `transform ${this.options.transitionMs}ms ease`;\n resolve();\n };\n track.addEventListener('transitionend', finish);\n const timer = setTimeout(finish, this.options.transitionMs + 120);\n track.style.transform = dir === 'next' ? 'translate3d(0,-66.6667%,0)' : 'translate3d(0,0,0)';\n });\n }\n\n // ── source / playback ──\n\n private async loadItem(i: number, opts: { userInitiated?: boolean; isStart?: boolean } = {}): Promise<void> {\n const item = this.items[i];\n if (!item) return;\n\n const mode = this.resolveMode(item);\n const payload = this.buildPayload(item, mode);\n if (!payload) return;\n\n this.ctx.videoEl.pause();\n if (item.image) this.ctx.setPoster(item.image);\n await this.ctx.loadSource(payload.src, payload.type);\n\n if (this.options.adsOnItemChange && this.lastAdsIndex !== i) {\n this.lastAdsIndex = i;\n this.ctx.requestFreshAd(item.adTagPreroll || this.rawOptions.adTagPreroll);\n }\n\n if (this.shouldAutoPlay(opts)) {\n try {\n await this.ctx.videoEl.play();\n } catch {\n /* autoplay engellendi */\n }\n }\n }\n\n private shouldAutoPlay({ userInitiated, isStart }: { userInitiated?: boolean; isStart?: boolean }): boolean {\n if (isStart) return !!this.ctx.videoEl.autoplay;\n if (userInitiated) return true;\n return this.options.autoplayNext && this.userHasStartedPlayback;\n }\n\n private resolveMode(item: PlayableItem): 'hls' | 'mp4' {\n const hasHls = this.hasMode(item, 'hls');\n const hasMp4 = this.hasMode(item, 'mp4');\n if (this.options.preferHls) return hasHls ? 'hls' : hasMp4 ? 'mp4' : 'hls';\n return hasMp4 ? 'mp4' : hasHls ? 'hls' : 'mp4';\n }\n\n private hasMode(item: PlayableItem, mode: 'hls' | 'mp4'): boolean {\n return Array.isArray(item[mode]) && item[mode]!.some((v) => v?.src);\n }\n\n private buildPayload(item: PlayableItem, mode: 'hls' | 'mp4'): { src: string; type?: string } | null {\n const list = (item[mode] || []).filter((v) => v?.src);\n if (!list.length) return null;\n const src = mode === 'mp4' ? list.find((v) => v.selected) || list[0] : list[0];\n return { src: src!.src, type: src!.type || (mode === 'hls' ? 'application/x-mpegURL' : 'video/mp4') };\n }\n\n // ── preload ──\n\n private preloadNeighbours(): void {\n const nav = navigator as Navigator & { connection?: { saveData?: boolean } };\n if (nav.connection?.saveData) return;\n\n [this.wrapIndex(this.index + 1), this.wrapIndex(this.index - 1)].forEach((i) => {\n if (i === this.index) return;\n const item = this.items[i];\n if (item?.image) {\n const img = new Image();\n img.decoding = 'async';\n img.src = item.image;\n }\n });\n }\n\n // ── ui sync ──\n\n private syncUi(): void {\n const item = this.items[this.index];\n const total = this.items.length;\n\n if (this.uiOpts.counter) this.els.counter.textContent = `${this.index + 1} / ${total}`;\n if (this.uiOpts.title) this.els.titleEl.textContent = item?.title || '';\n if (this.uiOpts.spot) this.els.spotEl.textContent = item?.spot || '';\n\n this.fillPane('prev', this.items[this.wrapIndex(this.index - 1)]);\n this.fillPane('next', this.items[this.wrapIndex(this.index + 1)]);\n\n const atStart = !this.options.loop && this.index === 0;\n const atEnd = !this.options.loop && this.index === total - 1;\n this.els.upBtn.disabled = atStart;\n this.els.downBtn.disabled = atEnd;\n\n if (this.uiOpts.dots) {\n if (this.els.dots.children.length !== total) {\n this.els.dots.innerHTML = '';\n for (let i = 0; i < total; i++) {\n const dot = document.createElement('i');\n dot.className = 'hp:block hp:w-1 hp:h-1 hp:rounded-full hp:bg-white/40';\n this.els.dots.appendChild(dot);\n }\n }\n Array.from(this.els.dots.children).forEach((el, i) => {\n (el as HTMLElement).className = `hp:block hp:w-1 hp:h-1 hp:rounded-full ${i === this.index ? 'hp:bg-white' : 'hp:bg-white/40'}`;\n });\n }\n\n this.setActiveThumb();\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:itemchange', { detail: { index: this.index, source: 'story' } }));\n }\n\n private renderList(grid: HTMLElement): void {\n grid.innerHTML = '';\n this.items.forEach((item, i) => {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'hp:flex hp:items-center hp:gap-2 hp:w-full hp:p-1.5 hp:rounded hp:text-left hp:text-on-surface hp:bg-transparent hp:border-0 hp:cursor-pointer hp:hover:bg-on-surface/5';\n btn.dataset.index = String(i);\n if (item.image) {\n const img = document.createElement('img');\n img.src = item.image;\n img.loading = 'lazy';\n img.className = 'hp:w-14 hp:aspect-[9/16] hp:object-cover hp:rounded hp:shrink-0';\n btn.appendChild(img);\n }\n const title = document.createElement('span');\n title.className = 'hp:text-xs hp:truncate';\n title.textContent = item.title || this.ctx.i18n.videoFallbackTitle(i);\n btn.appendChild(title);\n btn.addEventListener('click', () => {\n this.toggleList(false);\n void this.goTo(i);\n });\n grid.appendChild(btn);\n });\n }\n\n private setActiveThumb(): void {\n Array.from(this.els.grid.children).forEach((el, i) => {\n el.classList.toggle('hp:bg-accent/15', i === this.index);\n });\n }\n\n // ── events ──\n\n private bindEvents(): void {\n this.ctx.videoEl.addEventListener('ended', this.onEnded);\n this.ctx.videoEl.addEventListener('playing', this.onPlaying);\n this.ctx.videoEl.addEventListener('play', this.onFirstPlay);\n if (this.uiOpts.progress) this.ctx.videoEl.addEventListener('timeupdate', this.onTimeUpdate);\n\n this.els.upBtn.addEventListener('click', () => this.prev());\n this.els.downBtn.addEventListener('click', () => this.next());\n this.els.listBtn.addEventListener('click', () => this.toggleList());\n\n this.els.grid.parentElement?.addEventListener('keydown', (e) => {\n if ((e as KeyboardEvent).key === 'Escape') this.toggleList(false);\n });\n\n if (this.gestureOpts.wheel) this.els.viewport.addEventListener('wheel', this.onWheel, { passive: false });\n if (this.gestureOpts.swipe) {\n this.els.viewport.addEventListener('pointerdown', this.onPointerDown);\n window.addEventListener('pointermove', this.onPointerMove, { passive: false });\n window.addEventListener('pointerup', this.onPointerUp);\n }\n if (this.gestureOpts.keyboard) document.addEventListener('keydown', this.onKeyDown);\n }\n\n private readonly onEnded = (): void => {\n if (!this.options.autoplayNext) return;\n if (!this.options.loop && this.index === this.items.length - 1) return;\n this.next(false);\n };\n\n private readonly onPlaying = (): void => {};\n\n private readonly onFirstPlay = (): void => {\n this.userHasStartedPlayback = true;\n };\n\n private readonly onTimeUpdate = (): void => {\n const dur = this.ctx.videoEl.duration || 0;\n const cur = this.ctx.videoEl.currentTime || 0;\n this.els.progressBar.style.width = dur > 0 ? `${Math.min(100, (cur / dur) * 100)}%` : '0%';\n };\n\n private readonly onWheel = (e: WheelEvent): void => {\n if (this.switching) {\n e.preventDefault();\n return;\n }\n const dir: Dir = e.deltaY > 0 ? 'next' : 'prev';\n if (!this.canGo(dir)) return;\n e.preventDefault();\n\n const now = Date.now();\n if (now - this.lastNavAt < this.gestureOpts.wheelCooldownMs) return;\n this.wheelAccum += e.deltaY;\n if (Math.abs(this.wheelAccum) < this.gestureOpts.wheelThreshold) return;\n this.wheelAccum = 0;\n this.lastNavAt = now;\n dir === 'next' ? this.next() : this.prev();\n };\n\n private readonly onPointerDown = (e: PointerEvent): void => {\n if (this.switching || this.listOpen) return;\n if (e.pointerType === 'mouse' && e.button !== 0) return;\n this.drag = { startY: e.clientY, startX: e.clientX, dy: 0, active: false, id: e.pointerId };\n };\n\n private readonly onPointerMove = (e: PointerEvent): void => {\n const drag = this.drag;\n if (!drag || e.pointerId !== drag.id) return;\n const dy = e.clientY - drag.startY;\n const dx = e.clientX - drag.startX;\n\n if (!drag.active) {\n if (Math.abs(dy) < 10 || Math.abs(dy) < Math.abs(dx)) return;\n drag.active = true;\n this.els.track.style.transition = 'none';\n }\n e.preventDefault();\n\n const h = this.els.viewport.clientHeight || 1;\n const resisted = this.canGo(dy < 0 ? 'next' : 'prev') ? dy : dy * 0.25;\n drag.dy = resisted;\n\n const pct = -33.3333 + (resisted / h) * 33.3333;\n this.els.track.style.transform = `translate3d(0, ${pct}%, 0)`;\n };\n\n private readonly onPointerUp = (): void => {\n const drag = this.drag;\n this.drag = null;\n if (!drag?.active) return;\n\n const h = this.els.viewport.clientHeight || 1;\n const ratio = Math.abs(drag.dy) / h;\n const dir: Dir = drag.dy < 0 ? 'next' : 'prev';\n\n this.els.track.style.transition = `transform ${this.options.transitionMs}ms ease`;\n if (ratio >= this.gestureOpts.swipeThreshold && this.canGo(dir)) {\n this.els.track.style.transform = 'translate3d(0,-33.3333%,0)';\n dir === 'next' ? this.next() : this.prev();\n } else {\n this.els.track.style.transform = 'translate3d(0,-33.3333%,0)';\n }\n };\n\n private readonly onKeyDown = (e: KeyboardEvent): void => {\n if (this.destroyed) return;\n if (e.key === 'Escape' && this.listOpen) {\n this.toggleList(false);\n return;\n }\n const tag = document.activeElement?.tagName;\n if (tag === 'INPUT' || tag === 'TEXTAREA') return;\n if (!this.isInViewport()) return;\n\n if (e.key === 'ArrowDown' || e.key === 'PageDown' || e.key === 'j') {\n e.preventDefault();\n this.next();\n } else if (e.key === 'ArrowUp' || e.key === 'PageUp' || e.key === 'k') {\n e.preventDefault();\n this.prev();\n }\n };\n\n // ── helpers ──\n\n private canGo(dir: Dir): boolean {\n if (this.options.loop) return this.items.length > 1;\n return dir === 'next' ? this.index < this.items.length - 1 : this.index > 0;\n }\n\n private isInViewport(): boolean {\n const r = this.ctx.hostEl.getBoundingClientRect();\n return r.bottom > 0 && r.top < (window.innerHeight || 0);\n }\n\n private clamp(i: number): number {\n if (!Number.isFinite(i) || !this.items.length) return 0;\n return Math.max(0, Math.min(this.items.length - 1, Math.trunc(i)));\n }\n\n private wrapIndex(i: number): number {\n const n = this.items.length;\n if (!n) return 0;\n if (this.options.loop) return ((i % n) + n) % n;\n return this.clamp(i);\n }\n}\n","import { HopeStory, type StoryPlayerContext } from './HopeStory';\nimport type { StoryOptions } from '../../types';\n\nexport function installStory(ctx: StoryPlayerContext, options: StoryOptions): HopeStory {\n return new HopeStory(ctx, options);\n}\n\nexport { HopeStory };\nexport type { StoryPlayerContext };\n"],"names":["DEFAULTS","HopeStory","ctx","rawOptions","__publicField","dur","cur","e","dir","now","drag","dy","dx","h","resisted","pct","ratio","tag","_a","el","userInitiated","target","direction","force","viewport","track","panePrev","paneCurrent","paneNext","overlay","progressBar","progressFill","meta","counter","titleEl","spotEl","dots","navWrap","upBtn","downBtn","listBtn","createIcon","panel","grid","pane","iconName","label","btn","item","img","resolve","done","finish","timer","i","opts","mode","payload","isStart","hasHls","hasMp4","v","list","src","total","atStart","atEnd","dot","title","r","n","installStory","options"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-C5oGMHF_.js","sources":["../../src/plugins/tap-gestures/TapGestures.ts","../../src/plugins/tap-gestures/index.ts"],"sourcesContent":["import type { TapGesture, TapGestureType, TapRegion } from '../../types';\n\n/** Bir hareketin kaç dokunuşla tetiklendiği — `tripletap` eklemek için buraya `tripletap: 3` yeterli. */\nconst TAP_COUNTS: Record<TapGestureType, number> = {\n doubletap: 2,\n};\n/** Ardışık dokunuşların aynı harekete sayılacağı en uzun aralık (ms). */\nconst TAP_WINDOW_MS = 300;\n/** Sarmadan sonra aynı tarafa gelen her dokunuş sarmaya devam eder (YouTube gibi) — bu süre içinde. */\nconst CHAIN_WINDOW_MS = 700;\n/** Ekranın sol/sağ bölgesi — genişliğin üçte biri. */\nconst SIDE_FRACTION = 1 / 3;\n\nexport const DEFAULT_TAP_GESTURES: TapGesture[] = [\n { type: 'doubletap', region: 'left', pointer: 'touch', action: 'seekStep', value: -10 },\n { type: 'doubletap', region: 'right', pointer: 'touch', action: 'seekStep', value: 10 },\n];\n\nexport interface TapGesturesPlayerContext {\n /** Bölge hesabı için dokunulan alan (video alanı). */\n areaEl: HTMLElement;\n seekBy(delta: number): void;\n togglePlay(): void;\n toggleFullscreen(): void;\n toggleMute(): void;\n}\n\nexport type TapPointerType = 'touch' | 'mouse' | 'pen';\n\n/**\n * Ekranın sol/orta/sağ bölgesine çoklu dokunuş hareketleri (options.tapGestures). Bir bölgede tanımlı hareket varsa\n * tek dokunuşun normal davranışı (oynat/duraklat) hareket penceresi kadar bekletilir; ikinci dokunuş gelmezse uygulanır.\n */\nexport class TapGestures {\n private gestures: TapGesture[];\n private count = 0;\n private lastRegion: TapRegion | null = null;\n private lastPointer: TapPointerType | null = null;\n private pendingTimer: ReturnType<typeof setTimeout> | null = null;\n private chain: { gesture: TapGesture; region: TapRegion; pointer: TapPointerType; until: number } | null = null;\n\n constructor(\n private readonly ctx: TapGesturesPlayerContext,\n gestures: TapGesture[]\n ) {\n this.gestures = gestures;\n }\n\n setGestures(gestures: TapGesture[]): void {\n this.gestures = gestures;\n this.reset();\n }\n\n /**\n * Video alanına bir dokunuş. `true` = dokunuşu bu modül üstlendi (tek dokunuş davranışı gerekirse\n * `singleTap` ile sonradan çağrılır); `false` = bu bölge/işaretçi için hareket yok, normal davranış hemen uygulansın.\n */\n handleTap(clientX: number, pointer: TapPointerType, singleTap: () => void): boolean {\n const region = this.regionAt(clientX);\n const now = Date.now();\n\n // Sarma zinciri: çift dokunuştan sonra aynı tarafa her dokunuş bir adım daha sarar.\n const chain = this.chain;\n if (chain && now < chain.until && chain.pointer === pointer && (chain.gesture.region === 'full' || chain.region === region)) {\n this.clearPending();\n this.run(chain.gesture, region);\n chain.until = now + CHAIN_WINDOW_MS;\n return true;\n }\n this.chain = null;\n\n const candidates = this.gestures.filter((g) => matchesPointer(g, pointer) && (g.region === region || g.region === 'full'));\n if (!candidates.length) {\n this.reset();\n return false;\n }\n\n const continues = this.pendingTimer !== null && this.lastRegion === region && this.lastPointer === pointer;\n this.count = continues ? this.count + 1 : 1;\n this.lastRegion = region;\n this.lastPointer = pointer;\n this.clearPending();\n\n const maxCount = Math.max(...candidates.map((g) => TAP_COUNTS[g.type]));\n const match = candidates.find((g) => TAP_COUNTS[g.type] === this.count);\n // Bu bölgede daha uzun bir hareket (ör. üçlü dokunuş) yoksa beklemeden tetikle.\n if (match && this.count >= maxCount) {\n this.fire(match, region, pointer);\n return true;\n }\n const count = this.count;\n this.pendingTimer = setTimeout(() => {\n this.pendingTimer = null;\n const late = candidates.find((g) => TAP_COUNTS[g.type] === count);\n this.count = 0;\n if (late) this.fire(late, region, pointer);\n else if (count === 1) singleTap();\n }, TAP_WINDOW_MS);\n return true;\n }\n\n destroy(): void {\n this.reset();\n }\n\n private fire(gesture: TapGesture, region: TapRegion, pointer: TapPointerType): void {\n this.count = 0;\n this.run(gesture, region);\n if (gesture.action === 'seekStep') this.chain = { gesture, region, pointer, until: Date.now() + CHAIN_WINDOW_MS };\n }\n\n private run(gesture: TapGesture, region: TapRegion): void {\n switch (gesture.action) {\n case 'seekStep':\n this.ctx.seekBy(gesture.value ?? (region === 'left' ? -10 : 10));\n break;\n case 'togglePlay':\n this.ctx.togglePlay();\n break;\n case 'toggleFullscreen':\n this.ctx.toggleFullscreen();\n break;\n case 'toggleMute':\n this.ctx.toggleMute();\n break;\n }\n }\n\n private regionAt(clientX: number): TapRegion {\n const r = this.ctx.areaEl.getBoundingClientRect();\n const x = (clientX - r.left) / (r.width || 1);\n if (x < SIDE_FRACTION) return 'left';\n if (x > 1 - SIDE_FRACTION) return 'right';\n return 'center';\n }\n\n private clearPending(): void {\n if (this.pendingTimer) clearTimeout(this.pendingTimer);\n this.pendingTimer = null;\n }\n\n private reset(): void {\n this.clearPending();\n this.count = 0;\n this.chain = null;\n this.lastRegion = null;\n this.lastPointer = null;\n }\n}\n\nfunction matchesPointer(gesture: TapGesture, pointer: TapPointerType): boolean {\n const want = gesture.pointer ?? 'touch';\n return want === 'any' || want === pointer;\n}\n","import { TapGestures, DEFAULT_TAP_GESTURES, type TapGesturesPlayerContext, type TapPointerType } from './TapGestures';\nimport type { TapGesture } from '../../types';\n\nexport function installTapGestures(ctx: TapGesturesPlayerContext, gestures: TapGesture[]): TapGestures {\n return new TapGestures(ctx, gestures);\n}\n\nexport { TapGestures, DEFAULT_TAP_GESTURES };\nexport type { TapGesturesPlayerContext, TapPointerType };\n"],"names":["TAP_COUNTS","TAP_WINDOW_MS","CHAIN_WINDOW_MS","SIDE_FRACTION","DEFAULT_TAP_GESTURES","TapGestures","ctx","gestures","__publicField","clientX","pointer","singleTap","region","now","chain","candidates","g","matchesPointer","continues","maxCount","match","count","late","gesture","r","x","want","installTapGestures"],"mappings":";;;AAGA,MAAMA,IAA6C;AAAA,EAC/C,WAAW;AACf,GAEMC,IAAgB,KAEhBC,IAAkB,KAElBC,IAAgB,IAAI,GAEbC,IAAqC;AAAA,EAC9C,EAAE,MAAM,aAAa,QAAQ,QAAQ,SAAS,SAAS,QAAQ,YAAY,OAAO,IAAA;AAAA,EAClF,EAAE,MAAM,aAAa,QAAQ,SAAS,SAAS,SAAS,QAAQ,YAAY,OAAO,GAAA;AACvF;AAiBO,MAAMC,EAAY;AAAA,EAQrB,YACqBC,GACjBC,GACF;AAVM,IAAAC,EAAA;AACA,IAAAA,EAAA,eAAQ;AACR,IAAAA,EAAA,oBAA+B;AAC/B,IAAAA,EAAA,qBAAqC;AACrC,IAAAA,EAAA,sBAAqD;AACrD,IAAAA,EAAA,eAAmG;AAGtF,SAAA,MAAAF,GAGjB,KAAK,WAAWC;AAAA,EACpB;AAAA,EAEA,YAAYA,GAA8B;AACtC,SAAK,WAAWA,GAChB,KAAK,MAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAUE,GAAiBC,GAAyBC,GAAgC;AAChF,UAAMC,IAAS,KAAK,SAASH,CAAO,GAC9BI,IAAM,KAAK,IAAA,GAGXC,IAAQ,KAAK;AACnB,QAAIA,KAASD,IAAMC,EAAM,SAASA,EAAM,YAAYJ,MAAYI,EAAM,QAAQ,WAAW,UAAUA,EAAM,WAAWF;AAChH,kBAAK,aAAA,GACL,KAAK,IAAIE,EAAM,SAASF,CAAM,GAC9BE,EAAM,QAAQD,IAAMX,GACb;AAEX,SAAK,QAAQ;AAEb,UAAMa,IAAa,KAAK,SAAS,OAAO,CAACC,MAAMC,EAAeD,GAAGN,CAAO,MAAMM,EAAE,WAAWJ,KAAUI,EAAE,WAAW,OAAO;AACzH,QAAI,CAACD,EAAW;AACZ,kBAAK,MAAA,GACE;AAGX,UAAMG,IAAY,KAAK,iBAAiB,QAAQ,KAAK,eAAeN,KAAU,KAAK,gBAAgBF;AACnG,SAAK,QAAQQ,IAAY,KAAK,QAAQ,IAAI,GAC1C,KAAK,aAAaN,GAClB,KAAK,cAAcF,GACnB,KAAK,aAAA;AAEL,UAAMS,IAAW,KAAK,IAAI,GAAGJ,EAAW,IAAI,CAACC,MAAMhB,EAAWgB,EAAE,IAAI,CAAC,CAAC,GAChEI,IAAQL,EAAW,KAAK,CAACC,MAAMhB,EAAWgB,EAAE,IAAI,MAAM,KAAK,KAAK;AAEtE,QAAII,KAAS,KAAK,SAASD;AACvB,kBAAK,KAAKC,GAAOR,GAAQF,CAAO,GACzB;AAEX,UAAMW,IAAQ,KAAK;AACnB,gBAAK,eAAe,WAAW,MAAM;AACjC,WAAK,eAAe;AACpB,YAAMC,IAAOP,EAAW,KAAK,CAACC,MAAMhB,EAAWgB,EAAE,IAAI,MAAMK,CAAK;AAChE,WAAK,QAAQ,GACTC,IAAM,KAAK,KAAKA,GAAMV,GAAQF,CAAO,IAChCW,MAAU,KAAGV,EAAA;AAAA,IAC1B,GAAGV,CAAa,GACT;AAAA,EACX;AAAA,EAEA,UAAgB;AACZ,SAAK,MAAA;AAAA,EACT;AAAA,EAEQ,KAAKsB,GAAqBX,GAAmBF,GAA+B;AAChF,SAAK,QAAQ,GACb,KAAK,IAAIa,GAASX,CAAM,GACpBW,EAAQ,WAAW,eAAY,KAAK,QAAQ,EAAE,SAAAA,GAAS,QAAAX,GAAQ,SAAAF,GAAS,OAAO,KAAK,IAAA,IAAQR,EAAA;AAAA,EACpG;AAAA,EAEQ,IAAIqB,GAAqBX,GAAyB;AACtD,YAAQW,EAAQ,QAAA;AAAA,MACZ,KAAK;AACD,aAAK,IAAI,OAAOA,EAAQ,UAAUX,MAAW,SAAS,MAAM,GAAG;AAC/D;AAAA,MACJ,KAAK;AACD,aAAK,IAAI,WAAA;AACT;AAAA,MACJ,KAAK;AACD,aAAK,IAAI,iBAAA;AACT;AAAA,MACJ,KAAK;AACD,aAAK,IAAI,WAAA;AACT;AAAA,IAAA;AAAA,EAEZ;AAAA,EAEQ,SAASH,GAA4B;AACzC,UAAMe,IAAI,KAAK,IAAI,OAAO,sBAAA,GACpBC,KAAKhB,IAAUe,EAAE,SAASA,EAAE,SAAS;AAC3C,WAAIC,IAAItB,IAAsB,SAC1BsB,IAAI,IAAItB,IAAsB,UAC3B;AAAA,EACX;AAAA,EAEQ,eAAqB;AACzB,IAAI,KAAK,gBAAc,aAAa,KAAK,YAAY,GACrD,KAAK,eAAe;AAAA,EACxB;AAAA,EAEQ,QAAc;AAClB,SAAK,aAAA,GACL,KAAK,QAAQ,GACb,KAAK,QAAQ,MACb,KAAK,aAAa,MAClB,KAAK,cAAc;AAAA,EACvB;AACJ;AAEA,SAASc,EAAeM,GAAqBb,GAAkC;AAC3E,QAAMgB,IAAOH,EAAQ,WAAW;AAChC,SAAOG,MAAS,SAASA,MAAShB;AACtC;ACtJO,SAASiB,EAAmBrB,GAA+BC,GAAqC;AACnG,SAAO,IAAIF,EAAYC,GAAKC,CAAQ;AACxC;"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-CBX7bn-G.js","sources":["../../src/plugins/segments/Segments.ts","../../src/plugins/segments/index.ts"],"sourcesContent":["import type { SegmentItem } from '../../types';\nimport type { SeekBarChapterRange } from '../../controls/SeekBar';\nimport { formatTime } from '../../utils/format-time';\n\nexport interface SegmentsPlayerContext {\n videoEl: HTMLVideoElement;\n /** Chapter modunu destekleyen seek bar — parçalara bölme/zaman eşlemesi onda. */\n seekBar: {\n readonly el: HTMLElement;\n setChapters(ranges: SeekBarChapterRange[]): HTMLElement[];\n suppressHoverTime(key: string, suppressed: boolean): void;\n clearChapters(): void;\n ratioAtClientX(clientX: number): number;\n };\n}\n\ninterface Chapter {\n start: number;\n end: number;\n text?: string;\n color?: string;\n}\n\n/**\n * YouTube tarzı bölümler: seek bar parçalara bölünür (SeekBar.setChapters), hover'da bölüm adı + zaman.\n * Zaman çizgisi her zaman tam kaplanır (boşluklar adsız bölüm, son bölüm sona uzar).\n */\nexport class Segments {\n private chapters: Chapter[] = [];\n private chapterEls: HTMLElement[] = [];\n private hoverIndex = -1;\n private readonly tooltipEl: HTMLDivElement;\n private readonly titleEl: HTMLDivElement;\n private readonly timeEl: HTMLDivElement;\n\n constructor(\n private readonly ctx: SegmentsPlayerContext,\n private readonly segments: SegmentItem[]\n ) {\n this.tooltipEl = document.createElement('div');\n this.tooltipEl.className = 'hp-chapter-tooltip';\n this.tooltipEl.setAttribute('part', 'segment-tooltip');\n this.titleEl = document.createElement('div');\n this.titleEl.className = 'hp-chapter-tooltip-title';\n this.timeEl = document.createElement('div');\n this.timeEl.className = 'hp-chapter-tooltip-time';\n this.tooltipEl.append(this.titleEl, this.timeEl);\n ctx.seekBar.el.appendChild(this.tooltipEl);\n // Popup zamanı zaten gösteriyor — seek bar'ın varsayılan hover zamanı ikinci kez yazmasın.\n ctx.seekBar.suppressHoverTime('segments', true);\n\n ctx.seekBar.el.addEventListener('pointermove', this.onPointerMove);\n ctx.seekBar.el.addEventListener('pointerleave', this.onPointerLeave);\n ctx.videoEl.addEventListener('loadedmetadata', this.onLoadedMetadata);\n if (ctx.videoEl.readyState >= 1) this.onLoadedMetadata();\n }\n\n destroy(): void {\n this.ctx.videoEl.removeEventListener('loadedmetadata', this.onLoadedMetadata);\n this.ctx.seekBar.el.removeEventListener('pointermove', this.onPointerMove);\n this.ctx.seekBar.el.removeEventListener('pointerleave', this.onPointerLeave);\n this.ctx.seekBar.clearChapters();\n this.ctx.seekBar.suppressHoverTime('segments', false);\n this.tooltipEl.remove();\n this.chapterEls = [];\n this.chapters = [];\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.chapters = buildChapters(this.segments, duration);\n this.chapterEls = this.ctx.seekBar.setChapters(\n this.chapters.map((c) => ({ start: c.start / duration, end: c.end / duration, color: c.color }))\n );\n };\n\n private readonly onPointerMove = (e: PointerEvent): void => {\n const duration = this.ctx.videoEl.duration;\n if (!this.chapters.length || !Number.isFinite(duration) || duration <= 0) return;\n\n const time = this.ctx.seekBar.ratioAtClientX(e.clientX) * duration;\n let index = this.chapters.findIndex((c) => time < c.end);\n if (index === -1) index = this.chapters.length - 1;\n this.setHover(index);\n\n const chapter = this.chapters[index]!;\n this.titleEl.textContent = chapter.text ?? '';\n this.titleEl.style.display = chapter.text ? '' : 'none';\n this.timeEl.textContent = formatTime(time);\n\n // sprite-thumbnails önizlemesi de seek bar'ın hemen üstünde açılıyor —\n // görünürse popup onun ÜSTÜNE çıkıyor (üst üste binmesin).\n const sprite = this.ctx.seekBar.el.querySelector<HTMLElement>('[part=\"sprite-tooltip\"]');\n const spriteH = sprite && sprite.hasAttribute('data-visible') && sprite.offsetHeight > 0 ? sprite.offsetHeight + 8 : 0;\n this.tooltipEl.style.bottom = spriteH ? `calc(100% + 6px + ${spriteH}px)` : '';\n // Sprite önizlemesi zamanı zaten kendi altında gösteriyor — aynı zaman iki kez yazılmasın.\n this.timeEl.style.display = spriteH ? 'none' : '';\n\n // Popup imleci ortalar ama seek bar kenarlarından taşmaz.\n const barRect = this.ctx.seekBar.el.getBoundingClientRect();\n this.tooltipEl.setAttribute('data-visible', '');\n const tipWidth = this.tooltipEl.offsetWidth;\n const x = Math.min(Math.max(e.clientX - barRect.left - tipWidth / 2, 0), Math.max(barRect.width - tipWidth, 0));\n this.tooltipEl.style.transform = `translateX(${x}px)`;\n };\n\n private readonly onPointerLeave = (): void => {\n this.setHover(-1);\n this.tooltipEl.removeAttribute('data-visible');\n };\n\n private setHover(index: number): void {\n if (index === this.hoverIndex) return;\n this.chapterEls[this.hoverIndex]?.removeAttribute('data-hover');\n this.hoverIndex = index;\n this.chapterEls[index]?.setAttribute('data-hover', '');\n }\n}\n\n/** Segmentleri sıralar, boşlukları adsız bölümle doldurur, son bölümü video sonuna uzatır — sonuç 0→duration'ı kesintisiz kaplar. */\nfunction buildChapters(segments: SegmentItem[], duration: number): Chapter[] {\n const sorted = segments\n .filter((s) => Number.isFinite(s.start) && s.start < duration)\n .slice()\n .sort((a, b) => a.start - b.start);\n\n const chapters: Chapter[] = [];\n let cursor = 0;\n for (const seg of sorted) {\n const start = Math.max(seg.start, cursor);\n const end = Math.min(Number.isFinite(seg.end) ? seg.end : duration, duration);\n if (end <= start) continue;\n if (start > cursor) chapters.push({ start: cursor, end: start });\n chapters.push({ start, end, text: seg.text, color: seg.color });\n cursor = end;\n }\n if (!chapters.length) return [];\n if (cursor < duration) chapters[chapters.length - 1]!.end = duration;\n return chapters;\n}\n","import { Segments, type SegmentsPlayerContext } from './Segments';\nimport type { SegmentItem } from '../../types';\n\nexport function installSegments(ctx: SegmentsPlayerContext, items: SegmentItem[]): Segments {\n return new Segments(ctx, items);\n}\n\nexport { Segments };\nexport type { SegmentsPlayerContext };\n"],"names":["Segments","ctx","segments","__publicField","duration","buildChapters","c","e","time","index","chapter","formatTime","sprite","spriteH","barRect","tipWidth","x","_a","_b","sorted","a","b","chapters","cursor","seg","start","end","installSegments","items"],"mappings":"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"}