unified-video-framework 1.4.379 → 1.4.380

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unified-video-framework",
3
- "version": "1.4.379",
3
+ "version": "1.4.380",
4
4
  "description": "Cross-platform video player framework supporting iOS, Android, Web, Smart TVs (Samsung/LG), Roku, and more",
5
5
  "main": "packages/core/dist/index.js",
6
6
  "types": "packages/core/dist/index.d.ts",
@@ -1,5 +1,5 @@
1
1
  import { BasePlayer } from "../../core/dist/BasePlayer.js";
2
- import { ChapterManager as CoreChapterManager } from "@unified-video/core";
2
+ import { ChapterManager as CoreChapterManager } from "../../core/dist/index.js";
3
3
  import { ChapterManager } from "./chapters/ChapterManager.js";
4
4
  import YouTubeExtractor from "./utils/YouTubeExtractor.js";
5
5
  export class WebPlayer extends BasePlayer {
@@ -1,4 +1,4 @@
1
- import { DRMErrorCode, } from "@unified-video/core";
1
+ import { DRMErrorCode, } from '../../core/dist/index.js';
2
2
  export class WebDRMProtection {
3
3
  constructor(videoElement) {
4
4
  this.mediaKeys = null;
@@ -1,4 +1,4 @@
1
- export * from "@unified-video/core";
1
+ export * from "../../core/dist/index.js";
2
2
  export { WebPlayer } from "./WebPlayer.js";
3
3
  export { WebPlayerView } from "./react/WebPlayerView.js";
4
4
  export { SecureVideoPlayer } from "./SecureVideoPlayer.js";
@@ -11,25 +11,9 @@ const path = require('path');
11
11
  function fixImports(filePath) {
12
12
  let content = fs.readFileSync(filePath, 'utf8');
13
13
 
14
- // REVERSE: Convert relative core imports BACK to @unified-video/core
14
+ // Keep relative imports to ../../core/dist - they work in node_modules
15
15
  if (filePath.includes(path.join('packages', 'web', 'dist'))) {
16
- // Convert relative paths back to package imports
17
- content = content.replace(
18
- /require\(["']\.\.\/\.\.\/core\/dist["']\)/g,
19
- 'require("@unified-video/core")'
20
- );
21
- content = content.replace(
22
- /from\s+["']\.\.\/\.\.\/core\/dist\/index\.js["']/g,
23
- 'from "@unified-video/core"'
24
- );
25
- content = content.replace(
26
- /import\s+["']\.\.\/\.\.\/core\/dist\/index\.js["']/g,
27
- 'import "@unified-video/core"'
28
- );
29
- content = content.replace(
30
- /from\s+["']\.\.\/\.\.\/core\/dist["']/g,
31
- 'from "@unified-video/core"'
32
- );
16
+ // No changes needed for core imports - relative paths work fine
33
17
 
34
18
  // Fix relative imports within the same package to include .js extension
35
19
  content = content.replace(
@@ -46,23 +30,7 @@ function fixImports(filePath) {
46
30
  }
47
31
  );
48
32
  } else if (filePath.includes(path.join('packages', 'react-native', 'dist'))) {
49
- // Convert relative paths back to package imports
50
- content = content.replace(
51
- /require\(["']\.\.\/\.\.\/core\/dist["']\)/g,
52
- 'require("@unified-video/core")'
53
- );
54
- content = content.replace(
55
- /from\s+["']\.\.\/\.\.\/core\/dist\/index\.js["']/g,
56
- 'from "@unified-video/core"'
57
- );
58
- content = content.replace(
59
- /import\s+["']\.\.\/\.\.\/core\/dist\/index\.js["']/g,
60
- 'import "@unified-video/core"'
61
- );
62
- content = content.replace(
63
- /from\s+["']\.\.\/\.\.\/core\/dist["']/g,
64
- 'from "@unified-video/core"'
65
- );
33
+ // No changes needed for core imports - relative paths work fine
66
34
 
67
35
  // Fix relative imports within the same package to include .js extension
68
36
  content = content.replace(
@@ -1,65 +0,0 @@
1
- import { AdsManagerConfig, AdEventType } from './types';
2
- export declare class AdsManager {
3
- private config;
4
- private adContainer;
5
- private videoElement;
6
- private currentAdBreak;
7
- private currentAd;
8
- private adBreaks;
9
- private sessionId;
10
- private contentStarted;
11
- private adsCompleted;
12
- private imaSDKLoaded;
13
- private adsLoader;
14
- private adsManager;
15
- private adDisplayContainer;
16
- private eventListeners;
17
- private isAdPlaying;
18
- private pauseAdShown;
19
- private originalVideoSrc;
20
- constructor(config: AdsManagerConfig);
21
- private init;
22
- private loadIMASDK;
23
- private initializeIMA;
24
- private setupAdContainer;
25
- private setupVideoListeners;
26
- private fetchAdConfiguration;
27
- requestPrerollAds(): void;
28
- requestMidrollAds(position: number): void;
29
- requestPostrollAds(): void;
30
- private requestAdBreak;
31
- private requestAdsFromVAST;
32
- private onAdsManagerLoaded;
33
- private attachIMAEventListeners;
34
- private startAds;
35
- private onAdLoaded;
36
- private onAdStarted;
37
- private onAdQuartile;
38
- private onAdComplete;
39
- private onAdSkipped;
40
- private onAdClicked;
41
- private onAdError;
42
- private endAdBreak;
43
- private onVideoPlay;
44
- private onVideoPause;
45
- private onVideoTimeUpdate;
46
- private onVideoEnded;
47
- private playCustomAd;
48
- private showPauseAd;
49
- private trackEvent;
50
- on(eventType: AdEventType | string, callback: Function): void;
51
- off(eventType: AdEventType | string, callback: Function): void;
52
- private emit;
53
- private handleError;
54
- private resolveElement;
55
- private generateSessionId;
56
- private getContentId;
57
- private detectDeviceType;
58
- private log;
59
- destroy(): void;
60
- pause(): void;
61
- resume(): void;
62
- skip(): void;
63
- resize(width: number, height: number): void;
64
- }
65
- //# sourceMappingURL=AdsManager.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AdsManager.d.ts","sourceRoot":"","sources":["../../src/ads/AdsManager.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,gBAAgB,EAIhB,WAAW,EAOZ,MAAM,SAAS,CAAC;AAEjB,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,YAAY,CAAmB;IACvC,OAAO,CAAC,cAAc,CAAwB;IAC9C,OAAO,CAAC,SAAS,CAAmB;IACpC,OAAO,CAAC,QAAQ,CAAiB;IACjC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,YAAY,CAA0B;IAG9C,OAAO,CAAC,YAAY,CAAkB;IACtC,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,kBAAkB,CAAa;IAGvC,OAAO,CAAC,cAAc,CAAsC;IAG5D,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,YAAY,CAAkB;IACtC,OAAO,CAAC,gBAAgB,CAAc;gBAE1B,MAAM,EAAE,gBAAgB;YA8BtB,IAAI;YAsBJ,UAAU;IA8BxB,OAAO,CAAC,aAAa;IA0BrB,OAAO,CAAC,gBAAgB;IAWxB,OAAO,CAAC,mBAAmB;YAYb,oBAAoB;IAsD3B,iBAAiB,IAAI,IAAI;IAOzB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IASzC,kBAAkB,IAAI,IAAI;IAOjC,OAAO,CAAC,cAAc;IAkBtB,OAAO,CAAC,kBAAkB;IAgB1B,OAAO,CAAC,kBAAkB;IAc1B,OAAO,CAAC,uBAAuB;IAc/B,OAAO,CAAC,QAAQ;IA6BhB,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,WAAW;IAyBnB,OAAO,CAAC,YAAY;IAmBpB,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,WAAW;IAYnB,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,SAAS;IAcjB,OAAO,CAAC,UAAU;IAyBlB,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,iBAAiB;IAqBzB,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,WAAW;YAWL,UAAU;IA+BjB,EAAE,CAAC,SAAS,EAAE,WAAW,GAAG,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAO7D,GAAG,CAAC,SAAS,EAAE,WAAW,GAAG,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAUrE,OAAO,CAAC,IAAI;IAkBZ,OAAO,CAAC,WAAW;IAanB,OAAO,CAAC,cAAc;IAWtB,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,YAAY;IAKpB,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,GAAG;IAUJ,OAAO,IAAI,IAAI;IAgBf,KAAK,IAAI,IAAI;IAMb,MAAM,IAAI,IAAI;IAMd,IAAI,IAAI,IAAI;IAMZ,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;CAKnD"}
@@ -1,495 +0,0 @@
1
- import { AdPlacement, AdEventType, AdType, } from "./types.js";
2
- export class AdsManager {
3
- constructor(config) {
4
- this.currentAdBreak = null;
5
- this.currentAd = null;
6
- this.adBreaks = [];
7
- this.contentStarted = false;
8
- this.adsCompleted = new Set();
9
- this.imaSDKLoaded = false;
10
- this.adsLoader = null;
11
- this.adsManager = null;
12
- this.adDisplayContainer = null;
13
- this.eventListeners = new Map();
14
- this.isAdPlaying = false;
15
- this.pauseAdShown = false;
16
- this.originalVideoSrc = '';
17
- this.config = {
18
- adsManagerUrl: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js',
19
- debug: false,
20
- maxAdsPerBreak: 3,
21
- maxTotalAds: 10,
22
- adTimeout: 5000,
23
- retryOnError: true,
24
- maxRetryAttempts: 3,
25
- ...config,
26
- };
27
- this.adContainer = this.resolveElement(this.config.adContainer);
28
- this.videoElement = this.resolveElement(this.config.videoElement);
29
- this.sessionId = this.generateSessionId();
30
- this.originalVideoSrc = this.videoElement.src || this.videoElement.currentSrc;
31
- this.init();
32
- }
33
- async init() {
34
- try {
35
- if (this.config.adsEnabled) {
36
- await this.loadIMASDK();
37
- this.setupAdContainer();
38
- this.setupVideoListeners();
39
- if (this.config.apiEndpoint) {
40
- await this.fetchAdConfiguration();
41
- }
42
- this.log('AdsManager initialized successfully');
43
- }
44
- }
45
- catch (error) {
46
- this.handleError({
47
- code: 1000,
48
- message: 'Failed to initialize AdsManager',
49
- details: error,
50
- });
51
- }
52
- }
53
- async loadIMASDK() {
54
- return new Promise((resolve, reject) => {
55
- if (typeof window.google !== 'undefined' && window.google.ima) {
56
- this.imaSDKLoaded = true;
57
- this.initializeIMA();
58
- resolve();
59
- return;
60
- }
61
- const script = document.createElement('script');
62
- script.src = this.config.adsManagerUrl;
63
- script.async = true;
64
- script.onload = () => {
65
- this.imaSDKLoaded = true;
66
- this.initializeIMA();
67
- this.log('Google IMA SDK loaded');
68
- resolve();
69
- };
70
- script.onerror = () => {
71
- reject(new Error('Failed to load Google IMA SDK'));
72
- };
73
- document.head.appendChild(script);
74
- });
75
- }
76
- initializeIMA() {
77
- const ima = window.google.ima;
78
- this.adDisplayContainer = new ima.AdDisplayContainer(this.adContainer, this.videoElement);
79
- this.adsLoader = new ima.AdsLoader(this.adDisplayContainer);
80
- this.adsLoader.addEventListener(ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, this.onAdsManagerLoaded.bind(this), false);
81
- this.adsLoader.addEventListener(ima.AdErrorEvent.Type.AD_ERROR, this.onAdError.bind(this), false);
82
- }
83
- setupAdContainer() {
84
- this.adContainer.style.position = 'absolute';
85
- this.adContainer.style.top = '0';
86
- this.adContainer.style.left = '0';
87
- this.adContainer.style.width = '100%';
88
- this.adContainer.style.height = '100%';
89
- this.adContainer.style.zIndex = '1000';
90
- this.adContainer.style.display = 'none';
91
- }
92
- setupVideoListeners() {
93
- this.videoElement.addEventListener('play', this.onVideoPlay.bind(this));
94
- this.videoElement.addEventListener('pause', this.onVideoPause.bind(this));
95
- this.videoElement.addEventListener('timeupdate', this.onVideoTimeUpdate.bind(this));
96
- this.videoElement.addEventListener('ended', this.onVideoEnded.bind(this));
97
- }
98
- async fetchAdConfiguration() {
99
- try {
100
- const request = {
101
- contentId: this.getContentId(),
102
- sessionId: this.sessionId,
103
- placement: AdPlacement.PREROLL,
104
- width: this.videoElement.clientWidth,
105
- height: this.videoElement.clientHeight,
106
- deviceType: this.detectDeviceType(),
107
- browser: navigator.userAgent,
108
- language: navigator.language,
109
- referrer: document.referrer,
110
- gdprConsent: this.config.gdprConsent,
111
- coppa: this.config.coppa,
112
- };
113
- const response = await fetch(`${this.config.apiEndpoint}/config?${new URLSearchParams(request)}`, {
114
- method: 'GET',
115
- headers: {
116
- 'Content-Type': 'application/json',
117
- },
118
- });
119
- const data = await response.json();
120
- if (data.status === 'success' && data.data) {
121
- this.adBreaks = data.data.adBreaks;
122
- this.log('Ad configuration fetched', data);
123
- if (this.config.preroll && this.adBreaks.some(ab => ab.type === AdPlacement.PREROLL)) {
124
- this.requestPrerollAds();
125
- }
126
- }
127
- else if (data.status === 'no_ads') {
128
- this.log('No ads available');
129
- }
130
- else {
131
- throw new Error(data.message || 'Failed to fetch ad configuration');
132
- }
133
- }
134
- catch (error) {
135
- this.handleError({
136
- code: 1001,
137
- message: 'Failed to fetch ad configuration',
138
- details: error,
139
- });
140
- }
141
- }
142
- requestPrerollAds() {
143
- const prerollBreak = this.adBreaks.find(ab => ab.type === AdPlacement.PREROLL);
144
- if (prerollBreak) {
145
- this.requestAdBreak(prerollBreak);
146
- }
147
- }
148
- requestMidrollAds(position) {
149
- const midrollBreak = this.adBreaks.find(ab => ab.type === AdPlacement.MIDROLL && ab.position === position);
150
- if (midrollBreak) {
151
- this.requestAdBreak(midrollBreak);
152
- }
153
- }
154
- requestPostrollAds() {
155
- const postrollBreak = this.adBreaks.find(ab => ab.type === AdPlacement.POSTROLL);
156
- if (postrollBreak) {
157
- this.requestAdBreak(postrollBreak);
158
- }
159
- }
160
- requestAdBreak(adBreak) {
161
- this.currentAdBreak = adBreak;
162
- const firstAd = adBreak.ads[0];
163
- if (firstAd && firstAd.vastUrl) {
164
- this.requestAdsFromVAST(firstAd.vastUrl);
165
- }
166
- else if (firstAd && firstAd.videoUrl) {
167
- this.playCustomAd(firstAd);
168
- }
169
- this.emit(AdEventType.AD_BREAK_READY, { adBreak });
170
- if (this.config.onAdBreakReady) {
171
- this.config.onAdBreakReady(adBreak);
172
- }
173
- }
174
- requestAdsFromVAST(vastUrl) {
175
- const ima = window.google.ima;
176
- const adsRequest = new ima.AdsRequest();
177
- adsRequest.adTagUrl = vastUrl;
178
- adsRequest.linearAdSlotWidth = this.videoElement.clientWidth;
179
- adsRequest.linearAdSlotHeight = this.videoElement.clientHeight;
180
- adsRequest.nonLinearAdSlotWidth = this.videoElement.clientWidth;
181
- adsRequest.nonLinearAdSlotHeight = this.videoElement.clientHeight / 3;
182
- this.adsLoader.requestAds(adsRequest);
183
- }
184
- onAdsManagerLoaded(adsManagerLoadedEvent) {
185
- const ima = window.google.ima;
186
- const adsRenderingSettings = new ima.AdsRenderingSettings();
187
- adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true;
188
- this.adsManager = adsManagerLoadedEvent.getAdsManager(this.videoElement, adsRenderingSettings);
189
- this.attachIMAEventListeners();
190
- this.startAds();
191
- }
192
- attachIMAEventListeners() {
193
- const ima = window.google.ima;
194
- this.adsManager.addEventListener(ima.AdEvent.Type.LOADED, this.onAdLoaded.bind(this));
195
- this.adsManager.addEventListener(ima.AdEvent.Type.STARTED, this.onAdStarted.bind(this));
196
- this.adsManager.addEventListener(ima.AdEvent.Type.FIRST_QUARTILE, this.onAdQuartile.bind(this));
197
- this.adsManager.addEventListener(ima.AdEvent.Type.MIDPOINT, this.onAdQuartile.bind(this));
198
- this.adsManager.addEventListener(ima.AdEvent.Type.THIRD_QUARTILE, this.onAdQuartile.bind(this));
199
- this.adsManager.addEventListener(ima.AdEvent.Type.COMPLETE, this.onAdComplete.bind(this));
200
- this.adsManager.addEventListener(ima.AdEvent.Type.SKIPPED, this.onAdSkipped.bind(this));
201
- this.adsManager.addEventListener(ima.AdEvent.Type.CLICKED, this.onAdClicked.bind(this));
202
- this.adsManager.addEventListener(ima.AdErrorEvent.Type.AD_ERROR, this.onAdError.bind(this));
203
- }
204
- startAds() {
205
- try {
206
- this.adDisplayContainer.initialize();
207
- const width = this.videoElement.clientWidth;
208
- const height = this.videoElement.clientHeight;
209
- const viewMode = 'normal';
210
- this.adsManager.init(width, height, viewMode);
211
- this.adsManager.start();
212
- this.isAdPlaying = true;
213
- this.adContainer.style.display = 'block';
214
- if (this.currentAdBreak) {
215
- this.emit(AdEventType.AD_BREAK_STARTED, { adBreak: this.currentAdBreak });
216
- if (this.config.onAdBreakStarted) {
217
- this.config.onAdBreakStarted(this.currentAdBreak);
218
- }
219
- }
220
- }
221
- catch (error) {
222
- this.handleError({
223
- code: 1002,
224
- message: 'Failed to start ads',
225
- details: error,
226
- });
227
- }
228
- }
229
- onAdLoaded(adEvent) {
230
- this.log('Ad loaded', adEvent);
231
- this.emit(AdEventType.LOADED, { ad: this.currentAd || undefined });
232
- }
233
- onAdStarted(adEvent) {
234
- const ad = adEvent.getAd();
235
- this.currentAd = {
236
- id: ad.getAdId(),
237
- type: AdType.SKIPPABLE_IN_STREAM,
238
- metadata: {
239
- id: ad.getAdId(),
240
- title: ad.getTitle(),
241
- description: ad.getDescription(),
242
- advertiser: ad.getAdvertiserName(),
243
- duration: ad.getDuration(),
244
- skippable: ad.isSkippable(),
245
- skipOffset: ad.getSkipTimeOffset(),
246
- },
247
- };
248
- this.log('Ad started', this.currentAd);
249
- this.emit(AdEventType.STARTED, { ad: this.currentAd });
250
- this.trackEvent(AdEventType.STARTED);
251
- if (this.config.onAdStarted) {
252
- this.config.onAdStarted(this.currentAd);
253
- }
254
- }
255
- onAdQuartile(adEvent) {
256
- const eventType = adEvent.type;
257
- let quartileEvent;
258
- if (eventType.includes('FIRST_QUARTILE')) {
259
- quartileEvent = AdEventType.FIRST_QUARTILE;
260
- }
261
- else if (eventType.includes('MIDPOINT')) {
262
- quartileEvent = AdEventType.MIDPOINT;
263
- }
264
- else if (eventType.includes('THIRD_QUARTILE')) {
265
- quartileEvent = AdEventType.THIRD_QUARTILE;
266
- }
267
- else {
268
- return;
269
- }
270
- this.log(`Ad ${quartileEvent}`, this.currentAd);
271
- this.emit(quartileEvent, { ad: this.currentAd || undefined });
272
- this.trackEvent(quartileEvent);
273
- }
274
- onAdComplete(adEvent) {
275
- this.log('Ad completed', this.currentAd);
276
- this.emit(AdEventType.COMPLETED, { ad: this.currentAd || undefined });
277
- this.trackEvent(AdEventType.COMPLETED);
278
- if (this.config.onAdCompleted && this.currentAd) {
279
- this.config.onAdCompleted(this.currentAd);
280
- }
281
- this.endAdBreak();
282
- }
283
- onAdSkipped(adEvent) {
284
- this.log('Ad skipped', this.currentAd);
285
- this.emit(AdEventType.SKIPPED, { ad: this.currentAd || undefined });
286
- this.trackEvent(AdEventType.SKIPPED);
287
- if (this.config.onAdSkipped && this.currentAd) {
288
- this.config.onAdSkipped(this.currentAd);
289
- }
290
- this.endAdBreak();
291
- }
292
- onAdClicked(adEvent) {
293
- this.log('Ad clicked', this.currentAd);
294
- this.emit(AdEventType.CLICKED, { ad: this.currentAd || undefined });
295
- this.trackEvent(AdEventType.CLICKED);
296
- }
297
- onAdError(adErrorEvent) {
298
- const error = adErrorEvent.getError();
299
- this.handleError({
300
- code: error.getErrorCode(),
301
- message: error.getMessage(),
302
- ad: this.currentAd || undefined,
303
- adBreak: this.currentAdBreak || undefined,
304
- details: error,
305
- });
306
- this.endAdBreak();
307
- }
308
- endAdBreak() {
309
- this.isAdPlaying = false;
310
- this.adContainer.style.display = 'none';
311
- if (this.currentAdBreak) {
312
- this.emit(AdEventType.AD_BREAK_COMPLETED, { adBreak: this.currentAdBreak });
313
- if (this.config.onAdBreakCompleted) {
314
- this.config.onAdBreakCompleted(this.currentAdBreak);
315
- }
316
- }
317
- this.currentAd = null;
318
- this.currentAdBreak = null;
319
- if (!this.contentStarted) {
320
- this.videoElement.play();
321
- this.contentStarted = true;
322
- }
323
- }
324
- onVideoPlay() {
325
- if (!this.contentStarted && this.config.preroll) {
326
- this.videoElement.pause();
327
- this.requestPrerollAds();
328
- }
329
- }
330
- onVideoPause() {
331
- if (this.config.pauseAds && !this.pauseAdShown && !this.isAdPlaying) {
332
- setTimeout(() => {
333
- if (this.videoElement.paused) {
334
- this.showPauseAd();
335
- }
336
- }, (this.config.pauseAds.triggers.minPauseDuration || 3) * 1000);
337
- }
338
- }
339
- onVideoTimeUpdate() {
340
- const currentTime = this.videoElement.currentTime;
341
- this.adBreaks.forEach((adBreak) => {
342
- if (adBreak.type === AdPlacement.MIDROLL) {
343
- const position = typeof adBreak.position === 'number' ? adBreak.position : 0;
344
- if (!this.adsCompleted.has(adBreak.id) &&
345
- currentTime >= position &&
346
- currentTime < position + 1) {
347
- this.videoElement.pause();
348
- this.requestAdBreak(adBreak);
349
- this.adsCompleted.add(adBreak.id);
350
- }
351
- }
352
- });
353
- }
354
- onVideoEnded() {
355
- if (this.config.postroll) {
356
- this.requestPostrollAds();
357
- }
358
- else {
359
- this.emit(AdEventType.ALL_ADS_COMPLETED, {});
360
- if (this.config.onAllAdsCompleted) {
361
- this.config.onAllAdsCompleted();
362
- }
363
- }
364
- }
365
- playCustomAd(ad) {
366
- this.log('Playing custom ad', ad);
367
- }
368
- showPauseAd() {
369
- this.pauseAdShown = true;
370
- this.log('Showing pause ad');
371
- }
372
- async trackEvent(eventType) {
373
- if (!this.config.apiEndpoint || !this.currentAd)
374
- return;
375
- try {
376
- const request = {
377
- eventType,
378
- adId: this.currentAd.id,
379
- sessionId: this.sessionId,
380
- contentId: this.getContentId(),
381
- timestamp: new Date().toISOString(),
382
- playerTime: this.videoElement.currentTime,
383
- };
384
- await fetch(`${this.config.apiEndpoint}/track/event`, {
385
- method: 'POST',
386
- headers: {
387
- 'Content-Type': 'application/json',
388
- },
389
- body: JSON.stringify(request),
390
- });
391
- this.log(`Tracked event: ${eventType}`);
392
- }
393
- catch (error) {
394
- this.log(`Failed to track event: ${eventType}`, error);
395
- }
396
- }
397
- on(eventType, callback) {
398
- if (!this.eventListeners.has(eventType)) {
399
- this.eventListeners.set(eventType, []);
400
- }
401
- this.eventListeners.get(eventType).push(callback);
402
- }
403
- off(eventType, callback) {
404
- const listeners = this.eventListeners.get(eventType);
405
- if (listeners) {
406
- const index = listeners.indexOf(callback);
407
- if (index > -1) {
408
- listeners.splice(index, 1);
409
- }
410
- }
411
- }
412
- emit(eventType, data) {
413
- const listeners = this.eventListeners.get(eventType);
414
- if (listeners) {
415
- const event = {
416
- type: eventType,
417
- timestamp: new Date().toISOString(),
418
- playerTime: this.videoElement.currentTime,
419
- ...data,
420
- };
421
- listeners.forEach((callback) => callback(event));
422
- }
423
- }
424
- handleError(error) {
425
- this.log('Ad error', error);
426
- this.emit(AdEventType.AD_ERROR, { customData: error });
427
- if (this.config.onAdError) {
428
- this.config.onAdError(error);
429
- }
430
- }
431
- resolveElement(element) {
432
- if (typeof element === 'string') {
433
- const el = document.querySelector(element);
434
- if (!el) {
435
- throw new Error(`Element not found: ${element}`);
436
- }
437
- return el;
438
- }
439
- return element;
440
- }
441
- generateSessionId() {
442
- return `ads-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
443
- }
444
- getContentId() {
445
- return this.originalVideoSrc || 'unknown';
446
- }
447
- detectDeviceType() {
448
- const ua = navigator.userAgent;
449
- if (/mobile/i.test(ua))
450
- return 'mobile';
451
- if (/tablet|ipad/i.test(ua))
452
- return 'tablet';
453
- if (/tv|smarttv/i.test(ua))
454
- return 'tv';
455
- return 'desktop';
456
- }
457
- log(message, ...args) {
458
- if (this.config.debug) {
459
- console.log(`[AdsManager] ${message}`, ...args);
460
- }
461
- }
462
- destroy() {
463
- if (this.adsManager) {
464
- this.adsManager.destroy();
465
- }
466
- if (this.adsLoader) {
467
- this.adsLoader.destroy();
468
- }
469
- this.eventListeners.clear();
470
- this.adBreaks = [];
471
- this.adsCompleted.clear();
472
- this.log('AdsManager destroyed');
473
- }
474
- pause() {
475
- if (this.adsManager && this.isAdPlaying) {
476
- this.adsManager.pause();
477
- }
478
- }
479
- resume() {
480
- if (this.adsManager && this.isAdPlaying) {
481
- this.adsManager.resume();
482
- }
483
- }
484
- skip() {
485
- if (this.adsManager && this.isAdPlaying) {
486
- this.adsManager.skip();
487
- }
488
- }
489
- resize(width, height) {
490
- if (this.adsManager) {
491
- this.adsManager.resize(width, height, 'normal');
492
- }
493
- }
494
- }
495
- //# sourceMappingURL=AdsManager.js.map