@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.
- package/README.md +24 -14
- package/dist/HopePlayerElement.d.ts +3 -0
- package/dist/HopePlayerElement.d.ts.map +1 -1
- package/dist/chunks/{index-CWLyz1fp.js → adTriggers-DXmtF4t2.js} +113 -118
- package/dist/chunks/adTriggers-DXmtF4t2.js.map +1 -0
- package/dist/chunks/{index-DITXYcHx.js → ads-MCG5a6eK.js} +130 -125
- package/dist/chunks/ads-MCG5a6eK.js.map +1 -0
- package/dist/chunks/{index-BeJNpAyx.js → audio-LkYgd5Wq.js} +7 -7
- package/dist/chunks/audio-LkYgd5Wq.js.map +1 -0
- package/dist/chunks/{ScratchSound-0XKHUcJK.js → audioScratchSound-7XkwCCDm.js} +1 -1
- package/dist/chunks/audioScratchSound-7XkwCCDm.js.map +1 -0
- package/dist/chunks/{index-Miba3PD_.js → cast-bMrkGGuD.js} +70 -66
- package/dist/chunks/cast-bMrkGGuD.js.map +1 -0
- package/dist/chunks/{index-rENB3n9O.js → countdownScreen-CI-u6jjA.js} +1 -1
- package/dist/chunks/countdownScreen-CI-u6jjA.js.map +1 -0
- package/dist/chunks/{index-Q8FMOHj0.js → dai-B9Tth1Iv.js} +1 -1
- package/dist/chunks/dai-B9Tth1Iv.js.map +1 -0
- package/dist/chunks/{index-DCXX1ZJG.js → debugPanel-Bnc_7GOn.js} +1 -1
- package/dist/chunks/debugPanel-Bnc_7GOn.js.map +1 -0
- package/dist/chunks/{index-DXWK4EFa.js → dubbing-kNMPpyHl.js} +1 -1
- package/dist/chunks/dubbing-kNMPpyHl.js.map +1 -0
- package/dist/chunks/{index-BBmuCtKu.js → geoChecker-BRtvHwI-.js} +1 -1
- package/dist/chunks/geoChecker-BRtvHwI-.js.map +1 -0
- package/dist/chunks/{index-Ca8hocby.js → gesture-BzPCgi87.js} +1 -1
- package/dist/chunks/gesture-BzPCgi87.js.map +1 -0
- package/dist/chunks/{loadGpt-CmiAy366.js → gpt-CGXHTG_H.js} +1 -1
- package/dist/chunks/gpt-CGXHTG_H.js.map +1 -0
- package/dist/chunks/{index-3QALpwsf.js → inViewAutoplay-CRJe7GA4.js} +1 -1
- package/dist/chunks/inViewAutoplay-CRJe7GA4.js.map +1 -0
- package/dist/chunks/{index-7IBf8Y-R.js → liveWallClock-ChUTtzLD.js} +1 -1
- package/dist/chunks/liveWallClock-ChUTtzLD.js.map +1 -0
- package/dist/chunks/{index-f0vSgRIK.js → loopSection-CvF4l5uf.js} +1 -1
- package/dist/chunks/loopSection-CvF4l5uf.js.map +1 -0
- package/dist/chunks/{index-e00_M05B.js → markers-BhMJLPqj.js} +2 -2
- package/dist/chunks/markers-BhMJLPqj.js.map +1 -0
- package/dist/chunks/{index-CDPrkLq0.js → pauseAd-BQQe21X4.js} +2 -2
- package/dist/chunks/pauseAd-BQQe21X4.js.map +1 -0
- package/dist/chunks/{index-DEv3YqLg.js → player-DW5iWvPs.js} +939 -880
- package/dist/chunks/player-DW5iWvPs.js.map +1 -0
- package/dist/chunks/{index-D3Z7ZDLJ.js → playlist-DYGbJ5wz.js} +24 -24
- package/dist/chunks/playlist-DYGbJ5wz.js.map +1 -0
- package/dist/chunks/{VideoPrebid-CpckFzSq.js → prebid-CRY3i2OT.js} +1 -1
- package/dist/chunks/prebid-CRY3i2OT.js.map +1 -0
- package/dist/chunks/{index-DT8-oMPm.js → qrResume-DXwD3oSA.js} +29 -30
- package/dist/chunks/qrResume-DXwD3oSA.js.map +1 -0
- package/dist/chunks/redirectScreen-CSjrS8Kg.js +208 -0
- package/dist/chunks/redirectScreen-CSjrS8Kg.js.map +1 -0
- package/dist/chunks/{index-BbRYOSvk.js → rewardedUnlock-DZ_qPcDG.js} +22 -19
- package/dist/chunks/rewardedUnlock-DZ_qPcDG.js.map +1 -0
- package/dist/chunks/seekWhenReady-Clzne3-S.js +32 -0
- package/dist/chunks/seekWhenReady-Clzne3-S.js.map +1 -0
- package/dist/chunks/{index-CBX7bn-G.js → segments-LsZPlbYi.js} +2 -2
- package/dist/chunks/segments-LsZPlbYi.js.map +1 -0
- package/dist/chunks/{index-Ch3ep-eJ.js → sponsorship-BT21uwN5.js} +36 -41
- package/dist/chunks/sponsorship-BT21uwN5.js.map +1 -0
- package/dist/chunks/{index-BXSND_xN.js → spriteThumbnails-BQkEBRu-.js} +2 -2
- package/dist/chunks/spriteThumbnails-BQkEBRu-.js.map +1 -0
- package/dist/chunks/{index-DGtpFgHV.js → statsPanel-DSClIwA3.js} +1 -1
- package/dist/chunks/statsPanel-DSClIwA3.js.map +1 -0
- package/dist/chunks/{index-CDDke5rz.js → sticky-D_eLCNFk.js} +1 -1
- package/dist/chunks/sticky-D_eLCNFk.js.map +1 -0
- package/dist/chunks/{index-C3BQGcT3.js → story-H6f7gSoX.js} +27 -15
- package/dist/chunks/story-H6f7gSoX.js.map +1 -0
- package/dist/chunks/{index-C5oGMHF_.js → tapGestures-DrC42DiI.js} +1 -1
- package/dist/chunks/tapGestures-DrC42DiI.js.map +1 -0
- package/dist/chunks/trackingPixel-D2wxdCEz.js +20 -0
- package/dist/chunks/trackingPixel-D2wxdCEz.js.map +1 -0
- package/dist/controls/SeekBar.d.ts.map +1 -1
- package/dist/hls/SourceManager.d.ts.map +1 -1
- package/dist/hope-player.js +1 -1
- package/dist/i18n/locales/en.d.ts.map +1 -1
- package/dist/i18n/locales/tr.d.ts.map +1 -1
- package/dist/i18n/types.d.ts +3 -0
- package/dist/i18n/types.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/keyboard/KeyboardController.d.ts.map +1 -1
- package/dist/plugins/ad-triggers/AdTriggers.d.ts.map +1 -1
- package/dist/plugins/ads/AdsController.d.ts.map +1 -1
- package/dist/plugins/ads/generateVastUrl.d.ts +10 -0
- package/dist/plugins/ads/generateVastUrl.d.ts.map +1 -1
- package/dist/plugins/cast/CastController.d.ts.map +1 -1
- package/dist/plugins/playlist/PlaylistRunner.d.ts.map +1 -1
- package/dist/plugins/qr-resume/QrResume.d.ts.map +1 -1
- package/dist/plugins/redirect-screen/RedirectScreen.d.ts +26 -3
- package/dist/plugins/redirect-screen/RedirectScreen.d.ts.map +1 -1
- package/dist/plugins/rewarded/RewardedUnlock.d.ts +0 -5
- package/dist/plugins/rewarded/RewardedUnlock.d.ts.map +1 -1
- package/dist/plugins/shared/seekWhenReady.d.ts +22 -0
- package/dist/plugins/shared/seekWhenReady.d.ts.map +1 -0
- package/dist/plugins/shared/trackingPixel.d.ts +8 -0
- package/dist/plugins/shared/trackingPixel.d.ts.map +1 -0
- package/dist/plugins/sponsorship/SponsorshipLayer.d.ts.map +1 -1
- package/dist/plugins/story/HopeStory.d.ts +2 -0
- package/dist/plugins/story/HopeStory.d.ts.map +1 -1
- package/dist/screens/ErrorScreen.d.ts +7 -0
- package/dist/screens/ErrorScreen.d.ts.map +1 -1
- package/dist/types/index.d.ts +49 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/media-error.d.ts +10 -0
- package/dist/utils/media-error.d.ts.map +1 -0
- package/dist/utils/seek-by.d.ts +8 -0
- package/dist/utils/seek-by.d.ts.map +1 -1
- package/package.json +4 -1
- package/dist/chunks/ScratchSound-0XKHUcJK.js.map +0 -1
- package/dist/chunks/VideoPrebid-CpckFzSq.js.map +0 -1
- package/dist/chunks/index-3QALpwsf.js.map +0 -1
- package/dist/chunks/index-7IBf8Y-R.js.map +0 -1
- package/dist/chunks/index-BBmuCtKu.js.map +0 -1
- package/dist/chunks/index-BXSND_xN.js.map +0 -1
- package/dist/chunks/index-BbRYOSvk.js.map +0 -1
- package/dist/chunks/index-BeJNpAyx.js.map +0 -1
- package/dist/chunks/index-C3BQGcT3.js.map +0 -1
- package/dist/chunks/index-C5oGMHF_.js.map +0 -1
- package/dist/chunks/index-CBX7bn-G.js.map +0 -1
- package/dist/chunks/index-CDDke5rz.js.map +0 -1
- package/dist/chunks/index-CDPrkLq0.js.map +0 -1
- package/dist/chunks/index-CWLyz1fp.js.map +0 -1
- package/dist/chunks/index-Ca8hocby.js.map +0 -1
- package/dist/chunks/index-Ch3ep-eJ.js.map +0 -1
- package/dist/chunks/index-D3Z7ZDLJ.js.map +0 -1
- package/dist/chunks/index-D6r-BGAV.js +0 -77
- package/dist/chunks/index-D6r-BGAV.js.map +0 -1
- package/dist/chunks/index-DCXX1ZJG.js.map +0 -1
- package/dist/chunks/index-DEv3YqLg.js.map +0 -1
- package/dist/chunks/index-DGtpFgHV.js.map +0 -1
- package/dist/chunks/index-DITXYcHx.js.map +0 -1
- package/dist/chunks/index-DT8-oMPm.js.map +0 -1
- package/dist/chunks/index-DXWK4EFa.js.map +0 -1
- package/dist/chunks/index-Miba3PD_.js.map +0 -1
- package/dist/chunks/index-Q8FMOHj0.js.map +0 -1
- package/dist/chunks/index-e00_M05B.js.map +0 -1
- package/dist/chunks/index-f0vSgRIK.js.map +0 -1
- package/dist/chunks/index-rENB3n9O.js.map +0 -1
- package/dist/chunks/loadGpt-CmiAy366.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-CDDke5rz.js","sources":["../../src/plugins/sticky/StickyManager.ts","../../src/plugins/sticky/index.ts"],"sourcesContent":["import type { StickyCorner, StickyOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\n\nexport interface StickyPlayerContext {\n key: string;\n videoEl: HTMLVideoElement;\n hostEl: HTMLElement;\n /** Sticky olarak köşeye taşınacak element — genelde hostEl'in kendisi (bkz. options.wrapperSelector). */\n wrapperEl: HTMLElement;\n /**\n * Kapat butonu wrapperEl'e değil shadow root içine eklenir — wrapperEl varsayılan olarak host;\n * slot olmadığı için light DOM child'ı render edilmez.\n */\n closeButtonMountEl: HTMLElement;\n isAdActive(): boolean;\n i18n: HopeLocaleStrings;\n}\n\n/** `register()`'ın döndürdüğü unregister fonksiyonu — dil sonradan değişince close butonunun statik etiketini tazelemek için `refreshLabels` da taşıyor (bkz. loop-section'daki aynı \"fonksiyona metod ekleme\" deseni). */\nexport type StickyUnregister = (() => void) & { refreshLabels?: () => void };\n\ninterface StickyItemState {\n inView: boolean;\n playing: boolean;\n sticky: boolean;\n hasEverBeenInView: boolean;\n hasEverBeenInViewWhilePlaying: boolean;\n watchMsInView: number;\n lastTickAt: number;\n minPlaySatisfied: boolean;\n userPaused: boolean;\n userPausedAt: number;\n adStartedOnce: boolean;\n contentStartedOnce: boolean;\n blockResumeUntil: number;\n programmaticPauseUntil: number;\n placeholderEl: HTMLElement | null;\n closeBtnEl: HTMLElement | null;\n}\n\ninterface StickyItem {\n ctx: StickyPlayerContext;\n options: Required<Omit<StickyOptions, 'wrapperSelector'>>;\n state: StickyItemState;\n /** wrapperEl'in doğal konumundaki görünmez işaretçi — IntersectionObserver bunu izler (sticky olunca wrapper yer değiştirir). */\n sentinelEl: HTMLElement;\n}\n\nconst GESTURE_WINDOW_MS = 1200;\nconst USER_PAUSED_MAX_MS = 30000;\nconst PROGRAMMATIC_PAUSE_MS = 800;\nconst BLOCK_RESUME_MS = 1200;\nconst STORAGE_KEY = 'hope_sticky_dismissed_until';\nconst STORAGE_KEY_FOREVER = 'hope_sticky_dismissed_forever';\n\n/** Sayfadaki tüm sticky player'ları koordine eden modül seviyesi singleton (aynı anda tek sticky). */\nclass StickyManagerImpl {\n private readonly items = new Map<string, StickyItem>();\n private activeKey: string | null = null;\n private observer: IntersectionObserver | null = null;\n\n private lastUserGestureAt = 0;\n private lastGestureType: 'play' | 'pause' | 'other' | null = null;\n private gestureListenersAttached = false;\n\n private dismissedUntil = 0;\n private dismissedForever = false;\n private dismissLoaded = false;\n\n register(ctx: StickyPlayerContext, options: StickyOptions): StickyUnregister {\n this.ensureGestureListeners();\n this.loadDismissState();\n\n const resolved: StickyItem['options'] = {\n enabled: options.enabled ?? true,\n corner: options.corner ?? 'br',\n requirePlaying: options.requirePlaying ?? true,\n minPlayMs: options.minPlayMs ?? 800,\n onlyOneSticky: options.onlyOneSticky ?? true,\n closeActiveStickyOnAnotherPlay: options.closeActiveStickyOnAnotherPlay ?? true,\n userGestureWindowMs: options.userGestureWindowMs ?? GESTURE_WINDOW_MS,\n adCanTriggerSticky: options.adCanTriggerSticky ?? 'preroll-only',\n dismissMode: options.dismissMode ?? 'cooldown',\n cooldownMinutes: options.cooldownMinutes ?? 5,\n storage: options.storage ?? 'local',\n closeButton: options.closeButton ?? true,\n };\n\n if (!resolved.enabled) return () => {};\n\n const sentinel = document.createElement('div');\n sentinel.setAttribute('aria-hidden', 'true');\n sentinel.style.cssText = 'position:relative;width:1px;height:1px;pointer-events:none;opacity:0;';\n ctx.wrapperEl.parentNode?.insertBefore(sentinel, ctx.wrapperEl);\n\n const item: StickyItem = {\n ctx,\n options: resolved,\n sentinelEl: sentinel,\n state: {\n inView: true,\n playing: false,\n sticky: false,\n hasEverBeenInView: false,\n hasEverBeenInViewWhilePlaying: false,\n watchMsInView: 0,\n lastTickAt: 0,\n minPlaySatisfied: false,\n userPaused: false,\n userPausedAt: 0,\n adStartedOnce: false,\n contentStartedOnce: false,\n blockResumeUntil: 0,\n programmaticPauseUntil: 0,\n placeholderEl: null,\n closeBtnEl: null,\n },\n };\n this.items.set(ctx.key, item);\n\n this.ensureObserver().observe(sentinel);\n\n const onPlay = () => this.handlePlay(item);\n const onPause = () => this.handlePauseOrEnded(item, 'pause');\n const onEnded = () => this.handlePauseOrEnded(item, 'ended');\n const onAdStart = () => this.handleAdStart(item);\n const onAdEnd = () => this.handleAdEnd(item);\n\n ctx.videoEl.addEventListener('play', onPlay);\n ctx.videoEl.addEventListener('pause', onPause);\n ctx.videoEl.addEventListener('ended', onEnded);\n ctx.hostEl.addEventListener('hp:adstart', onAdStart);\n ctx.hostEl.addEventListener('hp:adend', onAdEnd);\n\n // Plugin dinamik yüklendiği için autoplay video'yu bu dinleyiciden önce başlatmış olabilir —\n // kaçırılan 'play'i telafi et, yoksa requirePlaying sticky'yi hiç açmaz.\n if (!ctx.videoEl.paused && !ctx.videoEl.ended) {\n this.handlePlay(item);\n }\n\n const unregister: StickyUnregister = () => {\n if (item.state.sticky) this.unstick(ctx.key, 'destroy');\n ctx.videoEl.removeEventListener('play', onPlay);\n ctx.videoEl.removeEventListener('pause', onPause);\n ctx.videoEl.removeEventListener('ended', onEnded);\n ctx.hostEl.removeEventListener('hp:adstart', onAdStart);\n ctx.hostEl.removeEventListener('hp:adend', onAdEnd);\n this.observer?.unobserve(sentinel);\n sentinel.remove();\n this.items.delete(ctx.key);\n };\n unregister.refreshLabels = () => {\n if (item.state.closeBtnEl) {\n item.state.closeBtnEl.setAttribute('aria-label', ctx.i18n.close);\n }\n };\n return unregister;\n }\n\n // ── gesture tracking (tüm sayfa için tek dinleyici) ──\n\n private ensureGestureListeners(): void {\n if (this.gestureListenersAttached || typeof window === 'undefined') return;\n this.gestureListenersAttached = true;\n\n window.addEventListener(\n 'pointerdown',\n (e) => {\n this.lastUserGestureAt = Date.now();\n // composedPath()[0]: Shadow DOM'da e.target host'a retarget edilir; gerçek iç butonu almak için.\n const target = (e.composedPath()[0] ?? e.target) as HTMLElement | null;\n const btn = target?.closest?.('button,[role=\"button\"]') as HTMLElement | null;\n if (btn?.querySelector('.hp-icon-pause')) this.lastGestureType = 'pause';\n else if (btn?.querySelector('.hp-icon-play')) this.lastGestureType = 'play';\n else this.lastGestureType = 'other';\n },\n { capture: true, passive: true }\n );\n window.addEventListener(\n 'keydown',\n () => {\n this.lastUserGestureAt = Date.now();\n this.lastGestureType = 'other';\n },\n { capture: true }\n );\n }\n\n // ── intersection observer (tüm sticky item'lar için tek instance) ──\n\n private ensureObserver(): IntersectionObserver {\n if (this.observer) return this.observer;\n this.observer = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n const item = [...this.items.values()].find((i) => i.sentinelEl === entry.target);\n if (!item) continue;\n this.onIntersect(item, entry);\n }\n },\n { threshold: [0.35], rootMargin: '0px 0px -20% 0px' }\n );\n return this.observer;\n }\n\n private onIntersect(item: StickyItem, entry: IntersectionObserverEntry): void {\n this.accumulateWatch(item);\n const inView = entry.isIntersecting && entry.intersectionRatio >= 0.35;\n item.state.inView = inView;\n\n if (inView) {\n item.state.hasEverBeenInView = true;\n if (item.state.playing) item.state.hasEverBeenInViewWhilePlaying = true;\n if (item.state.sticky) this.unstick(item.ctx.key, 'back_in_view');\n } else {\n if (!item.state.hasEverBeenInView) return;\n const isActive = item.state.playing;\n if (item.options.requirePlaying && !isActive) return;\n this.maybeStick(item, 'out_of_view');\n }\n }\n\n // ── player event handlers ──\n\n private handlePlay(item: StickyItem): void {\n if (item.state.blockResumeUntil && Date.now() < item.state.blockResumeUntil) {\n item.ctx.videoEl.pause();\n item.state.playing = false;\n return;\n }\n if (item.ctx.isAdActive()) return;\n\n item.state.contentStartedOnce = true;\n const wasPlaying = item.state.playing;\n item.state.playing = true;\n if (!wasPlaying) {\n item.state.lastTickAt = Date.now();\n item.state.watchMsInView = 0;\n }\n if (item.state.inView) item.state.hasEverBeenInViewWhilePlaying = true;\n\n const gestureWindow = item.options.userGestureWindowMs;\n let userInitiated = Date.now() - this.lastUserGestureAt <= gestureWindow;\n if (this.lastGestureType === 'pause') userInitiated = false;\n if (item.state.userPaused && Date.now() - item.state.userPausedAt <= 1500) userInitiated = false;\n\n if (userInitiated) {\n item.state.userPaused = false;\n item.state.userPausedAt = 0;\n this.lastGestureType = 'play';\n }\n\n this.handleBecameActive(item, 'content', userInitiated);\n }\n\n private handlePauseOrEnded(item: StickyItem, kind: 'pause' | 'ended'): void {\n this.accumulateWatch(item);\n if (item.ctx.isAdActive()) {\n item.state.playing = true;\n return;\n }\n item.state.playing = false;\n\n const now = Date.now();\n if (item.state.programmaticPauseUntil && now < item.state.programmaticPauseUntil) {\n item.state.programmaticPauseUntil = 0;\n item.state.userPaused = false;\n item.state.userPausedAt = 0;\n return;\n }\n\n if (kind === 'pause') {\n const isUserPause = now - this.lastUserGestureAt <= item.options.userGestureWindowMs;\n if (isUserPause) {\n item.state.userPaused = true;\n item.state.userPausedAt = now;\n this.lastGestureType = 'pause';\n }\n } else if (item.state.sticky) {\n this.unstick(item.ctx.key, 'ended');\n }\n }\n\n private handleAdStart(item: StickyItem): void {\n const mode = item.options.adCanTriggerSticky;\n const isCurrentlySticky = this.activeKey === item.ctx.key;\n const isFirstAdEver = !item.state.adStartedOnce;\n item.state.adStartedOnce = true;\n item.state.lastTickAt = Date.now();\n item.state.playing = true;\n\n let allow = false;\n if (mode === 'always') allow = true;\n else if (mode === 'never') allow = false;\n else allow = isCurrentlySticky || (isFirstAdEver && !item.state.contentStartedOnce);\n\n if (!allow) return;\n this.handleBecameActive(item, 'ad', false);\n }\n\n private handleAdEnd(item: StickyItem): void {\n this.accumulateWatch(item);\n item.state.playing = !item.ctx.videoEl.paused && !item.ctx.videoEl.ended;\n item.state.lastTickAt = Date.now();\n }\n\n private handleBecameActive(item: StickyItem, source: 'content' | 'ad', userInitiated: boolean): void {\n item.state.playing = true;\n if (userInitiated) {\n item.state.userPaused = false;\n item.state.userPausedAt = 0;\n this.lastGestureType = 'play';\n }\n\n const now = Date.now();\n if (!item.state.lastTickAt) item.state.lastTickAt = now;\n if (item.state.inView) {\n item.state.hasEverBeenInView = true;\n item.state.hasEverBeenInViewWhilePlaying = true;\n }\n\n if (item.options.closeActiveStickyOnAnotherPlay && userInitiated && this.activeKey && this.activeKey !== item.ctx.key) {\n this.pauseAndUnstick(this.activeKey, 'another_played');\n }\n\n if (!item.state.inView) this.maybeStick(item, source === 'ad' ? 'play_ad' : 'play');\n }\n\n private accumulateWatch(item: StickyItem): void {\n const now = Date.now();\n const last = item.state.lastTickAt || now;\n item.state.lastTickAt = now;\n if (!item.state.playing || !item.state.inView) return;\n\n item.state.watchMsInView += now - last;\n if (!item.state.minPlaySatisfied && item.options.minPlayMs > 0 && item.state.watchMsInView >= item.options.minPlayMs) {\n item.state.minPlaySatisfied = true;\n }\n }\n\n // ── stick / unstick ──\n\n private maybeStick(item: StickyItem, _trigger: string): void {\n const maxMs = USER_PAUSED_MAX_MS;\n if (item.state.userPaused && Date.now() - item.state.userPausedAt > maxMs) {\n item.state.userPaused = false;\n item.state.userPausedAt = 0;\n }\n\n if (!item.state.hasEverBeenInView) return;\n if (!item.state.hasEverBeenInViewWhilePlaying) return;\n if (item.state.userPaused) return;\n\n const now = Date.now();\n if (item.options.dismissMode === 'never' && this.dismissedForever) return;\n if (item.options.dismissMode === 'cooldown' && this.dismissedUntil && now < this.dismissedUntil) return;\n\n if (item.options.requirePlaying && !item.state.playing) return;\n if (item.state.sticky) return;\n if (item.options.minPlayMs > 0 && !item.state.minPlaySatisfied) return;\n\n if (item.options.onlyOneSticky && this.activeKey && this.activeKey !== item.ctx.key) {\n this.pauseAndUnstick(this.activeKey, 'replaced');\n }\n\n this.stick(item);\n }\n\n private stick(item: StickyItem): void {\n const wrapper = item.ctx.wrapperEl;\n const corner = item.options.corner;\n\n if (!item.state.placeholderEl) {\n const ph = document.createElement('div');\n ph.setAttribute('data-hope-sticky-placeholder', '1');\n const rect = wrapper.getBoundingClientRect();\n ph.style.height = `${rect.height}px`;\n wrapper.parentNode?.insertBefore(ph, wrapper);\n item.state.placeholderEl = ph;\n }\n\n wrapper.setAttribute('data-sticky', '1');\n wrapper.setAttribute('data-sticky-corner', corner);\n\n if (item.options.closeButton && !item.state.closeBtnEl) {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.setAttribute('part', 'sticky-close-button');\n btn.setAttribute('aria-label', item.ctx.i18n.close);\n btn.className =\n 'hp:absolute hp:top-1 hp:right-1 hp:z-30 hp:flex hp:items-center hp:justify-center hp:w-6 hp:h-6 ' +\n 'hp:rounded-full hp:bg-black/60 hp:text-white hp:border-0 hp:cursor-pointer';\n btn.innerHTML = '<i class=\"hp-icon hp-icon-close\" aria-hidden=\"true\"></i>';\n btn.addEventListener('click', () => {\n this.applyGlobalDismiss(item.options);\n this.pauseAndUnstick(item.ctx.key, 'closed');\n });\n item.ctx.closeButtonMountEl.appendChild(btn);\n item.state.closeBtnEl = btn;\n }\n\n item.state.sticky = true;\n this.activeKey = item.ctx.key;\n item.ctx.hostEl.dispatchEvent(new CustomEvent('hp:sticky', { detail: { sticky: true, corner } }));\n }\n\n private unstick(key: string, _reason: string): void {\n const item = this.items.get(key);\n if (!item) return;\n\n const wrapper = item.ctx.wrapperEl;\n wrapper.removeAttribute('data-sticky');\n wrapper.removeAttribute('data-sticky-corner');\n\n item.state.closeBtnEl?.remove();\n item.state.closeBtnEl = null;\n item.state.placeholderEl?.remove();\n item.state.placeholderEl = null;\n\n item.state.sticky = false;\n if (this.activeKey === key) this.activeKey = null;\n item.ctx.hostEl.dispatchEvent(new CustomEvent('hp:sticky', { detail: { sticky: false } }));\n }\n\n private pauseAndUnstick(key: string, reason: string): void {\n const item = this.items.get(key);\n if (!item) return;\n\n const now = Date.now();\n item.state.blockResumeUntil = now + BLOCK_RESUME_MS;\n item.state.programmaticPauseUntil = now + PROGRAMMATIC_PAUSE_MS;\n\n item.ctx.videoEl.pause();\n item.state.playing = false;\n this.unstick(key, reason);\n }\n\n // ── global dismiss (localStorage/sessionStorage) ──\n\n private loadDismissState(): void {\n if (this.dismissLoaded) return;\n this.dismissLoaded = true;\n try {\n const st = window.localStorage;\n this.dismissedUntil = Number(st.getItem(STORAGE_KEY) || 0) || 0;\n this.dismissedForever = st.getItem(STORAGE_KEY_FOREVER) === '1';\n } catch {\n /* storage erişilemez (gizli mod vb.) — sessizce yoksay */\n }\n }\n\n private applyGlobalDismiss(options: StickyItem['options']): void {\n if (options.dismissMode === 'none') return;\n const storage = options.storage === 'memory' ? null : options.storage === 'session' ? window.sessionStorage : window.localStorage;\n\n if (options.dismissMode === 'never') {\n this.dismissedForever = true;\n try {\n storage?.setItem(STORAGE_KEY_FOREVER, '1');\n } catch {\n /* no-op */\n }\n return;\n }\n\n const until = Date.now() + options.cooldownMinutes * 60000;\n this.dismissedUntil = until;\n try {\n storage?.setItem(STORAGE_KEY, String(until));\n } catch {\n /* no-op */\n }\n }\n}\n\nexport const stickyManager = new StickyManagerImpl();\nexport type { StickyCorner };\n","import { stickyManager, type StickyPlayerContext, type StickyUnregister } from './StickyManager';\nimport type { StickyOptions } from '../../types';\n\n/** Dönen fonksiyon unregister/cleanup — HopePlayerElement.disconnectedCallback'te çağrılmalı. `refreshLabels()` da taşır (dil değişince close butonu için). */\nexport function installSticky(ctx: StickyPlayerContext, options: StickyOptions): StickyUnregister {\n return stickyManager.register(ctx, options);\n}\n\nexport type { StickyPlayerContext, StickyUnregister };\n"],"names":["STORAGE_KEY","STORAGE_KEY_FOREVER","StickyManagerImpl","__publicField","ctx","options","_a","resolved","sentinel","item","onPlay","onPause","onEnded","onAdStart","onAdEnd","unregister","target","btn","entries","entry","i","inView","isActive","wasPlaying","gestureWindow","userInitiated","kind","now","mode","isCurrentlySticky","isFirstAdEver","allow","source","last","_trigger","wrapper","corner","ph","rect","key","_reason","_b","reason","st","storage","until","stickyManager","installSticky"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-CDPrkLq0.js","sources":["../../src/plugins/pause-ad/PauseAd.ts","../../src/plugins/pause-ad/index.ts"],"sourcesContent":["import type { PauseAdOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\nimport { loadGpt, type GoogleTag, type GptSlot, type GptSlotRenderEndedEvent } from './loadGpt';\n\nexport interface PauseAdPlayerContext {\n videoEl: HTMLVideoElement;\n /** Light DOM sahibi (GPT reklam div'ini bulabilsin diye slot'lu div buraya eklenir) + hp:pausead olayları. */\n hostEl: HTMLElement;\n videoArea: HTMLElement;\n i18n: HopeLocaleStrings;\n /** IMA reklamı oynuyor ya da giriş ekranı (countdown/geo) açık — bu sırada gösterilmez. */\n isBlocked(): boolean;\n}\n\nconst DEFAULT_SIZES: Array<[number, number]> = [\n [300, 250],\n [336, 280],\n [250, 250],\n [200, 200],\n];\nconst PANEL_PADDING_X = 16;\n/** Başlık + \"Videoya devam et\" satırı + boşluklar (px) — dikey sığma hesabı için. */\nconst PANEL_CHROME_Y = 104;\nconst SLOT_NAME = 'hp-pause-ad';\n/** tailwind.css'teki sıkışma geçişiyle (380ms) aynı + küçük pay. */\nconst SHIFT_TRANSITION_MS = 420;\nlet instanceCount = 0;\n\n/**\n * Pause reklamı: video duraklatılınca Google display reklamı (GPT) istenir; dolarsa video sola animasyonla\n * sıkışır (cover — dış kenarlar kırpılır), sağdan reklam paneli kayar. Boş dönerse hiçbir şey açılmaz.\n * GPT reklamı document.getElementById ile bulur — Shadow DOM'u göremez; bu yüzden reklam div'i host'un light\n * DOM çocuğu olarak oluşturulup paneldeki <slot>'a yansıtılır.\n */\nexport class PauseAd {\n private readonly panel: HTMLDivElement;\n private readonly adHost: HTMLDivElement;\n private readonly labelEl: HTMLSpanElement;\n private readonly closeBtn: HTMLButtonElement;\n private readonly resumeBtn: HTMLButtonElement;\n private readonly divId: string;\n private googletag: GoogleTag | null = null;\n private slot: GptSlot | null = null;\n private slotSizesKey = '';\n private lastFetchAt = 0;\n private lastFilled = false;\n private waitingForRender = false;\n private delayTimer: ReturnType<typeof setTimeout> | null = null;\n private coverTimer: ReturnType<typeof setTimeout> | null = null;\n private open = false;\n private destroyed = false;\n\n constructor(\n private readonly ctx: PauseAdPlayerContext,\n private readonly options: PauseAdOptions\n ) {\n this.divId = `hp-pause-ad-${++instanceCount}`;\n\n this.panel = document.createElement('div');\n this.panel.className = 'hp-pause-ad';\n this.panel.setAttribute('part', 'pause-ad');\n this.panel.setAttribute('aria-hidden', 'true');\n\n const header = document.createElement('div');\n header.className = 'hp-pause-ad-header';\n this.labelEl = document.createElement('span');\n this.labelEl.className = 'hp-pause-ad-label';\n this.closeBtn = document.createElement('button');\n this.closeBtn.type = 'button';\n this.closeBtn.className = 'hp-pause-ad-close';\n this.closeBtn.innerHTML =\n '<svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" aria-hidden=\"true\"><path d=\"M6 6l12 12M18 6L6 18\"/></svg>';\n this.closeBtn.addEventListener('click', () => this.hide('closed'));\n header.append(this.labelEl, this.closeBtn);\n\n const body = document.createElement('div');\n body.className = 'hp-pause-ad-body';\n const slotEl = document.createElement('slot');\n slotEl.name = SLOT_NAME;\n body.appendChild(slotEl);\n\n this.resumeBtn = document.createElement('button');\n this.resumeBtn.type = 'button';\n this.resumeBtn.className = 'hp-pause-ad-resume';\n this.resumeBtn.addEventListener('click', () => void this.ctx.videoEl.play());\n if (options.showResumeButton === false) this.resumeBtn.style.display = 'none';\n\n this.panel.append(header, body, this.resumeBtn);\n // Videoya dokunma/tıklama (oynat/duraklat) panelden tetiklenmesin.\n this.panel.addEventListener('pointerdown', (e) => e.stopPropagation());\n this.panel.addEventListener('click', (e) => e.stopPropagation());\n ctx.videoArea.appendChild(this.panel);\n ctx.videoArea.setAttribute('data-pause-ad-ready', '');\n\n // Light DOM reklam kapsayıcısı — GPT bunu id ile bulur; görüntüsü paneldeki slot'ta.\n this.adHost = document.createElement('div');\n this.adHost.slot = SLOT_NAME;\n this.adHost.id = this.divId;\n ctx.hostEl.appendChild(this.adHost);\n\n this.refreshLabels();\n ctx.videoEl.addEventListener('pause', this.onPause);\n ctx.videoEl.addEventListener('play', this.onPlay);\n }\n\n refreshLabels(): void {\n this.labelEl.textContent = this.options.label ?? this.ctx.i18n.pauseAdLabel;\n this.closeBtn.setAttribute('aria-label', this.ctx.i18n.pauseAdClose);\n this.resumeBtn.textContent = this.ctx.i18n.pauseAdResume;\n }\n\n destroy(): void {\n this.destroyed = true;\n if (this.delayTimer) clearTimeout(this.delayTimer);\n this.ctx.videoEl.removeEventListener('pause', this.onPause);\n this.ctx.videoEl.removeEventListener('play', this.onPlay);\n this.googletag?.pubads().removeEventListener?.('slotRenderEnded', this.onRenderEnded);\n if (this.slot) this.googletag?.destroySlots([this.slot]);\n this.setShift(0);\n if (this.coverTimer) clearTimeout(this.coverTimer);\n this.ctx.videoArea.removeAttribute('data-pause-ad');\n this.ctx.videoArea.removeAttribute('data-pause-ad-ready');\n this.panel.remove();\n this.adHost.remove();\n }\n\n // ── olaylar ──\n\n private readonly onPause = (): void => {\n if (this.delayTimer) clearTimeout(this.delayTimer);\n this.delayTimer = setTimeout(() => void this.request(), this.options.delayMs ?? 300);\n };\n\n private readonly onPlay = (): void => {\n if (this.delayTimer) clearTimeout(this.delayTimer);\n this.waitingForRender = false;\n this.hide('resumed');\n };\n\n // ── istek / gösterim ──\n\n /** Alana sığan reklam boyutları (genişlik oranı + dikey alan) — hiçbiri sığmazsa gösterilmez. */\n private fittingSizes(): Array<[number, number]> {\n const area = this.ctx.videoArea.getBoundingClientRect();\n if (area.width < (this.options.minPlayerWidth ?? 640)) return [];\n const maxW = area.width * (this.options.maxWidthRatio ?? 0.5) - PANEL_PADDING_X * 2;\n const maxH = area.height - PANEL_CHROME_Y;\n return (this.options.sizes ?? DEFAULT_SIZES).filter(([w, h]) => w <= maxW && h <= maxH);\n }\n\n private async request(): Promise<void> {\n const v = this.ctx.videoEl;\n if (this.destroyed || !v.paused || v.ended || v.seeking || this.ctx.isBlocked()) return;\n const sizes = this.fittingSizes();\n if (!sizes.length) return;\n\n // Panel genişliği: sığan en geniş reklam + iç boşluk.\n const panelW = Math.max(...sizes.map(([w]) => w)) + PANEL_PADDING_X * 2;\n this.panel.style.setProperty('--hp-pause-ad-panel-w', `${panelW}px`);\n\n const refreshMs = (this.options.refreshIntervalSec ?? 30) * 1000;\n const sizesKey = JSON.stringify(sizes);\n // Yakın zamanda doldurulmuş ve boyutlar aynı → yeni istek atmadan mevcut reklamı göster.\n if (this.slot && this.lastFilled && sizesKey === this.slotSizesKey && Date.now() - this.lastFetchAt < refreshMs) {\n this.show(panelW);\n return;\n }\n\n try {\n this.googletag = this.googletag ?? (await loadGpt());\n } catch (err) {\n console.warn('[HopePlayer pause-ad]', err);\n return;\n }\n if (this.destroyed || !v.paused) return;\n const gt = this.googletag;\n this.waitingForRender = true;\n gt.cmd.push(() => {\n if (this.destroyed) return;\n if (!this.slot || sizesKey !== this.slotSizesKey) {\n if (this.slot) gt.destroySlots([this.slot]);\n this.slot = gt.defineSlot(this.options.adUnitPath, sizes, this.divId);\n if (!this.slot) return;\n this.slot.addService(gt.pubads());\n for (const [k, val] of Object.entries(this.options.targeting ?? {})) this.slot.setTargeting(k, val);\n this.slotSizesKey = sizesKey;\n gt.pubads().addEventListener('slotRenderEnded', this.onRenderEnded);\n gt.enableServices();\n gt.display(this.divId);\n // Sayfa disableInitialLoad kullanıyorsa display istek atmaz — elle refresh.\n if (gt.pubads().isInitialLoadDisabled()) gt.pubads().refresh([this.slot]);\n } else {\n gt.pubads().refresh([this.slot]);\n }\n this.lastFetchAt = Date.now();\n });\n }\n\n private readonly onRenderEnded = (e: GptSlotRenderEndedEvent): void => {\n if (e.slot !== this.slot) return;\n this.lastFilled = !e.isEmpty;\n const wasWaiting = this.waitingForRender;\n this.waitingForRender = false;\n if (e.isEmpty) {\n this.emit('empty');\n return;\n }\n // İstek sürerken kullanıcı oynattıysa açma.\n if (!wasWaiting || !this.ctx.videoEl.paused || this.ctx.isBlocked()) return;\n const width = Array.isArray(e.size) && typeof e.size[0] === 'number' ? e.size[0] : null;\n this.show(width ? width + PANEL_PADDING_X * 2 : undefined, e.size as [number, number] | undefined);\n };\n\n private show(panelW?: number, size?: [number, number]): void {\n if (panelW) this.panel.style.setProperty('--hp-pause-ad-panel-w', `${panelW}px`);\n const w = parseFloat(this.panel.style.getPropertyValue('--hp-pause-ad-panel-w')) || 332;\n this.open = true;\n this.panel.setAttribute('data-open', '');\n this.panel.setAttribute('aria-hidden', 'false');\n this.setShift(w);\n this.emit('shown', size);\n }\n\n private hide(reason: 'closed' | 'resumed'): void {\n if (!this.open) return;\n this.open = false;\n this.panel.removeAttribute('data-open');\n this.panel.setAttribute('aria-hidden', 'true');\n this.setShift(0);\n this.emit('hidden', undefined, reason);\n }\n\n /** Video ve kontrolleri panel genişliği kadar sola sıkıştırır (tailwind.css `.video-area[data-pause-ad]`). */\n private setShift(px: number): void {\n const area = this.ctx.videoArea;\n if (this.coverTimer) clearTimeout(this.coverTimer);\n this.coverTimer = null;\n area.style.setProperty('--hp-pause-ad-w', `${px}px`);\n if (px > 0) {\n area.setAttribute('data-pause-ad', '');\n } else if (area.hasAttribute('data-pause-ad')) {\n // cover, genişleme animasyonu bitene kadar kalır — hemen contain'e dönmek kapanışta görüntüyü sıçratıyordu.\n this.coverTimer = setTimeout(() => {\n this.coverTimer = null;\n area.removeAttribute('data-pause-ad');\n }, SHIFT_TRANSITION_MS);\n }\n }\n\n private emit(state: 'shown' | 'hidden' | 'empty', size?: [number, number], reason?: 'closed' | 'resumed'): void {\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:pausead', { detail: { state, size, reason } }));\n }\n}\n","import { PauseAd, type PauseAdPlayerContext } from './PauseAd';\nimport type { PauseAdOptions } from '../../types';\n\nexport function installPauseAd(ctx: PauseAdPlayerContext, options: PauseAdOptions): PauseAd {\n return new PauseAd(ctx, options);\n}\n\nexport { PauseAd };\nexport type { PauseAdPlayerContext };\n"],"names":["DEFAULT_SIZES","PANEL_PADDING_X","PANEL_CHROME_Y","SLOT_NAME","SHIFT_TRANSITION_MS","instanceCount","PauseAd","ctx","options","__publicField","wasWaiting","width","header","body","slotEl","e","_c","_a","_b","_d","area","maxW","maxH","w","h","v","sizes","panelW","refreshMs","sizesKey","loadGpt","err","gt","k","val","size","reason","px","state","installPauseAd"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-CWLyz1fp.js","sources":["../../src/plugins/ad-triggers/AdTriggers.ts","../../src/plugins/ad-triggers/index.ts"],"sourcesContent":["import type { AdTrigger, AdTriggerLayout, AdTriggerRule, AdTriggersConfig, AdTriggersOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\nimport { loadGpt, type GoogleTag, type GptSlot, type GptSlotRenderEndedEvent } from '../pause-ad/loadGpt';\n\nexport interface AdTriggersContext {\n /** Light DOM sahibi: GPT reklam div'ini id ile bulabilsin diye div buraya eklenir (tam ekranda da görünür). */\n hostEl: HTMLElement;\n videoEl: HTMLVideoElement;\n /** Reklam kutusunun ekleneceği alan (video alanı). */\n overlayEl: HTMLElement;\n i18n: HopeLocaleStrings;\n log(entry: { message: string; fatal?: boolean; details?: Record<string, string | number | boolean | undefined> }): void;\n /** Video reklamı (IMA) oynuyor ya da giriş ekranı (geri sayım / geo) açık — bu sırada istenmez. */\n isBlocked(): boolean;\n isFullscreen(): boolean;\n /** iPhone'un kendi video tam ekranı — player katmanları orada görünmez, reklam istenmez. */\n isNativeFullscreen(): boolean;\n /** İçerik kimliği — kalite değişimi / yedek kaynak aynı içerik sayılır; değişince sayaçlar sıfırlanır. */\n contentKey(): string;\n}\n\nconst DEFAULT_TIMEOUT_MS = 5000;\nconst DEFAULT_RENDER_TIMEOUT_MS = 8000;\nconst DEFAULT_GLOBAL_GAP_S = 30;\nconst LAYOUTS: AdTriggerLayout[] = ['none', 'full', 'center', 'top', 'bottom', 'top-left', 'top-right', 'bottom-left', 'bottom-right'];\nconst TRIGGER_TYPES = ['time', 'interval', 'percent', 'fullscreen', 'fullscreenExit', 'start', 'pause', 'resume', 'ended'] as const;\n/** Doğal ilerleme sayılan en büyük timeupdate adımı (sn) — daha büyük sıçrama ileri sarmadır, aradaki anlar atlanır. */\nconst MAX_NATURAL_STEP_S = 1.5;\nlet instanceCount = 0;\n\nfunction safeUrl(value: unknown): string | null {\n if (typeof value !== 'string' || !value.trim()) return null;\n try {\n const u = new URL(value, document.baseURI);\n return u.protocol === 'https:' || u.protocol === 'http:' ? u.href : null;\n } catch {\n return null;\n }\n}\n\nconst num = (n: unknown, min: number, max: number): number | undefined =>\n typeof n === 'number' && Number.isFinite(n) ? Math.min(max, Math.max(min, n)) : undefined;\n\ntype KeyValues = Record<string, string | string[]>;\nconst prim = (v: unknown): string | null =>\n typeof v === 'string' ? v.slice(0, 200) : typeof v === 'number' && Number.isFinite(v) ? String(v) : typeof v === 'boolean' ? String(v) : null;\n\n/**\n * Ad Manager key-value'ları (GPT slot hedeflemesi = VAST tag'lerindeki `cust_params`): JSON nesnesi\n * `{ \"kategori\": \"spor\", \"etiket\": [\"mac\", \"ozet\"], \"sezon\": 2026 }` ya da `\"kategori=spor&etiket=mac,ozet\"` metni.\n * Sayı / boolean metne çevrilir; geçersiz anahtar ve değerler atılır.\n */\nexport function parseCustParams(raw: unknown): KeyValues | undefined {\n let entries: Array<[string, unknown]>;\n if (typeof raw === 'string') {\n if (!raw.trim()) return undefined;\n entries = [...new URLSearchParams(raw.trim().replace(/^\\?/, '')).entries()].map(([k, v]) => [k, v.includes(',') ? v.split(',') : v]);\n } else if (raw && typeof raw === 'object' && !Array.isArray(raw)) {\n entries = Object.entries(raw as Record<string, unknown>);\n } else {\n return undefined;\n }\n const out: KeyValues = {};\n for (const [k, v] of entries.slice(0, 50)) {\n if (!/^[\\w.-]{1,40}$/.test(k)) continue;\n if (Array.isArray(v)) {\n const list = v.map(prim).filter((x): x is string => x !== null && x !== '').slice(0, 30);\n if (list.length) out[k] = list;\n } else {\n const one = prim(v);\n if (one !== null && one !== '') out[k] = one;\n }\n }\n return Object.keys(out).length ? out : undefined;\n}\n\nfunction normalizeTrigger(raw: unknown): AdTrigger | null {\n if (!raw || typeof raw !== 'object') return null;\n const t = raw as Record<string, unknown>;\n const type = t.type as (typeof TRIGGER_TYPES)[number];\n if (!TRIGGER_TYPES.includes(type)) return null;\n const list = (v: unknown, min: number, max: number): number[] =>\n (Array.isArray(v) ? v : [v]).map((x) => num(x, min, max)).filter((x): x is number => x !== undefined).slice(0, 50);\n if (type === 'time') {\n const at = list(t.at, 0, 86_400);\n return at.length ? { type, at } : null;\n }\n if (type === 'percent') {\n const at = list(t.at, 1, 99);\n return at.length ? { type, at } : null;\n }\n if (type === 'interval') {\n const every = num(t.every, 10, 86_400);\n return every ? { type, every, startAfter: num(t.startAfter, 0, 86_400) } : null;\n }\n return { type, delay: num(t.delay, 0, 600) };\n}\n\n/** API yanıtını doğrular, geçersiz kural/tetikleyicileri atar; modül kapalıysa ya da geçerli kural yoksa null. */\nexport function normalizeAdTriggers(raw: unknown): AdTriggersConfig | null {\n if (!raw || typeof raw !== 'object') return null;\n const r = raw as Partial<AdTriggersConfig>;\n if (r.active !== true || !Array.isArray(r.rules)) return null;\n const now = Date.now();\n const from = r.validFrom ? Date.parse(r.validFrom) : NaN;\n const until = r.validUntil ? Date.parse(r.validUntil) : NaN;\n if ((Number.isFinite(from) && now < from) || (Number.isFinite(until) && now > until)) return null;\n const urls = (list: unknown): string[] => (Array.isArray(list) ? list.map(safeUrl).filter((u): u is string => !!u).slice(0, 10) : []);\n const rules: AdTriggerRule[] = [];\n for (const raw of r.rules.slice(0, 20)) {\n if (!raw || typeof raw !== 'object') continue;\n const x = raw as Partial<AdTriggerRule>;\n // Reklam birimi yolu: \"/ağ kodu/birim/...\" biçimi.\n if (typeof x.adUnitPath !== 'string' || !/^\\/\\d+(?:[,/][\\w.\\-/]*)?$/.test(x.adUnitPath)) continue;\n const triggers = (Array.isArray(x.triggers) ? x.triggers : []).map(normalizeTrigger).filter((t): t is AdTrigger => !!t).slice(0, 20);\n if (!triggers.length) continue;\n const size = Array.isArray(x.size) && x.size.length === 2 ? [num(x.size[0], 1, 4000), num(x.size[1], 1, 4000)] : null;\n const layout = LAYOUTS.includes(x.layout as AdTriggerLayout) ? x.layout! : 'none';\n rules.push({\n id: typeof x.id === 'string' ? x.id.slice(0, 80) : undefined,\n adUnitPath: x.adUnitPath,\n mode: x.mode === 'fullscreen' || x.mode === 'normal' ? x.mode : 'any',\n triggers,\n targeting: parseCustParams(x.targeting),\n // API'lerde yaygın `cust_params` yazımı da kabul edilir.\n custParams: parseCustParams(x.custParams ?? (x as { cust_params?: unknown }).cust_params),\n layout,\n size: size && size[0] && size[1] ? [size[0], size[1]] : undefined,\n backdrop: typeof x.backdrop === 'boolean' ? x.backdrop : layout === 'full',\n pauseContent: x.pauseContent === true,\n closeButton: x.closeButton !== false,\n closeDelay: num(x.closeDelay, 0, 120) ?? 0,\n duration: num(x.duration, 1, 3600),\n label: x.label === false ? false : typeof x.label === 'string' ? x.label.slice(0, 40) : undefined,\n maxShows: num(x.maxShows, 1, 1000),\n minGapSeconds: num(x.minGapSeconds, 0, 86_400),\n minPlayerWidth: num(x.minPlayerWidth, 0, 4000),\n tracking: { impression: urls(x.tracking?.impression), close: urls(x.tracking?.close), empty: urls(x.tracking?.empty) },\n });\n }\n if (!rules.length) return null;\n return {\n active: true,\n id: typeof r.id === 'string' ? r.id.slice(0, 120) : undefined,\n minGapSeconds: num(r.minGapSeconds, 0, 86_400) ?? DEFAULT_GLOBAL_GAP_S,\n rules,\n };\n}\n\nfunction fire(urls: string[] | undefined): void {\n for (const u of urls ?? []) {\n const img = new Image();\n img.referrerPolicy = 'no-referrer-when-downgrade';\n img.src = u;\n }\n}\n\ntype TriggerType = AdTrigger['type'];\ntype CloseReason = 'user' | 'timeout' | 'mode' | 'ad' | 'content' | 'replaced';\n\ninterface Showing {\n rule: AdTriggerRule;\n trigger: TriggerType;\n box: HTMLDivElement;\n adHost: HTMLDivElement;\n slot: GptSlot | null;\n filled: boolean;\n pausedContent: boolean;\n timers: Array<ReturnType<typeof setTimeout>>;\n /** İsteğe giden key-value'ların son hali (olayda bildirilir). */\n custParams?: KeyValues;\n}\n\n/**\n * Reklam tetikleyici: kurallara göre Ad Manager out-of-page reklamı ister ve player içinde (tam ekranda da) gösterir.\n * Kurallar API'den (`endpoint`) ya da `config`'ten gelir; API hatasında son geçerli kurallar korunur.\n * Aynı anda tek reklam; video reklamı (IMA) oynarken, sekme arka plandayken ve iPhone native tam ekranında istenmez.\n */\nexport class AdTriggers {\n private options: AdTriggersOptions;\n private config: AdTriggersConfig | null = null;\n private loaded = false;\n private googletag: GoogleTag | null = null;\n private showing: Showing | null = null;\n private readonly instance = ++instanceCount;\n private seq = 0;\n private requestSeq = 0;\n private destroyed = false;\n private refreshTimer: ReturnType<typeof setInterval> | null = null;\n private readonly tickTimer: ReturnType<typeof setInterval>;\n /** Olaydan `delay` sn sonra çalışacak tetiklemeler — koşul bozulunca iptal edilir. */\n private delayed: Array<{ type: TriggerType; timer: ReturnType<typeof setTimeout> }> = [];\n // ── içerik başına durum (kaynak değişince sıfırlanır) ──\n private contentKey = '';\n private fired = new Set<string>();\n private shows = new Map<number, number>();\n private lastShownAt = new Map<number, number>();\n private lastAnyAt = 0;\n private watchedMs = 0;\n private lastTick = performance.now();\n private lastPos = 0;\n private started = false;\n private userPaused = false;\n /** Player'ın kendi duraklatması (pauseContent) — pause/resume kuralı sayılmaz. */\n private selfPause = false;\n private wasFullscreen = false;\n\n constructor(\n private readonly ctx: AdTriggersContext,\n options: AdTriggersOptions\n ) {\n this.options = options;\n const v = ctx.videoEl;\n v.addEventListener('timeupdate', this.onTimeUpdate);\n v.addEventListener('seeked', this.onSeeked);\n v.addEventListener('playing', this.onPlaying);\n v.addEventListener('pause', this.onPause);\n v.addEventListener('ended', this.onEnded);\n v.addEventListener('loadstart', this.onLoadStart);\n v.addEventListener('webkitbeginfullscreen', this.onFullscreenChange);\n v.addEventListener('webkitendfullscreen', this.onFullscreenChange);\n document.addEventListener('fullscreenchange', this.onFullscreenChange);\n document.addEventListener('webkitfullscreenchange', this.onFullscreenChange);\n ctx.hostEl.addEventListener('hp:adstart', this.onVideoAdStart);\n this.wasFullscreen = ctx.isFullscreen();\n this.contentKey = ctx.contentKey();\n this.tickTimer = setInterval(this.tick, 1000);\n void this.load();\n this.scheduleRefresh();\n }\n\n update(options: AdTriggersOptions): void {\n const changed =\n options.endpoint !== this.options.endpoint ||\n JSON.stringify(options.params) !== JSON.stringify(this.options.params) ||\n JSON.stringify(options.config) !== JSON.stringify(this.options.config);\n const refreshChanged = options.refreshSeconds !== this.options.refreshSeconds;\n this.options = options;\n if (changed) void this.load();\n if (refreshChanged) this.scheduleRefresh();\n }\n\n get current(): AdTriggersConfig | null {\n return this.config;\n }\n\n /** Şu an bir reklam gösteriliyor mu. */\n get active(): boolean {\n return !!this.showing?.filled;\n }\n\n // ── kurallar ──\n\n private scheduleRefresh(): void {\n if (this.refreshTimer) clearInterval(this.refreshTimer);\n this.refreshTimer = null;\n const s = this.options.refreshSeconds;\n if (this.options.endpoint && typeof s === 'number' && s >= 10) this.refreshTimer = setInterval(() => void this.load(), s * 1000);\n }\n\n private async load(): Promise<void> {\n const seq = ++this.requestSeq;\n if (!this.options.endpoint) {\n this.apply(normalizeAdTriggers(this.options.config));\n return;\n }\n const ctrl = typeof AbortController !== 'undefined' ? new AbortController() : null;\n const timer = setTimeout(() => ctrl?.abort(), this.options.timeoutMs ?? DEFAULT_TIMEOUT_MS);\n let url = '';\n try {\n const u = new URL(this.options.endpoint, document.baseURI);\n for (const [k, v] of Object.entries(this.options.params ?? {})) u.searchParams.set(k, v);\n url = u.href;\n const res = await fetch(url, { ...this.options.fetchInit, signal: ctrl?.signal });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const json: unknown = await res.json();\n if (this.destroyed || seq !== this.requestSeq) return;\n this.apply(normalizeAdTriggers(json));\n } catch (err) {\n if (this.destroyed || seq !== this.requestSeq) return;\n this.ctx.log({ message: `Ad triggers API failed: ${String(err)}`, details: { url } });\n // Hiç kural yoksa yerel varsayılan (config) kullanılır; varsa son geçerli kurallar korunur.\n if (!this.config && this.options.config) this.apply(normalizeAdTriggers(this.options.config));\n } finally {\n clearTimeout(timer);\n }\n }\n\n private apply(config: AdTriggersConfig | null): void {\n // İlk yanıt her zaman bildirilir (kapalı olsa da) — sonrakiler yalnızca değişince.\n const changed = !this.loaded || JSON.stringify(config) !== JSON.stringify(this.config);\n this.loaded = true;\n this.config = config;\n if (!changed) return;\n this.cancelDelayed();\n if (!config) this.close('content');\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:adtriggers', { detail: { config } }));\n }\n\n // ── olaylar → tetikleyiciler ──\n\n private readonly onLoadStart = (): void => {\n const key = this.ctx.contentKey();\n // Aynı içeriğin kalite değişimi de loadstart üretir — yalnızca gerçekten başka bir içerik gelince sıfırla.\n if (key === this.contentKey) return;\n this.contentKey = key;\n this.fired.clear();\n this.shows.clear();\n this.lastShownAt.clear();\n this.watchedMs = 0;\n this.lastPos = 0;\n this.started = false;\n this.userPaused = false;\n this.cancelDelayed();\n this.close('content');\n };\n\n private readonly onPlaying = (): void => {\n if (this.ctx.isBlocked()) return;\n if (!this.started) {\n this.started = true;\n this.trigger('start');\n } else if (this.userPaused) {\n this.trigger('resume');\n }\n this.userPaused = false;\n this.cancelDelayed('pause');\n };\n\n private readonly onPause = (): void => {\n const v = this.ctx.videoEl;\n if (this.selfPause) {\n this.selfPause = false;\n return;\n }\n if (v.ended || v.seeking || this.ctx.isBlocked()) return;\n this.userPaused = true;\n this.cancelDelayed('start', 'resume');\n this.trigger('pause');\n };\n\n private readonly onEnded = (): void => {\n if (!this.ctx.isBlocked()) this.trigger('ended');\n };\n\n private readonly onSeeked = (): void => {\n this.lastPos = this.ctx.videoEl.currentTime;\n };\n\n private readonly onFullscreenChange = (): void => {\n const fs = this.ctx.isFullscreen();\n if (fs === this.wasFullscreen) return;\n this.wasFullscreen = fs;\n this.cancelDelayed(fs ? 'fullscreenExit' : 'fullscreen');\n // Tam ekran durumu değişti: o duruma özel gösterilen reklam kapanır.\n const mode = this.showing?.rule.mode;\n if ((mode === 'fullscreen' && !fs) || (mode === 'normal' && fs)) this.close('mode');\n this.trigger(fs ? 'fullscreen' : 'fullscreenExit');\n };\n\n private readonly onVideoAdStart = (e: Event): void => {\n if ((e as CustomEvent<{ linear?: boolean }>).detail?.linear === false) return;\n this.cancelDelayed();\n this.close('ad');\n };\n\n private isLive(): boolean {\n return this.ctx.videoEl.duration === Infinity;\n }\n\n private readonly onTimeUpdate = (): void => {\n const v = this.ctx.videoEl;\n const pos = v.currentTime;\n const prev = this.lastPos;\n this.lastPos = pos;\n const c = this.config;\n if (!c || v.paused || v.seeking || this.isLive() || this.ctx.isBlocked()) return;\n // Yalnızca doğal ilerleme — ileri sarınca aradaki anlar tetiklenmez.\n if (pos <= prev || pos - prev > MAX_NATURAL_STEP_S) return;\n const dur = v.duration;\n c.rules.forEach((rule, ri) =>\n rule.triggers.forEach((t, ti) => {\n if (t.type !== 'time' && t.type !== 'percent') return;\n for (const mark of t.at) {\n const at = t.type === 'percent' ? (Number.isFinite(dur) && dur > 0 ? (dur * mark) / 100 : NaN) : mark;\n const key = `${ri}:${ti}:${mark}`;\n if (prev < at && at <= pos && !this.fired.has(key)) {\n this.fired.add(key);\n this.showRule(ri, t.type);\n }\n }\n })\n );\n };\n\n /** Gerçek izleme süresi: interval kuralları (ve canlıda time kuralları) bununla sayılır. */\n private readonly tick = (): void => {\n const now = performance.now();\n const delta = Math.min(2000, Math.max(0, now - this.lastTick));\n this.lastTick = now;\n const v = this.ctx.videoEl;\n const c = this.config;\n if (!c || v.paused || v.ended || document.hidden || this.ctx.isBlocked() || this.showing?.filled) return;\n const before = this.watchedMs / 1000;\n this.watchedMs += delta;\n const after = this.watchedMs / 1000;\n c.rules.forEach((rule, ri) =>\n rule.triggers.forEach((t, ti) => {\n if (t.type === 'interval') {\n const first = t.startAfter ?? t.every;\n // Bu adımda geçilen eşik: first, first + every, first + 2·every…\n const n = Math.floor((after - first) / t.every);\n if (after >= first && first + n * t.every > before) this.showRule(ri, 'interval');\n } else if (t.type === 'time' && this.isLive()) {\n for (const at of t.at) {\n const key = `${ri}:${ti}:${at}:live`;\n if (before < at && at <= after && !this.fired.has(key)) {\n this.fired.add(key);\n this.showRule(ri, 'time');\n }\n }\n }\n })\n );\n };\n\n /** Olay tipindeki tetikleyicisi olan her kural (gecikmeliyse zamanlanır). */\n private trigger(type: TriggerType): void {\n const c = this.config;\n if (!c) return;\n c.rules.forEach((rule, ri) => {\n const t = rule.triggers.find((x) => x.type === type) as { delay?: number } | undefined;\n if (!t) return;\n const delay = (t.delay ?? 0) * 1000;\n if (delay <= 0) {\n this.showRule(ri, type);\n return;\n }\n const timer = setTimeout(() => {\n this.delayed = this.delayed.filter((d) => d.timer !== timer);\n this.showRule(ri, type);\n }, delay);\n this.delayed.push({ type, timer });\n });\n }\n\n private cancelDelayed(...types: TriggerType[]): void {\n this.delayed = this.delayed.filter((d) => {\n if (types.length && !types.includes(d.type)) return true;\n clearTimeout(d.timer);\n return false;\n });\n }\n\n // ── gösterim ──\n\n /** Koşullar uygunsa kuralın reklamını ister. Uygun değilse sessizce atlanır (sebep kayda düşer). */\n private showRule(index: number, trigger: TriggerType): void {\n const rule = this.config?.rules[index];\n if (!rule || this.destroyed) return;\n const v = this.ctx.videoEl;\n const fs = this.ctx.isFullscreen();\n const skip = (why: string): void => this.ctx.log({ message: `Ad trigger skipped (${why})`, details: { rule: rule.id, trigger } });\n // layout 'none' reklamının kapanışı kreatifte — yeni tetikleme onu değiştirir; diğerleri (ya da süren istek) bekletir.\n if (this.showing && !(this.showing.filled && this.showing.rule.layout === 'none')) return skip('another ad is showing');\n if (this.ctx.isBlocked()) return skip('video ad / intro screen');\n if (document.hidden) return skip('tab hidden');\n if (this.ctx.isNativeFullscreen()) return skip('native iOS fullscreen');\n if (rule.mode === 'fullscreen' && !fs) return skip('not fullscreen');\n if (rule.mode === 'normal' && fs) return skip('fullscreen');\n // Olay anındaki durum hâlâ geçerli mi (gecikmeli tetiklemeler için).\n if (trigger === 'pause' && (!v.paused || v.ended)) return;\n if (trigger === 'ended' && !v.ended) return;\n if (['time', 'percent', 'interval', 'start', 'resume'].includes(trigger) && v.paused) return;\n if (rule.minPlayerWidth && this.ctx.overlayEl.getBoundingClientRect().width < rule.minPlayerWidth) return skip('player too narrow');\n const now = Date.now();\n if (rule.maxShows && (this.shows.get(index) ?? 0) >= rule.maxShows) return skip('maxShows');\n if (rule.minGapSeconds && now - (this.lastShownAt.get(index) ?? 0) < rule.minGapSeconds * 1000) return skip('rule minGapSeconds');\n if (now - this.lastAnyAt < (this.config?.minGapSeconds ?? DEFAULT_GLOBAL_GAP_S) * 1000) return skip('minGapSeconds');\n if (this.showing) this.close('replaced');\n // İstek anı aralığa sayılır: boş dönen birim her saniye yeniden istenmesin.\n this.lastAnyAt = now;\n this.lastShownAt.set(index, now);\n void this.request(index, rule, trigger, fs);\n }\n\n private async request(index: number, rule: AdTriggerRule, trigger: TriggerType, fullscreen: boolean): Promise<void> {\n const id = ++this.seq;\n const slotName = `hp-adtrigger-${this.instance}`;\n const box = this.buildBox(rule, slotName);\n const adHost = document.createElement('div');\n adHost.id = `hp-adtrigger-${this.instance}-${id}`;\n adHost.slot = slotName;\n const s: Showing = { rule, trigger, box, adHost, slot: null, filled: false, pausedContent: false, timers: [] };\n this.showing = s;\n this.ctx.overlayEl.appendChild(box);\n this.ctx.hostEl.appendChild(adHost);\n const detail = { rule: rule.id, trigger, adUnitPath: rule.adUnitPath };\n const empty = (why: string): void => {\n if (this.showing !== s) return;\n this.ctx.log({ message: `Ad trigger: no ad (${why})`, details: { ...detail } });\n fire(rule.tracking?.empty);\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:adtriggerempty', { detail }));\n this.teardown(s);\n };\n // GPT hiç yüklenemez / yanıt vermezse (engelleyici, ağ) kutu asılı kalmasın.\n s.timers.push(setTimeout(() => !s.filled && empty('timeout'), this.options.renderTimeoutMs ?? DEFAULT_RENDER_TIMEOUT_MS));\n try {\n this.googletag ??= await loadGpt();\n } catch (err) {\n empty(String(err));\n return;\n }\n if (this.showing !== s) return;\n const gt = this.googletag;\n gt.cmd.push(() => {\n if (this.showing !== s) return;\n const slot = gt.defineOutOfPageSlot(rule.adUnitPath, adHost.id);\n if (!slot) {\n empty('slot could not be defined');\n return;\n }\n s.slot = slot;\n slot.addService(gt.pubads());\n // Öncelik (sonraki ezer): sayfa targeting → sayfa custParams → kural targeting → kural custParams → hp_*.\n const targeting: Record<string, string | string[]> = {\n ...parseCustParams(this.options.targeting),\n ...parseCustParams(this.options.custParams),\n ...rule.targeting,\n ...parseCustParams(rule.custParams),\n hp_trigger: trigger,\n hp_mode: fullscreen ? 'fullscreen' : 'normal',\n };\n if (rule.id) targeting.hp_rule = rule.id;\n for (const [k, val] of Object.entries(targeting)) slot.setTargeting(k, val);\n s.custParams = targeting;\n const onRender = (e: GptSlotRenderEndedEvent): void => {\n if (e.slot !== slot) return;\n gt.pubads().removeEventListener?.('slotRenderEnded', onRender);\n if (e.isEmpty) empty('empty');\n else this.reveal(index, s, fullscreen);\n };\n gt.pubads().addEventListener('slotRenderEnded', onRender);\n gt.enableServices();\n gt.display(adHost.id);\n // Sayfa disableInitialLoad kullanıyorsa display istek atmaz — elle refresh.\n if (gt.pubads().isInitialLoadDisabled()) gt.pubads().refresh([slot]);\n });\n }\n\n private buildBox(rule: AdTriggerRule, slotName: string): HTMLDivElement {\n const box = document.createElement('div');\n box.className = 'hp-adtrigger';\n box.setAttribute('part', 'ad-trigger');\n const bare = rule.layout === 'none';\n box.setAttribute('data-layout', rule.layout ?? 'none');\n box.toggleAttribute('data-backdrop', !!rule.backdrop);\n const frame = document.createElement('div');\n frame.className = 'hp-adtrigger-frame';\n if (rule.size && rule.layout !== 'full') {\n frame.style.setProperty('--hp-adtrigger-w', `${rule.size[0]}px`);\n frame.style.setProperty('--hp-adtrigger-h', `${rule.size[1]}px`);\n frame.setAttribute('data-sized', '');\n }\n // 'none': player yalnızca isteği atar ve kreatifi yerleştirir — etiket, kapat butonu, boyut kreatifin işi.\n if (rule.label !== false && !bare) {\n const label = document.createElement('span');\n label.className = 'hp-adtrigger-label';\n label.textContent = rule.label || this.ctx.i18n.adTriggerLabel;\n frame.appendChild(label);\n }\n const slot = document.createElement('slot');\n slot.name = slotName;\n frame.appendChild(slot);\n if (rule.closeButton !== false && !bare) {\n const close = document.createElement('button');\n close.type = 'button';\n close.className = 'hp-adtrigger-close';\n close.setAttribute('part', 'ad-trigger-close');\n close.setAttribute('aria-label', this.ctx.i18n.pauseAdClose);\n close.hidden = true;\n close.innerHTML =\n '<svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" aria-hidden=\"true\"><path d=\"M6 6l12 12M18 6L6 18\"/></svg>';\n close.addEventListener('click', () => this.close('user'));\n frame.appendChild(close);\n }\n box.appendChild(frame);\n // Reklama tıklama / dokunma videoyu oynat-duraklat yapmasın, kontrolleri açmasın.\n for (const t of ['pointerdown', 'click', 'dblclick'] as const) box.addEventListener(t, (e) => e.stopPropagation());\n return box;\n }\n\n private reveal(index: number, s: Showing, fullscreen: boolean): void {\n if (this.showing !== s) return;\n const { rule } = s;\n s.filled = true;\n this.shows.set(index, (this.shows.get(index) ?? 0) + 1);\n this.lastAnyAt = Date.now();\n // Kutu boyutlu ya da tam alan ise reklam iframe'i kutuyu doldursun (out-of-page kreatifleri kendi boyutunu vermez).\n if (rule.layout === 'full' || (rule.size && rule.layout !== 'none')) {\n const iframe = s.adHost.querySelector('iframe');\n if (iframe) Object.assign(iframe.style, { width: '100%', height: '100%', border: '0' });\n Object.assign(s.adHost.style, { width: '100%', height: '100%' });\n }\n s.box.setAttribute('data-open', '');\n const close = s.box.querySelector<HTMLButtonElement>('.hp-adtrigger-close');\n if (close) s.timers.push(setTimeout(() => (close.hidden = false), (rule.closeDelay ?? 0) * 1000));\n if (rule.duration) s.timers.push(setTimeout(() => this.close('timeout'), rule.duration * 1000));\n const v = this.ctx.videoEl;\n if (rule.pauseContent && !v.paused) {\n s.pausedContent = true;\n this.selfPause = true;\n v.pause();\n }\n fire(rule.tracking?.impression);\n this.ctx.hostEl.dispatchEvent(\n new CustomEvent('hp:adtriggershow', { detail: { rule: rule.id, trigger: s.trigger, adUnitPath: rule.adUnitPath, fullscreen, custParams: s.custParams ?? {} } })\n );\n }\n\n /** Gösterilen reklamı kapat (bekleyen istek varsa iptal). */\n close(reason: CloseReason): void {\n const s = this.showing;\n if (!s) return;\n const wasFilled = s.filled;\n this.teardown(s);\n if (!wasFilled) return;\n fire(s.rule.tracking?.close);\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:adtriggerclose', { detail: { rule: s.rule.id, reason } }));\n // Duraklattığımız içerik kaldığı yerden devam etsin (içerik değişmediyse / video reklamı başlamadıysa).\n if (s.pausedContent && reason !== 'content' && reason !== 'ad') void this.ctx.videoEl.play().catch(() => {});\n }\n\n private teardown(s: Showing): void {\n if (this.showing === s) this.showing = null;\n for (const t of s.timers) clearTimeout(t);\n if (s.slot && this.googletag) {\n try {\n this.googletag.destroySlots([s.slot]);\n } catch {\n /* zaten yok edildi */\n }\n }\n s.box.remove();\n s.adHost.remove();\n }\n\n destroy(): void {\n this.destroyed = true;\n this.cancelDelayed();\n this.close('content');\n clearInterval(this.tickTimer);\n if (this.refreshTimer) clearInterval(this.refreshTimer);\n const v = this.ctx.videoEl;\n v.removeEventListener('timeupdate', this.onTimeUpdate);\n v.removeEventListener('seeked', this.onSeeked);\n v.removeEventListener('playing', this.onPlaying);\n v.removeEventListener('pause', this.onPause);\n v.removeEventListener('ended', this.onEnded);\n v.removeEventListener('loadstart', this.onLoadStart);\n v.removeEventListener('webkitbeginfullscreen', this.onFullscreenChange);\n v.removeEventListener('webkitendfullscreen', this.onFullscreenChange);\n document.removeEventListener('fullscreenchange', this.onFullscreenChange);\n document.removeEventListener('webkitfullscreenchange', this.onFullscreenChange);\n this.ctx.hostEl.removeEventListener('hp:adstart', this.onVideoAdStart);\n }\n}\n","import { AdTriggers, normalizeAdTriggers, type AdTriggersContext } from './AdTriggers';\nimport type { AdTriggersOptions } from '../../types';\n\n/** Reklam tetikleyicisini kurar (kuralları `endpoint`'ten ya da `config`'ten alır). */\nexport function installAdTriggers(ctx: AdTriggersContext, options: AdTriggersOptions): AdTriggers {\n return new AdTriggers(ctx, options);\n}\n\nexport { AdTriggers, normalizeAdTriggers };\nexport type { AdTriggersContext };\n"],"names":["DEFAULT_TIMEOUT_MS","DEFAULT_RENDER_TIMEOUT_MS","DEFAULT_GLOBAL_GAP_S","LAYOUTS","TRIGGER_TYPES","MAX_NATURAL_STEP_S","instanceCount","safeUrl","value","u","num","n","min","max","prim","v","parseCustParams","raw","entries","k","out","list","x","one","normalizeTrigger","t","type","at","every","normalizeAdTriggers","r","now","from","until","urls","rules","triggers","size","layout","_a","_b","_c","fire","img","AdTriggers","ctx","options","__publicField","key","fs","mode","pos","prev","c","dur","rule","ri","ti","mark","delta","before","after","first","changed","refreshChanged","s","seq","ctrl","timer","url","res","json","err","config","delay","types","d","index","trigger","skip","why","fullscreen","id","slotName","box","adHost","detail","empty","loadGpt","gt","slot","targeting","val","onRender","e","bare","frame","label","close","iframe","reason","wasFilled","installAdTriggers"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-Ca8hocby.js","sources":["../../src/plugins/gesture/GestureControls.ts","../../src/plugins/gesture/index.ts"],"sourcesContent":["import type { GestureOptions } from '../../types';\n\nexport interface GesturePlayerContext {\n videoEl: HTMLVideoElement;\n /** Basılı tutma göstergesinin (hız/sarma overlay'i) ekleneceği katman. */\n overlayContainerEl: HTMLElement;\n isAdActive(): boolean;\n}\n\nfunction isMobileDevice(): boolean {\n if (typeof navigator === 'undefined') return false;\n return /Android|iPhone|iPad|iPod/i.test(navigator.userAgent);\n}\n\n/** Basılı tutma: mobilde adım adım ileri sarma, masaüstünde playbackRate hızlandırma. */\nexport class GestureControls {\n private readonly options: Required<GestureOptions>;\n private readonly overlayEl: HTMLElement;\n\n private isHolding = false;\n private holdTimeout: ReturnType<typeof setTimeout> | null = null;\n private holdInterval: ReturnType<typeof setInterval> | null = null;\n private wasPaused = false;\n\n constructor(\n private readonly ctx: GesturePlayerContext,\n options: GestureOptions = {}\n ) {\n this.options = {\n holdRate: options.holdRate ?? 2,\n holdIntervalMs: options.holdIntervalMs ?? 200,\n holdDelayMs: options.holdDelayMs ?? 300,\n };\n\n this.overlayEl = document.createElement('div');\n this.overlayEl.setAttribute('part', 'gesture-overlay');\n this.overlayEl.className =\n 'hp:hidden hp:absolute hp:inset-0 hp:z-20 hp:items-center hp:justify-center hp:gap-2 ' +\n 'hp:bg-black/30 hp:text-white hp:text-xl hp:font-semibold hp:pointer-events-none';\n ctx.overlayContainerEl.appendChild(this.overlayEl);\n\n ctx.videoEl.addEventListener('touchstart', this.onPressStart, { passive: false });\n ctx.videoEl.addEventListener('touchend', this.onPressEnd);\n ctx.videoEl.addEventListener('touchcancel', this.onPressLeave);\n ctx.videoEl.addEventListener('mousedown', this.onPressStart);\n ctx.videoEl.addEventListener('mouseup', this.onPressEnd);\n ctx.videoEl.addEventListener('mouseleave', this.onPressLeave);\n }\n\n /** HopePlayerElement'in kendi \"ekrana tıkla → oynat/duraklat\" tetikleyicisinin bir hold sırasında devre dışı kalması için — tek doğruluk kaynağı burası, ayrı bir zamanlayıcı tekrarlanmıyor. */\n isCurrentlyHolding(): boolean {\n return this.isHolding;\n }\n\n destroy(): void {\n this.ctx.videoEl.removeEventListener('touchstart', this.onPressStart);\n this.ctx.videoEl.removeEventListener('touchend', this.onPressEnd);\n this.ctx.videoEl.removeEventListener('touchcancel', this.onPressLeave);\n this.ctx.videoEl.removeEventListener('mousedown', this.onPressStart);\n this.ctx.videoEl.removeEventListener('mouseup', this.onPressEnd);\n this.ctx.videoEl.removeEventListener('mouseleave', this.onPressLeave);\n if (this.holdTimeout) clearTimeout(this.holdTimeout);\n if (this.holdInterval) clearInterval(this.holdInterval);\n this.overlayEl.remove();\n }\n\n private readonly onPressStart = (e: Event): void => {\n if (this.ctx.isAdActive()) return;\n if (this.ctx.videoEl.ended) return;\n this.wasPaused = this.ctx.videoEl.paused;\n\n this.holdTimeout = setTimeout(() => this.startHold(), this.options.holdDelayMs);\n e.preventDefault();\n };\n\n private startHold(): void {\n if (this.isHolding) return;\n this.isHolding = true;\n\n if (isMobileDevice()) {\n const step = (this.options.holdRate * this.options.holdIntervalMs) / 1000;\n this.holdInterval = setInterval(() => {\n const video = this.ctx.videoEl;\n video.currentTime = Math.min(video.duration || video.currentTime + step, video.currentTime + step);\n }, this.options.holdIntervalMs);\n } else {\n this.ctx.videoEl.playbackRate = this.options.holdRate;\n }\n\n this.showOverlay(`${this.options.holdRate}x »`);\n if (this.ctx.videoEl.paused) void this.ctx.videoEl.play().catch(() => {});\n }\n\n private readonly onPressEnd = (): void => {\n this.endHold();\n };\n\n private readonly onPressLeave = (): void => {\n this.endHold();\n };\n\n private endHold(): void {\n if (this.holdTimeout) {\n clearTimeout(this.holdTimeout);\n this.holdTimeout = null;\n }\n\n // Kısa dokunuş: oynat/duraklat HopePlayerElement'in kendi dinleyicisinde.\n if (!this.isHolding) return;\n\n this.isHolding = false;\n this.ctx.videoEl.playbackRate = 1;\n if (this.holdInterval) {\n clearInterval(this.holdInterval);\n this.holdInterval = null;\n }\n this.hideOverlay();\n\n if (this.wasPaused) this.ctx.videoEl.pause();\n }\n\n private showOverlay(text: string): void {\n this.overlayEl.textContent = text;\n this.overlayEl.classList.remove('hp:hidden');\n this.overlayEl.classList.add('hp:flex');\n }\n\n private hideOverlay(): void {\n this.overlayEl.classList.add('hp:hidden');\n this.overlayEl.classList.remove('hp:flex');\n }\n}\n","import { GestureControls, type GesturePlayerContext } from './GestureControls';\nimport type { GestureOptions } from '../../types';\n\nexport function installGesture(ctx: GesturePlayerContext, options: GestureOptions): GestureControls {\n return new GestureControls(ctx, options);\n}\n\nexport { GestureControls };\nexport type { GesturePlayerContext };\n"],"names":["isMobileDevice","GestureControls","ctx","options","__publicField","step","video","text","installGesture"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-Ch3ep-eJ.js","sources":["../../src/plugins/sponsorship/SponsorshipLayer.ts","../../src/plugins/sponsorship/index.ts"],"sourcesContent":["import type { SponsorshipConfig, SponsorshipOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\n\nexport interface SponsorshipContext {\n hostEl: HTMLElement;\n videoEl: HTMLVideoElement;\n /** Logo ve giriş kartının ekleneceği alan (video alanı). */\n overlayEl: HTMLElement;\n i18n: HopeLocaleStrings;\n log(entry: { message: string; fatal?: boolean; details?: Record<string, string | number | boolean | undefined> }): void;\n}\n\nconst DEFAULT_TIMEOUT_MS = 5000;\nconst DEFAULT_LOGO_WIDTH = 96;\nconst DEFAULT_INTRO_MS = 3500;\n/** API'den gelen tema değerleri → player'ın CSS değişkenleri. */\nconst THEME_TOKENS: Record<keyof NonNullable<SponsorshipConfig['theme']>, string> = {\n accent: '--hp-color-accent',\n onAccent: '--hp-color-on-accent',\n surface: '--hp-color-surface',\n onSurface: '--hp-color-on-surface',\n};\nconst POSITIONS = ['top-left', 'top-right', 'bottom-left', 'bottom-right'] as const;\n\n/** Yalnızca http(s) ya da göreli adresler — `javascript:` / `data:` gibi şemalar reddedilir. */\nfunction safeUrl(value: unknown): string | null {\n if (typeof value !== 'string' || !value.trim()) return null;\n try {\n const u = new URL(value, document.baseURI);\n return u.protocol === 'https:' || u.protocol === 'http:' ? u.href : null;\n } catch {\n return null;\n }\n}\n\nfunction safeColor(value: unknown): string | null {\n return typeof value === 'string' && value.length < 64 && CSS.supports('color', value) ? value : null;\n}\n\nfunction clamp(n: unknown, min: number, max: number, fallback: number): number {\n return typeof n === 'number' && Number.isFinite(n) ? Math.min(max, Math.max(min, n)) : fallback;\n}\n\n/** API yanıtını doğrular, geçersiz alanları atar; katman kapalıysa null. */\nexport function normalizeSponsorship(raw: unknown): SponsorshipConfig | null {\n if (!raw || typeof raw !== 'object') return null;\n const r = raw as Partial<SponsorshipConfig>;\n if (r.active !== true || !r.sponsor || typeof r.sponsor.name !== 'string' || !r.sponsor.name.trim()) return null;\n const now = Date.now();\n const from = r.validFrom ? Date.parse(r.validFrom) : NaN;\n const until = r.validUntil ? Date.parse(r.validUntil) : NaN;\n if ((Number.isFinite(from) && now < from) || (Number.isFinite(until) && now > until)) return null;\n const theme: NonNullable<SponsorshipConfig['theme']> = {};\n for (const key of Object.keys(THEME_TOKENS) as Array<keyof typeof THEME_TOKENS>) {\n const c = safeColor(r.theme?.[key]);\n if (c) theme[key] = c;\n }\n const urls = (list: unknown): string[] => (Array.isArray(list) ? list.map(safeUrl).filter((u): u is string => !!u).slice(0, 10) : []);\n return {\n active: true,\n id: typeof r.id === 'string' ? r.id.slice(0, 120) : undefined,\n sponsor: {\n name: r.sponsor.name.slice(0, 80),\n logo: safeUrl(r.sponsor.logo) ?? undefined,\n url: safeUrl(r.sponsor.url) ?? undefined,\n },\n theme,\n logo: {\n position: POSITIONS.includes(r.logo?.position as (typeof POSITIONS)[number]) ? r.logo!.position : 'top-left',\n width: clamp(r.logo?.width, 32, 240, DEFAULT_LOGO_WIDTH),\n opacity: clamp(r.logo?.opacity, 0.2, 1, 0.9),\n label: typeof r.logo?.label === 'string' ? r.logo.label.slice(0, 40) : undefined,\n },\n intro: r.intro\n ? {\n text: typeof r.intro.text === 'string' ? r.intro.text.slice(0, 120) : undefined,\n durationMs: clamp(r.intro.durationMs, 1000, 15000, DEFAULT_INTRO_MS),\n repeatMinutes: typeof r.intro.repeatMinutes === 'number' && r.intro.repeatMinutes > 0 ? Math.min(240, Math.max(1, r.intro.repeatMinutes)) : undefined,\n maxShows: typeof r.intro.maxShows === 'number' && r.intro.maxShows >= 1 ? Math.min(100, Math.floor(r.intro.maxShows)) : undefined,\n }\n : undefined,\n tracking: { impression: urls(r.tracking?.impression), click: urls(r.tracking?.click), intro: urls(r.tracking?.intro) },\n };\n}\n\n/** Takip pikseli: yanıtı beklenmeyen GET (img beacon). */\nfunction fire(urls: string[] | undefined): void {\n for (const u of urls ?? []) {\n const img = new Image();\n img.referrerPolicy = 'no-referrer-when-downgrade';\n img.src = u;\n }\n}\n\n/**\n * Sponsorluk katmanı: `endpoint`'ten JSON çeker (SponsorshipConfig), player renklerini değiştirir, köşeye logo koyar,\n * oynatma başlarken \"X sunar\" kartını gösterir. Canlıda `refreshSeconds` ile kampanya değişimi izlenir. API hatasında\n * son geçerli ayar korunur; hiç alınamadıysa katman kapalı kalır — player normal çalışır.\n */\nexport class SponsorshipLayer {\n private options: SponsorshipOptions;\n private config: SponsorshipConfig | null = null;\n private logoEl: HTMLAnchorElement | HTMLDivElement | null = null;\n private introEl: HTMLDivElement | null = null;\n private introTimer: ReturnType<typeof setTimeout> | null = null;\n private refreshTimer: ReturnType<typeof setInterval> | null = null;\n /** Player boyutu / kontrol düzeni değişince logo kontrollerin üstüne binmesin diye yeniden konumlanır. */\n private readonly resizeObserver: ResizeObserver | null;\n /** Uygulanan tema değişkenlerinin önceki satır içi değerleri — katman kalkınca geri yüklenir. */\n private previousTokens = new Map<string, string>();\n /** Gösterim pikseli kampanya başına bir kez. */\n private impressed = new Set<string>();\n /** Kampanya başına giriş gösterim sayısı. */\n private introCount = new Map<string, number>();\n /** Son girişten bu yana gerçek izleme süresi (ms) — intro.repeatMinutes için. */\n private watchedSinceIntro = 0;\n private lastTick = 0;\n private readonly tickTimer: ReturnType<typeof setInterval>;\n private destroyed = false;\n private requestSeq = 0;\n\n constructor(\n private readonly ctx: SponsorshipContext,\n options: SponsorshipOptions\n ) {\n this.options = options;\n ctx.videoEl.addEventListener('play', this.onPlay);\n ctx.hostEl.addEventListener('hp:adstart', this.onAdStart);\n ctx.hostEl.addEventListener('hp:adend', this.onAdEnd);\n this.lastTick = performance.now();\n this.tickTimer = setInterval(this.tick, 1000);\n this.resizeObserver = typeof ResizeObserver !== 'undefined' ? new ResizeObserver(() => this.positionLogo()) : null;\n this.resizeObserver?.observe(ctx.overlayEl);\n const topBar = ctx.overlayEl.querySelector('.hp-top-bar');\n if (topBar) this.resizeObserver?.observe(topBar);\n void this.load();\n this.scheduleRefresh();\n }\n\n update(options: SponsorshipOptions): void {\n const changed = options.endpoint !== this.options.endpoint || JSON.stringify(options.params) !== JSON.stringify(this.options.params);\n const refreshChanged = options.refreshSeconds !== this.options.refreshSeconds;\n this.options = options;\n if (changed) void this.load();\n if (refreshChanged) this.scheduleRefresh();\n }\n\n /** Şu an uygulanan kampanya (yoksa null). */\n get current(): SponsorshipConfig | null {\n return this.config;\n }\n\n private scheduleRefresh(): void {\n if (this.refreshTimer) clearInterval(this.refreshTimer);\n this.refreshTimer = null;\n const s = this.options.refreshSeconds;\n if (typeof s === 'number' && s >= 10) this.refreshTimer = setInterval(() => void this.load(), s * 1000);\n }\n\n private buildUrl(): string {\n const u = new URL(this.options.endpoint, document.baseURI);\n for (const [k, v] of Object.entries(this.options.params ?? {})) u.searchParams.set(k, v);\n return u.href;\n }\n\n private async load(): Promise<void> {\n const seq = ++this.requestSeq;\n const ctrl = typeof AbortController !== 'undefined' ? new AbortController() : null;\n const timer = setTimeout(() => ctrl?.abort(), this.options.timeoutMs ?? DEFAULT_TIMEOUT_MS);\n let url = '';\n try {\n url = this.buildUrl();\n const res = await fetch(url, { ...this.options.fetchInit, signal: ctrl?.signal });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const json: unknown = await res.json();\n if (this.destroyed || seq !== this.requestSeq) return; // daha yeni bir istek var\n this.apply(normalizeSponsorship(json));\n } catch (err) {\n if (this.destroyed || seq !== this.requestSeq) return;\n // Son geçerli kampanya korunur — geçici API hatası katmanı söndürmesin.\n this.ctx.log({ message: `Sponsorship API failed: ${String(err)}`, details: { url } });\n } finally {\n clearTimeout(timer);\n }\n }\n\n private apply(config: SponsorshipConfig | null): void {\n const prevKey = this.key(this.config);\n this.config = config;\n this.applyTheme(config?.theme ?? null);\n this.renderLogo();\n this.ctx.hostEl.toggleAttribute('data-sponsored', !!config);\n if (this.key(config) !== prevKey) {\n this.watchedSinceIntro = 0;\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:sponsorship', { detail: { config } }));\n // Yeni kampanya oynarken geldiyse (canlı yenileme) girişi hemen göster.\n if (config && !this.ctx.videoEl.paused) this.onPlay();\n }\n }\n\n private key(c: SponsorshipConfig | null): string {\n return c ? c.id || c.sponsor.name : '';\n }\n\n private applyTheme(theme: SponsorshipConfig['theme'] | null): void {\n const style = this.ctx.hostEl.style;\n // Önce önceki kampanyanın değerlerini geri al.\n for (const [prop, value] of this.previousTokens) {\n if (value) style.setProperty(prop, value);\n else style.removeProperty(prop);\n }\n this.previousTokens.clear();\n if (!theme) return;\n for (const [key, prop] of Object.entries(THEME_TOKENS) as Array<[keyof typeof THEME_TOKENS, string]>) {\n const value = theme[key];\n if (!value) continue;\n this.previousTokens.set(prop, style.getPropertyValue(prop));\n style.setProperty(prop, value);\n }\n }\n\n private renderLogo(): void {\n this.logoEl?.remove();\n this.logoEl = null;\n const c = this.config;\n if (!c || (!c.sponsor.logo && !c.logo?.label)) return;\n const el = c.sponsor.url ? document.createElement('a') : document.createElement('div');\n el.className = 'hp-sponsor-logo';\n el.setAttribute('part', 'sponsor-logo');\n el.setAttribute('data-position', c.logo?.position ?? 'top-left');\n el.style.setProperty('--hp-sponsor-logo-w', `${c.logo?.width ?? DEFAULT_LOGO_WIDTH}px`);\n el.style.opacity = String(c.logo?.opacity ?? 0.9);\n if (el instanceof HTMLAnchorElement) {\n el.href = c.sponsor.url!;\n el.target = '_blank';\n el.rel = 'noopener sponsored';\n el.addEventListener('click', (e) => {\n e.stopPropagation();\n fire(c.tracking?.click);\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:sponsorclick', { detail: { id: c.id, sponsor: c.sponsor.name } }));\n });\n }\n el.setAttribute('aria-label', c.sponsor.name);\n if (c.sponsor.logo) {\n const img = document.createElement('img');\n img.src = c.sponsor.logo;\n img.alt = c.sponsor.name;\n img.decoding = 'async';\n img.addEventListener('error', () => img.remove());\n el.appendChild(img);\n }\n // Etiket logonun altında, ortalı.\n if (c.logo?.label) {\n const label = document.createElement('span');\n label.className = 'hp-sponsor-label';\n label.textContent = c.logo.label;\n el.appendChild(label);\n }\n for (const t of ['pointerdown', 'dblclick'] as const) el.addEventListener(t, (e) => e.stopPropagation());\n this.ctx.overlayEl.appendChild(el);\n this.logoEl = el;\n this.positionLogo();\n }\n\n /**\n * Logo kontrollerin üstüne binmesin: sağ üstte (dar player'da ayarlar / PiP oraya taşınır) üst çubuğun soluna,\n * altta seek bar'ın hemen üstüne yerleşir. Dar player'da logo en fazla 48 px.\n */\n private positionLogo(): void {\n const el = this.logoEl;\n if (!el) return;\n const area = this.ctx.overlayEl;\n const compact = area.hasAttribute('data-compact');\n const position = el.getAttribute('data-position');\n // Kontroller görünürken kaçınılacak mesafe CSS değişkenine yazılır; kontroller gizliyken CSS logoyu köşeye\n // alır (bkz. :host([data-chrome-hidden])) ve geçiş animasyonlu olur.\n el.style.removeProperty('--hp-sponsor-avoid-right');\n el.style.removeProperty('--hp-sponsor-avoid-bottom');\n el.toggleAttribute('data-compact', compact);\n const a = area.getBoundingClientRect();\n if (position === 'top-right') {\n const bar = area.querySelector('.hp-top-bar')?.getBoundingClientRect();\n if (bar && bar.width > 0) el.style.setProperty('--hp-sponsor-avoid-right', `${Math.round(a.right - bar.left + 8)}px`);\n } else if (position === 'bottom-left' || position === 'bottom-right') {\n const seek = area.querySelector('[part=\"seek-bar\"]')?.getBoundingClientRect();\n if (seek && seek.height > 0) el.style.setProperty('--hp-sponsor-avoid-bottom', `${Math.round(a.bottom - seek.top + 6)}px`);\n }\n }\n\n /** Oynatma başladı: kampanya başına bir kez gösterim pikseli + \"X sunar\" kartı. */\n private readonly onPlay = (): void => {\n const c = this.config;\n if (!c) return;\n const key = this.key(c);\n if (!this.impressed.has(key)) {\n this.impressed.add(key);\n fire(c.tracking?.impression);\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:sponsorimpression', { detail: { id: c.id, sponsor: c.sponsor.name } }));\n }\n if (c.intro && !this.introCount.has(key)) this.showIntro(c);\n };\n\n /**\n * intro.repeatMinutes: yalnızca gerçekten izlenirken sayar (oynuyor, sekme önde, reklam yok); süre dolunca giriş\n * tekrar gösterilir — maxShows'a kadar.\n */\n private readonly tick = (): void => {\n const now = performance.now();\n // Sekme uyuyunca setInterval seyrekleşir — tek seferde en fazla 2 sn sayılır.\n const delta = Math.min(2000, Math.max(0, now - this.lastTick));\n this.lastTick = now;\n const c = this.config;\n const repeat = c?.intro?.repeatMinutes;\n if (!c || !repeat) return;\n const watching =\n !this.ctx.videoEl.paused && !this.ctx.videoEl.ended && !document.hidden && !this.ctx.hostEl.hasAttribute('data-sponsor-hidden');\n if (!watching || !this.introCount.has(this.key(c))) return;\n this.watchedSinceIntro += delta;\n if (this.watchedSinceIntro < repeat * 60_000) return;\n const max = c.intro?.maxShows;\n if (max && (this.introCount.get(this.key(c)) ?? 0) >= max) return;\n this.showIntro(c);\n };\n\n private showIntro(c: SponsorshipConfig): void {\n const key = this.key(c);\n const count = (this.introCount.get(key) ?? 0) + 1;\n this.introCount.set(key, count);\n this.watchedSinceIntro = 0;\n fire(c.tracking?.intro);\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:sponsorintro', { detail: { id: c.id, sponsor: c.sponsor.name, count } }));\n if (this.introTimer) clearTimeout(this.introTimer);\n this.introEl?.remove();\n const el = document.createElement('div');\n el.className = 'hp-sponsor-intro';\n el.setAttribute('part', 'sponsor-intro');\n el.setAttribute('role', 'status');\n if (c.sponsor.logo) {\n const img = document.createElement('img');\n img.src = c.sponsor.logo;\n img.alt = '';\n img.addEventListener('error', () => img.remove());\n el.appendChild(img);\n }\n const text = document.createElement('span');\n text.textContent = c.intro?.text || this.ctx.i18n.sponsorPresents.replace('{name}', c.sponsor.name);\n el.appendChild(text);\n this.ctx.overlayEl.appendChild(el);\n this.introEl = el;\n // Giriş kartı sponsoru zaten gösteriyor — kart görünürken köşe logosu gizli (küçük player'da üst üste binmesin).\n this.ctx.hostEl.setAttribute('data-sponsor-intro', '');\n this.introTimer = setTimeout(() => {\n el.setAttribute('data-leaving', '');\n this.ctx.hostEl.removeAttribute('data-sponsor-intro');\n this.introTimer = setTimeout(() => {\n el.remove();\n if (this.introEl === el) this.introEl = null;\n }, 400);\n }, c.intro?.durationMs ?? DEFAULT_INTRO_MS);\n }\n\n /** Lineer reklam sırasında logo / giriş gizlenir (reklamın üstüne binmesin). */\n private readonly onAdStart = (e: Event): void => {\n if ((e as CustomEvent<{ linear?: boolean }>).detail?.linear === false) return;\n this.ctx.hostEl.setAttribute('data-sponsor-hidden', '');\n };\n\n private readonly onAdEnd = (e: Event): void => {\n if ((e as CustomEvent<{ linear?: boolean }>).detail?.linear === false) return;\n this.ctx.hostEl.removeAttribute('data-sponsor-hidden');\n };\n\n destroy(): void {\n this.destroyed = true;\n clearInterval(this.tickTimer);\n this.resizeObserver?.disconnect();\n if (this.refreshTimer) clearInterval(this.refreshTimer);\n if (this.introTimer) clearTimeout(this.introTimer);\n this.ctx.videoEl.removeEventListener('play', this.onPlay);\n this.ctx.hostEl.removeEventListener('hp:adstart', this.onAdStart);\n this.ctx.hostEl.removeEventListener('hp:adend', this.onAdEnd);\n this.applyTheme(null);\n this.logoEl?.remove();\n this.introEl?.remove();\n this.ctx.hostEl.removeAttribute('data-sponsored');\n this.ctx.hostEl.removeAttribute('data-sponsor-hidden');\n this.ctx.hostEl.removeAttribute('data-sponsor-intro');\n }\n}\n","import { SponsorshipLayer, normalizeSponsorship, type SponsorshipContext } from './SponsorshipLayer';\nimport type { SponsorshipOptions } from '../../types';\n\n/** Sponsorluk katmanını kurar (ayarları `endpoint`'ten alır). */\nexport function installSponsorship(ctx: SponsorshipContext, options: SponsorshipOptions): SponsorshipLayer {\n return new SponsorshipLayer(ctx, options);\n}\n\nexport { SponsorshipLayer, normalizeSponsorship };\nexport type { SponsorshipContext };\n"],"names":["THEME_TOKENS","POSITIONS","safeUrl","value","u","safeColor","clamp","n","min","max","fallback","normalizeSponsorship","raw","_a","_b","_c","_d","_e","_f","_g","_h","r","now","from","until","theme","key","c","urls","list","fire","img","SponsorshipLayer","ctx","options","__publicField","delta","repeat","e","topBar","changed","refreshChanged","s","k","v","seq","ctrl","timer","url","res","json","err","config","prevKey","style","prop","el","label","t","area","compact","position","a","bar","seek","count","text","installSponsorship"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-D3Z7ZDLJ.js","sources":["../../src/plugins/playlist/PlaylistRunner.ts","../../src/plugins/playlist/index.ts"],"sourcesContent":["import { createIcon } from '../../icons/Icon';\nimport type { PlayableItem, PlaylistOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\n\nexport interface PlaylistPlayerContext {\n videoEl: HTMLVideoElement;\n hostEl: HTMLElement;\n /** Liste UI'ının monte edileceği, shadow root içindeki panel. */\n panelEl: HTMLElement;\n loadSource(src: string, type?: string): Promise<void>;\n setPoster(url: string): void;\n /** AdsController varsa retry/VMAP durumunu sıfırlayıp item'ın (varsa) kendi adTagPreroll'üyle yeniden reklam ister — yoksa no-op. */\n requestFreshAd(prerollTag?: string): void;\n i18n: HopeLocaleStrings;\n}\n\ntype SourceMode = 'hls' | 'mp4';\n\ninterface Attempt {\n id: number;\n index: number;\n mode: SourceMode;\n tried: Set<SourceMode>;\n mp4Index: number;\n}\n\nconst DEFAULTS: Required<Omit<PlaylistOptions, 'items' | 'adTagPreroll' | 'ui'>> = {\n startMode: 'after_current',\n startIndex: 0,\n loop: false,\n autoplayNext: true,\n preferHls: true,\n adsOnItemChange: true,\n};\n\n/** Tek player üzerinde sıralı oynatma listesi (startMode, loop, hata fallback zinciri). */\nexport class PlaylistRunner {\n private readonly options: Required<Omit<PlaylistOptions, 'items' | 'adTagPreroll' | 'ui'>>;\n private readonly items: PlayableItem[];\n\n private index: number;\n private destroyed = false;\n private switching = false;\n private playlistActive = false;\n private startPendingAfterCurrent = false;\n private attemptId = 0;\n private attempt: Attempt | null = null;\n private lastErrorAt = 0;\n private lastAdsIndex: number | null = null;\n private lastDispatchedIndex: number | null = null;\n private userHasStartedPlayback = false;\n\n private readonly ui: {\n root: HTMLElement;\n titleEl: HTMLElement;\n listEl: HTMLElement;\n prevBtn: HTMLButtonElement;\n nextBtn: HTMLButtonElement;\n itemEls: Array<{ li: HTMLElement; titleRow: HTMLElement; progressFill: HTMLElement | null; timeEl: HTMLElement | null }>;\n };\n\n constructor(\n private readonly ctx: PlaylistPlayerContext,\n private readonly rawOptions: PlaylistOptions\n ) {\n this.options = { ...DEFAULTS, ...rawOptions };\n this.items = Array.isArray(rawOptions.items) ? rawOptions.items : [];\n this.index = this.clampIndex(this.options.startIndex);\n\n this.ui = this.buildUi();\n this.bindPlayerEvents();\n this.init();\n }\n\n // ── lifecycle ──\n\n private init(): void {\n if (!this.items.length) return;\n\n if (this.options.startMode === 'after_current') {\n this.startPendingAfterCurrent = true;\n this.playlistActive = false;\n this.setActive(this.index);\n return;\n }\n\n this.playlistActive = true;\n void this.loadAndPlay(this.index, { userInitiated: false, isPlaylistStart: true });\n }\n\n refreshLabels(): void {\n this.ui.titleEl.textContent = this.playlistTitleText();\n this.ui.prevBtn.setAttribute('aria-label', this.ctx.i18n.playlistPrev);\n this.ui.nextBtn.setAttribute('aria-label', this.ctx.i18n.playlistNext);\n this.ui.itemEls.forEach((entry, idx) => {\n const item = this.items[idx];\n if (item && !item.title) entry.titleRow.textContent = this.ctx.i18n.videoFallbackTitle(idx);\n });\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.ctx.videoEl.removeEventListener('ended', this.onEnded);\n this.ctx.videoEl.removeEventListener('error', this.onError);\n this.ctx.videoEl.removeEventListener('play', this.onUserPlay);\n this.ui.root.remove();\n }\n\n // ── public api ──\n\n start(opts: { index?: number } = {}): void {\n if (this.destroyed || !this.items.length) return;\n this.startPendingAfterCurrent = false;\n this.playlistActive = true;\n this.index = this.clampIndex(opts.index ?? this.index);\n this.setActive(this.index);\n void this.loadAndPlay(this.index, { userInitiated: false, isPlaylistStart: true });\n }\n\n next(): void {\n if (this.destroyed || !this.items.length) return;\n if (!this.playlistActive) return this.start({ index: this.index });\n\n if (this.index < this.items.length - 1) this.index++;\n else if (this.options.loop) this.index = 0;\n else return;\n\n this.setActive(this.index);\n void this.loadAndPlay(this.index, { userInitiated: true });\n }\n\n prev(): void {\n if (this.destroyed || !this.items.length) return;\n if (!this.playlistActive) return this.start({ index: this.index });\n if (this.index === 0) return;\n this.index--;\n this.setActive(this.index);\n void this.loadAndPlay(this.index, { userInitiated: true });\n }\n\n setIndex(i: number): void {\n if (this.destroyed || !this.items.length) return;\n this.index = this.clampIndex(i);\n this.setActive(this.index);\n if (!this.playlistActive) return this.start({ index: this.index });\n void this.loadAndPlay(this.index, { userInitiated: true });\n }\n\n getIndex(): number {\n return this.index;\n }\n\n isActive(): boolean {\n return this.playlistActive;\n }\n\n // ── player events ──\n\n private bindPlayerEvents(): void {\n this.ctx.videoEl.addEventListener('ended', this.onEnded);\n this.ctx.videoEl.addEventListener('error', this.onError);\n this.ctx.videoEl.addEventListener('play', this.onUserPlay);\n this.ctx.videoEl.addEventListener('timeupdate', this.onTimeUpdate);\n }\n\n private readonly onUserPlay = (): void => {\n this.userHasStartedPlayback = true;\n };\n\n private readonly onEnded = (): void => {\n if (this.startPendingAfterCurrent && !this.playlistActive) {\n this.startPendingAfterCurrent = false;\n this.playlistActive = true;\n this.setActive(this.index);\n void this.loadAndPlay(this.index, { userInitiated: true, isPlaylistStart: true });\n return;\n }\n if (this.playlistActive) this.next();\n };\n\n private readonly onError = (): void => {\n if (this.destroyed || !this.playlistActive) return;\n const now = Date.now();\n if (now - this.lastErrorAt < 200) return;\n this.lastErrorAt = now;\n void this.fallbackOrSkip();\n };\n\n private readonly onTimeUpdate = (): void => {\n this.updateProgress();\n };\n\n // ── core load ──\n\n private async loadAndPlay(\n i: number,\n opts: { userInitiated?: boolean; forceMode?: SourceMode | null; forceMp4Index?: number | null; isFallback?: boolean; isPlaylistStart?: boolean } = {}\n ): Promise<void> {\n if (this.destroyed || this.switching || !this.playlistActive) return;\n this.switching = true;\n\n const item = this.items[i];\n if (!item) {\n this.switching = false;\n return;\n }\n const attemptId = ++this.attemptId;\n const mode = opts.forceMode ?? this.resolveMode(item);\n\n let tried = new Set<SourceMode>([mode]);\n let mp4Index = opts.forceMp4Index ?? 0;\n if (opts.isFallback && this.attempt?.index === i && this.attempt?.tried) {\n tried = new Set(this.attempt.tried);\n tried.add(mode);\n if (opts.forceMp4Index == null) mp4Index = this.attempt.mp4Index ?? 0;\n }\n this.attempt = { id: attemptId, index: i, mode, tried, mp4Index };\n\n try {\n const payload = this.buildPayload(item, mode, mp4Index);\n if (!payload) throw new Error('No playable source');\n\n this.setActive(i);\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.maybeRequestAds(i, item, !!opts.isFallback);\n\n if (this.shouldAutoPlay(!!opts.userInitiated)) {\n try {\n await this.ctx.videoEl.play();\n } catch {\n /* autoplay engellendi — sessizce geç */\n }\n }\n this.updateProgress();\n } finally {\n this.switching = false;\n }\n }\n\n private async fallbackOrSkip(): Promise<void> {\n if (this.destroyed || !this.attempt) return;\n const item = this.items[this.attempt.index];\n if (!item) return;\n\n if (this.attempt.mode === 'mp4') {\n const mp4List = (item.mp4 || []).filter((v) => v?.src);\n const nextMp4 = (this.attempt.mp4Index ?? 0) + 1;\n if (nextMp4 < mp4List.length) {\n await this.loadAndPlay(this.attempt.index, { forceMode: 'mp4', forceMp4Index: nextMp4, isFallback: true });\n return;\n }\n }\n\n const otherMode: SourceMode = this.attempt.mode === 'hls' ? 'mp4' : 'hls';\n if (this.hasMode(item, otherMode) && !this.attempt.tried.has(otherMode)) {\n await this.loadAndPlay(this.attempt.index, { forceMode: otherMode, isFallback: true });\n return;\n }\n\n this.next();\n }\n\n // ── ads ──\n\n private maybeRequestAds(index: number, item: PlayableItem, _isFallback: boolean): void {\n if (this.lastAdsIndex === index) return;\n this.lastAdsIndex = index;\n this.ctx.requestFreshAd(item.adTagPreroll || this.rawOptions.adTagPreroll);\n }\n\n // ── sources ──\n\n private resolveMode(item: PlayableItem): SourceMode {\n if (this.options.preferHls) return this.hasMode(item, 'hls') ? 'hls' : this.hasMode(item, 'mp4') ? 'mp4' : 'hls';\n return this.hasMode(item, 'mp4') ? 'mp4' : this.hasMode(item, 'hls') ? 'hls' : 'mp4';\n }\n\n private hasMode(item: PlayableItem, mode: SourceMode): boolean {\n return Array.isArray(item[mode]) && item[mode]!.some((v) => v?.src);\n }\n\n private buildPayload(item: PlayableItem, mode: SourceMode, mp4Index = 0): { src: string; type?: string } | null {\n const list = (item[mode] || []).filter((v) => v?.src);\n if (!list.length) return null;\n\n let src;\n if (mode === 'mp4') {\n src = mp4Index > 0 ? list[mp4Index] || list[0] : list.find((v) => v.selected) || list[0];\n } else {\n src = list[0];\n }\n return { src: src!.src, type: src!.type || (mode === 'hls' ? 'application/x-mpegURL' : 'video/mp4') };\n }\n\n private shouldAutoPlay(userInitiated: boolean): boolean {\n if (userInitiated) return true;\n return this.options.autoplayNext && this.userHasStartedPlayback;\n }\n\n private clampIndex(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 // ── ui ──\n\n private buildUi() {\n const ui = this.rawOptions.ui ?? {};\n const root = document.createElement('div');\n root.setAttribute('part', 'playlist-panel');\n root.className = 'hp:flex hp:flex-col hp:gap-2 hp:p-3 hp:bg-surface-elev hp:max-h-80 hp:overflow-y-auto';\n\n const header = document.createElement('div');\n header.className = 'hp:flex hp:items-center hp:justify-between hp:gap-2 hp:mb-1';\n\n const titleEl = document.createElement('div');\n titleEl.className = 'hp:text-sm hp:font-semibold hp:text-on-surface';\n titleEl.textContent = this.playlistTitleText();\n header.appendChild(titleEl);\n\n const navWrap = document.createElement('div');\n navWrap.className = 'hp:flex hp:gap-1';\n const prevBtn = this.navButton('chevron-left', this.ctx.i18n.playlistPrev, () => this.prev());\n const nextBtn = this.navButton('chevron-left', this.ctx.i18n.playlistNext, () => this.next());\n nextBtn.style.transform = 'rotate(180deg)';\n navWrap.append(prevBtn, nextBtn);\n header.appendChild(navWrap);\n\n root.appendChild(header);\n\n const listEl = document.createElement('ul');\n listEl.className = 'hp:flex hp:flex-col hp:gap-1 hp:list-none hp:m-0 hp:p-0';\n root.appendChild(listEl);\n\n const itemEls: Array<{ li: HTMLElement; titleRow: HTMLElement; progressFill: HTMLElement | null; timeEl: HTMLElement | null }> = [];\n this.items.forEach((item, idx) => {\n const li = document.createElement('li');\n li.className =\n 'hp:flex hp:items-center hp:gap-2 hp:p-2 hp:rounded hp:cursor-pointer hp:text-on-surface-muted hp:text-sm ' +\n 'hp:hover:bg-on-surface/5 hp:data-[active=true]:bg-accent/15 hp:data-[active=true]:text-on-surface';\n\n if (item.image) {\n const img = document.createElement('img');\n img.src = item.image;\n img.loading = 'lazy';\n img.className = 'hp:w-16 hp:aspect-video hp:object-cover hp:rounded hp:shrink-0';\n li.appendChild(img);\n }\n\n const body = document.createElement('div');\n body.className = 'hp:flex-1 hp:min-w-0';\n const titleRow = document.createElement('div');\n titleRow.className = 'hp:truncate hp:font-medium';\n titleRow.textContent = item.title || this.ctx.i18n.videoFallbackTitle(idx);\n body.appendChild(titleRow);\n\n let progressFill: HTMLElement | null = null;\n let timeEl: HTMLElement | null = null;\n if (ui.showMeta !== false) {\n const metaRow = document.createElement('div');\n metaRow.className = 'hp:flex hp:items-center hp:gap-2 hp:text-xs hp:opacity-70 hp:mt-0.5';\n timeEl = document.createElement('span');\n timeEl.textContent = '';\n metaRow.appendChild(timeEl);\n\n const bar = document.createElement('div');\n bar.className = 'hp:flex-1 hp:h-0.5 hp:bg-on-surface/20 hp:rounded-full hp:overflow-hidden';\n progressFill = document.createElement('div');\n progressFill.className = 'hp:h-full hp:bg-accent';\n progressFill.style.width = '0%';\n bar.appendChild(progressFill);\n metaRow.appendChild(bar);\n body.appendChild(metaRow);\n }\n\n li.appendChild(body);\n li.addEventListener('click', () => this.setIndex(idx));\n listEl.appendChild(li);\n itemEls.push({ li, titleRow, progressFill, timeEl });\n });\n\n this.ctx.panelEl.appendChild(root);\n return { root, titleEl, listEl, prevBtn, nextBtn, itemEls };\n }\n\n private playlistTitleText(): string {\n const ui = this.rawOptions.ui ?? {};\n const title = ui.title || this.ctx.i18n.playlistTitle;\n return ui.showCount === false ? title : `${title} (${this.items.length})`;\n }\n\n private navButton(iconName: string, label: string, onClick: () => void): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.setAttribute('aria-label', label);\n btn.className = 'hp:flex hp:items-center hp:justify-center hp:w-6 hp:h-6 hp:text-on-surface hp:bg-transparent hp:border-0 hp:cursor-pointer';\n btn.appendChild(createIcon(iconName, 'hp:text-sm'));\n btn.addEventListener('click', onClick);\n return btn;\n }\n\n private setActive(index: number): void {\n this.ui.itemEls.forEach((entry, idx) => {\n if (idx === index) entry.li.setAttribute('data-active', 'true');\n else entry.li.removeAttribute('data-active');\n });\n // loadAndPlay() hem anlık UI geri bildirimi için önceden (next/prev/setIndex\n // içinden) hem de kaynak gerçekten yüklendiğinde setActive() çağırıyor —\n // aynı index için event'i yalnızca BİR kez yaymak için guard.\n if (this.lastDispatchedIndex !== index) {\n this.lastDispatchedIndex = index;\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:itemchange', { detail: { index, source: 'playlist' } }));\n }\n }\n\n private updateProgress(): void {\n const active = this.ui.itemEls[this.index];\n if (!active) return;\n const duration = this.ctx.videoEl.duration;\n const current = this.ctx.videoEl.currentTime;\n if (active.timeEl) active.timeEl.textContent = this.formatTime(current);\n if (active.progressFill && Number.isFinite(duration) && duration > 0) {\n active.progressFill.style.width = `${Math.min(100, (current / duration) * 100)}%`;\n }\n }\n\n private formatTime(sec: number): string {\n const s = Math.max(0, Math.floor(sec || 0));\n const m = Math.floor(s / 60);\n const r = s % 60;\n return `${m}:${String(r).padStart(2, '0')}`;\n }\n}\n","import { PlaylistRunner, type PlaylistPlayerContext } from './PlaylistRunner';\nimport type { PlaylistOptions } from '../../types';\n\nexport function installPlaylist(ctx: PlaylistPlayerContext, options: PlaylistOptions): PlaylistRunner {\n return new PlaylistRunner(ctx, options);\n}\n\nexport { PlaylistRunner };\nexport type { PlaylistPlayerContext };\n"],"names":["DEFAULTS","PlaylistRunner","ctx","rawOptions","__publicField","now","entry","idx","item","opts","i","attemptId","mode","tried","mp4Index","_a","_b","payload","mp4List","v","nextMp4","otherMode","index","_isFallback","list","src","userInitiated","ui","root","header","titleEl","navWrap","prevBtn","nextBtn","listEl","itemEls","li","img","body","titleRow","progressFill","timeEl","metaRow","bar","title","iconName","label","onClick","btn","createIcon","active","duration","current","sec","s","m","r","installPlaylist","options"],"mappings":"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"}
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
var a = Object.defineProperty;
|
|
2
|
-
var l = (s, e, t) => e in s ? a(s, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : s[e] = t;
|
|
3
|
-
var p = (s, e, t) => l(s, typeof e != "symbol" ? e + "" : e, t);
|
|
4
|
-
class d {
|
|
5
|
-
constructor(e, t) {
|
|
6
|
-
p(this, "counterTimer", null);
|
|
7
|
-
p(this, "wrapper", null);
|
|
8
|
-
p(this, "onPlay", () => {
|
|
9
|
-
this.remove();
|
|
10
|
-
});
|
|
11
|
-
p(this, "onEnded", () => {
|
|
12
|
-
this.ctx.isAdActive() || this.create();
|
|
13
|
-
});
|
|
14
|
-
this.ctx = e, this.options = t, t.enabled !== !1 && (e.videoEl.addEventListener("ended", this.onEnded), e.videoEl.addEventListener("play", this.onPlay));
|
|
15
|
-
}
|
|
16
|
-
/** Ekran her gösterimde sıfırdan oluşturuluyor (`create()`) ve güncel `ctx.i18n`'i okuyor — burada tazelenecek kalıcı bir etiket yok, diğer plugin'lerle TUTARLI bir çağrı yüzeyi için var. */
|
|
17
|
-
refreshLabels() {
|
|
18
|
-
}
|
|
19
|
-
destroy() {
|
|
20
|
-
this.ctx.videoEl.removeEventListener("ended", this.onEnded), this.ctx.videoEl.removeEventListener("play", this.onPlay), this.remove();
|
|
21
|
-
}
|
|
22
|
-
remove() {
|
|
23
|
-
var e;
|
|
24
|
-
this.counterTimer && (clearInterval(this.counterTimer), this.counterTimer = null), (e = this.wrapper) == null || e.remove(), this.wrapper = null;
|
|
25
|
-
}
|
|
26
|
-
create() {
|
|
27
|
-
this.remove();
|
|
28
|
-
const e = document.createElement("div");
|
|
29
|
-
if (e.setAttribute("part", "redirect-screen"), e.className = "hp:absolute hp:inset-0 hp:z-30 hp:flex hp:flex-col hp:items-center hp:justify-center hp:gap-3 hp:bg-black/85 hp:text-white hp:text-center hp:p-4", this.options.image) {
|
|
30
|
-
const i = document.createElement("img");
|
|
31
|
-
i.src = this.options.image, i.className = "hp:max-w-[50%] hp:rounded-lg", e.appendChild(i);
|
|
32
|
-
}
|
|
33
|
-
if (this.options.title) {
|
|
34
|
-
const i = document.createElement("div");
|
|
35
|
-
i.className = "hp:text-base hp:font-semibold", i.textContent = this.options.title, e.appendChild(i);
|
|
36
|
-
}
|
|
37
|
-
const t = document.createElement("div");
|
|
38
|
-
t.className = "hp:text-sm hp:opacity-80", e.appendChild(t);
|
|
39
|
-
const r = document.createElement("div");
|
|
40
|
-
r.className = "hp:flex hp:gap-2 hp:mt-2";
|
|
41
|
-
const n = document.createElement("button");
|
|
42
|
-
n.type = "button", n.textContent = this.ctx.i18n.redirectCancel, n.className = "hp:px-4 hp:py-1.5 hp:rounded hp:bg-white/15 hp:text-white hp:border-0 hp:cursor-pointer hp:text-sm";
|
|
43
|
-
const o = document.createElement("button");
|
|
44
|
-
o.type = "button", o.textContent = this.ctx.i18n.redirectPlayNow, o.className = "hp:px-4 hp:py-1.5 hp:rounded hp:bg-accent hp:text-on-accent hp:border-0 hp:cursor-pointer hp:text-sm", o.addEventListener("click", () => {
|
|
45
|
-
window.location.href = this.options.url;
|
|
46
|
-
}), r.append(n, o), e.appendChild(r), this.ctx.overlayContainerEl.appendChild(e), this.wrapper = e;
|
|
47
|
-
let h = this.options.time;
|
|
48
|
-
const c = () => {
|
|
49
|
-
t.textContent = this.ctx.i18n.redirectCountdown(h);
|
|
50
|
-
};
|
|
51
|
-
c(), this.counterTimer = setInterval(() => {
|
|
52
|
-
h--, h >= 0 ? c() : (this.counterTimer && clearInterval(this.counterTimer), t.textContent = this.ctx.i18n.redirectNowPlaying, window.location.href = this.options.url);
|
|
53
|
-
}, 1e3), n.addEventListener("click", () => {
|
|
54
|
-
this.remove();
|
|
55
|
-
const i = this.options.suggestions || [];
|
|
56
|
-
i.length && this.showSuggestions(i);
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
showSuggestions(e) {
|
|
60
|
-
const t = document.createElement("div");
|
|
61
|
-
t.setAttribute("part", "redirect-suggestions"), t.className = "hp:absolute hp:inset-0 hp:z-30 hp:grid hp:grid-cols-2 hp:gap-2 hp:p-3 hp:overflow-y-auto hp:bg-black/85";
|
|
62
|
-
for (const r of e) {
|
|
63
|
-
const n = document.createElement("a");
|
|
64
|
-
n.href = r.url, n.className = "hp:relative hp:block hp:rounded-lg hp:overflow-hidden hp:text-white hp:no-underline", n.innerHTML = `<img src="${r.image}" class="hp:w-full hp:aspect-video hp:object-cover" />
|
|
65
|
-
<div class="hp:absolute hp:inset-x-0 hp:bottom-0 hp:bg-gradient-to-t hp:from-black/80 hp:to-transparent hp:p-2 hp:text-xs">${r.title}</div>`, t.appendChild(n);
|
|
66
|
-
}
|
|
67
|
-
this.ctx.overlayContainerEl.appendChild(t), this.wrapper = t;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
function u(s, e) {
|
|
71
|
-
return new d(s, e);
|
|
72
|
-
}
|
|
73
|
-
export {
|
|
74
|
-
d as RedirectScreen,
|
|
75
|
-
u as installRedirectScreen
|
|
76
|
-
};
|
|
77
|
-
//# sourceMappingURL=index-D6r-BGAV.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-D6r-BGAV.js","sources":["../../src/plugins/redirect-screen/RedirectScreen.ts","../../src/plugins/redirect-screen/index.ts"],"sourcesContent":["import type { RedirectScreenOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\n\nexport interface RedirectScreenPlayerContext {\n videoEl: HTMLVideoElement;\n overlayContainerEl: HTMLElement;\n isAdActive(): boolean;\n i18n: HopeLocaleStrings;\n}\n\n/** İçerik bitince \"N saniye içinde sıradaki video\" ekranı; postroll sırasında gösterilmez. */\nexport class RedirectScreen {\n private counterTimer: ReturnType<typeof setInterval> | null = null;\n private wrapper: HTMLElement | null = null;\n\n constructor(\n private readonly ctx: RedirectScreenPlayerContext,\n private readonly options: RedirectScreenOptions\n ) {\n if (options.enabled === false) return;\n ctx.videoEl.addEventListener('ended', this.onEnded);\n ctx.videoEl.addEventListener('play', this.onPlay);\n }\n\n /** Ekran her gösterimde sıfırdan oluşturuluyor (`create()`) ve güncel `ctx.i18n`'i okuyor — burada tazelenecek kalıcı bir etiket yok, diğer plugin'lerle TUTARLI bir çağrı yüzeyi için var. */\n refreshLabels(): void {\n /* no-op */\n }\n\n destroy(): void {\n this.ctx.videoEl.removeEventListener('ended', this.onEnded);\n this.ctx.videoEl.removeEventListener('play', this.onPlay);\n this.remove();\n }\n\n private readonly onPlay = (): void => {\n this.remove();\n };\n\n private readonly onEnded = (): void => {\n if (this.ctx.isAdActive()) return;\n this.create();\n };\n\n private remove(): void {\n if (this.counterTimer) {\n clearInterval(this.counterTimer);\n this.counterTimer = null;\n }\n this.wrapper?.remove();\n this.wrapper = null;\n }\n\n private create(): void {\n this.remove();\n\n const wrapper = document.createElement('div');\n wrapper.setAttribute('part', 'redirect-screen');\n wrapper.className = 'hp:absolute hp:inset-0 hp:z-30 hp:flex hp:flex-col hp:items-center hp:justify-center hp:gap-3 hp:bg-black/85 hp:text-white hp:text-center hp:p-4';\n\n if (this.options.image) {\n const img = document.createElement('img');\n img.src = this.options.image;\n img.className = 'hp:max-w-[50%] hp:rounded-lg';\n wrapper.appendChild(img);\n }\n\n if (this.options.title) {\n const title = document.createElement('div');\n title.className = 'hp:text-base hp:font-semibold';\n title.textContent = this.options.title;\n wrapper.appendChild(title);\n }\n\n const counter = document.createElement('div');\n counter.className = 'hp:text-sm hp:opacity-80';\n wrapper.appendChild(counter);\n\n const buttons = document.createElement('div');\n buttons.className = 'hp:flex hp:gap-2 hp:mt-2';\n\n const cancelBtn = document.createElement('button');\n cancelBtn.type = 'button';\n cancelBtn.textContent = this.ctx.i18n.redirectCancel;\n cancelBtn.className = 'hp:px-4 hp:py-1.5 hp:rounded hp:bg-white/15 hp:text-white hp:border-0 hp:cursor-pointer hp:text-sm';\n\n const acceptBtn = document.createElement('button');\n acceptBtn.type = 'button';\n acceptBtn.textContent = this.ctx.i18n.redirectPlayNow;\n acceptBtn.className = 'hp:px-4 hp:py-1.5 hp:rounded hp:bg-accent hp:text-on-accent hp:border-0 hp:cursor-pointer hp:text-sm';\n acceptBtn.addEventListener('click', () => {\n window.location.href = this.options.url;\n });\n\n buttons.append(cancelBtn, acceptBtn);\n wrapper.appendChild(buttons);\n\n this.ctx.overlayContainerEl.appendChild(wrapper);\n this.wrapper = wrapper;\n\n let remaining = this.options.time;\n const render = () => {\n counter.textContent = this.ctx.i18n.redirectCountdown(remaining);\n };\n render();\n\n this.counterTimer = setInterval(() => {\n remaining--;\n if (remaining >= 0) {\n render();\n } else {\n if (this.counterTimer) clearInterval(this.counterTimer);\n counter.textContent = this.ctx.i18n.redirectNowPlaying;\n window.location.href = this.options.url;\n }\n }, 1000);\n\n cancelBtn.addEventListener('click', () => {\n this.remove();\n const suggestions = this.options.suggestions || [];\n if (suggestions.length) this.showSuggestions(suggestions);\n });\n }\n\n private showSuggestions(items: NonNullable<RedirectScreenOptions['suggestions']>): void {\n const wrapper = document.createElement('div');\n wrapper.setAttribute('part', 'redirect-suggestions');\n wrapper.className = 'hp:absolute hp:inset-0 hp:z-30 hp:grid hp:grid-cols-2 hp:gap-2 hp:p-3 hp:overflow-y-auto hp:bg-black/85';\n\n for (const item of items) {\n const box = document.createElement('a');\n box.href = item.url;\n box.className = 'hp:relative hp:block hp:rounded-lg hp:overflow-hidden hp:text-white hp:no-underline';\n box.innerHTML = `<img src=\"${item.image}\" class=\"hp:w-full hp:aspect-video hp:object-cover\" />\n <div class=\"hp:absolute hp:inset-x-0 hp:bottom-0 hp:bg-gradient-to-t hp:from-black/80 hp:to-transparent hp:p-2 hp:text-xs\">${item.title}</div>`;\n wrapper.appendChild(box);\n }\n\n this.ctx.overlayContainerEl.appendChild(wrapper);\n this.wrapper = wrapper;\n }\n}\n","import { RedirectScreen, type RedirectScreenPlayerContext } from './RedirectScreen';\nimport type { RedirectScreenOptions } from '../../types';\n\nexport function installRedirectScreen(ctx: RedirectScreenPlayerContext, options: RedirectScreenOptions): RedirectScreen {\n return new RedirectScreen(ctx, options);\n}\n\nexport { RedirectScreen };\nexport type { RedirectScreenPlayerContext };\n"],"names":["RedirectScreen","ctx","options","__publicField","_a","wrapper","img","title","counter","buttons","cancelBtn","acceptBtn","remaining","render","suggestions","items","item","box","installRedirectScreen"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-DCXX1ZJG.js","sources":["../../src/plugins/debug/DebugPanel.ts","../../src/plugins/debug/index.ts"],"sourcesContent":["import type { HopeLocaleStrings } from '../../i18n/types';\nimport type { ErrorLog, PlayerLogEntry, PlayerLogSource } from '../../debug/ErrorLog';\n\nexport interface DebugPanelContext {\n containerEl: HTMLElement;\n i18n: HopeLocaleStrings;\n log: ErrorLog;\n version: string;\n}\n\nconst CLOSE_ICON =\n '<svg viewBox=\"0 0 24 24\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.4\" stroke-linecap=\"round\" aria-hidden=\"true\"><path d=\"M6 6l12 12M18 6L6 18\"/></svg>';\n\n/**\n * Sağ tık menüsündeki \"Hata ayıklama\" — player'ın tüm hatalarını (medya, yayın, reklam, altyazı) zaman sırasıyla,\n * ayrıntılarıyla gösteren ve tüm player alanını kaplayan pencere. Uzun satırlar (URL'ler) kırılır, liste kendi içinde\n * kayar; yeni hata gelince açık pencere canlı güncellenir.\n */\nexport class DebugPanel {\n private readonly el: HTMLDivElement;\n private readonly titleEl: HTMLSpanElement;\n private readonly countEl: HTMLSpanElement;\n private readonly copyBtn: HTMLButtonElement;\n private readonly clearBtn: HTMLButtonElement;\n private readonly closeBtn: HTMLButtonElement;\n private readonly list: HTMLOListElement;\n private readonly emptyEl: HTMLParagraphElement;\n private copiedTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(private readonly ctx: DebugPanelContext) {\n this.el = document.createElement('div');\n this.el.className = 'hp-debug';\n this.el.setAttribute('part', 'debug-panel');\n this.el.setAttribute('role', 'dialog');\n // Odak pencerenin kendisinde (ESC ile kapanır) — butona odaklanınca ipucu kendiliğinden açılıyordu.\n this.el.tabIndex = -1;\n\n const header = document.createElement('div');\n header.className = 'hp-debug-header';\n const title = document.createElement('div');\n title.className = 'hp-debug-title';\n this.titleEl = document.createElement('span');\n this.countEl = document.createElement('span');\n this.countEl.className = 'hp-debug-count';\n title.append(this.titleEl, this.countEl);\n\n const actions = document.createElement('div');\n actions.className = 'hp-debug-actions';\n this.copyBtn = this.button('hp-debug-btn', () => void this.copy());\n this.clearBtn = this.button('hp-debug-btn', () => this.ctx.log.clear());\n this.closeBtn = this.button('hp-stats-close', () => this.hide());\n this.closeBtn.innerHTML = CLOSE_ICON;\n actions.append(this.copyBtn, this.clearBtn, this.closeBtn);\n header.append(title, actions);\n\n this.list = document.createElement('ol');\n this.list.className = 'hp-debug-list';\n this.emptyEl = document.createElement('p');\n this.emptyEl.className = 'hp-debug-empty';\n\n this.el.append(header, this.list, this.emptyEl);\n // Panel tıklamaları / kaydırma videoyu oynat-duraklat yapmasın, klavye kısayolları tetiklenmesin.\n this.el.addEventListener('pointerdown', (e) => e.stopPropagation());\n this.el.addEventListener('click', (e) => e.stopPropagation());\n this.el.addEventListener('dblclick', (e) => e.stopPropagation());\n this.el.addEventListener('keydown', (e) => {\n if (e.key === 'Escape') this.hide();\n e.stopPropagation();\n });\n this.refreshLabels();\n }\n\n get isVisible(): boolean {\n return this.el.isConnected;\n }\n\n show(): void {\n if (!this.isVisible) this.ctx.containerEl.appendChild(this.el);\n this.ctx.log.onChange = () => this.render();\n this.render();\n this.el.focus({ preventScroll: true });\n }\n\n hide(): void {\n if (this.ctx.log.onChange) this.ctx.log.onChange = null;\n this.el.remove();\n }\n\n refreshLabels(): void {\n const t = this.ctx.i18n;\n this.titleEl.textContent = t.debugTitle;\n this.copyBtn.textContent = t.debugCopy;\n this.clearBtn.textContent = t.debugClear;\n this.closeBtn.setAttribute('aria-label', t.debugClose);\n this.emptyEl.textContent = t.debugEmpty;\n if (this.isVisible) this.render();\n }\n\n destroy(): void {\n if (this.copiedTimer) clearTimeout(this.copiedTimer);\n this.hide();\n }\n\n private button(className: string, onClick: () => void): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = className;\n btn.addEventListener('click', onClick);\n return btn;\n }\n\n private sourceLabel(source: PlayerLogSource): string {\n const t = this.ctx.i18n;\n return { media: t.debugSourceMedia, stream: t.debugSourceStream, ads: t.debugSourceAds, subtitles: t.debugSourceSubtitles, player: t.debugSourcePlayer }[source];\n }\n\n private render(): void {\n const entries = this.ctx.log.entries;\n this.countEl.textContent = entries.length ? String(entries.length) : '';\n this.emptyEl.hidden = entries.length > 0;\n this.clearBtn.disabled = entries.length === 0;\n this.copyBtn.disabled = entries.length === 0;\n // En yeni en üstte.\n this.list.replaceChildren(...[...entries].reverse().map((e) => this.row(e)));\n }\n\n private row(entry: PlayerLogEntry): HTMLLIElement {\n const li = document.createElement('li');\n li.className = 'hp-debug-row';\n if (entry.fatal) li.setAttribute('data-fatal', '');\n\n const head = document.createElement('div');\n head.className = 'hp-debug-row-head';\n const time = document.createElement('time');\n time.className = 'hp-debug-time';\n const d = new Date(entry.time);\n time.textContent = `${d.toLocaleTimeString([], { hour12: false })}.${String(d.getMilliseconds()).padStart(3, '0')}`;\n const source = document.createElement('span');\n source.className = 'hp-debug-source';\n source.setAttribute('data-source', entry.source);\n source.textContent = this.sourceLabel(entry.source);\n head.append(time, source);\n if (entry.fatal) {\n const fatal = document.createElement('span');\n fatal.className = 'hp-debug-fatal';\n fatal.textContent = this.ctx.i18n.debugFatal;\n head.appendChild(fatal);\n }\n\n const message = document.createElement('div');\n message.className = 'hp-debug-message';\n message.textContent = entry.message;\n if (entry.count && entry.count > 1) {\n const repeat = document.createElement('span');\n repeat.className = 'hp-debug-repeat';\n repeat.textContent = ` ×${entry.count}`;\n message.appendChild(repeat);\n }\n li.append(head, message);\n\n const details = Object.entries(entry.details ?? {}).filter(([, v]) => v !== undefined && v !== '');\n if (details.length) {\n const dl = document.createElement('dl');\n dl.className = 'hp-debug-details';\n for (const [k, v] of details) {\n const dt = document.createElement('dt');\n dt.textContent = k;\n const dd = document.createElement('dd');\n dd.textContent = String(v);\n dl.append(dt, dd);\n }\n li.appendChild(dl);\n }\n return li;\n }\n\n private async copy(): Promise<void> {\n const text = `HopeCorePlayer ${this.ctx.version} · ${navigator.userAgent}\\n${this.ctx.log.toText()}`;\n try {\n await navigator.clipboard.writeText(text);\n } catch {\n return;\n }\n this.copyBtn.textContent = this.ctx.i18n.debugCopied;\n if (this.copiedTimer) clearTimeout(this.copiedTimer);\n this.copiedTimer = setTimeout(() => {\n this.copiedTimer = null;\n this.copyBtn.textContent = this.ctx.i18n.debugCopy;\n }, 1500);\n }\n}\n","import { DebugPanel, type DebugPanelContext } from './DebugPanel';\n\nexport function installDebugPanel(ctx: DebugPanelContext): DebugPanel {\n return new DebugPanel(ctx);\n}\n\nexport { DebugPanel };\nexport type { DebugPanelContext };\n"],"names":["CLOSE_ICON","DebugPanel","ctx","__publicField","header","title","actions","e","className","onClick","btn","source","t","entries","entry","li","head","time","d","fatal","message","repeat","details","v","dl","k","dt","dd","text","installDebugPanel"],"mappings":"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"}
|