@hopeplayer/core 1.0.0 → 1.0.2
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/dist/chunks/index-BBmuCtKu.js.map +1 -1
- package/dist/chunks/{index-q5DsrT-Q.js → index-BR31cEYA.js} +2 -2
- package/dist/chunks/index-BR31cEYA.js.map +1 -0
- package/dist/chunks/{index-DiCkShCE.js → index-BjmWoP4E.js} +80 -70
- package/dist/chunks/index-BjmWoP4E.js.map +1 -0
- package/dist/chunks/{index-B4ujPVcl.js → index-CEmsL1uT.js} +2 -2
- package/dist/chunks/{index-B4ujPVcl.js.map → index-CEmsL1uT.js.map} +1 -1
- package/dist/chunks/{index-CQqGn9as.js → index-CZK3TwzR.js} +2 -2
- package/dist/chunks/index-CZK3TwzR.js.map +1 -0
- package/dist/chunks/{index-BFgqg05L.js → index-DadIEuQc.js} +2 -2
- package/dist/chunks/{index-BFgqg05L.js.map → index-DadIEuQc.js.map} +1 -1
- package/dist/chunks/index-glxDu2eJ.js.map +1 -1
- package/dist/chunks/{index-DXf2Al1x.js → index-lrAXde76.js} +2 -2
- package/dist/chunks/{index-DXf2Al1x.js.map → index-lrAXde76.js.map} +1 -1
- package/dist/hls/SourceManager.d.ts +5 -2
- package/dist/hls/SourceManager.d.ts.map +1 -1
- package/dist/hope-player.js +1 -1
- package/package.json +1 -1
- package/dist/chunks/index-CQqGn9as.js.map +0 -1
- package/dist/chunks/index-DiCkShCE.js.map +0 -1
- package/dist/chunks/index-q5DsrT-Q.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-glxDu2eJ.js","sources":["../../src/plugins/ads/loadImaSdk.ts","../../src/plugins/ads/generateVastUrl.ts","../../src/plugins/ads/RetryController.ts","../../src/plugins/ads/consent.ts","../../src/plugins/ads/scte35.ts","../../src/plugins/ads/AdsController.ts","../../src/plugins/ads/index.ts"],"sourcesContent":["const IMA_SDK_URL = 'https://imasdk.googleapis.com/js/sdkloader/ima3.js';\n\ndeclare global {\n interface Window {\n google?: { ima?: typeof google.ima };\n }\n}\n\nlet loadPromise: Promise<typeof google.ima> | null = null;\n\n/** Google IMA SDK'yı bir kez <script> ile yükler. */\nexport function loadImaSdk(): Promise<typeof google.ima> {\n if (window.google?.ima) return Promise.resolve(window.google.ima);\n if (loadPromise) return loadPromise;\n\n loadPromise = new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.src = IMA_SDK_URL;\n script.async = true;\n script.onload = () => {\n if (window.google?.ima) resolve(window.google.ima);\n else reject(new Error('IMA SDK yüklendi ama window.google.ima yok'));\n };\n script.onerror = () => reject(new Error('IMA SDK yüklenemedi (reklam engelleyici olabilir)'));\n document.head.appendChild(script);\n });\n\n return loadPromise;\n}\n","/** adTaxonomy.keyValues → GAM cust_params (key=value, & ile; virgül GAM'de aynı key'in çoklu değer ayracı). */\nfunction buildAdTaxonomyKeyValues(): string {\n const w = window as unknown as { adTaxonomy?: { keyValues?: Record<string, unknown> } };\n const kv = w.adTaxonomy?.keyValues;\n if (!kv || typeof kv !== 'object') return '';\n\n const pairs: string[] = [];\n for (const [key, value] of Object.entries(kv)) {\n if (value === undefined || value === null || value === '') continue;\n pairs.push(`${key}=${value}`);\n }\n return pairs.join('&');\n}\n\nexport interface GenerateVastUrlOptions {\n adRefreshCount?: number;\n /** true ise cust_params'a adrefreshCount eklenir (adsRetry.enabled ile aynı anlam). */\n includeRefreshCount?: boolean;\n}\n\n/** [referrer_url]/[description_url]/[timestamp] placeholder'larını doldurur, cust_params'a adrefreshCount + adTaxonomy ekler. */\nexport function generateVastUrl(baseUrl: string, options: GenerateVastUrlOptions = {}): string {\n const referrerUrl = encodeURIComponent(document.referrer || window.location.href);\n const descriptionUrl = encodeURIComponent(window.location.href);\n const timestamp = Date.now();\n\n let url = baseUrl;\n const params: Record<string, string | number> = {\n referrer_url: referrerUrl,\n description_url: descriptionUrl,\n timestamp,\n };\n\n for (const [key, value] of Object.entries(params)) {\n const placeholder = `[${key}]`;\n if (url.includes(placeholder)) {\n url = url.replace(placeholder, String(value));\n } else if (!new URLSearchParams(url.split('?')[1]).has(key)) {\n const delimiter = url.includes('?') ? '&' : '?';\n url += `${delimiter}${key}=${value}`;\n }\n }\n\n try {\n const parsedUrl = new URL(url);\n const isVmap = parsedUrl.pathname.includes('/vmap/');\n if (isVmap) return baseUrl;\n\n const extras: string[] = [];\n if (options.includeRefreshCount) extras.push(`adrefreshCount=${options.adRefreshCount ?? 0}`);\n const taxonomyKeyValues = buildAdTaxonomyKeyValues();\n if (taxonomyKeyValues) extras.push(taxonomyKeyValues);\n\n if (extras.length) {\n const custParams = parsedUrl.searchParams.get('cust_params');\n parsedUrl.searchParams.set('cust_params', custParams ? `${custParams}&${extras.join('&')}` : extras.join('&'));\n }\n\n return parsedUrl.toString();\n } catch {\n return url;\n }\n}\n","import type { AdsRetryOptions, RetryDelayEntry } from '../../types';\n\nexport type AdBreakType = 'Preroll' | 'Midroll' | 'Postroll';\n\ninterface ChainState {\n tags: string[];\n index: number;\n attemptsOnCurrent: number;\n}\n\n/** Reklam retry zamanlaması ve fallback zinciri kararları (network'ten bağımsız). */\nexport class RetryController {\n private adRetryCount = 0;\n private chain: Partial<Record<AdBreakType, ChainState>> = {};\n private retryTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(private readonly config: AdsRetryOptions) {}\n\n get isPending(): boolean {\n return this.retryTimer !== null;\n }\n\n reset(): void {\n this.adRetryCount = 0;\n this.chain = {};\n this.cancelPending();\n }\n\n cancelPending(): void {\n if (this.retryTimer) {\n clearTimeout(this.retryTimer);\n this.retryTimer = null;\n }\n }\n\n /** Devre dışı/kapsam dışı/limit dolduysa onGiveUp; aksi halde (jitter'lı) gecikmeden sonra onRetry. */\n retry(type: AdBreakType, rawTag: string | string[] | undefined, onRetry: (tag: string, attempt: number) => void, onGiveUp: (reason: 'retry-disabled' | 'retry-limit') => void): void {\n if (!this.config.enabled) {\n onGiveUp('retry-disabled');\n return;\n }\n\n const scope = this.config.retryScope ?? 'preroll';\n if (scope === 'preroll' && type !== 'Preroll') {\n onGiveUp('retry-disabled');\n return;\n }\n\n const maxRetry = this.resolveMaxRetry();\n if (this.adRetryCount >= maxRetry) {\n this.reset();\n onGiveUp('retry-limit');\n return;\n }\n\n this.cancelPending();\n this.adRetryCount++;\n\n const chain = this.getChainState(type, rawTag);\n chain.attemptsOnCurrent++;\n const maxAttemptsPerTag = this.config.maxAttemptsPerTag ?? Infinity;\n if (chain.attemptsOnCurrent > maxAttemptsPerTag && chain.index < chain.tags.length - 1) {\n chain.index++;\n chain.attemptsOnCurrent = 1;\n }\n const tag = chain.tags[chain.index]!;\n const attempt = this.adRetryCount;\n\n this.retryTimer = setTimeout(() => {\n this.retryTimer = null;\n onRetry(tag, attempt);\n }, this.applyJitter(this.resolveRetryDelay()));\n }\n\n private getChainState(type: AdBreakType, rawTag: string | string[] | undefined): ChainState {\n const existing = this.chain[type];\n if (existing) return existing;\n\n const tags = (Array.isArray(rawTag) ? rawTag : [rawTag]).filter((t): t is string => !!t);\n const state: ChainState = { tags: tags.length ? tags : [rawTag as string], index: 0, attemptsOnCurrent: 0 };\n this.chain[type] = state;\n return state;\n }\n\n private resolveRetryDelay(): number {\n const pattern = this.config.retryDelayPattern;\n if (!Array.isArray(pattern) || pattern.length === 0) return this.config.retryDelay ?? 800;\n\n for (const entry of pattern) {\n const [upTo, delay] = this.normalizeEntry(entry);\n if (this.adRetryCount <= upTo) return delay;\n }\n return this.normalizeEntry(pattern[pattern.length - 1]!)[1];\n }\n\n private resolveMaxRetry(): number {\n const pattern = this.config.retryDelayPattern;\n if (Array.isArray(pattern) && pattern.length > 0) {\n return this.normalizeEntry(pattern[pattern.length - 1]!)[0];\n }\n return this.config.maxRetry ?? 10;\n }\n\n private normalizeEntry(entry: RetryDelayEntry): [number, number] {\n return Array.isArray(entry) ? entry : [entry.upTo, entry.delay];\n }\n\n private applyJitter(delay: number): number {\n const jitter = this.config.jitter ?? 0;\n if (!jitter) return delay;\n const factor = 1 + (Math.random() * 2 - 1) * jitter;\n return Math.max(0, Math.round(delay * factor));\n }\n}\n","import type { AdsOptions } from '../../types';\r\n\r\n/**\n * Generic TCF/USP consent — options.consentAware === true gerektirir. Non-blocking; yetersiz onay/opt-out'ta\n * google.ima.settings.setPrivacySettings({ nonPersonalizedAds: true }) zorlar.\n */\r\n\r\ninterface TcfData {\r\n gdprApplies?: boolean;\r\n vendor?: { consents?: Record<number, boolean> };\r\n purpose?: { consents?: Record<number, boolean> };\r\n}\r\n\r\ndeclare global {\r\n interface Window {\r\n __uspapi?: (command: string, version: number, callback: (data: { uspString?: string } | undefined, success: boolean) => void) => void;\r\n __tcfapi?: (command: string, version: number, callback: (data: TcfData | undefined, success: boolean) => void) => void;\r\n }\r\n}\r\n\r\nfunction restrictAdsForConsent(ima: typeof google.ima | null, reason: string): void {\r\n try {\r\n if (ima?.settings?.setPrivacySettings) {\r\n ima.settings.setPrivacySettings({ nonPersonalizedAds: true });\r\n console.warn(`[HopePlayer consent] non-personalized ads zorlandı (${reason})`);\r\n }\r\n } catch (err) {\r\n console.warn('[HopePlayer consent] setPrivacySettings hatası:', err);\r\n }\r\n}\r\n\r\n/** options.consentAware değilse no-op. IMA TC/GPP string'ini zaten ekliyor; bu ek bir \"Limited Ads\" zorlaması. */\r\nexport function initConsentAware(options: AdsOptions, ima: typeof google.ima | null): void {\r\n if (!options.consentAware) return;\r\n\r\n try {\r\n if (typeof window.__uspapi === 'function') {\r\n window.__uspapi('getUSPData', 1, (uspData, success) => {\r\n if (!success || !uspData?.uspString) return;\r\n if (uspData.uspString.charAt(2) === 'Y') restrictAdsForConsent(ima, 'USP/CCPA opt-out');\r\n });\r\n }\r\n } catch (err) {\r\n console.warn('[HopePlayer consent] __uspapi okuma hatası:', err);\r\n }\r\n\r\n try {\r\n if (typeof window.__tcfapi === 'function') {\r\n window.__tcfapi('getTCData', 2, (tcData, success) => {\r\n if (!success || !tcData || tcData.gdprApplies !== true) return;\r\n const googleVendorConsent = tcData.vendor?.consents?.[755];\r\n const purpose1Consent = tcData.purpose?.consents?.[1];\r\n if (googleVendorConsent === false || purpose1Consent === false) {\r\n restrictAdsForConsent(ima, 'TCF yetersiz onay');\r\n }\r\n });\r\n }\r\n } catch (err) {\r\n console.warn('[HopePlayer consent] __tcfapi okuma hatası:', err);\r\n }\r\n}\r\n","/** SCTE-35 sinyal ayrıştırma + canlı yayın reklam yöneticisi. */\n\nexport interface Scte35Signal {\n type: 'out' | 'in' | 'cancel';\n spliceEventId?: number;\n duration?: number | null;\n breakDuration?: { autoReturn: number; seconds: number } | null;\n programSplice?: boolean;\n class?: string | null;\n raw?: string;\n}\n\n/** Base64 encoded SCTE-35 binary verisini parse eder — yalnızca splice_insert (0x05) komutlarını destekler. */\nexport function parseScte35Base64(base64: string): Scte35Signal | null {\n try {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);\n\n if (bytes[0] !== 0xfc) return null; // table_id\n\n const spliceCommandType = bytes[13];\n if (spliceCommandType !== 0x05) return null; // yalnızca splice_insert\n\n const spliceEventId = ((bytes[14]! << 24) | (bytes[15]! << 16) | (bytes[16]! << 8) | bytes[17]!) >>> 0;\n\n const cancelIndicator = (bytes[18]! >> 7) & 0x01;\n if (cancelIndicator) return { type: 'cancel', spliceEventId };\n\n const outOfNetwork = (bytes[19]! >> 7) & 0x01;\n const programSplice = (bytes[19]! >> 6) & 0x01;\n const durationFlag = (bytes[19]! >> 5) & 0x01;\n\n let breakDuration: Scte35Signal['breakDuration'] = null;\n\n if (programSplice) {\n let offset = 20;\n const timeSpecified = (bytes[offset]! >> 7) & 0x01;\n offset += timeSpecified ? 5 : 1;\n\n if (durationFlag) {\n const autoReturn = (bytes[offset]! >> 7) & 0x01;\n const durationHigh = bytes[offset]! & 0x01;\n const duration =\n durationHigh * Math.pow(2, 32) +\n bytes[offset + 1]! * Math.pow(2, 24) +\n bytes[offset + 2]! * Math.pow(2, 16) +\n bytes[offset + 3]! * Math.pow(2, 8) +\n bytes[offset + 4]!;\n breakDuration = { autoReturn, seconds: duration / 90000 };\n }\n }\n\n return { type: outOfNetwork ? 'out' : 'in', spliceEventId, breakDuration, programSplice: !!programSplice };\n } catch {\n return null;\n }\n}\n\n/** HLS manifest/segment'teki EXT-X-CUE-OUT/IN, EXT-X-DATERANGE, EXT-OATCLS-SCTE35 tag'lerini parse eder. */\nexport function parseHlsScteTag(tagName: string, tagValue: string): Scte35Signal | null {\n if (tagName === 'EXT-X-CUE-OUT') {\n return { type: 'out', duration: parseFloat(tagValue) || null };\n }\n if (tagName === 'EXT-X-CUE-IN') {\n return { type: 'in' };\n }\n if (tagName === 'EXT-X-DATERANGE') {\n const scteOut = tagValue.match(/SCTE35-OUT=0x([0-9A-Fa-f]+)/);\n const scteIn = tagValue.match(/SCTE35-IN=0x([0-9A-Fa-f]+)/);\n const duration = tagValue.match(/PLANNED-DURATION=([\\d.]+)/);\n const classAttr = tagValue.match(/CLASS=\"([^\"]+)\"/);\n\n if (scteOut) {\n return { type: 'out', duration: duration ? parseFloat(duration[1]!) : null, class: classAttr ? classAttr[1]! : null, raw: scteOut[1]! };\n }\n if (scteIn) return { type: 'in', raw: scteIn[1]! };\n }\n if (tagName === 'EXT-OATCLS-SCTE35') {\n return parseScte35Base64(tagValue);\n }\n return null;\n}\n\nexport interface Scte35ManagerCallbacks {\n onAdBreakStart(duration: number | null): void;\n onAdBreakEnd(): void;\n}\n\n/** textTracks metadata cue'larından SCTE-35 sinyallerini dinler (hls.js ve Safari native HLS). */\nexport class Scte35LiveAdManager {\n private inAdBreak = false;\n private adBreakTimer: ReturnType<typeof setTimeout> | null = null;\n private readonly processedEventIds = new Set<number>();\n private readonly trackListeners = new Map<TextTrack, () => void>();\n\n constructor(\n private readonly videoEl: HTMLVideoElement,\n private readonly callbacks: Scte35ManagerCallbacks\n ) {\n this.attachExistingTracks();\n videoEl.textTracks.addEventListener('addtrack', this.onAddTrack);\n }\n\n destroy(): void {\n this.videoEl.textTracks.removeEventListener('addtrack', this.onAddTrack);\n for (const [track, listener] of this.trackListeners) {\n track.removeEventListener('cuechange', listener);\n }\n this.trackListeners.clear();\n if (this.adBreakTimer) clearTimeout(this.adBreakTimer);\n this.processedEventIds.clear();\n }\n\n private readonly onAddTrack = (e: TrackEvent): void => {\n if (e.track instanceof TextTrack) this.listenTrack(e.track);\n };\n\n private attachExistingTracks(): void {\n for (let i = 0; i < this.videoEl.textTracks.length; i++) {\n this.listenTrack(this.videoEl.textTracks[i]!);\n }\n }\n\n private listenTrack(track: TextTrack): void {\n if (track.kind !== 'metadata' || this.trackListeners.has(track)) return;\n track.mode = 'hidden'; // cue'lar işlensin diye aktif olmalı ama görünmesin.\n\n const listener = () => {\n const cues = track.activeCues;\n if (!cues) return;\n for (let i = 0; i < cues.length; i++) this.processCue(cues[i]!);\n };\n track.addEventListener('cuechange', listener);\n this.trackListeners.set(track, listener);\n }\n\n private processCue(cue: TextTrackCue): void {\n const anyCue = cue as unknown as { value?: { key?: string; data?: string; value?: string }; text?: string };\n let tagName: string | null = null;\n let tagValue = '';\n\n if (anyCue.value && typeof anyCue.value === 'object') {\n tagName = anyCue.value.key ?? null;\n tagValue = anyCue.value.data ?? anyCue.value.value ?? '';\n } else if (typeof anyCue.text === 'string') {\n const match = anyCue.text.match(/^(EXT[^:]+):?(.*)$/);\n if (match) {\n tagName = match[1]!;\n tagValue = match[2] ?? '';\n }\n }\n\n if (!tagName) return;\n const signal = parseHlsScteTag(tagName, tagValue);\n if (signal) this.handleSignal(signal);\n }\n\n private handleSignal(signal: Scte35Signal): void {\n if (signal.spliceEventId !== undefined) {\n if (this.processedEventIds.has(signal.spliceEventId)) return;\n this.processedEventIds.add(signal.spliceEventId);\n setTimeout(() => this.processedEventIds.delete(signal.spliceEventId!), 5 * 60 * 1000);\n }\n\n if (signal.type === 'cancel') {\n this.endAdBreak(true);\n return;\n }\n if (signal.type === 'out' && !this.inAdBreak) {\n this.startAdBreak(signal.breakDuration?.seconds ?? signal.duration ?? null);\n } else if (signal.type === 'in' && this.inAdBreak) {\n this.endAdBreak(false);\n }\n }\n\n private startAdBreak(duration: number | null): void {\n if (this.inAdBreak) return;\n this.inAdBreak = true;\n this.callbacks.onAdBreakStart(duration);\n\n if (duration && duration > 0) {\n this.adBreakTimer = setTimeout(() => {\n if (this.inAdBreak) this.endAdBreak(true);\n }, (duration + 5) * 1000);\n }\n }\n\n endAdBreak(_forced = false): void {\n if (!this.inAdBreak) return;\n this.inAdBreak = false;\n if (this.adBreakTimer) {\n clearTimeout(this.adBreakTimer);\n this.adBreakTimer = null;\n }\n this.callbacks.onAdBreakEnd();\n }\n}\n","import { loadImaSdk } from './loadImaSdk';\r\nimport { generateVastUrl } from './generateVastUrl';\r\nimport { RetryController, type AdBreakType } from './RetryController';\r\nimport { initConsentAware } from './consent';\r\nimport { Scte35LiveAdManager } from './scte35';\r\nimport type { AdsOptions, PrebidBreakOptions } from '../../types';\r\nimport type { VideoPrebid } from '../prebid/VideoPrebid';\r\n\r\nexport interface AdsPlayerContext {\r\n videoEl: HTMLVideoElement;\r\n hostEl: HTMLElement;\r\n /** IMA'nın ad UI'ını (skip butonu/sayaç) çizdiği, video'nun üzerindeki katman. */\r\n adLayerEl: HTMLElement;\r\n hideChrome(): void;\r\n showChrome(): void;\r\n /** `options.locale` (ör. 'tr'/'en') — IMA SDK'nın KENDİ ad-UI'ının (skip butonu/sayaç/\"Reklam\" etiketi) dili de oynatıcının geri kalanıyla AYNI dili takip etsin diye `ima.settings.setLocale()`'a aktarılıyor. */\r\n locale: string;\r\n /** Reklamın oynat/duraklat durumu DIŞARIDAN (IMA'nın kendi UI'ı üzerinden) değişince toolbar'ı tazelemesi için — bkz. `adPaused` notu. */\r\n onAdPlayStateChange?(): void;\r\n}\r\n\r\nfunction tagConfigFor(options: AdsOptions, type: AdBreakType): string | string[] | undefined {\r\n if (type === 'Preroll') return options.adTagPreroll;\r\n if (type === 'Midroll') return options.adTagMidroll;\r\n return options.adTagPostroll;\r\n}\r\n\r\n/** Google IMA SDK ile doğrudan konuşan reklam çekirdeği (preroll/midroll/postroll, VMAP, retry, Prebid, SCTE-35). */\r\nexport class AdsController {\r\n private ima: typeof google.ima | null = null;\r\n private adDisplayContainer: google.ima.AdDisplayContainer | null = null;\r\n private adsLoader: google.ima.AdsLoader | null = null;\r\n private adsManager: google.ima.AdsManager | null = null;\r\n\r\n private readonly retry: RetryController;\r\n private currentBreakType: AdBreakType = 'Preroll';\r\n private vmapRequested = false;\r\n private postrollPending = false;\r\n private postrollShown = false;\r\n private lastMidrollTime = 0;\r\n private displayContainerInitialized = false;\r\n /**\n * Reklam sırasında toolbar oynat/duraklat + ses buraya yönlenir (IMA reklamı ayrı bir video'da oynatır).\n * Durum hem bizim çağrılarımızdan hem IMA'nın kendi PAUSED/RESUMED event'lerinden senkron tutulur.\n */\r\n private adPaused = false;\r\n private adVolumeBeforeMute = 1;\r\n private readonly prebidIdSuffix: string;\r\n private readonly prebidInstances: Partial<Record<AdBreakType, VideoPrebid>> = {};\r\n private scte35Manager: Scte35LiveAdManager | null = null;\r\n private scte35BreakActive = false;\r\n private scte35BreakTimeout: ReturnType<typeof setTimeout> | null = null;\r\n\r\n constructor(\r\n private readonly ctx: AdsPlayerContext,\r\n readonly options: AdsOptions\r\n ) {\r\n this.retry = new RetryController(options.retry ?? {});\r\n this.prebidIdSuffix = ctx.hostEl.id || Math.random().toString(36).slice(2, 8);\r\n }\r\n\r\n async install(): Promise<void> {\r\n let ima: typeof google.ima;\r\n try {\r\n ima = await loadImaSdk();\r\n } catch (err) {\r\n // Reklam engelleyici / ağ hatası — içerik reklamsız normal oynar.\r\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:aderror', { detail: { message: String(err) } }));\r\n return;\r\n }\r\n this.ima = ima;\r\n\r\n try {\r\n ima.settings.setLocale(this.ctx.locale);\r\n } catch {\r\n /* eski SDK sürümünde olmayabilir — kritik değil */\r\n }\r\n\r\n // setNumRedirects kritik: SDK varsayılanı 4 wrapper — çok hoplu zincirlerde IMA reklamı hata vermeden bırakır.\n // Her ayar ayrı try/catch'te (eski SDK'da olmayabilir).\r\n try {\r\n ima.settings.setNumRedirects(this.options.numRedirects ?? 15);\r\n } catch {\r\n /* eski SDK sürümünde olmayabilir */\r\n }\r\n try {\r\n ima.settings.setDisableCustomPlaybackForIOS10Plus(true);\r\n } catch {\r\n /* eski SDK sürümünde olmayabilir */\r\n }\r\n try {\r\n if (ima.ImaSdkSettings?.VpaidMode) {\r\n ima.settings.setVpaidMode(ima.ImaSdkSettings.VpaidMode.INSECURE);\r\n }\r\n } catch {\r\n /* eski SDK sürümünde olmayabilir */\r\n }\r\n\r\n // consentAware (TCF/USP) — options.consentAware===true gerektirir, non-blocking.\r\n initConsentAware(this.options, this.ima);\r\n\r\n this.adDisplayContainer = new ima.AdDisplayContainer(this.ctx.adLayerEl, this.ctx.videoEl);\r\n this.adsLoader = new ima.AdsLoader(this.adDisplayContainer);\r\n this.adsLoader.addEventListener(ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, this.onAdsManagerLoaded);\r\n this.adsLoader.addEventListener(ima.AdErrorEvent.Type.AD_ERROR, this.onAdsLoaderError);\r\n\r\n // iOS/Safari: AdDisplayContainer.initialize() kullanıcı jestiyle çağrılmalı.\r\n this.ctx.videoEl.addEventListener('play', this.initializeDisplayContainerOnce);\r\n\r\n // Plugin dinamik yüklendiği için autoplay video'yu bu dinleyici bağlanmadan başlatmış olabilir —\n // kaçırılan 'play'i telafi et, yoksa initialize() hiç çağrılmaz (AdError 400).\r\n const hasPageLevelUserActivation =\r\n typeof navigator !== 'undefined' &&\r\n 'userActivation' in navigator &&\r\n (navigator as unknown as { userActivation: { hasBeenActive: boolean } }).userActivation.hasBeenActive;\r\n if (!this.ctx.videoEl.paused || hasPageLevelUserActivation) {\r\n this.initializeDisplayContainerOnce();\r\n }\r\n\r\n if (this.options.adTagPostroll) {\r\n this.ctx.videoEl.addEventListener('ended', this.onContentEnded);\r\n }\r\n\r\n if (this.options.adTagMidroll && !this.options.adTagVmap && this.options.midrollIntervalSeconds) {\r\n this.ctx.videoEl.addEventListener('timeupdate', this.onTimeUpdateForMidroll);\r\n }\r\n\r\n this.requestInitialPrerollOrVmap();\r\n\r\n // Canlı + SCTE-35: normal preroll/midroll zamanlayıcısı yerine yayın\r\n // içindeki OUT/IN sinyalleri reklamı tetikler/bitirir — preroll YOK\r\n // (yayının \"başlangıcı\" olmadığı için auto-request edilmiyor).\r\n if (this.options.live?.scte35 && this.options.live.adTagLive) {\r\n this.scte35Manager = new Scte35LiveAdManager(this.ctx.videoEl, {\r\n onAdBreakStart: (duration) => this.onScte35AdBreakStart(duration),\r\n onAdBreakEnd: () => this.onScte35AdBreakEnd(),\r\n });\r\n }\r\n }\r\n\r\n /** requestOnPlay yoksa preroll/VMAP hemen istenir; varsa kullanıcı oynatana kadar ertelenir. */\r\n private requestInitialPrerollOrVmap(): void {\r\n const fire = (): void => {\r\n if (this.options.adTagPreroll) {\r\n this.requestAd('Preroll', this.options.adTagPreroll);\r\n } else if (this.options.adTagVmap) {\r\n // Ayrı bir preroll tag'i yok — VMAP tek başına (preroll dahil) kullanılıyor.\r\n this.vmapRequested = true;\r\n this.requestAd('Preroll', this.options.adTagVmap, 0, true);\r\n }\r\n };\r\n if (!this.options.requestOnPlay || !this.ctx.videoEl.paused) {\r\n fire();\r\n return;\r\n }\r\n this.ctx.videoEl.addEventListener('play', fire, { once: true });\r\n }\r\n\r\n /** Playlist/story item değişiminde: önceki item'ın reklam durumunu sıfırla. */\r\n resetForNewItem(newPrerollTag?: string | string[]): void {\r\n this.retry.reset();\r\n this.vmapRequested = false;\r\n this.postrollShown = false;\r\n this.postrollPending = false;\r\n this.lastMidrollTime = 0;\r\n if (newPrerollTag !== undefined) this.options.adTagPreroll = newPrerollTag;\r\n\r\n if (this.options.adTagPreroll) {\r\n void this.requestAd('Preroll', this.options.adTagPreroll);\r\n } else if (this.options.adTagVmap) {\r\n this.vmapRequested = true;\r\n void this.requestAd('Preroll', this.options.adTagVmap, 0, true);\r\n }\r\n }\r\n\r\n destroy(): void {\r\n this.ctx.videoEl.removeEventListener('play', this.initializeDisplayContainerOnce);\r\n this.ctx.videoEl.removeEventListener('ended', this.onContentEnded);\r\n this.ctx.videoEl.removeEventListener('timeupdate', this.onTimeUpdateForMidroll);\r\n this.retry.cancelPending();\r\n this.adsManager?.destroy();\r\n this.adsLoader?.destroy();\r\n this.adDisplayContainer?.destroy();\r\n this.scte35Manager?.destroy();\r\n if (this.scte35BreakTimeout) clearTimeout(this.scte35BreakTimeout);\r\n }\r\n\r\n /** SCTE-35 OUT sinyali: IMA'ya reklam iste (normal midroll gibi) + IMA cevap vermezse N ms sonra vazgeç. */\r\n private onScte35AdBreakStart(_duration: number | null): void {\r\n this.scte35BreakActive = true;\r\n this.requestAd('Midroll', this.options.live!.adTagLive!);\r\n\r\n const timeoutMs = this.options.live?.breakTimeoutMs ?? 10000;\r\n if (this.scte35BreakTimeout) clearTimeout(this.scte35BreakTimeout);\r\n this.scte35BreakTimeout = setTimeout(() => {\r\n // Ad gerçekten başladıysa (onContentPauseRequested) bu timer zaten iptal edilmiş olur.\r\n this.endScte35Break();\r\n }, timeoutMs);\r\n }\r\n\r\n /** SCTE-35 IN sinyali: yayıncının sinyaline güvenilir — reklam hâlâ oynuyor olsa bile içeriğe dönülür. */\r\n private onScte35AdBreakEnd(): void {\r\n this.endScte35Break();\r\n }\r\n\r\n private endScte35Break(): void {\r\n if (!this.scte35BreakActive) return;\r\n this.scte35BreakActive = false;\r\n if (this.scte35BreakTimeout) {\r\n clearTimeout(this.scte35BreakTimeout);\r\n this.scte35BreakTimeout = null;\r\n }\r\n this.adsManager?.destroy();\r\n this.adsManager = null;\r\n this.hideAdLayer();\r\n if (this.ctx.videoEl.paused) this.ctx.videoEl.play().catch(() => {});\r\n }\r\n\r\n /**\n * initialize() yalnızca 'play'e değil, player'a ilk dokunuşa da bağlı: preroll kullanıcı oynatmadan\n * adsManager.start()'a ulaşabiliyor ve initialize() önce çağrılmazsa IMA AdError 400 veriyor.\n */\r\n readonly initializeDisplayContainerOnce = (): void => {\r\n if (this.displayContainerInitialized) return;\r\n this.displayContainerInitialized = true;\r\n this.adDisplayContainer?.initialize();\r\n };\r\n\r\n private readonly onTimeUpdateForMidroll = (): void => {\r\n const interval = this.options.midrollIntervalSeconds ?? 0;\r\n if (interval <= 0 || !this.options.adTagMidroll) return;\r\n const currentTime = this.ctx.videoEl.currentTime;\r\n if (currentTime > 60 && currentTime - this.lastMidrollTime >= interval) {\r\n this.lastMidrollTime = currentTime;\r\n this.requestAd('Midroll', this.options.adTagMidroll);\r\n }\r\n };\r\n\r\n private readonly onContentEnded = (): void => {\r\n if (this.postrollShown || !this.options.adTagPostroll) return;\r\n this.postrollPending = true;\r\n this.postrollShown = true;\r\n this.requestAd('Postroll', this.options.adTagPostroll);\r\n };\r\n\r\n /** Preroll: options.prebid, Midroll: options.prebid.midroll. Postroll'da prebid yok. */\r\n private getPrebidConfigFor(type: AdBreakType): PrebidBreakOptions | null {\r\n const prebid = this.options.prebid;\r\n if (!prebid) return null;\r\n if (type === 'Preroll') return prebid.enabled ? prebid : null;\r\n if (type === 'Midroll') return prebid.midroll?.enabled ? { ...prebid, ...prebid.midroll } : null;\r\n return null;\r\n }\r\n\r\n private async getOrCreatePrebidInstance(type: AdBreakType, config: PrebidBreakOptions): Promise<VideoPrebid> {\r\n const existing = this.prebidInstances[type];\r\n if (existing) return existing;\r\n\r\n const { VideoPrebid: VideoPrebidClass } = await import('../prebid/VideoPrebid');\r\n const defaultCode = type === 'Midroll' ? 'hope-video-midroll' : 'hope-video-preroll';\r\n const instance = new VideoPrebidClass({\r\n ...config,\r\n adUnitCode: `${config.adUnitCode || defaultCode}-${this.prebidIdSuffix}`,\r\n consentManagement: this.options.prebid?.consentManagement,\r\n });\r\n this.prebidInstances[type] = instance;\r\n return instance;\r\n }\r\n\r\n private async requestAd(type: AdBreakType, rawTag: string | string[], attempt = 0, skipUrlProcessing = false): Promise<void> {\r\n if (!this.adsLoader || !this.ima) return;\r\n this.currentBreakType = type;\r\n\r\n const tag = Array.isArray(rawTag) ? rawTag[0]! : rawTag;\r\n let vastUrl = skipUrlProcessing\r\n ? tag\r\n : generateVastUrl(tag, { includeRefreshCount: !!this.options.retry?.enabled, adRefreshCount: attempt });\r\n\r\n // Prebid yalnızca ham VAST tag'lerinde ve ilk denemede; retry'da auction tekrarlanmaz.\r\n if (!skipUrlProcessing && attempt === 0) {\r\n const prebidConfig = this.getPrebidConfigFor(type);\r\n if (prebidConfig) {\r\n const instance = await this.getOrCreatePrebidInstance(type, prebidConfig);\r\n if (instance.isAvailable()) {\r\n vastUrl = await instance.runAuction(vastUrl);\r\n }\r\n }\r\n }\r\n\r\n if (!this.adsLoader || !this.ima) return; // await sırasında destroy() olmuş olabilir\r\n\r\n const request = new this.ima.AdsRequest();\r\n request.adTagUrl = vastUrl;\r\n request.linearAdSlotWidth = this.ctx.videoEl.clientWidth || 640;\r\n request.linearAdSlotHeight = this.ctx.videoEl.clientHeight || 360;\r\n // Uzun wrapper zincirlerinde SDK'nın 5000ms varsayılanı yetmeyebilir.\r\n request.vastLoadTimeout = this.options.vastLoadTimeoutMs ?? 10000;\r\n\r\n try {\r\n this.adsLoader.requestAds(request);\r\n } catch (err) {\r\n this.giveUpOrRetry(type, String(err));\r\n }\r\n }\r\n\r\n private readonly onAdsManagerLoaded = (event: google.ima.AdsManagerLoadedEvent): void => {\r\n if (!this.ima) return;\r\n this.adsManager = event.getAdsManager(this.ctx.videoEl, {\r\n restoreCustomPlaybackStateOnAdBreakComplete: true,\r\n // VAST çözüldükten sonra creative'in yüklenmesi için üst sınır.\r\n loadVideoTimeout: this.options.loadVideoTimeoutMs ?? 10000,\r\n enablePreloading: true,\r\n // false: IMA'nın KENDİ styled linear ad UI'ı (skip/sayaç\r\n // kutusu) yerine bizim ControlBar'ımız (ad mode) kullanılıyor —\r\n // ikisi üst üste binmesin diye.\r\n useStyledLinearAds: false,\r\n useStyledNonLinearAds: true,\r\n });\r\n\r\n const AdEvent = this.ima.AdEvent;\r\n this.adsManager.addEventListener(AdEvent.Type.CONTENT_PAUSE_REQUESTED, this.onContentPauseRequested);\r\n this.adsManager.addEventListener(AdEvent.Type.CONTENT_RESUME_REQUESTED, this.onContentResumeRequested);\r\n this.adsManager.addEventListener(AdEvent.Type.ALL_ADS_COMPLETED, this.onAllAdsCompleted);\r\n this.adsManager.addEventListener(this.ima.AdErrorEvent.Type.AD_ERROR, this.onAdsManagerError);\r\n // IMA'nın KENDİ reklam UI'ı üzerinden (ör. reklam video'suna tıklama)\r\n // de duraklatılabilir/devam ettirilebilir — bizim toolbar'ımızın\r\n // ikonu bu durumda da senkron kalsın diye dinleniyor.\r\n this.adsManager.addEventListener(AdEvent.Type.PAUSED, this.onAdPaused);\r\n this.adsManager.addEventListener(AdEvent.Type.RESUMED, this.onAdResumed);\r\n\r\n try {\r\n this.adsManager.init(this.ctx.videoEl.clientWidth || 640, this.ctx.videoEl.clientHeight || 360, this.ima.ViewMode.NORMAL);\r\n this.adsManager.start();\r\n } catch (err) {\r\n this.giveUpOrRetry(this.currentBreakType, String(err));\r\n }\r\n };\r\n\r\n /** Toolbar'daki oynat/duraklat butonunun (reklam modunda) hedefi — content videoEl yerine bu çağrılır. */\r\n toggleAdPlayPause(): void {\r\n if (!this.adsManager) return;\r\n if (this.adPaused) this.adsManager.resume();\r\n else this.adsManager.pause();\r\n // Optimistic: IMA'nın PAUSED/RESUMED event'ini beklemeden ikon hemen\r\n // güncellensin — event zaten aynı değere ayarlayıp no-op olacak.\r\n this.adPaused = !this.adPaused;\r\n }\r\n\r\n isAdPaused(): boolean {\r\n return this.adPaused;\r\n }\r\n\r\n getAdVolume(): number {\r\n return this.adsManager?.getVolume() ?? 1;\r\n }\r\n\r\n setAdVolume(volume: number): void {\r\n this.adsManager?.setVolume(Math.min(1, Math.max(0, volume)));\r\n }\r\n\r\n isAdMuted(): boolean {\r\n return this.getAdVolume() === 0;\r\n }\r\n\r\n /** VolumePanel'deki `onToggleMute` ile AYNI desen: 0 ↔ son bilinen (ya da varsayılan 0.5) ses seviyesi arasında geçiş. */\r\n toggleAdMute(): void {\r\n if (!this.adsManager) return;\r\n const current = this.adsManager.getVolume();\r\n if (current > 0) {\r\n this.adVolumeBeforeMute = current;\r\n this.adsManager.setVolume(0);\r\n } else {\r\n this.adsManager.setVolume(this.adVolumeBeforeMute > 0 ? this.adVolumeBeforeMute : 0.5);\r\n }\r\n }\r\n\r\n private readonly onAdPaused = (): void => {\r\n this.adPaused = true;\r\n this.ctx.onAdPlayStateChange?.();\r\n };\r\n\r\n private readonly onAdResumed = (): void => {\r\n this.adPaused = false;\r\n this.ctx.onAdPlayStateChange?.();\r\n };\r\n\r\n private readonly onContentPauseRequested = (): void => {\r\n this.ctx.videoEl.pause();\r\n this.adPaused = false;\r\n this.ctx.hideChrome();\r\n this.ctx.adLayerEl.classList.remove('hp:hidden');\r\n this.ctx.adLayerEl.classList.add('hp:block');\r\n // Reklam gerçekten başladı — retry sayaçlarını sıfırla.\r\n this.retry.reset();\r\n // SCTE-35 ad gerçekten başladı — güvenlik timeout'una artık gerek yok.\r\n if (this.scte35BreakActive && this.scte35BreakTimeout) {\r\n clearTimeout(this.scte35BreakTimeout);\r\n this.scte35BreakTimeout = null;\r\n }\r\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:adstart', { detail: { type: this.breakTypeLower() } }));\r\n };\r\n\r\n private readonly onContentResumeRequested = (): void => {\r\n this.hideAdLayer();\r\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:adend', { detail: { type: this.breakTypeLower() } }));\r\n // Reklam IMA tarafında doğal yoldan (ALL_ADS_COMPLETED) bitti — SCTE-35\r\n // IN sinyali hiç gelmemiş olabilir (broadcaster planlanan süreden\r\n // kısa kesmiş olabilir), bu yüzden flag'i burada da temizliyoruz.\r\n this.scte35BreakActive = false;\r\n\r\n if (this.currentBreakType === 'Preroll') {\r\n this.maybeRequestVmapAfterPreroll();\r\n }\r\n // Postroll'dan sonra play() çağırmak videoyu baştan başlatır — yapma.\r\n if (this.currentBreakType !== 'Postroll') {\r\n this.ctx.videoEl.play().catch(() => {});\r\n }\r\n };\r\n\r\n private readonly onAllAdsCompleted = (): void => {\r\n this.adsManager?.destroy();\r\n this.adsManager = null;\r\n };\r\n\r\n private readonly onAdsLoaderError = (event: google.ima.AdErrorEvent): void => {\r\n this.adsManager?.destroy();\r\n this.adsManager = null;\r\n if (this.scte35BreakActive) {\r\n this.endScte35Break();\r\n return;\r\n }\r\n this.giveUpOrRetry(this.currentBreakType, event.getError?.()?.getMessage?.());\r\n };\r\n\r\n private readonly onAdsManagerError = (event: google.ima.AdErrorEvent): void => {\r\n this.adsManager?.destroy();\r\n this.adsManager = null;\r\n if (this.scte35BreakActive) {\r\n this.endScte35Break();\r\n return;\r\n }\r\n this.giveUpOrRetry(this.currentBreakType, event.getError?.()?.getMessage?.());\r\n };\r\n\r\n private giveUpOrRetry(type: AdBreakType, message?: string): void {\r\n // Canlı + SCTE-35: yayıncının OUT/IN sinyaline güveniliyor, normal\r\n // preroll/midroll fallback zinciri/retry'ı kullanılmıyor.\r\n if (this.scte35BreakActive) {\r\n this.endScte35Break();\r\n return;\r\n }\r\n const rawTag = tagConfigFor(this.options, type);\r\n if (!rawTag) {\r\n this.resumeContentAfterGiveUp(type, message);\r\n return;\r\n }\r\n this.retry.retry(\r\n type,\r\n rawTag,\r\n (tag, attempt) => this.requestAd(type, tag, attempt),\r\n () => this.resumeContentAfterGiveUp(type, message)\r\n );\r\n }\r\n\r\n private resumeContentAfterGiveUp(type: AdBreakType, message?: string): void {\r\n this.hideAdLayer();\r\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:aderror', { detail: { message: message ?? 'ad-error' } }));\r\n if (type === 'Preroll') this.maybeRequestVmapAfterPreroll();\r\n if (type !== 'Postroll' && this.ctx.videoEl.paused) {\r\n this.ctx.videoEl.play().catch(() => {});\r\n }\r\n }\r\n\r\n /** VMAP split: preroll (başarılı ya da vazgeçilerek) bitince, VMAP TAM OLARAK BİR KEZ, değiştirilmeden istenir. */\r\n private maybeRequestVmapAfterPreroll(): void {\r\n if (this.vmapRequested || !this.options.adTagVmap) return;\r\n this.vmapRequested = true;\r\n this.requestAd('Midroll', this.options.adTagVmap, 0, true);\r\n }\r\n\r\n private hideAdLayer(): void {\r\n this.ctx.adLayerEl.classList.add('hp:hidden');\r\n this.ctx.adLayerEl.classList.remove('hp:block');\r\n this.ctx.showChrome();\r\n }\r\n\r\n private breakTypeLower(): 'preroll' | 'midroll' | 'postroll' {\r\n return this.currentBreakType.toLowerCase() as 'preroll' | 'midroll' | 'postroll';\r\n }\r\n}\r\n","import { AdsController, type AdsPlayerContext } from './AdsController';\nimport type { AdsOptions } from '../../types';\n\n/** Reklam plugin'inin giriş noktası — yalnızca options.ads doluyken dinamik import edilir. */\nexport async function installAds(ctx: AdsPlayerContext, options: AdsOptions): Promise<AdsController> {\n const controller = new AdsController(ctx, options);\n await controller.install();\n return controller;\n}\n\nexport { AdsController };\nexport type { AdsPlayerContext };\n"],"names":["IMA_SDK_URL","loadPromise","loadImaSdk","_a","resolve","reject","script","buildAdTaxonomyKeyValues","kv","pairs","key","value","generateVastUrl","baseUrl","options","referrerUrl","descriptionUrl","timestamp","url","params","placeholder","delimiter","parsedUrl","extras","taxonomyKeyValues","custParams","RetryController","config","__publicField","type","rawTag","onRetry","onGiveUp","maxRetry","chain","maxAttemptsPerTag","tag","attempt","existing","tags","t","state","pattern","entry","upTo","delay","jitter","factor","restrictAdsForConsent","ima","reason","err","initConsentAware","uspData","success","tcData","_b","_c","_d","googleVendorConsent","purpose1Consent","parseScte35Base64","base64","binary","bytes","i","spliceEventId","outOfNetwork","programSplice","durationFlag","breakDuration","offset","timeSpecified","autoReturn","duration","parseHlsScteTag","tagName","tagValue","scteOut","scteIn","classAttr","Scte35LiveAdManager","videoEl","callbacks","track","listener","cues","cue","anyCue","match","signal","_forced","tagConfigFor","AdsController","ctx","interval","currentTime","event","AdEvent","hasPageLevelUserActivation","fire","newPrerollTag","_duration","timeoutMs","prebid","VideoPrebidClass","defaultCode","instance","skipUrlProcessing","vastUrl","prebidConfig","request","volume","current","message","installAds","controller"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index-glxDu2eJ.js","sources":["../../src/plugins/ads/loadImaSdk.ts","../../src/plugins/ads/generateVastUrl.ts","../../src/plugins/ads/RetryController.ts","../../src/plugins/ads/consent.ts","../../src/plugins/ads/scte35.ts","../../src/plugins/ads/AdsController.ts","../../src/plugins/ads/index.ts"],"sourcesContent":["const IMA_SDK_URL = 'https://imasdk.googleapis.com/js/sdkloader/ima3.js';\n\ndeclare global {\n interface Window {\n google?: { ima?: typeof google.ima };\n }\n}\n\nlet loadPromise: Promise<typeof google.ima> | null = null;\n\n/** Google IMA SDK'yı bir kez <script> ile yükler. */\nexport function loadImaSdk(): Promise<typeof google.ima> {\n if (window.google?.ima) return Promise.resolve(window.google.ima);\n if (loadPromise) return loadPromise;\n\n loadPromise = new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.src = IMA_SDK_URL;\n script.async = true;\n script.onload = () => {\n if (window.google?.ima) resolve(window.google.ima);\n else reject(new Error('IMA SDK yüklendi ama window.google.ima yok'));\n };\n script.onerror = () => reject(new Error('IMA SDK yüklenemedi (reklam engelleyici olabilir)'));\n document.head.appendChild(script);\n });\n\n return loadPromise;\n}\n","/** adTaxonomy.keyValues → GAM cust_params (key=value, & ile; virgül GAM'de aynı key'in çoklu değer ayracı). */\nfunction buildAdTaxonomyKeyValues(): string {\n const w = window as unknown as { adTaxonomy?: { keyValues?: Record<string, unknown> } };\n const kv = w.adTaxonomy?.keyValues;\n if (!kv || typeof kv !== 'object') return '';\n\n const pairs: string[] = [];\n for (const [key, value] of Object.entries(kv)) {\n if (value === undefined || value === null || value === '') continue;\n pairs.push(`${key}=${value}`);\n }\n return pairs.join('&');\n}\n\nexport interface GenerateVastUrlOptions {\n adRefreshCount?: number;\n /** true ise cust_params'a adrefreshCount eklenir (adsRetry.enabled ile aynı anlam). */\n includeRefreshCount?: boolean;\n}\n\n/** [referrer_url]/[description_url]/[timestamp] placeholder'larını doldurur, cust_params'a adrefreshCount + adTaxonomy ekler. */\nexport function generateVastUrl(baseUrl: string, options: GenerateVastUrlOptions = {}): string {\n const referrerUrl = encodeURIComponent(document.referrer || window.location.href);\n const descriptionUrl = encodeURIComponent(window.location.href);\n const timestamp = Date.now();\n\n let url = baseUrl;\n const params: Record<string, string | number> = {\n referrer_url: referrerUrl,\n description_url: descriptionUrl,\n timestamp,\n };\n\n for (const [key, value] of Object.entries(params)) {\n const placeholder = `[${key}]`;\n if (url.includes(placeholder)) {\n url = url.replace(placeholder, String(value));\n } else if (!new URLSearchParams(url.split('?')[1]).has(key)) {\n const delimiter = url.includes('?') ? '&' : '?';\n url += `${delimiter}${key}=${value}`;\n }\n }\n\n try {\n const parsedUrl = new URL(url);\n const isVmap = parsedUrl.pathname.includes('/vmap/');\n if (isVmap) return baseUrl;\n\n const extras: string[] = [];\n if (options.includeRefreshCount) extras.push(`adrefreshCount=${options.adRefreshCount ?? 0}`);\n const taxonomyKeyValues = buildAdTaxonomyKeyValues();\n if (taxonomyKeyValues) extras.push(taxonomyKeyValues);\n\n if (extras.length) {\n const custParams = parsedUrl.searchParams.get('cust_params');\n parsedUrl.searchParams.set('cust_params', custParams ? `${custParams}&${extras.join('&')}` : extras.join('&'));\n }\n\n return parsedUrl.toString();\n } catch {\n return url;\n }\n}\n","import type { AdsRetryOptions, RetryDelayEntry } from '../../types';\n\nexport type AdBreakType = 'Preroll' | 'Midroll' | 'Postroll';\n\ninterface ChainState {\n tags: string[];\n index: number;\n attemptsOnCurrent: number;\n}\n\n/** Reklam retry zamanlaması ve fallback zinciri kararları (network'ten bağımsız). */\nexport class RetryController {\n private adRetryCount = 0;\n private chain: Partial<Record<AdBreakType, ChainState>> = {};\n private retryTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(private readonly config: AdsRetryOptions) {}\n\n get isPending(): boolean {\n return this.retryTimer !== null;\n }\n\n reset(): void {\n this.adRetryCount = 0;\n this.chain = {};\n this.cancelPending();\n }\n\n cancelPending(): void {\n if (this.retryTimer) {\n clearTimeout(this.retryTimer);\n this.retryTimer = null;\n }\n }\n\n /** Devre dışı/kapsam dışı/limit dolduysa onGiveUp; aksi halde (jitter'lı) gecikmeden sonra onRetry. */\n retry(type: AdBreakType, rawTag: string | string[] | undefined, onRetry: (tag: string, attempt: number) => void, onGiveUp: (reason: 'retry-disabled' | 'retry-limit') => void): void {\n if (!this.config.enabled) {\n onGiveUp('retry-disabled');\n return;\n }\n\n const scope = this.config.retryScope ?? 'preroll';\n if (scope === 'preroll' && type !== 'Preroll') {\n onGiveUp('retry-disabled');\n return;\n }\n\n const maxRetry = this.resolveMaxRetry();\n if (this.adRetryCount >= maxRetry) {\n this.reset();\n onGiveUp('retry-limit');\n return;\n }\n\n this.cancelPending();\n this.adRetryCount++;\n\n const chain = this.getChainState(type, rawTag);\n chain.attemptsOnCurrent++;\n const maxAttemptsPerTag = this.config.maxAttemptsPerTag ?? Infinity;\n if (chain.attemptsOnCurrent > maxAttemptsPerTag && chain.index < chain.tags.length - 1) {\n chain.index++;\n chain.attemptsOnCurrent = 1;\n }\n const tag = chain.tags[chain.index]!;\n const attempt = this.adRetryCount;\n\n this.retryTimer = setTimeout(() => {\n this.retryTimer = null;\n onRetry(tag, attempt);\n }, this.applyJitter(this.resolveRetryDelay()));\n }\n\n private getChainState(type: AdBreakType, rawTag: string | string[] | undefined): ChainState {\n const existing = this.chain[type];\n if (existing) return existing;\n\n const tags = (Array.isArray(rawTag) ? rawTag : [rawTag]).filter((t): t is string => !!t);\n const state: ChainState = { tags: tags.length ? tags : [rawTag as string], index: 0, attemptsOnCurrent: 0 };\n this.chain[type] = state;\n return state;\n }\n\n private resolveRetryDelay(): number {\n const pattern = this.config.retryDelayPattern;\n if (!Array.isArray(pattern) || pattern.length === 0) return this.config.retryDelay ?? 800;\n\n for (const entry of pattern) {\n const [upTo, delay] = this.normalizeEntry(entry);\n if (this.adRetryCount <= upTo) return delay;\n }\n return this.normalizeEntry(pattern[pattern.length - 1]!)[1];\n }\n\n private resolveMaxRetry(): number {\n const pattern = this.config.retryDelayPattern;\n if (Array.isArray(pattern) && pattern.length > 0) {\n return this.normalizeEntry(pattern[pattern.length - 1]!)[0];\n }\n return this.config.maxRetry ?? 10;\n }\n\n private normalizeEntry(entry: RetryDelayEntry): [number, number] {\n return Array.isArray(entry) ? entry : [entry.upTo, entry.delay];\n }\n\n private applyJitter(delay: number): number {\n const jitter = this.config.jitter ?? 0;\n if (!jitter) return delay;\n const factor = 1 + (Math.random() * 2 - 1) * jitter;\n return Math.max(0, Math.round(delay * factor));\n }\n}\n","import type { AdsOptions } from '../../types';\n\n/**\n * Generic TCF/USP consent — options.consentAware === true gerektirir. Non-blocking; yetersiz onay/opt-out'ta\n * google.ima.settings.setPrivacySettings({ nonPersonalizedAds: true }) zorlar.\n */\n\ninterface TcfData {\n gdprApplies?: boolean;\n vendor?: { consents?: Record<number, boolean> };\n purpose?: { consents?: Record<number, boolean> };\n}\n\ndeclare global {\n interface Window {\n __uspapi?: (command: string, version: number, callback: (data: { uspString?: string } | undefined, success: boolean) => void) => void;\n __tcfapi?: (command: string, version: number, callback: (data: TcfData | undefined, success: boolean) => void) => void;\n }\n}\n\nfunction restrictAdsForConsent(ima: typeof google.ima | null, reason: string): void {\n try {\n if (ima?.settings?.setPrivacySettings) {\n ima.settings.setPrivacySettings({ nonPersonalizedAds: true });\n console.warn(`[HopePlayer consent] non-personalized ads zorlandı (${reason})`);\n }\n } catch (err) {\n console.warn('[HopePlayer consent] setPrivacySettings hatası:', err);\n }\n}\n\n/** options.consentAware değilse no-op. IMA TC/GPP string'ini zaten ekliyor; bu ek bir \"Limited Ads\" zorlaması. */\nexport function initConsentAware(options: AdsOptions, ima: typeof google.ima | null): void {\n if (!options.consentAware) return;\n\n try {\n if (typeof window.__uspapi === 'function') {\n window.__uspapi('getUSPData', 1, (uspData, success) => {\n if (!success || !uspData?.uspString) return;\n if (uspData.uspString.charAt(2) === 'Y') restrictAdsForConsent(ima, 'USP/CCPA opt-out');\n });\n }\n } catch (err) {\n console.warn('[HopePlayer consent] __uspapi okuma hatası:', err);\n }\n\n try {\n if (typeof window.__tcfapi === 'function') {\n window.__tcfapi('getTCData', 2, (tcData, success) => {\n if (!success || !tcData || tcData.gdprApplies !== true) return;\n const googleVendorConsent = tcData.vendor?.consents?.[755];\n const purpose1Consent = tcData.purpose?.consents?.[1];\n if (googleVendorConsent === false || purpose1Consent === false) {\n restrictAdsForConsent(ima, 'TCF yetersiz onay');\n }\n });\n }\n } catch (err) {\n console.warn('[HopePlayer consent] __tcfapi okuma hatası:', err);\n }\n}\n","/** SCTE-35 sinyal ayrıştırma + canlı yayın reklam yöneticisi. */\n\nexport interface Scte35Signal {\n type: 'out' | 'in' | 'cancel';\n spliceEventId?: number;\n duration?: number | null;\n breakDuration?: { autoReturn: number; seconds: number } | null;\n programSplice?: boolean;\n class?: string | null;\n raw?: string;\n}\n\n/** Base64 encoded SCTE-35 binary verisini parse eder — yalnızca splice_insert (0x05) komutlarını destekler. */\nexport function parseScte35Base64(base64: string): Scte35Signal | null {\n try {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);\n\n if (bytes[0] !== 0xfc) return null; // table_id\n\n const spliceCommandType = bytes[13];\n if (spliceCommandType !== 0x05) return null; // yalnızca splice_insert\n\n const spliceEventId = ((bytes[14]! << 24) | (bytes[15]! << 16) | (bytes[16]! << 8) | bytes[17]!) >>> 0;\n\n const cancelIndicator = (bytes[18]! >> 7) & 0x01;\n if (cancelIndicator) return { type: 'cancel', spliceEventId };\n\n const outOfNetwork = (bytes[19]! >> 7) & 0x01;\n const programSplice = (bytes[19]! >> 6) & 0x01;\n const durationFlag = (bytes[19]! >> 5) & 0x01;\n\n let breakDuration: Scte35Signal['breakDuration'] = null;\n\n if (programSplice) {\n let offset = 20;\n const timeSpecified = (bytes[offset]! >> 7) & 0x01;\n offset += timeSpecified ? 5 : 1;\n\n if (durationFlag) {\n const autoReturn = (bytes[offset]! >> 7) & 0x01;\n const durationHigh = bytes[offset]! & 0x01;\n const duration =\n durationHigh * Math.pow(2, 32) +\n bytes[offset + 1]! * Math.pow(2, 24) +\n bytes[offset + 2]! * Math.pow(2, 16) +\n bytes[offset + 3]! * Math.pow(2, 8) +\n bytes[offset + 4]!;\n breakDuration = { autoReturn, seconds: duration / 90000 };\n }\n }\n\n return { type: outOfNetwork ? 'out' : 'in', spliceEventId, breakDuration, programSplice: !!programSplice };\n } catch {\n return null;\n }\n}\n\n/** HLS manifest/segment'teki EXT-X-CUE-OUT/IN, EXT-X-DATERANGE, EXT-OATCLS-SCTE35 tag'lerini parse eder. */\nexport function parseHlsScteTag(tagName: string, tagValue: string): Scte35Signal | null {\n if (tagName === 'EXT-X-CUE-OUT') {\n return { type: 'out', duration: parseFloat(tagValue) || null };\n }\n if (tagName === 'EXT-X-CUE-IN') {\n return { type: 'in' };\n }\n if (tagName === 'EXT-X-DATERANGE') {\n const scteOut = tagValue.match(/SCTE35-OUT=0x([0-9A-Fa-f]+)/);\n const scteIn = tagValue.match(/SCTE35-IN=0x([0-9A-Fa-f]+)/);\n const duration = tagValue.match(/PLANNED-DURATION=([\\d.]+)/);\n const classAttr = tagValue.match(/CLASS=\"([^\"]+)\"/);\n\n if (scteOut) {\n return { type: 'out', duration: duration ? parseFloat(duration[1]!) : null, class: classAttr ? classAttr[1]! : null, raw: scteOut[1]! };\n }\n if (scteIn) return { type: 'in', raw: scteIn[1]! };\n }\n if (tagName === 'EXT-OATCLS-SCTE35') {\n return parseScte35Base64(tagValue);\n }\n return null;\n}\n\nexport interface Scte35ManagerCallbacks {\n onAdBreakStart(duration: number | null): void;\n onAdBreakEnd(): void;\n}\n\n/** textTracks metadata cue'larından SCTE-35 sinyallerini dinler (hls.js ve Safari native HLS). */\nexport class Scte35LiveAdManager {\n private inAdBreak = false;\n private adBreakTimer: ReturnType<typeof setTimeout> | null = null;\n private readonly processedEventIds = new Set<number>();\n private readonly trackListeners = new Map<TextTrack, () => void>();\n\n constructor(\n private readonly videoEl: HTMLVideoElement,\n private readonly callbacks: Scte35ManagerCallbacks\n ) {\n this.attachExistingTracks();\n videoEl.textTracks.addEventListener('addtrack', this.onAddTrack);\n }\n\n destroy(): void {\n this.videoEl.textTracks.removeEventListener('addtrack', this.onAddTrack);\n for (const [track, listener] of this.trackListeners) {\n track.removeEventListener('cuechange', listener);\n }\n this.trackListeners.clear();\n if (this.adBreakTimer) clearTimeout(this.adBreakTimer);\n this.processedEventIds.clear();\n }\n\n private readonly onAddTrack = (e: TrackEvent): void => {\n if (e.track instanceof TextTrack) this.listenTrack(e.track);\n };\n\n private attachExistingTracks(): void {\n for (let i = 0; i < this.videoEl.textTracks.length; i++) {\n this.listenTrack(this.videoEl.textTracks[i]!);\n }\n }\n\n private listenTrack(track: TextTrack): void {\n if (track.kind !== 'metadata' || this.trackListeners.has(track)) return;\n track.mode = 'hidden'; // cue'lar işlensin diye aktif olmalı ama görünmesin.\n\n const listener = () => {\n const cues = track.activeCues;\n if (!cues) return;\n for (let i = 0; i < cues.length; i++) this.processCue(cues[i]!);\n };\n track.addEventListener('cuechange', listener);\n this.trackListeners.set(track, listener);\n }\n\n private processCue(cue: TextTrackCue): void {\n const anyCue = cue as unknown as { value?: { key?: string; data?: string; value?: string }; text?: string };\n let tagName: string | null = null;\n let tagValue = '';\n\n if (anyCue.value && typeof anyCue.value === 'object') {\n tagName = anyCue.value.key ?? null;\n tagValue = anyCue.value.data ?? anyCue.value.value ?? '';\n } else if (typeof anyCue.text === 'string') {\n const match = anyCue.text.match(/^(EXT[^:]+):?(.*)$/);\n if (match) {\n tagName = match[1]!;\n tagValue = match[2] ?? '';\n }\n }\n\n if (!tagName) return;\n const signal = parseHlsScteTag(tagName, tagValue);\n if (signal) this.handleSignal(signal);\n }\n\n private handleSignal(signal: Scte35Signal): void {\n if (signal.spliceEventId !== undefined) {\n if (this.processedEventIds.has(signal.spliceEventId)) return;\n this.processedEventIds.add(signal.spliceEventId);\n setTimeout(() => this.processedEventIds.delete(signal.spliceEventId!), 5 * 60 * 1000);\n }\n\n if (signal.type === 'cancel') {\n this.endAdBreak(true);\n return;\n }\n if (signal.type === 'out' && !this.inAdBreak) {\n this.startAdBreak(signal.breakDuration?.seconds ?? signal.duration ?? null);\n } else if (signal.type === 'in' && this.inAdBreak) {\n this.endAdBreak(false);\n }\n }\n\n private startAdBreak(duration: number | null): void {\n if (this.inAdBreak) return;\n this.inAdBreak = true;\n this.callbacks.onAdBreakStart(duration);\n\n if (duration && duration > 0) {\n this.adBreakTimer = setTimeout(() => {\n if (this.inAdBreak) this.endAdBreak(true);\n }, (duration + 5) * 1000);\n }\n }\n\n endAdBreak(_forced = false): void {\n if (!this.inAdBreak) return;\n this.inAdBreak = false;\n if (this.adBreakTimer) {\n clearTimeout(this.adBreakTimer);\n this.adBreakTimer = null;\n }\n this.callbacks.onAdBreakEnd();\n }\n}\n","import { loadImaSdk } from './loadImaSdk';\nimport { generateVastUrl } from './generateVastUrl';\nimport { RetryController, type AdBreakType } from './RetryController';\nimport { initConsentAware } from './consent';\nimport { Scte35LiveAdManager } from './scte35';\nimport type { AdsOptions, PrebidBreakOptions } from '../../types';\nimport type { VideoPrebid } from '../prebid/VideoPrebid';\n\nexport interface AdsPlayerContext {\n videoEl: HTMLVideoElement;\n hostEl: HTMLElement;\n /** IMA'nın ad UI'ını (skip butonu/sayaç) çizdiği, video'nun üzerindeki katman. */\n adLayerEl: HTMLElement;\n hideChrome(): void;\n showChrome(): void;\n /** `options.locale` (ör. 'tr'/'en') — IMA SDK'nın KENDİ ad-UI'ının (skip butonu/sayaç/\"Reklam\" etiketi) dili de oynatıcının geri kalanıyla AYNI dili takip etsin diye `ima.settings.setLocale()`'a aktarılıyor. */\n locale: string;\n /** Reklamın oynat/duraklat durumu DIŞARIDAN (IMA'nın kendi UI'ı üzerinden) değişince toolbar'ı tazelemesi için — bkz. `adPaused` notu. */\n onAdPlayStateChange?(): void;\n}\n\nfunction tagConfigFor(options: AdsOptions, type: AdBreakType): string | string[] | undefined {\n if (type === 'Preroll') return options.adTagPreroll;\n if (type === 'Midroll') return options.adTagMidroll;\n return options.adTagPostroll;\n}\n\n/** Google IMA SDK ile doğrudan konuşan reklam çekirdeği (preroll/midroll/postroll, VMAP, retry, Prebid, SCTE-35). */\nexport class AdsController {\n private ima: typeof google.ima | null = null;\n private adDisplayContainer: google.ima.AdDisplayContainer | null = null;\n private adsLoader: google.ima.AdsLoader | null = null;\n private adsManager: google.ima.AdsManager | null = null;\n\n private readonly retry: RetryController;\n private currentBreakType: AdBreakType = 'Preroll';\n private vmapRequested = false;\n private postrollPending = false;\n private postrollShown = false;\n private lastMidrollTime = 0;\n private displayContainerInitialized = false;\n /**\n * Reklam sırasında toolbar oynat/duraklat + ses buraya yönlenir (IMA reklamı ayrı bir video'da oynatır).\n * Durum hem bizim çağrılarımızdan hem IMA'nın kendi PAUSED/RESUMED event'lerinden senkron tutulur.\n */\n private adPaused = false;\n private adVolumeBeforeMute = 1;\n private readonly prebidIdSuffix: string;\n private readonly prebidInstances: Partial<Record<AdBreakType, VideoPrebid>> = {};\n private scte35Manager: Scte35LiveAdManager | null = null;\n private scte35BreakActive = false;\n private scte35BreakTimeout: ReturnType<typeof setTimeout> | null = null;\n\n constructor(\n private readonly ctx: AdsPlayerContext,\n readonly options: AdsOptions\n ) {\n this.retry = new RetryController(options.retry ?? {});\n this.prebidIdSuffix = ctx.hostEl.id || Math.random().toString(36).slice(2, 8);\n }\n\n async install(): Promise<void> {\n let ima: typeof google.ima;\n try {\n ima = await loadImaSdk();\n } catch (err) {\n // Reklam engelleyici / ağ hatası — içerik reklamsız normal oynar.\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:aderror', { detail: { message: String(err) } }));\n return;\n }\n this.ima = ima;\n\n try {\n ima.settings.setLocale(this.ctx.locale);\n } catch {\n /* eski SDK sürümünde olmayabilir — kritik değil */\n }\n\n // setNumRedirects kritik: SDK varsayılanı 4 wrapper — çok hoplu zincirlerde IMA reklamı hata vermeden bırakır.\n // Her ayar ayrı try/catch'te (eski SDK'da olmayabilir).\n try {\n ima.settings.setNumRedirects(this.options.numRedirects ?? 15);\n } catch {\n /* eski SDK sürümünde olmayabilir */\n }\n try {\n ima.settings.setDisableCustomPlaybackForIOS10Plus(true);\n } catch {\n /* eski SDK sürümünde olmayabilir */\n }\n try {\n if (ima.ImaSdkSettings?.VpaidMode) {\n ima.settings.setVpaidMode(ima.ImaSdkSettings.VpaidMode.INSECURE);\n }\n } catch {\n /* eski SDK sürümünde olmayabilir */\n }\n\n // consentAware (TCF/USP) — options.consentAware===true gerektirir, non-blocking.\n initConsentAware(this.options, this.ima);\n\n this.adDisplayContainer = new ima.AdDisplayContainer(this.ctx.adLayerEl, this.ctx.videoEl);\n this.adsLoader = new ima.AdsLoader(this.adDisplayContainer);\n this.adsLoader.addEventListener(ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, this.onAdsManagerLoaded);\n this.adsLoader.addEventListener(ima.AdErrorEvent.Type.AD_ERROR, this.onAdsLoaderError);\n\n // iOS/Safari: AdDisplayContainer.initialize() kullanıcı jestiyle çağrılmalı.\n this.ctx.videoEl.addEventListener('play', this.initializeDisplayContainerOnce);\n\n // Plugin dinamik yüklendiği için autoplay video'yu bu dinleyici bağlanmadan başlatmış olabilir —\n // kaçırılan 'play'i telafi et, yoksa initialize() hiç çağrılmaz (AdError 400).\n const hasPageLevelUserActivation =\n typeof navigator !== 'undefined' &&\n 'userActivation' in navigator &&\n (navigator as unknown as { userActivation: { hasBeenActive: boolean } }).userActivation.hasBeenActive;\n if (!this.ctx.videoEl.paused || hasPageLevelUserActivation) {\n this.initializeDisplayContainerOnce();\n }\n\n if (this.options.adTagPostroll) {\n this.ctx.videoEl.addEventListener('ended', this.onContentEnded);\n }\n\n if (this.options.adTagMidroll && !this.options.adTagVmap && this.options.midrollIntervalSeconds) {\n this.ctx.videoEl.addEventListener('timeupdate', this.onTimeUpdateForMidroll);\n }\n\n this.requestInitialPrerollOrVmap();\n\n // Canlı + SCTE-35: normal preroll/midroll zamanlayıcısı yerine yayın\n // içindeki OUT/IN sinyalleri reklamı tetikler/bitirir — preroll YOK\n // (yayının \"başlangıcı\" olmadığı için auto-request edilmiyor).\n if (this.options.live?.scte35 && this.options.live.adTagLive) {\n this.scte35Manager = new Scte35LiveAdManager(this.ctx.videoEl, {\n onAdBreakStart: (duration) => this.onScte35AdBreakStart(duration),\n onAdBreakEnd: () => this.onScte35AdBreakEnd(),\n });\n }\n }\n\n /** requestOnPlay yoksa preroll/VMAP hemen istenir; varsa kullanıcı oynatana kadar ertelenir. */\n private requestInitialPrerollOrVmap(): void {\n const fire = (): void => {\n if (this.options.adTagPreroll) {\n this.requestAd('Preroll', this.options.adTagPreroll);\n } else if (this.options.adTagVmap) {\n // Ayrı bir preroll tag'i yok — VMAP tek başına (preroll dahil) kullanılıyor.\n this.vmapRequested = true;\n this.requestAd('Preroll', this.options.adTagVmap, 0, true);\n }\n };\n if (!this.options.requestOnPlay || !this.ctx.videoEl.paused) {\n fire();\n return;\n }\n this.ctx.videoEl.addEventListener('play', fire, { once: true });\n }\n\n /** Playlist/story item değişiminde: önceki item'ın reklam durumunu sıfırla. */\n resetForNewItem(newPrerollTag?: string | string[]): void {\n this.retry.reset();\n this.vmapRequested = false;\n this.postrollShown = false;\n this.postrollPending = false;\n this.lastMidrollTime = 0;\n if (newPrerollTag !== undefined) this.options.adTagPreroll = newPrerollTag;\n\n if (this.options.adTagPreroll) {\n void this.requestAd('Preroll', this.options.adTagPreroll);\n } else if (this.options.adTagVmap) {\n this.vmapRequested = true;\n void this.requestAd('Preroll', this.options.adTagVmap, 0, true);\n }\n }\n\n destroy(): void {\n this.ctx.videoEl.removeEventListener('play', this.initializeDisplayContainerOnce);\n this.ctx.videoEl.removeEventListener('ended', this.onContentEnded);\n this.ctx.videoEl.removeEventListener('timeupdate', this.onTimeUpdateForMidroll);\n this.retry.cancelPending();\n this.adsManager?.destroy();\n this.adsLoader?.destroy();\n this.adDisplayContainer?.destroy();\n this.scte35Manager?.destroy();\n if (this.scte35BreakTimeout) clearTimeout(this.scte35BreakTimeout);\n }\n\n /** SCTE-35 OUT sinyali: IMA'ya reklam iste (normal midroll gibi) + IMA cevap vermezse N ms sonra vazgeç. */\n private onScte35AdBreakStart(_duration: number | null): void {\n this.scte35BreakActive = true;\n this.requestAd('Midroll', this.options.live!.adTagLive!);\n\n const timeoutMs = this.options.live?.breakTimeoutMs ?? 10000;\n if (this.scte35BreakTimeout) clearTimeout(this.scte35BreakTimeout);\n this.scte35BreakTimeout = setTimeout(() => {\n // Ad gerçekten başladıysa (onContentPauseRequested) bu timer zaten iptal edilmiş olur.\n this.endScte35Break();\n }, timeoutMs);\n }\n\n /** SCTE-35 IN sinyali: yayıncının sinyaline güvenilir — reklam hâlâ oynuyor olsa bile içeriğe dönülür. */\n private onScte35AdBreakEnd(): void {\n this.endScte35Break();\n }\n\n private endScte35Break(): void {\n if (!this.scte35BreakActive) return;\n this.scte35BreakActive = false;\n if (this.scte35BreakTimeout) {\n clearTimeout(this.scte35BreakTimeout);\n this.scte35BreakTimeout = null;\n }\n this.adsManager?.destroy();\n this.adsManager = null;\n this.hideAdLayer();\n if (this.ctx.videoEl.paused) this.ctx.videoEl.play().catch(() => {});\n }\n\n /**\n * initialize() yalnızca 'play'e değil, player'a ilk dokunuşa da bağlı: preroll kullanıcı oynatmadan\n * adsManager.start()'a ulaşabiliyor ve initialize() önce çağrılmazsa IMA AdError 400 veriyor.\n */\n readonly initializeDisplayContainerOnce = (): void => {\n if (this.displayContainerInitialized) return;\n this.displayContainerInitialized = true;\n this.adDisplayContainer?.initialize();\n };\n\n private readonly onTimeUpdateForMidroll = (): void => {\n const interval = this.options.midrollIntervalSeconds ?? 0;\n if (interval <= 0 || !this.options.adTagMidroll) return;\n const currentTime = this.ctx.videoEl.currentTime;\n if (currentTime > 60 && currentTime - this.lastMidrollTime >= interval) {\n this.lastMidrollTime = currentTime;\n this.requestAd('Midroll', this.options.adTagMidroll);\n }\n };\n\n private readonly onContentEnded = (): void => {\n if (this.postrollShown || !this.options.adTagPostroll) return;\n this.postrollPending = true;\n this.postrollShown = true;\n this.requestAd('Postroll', this.options.adTagPostroll);\n };\n\n /** Preroll: options.prebid, Midroll: options.prebid.midroll. Postroll'da prebid yok. */\n private getPrebidConfigFor(type: AdBreakType): PrebidBreakOptions | null {\n const prebid = this.options.prebid;\n if (!prebid) return null;\n if (type === 'Preroll') return prebid.enabled ? prebid : null;\n if (type === 'Midroll') return prebid.midroll?.enabled ? { ...prebid, ...prebid.midroll } : null;\n return null;\n }\n\n private async getOrCreatePrebidInstance(type: AdBreakType, config: PrebidBreakOptions): Promise<VideoPrebid> {\n const existing = this.prebidInstances[type];\n if (existing) return existing;\n\n const { VideoPrebid: VideoPrebidClass } = await import('../prebid/VideoPrebid');\n const defaultCode = type === 'Midroll' ? 'hope-video-midroll' : 'hope-video-preroll';\n const instance = new VideoPrebidClass({\n ...config,\n adUnitCode: `${config.adUnitCode || defaultCode}-${this.prebidIdSuffix}`,\n consentManagement: this.options.prebid?.consentManagement,\n });\n this.prebidInstances[type] = instance;\n return instance;\n }\n\n private async requestAd(type: AdBreakType, rawTag: string | string[], attempt = 0, skipUrlProcessing = false): Promise<void> {\n if (!this.adsLoader || !this.ima) return;\n this.currentBreakType = type;\n\n const tag = Array.isArray(rawTag) ? rawTag[0]! : rawTag;\n let vastUrl = skipUrlProcessing\n ? tag\n : generateVastUrl(tag, { includeRefreshCount: !!this.options.retry?.enabled, adRefreshCount: attempt });\n\n // Prebid yalnızca ham VAST tag'lerinde ve ilk denemede; retry'da auction tekrarlanmaz.\n if (!skipUrlProcessing && attempt === 0) {\n const prebidConfig = this.getPrebidConfigFor(type);\n if (prebidConfig) {\n const instance = await this.getOrCreatePrebidInstance(type, prebidConfig);\n if (instance.isAvailable()) {\n vastUrl = await instance.runAuction(vastUrl);\n }\n }\n }\n\n if (!this.adsLoader || !this.ima) return; // await sırasında destroy() olmuş olabilir\n\n const request = new this.ima.AdsRequest();\n request.adTagUrl = vastUrl;\n request.linearAdSlotWidth = this.ctx.videoEl.clientWidth || 640;\n request.linearAdSlotHeight = this.ctx.videoEl.clientHeight || 360;\n // Uzun wrapper zincirlerinde SDK'nın 5000ms varsayılanı yetmeyebilir.\n request.vastLoadTimeout = this.options.vastLoadTimeoutMs ?? 10000;\n\n try {\n this.adsLoader.requestAds(request);\n } catch (err) {\n this.giveUpOrRetry(type, String(err));\n }\n }\n\n private readonly onAdsManagerLoaded = (event: google.ima.AdsManagerLoadedEvent): void => {\n if (!this.ima) return;\n this.adsManager = event.getAdsManager(this.ctx.videoEl, {\n restoreCustomPlaybackStateOnAdBreakComplete: true,\n // VAST çözüldükten sonra creative'in yüklenmesi için üst sınır.\n loadVideoTimeout: this.options.loadVideoTimeoutMs ?? 10000,\n enablePreloading: true,\n // false: IMA'nın KENDİ styled linear ad UI'ı (skip/sayaç\n // kutusu) yerine bizim ControlBar'ımız (ad mode) kullanılıyor —\n // ikisi üst üste binmesin diye.\n useStyledLinearAds: false,\n useStyledNonLinearAds: true,\n });\n\n const AdEvent = this.ima.AdEvent;\n this.adsManager.addEventListener(AdEvent.Type.CONTENT_PAUSE_REQUESTED, this.onContentPauseRequested);\n this.adsManager.addEventListener(AdEvent.Type.CONTENT_RESUME_REQUESTED, this.onContentResumeRequested);\n this.adsManager.addEventListener(AdEvent.Type.ALL_ADS_COMPLETED, this.onAllAdsCompleted);\n this.adsManager.addEventListener(this.ima.AdErrorEvent.Type.AD_ERROR, this.onAdsManagerError);\n // IMA'nın KENDİ reklam UI'ı üzerinden (ör. reklam video'suna tıklama)\n // de duraklatılabilir/devam ettirilebilir — bizim toolbar'ımızın\n // ikonu bu durumda da senkron kalsın diye dinleniyor.\n this.adsManager.addEventListener(AdEvent.Type.PAUSED, this.onAdPaused);\n this.adsManager.addEventListener(AdEvent.Type.RESUMED, this.onAdResumed);\n\n try {\n this.adsManager.init(this.ctx.videoEl.clientWidth || 640, this.ctx.videoEl.clientHeight || 360, this.ima.ViewMode.NORMAL);\n this.adsManager.start();\n } catch (err) {\n this.giveUpOrRetry(this.currentBreakType, String(err));\n }\n };\n\n /** Toolbar'daki oynat/duraklat butonunun (reklam modunda) hedefi — content videoEl yerine bu çağrılır. */\n toggleAdPlayPause(): void {\n if (!this.adsManager) return;\n if (this.adPaused) this.adsManager.resume();\n else this.adsManager.pause();\n // Optimistic: IMA'nın PAUSED/RESUMED event'ini beklemeden ikon hemen\n // güncellensin — event zaten aynı değere ayarlayıp no-op olacak.\n this.adPaused = !this.adPaused;\n }\n\n isAdPaused(): boolean {\n return this.adPaused;\n }\n\n getAdVolume(): number {\n return this.adsManager?.getVolume() ?? 1;\n }\n\n setAdVolume(volume: number): void {\n this.adsManager?.setVolume(Math.min(1, Math.max(0, volume)));\n }\n\n isAdMuted(): boolean {\n return this.getAdVolume() === 0;\n }\n\n /** VolumePanel'deki `onToggleMute` ile AYNI desen: 0 ↔ son bilinen (ya da varsayılan 0.5) ses seviyesi arasında geçiş. */\n toggleAdMute(): void {\n if (!this.adsManager) return;\n const current = this.adsManager.getVolume();\n if (current > 0) {\n this.adVolumeBeforeMute = current;\n this.adsManager.setVolume(0);\n } else {\n this.adsManager.setVolume(this.adVolumeBeforeMute > 0 ? this.adVolumeBeforeMute : 0.5);\n }\n }\n\n private readonly onAdPaused = (): void => {\n this.adPaused = true;\n this.ctx.onAdPlayStateChange?.();\n };\n\n private readonly onAdResumed = (): void => {\n this.adPaused = false;\n this.ctx.onAdPlayStateChange?.();\n };\n\n private readonly onContentPauseRequested = (): void => {\n this.ctx.videoEl.pause();\n this.adPaused = false;\n this.ctx.hideChrome();\n this.ctx.adLayerEl.classList.remove('hp:hidden');\n this.ctx.adLayerEl.classList.add('hp:block');\n // Reklam gerçekten başladı — retry sayaçlarını sıfırla.\n this.retry.reset();\n // SCTE-35 ad gerçekten başladı — güvenlik timeout'una artık gerek yok.\n if (this.scte35BreakActive && this.scte35BreakTimeout) {\n clearTimeout(this.scte35BreakTimeout);\n this.scte35BreakTimeout = null;\n }\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:adstart', { detail: { type: this.breakTypeLower() } }));\n };\n\n private readonly onContentResumeRequested = (): void => {\n this.hideAdLayer();\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:adend', { detail: { type: this.breakTypeLower() } }));\n // Reklam IMA tarafında doğal yoldan (ALL_ADS_COMPLETED) bitti — SCTE-35\n // IN sinyali hiç gelmemiş olabilir (broadcaster planlanan süreden\n // kısa kesmiş olabilir), bu yüzden flag'i burada da temizliyoruz.\n this.scte35BreakActive = false;\n\n if (this.currentBreakType === 'Preroll') {\n this.maybeRequestVmapAfterPreroll();\n }\n // Postroll'dan sonra play() çağırmak videoyu baştan başlatır — yapma.\n if (this.currentBreakType !== 'Postroll') {\n this.ctx.videoEl.play().catch(() => {});\n }\n };\n\n private readonly onAllAdsCompleted = (): void => {\n this.adsManager?.destroy();\n this.adsManager = null;\n };\n\n private readonly onAdsLoaderError = (event: google.ima.AdErrorEvent): void => {\n this.adsManager?.destroy();\n this.adsManager = null;\n if (this.scte35BreakActive) {\n this.endScte35Break();\n return;\n }\n this.giveUpOrRetry(this.currentBreakType, event.getError?.()?.getMessage?.());\n };\n\n private readonly onAdsManagerError = (event: google.ima.AdErrorEvent): void => {\n this.adsManager?.destroy();\n this.adsManager = null;\n if (this.scte35BreakActive) {\n this.endScte35Break();\n return;\n }\n this.giveUpOrRetry(this.currentBreakType, event.getError?.()?.getMessage?.());\n };\n\n private giveUpOrRetry(type: AdBreakType, message?: string): void {\n // Canlı + SCTE-35: yayıncının OUT/IN sinyaline güveniliyor, normal\n // preroll/midroll fallback zinciri/retry'ı kullanılmıyor.\n if (this.scte35BreakActive) {\n this.endScte35Break();\n return;\n }\n const rawTag = tagConfigFor(this.options, type);\n if (!rawTag) {\n this.resumeContentAfterGiveUp(type, message);\n return;\n }\n this.retry.retry(\n type,\n rawTag,\n (tag, attempt) => this.requestAd(type, tag, attempt),\n () => this.resumeContentAfterGiveUp(type, message)\n );\n }\n\n private resumeContentAfterGiveUp(type: AdBreakType, message?: string): void {\n this.hideAdLayer();\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:aderror', { detail: { message: message ?? 'ad-error' } }));\n if (type === 'Preroll') this.maybeRequestVmapAfterPreroll();\n if (type !== 'Postroll' && this.ctx.videoEl.paused) {\n this.ctx.videoEl.play().catch(() => {});\n }\n }\n\n /** VMAP split: preroll (başarılı ya da vazgeçilerek) bitince, VMAP TAM OLARAK BİR KEZ, değiştirilmeden istenir. */\n private maybeRequestVmapAfterPreroll(): void {\n if (this.vmapRequested || !this.options.adTagVmap) return;\n this.vmapRequested = true;\n this.requestAd('Midroll', this.options.adTagVmap, 0, true);\n }\n\n private hideAdLayer(): void {\n this.ctx.adLayerEl.classList.add('hp:hidden');\n this.ctx.adLayerEl.classList.remove('hp:block');\n this.ctx.showChrome();\n }\n\n private breakTypeLower(): 'preroll' | 'midroll' | 'postroll' {\n return this.currentBreakType.toLowerCase() as 'preroll' | 'midroll' | 'postroll';\n }\n}\n","import { AdsController, type AdsPlayerContext } from './AdsController';\nimport type { AdsOptions } from '../../types';\n\n/** Reklam plugin'inin giriş noktası — yalnızca options.ads doluyken dinamik import edilir. */\nexport async function installAds(ctx: AdsPlayerContext, options: AdsOptions): Promise<AdsController> {\n const controller = new AdsController(ctx, options);\n await controller.install();\n return controller;\n}\n\nexport { AdsController };\nexport type { AdsPlayerContext };\n"],"names":["IMA_SDK_URL","loadPromise","loadImaSdk","_a","resolve","reject","script","buildAdTaxonomyKeyValues","kv","pairs","key","value","generateVastUrl","baseUrl","options","referrerUrl","descriptionUrl","timestamp","url","params","placeholder","delimiter","parsedUrl","extras","taxonomyKeyValues","custParams","RetryController","config","__publicField","type","rawTag","onRetry","onGiveUp","maxRetry","chain","maxAttemptsPerTag","tag","attempt","existing","tags","t","state","pattern","entry","upTo","delay","jitter","factor","restrictAdsForConsent","ima","reason","err","initConsentAware","uspData","success","tcData","_b","_c","_d","googleVendorConsent","purpose1Consent","parseScte35Base64","base64","binary","bytes","i","spliceEventId","outOfNetwork","programSplice","durationFlag","breakDuration","offset","timeSpecified","autoReturn","duration","parseHlsScteTag","tagName","tagValue","scteOut","scteIn","classAttr","Scte35LiveAdManager","videoEl","callbacks","track","listener","cues","cue","anyCue","match","signal","_forced","tagConfigFor","AdsController","ctx","interval","currentTime","event","AdEvent","hasPageLevelUserActivation","fire","newPrerollTag","_duration","timeoutMs","prebid","VideoPrebidClass","defaultCode","instance","skipUrlProcessing","vastUrl","prebidConfig","request","volume","current","message","installAds","controller"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
var u = Object.defineProperty;
|
|
2
2
|
var m = (p, e, t) => e in p ? u(p, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : p[e] = t;
|
|
3
3
|
var o = (p, e, t) => m(p, typeof e != "symbol" ? e + "" : e, t);
|
|
4
|
-
import { c as b } from "./index-
|
|
4
|
+
import { c as b } from "./index-BjmWoP4E.js";
|
|
5
5
|
const f = {
|
|
6
6
|
enabled: !1,
|
|
7
7
|
mode: "rich",
|
|
@@ -202,4 +202,4 @@ export {
|
|
|
202
202
|
v as MarkProgress,
|
|
203
203
|
y as installMarkers
|
|
204
204
|
};
|
|
205
|
-
//# sourceMappingURL=index-
|
|
205
|
+
//# sourceMappingURL=index-lrAXde76.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-DXf2Al1x.js","sources":["../../src/plugins/markers/MarkProgress.ts","../../src/plugins/markers/index.ts"],"sourcesContent":["import { createIcon } from '../../icons/Icon';\nimport type { MarkerItem, MarkerPingOptions, MarkerPopupOptions, MarkersOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\n\nexport interface MarkersPlayerContext {\n videoEl: HTMLVideoElement;\n /** Popup overlay'in ekleneceği katman (shadow root içinde, video üzerinde). */\n overlayContainerEl: HTMLElement;\n /** Seek bar üzerinde işaretçi çizmek için — SeekBar.addMarker ile aynı imza. */\n addSeekBarMarker(ratio: number, extraClass?: string): HTMLDivElement;\n i18n: HopeLocaleStrings;\n}\n\ninterface NormalizedMarker extends Required<Pick<MarkerItem, 'time'>> {\n idx: number;\n color?: string;\n label: string;\n pauseOnHit: boolean;\n once: boolean;\n tolerance: number;\n cooldownMs: number;\n action?: MarkerItem['action'];\n popup: MarkerPopupOptions | null;\n pingUrl: string;\n el?: HTMLElement;\n}\n\nconst POPUP_DEFAULTS: Required<MarkerPopupOptions> = {\n enabled: false,\n mode: 'rich',\n text: '',\n imageUrl: '',\n imageAlt: '',\n linkUrl: '',\n // Boş bırakılıyor (sentinel) — gerçek varsayılan metin showPopup()'ta\n // `ctx.i18n.markerLearnMore`/`markerContinue`'dan okunuyor, dil\n // değişimini takip edebilsin diye burada SABİT bir dilde gömülü değil.\n linkText: '',\n continueText: '',\n showContinue: true,\n showClose: true,\n autoplayOnClose: true,\n autoplayOnContinue: true,\n};\n\nconst PING_DEFAULTS: Required<MarkerPingOptions> = { enabled: false, url: '', method: 'GET', includeMarker: false };\n\n/** Zaman tabanlı seek bar işaretçileri — seek/jump koruması, once/cooldown, popup/ping/aksiyon. */\nexport class MarkProgress {\n private readonly markers: NormalizedMarker[];\n private readonly popupGlobal: Required<MarkerPopupOptions>;\n private readonly pingGlobal: Required<MarkerPingOptions>;\n private readonly triggerOnSeek: boolean;\n private readonly seekJumpThresholdSec: number;\n private readonly seekIgnoreWindowMs: number;\n\n private hitSet = new Set<string>();\n private lastHitAt = new Map<string, number>();\n private lastTime = 0;\n private isSeeking = false;\n private ignoreUntilTs = 0;\n private popupEl: HTMLElement | null = null;\n\n constructor(\n private readonly ctx: MarkersPlayerContext,\n options: MarkersOptions\n ) {\n this.triggerOnSeek = options.triggerOnSeek === true;\n this.seekJumpThresholdSec = options.seekJumpThresholdSec ?? 1;\n this.seekIgnoreWindowMs = options.seekIgnoreWindowMs ?? 250;\n this.popupGlobal = { ...POPUP_DEFAULTS, ...options.popup };\n this.pingGlobal = { ...PING_DEFAULTS, ...options.ping };\n\n this.markers = (options.items || [])\n .map((m, idx) => this.normalize(m, idx))\n .filter((m) => Number.isFinite(m.time) && m.time >= 0)\n .sort((a, b) => a.time - b.time);\n\n ctx.videoEl.addEventListener('loadedmetadata', this.onLoadedMetadata);\n ctx.videoEl.addEventListener('timeupdate', this.onTimeUpdate);\n ctx.videoEl.addEventListener('seeking', this.onSeeking);\n ctx.videoEl.addEventListener('seeked', this.onSeeked);\n\n if (ctx.videoEl.readyState >= 1) this.onLoadedMetadata();\n }\n\n /** Popup lazy oluşturulup yeniden kullanılıyor (`ensurePopup`) — zaten açıksa close butonunun statik etiketini tazeler. */\n refreshLabels(): void {\n const closeBtn = this.popupEl?.querySelector('button') as HTMLButtonElement | null;\n if (closeBtn) {\n closeBtn.setAttribute('aria-label', this.ctx.i18n.close);\n }\n }\n\n destroy(): void {\n this.ctx.videoEl.removeEventListener('loadedmetadata', this.onLoadedMetadata);\n this.ctx.videoEl.removeEventListener('timeupdate', this.onTimeUpdate);\n this.ctx.videoEl.removeEventListener('seeking', this.onSeeking);\n this.ctx.videoEl.removeEventListener('seeked', this.onSeeked);\n this.markers.forEach((m) => m.el?.remove());\n this.popupEl?.remove();\n this.popupEl = null;\n this.hitSet.clear();\n this.lastHitAt.clear();\n }\n\n private normalize(m: MarkerItem, idx: number): NormalizedMarker {\n return {\n idx,\n time: Number(m.time),\n color: m.color,\n label: m.label ?? '',\n pauseOnHit: m.pauseOnHit ?? true,\n once: m.once ?? true,\n tolerance: m.tolerance ?? 0.25,\n cooldownMs: m.cooldownMs ?? 600,\n action: m.action,\n popup: m.popup ?? null,\n pingUrl: m.pingUrl ?? '',\n };\n }\n\n private readonly onLoadedMetadata = (): void => {\n const duration = this.ctx.videoEl.duration;\n if (!Number.isFinite(duration) || duration <= 0) return;\n\n this.markers.forEach((m) => {\n if (m.el) return;\n const el = this.ctx.addSeekBarMarker(m.time / duration);\n if (m.color) el.style.backgroundColor = m.color;\n if (m.label) el.title = m.label;\n m.el = el;\n });\n\n this.lastTime = this.ctx.videoEl.currentTime || 0;\n };\n\n private readonly onSeeking = (): void => {\n this.isSeeking = true;\n this.ignoreUntilTs = Date.now() + this.seekIgnoreWindowMs;\n this.lastTime = this.ctx.videoEl.currentTime || 0;\n };\n\n private readonly onSeeked = (): void => {\n this.lastTime = this.ctx.videoEl.currentTime || 0;\n this.isSeeking = false;\n this.ignoreUntilTs = Date.now() + this.seekIgnoreWindowMs;\n };\n\n private readonly onTimeUpdate = (): void => {\n const now = Date.now();\n if (now < this.ignoreUntilTs) return;\n if (this.isSeeking) return;\n\n const t = this.ctx.videoEl.currentTime;\n if (!Number.isFinite(t)) return;\n\n const jumped = Math.abs(t - this.lastTime) >= this.seekJumpThresholdSec;\n if (jumped && !this.triggerOnSeek) {\n this.lastTime = t;\n return;\n }\n\n for (const m of this.markers) {\n const key = `${m.time}-${m.idx}`;\n if (m.once && this.hitSet.has(key)) continue;\n if (!m.once) {\n const last = this.lastHitAt.get(key) || 0;\n if (now - last < m.cooldownMs) continue;\n }\n\n const crossed = this.lastTime < m.time && t >= m.time - m.tolerance;\n if (!crossed) continue;\n\n if (m.once) this.hitSet.add(key);\n else this.lastHitAt.set(key, now);\n\n if (m.pauseOnHit) this.ctx.videoEl.pause();\n\n this.firePing(m);\n this.fireAction(m);\n\n const popupCfg = m.popup ? { ...this.popupGlobal, ...m.popup } : this.popupGlobal;\n if (popupCfg.enabled) {\n this.ctx.videoEl.pause();\n this.showPopup(popupCfg);\n }\n break;\n }\n\n this.lastTime = t;\n };\n\n private resolveUrlTemplate(url: string, m: NormalizedMarker): string {\n if (!url) return '';\n return url.replaceAll('{time}', encodeURIComponent(String(m.time))).replaceAll('{label}', encodeURIComponent(m.label));\n }\n\n private firePing(m: NormalizedMarker): void {\n const baseUrl = m.pingUrl || this.pingGlobal.url;\n const url = this.resolveUrlTemplate(baseUrl, m);\n if (!this.pingGlobal.enabled || !url) return;\n\n try {\n if (this.pingGlobal.method === 'POST') {\n fetch(url, {\n method: 'POST',\n keepalive: true,\n headers: this.pingGlobal.includeMarker ? { 'Content-Type': 'application/json' } : undefined,\n body: this.pingGlobal.includeMarker ? JSON.stringify({ time: m.time, label: m.label, ts: Date.now() }) : undefined,\n }).catch(() => {});\n } else {\n fetch(url, { method: 'GET', keepalive: true }).catch(() => {});\n }\n } catch {\n /* no-op */\n }\n }\n\n private fireAction(m: NormalizedMarker): void {\n const a = m.action;\n if (!a) return;\n\n if (a.type === 'log') {\n console.log('[HopePlayer markers]', a.name || 'marker_hit', { time: m.time, label: m.label }, a.payload);\n return;\n }\n\n if (a.type === 'datalayer') {\n try {\n const w = window as unknown as { dataLayer?: unknown[] };\n w.dataLayer = w.dataLayer || [];\n w.dataLayer.push({\n event: 'HopePlayerVideoEvents',\n trigger: a.name || 'marker_hit',\n marker: { time: m.time, label: m.label, color: m.color },\n payload: a.payload ?? {},\n ts: Date.now(),\n });\n } catch {\n /* no-op */\n }\n return;\n }\n\n if (a.type === 'custom') {\n const fn = a.name ? (window as unknown as Record<string, unknown>)[a.name] : null;\n if (typeof fn === 'function') {\n try {\n (fn as (ctx: unknown) => void)({ marker: m, payload: a.payload });\n } catch (err) {\n console.warn('[HopePlayer markers] custom action fonksiyonu hata verdi:', err);\n }\n } else {\n console.warn('[HopePlayer markers] custom action fonksiyonu bulunamadı: window.' + a.name);\n }\n }\n }\n\n private ensurePopup(): HTMLElement {\n if (this.popupEl) return this.popupEl;\n\n const overlay = document.createElement('div');\n overlay.setAttribute('part', 'marker-popup');\n overlay.className = 'hp:hidden hp:absolute hp:inset-0 hp:z-30 hp:items-center hp:justify-center hp:bg-black/70';\n\n const panel = document.createElement('div');\n panel.className = 'hp:relative hp:max-w-[85%] hp:bg-surface-elev hp:text-on-surface hp:rounded-lg hp:p-4 hp:text-center hp:shadow-xl';\n panel.setAttribute('role', 'dialog');\n panel.setAttribute('aria-modal', 'true');\n\n const closeBtn = document.createElement('button');\n closeBtn.type = 'button';\n closeBtn.setAttribute('aria-label', this.ctx.i18n.close);\n closeBtn.className = 'hp:absolute hp:top-1 hp:right-1 hp:w-6 hp:h-6 hp:flex hp:items-center hp:justify-center hp:bg-transparent hp:border-0 hp:cursor-pointer hp:text-on-surface';\n closeBtn.appendChild(createIcon('close', 'hp:text-sm'));\n\n const mediaWrap = document.createElement('div');\n mediaWrap.className = 'hp:hidden hp:mb-2';\n const img = document.createElement('img');\n img.className = 'hp:max-w-full hp:rounded';\n mediaWrap.appendChild(img);\n\n const textEl = document.createElement('div');\n textEl.className = 'hp:text-sm hp:mb-2';\n\n const linkEl = document.createElement('a');\n linkEl.target = '_blank';\n linkEl.rel = 'noopener noreferrer';\n linkEl.className = 'hp:hidden hp:text-accent hp:underline hp:text-sm hp:block hp:mb-2';\n\n const continueBtn = document.createElement('button');\n continueBtn.type = 'button';\n continueBtn.className = 'hp:hidden hp:px-4 hp:py-1.5 hp:rounded hp:bg-accent hp:text-on-accent hp:border-0 hp:cursor-pointer hp:text-sm';\n\n panel.append(closeBtn, mediaWrap, textEl, linkEl, continueBtn);\n overlay.appendChild(panel);\n this.ctx.overlayContainerEl.appendChild(overlay);\n this.popupEl = overlay;\n return overlay;\n }\n\n private hidePopup(): void {\n this.popupEl?.classList.add('hp:hidden');\n this.popupEl?.classList.remove('hp:flex');\n }\n\n private safePlay(): void {\n void this.ctx.videoEl.play().catch(() => {});\n }\n\n private showPopup(cfg: Required<MarkerPopupOptions>): void {\n const el = this.ensurePopup();\n const textEl = el.querySelector('div.hp\\\\:text-sm.hp\\\\:mb-2:not(.hp\\\\:hidden)') as HTMLElement | null;\n const mediaWrap = el.querySelector('div.hp\\\\:mb-2') as HTMLElement | null;\n const img = el.querySelector('img') as HTMLImageElement | null;\n const linkEl = el.querySelector('a') as HTMLAnchorElement | null;\n const continueBtn = el.querySelectorAll('button')[1] as HTMLButtonElement | null;\n const closeBtn = el.querySelector('button') as HTMLButtonElement | null;\n\n if (closeBtn) closeBtn.style.display = cfg.showClose === false ? 'none' : '';\n if (textEl) textEl.textContent = cfg.text || '';\n\n const isRich = cfg.mode === 'rich';\n if (mediaWrap && img) {\n if (isRich && cfg.imageUrl) {\n mediaWrap.classList.remove('hp:hidden');\n img.src = cfg.imageUrl;\n img.alt = cfg.imageAlt || '';\n } else {\n mediaWrap.classList.add('hp:hidden');\n img.removeAttribute('src');\n }\n }\n\n if (linkEl) {\n if (isRich && cfg.linkUrl) {\n linkEl.classList.remove('hp:hidden');\n linkEl.href = cfg.linkUrl;\n linkEl.textContent = cfg.linkText || this.ctx.i18n.markerLearnMore;\n } else {\n linkEl.classList.add('hp:hidden');\n linkEl.removeAttribute('href');\n }\n }\n\n if (continueBtn) {\n if (cfg.showContinue) {\n continueBtn.classList.remove('hp:hidden');\n continueBtn.textContent = cfg.continueText || this.ctx.i18n.markerContinue;\n } else {\n continueBtn.classList.add('hp:hidden');\n }\n }\n\n const newClose = closeBtn?.cloneNode(true) as HTMLButtonElement | undefined;\n if (closeBtn && newClose) closeBtn.replaceWith(newClose);\n const newCont = continueBtn?.cloneNode(true) as HTMLButtonElement | undefined;\n if (continueBtn && newCont) continueBtn.replaceWith(newCont);\n\n newClose?.addEventListener('click', () => {\n this.hidePopup();\n if (cfg.autoplayOnClose) this.safePlay();\n });\n newCont?.addEventListener('click', () => {\n this.hidePopup();\n if (cfg.autoplayOnContinue) this.safePlay();\n });\n\n el.classList.remove('hp:hidden');\n el.classList.add('hp:flex');\n }\n}\n","import { MarkProgress, type MarkersPlayerContext } from './MarkProgress';\nimport type { MarkersOptions } from '../../types';\n\nexport function installMarkers(ctx: MarkersPlayerContext, options: MarkersOptions): MarkProgress {\n return new MarkProgress(ctx, options);\n}\n\nexport { MarkProgress };\nexport type { MarkersPlayerContext };\n"],"names":["POPUP_DEFAULTS","PING_DEFAULTS","MarkProgress","ctx","options","__publicField","duration","m","el","now","key","last","popupCfg","idx","a","b","closeBtn","_a","url","baseUrl","w","fn","err","overlay","panel","createIcon","mediaWrap","img","textEl","linkEl","continueBtn","_b","cfg","isRich","newClose","newCont","installMarkers"],"mappings":";;;;AA2BA,MAAMA,IAA+C;AAAA,EACjD,SAAS;AAAA,EACT,MAAM;AAAA,EACN,MAAM;AAAA,EACN,UAAU;AAAA,EACV,UAAU;AAAA,EACV,SAAS;AAAA;AAAA;AAAA;AAAA,EAIT,UAAU;AAAA,EACV,cAAc;AAAA,EACd,cAAc;AAAA,EACd,WAAW;AAAA,EACX,iBAAiB;AAAA,EACjB,oBAAoB;AACxB,GAEMC,IAA6C,EAAE,SAAS,IAAO,KAAK,IAAI,QAAQ,OAAO,eAAe,GAAA;AAGrG,MAAMC,EAAa;AAAA,EAetB,YACqBC,GACjBC,GACF;AAjBe,IAAAC,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAET,IAAAA,EAAA,oCAAa,IAAA;AACb,IAAAA,EAAA,uCAAgB,IAAA;AAChB,IAAAA,EAAA,kBAAW;AACX,IAAAA,EAAA,mBAAY;AACZ,IAAAA,EAAA,uBAAgB;AAChB,IAAAA,EAAA,iBAA8B;AA6DrB,IAAAA,EAAA,0BAAmB,MAAY;AAC5C,YAAMC,IAAW,KAAK,IAAI,QAAQ;AAClC,MAAI,CAAC,OAAO,SAASA,CAAQ,KAAKA,KAAY,MAE9C,KAAK,QAAQ,QAAQ,CAACC,MAAM;AACxB,YAAIA,EAAE,GAAI;AACV,cAAMC,IAAK,KAAK,IAAI,iBAAiBD,EAAE,OAAOD,CAAQ;AACtD,QAAIC,EAAE,UAAOC,EAAG,MAAM,kBAAkBD,EAAE,QACtCA,EAAE,UAAOC,EAAG,QAAQD,EAAE,QAC1BA,EAAE,KAAKC;AAAA,MACX,CAAC,GAED,KAAK,WAAW,KAAK,IAAI,QAAQ,eAAe;AAAA,IACpD;AAEiB,IAAAH,EAAA,mBAAY,MAAY;AACrC,WAAK,YAAY,IACjB,KAAK,gBAAgB,KAAK,IAAA,IAAQ,KAAK,oBACvC,KAAK,WAAW,KAAK,IAAI,QAAQ,eAAe;AAAA,IACpD;AAEiB,IAAAA,EAAA,kBAAW,MAAY;AACpC,WAAK,WAAW,KAAK,IAAI,QAAQ,eAAe,GAChD,KAAK,YAAY,IACjB,KAAK,gBAAgB,KAAK,IAAA,IAAQ,KAAK;AAAA,IAC3C;AAEiB,IAAAA,EAAA,sBAAe,MAAY;AACxC,YAAMI,IAAM,KAAK,IAAA;AAEjB,UADIA,IAAM,KAAK,iBACX,KAAK,UAAW;AAEpB,YAAM,IAAI,KAAK,IAAI,QAAQ;AAC3B,UAAI,CAAC,OAAO,SAAS,CAAC,EAAG;AAGzB,UADe,KAAK,IAAI,IAAI,KAAK,QAAQ,KAAK,KAAK,wBACrC,CAAC,KAAK,eAAe;AAC/B,aAAK,WAAW;AAChB;AAAA,MACJ;AAEA,iBAAWF,KAAK,KAAK,SAAS;AAC1B,cAAMG,IAAM,GAAGH,EAAE,IAAI,IAAIA,EAAE,GAAG;AAC9B,YAAIA,EAAE,QAAQ,KAAK,OAAO,IAAIG,CAAG,EAAG;AACpC,YAAI,CAACH,EAAE,MAAM;AACT,gBAAMI,IAAO,KAAK,UAAU,IAAID,CAAG,KAAK;AACxC,cAAID,IAAME,IAAOJ,EAAE,WAAY;AAAA,QACnC;AAGA,YAAI,EADY,KAAK,WAAWA,EAAE,QAAQ,KAAKA,EAAE,OAAOA,EAAE,WAC5C;AAEd,QAAIA,EAAE,OAAM,KAAK,OAAO,IAAIG,CAAG,IAC1B,KAAK,UAAU,IAAIA,GAAKD,CAAG,GAE5BF,EAAE,cAAY,KAAK,IAAI,QAAQ,MAAA,GAEnC,KAAK,SAASA,CAAC,GACf,KAAK,WAAWA,CAAC;AAEjB,cAAMK,IAAWL,EAAE,QAAQ,EAAE,GAAG,KAAK,aAAa,GAAGA,EAAE,MAAA,IAAU,KAAK;AACtE,QAAIK,EAAS,YACT,KAAK,IAAI,QAAQ,MAAA,GACjB,KAAK,UAAUA,CAAQ;AAE3B;AAAA,MACJ;AAEA,WAAK,WAAW;AAAA,IACpB;AA/HqB,SAAA,MAAAT,GAGjB,KAAK,gBAAgBC,EAAQ,kBAAkB,IAC/C,KAAK,uBAAuBA,EAAQ,wBAAwB,GAC5D,KAAK,qBAAqBA,EAAQ,sBAAsB,KACxD,KAAK,cAAc,EAAE,GAAGJ,GAAgB,GAAGI,EAAQ,MAAA,GACnD,KAAK,aAAa,EAAE,GAAGH,GAAe,GAAGG,EAAQ,KAAA,GAEjD,KAAK,WAAWA,EAAQ,SAAS,CAAA,GAC5B,IAAI,CAACG,GAAGM,MAAQ,KAAK,UAAUN,GAAGM,CAAG,CAAC,EACtC,OAAO,CAACN,MAAM,OAAO,SAASA,EAAE,IAAI,KAAKA,EAAE,QAAQ,CAAC,EACpD,KAAK,CAACO,GAAGC,MAAMD,EAAE,OAAOC,EAAE,IAAI,GAEnCZ,EAAI,QAAQ,iBAAiB,kBAAkB,KAAK,gBAAgB,GACpEA,EAAI,QAAQ,iBAAiB,cAAc,KAAK,YAAY,GAC5DA,EAAI,QAAQ,iBAAiB,WAAW,KAAK,SAAS,GACtDA,EAAI,QAAQ,iBAAiB,UAAU,KAAK,QAAQ,GAEhDA,EAAI,QAAQ,cAAc,UAAQ,iBAAA;AAAA,EAC1C;AAAA;AAAA,EAGA,gBAAsB;;AAClB,UAAMa,KAAWC,IAAA,KAAK,YAAL,gBAAAA,EAAc,cAAc;AAC7C,IAAID,KACAA,EAAS,aAAa,cAAc,KAAK,IAAI,KAAK,KAAK;AAAA,EAE/D;AAAA,EAEA,UAAgB;;AACZ,SAAK,IAAI,QAAQ,oBAAoB,kBAAkB,KAAK,gBAAgB,GAC5E,KAAK,IAAI,QAAQ,oBAAoB,cAAc,KAAK,YAAY,GACpE,KAAK,IAAI,QAAQ,oBAAoB,WAAW,KAAK,SAAS,GAC9D,KAAK,IAAI,QAAQ,oBAAoB,UAAU,KAAK,QAAQ,GAC5D,KAAK,QAAQ,QAAQ,CAACT;;AAAM,cAAAU,IAAAV,EAAE,OAAF,gBAAAU,EAAM;AAAA,KAAQ,IAC1CA,IAAA,KAAK,YAAL,QAAAA,EAAc,UACd,KAAK,UAAU,MACf,KAAK,OAAO,MAAA,GACZ,KAAK,UAAU,MAAA;AAAA,EACnB;AAAA,EAEQ,UAAUV,GAAeM,GAA+B;AAC5D,WAAO;AAAA,MACH,KAAAA;AAAA,MACA,MAAM,OAAON,EAAE,IAAI;AAAA,MACnB,OAAOA,EAAE;AAAA,MACT,OAAOA,EAAE,SAAS;AAAA,MAClB,YAAYA,EAAE,cAAc;AAAA,MAC5B,MAAMA,EAAE,QAAQ;AAAA,MAChB,WAAWA,EAAE,aAAa;AAAA,MAC1B,YAAYA,EAAE,cAAc;AAAA,MAC5B,QAAQA,EAAE;AAAA,MACV,OAAOA,EAAE,SAAS;AAAA,MAClB,SAASA,EAAE,WAAW;AAAA,IAAA;AAAA,EAE9B;AAAA,EAyEQ,mBAAmBW,GAAaX,GAA6B;AACjE,WAAKW,IACEA,EAAI,WAAW,UAAU,mBAAmB,OAAOX,EAAE,IAAI,CAAC,CAAC,EAAE,WAAW,WAAW,mBAAmBA,EAAE,KAAK,CAAC,IADpG;AAAA,EAErB;AAAA,EAEQ,SAASA,GAA2B;AACxC,UAAMY,IAAUZ,EAAE,WAAW,KAAK,WAAW,KACvCW,IAAM,KAAK,mBAAmBC,GAASZ,CAAC;AAC9C,QAAI,GAAC,KAAK,WAAW,WAAW,CAACW;AAEjC,UAAI;AACA,QAAI,KAAK,WAAW,WAAW,SAC3B,MAAMA,GAAK;AAAA,UACP,QAAQ;AAAA,UACR,WAAW;AAAA,UACX,SAAS,KAAK,WAAW,gBAAgB,EAAE,gBAAgB,uBAAuB;AAAA,UAClF,MAAM,KAAK,WAAW,gBAAgB,KAAK,UAAU,EAAE,MAAMX,EAAE,MAAM,OAAOA,EAAE,OAAO,IAAI,KAAK,IAAA,EAAI,CAAG,IAAI;AAAA,QAAA,CAC5G,EAAE,MAAM,MAAM;AAAA,QAAC,CAAC,IAEjB,MAAMW,GAAK,EAAE,QAAQ,OAAO,WAAW,GAAA,CAAM,EAAE,MAAM,MAAM;AAAA,QAAC,CAAC;AAAA,MAErE,QAAQ;AAAA,MAER;AAAA,EACJ;AAAA,EAEQ,WAAWX,GAA2B;AAC1C,UAAMO,IAAIP,EAAE;AACZ,QAAKO,GAEL;AAAA,UAAIA,EAAE,SAAS,OAAO;AAClB,gBAAQ,IAAI,wBAAwBA,EAAE,QAAQ,cAAc,EAAE,MAAMP,EAAE,MAAM,OAAOA,EAAE,MAAA,GAASO,EAAE,OAAO;AACvG;AAAA,MACJ;AAEA,UAAIA,EAAE,SAAS,aAAa;AACxB,YAAI;AACA,gBAAMM,IAAI;AACV,UAAAA,EAAE,YAAYA,EAAE,aAAa,CAAA,GAC7BA,EAAE,UAAU,KAAK;AAAA,YACb,OAAO;AAAA,YACP,SAASN,EAAE,QAAQ;AAAA,YACnB,QAAQ,EAAE,MAAMP,EAAE,MAAM,OAAOA,EAAE,OAAO,OAAOA,EAAE,MAAA;AAAA,YACjD,SAASO,EAAE,WAAW,CAAA;AAAA,YACtB,IAAI,KAAK,IAAA;AAAA,UAAI,CAChB;AAAA,QACL,QAAQ;AAAA,QAER;AACA;AAAA,MACJ;AAEA,UAAIA,EAAE,SAAS,UAAU;AACrB,cAAMO,IAAKP,EAAE,OAAQ,OAA8CA,EAAE,IAAI,IAAI;AAC7E,YAAI,OAAOO,KAAO;AACd,cAAI;AACC,YAAAA,EAA8B,EAAE,QAAQd,GAAG,SAASO,EAAE,SAAS;AAAA,UACpE,SAASQ,GAAK;AACV,oBAAQ,KAAK,6DAA6DA,CAAG;AAAA,UACjF;AAAA;AAEA,kBAAQ,KAAK,sEAAsER,EAAE,IAAI;AAAA,MAEjG;AAAA;AAAA,EACJ;AAAA,EAEQ,cAA2B;AAC/B,QAAI,KAAK,QAAS,QAAO,KAAK;AAE9B,UAAMS,IAAU,SAAS,cAAc,KAAK;AAC5C,IAAAA,EAAQ,aAAa,QAAQ,cAAc,GAC3CA,EAAQ,YAAY;AAEpB,UAAMC,IAAQ,SAAS,cAAc,KAAK;AAC1C,IAAAA,EAAM,YAAY,qHAClBA,EAAM,aAAa,QAAQ,QAAQ,GACnCA,EAAM,aAAa,cAAc,MAAM;AAEvC,UAAMR,IAAW,SAAS,cAAc,QAAQ;AAChD,IAAAA,EAAS,OAAO,UAChBA,EAAS,aAAa,cAAc,KAAK,IAAI,KAAK,KAAK,GACvDA,EAAS,YAAY,8JACrBA,EAAS,YAAYS,EAAW,SAAS,YAAY,CAAC;AAEtD,UAAMC,IAAY,SAAS,cAAc,KAAK;AAC9C,IAAAA,EAAU,YAAY;AACtB,UAAMC,IAAM,SAAS,cAAc,KAAK;AACxC,IAAAA,EAAI,YAAY,4BAChBD,EAAU,YAAYC,CAAG;AAEzB,UAAMC,IAAS,SAAS,cAAc,KAAK;AAC3C,IAAAA,EAAO,YAAY;AAEnB,UAAMC,IAAS,SAAS,cAAc,GAAG;AACzC,IAAAA,EAAO,SAAS,UAChBA,EAAO,MAAM,uBACbA,EAAO,YAAY;AAEnB,UAAMC,IAAc,SAAS,cAAc,QAAQ;AACnD,WAAAA,EAAY,OAAO,UACnBA,EAAY,YAAY,kHAExBN,EAAM,OAAOR,GAAUU,GAAWE,GAAQC,GAAQC,CAAW,GAC7DP,EAAQ,YAAYC,CAAK,GACzB,KAAK,IAAI,mBAAmB,YAAYD,CAAO,GAC/C,KAAK,UAAUA,GACRA;AAAA,EACX;AAAA,EAEQ,YAAkB;;AACtB,KAAAN,IAAA,KAAK,YAAL,QAAAA,EAAc,UAAU,IAAI,eAC5Bc,IAAA,KAAK,YAAL,QAAAA,EAAc,UAAU,OAAO;AAAA,EACnC;AAAA,EAEQ,WAAiB;AACrB,IAAK,KAAK,IAAI,QAAQ,KAAA,EAAO,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EAC/C;AAAA,EAEQ,UAAUC,GAAyC;AACvD,UAAMxB,IAAK,KAAK,YAAA,GACVoB,IAASpB,EAAG,cAAc,8CAA8C,GACxEkB,IAAYlB,EAAG,cAAc,eAAe,GAC5CmB,IAAMnB,EAAG,cAAc,KAAK,GAC5BqB,IAASrB,EAAG,cAAc,GAAG,GAC7BsB,IAActB,EAAG,iBAAiB,QAAQ,EAAE,CAAC,GAC7CQ,IAAWR,EAAG,cAAc,QAAQ;AAE1C,IAAIQ,MAAUA,EAAS,MAAM,UAAUgB,EAAI,cAAc,KAAQ,SAAS,KACtEJ,MAAQA,EAAO,cAAcI,EAAI,QAAQ;AAE7C,UAAMC,IAASD,EAAI,SAAS;AAC5B,IAAIN,KAAaC,MACTM,KAAUD,EAAI,YACdN,EAAU,UAAU,OAAO,WAAW,GACtCC,EAAI,MAAMK,EAAI,UACdL,EAAI,MAAMK,EAAI,YAAY,OAE1BN,EAAU,UAAU,IAAI,WAAW,GACnCC,EAAI,gBAAgB,KAAK,KAI7BE,MACII,KAAUD,EAAI,WACdH,EAAO,UAAU,OAAO,WAAW,GACnCA,EAAO,OAAOG,EAAI,SAClBH,EAAO,cAAcG,EAAI,YAAY,KAAK,IAAI,KAAK,oBAEnDH,EAAO,UAAU,IAAI,WAAW,GAChCA,EAAO,gBAAgB,MAAM,KAIjCC,MACIE,EAAI,gBACJF,EAAY,UAAU,OAAO,WAAW,GACxCA,EAAY,cAAcE,EAAI,gBAAgB,KAAK,IAAI,KAAK,kBAE5DF,EAAY,UAAU,IAAI,WAAW;AAI7C,UAAMI,IAAWlB,KAAA,gBAAAA,EAAU,UAAU;AACrC,IAAIA,KAAYkB,KAAUlB,EAAS,YAAYkB,CAAQ;AACvD,UAAMC,IAAUL,KAAA,gBAAAA,EAAa,UAAU;AACvC,IAAIA,KAAeK,KAASL,EAAY,YAAYK,CAAO,GAE3DD,KAAA,QAAAA,EAAU,iBAAiB,SAAS,MAAM;AACtC,WAAK,UAAA,GACDF,EAAI,mBAAiB,KAAK,SAAA;AAAA,IAClC,IACAG,KAAA,QAAAA,EAAS,iBAAiB,SAAS,MAAM;AACrC,WAAK,UAAA,GACDH,EAAI,sBAAoB,KAAK,SAAA;AAAA,IACrC,IAEAxB,EAAG,UAAU,OAAO,WAAW,GAC/BA,EAAG,UAAU,IAAI,SAAS;AAAA,EAC9B;AACJ;ACjXO,SAAS4B,EAAejC,GAA2BC,GAAuC;AAC7F,SAAO,IAAIF,EAAaC,GAAKC,CAAO;AACxC;"}
|
|
1
|
+
{"version":3,"file":"index-lrAXde76.js","sources":["../../src/plugins/markers/MarkProgress.ts","../../src/plugins/markers/index.ts"],"sourcesContent":["import { createIcon } from '../../icons/Icon';\nimport type { MarkerItem, MarkerPingOptions, MarkerPopupOptions, MarkersOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\n\nexport interface MarkersPlayerContext {\n videoEl: HTMLVideoElement;\n /** Popup overlay'in ekleneceği katman (shadow root içinde, video üzerinde). */\n overlayContainerEl: HTMLElement;\n /** Seek bar üzerinde işaretçi çizmek için — SeekBar.addMarker ile aynı imza. */\n addSeekBarMarker(ratio: number, extraClass?: string): HTMLDivElement;\n i18n: HopeLocaleStrings;\n}\n\ninterface NormalizedMarker extends Required<Pick<MarkerItem, 'time'>> {\n idx: number;\n color?: string;\n label: string;\n pauseOnHit: boolean;\n once: boolean;\n tolerance: number;\n cooldownMs: number;\n action?: MarkerItem['action'];\n popup: MarkerPopupOptions | null;\n pingUrl: string;\n el?: HTMLElement;\n}\n\nconst POPUP_DEFAULTS: Required<MarkerPopupOptions> = {\n enabled: false,\n mode: 'rich',\n text: '',\n imageUrl: '',\n imageAlt: '',\n linkUrl: '',\n // Boş bırakılıyor (sentinel) — gerçek varsayılan metin showPopup()'ta\n // `ctx.i18n.markerLearnMore`/`markerContinue`'dan okunuyor, dil\n // değişimini takip edebilsin diye burada SABİT bir dilde gömülü değil.\n linkText: '',\n continueText: '',\n showContinue: true,\n showClose: true,\n autoplayOnClose: true,\n autoplayOnContinue: true,\n};\n\nconst PING_DEFAULTS: Required<MarkerPingOptions> = { enabled: false, url: '', method: 'GET', includeMarker: false };\n\n/** Zaman tabanlı seek bar işaretçileri — seek/jump koruması, once/cooldown, popup/ping/aksiyon. */\nexport class MarkProgress {\n private readonly markers: NormalizedMarker[];\n private readonly popupGlobal: Required<MarkerPopupOptions>;\n private readonly pingGlobal: Required<MarkerPingOptions>;\n private readonly triggerOnSeek: boolean;\n private readonly seekJumpThresholdSec: number;\n private readonly seekIgnoreWindowMs: number;\n\n private hitSet = new Set<string>();\n private lastHitAt = new Map<string, number>();\n private lastTime = 0;\n private isSeeking = false;\n private ignoreUntilTs = 0;\n private popupEl: HTMLElement | null = null;\n\n constructor(\n private readonly ctx: MarkersPlayerContext,\n options: MarkersOptions\n ) {\n this.triggerOnSeek = options.triggerOnSeek === true;\n this.seekJumpThresholdSec = options.seekJumpThresholdSec ?? 1;\n this.seekIgnoreWindowMs = options.seekIgnoreWindowMs ?? 250;\n this.popupGlobal = { ...POPUP_DEFAULTS, ...options.popup };\n this.pingGlobal = { ...PING_DEFAULTS, ...options.ping };\n\n this.markers = (options.items || [])\n .map((m, idx) => this.normalize(m, idx))\n .filter((m) => Number.isFinite(m.time) && m.time >= 0)\n .sort((a, b) => a.time - b.time);\n\n ctx.videoEl.addEventListener('loadedmetadata', this.onLoadedMetadata);\n ctx.videoEl.addEventListener('timeupdate', this.onTimeUpdate);\n ctx.videoEl.addEventListener('seeking', this.onSeeking);\n ctx.videoEl.addEventListener('seeked', this.onSeeked);\n\n if (ctx.videoEl.readyState >= 1) this.onLoadedMetadata();\n }\n\n /** Popup lazy oluşturulup yeniden kullanılıyor (`ensurePopup`) — zaten açıksa close butonunun statik etiketini tazeler. */\n refreshLabels(): void {\n const closeBtn = this.popupEl?.querySelector('button') as HTMLButtonElement | null;\n if (closeBtn) {\n closeBtn.setAttribute('aria-label', this.ctx.i18n.close);\n }\n }\n\n destroy(): void {\n this.ctx.videoEl.removeEventListener('loadedmetadata', this.onLoadedMetadata);\n this.ctx.videoEl.removeEventListener('timeupdate', this.onTimeUpdate);\n this.ctx.videoEl.removeEventListener('seeking', this.onSeeking);\n this.ctx.videoEl.removeEventListener('seeked', this.onSeeked);\n this.markers.forEach((m) => m.el?.remove());\n this.popupEl?.remove();\n this.popupEl = null;\n this.hitSet.clear();\n this.lastHitAt.clear();\n }\n\n private normalize(m: MarkerItem, idx: number): NormalizedMarker {\n return {\n idx,\n time: Number(m.time),\n color: m.color,\n label: m.label ?? '',\n pauseOnHit: m.pauseOnHit ?? true,\n once: m.once ?? true,\n tolerance: m.tolerance ?? 0.25,\n cooldownMs: m.cooldownMs ?? 600,\n action: m.action,\n popup: m.popup ?? null,\n pingUrl: m.pingUrl ?? '',\n };\n }\n\n private readonly onLoadedMetadata = (): void => {\n const duration = this.ctx.videoEl.duration;\n if (!Number.isFinite(duration) || duration <= 0) return;\n\n this.markers.forEach((m) => {\n if (m.el) return;\n const el = this.ctx.addSeekBarMarker(m.time / duration);\n if (m.color) el.style.backgroundColor = m.color;\n if (m.label) el.title = m.label;\n m.el = el;\n });\n\n this.lastTime = this.ctx.videoEl.currentTime || 0;\n };\n\n private readonly onSeeking = (): void => {\n this.isSeeking = true;\n this.ignoreUntilTs = Date.now() + this.seekIgnoreWindowMs;\n this.lastTime = this.ctx.videoEl.currentTime || 0;\n };\n\n private readonly onSeeked = (): void => {\n this.lastTime = this.ctx.videoEl.currentTime || 0;\n this.isSeeking = false;\n this.ignoreUntilTs = Date.now() + this.seekIgnoreWindowMs;\n };\n\n private readonly onTimeUpdate = (): void => {\n const now = Date.now();\n if (now < this.ignoreUntilTs) return;\n if (this.isSeeking) return;\n\n const t = this.ctx.videoEl.currentTime;\n if (!Number.isFinite(t)) return;\n\n const jumped = Math.abs(t - this.lastTime) >= this.seekJumpThresholdSec;\n if (jumped && !this.triggerOnSeek) {\n this.lastTime = t;\n return;\n }\n\n for (const m of this.markers) {\n const key = `${m.time}-${m.idx}`;\n if (m.once && this.hitSet.has(key)) continue;\n if (!m.once) {\n const last = this.lastHitAt.get(key) || 0;\n if (now - last < m.cooldownMs) continue;\n }\n\n const crossed = this.lastTime < m.time && t >= m.time - m.tolerance;\n if (!crossed) continue;\n\n if (m.once) this.hitSet.add(key);\n else this.lastHitAt.set(key, now);\n\n if (m.pauseOnHit) this.ctx.videoEl.pause();\n\n this.firePing(m);\n this.fireAction(m);\n\n const popupCfg = m.popup ? { ...this.popupGlobal, ...m.popup } : this.popupGlobal;\n if (popupCfg.enabled) {\n this.ctx.videoEl.pause();\n this.showPopup(popupCfg);\n }\n break;\n }\n\n this.lastTime = t;\n };\n\n private resolveUrlTemplate(url: string, m: NormalizedMarker): string {\n if (!url) return '';\n return url.replaceAll('{time}', encodeURIComponent(String(m.time))).replaceAll('{label}', encodeURIComponent(m.label));\n }\n\n private firePing(m: NormalizedMarker): void {\n const baseUrl = m.pingUrl || this.pingGlobal.url;\n const url = this.resolveUrlTemplate(baseUrl, m);\n if (!this.pingGlobal.enabled || !url) return;\n\n try {\n if (this.pingGlobal.method === 'POST') {\n fetch(url, {\n method: 'POST',\n keepalive: true,\n headers: this.pingGlobal.includeMarker ? { 'Content-Type': 'application/json' } : undefined,\n body: this.pingGlobal.includeMarker ? JSON.stringify({ time: m.time, label: m.label, ts: Date.now() }) : undefined,\n }).catch(() => {});\n } else {\n fetch(url, { method: 'GET', keepalive: true }).catch(() => {});\n }\n } catch {\n /* no-op */\n }\n }\n\n private fireAction(m: NormalizedMarker): void {\n const a = m.action;\n if (!a) return;\n\n if (a.type === 'log') {\n console.log('[HopePlayer markers]', a.name || 'marker_hit', { time: m.time, label: m.label }, a.payload);\n return;\n }\n\n if (a.type === 'datalayer') {\n try {\n const w = window as unknown as { dataLayer?: unknown[] };\n w.dataLayer = w.dataLayer || [];\n w.dataLayer.push({\n event: 'HopePlayerVideoEvents',\n trigger: a.name || 'marker_hit',\n marker: { time: m.time, label: m.label, color: m.color },\n payload: a.payload ?? {},\n ts: Date.now(),\n });\n } catch {\n /* no-op */\n }\n return;\n }\n\n if (a.type === 'custom') {\n const fn = a.name ? (window as unknown as Record<string, unknown>)[a.name] : null;\n if (typeof fn === 'function') {\n try {\n (fn as (ctx: unknown) => void)({ marker: m, payload: a.payload });\n } catch (err) {\n console.warn('[HopePlayer markers] custom action fonksiyonu hata verdi:', err);\n }\n } else {\n console.warn('[HopePlayer markers] custom action fonksiyonu bulunamadı: window.' + a.name);\n }\n }\n }\n\n private ensurePopup(): HTMLElement {\n if (this.popupEl) return this.popupEl;\n\n const overlay = document.createElement('div');\n overlay.setAttribute('part', 'marker-popup');\n overlay.className = 'hp:hidden hp:absolute hp:inset-0 hp:z-30 hp:items-center hp:justify-center hp:bg-black/70';\n\n const panel = document.createElement('div');\n panel.className = 'hp:relative hp:max-w-[85%] hp:bg-surface-elev hp:text-on-surface hp:rounded-lg hp:p-4 hp:text-center hp:shadow-xl';\n panel.setAttribute('role', 'dialog');\n panel.setAttribute('aria-modal', 'true');\n\n const closeBtn = document.createElement('button');\n closeBtn.type = 'button';\n closeBtn.setAttribute('aria-label', this.ctx.i18n.close);\n closeBtn.className = 'hp:absolute hp:top-1 hp:right-1 hp:w-6 hp:h-6 hp:flex hp:items-center hp:justify-center hp:bg-transparent hp:border-0 hp:cursor-pointer hp:text-on-surface';\n closeBtn.appendChild(createIcon('close', 'hp:text-sm'));\n\n const mediaWrap = document.createElement('div');\n mediaWrap.className = 'hp:hidden hp:mb-2';\n const img = document.createElement('img');\n img.className = 'hp:max-w-full hp:rounded';\n mediaWrap.appendChild(img);\n\n const textEl = document.createElement('div');\n textEl.className = 'hp:text-sm hp:mb-2';\n\n const linkEl = document.createElement('a');\n linkEl.target = '_blank';\n linkEl.rel = 'noopener noreferrer';\n linkEl.className = 'hp:hidden hp:text-accent hp:underline hp:text-sm hp:block hp:mb-2';\n\n const continueBtn = document.createElement('button');\n continueBtn.type = 'button';\n continueBtn.className = 'hp:hidden hp:px-4 hp:py-1.5 hp:rounded hp:bg-accent hp:text-on-accent hp:border-0 hp:cursor-pointer hp:text-sm';\n\n panel.append(closeBtn, mediaWrap, textEl, linkEl, continueBtn);\n overlay.appendChild(panel);\n this.ctx.overlayContainerEl.appendChild(overlay);\n this.popupEl = overlay;\n return overlay;\n }\n\n private hidePopup(): void {\n this.popupEl?.classList.add('hp:hidden');\n this.popupEl?.classList.remove('hp:flex');\n }\n\n private safePlay(): void {\n void this.ctx.videoEl.play().catch(() => {});\n }\n\n private showPopup(cfg: Required<MarkerPopupOptions>): void {\n const el = this.ensurePopup();\n const textEl = el.querySelector('div.hp\\\\:text-sm.hp\\\\:mb-2:not(.hp\\\\:hidden)') as HTMLElement | null;\n const mediaWrap = el.querySelector('div.hp\\\\:mb-2') as HTMLElement | null;\n const img = el.querySelector('img') as HTMLImageElement | null;\n const linkEl = el.querySelector('a') as HTMLAnchorElement | null;\n const continueBtn = el.querySelectorAll('button')[1] as HTMLButtonElement | null;\n const closeBtn = el.querySelector('button') as HTMLButtonElement | null;\n\n if (closeBtn) closeBtn.style.display = cfg.showClose === false ? 'none' : '';\n if (textEl) textEl.textContent = cfg.text || '';\n\n const isRich = cfg.mode === 'rich';\n if (mediaWrap && img) {\n if (isRich && cfg.imageUrl) {\n mediaWrap.classList.remove('hp:hidden');\n img.src = cfg.imageUrl;\n img.alt = cfg.imageAlt || '';\n } else {\n mediaWrap.classList.add('hp:hidden');\n img.removeAttribute('src');\n }\n }\n\n if (linkEl) {\n if (isRich && cfg.linkUrl) {\n linkEl.classList.remove('hp:hidden');\n linkEl.href = cfg.linkUrl;\n linkEl.textContent = cfg.linkText || this.ctx.i18n.markerLearnMore;\n } else {\n linkEl.classList.add('hp:hidden');\n linkEl.removeAttribute('href');\n }\n }\n\n if (continueBtn) {\n if (cfg.showContinue) {\n continueBtn.classList.remove('hp:hidden');\n continueBtn.textContent = cfg.continueText || this.ctx.i18n.markerContinue;\n } else {\n continueBtn.classList.add('hp:hidden');\n }\n }\n\n const newClose = closeBtn?.cloneNode(true) as HTMLButtonElement | undefined;\n if (closeBtn && newClose) closeBtn.replaceWith(newClose);\n const newCont = continueBtn?.cloneNode(true) as HTMLButtonElement | undefined;\n if (continueBtn && newCont) continueBtn.replaceWith(newCont);\n\n newClose?.addEventListener('click', () => {\n this.hidePopup();\n if (cfg.autoplayOnClose) this.safePlay();\n });\n newCont?.addEventListener('click', () => {\n this.hidePopup();\n if (cfg.autoplayOnContinue) this.safePlay();\n });\n\n el.classList.remove('hp:hidden');\n el.classList.add('hp:flex');\n }\n}\n","import { MarkProgress, type MarkersPlayerContext } from './MarkProgress';\nimport type { MarkersOptions } from '../../types';\n\nexport function installMarkers(ctx: MarkersPlayerContext, options: MarkersOptions): MarkProgress {\n return new MarkProgress(ctx, options);\n}\n\nexport { MarkProgress };\nexport type { MarkersPlayerContext };\n"],"names":["POPUP_DEFAULTS","PING_DEFAULTS","MarkProgress","ctx","options","__publicField","duration","m","el","now","key","last","popupCfg","idx","a","b","closeBtn","_a","url","baseUrl","w","fn","err","overlay","panel","createIcon","mediaWrap","img","textEl","linkEl","continueBtn","_b","cfg","isRich","newClose","newCont","installMarkers"],"mappings":"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"}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* MP4: HTML5 video üzerinden doğrudan oynatılır.
|
|
3
|
+
* M3U8: Safari/iOS'ta native HLS; diğer tarayıcılarda gerektiğinde hls.js.
|
|
4
|
+
*/
|
|
2
5
|
export interface HlsQualityLevel {
|
|
3
6
|
index: number;
|
|
4
7
|
height: number;
|
|
@@ -10,7 +13,7 @@ export declare class SourceManager {
|
|
|
10
13
|
private readonly onLevelsChanged;
|
|
11
14
|
constructor(video: HTMLVideoElement, onLevelsChanged: (levels: HlsQualityLevel[], activeIndex: number) => void);
|
|
12
15
|
load(src: string, type?: string): Promise<void>;
|
|
13
|
-
/** -1 = otomatik (ABR). */
|
|
16
|
+
/** -1 = otomatik kalite (ABR). */
|
|
14
17
|
setLevel(index: number): void;
|
|
15
18
|
destroy(): void;
|
|
16
19
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SourceManager.d.ts","sourceRoot":"","sources":["../../src/hls/SourceManager.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SourceManager.d.ts","sourceRoot":"","sources":["../../src/hls/SourceManager.ts"],"names":[],"mappings":"AACA;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACnB;AAqCD,qBAAa,aAAa;IACtB,OAAO,CAAC,GAAG,CAA4B;IAEvC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmB;IAEzC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAGtB;gBAGN,KAAK,EAAE,gBAAgB,EACvB,eAAe,EAAE,CACb,MAAM,EAAE,eAAe,EAAE,EACzB,WAAW,EAAE,MAAM,KAClB,IAAI;IAMP,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuErD,kCAAkC;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAM7B,OAAO,IAAI,IAAI;CAMlB"}
|
package/dist/hope-player.js
CHANGED
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-CQqGn9as.js","sources":["../../src/plugins/segments/Segments.ts","../../src/plugins/segments/index.ts"],"sourcesContent":["import type { SegmentItem } from '../../types';\r\nimport type { SeekBarChapterRange } from '../../controls/SeekBar';\r\nimport { formatTime } from '../../utils/format-time';\r\n\r\nexport interface SegmentsPlayerContext {\r\n videoEl: HTMLVideoElement;\r\n /** Chapter modunu destekleyen seek bar — parçalara bölme/zaman eşlemesi onda. */\r\n seekBar: {\r\n readonly el: HTMLElement;\r\n setChapters(ranges: SeekBarChapterRange[]): HTMLElement[];\r\n suppressHoverTime(key: string, suppressed: boolean): void;\r\n clearChapters(): void;\r\n ratioAtClientX(clientX: number): number;\r\n };\r\n}\r\n\r\ninterface Chapter {\r\n start: number;\r\n end: number;\r\n text?: string;\r\n color?: string;\r\n}\r\n\r\n/**\n * YouTube tarzı bölümler: seek bar parçalara bölünür (SeekBar.setChapters), hover'da bölüm adı + zaman.\n * Zaman çizgisi her zaman tam kaplanır (boşluklar adsız bölüm, son bölüm sona uzar).\n */\r\nexport class Segments {\r\n private chapters: Chapter[] = [];\r\n private chapterEls: HTMLElement[] = [];\r\n private hoverIndex = -1;\r\n private readonly tooltipEl: HTMLDivElement;\r\n private readonly titleEl: HTMLDivElement;\r\n private readonly timeEl: HTMLDivElement;\r\n\r\n constructor(\r\n private readonly ctx: SegmentsPlayerContext,\r\n private readonly segments: SegmentItem[]\r\n ) {\r\n this.tooltipEl = document.createElement('div');\r\n this.tooltipEl.className = 'hp-chapter-tooltip';\r\n this.tooltipEl.setAttribute('part', 'segment-tooltip');\r\n this.titleEl = document.createElement('div');\r\n this.titleEl.className = 'hp-chapter-tooltip-title';\r\n this.timeEl = document.createElement('div');\r\n this.timeEl.className = 'hp-chapter-tooltip-time';\r\n this.tooltipEl.append(this.titleEl, this.timeEl);\r\n ctx.seekBar.el.appendChild(this.tooltipEl);\r\n // Popup zamanı zaten gösteriyor — seek bar'ın varsayılan hover zamanı ikinci kez yazmasın.\r\n ctx.seekBar.suppressHoverTime('segments', true);\r\n\r\n ctx.seekBar.el.addEventListener('pointermove', this.onPointerMove);\r\n ctx.seekBar.el.addEventListener('pointerleave', this.onPointerLeave);\r\n ctx.videoEl.addEventListener('loadedmetadata', this.onLoadedMetadata);\r\n if (ctx.videoEl.readyState >= 1) this.onLoadedMetadata();\r\n }\r\n\r\n destroy(): void {\r\n this.ctx.videoEl.removeEventListener('loadedmetadata', this.onLoadedMetadata);\r\n this.ctx.seekBar.el.removeEventListener('pointermove', this.onPointerMove);\r\n this.ctx.seekBar.el.removeEventListener('pointerleave', this.onPointerLeave);\r\n this.ctx.seekBar.clearChapters();\r\n this.ctx.seekBar.suppressHoverTime('segments', false);\r\n this.tooltipEl.remove();\r\n this.chapterEls = [];\r\n this.chapters = [];\r\n }\r\n\r\n private readonly onLoadedMetadata = (): void => {\r\n const duration = this.ctx.videoEl.duration;\r\n if (!Number.isFinite(duration) || duration <= 0) return;\r\n\r\n this.chapters = buildChapters(this.segments, duration);\r\n this.chapterEls = this.ctx.seekBar.setChapters(\r\n this.chapters.map((c) => ({ start: c.start / duration, end: c.end / duration, color: c.color }))\r\n );\r\n };\r\n\r\n private readonly onPointerMove = (e: PointerEvent): void => {\r\n const duration = this.ctx.videoEl.duration;\r\n if (!this.chapters.length || !Number.isFinite(duration) || duration <= 0) return;\r\n\r\n const time = this.ctx.seekBar.ratioAtClientX(e.clientX) * duration;\r\n let index = this.chapters.findIndex((c) => time < c.end);\r\n if (index === -1) index = this.chapters.length - 1;\r\n this.setHover(index);\r\n\r\n const chapter = this.chapters[index]!;\r\n this.titleEl.textContent = chapter.text ?? '';\r\n this.titleEl.style.display = chapter.text ? '' : 'none';\r\n this.timeEl.textContent = formatTime(time);\r\n\r\n // sprite-thumbnails önizlemesi de seek bar'ın hemen üstünde açılıyor —\r\n // görünürse popup onun ÜSTÜNE çıkıyor (üst üste binmesin).\r\n const sprite = this.ctx.seekBar.el.querySelector<HTMLElement>('[part=\"sprite-tooltip\"]');\r\n const spriteH = sprite && sprite.hasAttribute('data-visible') && sprite.offsetHeight > 0 ? sprite.offsetHeight + 8 : 0;\r\n this.tooltipEl.style.bottom = spriteH ? `calc(100% + 6px + ${spriteH}px)` : '';\r\n // Sprite önizlemesi zamanı zaten kendi altında gösteriyor — aynı zaman iki kez yazılmasın.\r\n this.timeEl.style.display = spriteH ? 'none' : '';\r\n\r\n // Popup imleci ortalar ama seek bar kenarlarından taşmaz.\r\n const barRect = this.ctx.seekBar.el.getBoundingClientRect();\r\n this.tooltipEl.setAttribute('data-visible', '');\r\n const tipWidth = this.tooltipEl.offsetWidth;\r\n const x = Math.min(Math.max(e.clientX - barRect.left - tipWidth / 2, 0), Math.max(barRect.width - tipWidth, 0));\r\n this.tooltipEl.style.transform = `translateX(${x}px)`;\r\n };\r\n\r\n private readonly onPointerLeave = (): void => {\r\n this.setHover(-1);\r\n this.tooltipEl.removeAttribute('data-visible');\r\n };\r\n\r\n private setHover(index: number): void {\r\n if (index === this.hoverIndex) return;\r\n this.chapterEls[this.hoverIndex]?.removeAttribute('data-hover');\r\n this.hoverIndex = index;\r\n this.chapterEls[index]?.setAttribute('data-hover', '');\r\n }\r\n}\r\n\r\n/** Segmentleri sıralar, boşlukları adsız bölümle doldurur, son bölümü video sonuna uzatır — sonuç 0→duration'ı kesintisiz kaplar. */\r\nfunction buildChapters(segments: SegmentItem[], duration: number): Chapter[] {\r\n const sorted = segments\r\n .filter((s) => Number.isFinite(s.start) && s.start < duration)\r\n .slice()\r\n .sort((a, b) => a.start - b.start);\r\n\r\n const chapters: Chapter[] = [];\r\n let cursor = 0;\r\n for (const seg of sorted) {\r\n const start = Math.max(seg.start, cursor);\r\n const end = Math.min(Number.isFinite(seg.end) ? seg.end : duration, duration);\r\n if (end <= start) continue;\r\n if (start > cursor) chapters.push({ start: cursor, end: start });\r\n chapters.push({ start, end, text: seg.text, color: seg.color });\r\n cursor = end;\r\n }\r\n if (!chapters.length) return [];\r\n if (cursor < duration) chapters[chapters.length - 1]!.end = duration;\r\n return chapters;\r\n}\r\n","import { Segments, type SegmentsPlayerContext } from './Segments';\nimport type { SegmentItem } from '../../types';\n\nexport function installSegments(ctx: SegmentsPlayerContext, items: SegmentItem[]): Segments {\n return new Segments(ctx, items);\n}\n\nexport { Segments };\nexport type { SegmentsPlayerContext };\n"],"names":["Segments","ctx","segments","__publicField","duration","buildChapters","c","e","time","index","chapter","formatTime","sprite","spriteH","barRect","tipWidth","x","_a","_b","sorted","a","b","chapters","cursor","seg","start","end","installSegments","items"],"mappings":"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"}
|