@eyevinn/player-analytics-client-sdk-web 0.2.0 → 0.4.0
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/.github/workflows/deploy-demo.yml +29 -0
- package/Readme.md +248 -46
- package/dist/index.d.ts +2 -0
- package/dist/index.js +513 -85
- package/dist/index.js.map +1 -1
- package/dist/module.js +513 -85
- package/dist/module.js.map +1 -1
- package/dist/types.d.ts +29 -8
- package/dist/types.d.ts.map +1 -1
- package/index.ts +7 -0
- package/package.json +15 -4
- package/pipeline.png +0 -0
- package/spec/PlayerAnalytics.spec.ts +338 -0
- package/spec/PlayerAnalyticsConnector.spec.ts +1474 -0
- package/spec/Reporter.spec.ts +825 -0
- package/spec/support/jasmine.json +7 -0
- package/tsconfig.json +1 -1
package/dist/module.js
CHANGED
|
@@ -148,44 +148,81 @@ var $1d47cc84225ea891$var$__generator = undefined && undefined.__generator || fu
|
|
|
148
148
|
return this;
|
|
149
149
|
}), g;
|
|
150
150
|
};
|
|
151
|
+
var $1d47cc84225ea891$var$MAX_QUEUE_SIZE = 100;
|
|
151
152
|
var $1d47cc84225ea891$export$957313a2f485e5ed = function() {
|
|
152
153
|
function $1d47cc84225ea891$export$957313a2f485e5ed(options) {
|
|
153
|
-
|
|
154
|
-
this.
|
|
154
|
+
var _a;
|
|
155
|
+
this.state = "idle";
|
|
156
|
+
this.eventQueue = [];
|
|
157
|
+
this.initPromise = null;
|
|
158
|
+
this.debug = (_a = options.debug) !== null && _a !== void 0 ? _a : false;
|
|
159
|
+
this.shardId = options.shardId;
|
|
155
160
|
this.eventsinkUrl = options.eventsinkUrl;
|
|
156
161
|
this.sessionId = options.sessionId;
|
|
157
162
|
this.heartbeatInterval = options.heartbeatInterval || $76abaee2435acae3$export$31c453b5fe09788d;
|
|
163
|
+
this.onError = options.onError;
|
|
158
164
|
if (this.debug) console.log("[AnalyticsReporter] Initiated AnalyticsReporter", options);
|
|
159
165
|
}
|
|
166
|
+
Object.defineProperty($1d47cc84225ea891$export$957313a2f485e5ed.prototype, "isInitiated", {
|
|
167
|
+
get: function() {
|
|
168
|
+
return this.state === "ready";
|
|
169
|
+
},
|
|
170
|
+
enumerable: false,
|
|
171
|
+
configurable: true
|
|
172
|
+
});
|
|
160
173
|
$1d47cc84225ea891$export$957313a2f485e5ed.prototype.init = function(sessionId) {
|
|
161
174
|
return $1d47cc84225ea891$var$__awaiter(this, void 0, Promise, function() {
|
|
162
|
-
var data,
|
|
175
|
+
var data, result;
|
|
176
|
+
return $1d47cc84225ea891$var$__generator(this, function(_a) {
|
|
177
|
+
if (this.state !== "idle") return [
|
|
178
|
+
2 /*return*/ ,
|
|
179
|
+
this.initPromise
|
|
180
|
+
];
|
|
181
|
+
this.sessionId = sessionId || this.sessionId;
|
|
182
|
+
this.state = "initializing";
|
|
183
|
+
data = {
|
|
184
|
+
event: "init",
|
|
185
|
+
sessionId: this.sessionId,
|
|
186
|
+
shardId: this.shardId,
|
|
187
|
+
timestamp: Date.now(),
|
|
188
|
+
playhead: -1,
|
|
189
|
+
duration: -1
|
|
190
|
+
};
|
|
191
|
+
if (this.debug) {
|
|
192
|
+
console.log("[AnalyticsReporter] Init session:", data);
|
|
193
|
+
this.state = "ready";
|
|
194
|
+
this.flushQueue();
|
|
195
|
+
result = {
|
|
196
|
+
sessionId: this.sessionId,
|
|
197
|
+
heartbeatInterval: this.heartbeatInterval,
|
|
198
|
+
isInitiated: true
|
|
199
|
+
};
|
|
200
|
+
this.initPromise = Promise.resolve(result);
|
|
201
|
+
return [
|
|
202
|
+
2 /*return*/ ,
|
|
203
|
+
this.initPromise
|
|
204
|
+
];
|
|
205
|
+
}
|
|
206
|
+
this.initPromise = this.doInit(data);
|
|
207
|
+
return [
|
|
208
|
+
2 /*return*/ ,
|
|
209
|
+
this.initPromise
|
|
210
|
+
];
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
};
|
|
214
|
+
$1d47cc84225ea891$export$957313a2f485e5ed.prototype.doInit = function(data) {
|
|
215
|
+
return $1d47cc84225ea891$var$__awaiter(this, void 0, Promise, function() {
|
|
216
|
+
var initResponse, initResponseJson, err_1;
|
|
163
217
|
return $1d47cc84225ea891$var$__generator(this, function(_a) {
|
|
164
218
|
switch(_a.label){
|
|
165
219
|
case 0:
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
duration: -1
|
|
173
|
-
};
|
|
174
|
-
if (!this.debug) return [
|
|
175
|
-
3 /*break*/ ,
|
|
176
|
-
1
|
|
177
|
-
];
|
|
178
|
-
console.log("[AnalyticsReporter] Init session:", data);
|
|
179
|
-
this.isInitiated = true;
|
|
180
|
-
return [
|
|
181
|
-
2 /*return*/ ,
|
|
182
|
-
{
|
|
183
|
-
sessionId: this.sessionId,
|
|
184
|
-
heartbeatInterval: this.heartbeatInterval,
|
|
185
|
-
isInitiated: this.isInitiated
|
|
186
|
-
}
|
|
187
|
-
];
|
|
188
|
-
case 1:
|
|
220
|
+
_a.trys.push([
|
|
221
|
+
0,
|
|
222
|
+
6,
|
|
223
|
+
,
|
|
224
|
+
7
|
|
225
|
+
]);
|
|
189
226
|
return [
|
|
190
227
|
4 /*yield*/ ,
|
|
191
228
|
fetch("".concat(this.eventsinkUrl), {
|
|
@@ -200,37 +237,150 @@ var $1d47cc84225ea891$export$957313a2f485e5ed = function() {
|
|
|
200
237
|
body: JSON.stringify(data)
|
|
201
238
|
})
|
|
202
239
|
];
|
|
203
|
-
case
|
|
240
|
+
case 1:
|
|
204
241
|
initResponse = _a.sent();
|
|
242
|
+
// Abort if destroy() was called during the await
|
|
243
|
+
if (this.state === "destroyed") throw new Error("[AnalyticsReporter] init aborted: reporter was destroyed");
|
|
205
244
|
if (!initResponse.ok) throw new Error("[AnalyticsReporter] init failed: ".concat(initResponse.statusText));
|
|
206
245
|
return [
|
|
207
246
|
4 /*yield*/ ,
|
|
208
247
|
initResponse.json()
|
|
209
248
|
];
|
|
210
|
-
case
|
|
249
|
+
case 2:
|
|
211
250
|
initResponseJson = _a.sent();
|
|
251
|
+
if (this.state === "destroyed") throw new Error("[AnalyticsReporter] init aborted: reporter was destroyed");
|
|
212
252
|
if (!this.sessionId && !initResponseJson.sessionId) throw new Error("[AnalyticsReporter] init failed: no sessionId");
|
|
213
253
|
if (initResponseJson.sessionId) this.sessionId = initResponseJson.sessionId;
|
|
214
|
-
|
|
254
|
+
_a.label = 3;
|
|
255
|
+
case 3:
|
|
256
|
+
if (!(this.eventQueue.length > 0)) return [
|
|
257
|
+
3 /*break*/ ,
|
|
258
|
+
5
|
|
259
|
+
];
|
|
260
|
+
if (this.state === "destroyed") throw new Error("[AnalyticsReporter] init aborted: reporter was destroyed");
|
|
261
|
+
return [
|
|
262
|
+
4 /*yield*/ ,
|
|
263
|
+
this.flushQueue()
|
|
264
|
+
];
|
|
265
|
+
case 4:
|
|
266
|
+
_a.sent();
|
|
267
|
+
return [
|
|
268
|
+
3 /*break*/ ,
|
|
269
|
+
3
|
|
270
|
+
];
|
|
271
|
+
case 5:
|
|
272
|
+
// Don't transition to ready if destroyed during flush
|
|
273
|
+
if (this.state !== "destroyed") this.state = "ready";
|
|
215
274
|
return [
|
|
216
275
|
2 /*return*/ ,
|
|
217
276
|
{
|
|
218
277
|
heartbeatInterval: this.heartbeatInterval,
|
|
219
278
|
sessionId: this.sessionId,
|
|
220
|
-
isInitiated:
|
|
279
|
+
isInitiated: true
|
|
221
280
|
}
|
|
222
281
|
];
|
|
282
|
+
case 6:
|
|
283
|
+
err_1 = _a.sent();
|
|
284
|
+
// Don't overwrite 'destroyed' state with 'failed'
|
|
285
|
+
if (this.state !== "destroyed") this.state = "failed";
|
|
286
|
+
this.eventQueue = [];
|
|
287
|
+
throw err_1;
|
|
288
|
+
case 7:
|
|
289
|
+
return [
|
|
290
|
+
2 /*return*/
|
|
291
|
+
];
|
|
223
292
|
}
|
|
224
293
|
});
|
|
225
294
|
});
|
|
226
295
|
};
|
|
227
296
|
$1d47cc84225ea891$export$957313a2f485e5ed.prototype.send = function(data) {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
297
|
+
switch(this.state){
|
|
298
|
+
case "ready":
|
|
299
|
+
this.dispatch(data);
|
|
300
|
+
break;
|
|
301
|
+
case "initializing":
|
|
302
|
+
if (this.eventQueue.length >= $1d47cc84225ea891$var$MAX_QUEUE_SIZE) {
|
|
303
|
+
console.warn("[AnalyticsReporter] Event queue full, dropping newest event");
|
|
304
|
+
break;
|
|
305
|
+
}
|
|
306
|
+
this.eventQueue.push(data);
|
|
307
|
+
break;
|
|
308
|
+
case "idle":
|
|
309
|
+
console.warn("[AnalyticsReporter] Cannot report before initiation:", data);
|
|
310
|
+
break;
|
|
311
|
+
case "failed":
|
|
312
|
+
console.warn("[AnalyticsReporter] Init failed, cannot send:", data);
|
|
313
|
+
break;
|
|
314
|
+
case "destroyed":
|
|
315
|
+
break;
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
$1d47cc84225ea891$export$957313a2f485e5ed.prototype.buildPayload = function(data) {
|
|
319
|
+
return $1d47cc84225ea891$var$__assign($1d47cc84225ea891$var$__assign({
|
|
320
|
+
}, data), {
|
|
321
|
+
sessionId: this.sessionId,
|
|
322
|
+
shardId: this.shardId
|
|
323
|
+
});
|
|
324
|
+
};
|
|
325
|
+
/**
|
|
326
|
+
* Deliver an event using a transport that survives page unload (tab close
|
|
327
|
+
* or reload).
|
|
328
|
+
*
|
|
329
|
+
* Uses `navigator.sendBeacon` with a `text/plain` JSON body. A plain-text
|
|
330
|
+
* body with no `X-EPAS-*` headers is a CORS "simple request", so the browser
|
|
331
|
+
* does not issue a preflight — the preflight is what gets dropped while the
|
|
332
|
+
* page is unloading, losing the event (notably the `stopped` event). The
|
|
333
|
+
* eventsink reads the event from the JSON body (`body.event`), not from
|
|
334
|
+
* headers, so the beacon is accepted.
|
|
335
|
+
*
|
|
336
|
+
* Falls back to `fetch(..., { keepalive: true })` when `sendBeacon` is
|
|
337
|
+
* unavailable or refuses the payload. Returns true when the event was handed
|
|
338
|
+
* off to a transport.
|
|
339
|
+
*/ $1d47cc84225ea891$export$957313a2f485e5ed.prototype.sendBeacon = function(data) {
|
|
340
|
+
if (this.state === "destroyed") return false;
|
|
341
|
+
var payload = this.buildPayload(data);
|
|
342
|
+
if (this.debug) {
|
|
343
|
+
console.log("[AnalyticsReporter] Send beacon payload:", payload);
|
|
344
|
+
return true;
|
|
345
|
+
}
|
|
346
|
+
var body = JSON.stringify(payload);
|
|
347
|
+
if (typeof navigator !== "undefined" && typeof navigator.sendBeacon === "function") try {
|
|
348
|
+
var blob = new Blob([
|
|
349
|
+
body
|
|
350
|
+
], {
|
|
351
|
+
type: "text/plain; charset=utf-8"
|
|
352
|
+
});
|
|
353
|
+
if (navigator.sendBeacon(this.eventsinkUrl, blob)) return true;
|
|
354
|
+
} catch (_a) {
|
|
355
|
+
// Fall through to the keepalive fetch fallback below.
|
|
356
|
+
}
|
|
357
|
+
if (typeof fetch === "function") try {
|
|
358
|
+
fetch("".concat(this.eventsinkUrl), {
|
|
359
|
+
method: "POST",
|
|
360
|
+
mode: "cors",
|
|
361
|
+
cache: "no-cache",
|
|
362
|
+
keepalive: true,
|
|
363
|
+
headers: {
|
|
364
|
+
"Content-Type": "text/plain; charset=utf-8"
|
|
365
|
+
},
|
|
366
|
+
body: body
|
|
367
|
+
}).catch(function() {
|
|
368
|
+
// Best-effort during unload — nothing actionable to do on failure.
|
|
369
|
+
});
|
|
370
|
+
return true;
|
|
371
|
+
} catch (_b) {
|
|
372
|
+
return false;
|
|
373
|
+
}
|
|
374
|
+
return false;
|
|
375
|
+
};
|
|
376
|
+
$1d47cc84225ea891$export$957313a2f485e5ed.prototype.dispatch = function(data) {
|
|
377
|
+
var _this = this;
|
|
378
|
+
var payload = this.buildPayload(data);
|
|
379
|
+
if (this.debug) {
|
|
380
|
+
console.log("[AnalyticsReporter] Send payload:", payload);
|
|
381
|
+
return Promise.resolve();
|
|
382
|
+
}
|
|
383
|
+
return fetch("".concat(this.eventsinkUrl), {
|
|
234
384
|
method: "POST",
|
|
235
385
|
mode: "cors",
|
|
236
386
|
cache: "no-cache",
|
|
@@ -240,8 +390,73 @@ var $1d47cc84225ea891$export$957313a2f485e5ed = function() {
|
|
|
240
390
|
"X-EPAS-Version": $76abaee2435acae3$export$8a65ed80196068d4
|
|
241
391
|
},
|
|
242
392
|
body: JSON.stringify(payload)
|
|
393
|
+
}).then(function(res) {
|
|
394
|
+
if (res && !res.ok) {
|
|
395
|
+
var error = {
|
|
396
|
+
status: res.status,
|
|
397
|
+
statusText: res.statusText,
|
|
398
|
+
message: "Send failed: ".concat(res.status, " ").concat(res.statusText)
|
|
399
|
+
};
|
|
400
|
+
if (_this.onError) _this.onError(error, data);
|
|
401
|
+
else console.warn("[AnalyticsReporter] ".concat(error.message));
|
|
402
|
+
}
|
|
403
|
+
}).catch(function(err) {
|
|
404
|
+
var error = {
|
|
405
|
+
message: err instanceof Error ? err.message : String(err)
|
|
406
|
+
};
|
|
407
|
+
if (_this.onError) _this.onError(error, data);
|
|
408
|
+
else console.warn("[AnalyticsReporter] Send failed:", error.message);
|
|
243
409
|
});
|
|
244
410
|
};
|
|
411
|
+
$1d47cc84225ea891$export$957313a2f485e5ed.prototype.flushQueue = function() {
|
|
412
|
+
return $1d47cc84225ea891$var$__awaiter(this, void 0, Promise, function() {
|
|
413
|
+
var queued, _i, queued_1, event;
|
|
414
|
+
return $1d47cc84225ea891$var$__generator(this, function(_a) {
|
|
415
|
+
switch(_a.label){
|
|
416
|
+
case 0:
|
|
417
|
+
queued = this.eventQueue;
|
|
418
|
+
this.eventQueue = [];
|
|
419
|
+
_i = 0, queued_1 = queued;
|
|
420
|
+
_a.label = 1;
|
|
421
|
+
case 1:
|
|
422
|
+
if (!(_i < queued_1.length)) return [
|
|
423
|
+
3 /*break*/ ,
|
|
424
|
+
4
|
|
425
|
+
];
|
|
426
|
+
event = queued_1[_i];
|
|
427
|
+
// Abort if destroy() was called mid-flush
|
|
428
|
+
if (this.state === "destroyed") return [
|
|
429
|
+
2 /*return*/
|
|
430
|
+
];
|
|
431
|
+
return [
|
|
432
|
+
4 /*yield*/ ,
|
|
433
|
+
this.dispatch(event)
|
|
434
|
+
];
|
|
435
|
+
case 2:
|
|
436
|
+
_a.sent();
|
|
437
|
+
_a.label = 3;
|
|
438
|
+
case 3:
|
|
439
|
+
_i++;
|
|
440
|
+
return [
|
|
441
|
+
3 /*break*/ ,
|
|
442
|
+
1
|
|
443
|
+
];
|
|
444
|
+
case 4:
|
|
445
|
+
return [
|
|
446
|
+
2 /*return*/
|
|
447
|
+
];
|
|
448
|
+
}
|
|
449
|
+
});
|
|
450
|
+
});
|
|
451
|
+
};
|
|
452
|
+
/**
|
|
453
|
+
* Tear down the reporter. Aborts any in-flight init, discards queued
|
|
454
|
+
* events without flushing, and prevents future send() calls from
|
|
455
|
+
* dispatching. Called by PlayerAnalytics.destroy().
|
|
456
|
+
*/ $1d47cc84225ea891$export$957313a2f485e5ed.prototype.destroy = function() {
|
|
457
|
+
this.state = "destroyed";
|
|
458
|
+
this.eventQueue = [];
|
|
459
|
+
};
|
|
245
460
|
return $1d47cc84225ea891$export$957313a2f485e5ed;
|
|
246
461
|
}();
|
|
247
462
|
|
|
@@ -369,13 +584,14 @@ var $03bb5e0d0325c534$var$__generator = undefined && undefined.__generator || fu
|
|
|
369
584
|
}), g;
|
|
370
585
|
};
|
|
371
586
|
var $03bb5e0d0325c534$export$f76c463fe9cb9f15 = function() {
|
|
372
|
-
function $03bb5e0d0325c534$export$f76c463fe9cb9f15(eventsinkUrl, debug) {
|
|
587
|
+
function $03bb5e0d0325c534$export$f76c463fe9cb9f15(eventsinkUrl, debug, onError) {
|
|
373
588
|
this.debug = false;
|
|
374
|
-
this.debug = debug;
|
|
589
|
+
this.debug = debug !== null && debug !== void 0 ? debug : false;
|
|
375
590
|
this.eventsinkUrl = eventsinkUrl;
|
|
591
|
+
this.onError = onError;
|
|
376
592
|
}
|
|
377
593
|
$03bb5e0d0325c534$export$f76c463fe9cb9f15.prototype.initiateAnalyticsReporter = function(_a) {
|
|
378
|
-
var sessionId = _a.sessionId, _b = _a.heartbeatInterval, heartbeatInterval = _b === void 0 ? $76abaee2435acae3$export$31c453b5fe09788d : _b;
|
|
594
|
+
var sessionId = _a.sessionId, shardId = _a.shardId, _b = _a.heartbeatInterval, heartbeatInterval = _b === void 0 ? $76abaee2435acae3$export$31c453b5fe09788d : _b;
|
|
379
595
|
return $03bb5e0d0325c534$var$__awaiter(this, void 0, void 0, function() {
|
|
380
596
|
var _c, generatedSessionId, isInitiated;
|
|
381
597
|
return $03bb5e0d0325c534$var$__generator(this, function(_d) {
|
|
@@ -385,7 +601,9 @@ var $03bb5e0d0325c534$export$f76c463fe9cb9f15 = function() {
|
|
|
385
601
|
sessionId: sessionId,
|
|
386
602
|
eventsinkUrl: this.eventsinkUrl,
|
|
387
603
|
debug: this.debug,
|
|
388
|
-
heartbeatInterval: heartbeatInterval
|
|
604
|
+
heartbeatInterval: heartbeatInterval,
|
|
605
|
+
shardId: shardId,
|
|
606
|
+
onError: this.onError
|
|
389
607
|
});
|
|
390
608
|
return [
|
|
391
609
|
4 /*yield*/ ,
|
|
@@ -405,52 +623,87 @@ var $03bb5e0d0325c534$export$f76c463fe9cb9f15 = function() {
|
|
|
405
623
|
});
|
|
406
624
|
});
|
|
407
625
|
};
|
|
626
|
+
$03bb5e0d0325c534$export$f76c463fe9cb9f15.prototype.ensureReporter = function() {
|
|
627
|
+
if (!this.analyticsReporter) {
|
|
628
|
+
console.warn("[PlayerAnalytics] Not initialized. Call initiateAnalyticsReporter() first.");
|
|
629
|
+
return false;
|
|
630
|
+
}
|
|
631
|
+
return true;
|
|
632
|
+
};
|
|
408
633
|
$03bb5e0d0325c534$export$f76c463fe9cb9f15.prototype.init = function(data) {
|
|
634
|
+
if (!this.ensureReporter()) return;
|
|
409
635
|
this.analyticsReporter.send(data);
|
|
410
636
|
};
|
|
411
637
|
$03bb5e0d0325c534$export$f76c463fe9cb9f15.prototype.metadata = function(data) {
|
|
638
|
+
if (!this.ensureReporter()) return;
|
|
412
639
|
this.analyticsReporter.send(data);
|
|
413
640
|
};
|
|
414
641
|
$03bb5e0d0325c534$export$f76c463fe9cb9f15.prototype.heartbeat = function(data) {
|
|
642
|
+
if (!this.ensureReporter()) return;
|
|
415
643
|
this.analyticsReporter.send(data);
|
|
416
644
|
};
|
|
417
645
|
$03bb5e0d0325c534$export$f76c463fe9cb9f15.prototype.loading = function(data) {
|
|
646
|
+
if (!this.ensureReporter()) return;
|
|
418
647
|
this.analyticsReporter.send(data);
|
|
419
648
|
};
|
|
420
649
|
$03bb5e0d0325c534$export$f76c463fe9cb9f15.prototype.loaded = function(data) {
|
|
650
|
+
if (!this.ensureReporter()) return;
|
|
421
651
|
this.analyticsReporter.send(data);
|
|
422
652
|
};
|
|
423
653
|
$03bb5e0d0325c534$export$f76c463fe9cb9f15.prototype.playing = function(data) {
|
|
654
|
+
if (!this.ensureReporter()) return;
|
|
424
655
|
this.analyticsReporter.send(data);
|
|
425
656
|
};
|
|
426
657
|
$03bb5e0d0325c534$export$f76c463fe9cb9f15.prototype.pause = function(data) {
|
|
658
|
+
if (!this.ensureReporter()) return;
|
|
427
659
|
this.analyticsReporter.send(data);
|
|
428
660
|
};
|
|
429
661
|
$03bb5e0d0325c534$export$f76c463fe9cb9f15.prototype.buffering = function(data) {
|
|
662
|
+
if (!this.ensureReporter()) return;
|
|
430
663
|
this.analyticsReporter.send(data);
|
|
431
664
|
};
|
|
432
665
|
$03bb5e0d0325c534$export$f76c463fe9cb9f15.prototype.buffered = function(data) {
|
|
666
|
+
if (!this.ensureReporter()) return;
|
|
433
667
|
this.analyticsReporter.send(data);
|
|
434
668
|
};
|
|
435
669
|
$03bb5e0d0325c534$export$f76c463fe9cb9f15.prototype.seeking = function(data) {
|
|
670
|
+
if (!this.ensureReporter()) return;
|
|
436
671
|
this.analyticsReporter.send(data);
|
|
437
672
|
};
|
|
438
673
|
$03bb5e0d0325c534$export$f76c463fe9cb9f15.prototype.seeked = function(data) {
|
|
674
|
+
if (!this.ensureReporter()) return;
|
|
439
675
|
this.analyticsReporter.send(data);
|
|
440
676
|
};
|
|
441
677
|
$03bb5e0d0325c534$export$f76c463fe9cb9f15.prototype.bitrateChanged = function(data) {
|
|
678
|
+
if (!this.ensureReporter()) return;
|
|
442
679
|
this.analyticsReporter.send(data);
|
|
443
680
|
};
|
|
444
681
|
$03bb5e0d0325c534$export$f76c463fe9cb9f15.prototype.error = function(data) {
|
|
682
|
+
if (!this.ensureReporter()) return;
|
|
445
683
|
this.analyticsReporter.send(data);
|
|
446
684
|
};
|
|
447
685
|
$03bb5e0d0325c534$export$f76c463fe9cb9f15.prototype.warning = function(data) {
|
|
686
|
+
if (!this.ensureReporter()) return;
|
|
448
687
|
this.analyticsReporter.send(data);
|
|
449
688
|
};
|
|
450
689
|
$03bb5e0d0325c534$export$f76c463fe9cb9f15.prototype.stopped = function(data) {
|
|
690
|
+
if (!this.ensureReporter()) return;
|
|
451
691
|
this.analyticsReporter.send(data);
|
|
452
692
|
};
|
|
693
|
+
/**
|
|
694
|
+
* Send a stopped event over the reporter's unload-safe beacon transport
|
|
695
|
+
* (navigator.sendBeacon with a fetch keepalive fallback). Used to deliver the
|
|
696
|
+
* stopped event when the page is closed or reloaded mid-playback, where a
|
|
697
|
+
* normal CORS fetch would be dropped during unload. Returns true when the
|
|
698
|
+
* event was handed off to a transport.
|
|
699
|
+
*/ $03bb5e0d0325c534$export$f76c463fe9cb9f15.prototype.stoppedViaBeacon = function(data) {
|
|
700
|
+
if (!this.ensureReporter()) return false;
|
|
701
|
+
return this.analyticsReporter.sendBeacon(data);
|
|
702
|
+
};
|
|
453
703
|
$03bb5e0d0325c534$export$f76c463fe9cb9f15.prototype.destroy = function() {
|
|
704
|
+
// Cascade destroy to the reporter so any in-flight init is aborted
|
|
705
|
+
// and queued events are discarded rather than flushed.
|
|
706
|
+
if (this.analyticsReporter) this.analyticsReporter.destroy();
|
|
454
707
|
this.analyticsReporter = null;
|
|
455
708
|
};
|
|
456
709
|
return $03bb5e0d0325c534$export$f76c463fe9cb9f15;
|
|
@@ -595,32 +848,83 @@ var $85819f9bdebfd936$var$__generator = undefined && undefined.__generator || fu
|
|
|
595
848
|
}), g;
|
|
596
849
|
};
|
|
597
850
|
var $85819f9bdebfd936$export$2daf9923c014a26e = function() {
|
|
598
|
-
function $85819f9bdebfd936$export$2daf9923c014a26e(eventsinkUrl, debug) {
|
|
851
|
+
function $85819f9bdebfd936$export$2daf9923c014a26e(eventsinkUrl, debug, onError) {
|
|
852
|
+
var _this = this;
|
|
599
853
|
this.analyticsInitiated = false;
|
|
854
|
+
this.initCalled = false;
|
|
855
|
+
this.initGeneration = 0;
|
|
856
|
+
// Direct DOM fallback for terminal/seek events on an element that was already
|
|
857
|
+
// playing when load() ran (autoplay started during a slow init() handshake).
|
|
858
|
+
// The media-event-filter attaches in its "loading" state and, never having
|
|
859
|
+
// observed the initial playing/canplaythrough transitions, stays stuck there
|
|
860
|
+
// and suppresses ENDED/SEEKING/SEEKED. These listeners drive that path
|
|
861
|
+
// directly. They self-disable the moment the filter proves it is live (emits
|
|
862
|
+
// any event), so a seek is never reported twice across the two sources.
|
|
863
|
+
this.autoplayFallbackActive = false;
|
|
864
|
+
this.pendingHeartbeatStart = false;
|
|
865
|
+
// Tracks whether a stopped event has already been reported for the current
|
|
866
|
+
// session, so the page-unload path does not emit a duplicate after an
|
|
867
|
+
// `ended`, reportStop(), or reportError() has already stopped the session.
|
|
868
|
+
this.stoppedReported = false;
|
|
869
|
+
this.unloadListenersRegistered = false;
|
|
870
|
+
this.handleAutoplayEnded = function() {
|
|
871
|
+
// Mirror the filter's ENDED branch: exactly one stopped(ended), stop
|
|
872
|
+
// heartbeats, and respect the stoppedReported guard so reportStop/
|
|
873
|
+
// reportError/unload can't produce a duplicate.
|
|
874
|
+
if (_this.stoppedReported) return;
|
|
875
|
+
_this.stoppedReported = true;
|
|
876
|
+
_this.stopInterval();
|
|
877
|
+
_this.sendFilteredEvent("stopped", {
|
|
878
|
+
reason: "ended"
|
|
879
|
+
});
|
|
880
|
+
};
|
|
881
|
+
this.handleAutoplaySeeking = function() {
|
|
882
|
+
_this.sendFilteredEvent("seeking");
|
|
883
|
+
};
|
|
884
|
+
this.handleAutoplaySeeked = function() {
|
|
885
|
+
_this.sendFilteredEvent("seeked");
|
|
886
|
+
};
|
|
887
|
+
this.handlePageHide = function() {
|
|
888
|
+
_this.flushStoppedOnUnload();
|
|
889
|
+
};
|
|
600
890
|
this.eventsinkUrl = eventsinkUrl;
|
|
601
|
-
this.playerAnalytics = new $03bb5e0d0325c534$exports.PlayerAnalytics(this.eventsinkUrl, debug);
|
|
891
|
+
this.playerAnalytics = new $03bb5e0d0325c534$exports.PlayerAnalytics(this.eventsinkUrl, debug, onError);
|
|
602
892
|
}
|
|
603
893
|
$85819f9bdebfd936$export$2daf9923c014a26e.prototype.init = function(options) {
|
|
604
894
|
return $85819f9bdebfd936$var$__awaiter(this, void 0, void 0, function() {
|
|
605
|
-
var
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
895
|
+
var currentGeneration, initPromise;
|
|
896
|
+
var _this = this;
|
|
897
|
+
return $85819f9bdebfd936$var$__generator(this, function(_a) {
|
|
898
|
+
this.sessionId = options.sessionId;
|
|
899
|
+
this.initCalled = true;
|
|
900
|
+
this.stoppedReported = false;
|
|
901
|
+
currentGeneration = ++this.initGeneration;
|
|
902
|
+
initPromise = this.playerAnalytics.initiateAnalyticsReporter($85819f9bdebfd936$var$__assign($85819f9bdebfd936$var$__assign({
|
|
903
|
+
}, options), {
|
|
904
|
+
sessionId: this.sessionId
|
|
905
|
+
}));
|
|
906
|
+
initPromise.then(function(result) {
|
|
907
|
+
// Ignore stale init completions (e.g., if destroy() was called during init)
|
|
908
|
+
if (currentGeneration !== _this.initGeneration) return;
|
|
909
|
+
_this.analyticsInitiated = result.isInitiated === true;
|
|
910
|
+
_this.heartbeatInterval = Number(result.heartbeatInterval) || _this.heartbeatInterval;
|
|
911
|
+
if (typeof result.sessionId === "string" && result.sessionId) _this.sessionId = result.sessionId;
|
|
912
|
+
if (_this.pendingHeartbeatStart) {
|
|
913
|
+
_this.pendingHeartbeatStart = false;
|
|
914
|
+
_this.startInterval();
|
|
915
|
+
}
|
|
916
|
+
}).catch(function(err) {
|
|
917
|
+
if (currentGeneration !== _this.initGeneration) return;
|
|
918
|
+
// Reset pendingHeartbeatStart so a retry doesn't fire heartbeats
|
|
919
|
+
// from a stale flag without a new PLAYING event.
|
|
920
|
+
_this.pendingHeartbeatStart = false;
|
|
921
|
+
var message = err instanceof Error ? err.message : String(err);
|
|
922
|
+
console.warn("[PlayerAnalyticsConnector] Init failed:", message);
|
|
923
|
+
});
|
|
924
|
+
return [
|
|
925
|
+
2 /*return*/ ,
|
|
926
|
+
initPromise
|
|
927
|
+
];
|
|
624
928
|
});
|
|
625
929
|
});
|
|
626
930
|
};
|
|
@@ -630,6 +934,30 @@ var $85819f9bdebfd936$export$2daf9923c014a26e = function() {
|
|
|
630
934
|
event: "loading"
|
|
631
935
|
}, this.playbackState()));
|
|
632
936
|
this.initiateVideoEventFilter();
|
|
937
|
+
this.registerUnloadListeners();
|
|
938
|
+
// If the element is already playing by the time load() is called (e.g.
|
|
939
|
+
// autoplay started during a slow init() handshake, before listeners were
|
|
940
|
+
// attached), the media-event-filter won't emit a fresh PLAYING for the
|
|
941
|
+
// DOM "playing" event that already fired. Emit it ourselves and start the
|
|
942
|
+
// heartbeat so the session isn't lost. While init() is still in-flight the
|
|
943
|
+
// event is queued by the Reporter and the heartbeat start is deferred via
|
|
944
|
+
// pendingHeartbeatStart, flushing once the handshake completes.
|
|
945
|
+
if (this.isPlayerAlreadyPlaying()) {
|
|
946
|
+
this.playerAnalytics.playing($85819f9bdebfd936$var$__assign({
|
|
947
|
+
event: "playing"
|
|
948
|
+
}, this.playbackState()));
|
|
949
|
+
this.startInterval();
|
|
950
|
+
// The filter won't emit terminal/seek events for this already-playing
|
|
951
|
+
// element (see isPlayerAlreadyPlaying / initiateVideoEventFilter notes),
|
|
952
|
+
// so drive ended/seeking/seeked from the element's own DOM events.
|
|
953
|
+
this.attachAutoplayTerminalFallback();
|
|
954
|
+
}
|
|
955
|
+
};
|
|
956
|
+
$85819f9bdebfd936$export$2daf9923c014a26e.prototype.isPlayerAlreadyPlaying = function() {
|
|
957
|
+
// HAVE_FUTURE_DATA (readyState 3) mirrors the media-event-filter's own
|
|
958
|
+
// "ready" threshold. Use the numeric literal rather than
|
|
959
|
+
// HTMLMediaElement.HAVE_FUTURE_DATA so this works in non-DOM test envs.
|
|
960
|
+
return !!(this.player && !this.player.paused && !this.player.ended && this.player.readyState >= 3);
|
|
633
961
|
};
|
|
634
962
|
$85819f9bdebfd936$export$2daf9923c014a26e.prototype.initiateVideoEventFilter = function() {
|
|
635
963
|
var _this = this;
|
|
@@ -638,6 +966,11 @@ var $85819f9bdebfd936$export$2daf9923c014a26e = function() {
|
|
|
638
966
|
mediaElement: this.player,
|
|
639
967
|
mp4Mode: false,
|
|
640
968
|
callback: function(event) {
|
|
969
|
+
// The filter emitting anything means it has left its initial "loading"
|
|
970
|
+
// state and is now the authoritative source for terminal/seek events;
|
|
971
|
+
// retire the autoplay DOM fallback so a single seek/ended is not
|
|
972
|
+
// reported twice.
|
|
973
|
+
_this.detachAutoplayTerminalFallback();
|
|
641
974
|
var eventType;
|
|
642
975
|
var extraData = {
|
|
643
976
|
};
|
|
@@ -665,32 +998,65 @@ var $85819f9bdebfd936$export$2daf9923c014a26e = function() {
|
|
|
665
998
|
eventType = "buffered";
|
|
666
999
|
break;
|
|
667
1000
|
case $hCgyA$FilteredMediaEvent.ENDED:
|
|
1001
|
+
// Guard against a duplicate stopped(ended) if the autoplay fallback
|
|
1002
|
+
// (or reportStop/reportError) already ended the session.
|
|
1003
|
+
if (_this.stoppedReported) return;
|
|
668
1004
|
eventType = "stopped";
|
|
669
1005
|
extraData["reason"] = "ended";
|
|
1006
|
+
_this.stoppedReported = true;
|
|
670
1007
|
_this.stopInterval();
|
|
671
1008
|
break;
|
|
672
1009
|
default:
|
|
673
1010
|
break;
|
|
674
1011
|
}
|
|
675
|
-
|
|
676
|
-
if (!_this.analyticsInitiated) {
|
|
677
|
-
console.warn("[PlayerAnalyticsConnector] Analytics not initiated");
|
|
678
|
-
return;
|
|
679
|
-
}
|
|
680
|
-
if (eventType) _this.playerAnalytics[eventType == "paused" ? "pause" : eventType]($85819f9bdebfd936$var$__assign($85819f9bdebfd936$var$__assign({
|
|
681
|
-
event: eventType
|
|
682
|
-
}, _this.playbackState()), Object.keys(extraData).length > 0 && {
|
|
683
|
-
payload: extraData
|
|
684
|
-
}));
|
|
685
|
-
} catch (err) {
|
|
686
|
-
console.error(err);
|
|
687
|
-
}
|
|
1012
|
+
_this.sendFilteredEvent(eventType, extraData);
|
|
688
1013
|
}
|
|
689
1014
|
});
|
|
690
1015
|
};
|
|
1016
|
+
// Shared emit path for events sourced from the media-event-filter and from
|
|
1017
|
+
// the autoplay DOM fallback, so both behave identically (init guard, the
|
|
1018
|
+
// paused→pause method-name mapping, optional payload, error swallowing).
|
|
1019
|
+
$85819f9bdebfd936$export$2daf9923c014a26e.prototype.sendFilteredEvent = function(eventType, extraData) {
|
|
1020
|
+
if (extraData === void 0) extraData = {
|
|
1021
|
+
};
|
|
1022
|
+
try {
|
|
1023
|
+
if (!this.initCalled) {
|
|
1024
|
+
console.warn("[PlayerAnalyticsConnector] Analytics not initiated");
|
|
1025
|
+
return;
|
|
1026
|
+
}
|
|
1027
|
+
if (eventType) this.playerAnalytics[eventType == "paused" ? "pause" : eventType]($85819f9bdebfd936$var$__assign($85819f9bdebfd936$var$__assign({
|
|
1028
|
+
event: eventType
|
|
1029
|
+
}, this.playbackState()), Object.keys(extraData).length > 0 && {
|
|
1030
|
+
payload: extraData
|
|
1031
|
+
}));
|
|
1032
|
+
} catch (err) {
|
|
1033
|
+
console.error(err);
|
|
1034
|
+
}
|
|
1035
|
+
};
|
|
1036
|
+
$85819f9bdebfd936$export$2daf9923c014a26e.prototype.attachAutoplayTerminalFallback = function() {
|
|
1037
|
+
if (this.autoplayFallbackActive) return;
|
|
1038
|
+
if (!this.player || typeof this.player.addEventListener !== "function") return;
|
|
1039
|
+
this.autoplayFallbackActive = true;
|
|
1040
|
+
this.player.addEventListener("ended", this.handleAutoplayEnded);
|
|
1041
|
+
this.player.addEventListener("seeking", this.handleAutoplaySeeking);
|
|
1042
|
+
this.player.addEventListener("seeked", this.handleAutoplaySeeked);
|
|
1043
|
+
};
|
|
1044
|
+
$85819f9bdebfd936$export$2daf9923c014a26e.prototype.detachAutoplayTerminalFallback = function() {
|
|
1045
|
+
if (!this.autoplayFallbackActive) return;
|
|
1046
|
+
this.autoplayFallbackActive = false;
|
|
1047
|
+
if (this.player && typeof this.player.removeEventListener === "function") {
|
|
1048
|
+
this.player.removeEventListener("ended", this.handleAutoplayEnded);
|
|
1049
|
+
this.player.removeEventListener("seeking", this.handleAutoplaySeeking);
|
|
1050
|
+
this.player.removeEventListener("seeked", this.handleAutoplaySeeked);
|
|
1051
|
+
}
|
|
1052
|
+
};
|
|
691
1053
|
$85819f9bdebfd936$export$2daf9923c014a26e.prototype.startInterval = function() {
|
|
692
1054
|
var _this = this;
|
|
693
1055
|
if (this.heartbeatIntervalTimer) return;
|
|
1056
|
+
if (!this.heartbeatInterval) {
|
|
1057
|
+
this.pendingHeartbeatStart = true;
|
|
1058
|
+
return;
|
|
1059
|
+
}
|
|
694
1060
|
this.heartbeatIntervalTimer = setInterval(function() {
|
|
695
1061
|
_this.playerAnalytics.heartbeat($85819f9bdebfd936$var$__assign({
|
|
696
1062
|
event: "heartbeat"
|
|
@@ -699,9 +1065,11 @@ var $85819f9bdebfd936$export$2daf9923c014a26e = function() {
|
|
|
699
1065
|
};
|
|
700
1066
|
$85819f9bdebfd936$export$2daf9923c014a26e.prototype.stopInterval = function() {
|
|
701
1067
|
clearInterval(this.heartbeatIntervalTimer);
|
|
1068
|
+
this.heartbeatIntervalTimer = null;
|
|
1069
|
+
this.pendingHeartbeatStart = false;
|
|
702
1070
|
};
|
|
703
1071
|
$85819f9bdebfd936$export$2daf9923c014a26e.prototype.reportBitrateChange = function(payload) {
|
|
704
|
-
if (!this.
|
|
1072
|
+
if (!this.initCalled) {
|
|
705
1073
|
console.warn("[PlayerAnalyticsConnector] Analytics not initiated");
|
|
706
1074
|
return;
|
|
707
1075
|
}
|
|
@@ -712,21 +1080,32 @@ var $85819f9bdebfd936$export$2daf9923c014a26e = function() {
|
|
|
712
1080
|
}));
|
|
713
1081
|
};
|
|
714
1082
|
$85819f9bdebfd936$export$2daf9923c014a26e.prototype.reportStop = function() {
|
|
715
|
-
if (!this.
|
|
1083
|
+
if (!this.initCalled) {
|
|
716
1084
|
console.warn("[PlayerAnalyticsConnector] Analytics not initiated");
|
|
717
1085
|
return;
|
|
718
1086
|
}
|
|
719
|
-
this
|
|
1087
|
+
// Already stopped this session (an `ended`, reportError(), or a prior
|
|
1088
|
+
// unload beacon) — don't emit a duplicate stopped.
|
|
1089
|
+
if (this.stoppedReported) return;
|
|
1090
|
+
this.stoppedReported = true;
|
|
1091
|
+
this.stopInterval();
|
|
1092
|
+
// Deliver over the unload-safe beacon transport (sendBeacon / keepalive
|
|
1093
|
+
// fetch), not the normal CORS fetch. Integrators call reportStop() from
|
|
1094
|
+
// pagehide/unload handlers, where the browser drops the preflighted CORS
|
|
1095
|
+
// fetch and the event is lost. Routing through the same beacon the SDK's
|
|
1096
|
+
// own unload path uses means setting `stoppedReported` here lets
|
|
1097
|
+
// flushStoppedOnUnload() short-circuit without losing the event, so
|
|
1098
|
+
// exactly one stopped is delivered.
|
|
1099
|
+
this.playerAnalytics.stoppedViaBeacon($85819f9bdebfd936$var$__assign($85819f9bdebfd936$var$__assign({
|
|
720
1100
|
event: "stopped"
|
|
721
1101
|
}, this.playbackState()), {
|
|
722
1102
|
payload: {
|
|
723
1103
|
reason: "aborted"
|
|
724
1104
|
}
|
|
725
1105
|
}));
|
|
726
|
-
this.stopInterval();
|
|
727
1106
|
};
|
|
728
1107
|
$85819f9bdebfd936$export$2daf9923c014a26e.prototype.reportError = function(error) {
|
|
729
|
-
if (!this.
|
|
1108
|
+
if (!this.initCalled) {
|
|
730
1109
|
console.warn("[PlayerAnalyticsConnector] Analytics not initiated");
|
|
731
1110
|
return;
|
|
732
1111
|
}
|
|
@@ -742,10 +1121,11 @@ var $85819f9bdebfd936$export$2daf9923c014a26e = function() {
|
|
|
742
1121
|
reason: "error"
|
|
743
1122
|
}
|
|
744
1123
|
}));
|
|
1124
|
+
this.stoppedReported = true;
|
|
745
1125
|
this.stopInterval();
|
|
746
1126
|
};
|
|
747
1127
|
$85819f9bdebfd936$export$2daf9923c014a26e.prototype.reportMetadata = function(payload) {
|
|
748
|
-
if (!this.
|
|
1128
|
+
if (!this.initCalled) {
|
|
749
1129
|
console.warn("[PlayerAnalyticsConnector] Analytics not initiated");
|
|
750
1130
|
return;
|
|
751
1131
|
}
|
|
@@ -756,7 +1136,7 @@ var $85819f9bdebfd936$export$2daf9923c014a26e = function() {
|
|
|
756
1136
|
}));
|
|
757
1137
|
};
|
|
758
1138
|
$85819f9bdebfd936$export$2daf9923c014a26e.prototype.reportWarning = function(payload) {
|
|
759
|
-
if (!this.
|
|
1139
|
+
if (!this.initCalled) {
|
|
760
1140
|
console.warn("[PlayerAnalyticsConnector] Analytics not initiated");
|
|
761
1141
|
return;
|
|
762
1142
|
}
|
|
@@ -769,7 +1149,7 @@ var $85819f9bdebfd936$export$2daf9923c014a26e = function() {
|
|
|
769
1149
|
$85819f9bdebfd936$export$2daf9923c014a26e.prototype.playbackState = function() {
|
|
770
1150
|
var _a, _b, _c, _d, _e;
|
|
771
1151
|
var duration = ((_a = this.player) === null || _a === void 0 ? void 0 : _a.duration) && ((_b = this.player) === null || _b === void 0 ? void 0 : _b.duration) !== Infinity && ((_c = this.player) === null || _c === void 0 ? void 0 : _c.duration) > 0 ? this.player.duration : -1;
|
|
772
|
-
var playhead = ((_d = this.player) === null || _d === void 0 ? void 0 : _d.currentTime) &&
|
|
1152
|
+
var playhead = ((_d = this.player) === null || _d === void 0 ? void 0 : _d.currentTime) != null && this.player.currentTime >= 0 ? (_e = this.player) === null || _e === void 0 ? void 0 : _e.currentTime : -1;
|
|
773
1153
|
return {
|
|
774
1154
|
sessionId: this.sessionId,
|
|
775
1155
|
timestamp: Date.now(),
|
|
@@ -777,25 +1157,73 @@ var $85819f9bdebfd936$export$2daf9923c014a26e = function() {
|
|
|
777
1157
|
duration: duration
|
|
778
1158
|
};
|
|
779
1159
|
};
|
|
1160
|
+
/**
|
|
1161
|
+
* Deliver a stopped event when the page is being unloaded (tab closed or
|
|
1162
|
+
* reloaded) mid-session. Driven by `pagehide`, which fires on genuine
|
|
1163
|
+
* discard (close/reload/navigate-away) but NOT on an ordinary tab switch —
|
|
1164
|
+
* the browser drops the normal CORS fetch (it needs a preflight) during
|
|
1165
|
+
* unload, losing the event, so the stopped event goes out over the
|
|
1166
|
+
* reporter's beacon transport instead. It is sent only once per session (a
|
|
1167
|
+
* later `ended`, reportStop(), or reportError() will already have reported
|
|
1168
|
+
* stopped). `visibilitychange→hidden` is deliberately NOT used here: a tab
|
|
1169
|
+
* switch / backgrounding is not an unload and must not end a still-playing
|
|
1170
|
+
* session (see #44).
|
|
1171
|
+
*/ $85819f9bdebfd936$export$2daf9923c014a26e.prototype.flushStoppedOnUnload = function() {
|
|
1172
|
+
if (!this.initCalled || this.stoppedReported || !this.player) return;
|
|
1173
|
+
this.stoppedReported = true;
|
|
1174
|
+
this.stopInterval();
|
|
1175
|
+
this.playerAnalytics.stoppedViaBeacon($85819f9bdebfd936$var$__assign($85819f9bdebfd936$var$__assign({
|
|
1176
|
+
event: "stopped"
|
|
1177
|
+
}, this.playbackState()), {
|
|
1178
|
+
payload: {
|
|
1179
|
+
reason: "aborted"
|
|
1180
|
+
}
|
|
1181
|
+
}));
|
|
1182
|
+
};
|
|
1183
|
+
$85819f9bdebfd936$export$2daf9923c014a26e.prototype.registerUnloadListeners = function() {
|
|
1184
|
+
if (this.unloadListenersRegistered) return;
|
|
1185
|
+
if (typeof window !== "undefined" && typeof window.addEventListener === "function") window.addEventListener("pagehide", this.handlePageHide);
|
|
1186
|
+
this.unloadListenersRegistered = true;
|
|
1187
|
+
};
|
|
1188
|
+
$85819f9bdebfd936$export$2daf9923c014a26e.prototype.removeUnloadListeners = function() {
|
|
1189
|
+
if (!this.unloadListenersRegistered) return;
|
|
1190
|
+
if (typeof window !== "undefined" && typeof window.removeEventListener === "function") window.removeEventListener("pagehide", this.handlePageHide);
|
|
1191
|
+
this.unloadListenersRegistered = false;
|
|
1192
|
+
};
|
|
780
1193
|
$85819f9bdebfd936$export$2daf9923c014a26e.prototype.deinit = function() {
|
|
781
|
-
if (!this.
|
|
1194
|
+
if (!this.initCalled) {
|
|
782
1195
|
console.warn("[PlayerAnalyticsConnector] Analytics not initiated");
|
|
783
1196
|
return;
|
|
784
1197
|
}
|
|
1198
|
+
this.initGeneration++; // Invalidate any pending init callbacks
|
|
1199
|
+
// Abort any in-flight init so queued events don't flush after teardown.
|
|
1200
|
+
// The next init() call creates a fresh Reporter, so destroying the
|
|
1201
|
+
// current one is safe even though deinit is meant to be reusable.
|
|
1202
|
+
this.playerAnalytics.destroy();
|
|
785
1203
|
this.stopInterval();
|
|
1204
|
+
this.removeUnloadListeners();
|
|
1205
|
+
this.detachAutoplayTerminalFallback();
|
|
786
1206
|
this.heartbeatInterval = null;
|
|
787
1207
|
this.videoEventFilter && this.videoEventFilter.teardown();
|
|
788
1208
|
this.videoEventFilter = null;
|
|
1209
|
+
this.analyticsInitiated = false;
|
|
1210
|
+
this.initCalled = false;
|
|
789
1211
|
};
|
|
790
1212
|
$85819f9bdebfd936$export$2daf9923c014a26e.prototype.destroy = function() {
|
|
791
|
-
if (!this.
|
|
1213
|
+
if (!this.initCalled) {
|
|
792
1214
|
console.warn("[PlayerAnalyticsConnector] Analytics not initiated");
|
|
793
1215
|
return;
|
|
794
1216
|
}
|
|
1217
|
+
this.initGeneration++; // Invalidate any pending init callbacks
|
|
1218
|
+
this.stopInterval();
|
|
795
1219
|
this.playerAnalytics.destroy();
|
|
1220
|
+
this.removeUnloadListeners();
|
|
1221
|
+
this.detachAutoplayTerminalFallback();
|
|
796
1222
|
this.heartbeatInterval = null;
|
|
797
1223
|
this.videoEventFilter && this.videoEventFilter.teardown();
|
|
798
|
-
this.
|
|
1224
|
+
this.videoEventFilter = null;
|
|
1225
|
+
this.analyticsInitiated = false;
|
|
1226
|
+
this.initCalled = false;
|
|
799
1227
|
};
|
|
800
1228
|
return $85819f9bdebfd936$export$2daf9923c014a26e;
|
|
801
1229
|
}();
|