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