@edm-webplayer/webplayer-angular 0.2.5 → 0.2.7
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.
|
@@ -84,11 +84,10 @@ class PlyrPlayerComponent {
|
|
|
84
84
|
menuObserver;
|
|
85
85
|
playbackEnded = false;
|
|
86
86
|
overlayBlockAll = false;
|
|
87
|
-
endedPosterOverlay;
|
|
88
|
-
interactionUnmuteCleanup;
|
|
89
|
-
endedLoggedOnPause = false;
|
|
90
87
|
liveInteractionBlocker;
|
|
91
|
-
|
|
88
|
+
controlsSafeZonePxDesktop = 96;
|
|
89
|
+
controlsSafeZonePxTouch = 144;
|
|
90
|
+
overlayInteractionGapPx = 20;
|
|
92
91
|
onResize = () => {
|
|
93
92
|
this.updateRecommendationBlockerSafeZone();
|
|
94
93
|
};
|
|
@@ -124,9 +123,6 @@ class PlyrPlayerComponent {
|
|
|
124
123
|
}
|
|
125
124
|
catch { }
|
|
126
125
|
};
|
|
127
|
-
controlsSafeZonePxDesktop = 96;
|
|
128
|
-
controlsSafeZonePxTouch = 144;
|
|
129
|
-
overlayInteractionGapPx = 20;
|
|
130
126
|
constructor(progressService, document) {
|
|
131
127
|
this.progressService = progressService;
|
|
132
128
|
this.document = document;
|
|
@@ -137,29 +133,22 @@ class PlyrPlayerComponent {
|
|
|
137
133
|
this.applyTheme(this.config.ui.colors);
|
|
138
134
|
}
|
|
139
135
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
145
|
-
const tolerance = 0.35;
|
|
146
|
-
if (Math.abs(pending.value - target) > tolerance) {
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
const callbacks = pending.queue.slice();
|
|
150
|
-
pending.queue.length = 0;
|
|
151
|
-
if (success) {
|
|
152
|
-
this.pendingStartTime = undefined;
|
|
136
|
+
isTouchDevice() {
|
|
137
|
+
if (typeof window === "undefined") {
|
|
138
|
+
return false;
|
|
153
139
|
}
|
|
154
|
-
|
|
155
|
-
|
|
140
|
+
if (typeof navigator !== "undefined" && navigator.maxTouchPoints > 0) {
|
|
141
|
+
return true;
|
|
156
142
|
}
|
|
157
|
-
|
|
143
|
+
if (window.matchMedia) {
|
|
158
144
|
try {
|
|
159
|
-
|
|
145
|
+
if (window.matchMedia("(pointer: coarse)").matches) {
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
160
148
|
}
|
|
161
149
|
catch { }
|
|
162
|
-
}
|
|
150
|
+
}
|
|
151
|
+
return "ontouchstart" in window;
|
|
163
152
|
}
|
|
164
153
|
getControlsSafeZone() {
|
|
165
154
|
const controls = (this.plyr?.elements?.controls ??
|
|
@@ -245,45 +234,6 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
245
234
|
}`;
|
|
246
235
|
styleEl.textContent = cssRule;
|
|
247
236
|
}
|
|
248
|
-
normalizeLocaleCandidate(value) {
|
|
249
|
-
if (value === null || value === undefined) {
|
|
250
|
-
return null;
|
|
251
|
-
}
|
|
252
|
-
const candidate = String(value).trim();
|
|
253
|
-
if (!candidate) {
|
|
254
|
-
return null;
|
|
255
|
-
}
|
|
256
|
-
return candidate.replace(/_/g, "-");
|
|
257
|
-
}
|
|
258
|
-
resolveLocale() {
|
|
259
|
-
const candidates = [
|
|
260
|
-
this.config?.video_locale,
|
|
261
|
-
this.config?.video_language,
|
|
262
|
-
this.config?.locale,
|
|
263
|
-
this.config?.language,
|
|
264
|
-
this.config?.content_locale,
|
|
265
|
-
this.config?.content_language,
|
|
266
|
-
];
|
|
267
|
-
for (const candidate of candidates) {
|
|
268
|
-
const normalized = this.normalizeLocaleCandidate(candidate);
|
|
269
|
-
if (normalized) {
|
|
270
|
-
return normalized;
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
return "pt-BR";
|
|
274
|
-
}
|
|
275
|
-
resolveCaptionsLanguage(locale) {
|
|
276
|
-
const explicit = this.normalizeLocaleCandidate(this.config?.captions_locale ??
|
|
277
|
-
this.config?.captions_language ??
|
|
278
|
-
this.config?.subtitle_locale ??
|
|
279
|
-
this.config?.subtitle_language ??
|
|
280
|
-
null);
|
|
281
|
-
const baseLocale = explicit || locale;
|
|
282
|
-
if (!baseLocale)
|
|
283
|
-
return null;
|
|
284
|
-
const code = baseLocale.split("-")[0]?.trim();
|
|
285
|
-
return code ? code.toLowerCase() : null;
|
|
286
|
-
}
|
|
287
237
|
getVideoWrapper() {
|
|
288
238
|
const container = this.plyr?.elements?.container;
|
|
289
239
|
if (!container)
|
|
@@ -404,94 +354,6 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
404
354
|
});
|
|
405
355
|
this.menuObserver = observer;
|
|
406
356
|
}
|
|
407
|
-
isIOSDevice() {
|
|
408
|
-
if (typeof navigator === "undefined")
|
|
409
|
-
return false;
|
|
410
|
-
const ua = navigator.userAgent || "";
|
|
411
|
-
const iOS = /iPad|iPhone|iPod/.test(ua);
|
|
412
|
-
const iPadOS = navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1;
|
|
413
|
-
return iOS || iPadOS;
|
|
414
|
-
}
|
|
415
|
-
isIOSContext() {
|
|
416
|
-
if (this.isIOSDevice()) {
|
|
417
|
-
return true;
|
|
418
|
-
}
|
|
419
|
-
if (typeof window === "undefined") {
|
|
420
|
-
return false;
|
|
421
|
-
}
|
|
422
|
-
try {
|
|
423
|
-
const params = new URLSearchParams(window.location.search);
|
|
424
|
-
const os = params.get("os");
|
|
425
|
-
if (os && os.toLowerCase() === "ios") {
|
|
426
|
-
return true;
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
catch { }
|
|
430
|
-
return false;
|
|
431
|
-
}
|
|
432
|
-
isTouchDevice() {
|
|
433
|
-
if (typeof window === "undefined") {
|
|
434
|
-
return false;
|
|
435
|
-
}
|
|
436
|
-
if (typeof navigator !== "undefined" && navigator.maxTouchPoints > 0) {
|
|
437
|
-
return true;
|
|
438
|
-
}
|
|
439
|
-
if (window.matchMedia) {
|
|
440
|
-
try {
|
|
441
|
-
if (window.matchMedia("(pointer: coarse)").matches) {
|
|
442
|
-
return true;
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
catch { }
|
|
446
|
-
}
|
|
447
|
-
return "ontouchstart" in window;
|
|
448
|
-
}
|
|
449
|
-
isIframeProvider() {
|
|
450
|
-
return this.config?.video_host === "youtube";
|
|
451
|
-
}
|
|
452
|
-
shouldDisableAutoplayForIOS() {
|
|
453
|
-
if (this.config?.is_live) {
|
|
454
|
-
return false;
|
|
455
|
-
}
|
|
456
|
-
return this.isIOSDevice();
|
|
457
|
-
}
|
|
458
|
-
shouldResetProgressToBeginning() {
|
|
459
|
-
const host = this.config?.video_host;
|
|
460
|
-
if (host !== "youtube") {
|
|
461
|
-
return false;
|
|
462
|
-
}
|
|
463
|
-
const seenFlag = this.config?.seen;
|
|
464
|
-
if (seenFlag === true || seenFlag === "true" || seenFlag === 1) {
|
|
465
|
-
return true;
|
|
466
|
-
}
|
|
467
|
-
const rawPercent = this.config?.last_percent;
|
|
468
|
-
if (rawPercent === undefined || rawPercent === null) {
|
|
469
|
-
return false;
|
|
470
|
-
}
|
|
471
|
-
let percent = Number(rawPercent);
|
|
472
|
-
if (!Number.isFinite(percent)) {
|
|
473
|
-
return false;
|
|
474
|
-
}
|
|
475
|
-
if (percent > 1) {
|
|
476
|
-
percent = percent / 100;
|
|
477
|
-
}
|
|
478
|
-
return percent >= 0.8;
|
|
479
|
-
}
|
|
480
|
-
shouldEmitEndedOnPause() {
|
|
481
|
-
if (!this.isIOSContext()) {
|
|
482
|
-
return false;
|
|
483
|
-
}
|
|
484
|
-
if (this.endedLoggedOnPause) {
|
|
485
|
-
return false;
|
|
486
|
-
}
|
|
487
|
-
const duration = this.plyr?.duration;
|
|
488
|
-
if (!Number.isFinite(duration) || !duration || duration <= 0) {
|
|
489
|
-
return false;
|
|
490
|
-
}
|
|
491
|
-
const current = this.plyr?.currentTime || 0;
|
|
492
|
-
const percent = duration > 0 ? current / duration : 0;
|
|
493
|
-
return percent >= 0.8 && duration - current < 1;
|
|
494
|
-
}
|
|
495
357
|
hasReachedEndThreshold() {
|
|
496
358
|
const duration = this.plyr?.duration;
|
|
497
359
|
if (!Number.isFinite(duration) || !duration || duration <= 0) {
|
|
@@ -542,520 +404,6 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
542
404
|
}
|
|
543
405
|
this.liveInteractionBlocker = null;
|
|
544
406
|
}
|
|
545
|
-
wantsAutoplay() {
|
|
546
|
-
return !!(this.config?.autoplay || this.config?.is_live);
|
|
547
|
-
}
|
|
548
|
-
shouldAutoplay() {
|
|
549
|
-
if (this.config?.is_live) {
|
|
550
|
-
return true;
|
|
551
|
-
}
|
|
552
|
-
if (this.shouldDisableAutoplayForIOS()) {
|
|
553
|
-
return false;
|
|
554
|
-
}
|
|
555
|
-
return this.wantsAutoplay();
|
|
556
|
-
}
|
|
557
|
-
requiresMutedAutoplay() {
|
|
558
|
-
if (this.config?.is_live && this.isIOSDevice()) {
|
|
559
|
-
return true;
|
|
560
|
-
}
|
|
561
|
-
if (!this.isIOSDevice() || this.shouldDisableAutoplayForIOS()) {
|
|
562
|
-
return false;
|
|
563
|
-
}
|
|
564
|
-
return this.wantsAutoplay();
|
|
565
|
-
}
|
|
566
|
-
shouldBlockIframeAutoplay() {
|
|
567
|
-
return this.shouldDisableAutoplayForIOS();
|
|
568
|
-
}
|
|
569
|
-
stopRestrictedIframeAutoplay() {
|
|
570
|
-
if (!this.shouldBlockIframeAutoplay()) {
|
|
571
|
-
return;
|
|
572
|
-
}
|
|
573
|
-
this.clearAutoplayUnlockListener();
|
|
574
|
-
this.setPlayerMutedState(false);
|
|
575
|
-
const media = this.videoRef?.nativeElement ?? null;
|
|
576
|
-
if (media) {
|
|
577
|
-
try {
|
|
578
|
-
media.autoplay = false;
|
|
579
|
-
}
|
|
580
|
-
catch { }
|
|
581
|
-
try {
|
|
582
|
-
media.pause();
|
|
583
|
-
}
|
|
584
|
-
catch { }
|
|
585
|
-
try {
|
|
586
|
-
media.muted = false;
|
|
587
|
-
}
|
|
588
|
-
catch { }
|
|
589
|
-
}
|
|
590
|
-
if (this.plyr) {
|
|
591
|
-
try {
|
|
592
|
-
this.plyr.autoplay = false;
|
|
593
|
-
}
|
|
594
|
-
catch { }
|
|
595
|
-
try {
|
|
596
|
-
if (typeof this.plyr.pause === "function") {
|
|
597
|
-
this.plyr.pause();
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
catch { }
|
|
601
|
-
}
|
|
602
|
-
const embed = this.plyr?.embed;
|
|
603
|
-
if (embed) {
|
|
604
|
-
try {
|
|
605
|
-
if (typeof embed.pause === "function") {
|
|
606
|
-
embed.pause();
|
|
607
|
-
}
|
|
608
|
-
if (typeof embed.setMuted === "function") {
|
|
609
|
-
embed.setMuted(false);
|
|
610
|
-
}
|
|
611
|
-
if (typeof embed.setVolume === "function") {
|
|
612
|
-
embed.setVolume(1);
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
catch { }
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
setPlayerMutedState(muted, volume = 1, target) {
|
|
619
|
-
if (this.plyr) {
|
|
620
|
-
try {
|
|
621
|
-
this.plyr.muted = muted;
|
|
622
|
-
}
|
|
623
|
-
catch { }
|
|
624
|
-
if (!muted) {
|
|
625
|
-
try {
|
|
626
|
-
this.plyr.volume = volume;
|
|
627
|
-
}
|
|
628
|
-
catch { }
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
const media = target ?? this.videoRef?.nativeElement ?? null;
|
|
632
|
-
if (media) {
|
|
633
|
-
try {
|
|
634
|
-
media.muted = muted;
|
|
635
|
-
}
|
|
636
|
-
catch { }
|
|
637
|
-
if (!muted && typeof media.volume === "number") {
|
|
638
|
-
try {
|
|
639
|
-
media.volume = volume;
|
|
640
|
-
}
|
|
641
|
-
catch { }
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
temporarilyMuteForSeek(target) {
|
|
646
|
-
const media = target ?? this.videoRef?.nativeElement ?? null;
|
|
647
|
-
const prevVideoMuted = media?.muted ?? false;
|
|
648
|
-
const prevPlyrMuted = !!this.plyr?.muted;
|
|
649
|
-
const shouldForceUnmute = !this.shouldAutoplay();
|
|
650
|
-
try {
|
|
651
|
-
if (media) {
|
|
652
|
-
media.muted = true;
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
catch { }
|
|
656
|
-
try {
|
|
657
|
-
if (this.plyr) {
|
|
658
|
-
this.plyr.muted = true;
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
catch { }
|
|
662
|
-
return () => {
|
|
663
|
-
try {
|
|
664
|
-
if (media) {
|
|
665
|
-
media.muted = prevVideoMuted;
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
catch { }
|
|
669
|
-
try {
|
|
670
|
-
if (this.plyr) {
|
|
671
|
-
this.plyr.muted = prevPlyrMuted;
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
catch { }
|
|
675
|
-
if (shouldForceUnmute) {
|
|
676
|
-
this.setPlayerMutedState(false, 1, media);
|
|
677
|
-
}
|
|
678
|
-
};
|
|
679
|
-
}
|
|
680
|
-
clearAutoplayUnlockListener() {
|
|
681
|
-
if (this.interactionUnmuteCleanup) {
|
|
682
|
-
try {
|
|
683
|
-
this.interactionUnmuteCleanup();
|
|
684
|
-
}
|
|
685
|
-
catch { }
|
|
686
|
-
this.interactionUnmuteCleanup = undefined;
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
ensureAutoplayUnlockListener() {
|
|
690
|
-
if (typeof window === "undefined" ||
|
|
691
|
-
this.interactionUnmuteCleanup ||
|
|
692
|
-
!this.shouldAutoplay()) {
|
|
693
|
-
return;
|
|
694
|
-
}
|
|
695
|
-
const capture = true;
|
|
696
|
-
const handler = () => {
|
|
697
|
-
this.setPlayerMutedState(false);
|
|
698
|
-
try {
|
|
699
|
-
this.plyr?.play();
|
|
700
|
-
}
|
|
701
|
-
catch { }
|
|
702
|
-
this.clearAutoplayUnlockListener();
|
|
703
|
-
};
|
|
704
|
-
window.addEventListener("touchend", handler, capture);
|
|
705
|
-
window.addEventListener("pointerup", handler, capture);
|
|
706
|
-
window.addEventListener("click", handler, capture);
|
|
707
|
-
this.interactionUnmuteCleanup = () => {
|
|
708
|
-
window.removeEventListener("touchend", handler, capture);
|
|
709
|
-
window.removeEventListener("pointerup", handler, capture);
|
|
710
|
-
window.removeEventListener("click", handler, capture);
|
|
711
|
-
this.interactionUnmuteCleanup = undefined;
|
|
712
|
-
};
|
|
713
|
-
}
|
|
714
|
-
ensureIframeAutoplayPermissions() {
|
|
715
|
-
if (!this.isIframeProvider()) {
|
|
716
|
-
return;
|
|
717
|
-
}
|
|
718
|
-
const container = this.plyr?.elements?.container;
|
|
719
|
-
if (!container)
|
|
720
|
-
return;
|
|
721
|
-
const iframe = container.querySelector("iframe") ?? null;
|
|
722
|
-
if (!iframe)
|
|
723
|
-
return;
|
|
724
|
-
const allowRaw = iframe.getAttribute("allow") || "";
|
|
725
|
-
const tokens = new Set(allowRaw
|
|
726
|
-
.split(";")
|
|
727
|
-
.map((token) => token.trim())
|
|
728
|
-
.filter(Boolean));
|
|
729
|
-
[
|
|
730
|
-
"autoplay",
|
|
731
|
-
"fullscreen",
|
|
732
|
-
"encrypted-media",
|
|
733
|
-
"picture-in-picture",
|
|
734
|
-
"gyroscope",
|
|
735
|
-
].forEach((rule) => tokens.add(rule));
|
|
736
|
-
iframe.setAttribute("allow", Array.from(tokens).join("; "));
|
|
737
|
-
if (this.config.video_host === "youtube") {
|
|
738
|
-
iframe.setAttribute("playsinline", "1");
|
|
739
|
-
iframe.setAttribute("webkit-playsinline", "1");
|
|
740
|
-
}
|
|
741
|
-
iframe.setAttribute("allowfullscreen", "true");
|
|
742
|
-
iframe.setAttribute("data-keepplaying", "true");
|
|
743
|
-
}
|
|
744
|
-
scheduleUserInteractionUnmute(video) {
|
|
745
|
-
this.unmuteAfterDelay(video || undefined);
|
|
746
|
-
this.ensureAutoplayUnlockListener();
|
|
747
|
-
}
|
|
748
|
-
requestStartTimeSeek(start, opts = {}) {
|
|
749
|
-
if (!(start > 0)) {
|
|
750
|
-
this.pendingStartTime = undefined;
|
|
751
|
-
return;
|
|
752
|
-
}
|
|
753
|
-
const video = opts.video ?? this.videoRef?.nativeElement ?? null;
|
|
754
|
-
const normalized = Math.max(0, start);
|
|
755
|
-
const tolerance = 0.35;
|
|
756
|
-
const pending = this.pendingStartTime;
|
|
757
|
-
if (pending && Math.abs(pending.value - normalized) <= tolerance) {
|
|
758
|
-
pending.video = video ?? pending.video;
|
|
759
|
-
pending.blockPlayback = true;
|
|
760
|
-
}
|
|
761
|
-
else {
|
|
762
|
-
const carryQueue = this.pendingStartTime?.queue ?? [];
|
|
763
|
-
this.pendingStartTime = {
|
|
764
|
-
value: normalized,
|
|
765
|
-
video,
|
|
766
|
-
queue: carryQueue,
|
|
767
|
-
blockPlayback: true,
|
|
768
|
-
};
|
|
769
|
-
}
|
|
770
|
-
this.applyStartTimeToCurrentSource(normalized, { video });
|
|
771
|
-
}
|
|
772
|
-
deferUntilStartTimeSettles(callback) {
|
|
773
|
-
if (!this.pendingStartTime || !this.pendingStartTime.blockPlayback)
|
|
774
|
-
return false;
|
|
775
|
-
this.pendingStartTime.queue.push(callback);
|
|
776
|
-
return true;
|
|
777
|
-
}
|
|
778
|
-
retryPendingStartTime() {
|
|
779
|
-
if (!this.pendingStartTime) {
|
|
780
|
-
return;
|
|
781
|
-
}
|
|
782
|
-
const { value, video } = this.pendingStartTime;
|
|
783
|
-
this.applyStartTimeToCurrentSource(value, {
|
|
784
|
-
video: video ?? this.videoRef?.nativeElement ?? null,
|
|
785
|
-
attempts: 3,
|
|
786
|
-
delayMs: 150,
|
|
787
|
-
});
|
|
788
|
-
}
|
|
789
|
-
applyStartTimeToCurrentSource(start, opts = {}) {
|
|
790
|
-
if (!this.plyr || !(start > 0)) {
|
|
791
|
-
return;
|
|
792
|
-
}
|
|
793
|
-
const video = opts.video ?? this.videoRef?.nativeElement ?? null;
|
|
794
|
-
let attempts = Math.max(1, opts.attempts ?? 6);
|
|
795
|
-
const delayMs = opts.delayMs ?? 250;
|
|
796
|
-
const tolerance = 0.35;
|
|
797
|
-
const scheduleRetry = () => {
|
|
798
|
-
attempts -= 1;
|
|
799
|
-
if (attempts > 0) {
|
|
800
|
-
setTimeout(trySeek, delayMs);
|
|
801
|
-
return;
|
|
802
|
-
}
|
|
803
|
-
this.flushPendingStartTime(start, false);
|
|
804
|
-
};
|
|
805
|
-
const verifyAfterAttempt = () => {
|
|
806
|
-
const current = this.plyr?.currentTime || 0;
|
|
807
|
-
if (Math.abs(current - start) <= tolerance) {
|
|
808
|
-
attempts = 0;
|
|
809
|
-
this.flushPendingStartTime(start, true);
|
|
810
|
-
return;
|
|
811
|
-
}
|
|
812
|
-
scheduleRetry();
|
|
813
|
-
};
|
|
814
|
-
const trySeek = () => {
|
|
815
|
-
if (!this.plyr)
|
|
816
|
-
return;
|
|
817
|
-
let maybePromise = null;
|
|
818
|
-
try {
|
|
819
|
-
const result = this.seekUsingHostAPI(start, video);
|
|
820
|
-
if (result && typeof result.then === "function") {
|
|
821
|
-
maybePromise = result;
|
|
822
|
-
}
|
|
823
|
-
}
|
|
824
|
-
catch {
|
|
825
|
-
scheduleRetry();
|
|
826
|
-
return;
|
|
827
|
-
}
|
|
828
|
-
if (maybePromise) {
|
|
829
|
-
maybePromise
|
|
830
|
-
.then(() => verifyAfterAttempt())
|
|
831
|
-
.catch(() => scheduleRetry());
|
|
832
|
-
return;
|
|
833
|
-
}
|
|
834
|
-
verifyAfterAttempt();
|
|
835
|
-
};
|
|
836
|
-
trySeek();
|
|
837
|
-
}
|
|
838
|
-
seekUsingHostAPI(target, video) {
|
|
839
|
-
if (!Number.isFinite(target) || target < 0) {
|
|
840
|
-
return null;
|
|
841
|
-
}
|
|
842
|
-
const restoreMute = this.temporarilyMuteForSeek(video);
|
|
843
|
-
if (video) {
|
|
844
|
-
try {
|
|
845
|
-
video.currentTime = target;
|
|
846
|
-
}
|
|
847
|
-
catch { }
|
|
848
|
-
}
|
|
849
|
-
try {
|
|
850
|
-
this.plyr.currentTime = target;
|
|
851
|
-
}
|
|
852
|
-
catch { }
|
|
853
|
-
if (restoreMute) {
|
|
854
|
-
setTimeout(() => restoreMute(), 300);
|
|
855
|
-
}
|
|
856
|
-
return null;
|
|
857
|
-
}
|
|
858
|
-
startAutoplayFlow(video) {
|
|
859
|
-
if (!this.shouldAutoplay() || !this.plyr)
|
|
860
|
-
return;
|
|
861
|
-
if (this.deferUntilStartTimeSettles(() => this.startAutoplayFlow(video))) {
|
|
862
|
-
return;
|
|
863
|
-
}
|
|
864
|
-
const media = video ?? this.videoRef?.nativeElement ?? null;
|
|
865
|
-
const tryPlay = (muted) => {
|
|
866
|
-
this.setPlayerMutedState(muted, 1, media);
|
|
867
|
-
let playResult;
|
|
868
|
-
try {
|
|
869
|
-
playResult = this.plyr.play();
|
|
870
|
-
this.forceIframeAutoplayFallback();
|
|
871
|
-
}
|
|
872
|
-
catch (error) {
|
|
873
|
-
if (!muted) {
|
|
874
|
-
tryPlay(true);
|
|
875
|
-
return;
|
|
876
|
-
}
|
|
877
|
-
if (media) {
|
|
878
|
-
try {
|
|
879
|
-
const nativePlay = media.play();
|
|
880
|
-
if (nativePlay && typeof nativePlay.catch === "function") {
|
|
881
|
-
nativePlay.catch(() => { });
|
|
882
|
-
}
|
|
883
|
-
}
|
|
884
|
-
catch { }
|
|
885
|
-
}
|
|
886
|
-
this.scheduleUserInteractionUnmute(media);
|
|
887
|
-
return;
|
|
888
|
-
}
|
|
889
|
-
if (playResult &&
|
|
890
|
-
typeof playResult.catch === "function") {
|
|
891
|
-
playResult.catch((error) => {
|
|
892
|
-
if (!muted) {
|
|
893
|
-
tryPlay(true);
|
|
894
|
-
return;
|
|
895
|
-
}
|
|
896
|
-
if (media) {
|
|
897
|
-
try {
|
|
898
|
-
const nativePlay = media.play();
|
|
899
|
-
if (nativePlay && typeof nativePlay.catch === "function") {
|
|
900
|
-
nativePlay.catch(() => { });
|
|
901
|
-
}
|
|
902
|
-
}
|
|
903
|
-
catch { }
|
|
904
|
-
}
|
|
905
|
-
this.scheduleUserInteractionUnmute(media);
|
|
906
|
-
});
|
|
907
|
-
return;
|
|
908
|
-
}
|
|
909
|
-
if (muted) {
|
|
910
|
-
this.scheduleUserInteractionUnmute(media);
|
|
911
|
-
}
|
|
912
|
-
else {
|
|
913
|
-
this.clearAutoplayUnlockListener();
|
|
914
|
-
}
|
|
915
|
-
};
|
|
916
|
-
if (this.requiresMutedAutoplay()) {
|
|
917
|
-
tryPlay(true);
|
|
918
|
-
}
|
|
919
|
-
else {
|
|
920
|
-
tryPlay(false);
|
|
921
|
-
}
|
|
922
|
-
}
|
|
923
|
-
forceIframeAutoplayFallback() {
|
|
924
|
-
if (!this.shouldAutoplay() || !this.isIframeProvider()) {
|
|
925
|
-
return;
|
|
926
|
-
}
|
|
927
|
-
const embed = this.plyr?.embed;
|
|
928
|
-
if (!embed)
|
|
929
|
-
return;
|
|
930
|
-
if (this.config.video_host === "youtube") {
|
|
931
|
-
if (typeof embed.playVideo === "function") {
|
|
932
|
-
try {
|
|
933
|
-
embed.playVideo();
|
|
934
|
-
}
|
|
935
|
-
catch { }
|
|
936
|
-
}
|
|
937
|
-
}
|
|
938
|
-
}
|
|
939
|
-
setupControlsVisibility() {
|
|
940
|
-
const container = this.plyr?.elements?.container;
|
|
941
|
-
if (!container) {
|
|
942
|
-
this.controlsVisibilityCleanup = undefined;
|
|
943
|
-
return;
|
|
944
|
-
}
|
|
945
|
-
if (this.isTouchDevice()) {
|
|
946
|
-
const HIDE_DELAY = 2000;
|
|
947
|
-
let hideTimeout = null;
|
|
948
|
-
const clearHideTimeout = () => {
|
|
949
|
-
if (hideTimeout) {
|
|
950
|
-
clearTimeout(hideTimeout);
|
|
951
|
-
hideTimeout = null;
|
|
952
|
-
}
|
|
953
|
-
};
|
|
954
|
-
const showControls = () => {
|
|
955
|
-
container.classList.remove("plyr--auto-hide-controls");
|
|
956
|
-
};
|
|
957
|
-
const hideControls = () => {
|
|
958
|
-
if (this.plyr?.playing) {
|
|
959
|
-
container.classList.add("plyr--auto-hide-controls");
|
|
960
|
-
}
|
|
961
|
-
};
|
|
962
|
-
const scheduleHide = () => {
|
|
963
|
-
clearHideTimeout();
|
|
964
|
-
if (!this.plyr?.playing)
|
|
965
|
-
return;
|
|
966
|
-
hideTimeout = setTimeout(() => hideControls(), HIDE_DELAY);
|
|
967
|
-
};
|
|
968
|
-
const onPlay = () => {
|
|
969
|
-
showControls();
|
|
970
|
-
this.overlayBlockAll = false;
|
|
971
|
-
};
|
|
972
|
-
const onPause = () => {
|
|
973
|
-
clearHideTimeout();
|
|
974
|
-
showControls();
|
|
975
|
-
this.overlayBlockAll = true;
|
|
976
|
-
this.updateTopClickBlockerSafeZone();
|
|
977
|
-
this.topClickBlocker?.setAttribute("data-state", "paused");
|
|
978
|
-
if (this.shouldEmitEndedOnPause()) {
|
|
979
|
-
this.endedLoggedOnPause = true;
|
|
980
|
-
console.log("event: ended");
|
|
981
|
-
}
|
|
982
|
-
};
|
|
983
|
-
const onEnded = () => {
|
|
984
|
-
clearHideTimeout();
|
|
985
|
-
showControls();
|
|
986
|
-
this.overlayBlockAll = true;
|
|
987
|
-
this.updateTopClickBlockerSafeZone();
|
|
988
|
-
this.topClickBlocker?.setAttribute("data-state", "ended");
|
|
989
|
-
};
|
|
990
|
-
const onUserInteraction = () => {
|
|
991
|
-
showControls();
|
|
992
|
-
scheduleHide();
|
|
993
|
-
};
|
|
994
|
-
this.plyr?.on?.("play", onPlay);
|
|
995
|
-
this.plyr?.on?.("pause", onPause);
|
|
996
|
-
this.plyr?.on?.("ended", onEnded);
|
|
997
|
-
container.addEventListener("touchstart", onUserInteraction);
|
|
998
|
-
container.addEventListener("click", onUserInteraction);
|
|
999
|
-
this.controlsVisibilityCleanup = () => {
|
|
1000
|
-
clearHideTimeout();
|
|
1001
|
-
this.plyr?.off?.("play", onPlay);
|
|
1002
|
-
this.plyr?.off?.("pause", onPause);
|
|
1003
|
-
this.plyr?.off?.("ended", onEnded);
|
|
1004
|
-
container.removeEventListener("touchstart", onUserInteraction);
|
|
1005
|
-
container.removeEventListener("click", onUserInteraction);
|
|
1006
|
-
container.classList.remove("plyr--auto-hide-controls");
|
|
1007
|
-
};
|
|
1008
|
-
onPlay();
|
|
1009
|
-
return;
|
|
1010
|
-
}
|
|
1011
|
-
let hovering = false;
|
|
1012
|
-
const toggleClass = () => {
|
|
1013
|
-
const playing = !!this.plyr?.playing;
|
|
1014
|
-
if (playing && !hovering) {
|
|
1015
|
-
container.classList.add("plyr--auto-hide-controls");
|
|
1016
|
-
}
|
|
1017
|
-
else {
|
|
1018
|
-
container.classList.remove("plyr--auto-hide-controls");
|
|
1019
|
-
}
|
|
1020
|
-
};
|
|
1021
|
-
const onPlay = () => toggleClass();
|
|
1022
|
-
const onPause = () => toggleClass();
|
|
1023
|
-
const onEnded = () => toggleClass();
|
|
1024
|
-
const onMouseEnter = () => {
|
|
1025
|
-
hovering = true;
|
|
1026
|
-
toggleClass();
|
|
1027
|
-
};
|
|
1028
|
-
const onMouseLeave = () => {
|
|
1029
|
-
hovering = false;
|
|
1030
|
-
toggleClass();
|
|
1031
|
-
};
|
|
1032
|
-
const onFocusIn = () => {
|
|
1033
|
-
hovering = true;
|
|
1034
|
-
toggleClass();
|
|
1035
|
-
};
|
|
1036
|
-
const onFocusOut = () => {
|
|
1037
|
-
hovering = container.matches(":hover");
|
|
1038
|
-
toggleClass();
|
|
1039
|
-
};
|
|
1040
|
-
this.plyr?.on?.("play", onPlay);
|
|
1041
|
-
this.plyr?.on?.("pause", onPause);
|
|
1042
|
-
this.plyr?.on?.("ended", onEnded);
|
|
1043
|
-
container.addEventListener("mouseenter", onMouseEnter);
|
|
1044
|
-
container.addEventListener("mouseleave", onMouseLeave);
|
|
1045
|
-
container.addEventListener("focusin", onFocusIn);
|
|
1046
|
-
container.addEventListener("focusout", onFocusOut);
|
|
1047
|
-
toggleClass();
|
|
1048
|
-
this.controlsVisibilityCleanup = () => {
|
|
1049
|
-
this.plyr?.off?.("play", onPlay);
|
|
1050
|
-
this.plyr?.off?.("pause", onPause);
|
|
1051
|
-
this.plyr?.off?.("ended", onEnded);
|
|
1052
|
-
container.removeEventListener("mouseenter", onMouseEnter);
|
|
1053
|
-
container.removeEventListener("mouseleave", onMouseLeave);
|
|
1054
|
-
container.removeEventListener("focusin", onFocusIn);
|
|
1055
|
-
container.removeEventListener("focusout", onFocusOut);
|
|
1056
|
-
container.classList.remove("plyr--auto-hide-controls");
|
|
1057
|
-
};
|
|
1058
|
-
}
|
|
1059
407
|
bindFullscreenBehavior() {
|
|
1060
408
|
const onEnterFullscreen = () => {
|
|
1061
409
|
console.log("event: enterfullscreen");
|
|
@@ -1075,26 +423,10 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1075
423
|
this.controlsVisibilityCleanup?.();
|
|
1076
424
|
this.controlsVisibilityCleanup = undefined;
|
|
1077
425
|
this.plyr?.destroy();
|
|
1078
|
-
this.clearAutoplayUnlockListener();
|
|
1079
426
|
this.recommendationBlocker = null;
|
|
1080
427
|
const speedOptions = [1, 1.25, 1.5, 2];
|
|
1081
|
-
const locale =
|
|
1082
|
-
const captionsLanguage =
|
|
1083
|
-
const shouldAutoplay = this.shouldAutoplay();
|
|
1084
|
-
const startMuted = this.requiresMutedAutoplay();
|
|
1085
|
-
try {
|
|
1086
|
-
this.videoRef.nativeElement.muted = startMuted;
|
|
1087
|
-
}
|
|
1088
|
-
catch { }
|
|
1089
|
-
try {
|
|
1090
|
-
this.videoRef.nativeElement.playsInline =
|
|
1091
|
-
this.config?.video_host === "youtube";
|
|
1092
|
-
}
|
|
1093
|
-
catch { }
|
|
1094
|
-
try {
|
|
1095
|
-
this.videoRef.nativeElement.autoplay = shouldAutoplay;
|
|
1096
|
-
}
|
|
1097
|
-
catch { }
|
|
428
|
+
const locale = 'pt-BR';
|
|
429
|
+
const captionsLanguage = "pt";
|
|
1098
430
|
const isLive = !!this.config?.is_live;
|
|
1099
431
|
const youtubePlayerVars = {
|
|
1100
432
|
rel: 0,
|
|
@@ -1104,8 +436,6 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1104
436
|
youtubePlayerVars.playerVars = {
|
|
1105
437
|
hl: locale,
|
|
1106
438
|
cc_lang_pref: captionsLanguage || locale.split("-")[0]?.toLowerCase(),
|
|
1107
|
-
autoplay: shouldAutoplay ? 1 : 0,
|
|
1108
|
-
mute: startMuted ? 1 : 0,
|
|
1109
439
|
playsinline: 1,
|
|
1110
440
|
};
|
|
1111
441
|
if (captionsLanguage) {
|
|
@@ -1144,8 +474,8 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1144
474
|
clickToPlay: !isLive,
|
|
1145
475
|
hideControls: isLive ? true : false,
|
|
1146
476
|
keyboard: { focused: !isLive, global: false },
|
|
1147
|
-
autoplay:
|
|
1148
|
-
muted:
|
|
477
|
+
autoplay: isLive ? true : false,
|
|
478
|
+
muted: false,
|
|
1149
479
|
};
|
|
1150
480
|
plyrOptions.hl = locale;
|
|
1151
481
|
if (captionsLanguage) {
|
|
@@ -1160,38 +490,15 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1160
490
|
}
|
|
1161
491
|
this.updateLiveInteractionBlocker(isLive);
|
|
1162
492
|
this.bindFullscreenBehavior();
|
|
1163
|
-
this.setupControlsVisibility();
|
|
1164
493
|
this.ensureTopClickBlocker();
|
|
1165
494
|
this.observeMenuChanges();
|
|
1166
495
|
this.playbackEnded = false;
|
|
1167
496
|
this.overlayBlockAll = false;
|
|
1168
|
-
this.endedLoggedOnPause = false;
|
|
1169
497
|
window.removeEventListener("resize", this.onResize);
|
|
1170
498
|
window.addEventListener("resize", this.onResize);
|
|
1171
499
|
this.bindProgressEvents();
|
|
1172
|
-
this.loadSource(this.videoRef.nativeElement).then(() => {
|
|
1173
|
-
|
|
1174
|
-
});
|
|
1175
|
-
// Dispara o evento ready quando o player estiver pronto
|
|
1176
|
-
// this.plyr.on("ready", () => {
|
|
1177
|
-
// this.ensureIframeAutoplayPermissions();
|
|
1178
|
-
// this.stopRestrictedIframeAutoplay();
|
|
1179
|
-
// });
|
|
1180
|
-
}
|
|
1181
|
-
/* private setupStartTime() {
|
|
1182
|
-
const apply = () => {
|
|
1183
|
-
const dur = this.plyr.duration || 0;
|
|
1184
|
-
const start = this.resolveStartTime(
|
|
1185
|
-
this.config.last_time,
|
|
1186
|
-
this.config.last_percent,
|
|
1187
|
-
dur
|
|
1188
|
-
);
|
|
1189
|
-
this.plyr?.pause();
|
|
1190
|
-
//this.requestStartTimeSeek(start);
|
|
1191
|
-
this.plyr.off("ready", apply as any);
|
|
1192
|
-
};
|
|
1193
|
-
this.plyr.on("ready", apply as any);
|
|
1194
|
-
} */
|
|
500
|
+
this.loadSource(this.videoRef.nativeElement).then(() => { });
|
|
501
|
+
}
|
|
1195
502
|
bindProgressEvents() {
|
|
1196
503
|
const THROTTLE_MS = 300;
|
|
1197
504
|
let lastEmit = 0;
|
|
@@ -1223,7 +530,6 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1223
530
|
});
|
|
1224
531
|
};
|
|
1225
532
|
this.plyr?.on?.("play", () => {
|
|
1226
|
-
this.retryPendingStartTime();
|
|
1227
533
|
this.playbackEnded = false;
|
|
1228
534
|
this.overlayBlockAll = false;
|
|
1229
535
|
this.updateRecommendationBlockerSafeZone();
|
|
@@ -1260,7 +566,6 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1260
566
|
this.playbackEnded = true;
|
|
1261
567
|
this.overlayBlockAll = true;
|
|
1262
568
|
this.updateRecommendationBlockerSafeZone();
|
|
1263
|
-
this.endedLoggedOnPause = true;
|
|
1264
569
|
console.log("event: ended");
|
|
1265
570
|
parent.postMessage("event: ended", "*");
|
|
1266
571
|
this.postCastEvent({
|
|
@@ -1271,48 +576,6 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1271
576
|
this.toggleRecommendationBlocker(true);
|
|
1272
577
|
});
|
|
1273
578
|
}
|
|
1274
|
-
unmuteAfterDelay(video, delayMs = 2000, volume = 1) {
|
|
1275
|
-
if (!this.shouldAutoplay())
|
|
1276
|
-
return;
|
|
1277
|
-
setTimeout(() => {
|
|
1278
|
-
try {
|
|
1279
|
-
if (this.plyr) {
|
|
1280
|
-
this.plyr.muted = false;
|
|
1281
|
-
this.plyr.volume = volume;
|
|
1282
|
-
}
|
|
1283
|
-
}
|
|
1284
|
-
catch { }
|
|
1285
|
-
try {
|
|
1286
|
-
if (video) {
|
|
1287
|
-
video.muted = false;
|
|
1288
|
-
if (typeof video.volume === "number")
|
|
1289
|
-
video.volume = volume;
|
|
1290
|
-
}
|
|
1291
|
-
}
|
|
1292
|
-
catch { }
|
|
1293
|
-
}, delayMs);
|
|
1294
|
-
}
|
|
1295
|
-
resetPlaybackRate(video) {
|
|
1296
|
-
try {
|
|
1297
|
-
if (this.plyr && typeof this.plyr.speed !== "undefined") {
|
|
1298
|
-
this.plyr.speed = 1;
|
|
1299
|
-
}
|
|
1300
|
-
}
|
|
1301
|
-
catch { }
|
|
1302
|
-
const media = video ?? this.videoRef?.nativeElement ?? null;
|
|
1303
|
-
if (media) {
|
|
1304
|
-
try {
|
|
1305
|
-
media.playbackRate = 1;
|
|
1306
|
-
}
|
|
1307
|
-
catch { }
|
|
1308
|
-
try {
|
|
1309
|
-
if (media.defaultPlaybackRate !== undefined) {
|
|
1310
|
-
media.defaultPlaybackRate = 1;
|
|
1311
|
-
}
|
|
1312
|
-
}
|
|
1313
|
-
catch { }
|
|
1314
|
-
}
|
|
1315
|
-
}
|
|
1316
579
|
loadSource(video) {
|
|
1317
580
|
return new Promise((resolve) => {
|
|
1318
581
|
if (!this.config) {
|
|
@@ -1322,19 +585,12 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1322
585
|
this.hls.destroy();
|
|
1323
586
|
this.hls = undefined;
|
|
1324
587
|
}
|
|
1325
|
-
this.
|
|
588
|
+
this.plyr?.pause();
|
|
1326
589
|
if (this.config.video_host === "youtube") {
|
|
1327
590
|
const onReady = () => {
|
|
1328
591
|
this.plyr.off("ready", onReady);
|
|
1329
|
-
this.ensureIframeAutoplayPermissions();
|
|
1330
592
|
const start = this.resolveStartTime(this.config.last_time, this.config.last_percent, this.plyr.duration);
|
|
1331
|
-
//this.requestStartTimeSeek(start);
|
|
1332
593
|
this.plyr?.forward(start);
|
|
1333
|
-
// if (this.shouldAutoplay()) {
|
|
1334
|
-
// this.startAutoplayFlow();
|
|
1335
|
-
// } else if (this.shouldBlockIframeAutoplay()) {
|
|
1336
|
-
// this.stopRestrictedIframeAutoplay();
|
|
1337
|
-
// }
|
|
1338
594
|
parent.postMessage("playerIsReadyToPlay", "*");
|
|
1339
595
|
parent.postMessage("duration:" + this.plyr.duration, "*");
|
|
1340
596
|
console.log("event: current_time " + this.plyr.currentTime);
|
|
@@ -1392,8 +648,7 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1392
648
|
const dur = this.plyr.duration || video.duration || 0;
|
|
1393
649
|
const start = this.resolveStartTime(this.config.last_time, this.config.last_percent, dur);
|
|
1394
650
|
console.log(start);
|
|
1395
|
-
this.
|
|
1396
|
-
this.startAutoplayFlow(video);
|
|
651
|
+
this.plyr?.forward(start);
|
|
1397
652
|
video.removeEventListener("loadedmetadata", onLoadedMeta);
|
|
1398
653
|
};
|
|
1399
654
|
video.addEventListener("loadedmetadata", onLoadedMeta);
|
|
@@ -1407,8 +662,7 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1407
662
|
this.hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
|
1408
663
|
const dur = video.duration || 0;
|
|
1409
664
|
const start = this.resolveStartTime(this.config.last_time, this.config.last_percent, dur);
|
|
1410
|
-
this.
|
|
1411
|
-
this.startAutoplayFlow(video);
|
|
665
|
+
this.plyr?.forward(start);
|
|
1412
666
|
});
|
|
1413
667
|
this.hls.on(Hls.Events.ERROR, (_evt, data) => {
|
|
1414
668
|
if (data?.fatal) {
|
|
@@ -1437,7 +691,7 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1437
691
|
});
|
|
1438
692
|
}
|
|
1439
693
|
resolveStartTime(last_time, last_percent, duration, opts = {}) {
|
|
1440
|
-
if (
|
|
694
|
+
if (!last_time || last_time <= 0) {
|
|
1441
695
|
return 0;
|
|
1442
696
|
}
|
|
1443
697
|
const minStartSec = opts.minStartSec ?? 3;
|
|
@@ -1495,7 +749,6 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1495
749
|
data = JSON.parse(data);
|
|
1496
750
|
}
|
|
1497
751
|
catch {
|
|
1498
|
-
/* ignora */
|
|
1499
752
|
}
|
|
1500
753
|
}
|
|
1501
754
|
if (data?.action === "request-iframe-media-metadata") {
|
|
@@ -1519,7 +772,6 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1519
772
|
this.hls?.destroy();
|
|
1520
773
|
this.controlsVisibilityCleanup?.();
|
|
1521
774
|
this.controlsVisibilityCleanup = undefined;
|
|
1522
|
-
this.clearAutoplayUnlockListener();
|
|
1523
775
|
this.detachLiveInteractionBlocker();
|
|
1524
776
|
const container = this.plyr?.elements?.container;
|
|
1525
777
|
if (this.recommendationBlocker?.parentElement) {
|