@edm-webplayer/webplayer-angular 0.1.99 → 0.2.1
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.
|
@@ -90,13 +90,32 @@ class PlyrPlayerComponent {
|
|
|
90
90
|
liveInteractionBlocker;
|
|
91
91
|
iosFullscreenCleanup;
|
|
92
92
|
pendingStartTime;
|
|
93
|
-
autoplayConfig;
|
|
94
93
|
onResize = () => {
|
|
95
94
|
this.updateRecommendationBlockerSafeZone();
|
|
96
95
|
};
|
|
97
|
-
|
|
98
|
-
if (
|
|
99
|
-
|
|
96
|
+
onRecommendationBlockerClick = (event) => {
|
|
97
|
+
if (event) {
|
|
98
|
+
try {
|
|
99
|
+
event.preventDefault();
|
|
100
|
+
}
|
|
101
|
+
catch { }
|
|
102
|
+
try {
|
|
103
|
+
event.stopPropagation();
|
|
104
|
+
}
|
|
105
|
+
catch { }
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
onTopBlockerPointerDown = (event) => {
|
|
109
|
+
try {
|
|
110
|
+
event.preventDefault();
|
|
111
|
+
}
|
|
112
|
+
catch { }
|
|
113
|
+
try {
|
|
114
|
+
event.stopPropagation();
|
|
115
|
+
}
|
|
116
|
+
catch { }
|
|
117
|
+
};
|
|
118
|
+
onTopBlockerClick = (event) => {
|
|
100
119
|
try {
|
|
101
120
|
event.preventDefault();
|
|
102
121
|
}
|
|
@@ -176,9 +195,6 @@ class PlyrPlayerComponent {
|
|
|
176
195
|
}
|
|
177
196
|
return Math.max(this.overlayInteractionGapPx, this.getControlsSafeZone());
|
|
178
197
|
}
|
|
179
|
-
getOverlayGuardHeight() {
|
|
180
|
-
return Math.max(48, Math.ceil(this.getOverlaySafeZone()));
|
|
181
|
-
}
|
|
182
198
|
getOpenMenuHeight() {
|
|
183
199
|
const container = this.plyr?.elements?.container;
|
|
184
200
|
if (!container)
|
|
@@ -286,32 +302,28 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
286
302
|
return null;
|
|
287
303
|
const blocker = this.document.createElement("div");
|
|
288
304
|
blocker.className = "plyr-recommendation-blocker";
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
cursor: "pointer",
|
|
300
|
-
});
|
|
305
|
+
blocker.style.position = "absolute";
|
|
306
|
+
blocker.style.top = "0";
|
|
307
|
+
blocker.style.left = "0";
|
|
308
|
+
blocker.style.width = "100%";
|
|
309
|
+
blocker.style.height = "100%";
|
|
310
|
+
blocker.style.zIndex = "9";
|
|
311
|
+
blocker.style.pointerEvents = "none";
|
|
312
|
+
blocker.style.display = "none";
|
|
313
|
+
blocker.style.background = "rgba(0,0,0,0)";
|
|
314
|
+
blocker.style.cursor = "pointer";
|
|
301
315
|
const activeZone = this.document.createElement("div");
|
|
302
316
|
activeZone.className = "plyr-recommendation-blocker__zone";
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
activeZone.addEventListener("pointerdown", this.consumeEvent);
|
|
314
|
-
activeZone.addEventListener("click", this.consumeEvent);
|
|
317
|
+
activeZone.style.position = "absolute";
|
|
318
|
+
activeZone.style.top = "0";
|
|
319
|
+
activeZone.style.left = "0";
|
|
320
|
+
activeZone.style.width = "100%";
|
|
321
|
+
activeZone.style.bottom = `20px`;
|
|
322
|
+
activeZone.style.pointerEvents = "auto";
|
|
323
|
+
activeZone.style.background = "rgba(0,0,0,0)";
|
|
324
|
+
activeZone.style.cursor = "pointer";
|
|
325
|
+
activeZone.addEventListener("pointerdown", this.onTopBlockerPointerDown);
|
|
326
|
+
activeZone.addEventListener("click", this.onRecommendationBlockerClick);
|
|
315
327
|
blocker.appendChild(activeZone);
|
|
316
328
|
wrapper.appendChild(blocker);
|
|
317
329
|
this.recommendationBlocker = blocker;
|
|
@@ -351,20 +363,18 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
351
363
|
}
|
|
352
364
|
const blocker = this.document.createElement("div");
|
|
353
365
|
blocker.className = "plyr-top-click-blocker";
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
blocker.addEventListener("pointerdown", this.consumeEvent);
|
|
367
|
-
blocker.addEventListener("click", this.consumeEvent);
|
|
366
|
+
blocker.style.position = "absolute";
|
|
367
|
+
blocker.style.top = "0";
|
|
368
|
+
blocker.style.left = "0";
|
|
369
|
+
blocker.style.right = "0";
|
|
370
|
+
blocker.style.width = "100%";
|
|
371
|
+
blocker.style.zIndex = "12";
|
|
372
|
+
blocker.style.pointerEvents = "auto";
|
|
373
|
+
blocker.style.background = "rgba(0,0,0,0)";
|
|
374
|
+
blocker.style.touchAction = "none";
|
|
375
|
+
blocker.style.cursor = "default";
|
|
376
|
+
blocker.addEventListener("pointerdown", this.onTopBlockerPointerDown);
|
|
377
|
+
blocker.addEventListener("click", this.onTopBlockerClick);
|
|
368
378
|
wrapper.appendChild(blocker);
|
|
369
379
|
this.topClickBlocker = blocker;
|
|
370
380
|
this.updateTopClickBlockerSafeZone();
|
|
@@ -372,7 +382,8 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
372
382
|
updateTopClickBlockerSafeZone() {
|
|
373
383
|
if (!this.topClickBlocker)
|
|
374
384
|
return;
|
|
375
|
-
|
|
385
|
+
const height = Math.max(48, Math.ceil(this.getOverlaySafeZone()));
|
|
386
|
+
this.topClickBlocker.style.height = `${height}px`;
|
|
376
387
|
this.topClickBlocker.style.pointerEvents = this.overlayBlockAll
|
|
377
388
|
? "auto"
|
|
378
389
|
: "none";
|
|
@@ -398,15 +409,9 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
398
409
|
if (typeof navigator === "undefined")
|
|
399
410
|
return false;
|
|
400
411
|
const ua = navigator.userAgent || "";
|
|
401
|
-
const uaDataPlatform = navigator?.userAgentData?.platform || "";
|
|
402
|
-
const uaDataBrands = navigator?.userAgentData?.brands || [];
|
|
403
|
-
const hasIOSBrand = Array.isArray(uaDataBrands)
|
|
404
|
-
? uaDataBrands.some((b) => String(b?.brand || "").toLowerCase().includes("ios"))
|
|
405
|
-
: false;
|
|
406
412
|
const iOS = /iPad|iPhone|iPod/.test(ua);
|
|
407
|
-
const iPadOS =
|
|
408
|
-
|
|
409
|
-
return iOS || iPadOS || hasIOSBrand;
|
|
413
|
+
const iPadOS = navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1;
|
|
414
|
+
return iOS || iPadOS;
|
|
410
415
|
}
|
|
411
416
|
isIOSContext() {
|
|
412
417
|
if (this.isIOSDevice()) {
|
|
@@ -490,6 +495,12 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
490
495
|
isIframeProvider() {
|
|
491
496
|
return this.config?.video_host === "youtube";
|
|
492
497
|
}
|
|
498
|
+
shouldDisableAutoplayForIOS() {
|
|
499
|
+
if (this.config?.is_live) {
|
|
500
|
+
return false;
|
|
501
|
+
}
|
|
502
|
+
return this.isIOSDevice();
|
|
503
|
+
}
|
|
493
504
|
shouldResetProgressToBeginning() {
|
|
494
505
|
const host = this.config?.video_host;
|
|
495
506
|
if (host !== "youtube") {
|
|
@@ -577,53 +588,32 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
577
588
|
}
|
|
578
589
|
this.liveInteractionBlocker = null;
|
|
579
590
|
}
|
|
580
|
-
|
|
581
|
-
return !!this.config?.is_live;
|
|
582
|
-
}
|
|
583
|
-
getAutoplayConfig() {
|
|
584
|
-
const isLive = this.isLivePlayback();
|
|
585
|
-
const enabled = isLive;
|
|
586
|
-
const startMuted = enabled;
|
|
587
|
-
const blockIframe = !isLive;
|
|
588
|
-
this.autoplayConfig = { enabled, startMuted, blockIframe };
|
|
589
|
-
return this.autoplayConfig;
|
|
591
|
+
wantsAutoplay() {
|
|
592
|
+
return !!(this.config?.autoplay || this.config?.is_live);
|
|
590
593
|
}
|
|
591
|
-
|
|
592
|
-
if (
|
|
593
|
-
return;
|
|
594
|
-
const media = this.videoRef?.nativeElement ?? null;
|
|
595
|
-
if (media) {
|
|
596
|
-
try {
|
|
597
|
-
media.autoplay = false;
|
|
598
|
-
media.pause();
|
|
599
|
-
}
|
|
600
|
-
catch { }
|
|
594
|
+
shouldAutoplay() {
|
|
595
|
+
if (this.config?.is_live) {
|
|
596
|
+
return true;
|
|
601
597
|
}
|
|
602
|
-
if (this.
|
|
603
|
-
|
|
604
|
-
this.plyr.autoplay = false;
|
|
605
|
-
this.plyr.pause();
|
|
606
|
-
}
|
|
607
|
-
catch { }
|
|
598
|
+
if (this.shouldDisableAutoplayForIOS()) {
|
|
599
|
+
return false;
|
|
608
600
|
}
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
catch { }
|
|
617
|
-
try {
|
|
618
|
-
if (typeof embed.setMuted === "function") {
|
|
619
|
-
embed.setMuted(false);
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
catch { }
|
|
601
|
+
return this.wantsAutoplay();
|
|
602
|
+
}
|
|
603
|
+
requiresMutedAutoplay() {
|
|
604
|
+
if (this.config?.is_live && this.isIOSDevice()) {
|
|
605
|
+
return true;
|
|
623
606
|
}
|
|
607
|
+
if (!this.isIOSDevice() || this.shouldDisableAutoplayForIOS()) {
|
|
608
|
+
return false;
|
|
609
|
+
}
|
|
610
|
+
return this.wantsAutoplay();
|
|
611
|
+
}
|
|
612
|
+
shouldBlockIframeAutoplay() {
|
|
613
|
+
return this.shouldDisableAutoplayForIOS();
|
|
624
614
|
}
|
|
625
|
-
stopRestrictedIframeAutoplay(
|
|
626
|
-
if (!
|
|
615
|
+
stopRestrictedIframeAutoplay() {
|
|
616
|
+
if (!this.shouldBlockIframeAutoplay()) {
|
|
627
617
|
return;
|
|
628
618
|
}
|
|
629
619
|
this.clearAutoplayUnlockListener();
|
|
@@ -702,8 +692,7 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
702
692
|
const media = target ?? this.videoRef?.nativeElement ?? null;
|
|
703
693
|
const prevVideoMuted = media?.muted ?? false;
|
|
704
694
|
const prevPlyrMuted = !!this.plyr?.muted;
|
|
705
|
-
const
|
|
706
|
-
const shouldForceUnmute = !autoplayConfig.enabled;
|
|
695
|
+
const shouldForceUnmute = !this.shouldAutoplay();
|
|
707
696
|
try {
|
|
708
697
|
if (media) {
|
|
709
698
|
media.muted = true;
|
|
@@ -743,11 +732,10 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
743
732
|
this.interactionUnmuteCleanup = undefined;
|
|
744
733
|
}
|
|
745
734
|
}
|
|
746
|
-
ensureAutoplayUnlockListener(
|
|
747
|
-
if (typeof window === "undefined" ||
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
if (!autoplayConfig.enabled) {
|
|
735
|
+
ensureAutoplayUnlockListener() {
|
|
736
|
+
if (typeof window === "undefined" ||
|
|
737
|
+
this.interactionUnmuteCleanup ||
|
|
738
|
+
!this.shouldAutoplay()) {
|
|
751
739
|
return;
|
|
752
740
|
}
|
|
753
741
|
const capture = true;
|
|
@@ -755,7 +743,6 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
755
743
|
this.setPlayerMutedState(false);
|
|
756
744
|
try {
|
|
757
745
|
this.plyr?.play();
|
|
758
|
-
console.log("Autoplay unlocked via user interaction");
|
|
759
746
|
}
|
|
760
747
|
catch { }
|
|
761
748
|
this.clearAutoplayUnlockListener();
|
|
@@ -771,7 +758,6 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
771
758
|
};
|
|
772
759
|
}
|
|
773
760
|
ensureIframeAutoplayPermissions() {
|
|
774
|
-
// Só ajusta permissões quando há iframe (ex.: YouTube)
|
|
775
761
|
if (!this.isIframeProvider()) {
|
|
776
762
|
return;
|
|
777
763
|
}
|
|
@@ -781,11 +767,19 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
781
767
|
const iframe = container.querySelector("iframe") ?? null;
|
|
782
768
|
if (!iframe)
|
|
783
769
|
return;
|
|
784
|
-
|
|
785
|
-
const
|
|
786
|
-
.
|
|
787
|
-
.
|
|
788
|
-
|
|
770
|
+
const allowRaw = iframe.getAttribute("allow") || "";
|
|
771
|
+
const tokens = new Set(allowRaw
|
|
772
|
+
.split(";")
|
|
773
|
+
.map((token) => token.trim())
|
|
774
|
+
.filter(Boolean));
|
|
775
|
+
[
|
|
776
|
+
"autoplay",
|
|
777
|
+
"fullscreen",
|
|
778
|
+
"encrypted-media",
|
|
779
|
+
"picture-in-picture",
|
|
780
|
+
"gyroscope",
|
|
781
|
+
].forEach((rule) => tokens.add(rule));
|
|
782
|
+
iframe.setAttribute("allow", Array.from(tokens).join("; "));
|
|
789
783
|
if (this.config.video_host === "youtube") {
|
|
790
784
|
iframe.setAttribute("playsinline", "1");
|
|
791
785
|
iframe.setAttribute("webkit-playsinline", "1");
|
|
@@ -793,11 +787,9 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
793
787
|
iframe.setAttribute("allowfullscreen", "true");
|
|
794
788
|
iframe.setAttribute("data-keepplaying", "true");
|
|
795
789
|
}
|
|
796
|
-
scheduleUserInteractionUnmute(video
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
this.unmuteAfterDelay(video || undefined, undefined, 1, autoplayConfig);
|
|
800
|
-
this.ensureAutoplayUnlockListener(autoplayConfig);
|
|
790
|
+
scheduleUserInteractionUnmute(video) {
|
|
791
|
+
this.unmuteAfterDelay(video || undefined);
|
|
792
|
+
this.ensureAutoplayUnlockListener();
|
|
801
793
|
}
|
|
802
794
|
requestStartTimeSeek(start, opts = {}) {
|
|
803
795
|
if (!(start > 0)) {
|
|
@@ -909,8 +901,8 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
909
901
|
}
|
|
910
902
|
return null;
|
|
911
903
|
}
|
|
912
|
-
startAutoplayFlow(video
|
|
913
|
-
if (!
|
|
904
|
+
startAutoplayFlow(video) {
|
|
905
|
+
if (!this.shouldAutoplay() || !this.plyr)
|
|
914
906
|
return;
|
|
915
907
|
if (this.deferUntilStartTimeSettles(() => this.startAutoplayFlow(video))) {
|
|
916
908
|
return;
|
|
@@ -921,7 +913,7 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
921
913
|
let playResult;
|
|
922
914
|
try {
|
|
923
915
|
playResult = this.plyr.play();
|
|
924
|
-
this.forceIframeAutoplayFallback(
|
|
916
|
+
this.forceIframeAutoplayFallback();
|
|
925
917
|
}
|
|
926
918
|
catch (error) {
|
|
927
919
|
if (!muted) {
|
|
@@ -937,7 +929,7 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
937
929
|
}
|
|
938
930
|
catch { }
|
|
939
931
|
}
|
|
940
|
-
this.scheduleUserInteractionUnmute(media
|
|
932
|
+
this.scheduleUserInteractionUnmute(media);
|
|
941
933
|
return;
|
|
942
934
|
}
|
|
943
935
|
if (playResult &&
|
|
@@ -956,26 +948,26 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
956
948
|
}
|
|
957
949
|
catch { }
|
|
958
950
|
}
|
|
959
|
-
this.scheduleUserInteractionUnmute(media
|
|
951
|
+
this.scheduleUserInteractionUnmute(media);
|
|
960
952
|
});
|
|
961
953
|
return;
|
|
962
954
|
}
|
|
963
955
|
if (muted) {
|
|
964
|
-
this.scheduleUserInteractionUnmute(media
|
|
956
|
+
this.scheduleUserInteractionUnmute(media);
|
|
965
957
|
}
|
|
966
958
|
else {
|
|
967
959
|
this.clearAutoplayUnlockListener();
|
|
968
960
|
}
|
|
969
961
|
};
|
|
970
|
-
if (
|
|
962
|
+
if (this.requiresMutedAutoplay()) {
|
|
971
963
|
tryPlay(true);
|
|
972
964
|
}
|
|
973
965
|
else {
|
|
974
966
|
tryPlay(false);
|
|
975
967
|
}
|
|
976
968
|
}
|
|
977
|
-
forceIframeAutoplayFallback(
|
|
978
|
-
if (!this.
|
|
969
|
+
forceIframeAutoplayFallback() {
|
|
970
|
+
if (!this.shouldAutoplay() || !this.isIframeProvider()) {
|
|
979
971
|
return;
|
|
980
972
|
}
|
|
981
973
|
const embed = this.plyr?.embed;
|
|
@@ -997,79 +989,71 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
997
989
|
return;
|
|
998
990
|
}
|
|
999
991
|
if (this.isTouchDevice()) {
|
|
1000
|
-
|
|
1001
|
-
|
|
992
|
+
const HIDE_DELAY = 2000;
|
|
993
|
+
let hideTimeout = null;
|
|
994
|
+
const clearHideTimeout = () => {
|
|
995
|
+
if (hideTimeout) {
|
|
996
|
+
clearTimeout(hideTimeout);
|
|
997
|
+
hideTimeout = null;
|
|
998
|
+
}
|
|
999
|
+
};
|
|
1000
|
+
const showControls = () => {
|
|
1001
|
+
container.classList.remove("plyr--auto-hide-controls");
|
|
1002
|
+
};
|
|
1003
|
+
const hideControls = () => {
|
|
1004
|
+
if (this.plyr?.playing) {
|
|
1005
|
+
container.classList.add("plyr--auto-hide-controls");
|
|
1006
|
+
}
|
|
1007
|
+
};
|
|
1008
|
+
const scheduleHide = () => {
|
|
1009
|
+
clearHideTimeout();
|
|
1010
|
+
if (!this.plyr?.playing)
|
|
1011
|
+
return;
|
|
1012
|
+
hideTimeout = setTimeout(() => hideControls(), HIDE_DELAY);
|
|
1013
|
+
};
|
|
1014
|
+
const onPlay = () => {
|
|
1015
|
+
showControls();
|
|
1016
|
+
this.overlayBlockAll = false;
|
|
1017
|
+
};
|
|
1018
|
+
const onPause = () => {
|
|
1019
|
+
clearHideTimeout();
|
|
1020
|
+
showControls();
|
|
1021
|
+
this.overlayBlockAll = true;
|
|
1022
|
+
this.updateTopClickBlockerSafeZone();
|
|
1023
|
+
this.topClickBlocker?.setAttribute("data-state", "paused");
|
|
1024
|
+
if (this.shouldEmitEndedOnPause()) {
|
|
1025
|
+
this.endedLoggedOnPause = true;
|
|
1026
|
+
console.log("event: ended");
|
|
1027
|
+
}
|
|
1028
|
+
};
|
|
1029
|
+
const onEnded = () => {
|
|
1030
|
+
clearHideTimeout();
|
|
1031
|
+
showControls();
|
|
1032
|
+
this.overlayBlockAll = true;
|
|
1033
|
+
this.updateTopClickBlockerSafeZone();
|
|
1034
|
+
this.topClickBlocker?.setAttribute("data-state", "ended");
|
|
1035
|
+
};
|
|
1036
|
+
const onUserInteraction = () => {
|
|
1037
|
+
showControls();
|
|
1038
|
+
scheduleHide();
|
|
1039
|
+
};
|
|
1040
|
+
this.plyr?.on?.("play", onPlay);
|
|
1041
|
+
this.plyr?.on?.("pause", onPause);
|
|
1042
|
+
this.plyr?.on?.("ended", onEnded);
|
|
1043
|
+
container.addEventListener("touchstart", onUserInteraction);
|
|
1044
|
+
container.addEventListener("click", onUserInteraction);
|
|
1045
|
+
this.controlsVisibilityCleanup = () => {
|
|
1046
|
+
clearHideTimeout();
|
|
1047
|
+
this.plyr?.off?.("play", onPlay);
|
|
1048
|
+
this.plyr?.off?.("pause", onPause);
|
|
1049
|
+
this.plyr?.off?.("ended", onEnded);
|
|
1050
|
+
container.removeEventListener("touchstart", onUserInteraction);
|
|
1051
|
+
container.removeEventListener("click", onUserInteraction);
|
|
1052
|
+
container.classList.remove("plyr--auto-hide-controls");
|
|
1053
|
+
};
|
|
1054
|
+
onPlay();
|
|
1002
1055
|
return;
|
|
1003
1056
|
}
|
|
1004
|
-
this.controlsVisibilityCleanup =
|
|
1005
|
-
this.setupDesktopControlsVisibility(container);
|
|
1006
|
-
}
|
|
1007
|
-
setupTouchControlsVisibility(container) {
|
|
1008
|
-
const HIDE_DELAY = 2000;
|
|
1009
|
-
let hideTimeout = null;
|
|
1010
|
-
const clearHideTimeout = () => {
|
|
1011
|
-
if (hideTimeout) {
|
|
1012
|
-
clearTimeout(hideTimeout);
|
|
1013
|
-
hideTimeout = null;
|
|
1014
|
-
}
|
|
1015
|
-
};
|
|
1016
|
-
const showControls = () => {
|
|
1017
|
-
container.classList.remove("plyr--auto-hide-controls");
|
|
1018
|
-
};
|
|
1019
|
-
const hideControls = () => {
|
|
1020
|
-
if (this.plyr?.playing) {
|
|
1021
|
-
container.classList.add("plyr--auto-hide-controls");
|
|
1022
|
-
}
|
|
1023
|
-
};
|
|
1024
|
-
const scheduleHide = () => {
|
|
1025
|
-
clearHideTimeout();
|
|
1026
|
-
if (!this.plyr?.playing)
|
|
1027
|
-
return;
|
|
1028
|
-
hideTimeout = setTimeout(() => hideControls(), HIDE_DELAY);
|
|
1029
|
-
};
|
|
1030
|
-
const onPlay = () => {
|
|
1031
|
-
showControls();
|
|
1032
|
-
this.overlayBlockAll = false;
|
|
1033
|
-
};
|
|
1034
|
-
const onPause = () => {
|
|
1035
|
-
clearHideTimeout();
|
|
1036
|
-
showControls();
|
|
1037
|
-
this.overlayBlockAll = true;
|
|
1038
|
-
this.updateTopClickBlockerSafeZone();
|
|
1039
|
-
this.topClickBlocker?.setAttribute("data-state", "paused");
|
|
1040
|
-
if (this.shouldEmitEndedOnPause()) {
|
|
1041
|
-
this.endedLoggedOnPause = true;
|
|
1042
|
-
console.log("event: ended");
|
|
1043
|
-
}
|
|
1044
|
-
};
|
|
1045
|
-
const onEnded = () => {
|
|
1046
|
-
clearHideTimeout();
|
|
1047
|
-
showControls();
|
|
1048
|
-
this.overlayBlockAll = true;
|
|
1049
|
-
this.updateTopClickBlockerSafeZone();
|
|
1050
|
-
this.topClickBlocker?.setAttribute("data-state", "ended");
|
|
1051
|
-
};
|
|
1052
|
-
const onUserInteraction = () => {
|
|
1053
|
-
showControls();
|
|
1054
|
-
scheduleHide();
|
|
1055
|
-
};
|
|
1056
|
-
this.plyr?.on?.("play", onPlay);
|
|
1057
|
-
this.plyr?.on?.("pause", onPause);
|
|
1058
|
-
this.plyr?.on?.("ended", onEnded);
|
|
1059
|
-
container.addEventListener("touchstart", onUserInteraction);
|
|
1060
|
-
container.addEventListener("click", onUserInteraction);
|
|
1061
|
-
onPlay();
|
|
1062
|
-
return () => {
|
|
1063
|
-
clearHideTimeout();
|
|
1064
|
-
this.plyr?.off?.("play", onPlay);
|
|
1065
|
-
this.plyr?.off?.("pause", onPause);
|
|
1066
|
-
this.plyr?.off?.("ended", onEnded);
|
|
1067
|
-
container.removeEventListener("touchstart", onUserInteraction);
|
|
1068
|
-
container.removeEventListener("click", onUserInteraction);
|
|
1069
|
-
container.classList.remove("plyr--auto-hide-controls");
|
|
1070
|
-
};
|
|
1071
|
-
}
|
|
1072
|
-
setupDesktopControlsVisibility(container) {
|
|
1073
1057
|
let hovering = false;
|
|
1074
1058
|
const toggleClass = () => {
|
|
1075
1059
|
const playing = !!this.plyr?.playing;
|
|
@@ -1107,7 +1091,7 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1107
1091
|
container.addEventListener("focusin", onFocusIn);
|
|
1108
1092
|
container.addEventListener("focusout", onFocusOut);
|
|
1109
1093
|
toggleClass();
|
|
1110
|
-
|
|
1094
|
+
this.controlsVisibilityCleanup = () => {
|
|
1111
1095
|
this.plyr?.off?.("play", onPlay);
|
|
1112
1096
|
this.plyr?.off?.("pause", onPause);
|
|
1113
1097
|
this.plyr?.off?.("ended", onEnded);
|
|
@@ -1146,8 +1130,8 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1146
1130
|
const speedOptions = [1, 1.25, 1.5, 2];
|
|
1147
1131
|
const locale = this.resolveLocale();
|
|
1148
1132
|
const captionsLanguage = this.resolveCaptionsLanguage(locale) ?? "pt";
|
|
1149
|
-
const
|
|
1150
|
-
const
|
|
1133
|
+
const shouldAutoplay = this.shouldAutoplay();
|
|
1134
|
+
const startMuted = this.requiresMutedAutoplay();
|
|
1151
1135
|
try {
|
|
1152
1136
|
this.videoRef.nativeElement.muted = startMuted;
|
|
1153
1137
|
}
|
|
@@ -1161,7 +1145,7 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1161
1145
|
this.videoRef.nativeElement.autoplay = shouldAutoplay;
|
|
1162
1146
|
}
|
|
1163
1147
|
catch { }
|
|
1164
|
-
const isLive = this.
|
|
1148
|
+
const isLive = !!this.config?.is_live;
|
|
1165
1149
|
const youtubePlayerVars = {
|
|
1166
1150
|
rel: 0,
|
|
1167
1151
|
modestbranding: 1,
|
|
@@ -1224,7 +1208,6 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1224
1208
|
plyrOptions.youtube = youtubePlayerVars;
|
|
1225
1209
|
}
|
|
1226
1210
|
this.plyr = new Plyr.default(this.videoRef.nativeElement, plyrOptions);
|
|
1227
|
-
this.enforceInitialPause(autoplayConfig);
|
|
1228
1211
|
if (typeof this.plyr?.toggleControls === "function") {
|
|
1229
1212
|
this.plyr.toggleControls(!isLive);
|
|
1230
1213
|
}
|
|
@@ -1240,13 +1223,13 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1240
1223
|
window.removeEventListener("resize", this.onResize);
|
|
1241
1224
|
window.addEventListener("resize", this.onResize);
|
|
1242
1225
|
this.bindProgressEvents();
|
|
1243
|
-
this.loadSource(this.videoRef.nativeElement
|
|
1226
|
+
this.loadSource(this.videoRef.nativeElement).then(() => {
|
|
1244
1227
|
this.setupStartTime();
|
|
1245
1228
|
});
|
|
1229
|
+
// Dispara o evento ready quando o player estiver pronto
|
|
1246
1230
|
this.plyr.on("ready", () => {
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
}
|
|
1231
|
+
this.ensureIframeAutoplayPermissions();
|
|
1232
|
+
this.stopRestrictedIframeAutoplay();
|
|
1250
1233
|
this.ready.emit();
|
|
1251
1234
|
});
|
|
1252
1235
|
}
|
|
@@ -1338,8 +1321,8 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1338
1321
|
this.toggleRecommendationBlocker(true);
|
|
1339
1322
|
});
|
|
1340
1323
|
}
|
|
1341
|
-
unmuteAfterDelay(video, delayMs = 2000, volume = 1
|
|
1342
|
-
if (!
|
|
1324
|
+
unmuteAfterDelay(video, delayMs = 2000, volume = 1) {
|
|
1325
|
+
if (!this.shouldAutoplay())
|
|
1343
1326
|
return;
|
|
1344
1327
|
setTimeout(() => {
|
|
1345
1328
|
try {
|
|
@@ -1380,7 +1363,7 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1380
1363
|
catch { }
|
|
1381
1364
|
}
|
|
1382
1365
|
}
|
|
1383
|
-
loadSource(video
|
|
1366
|
+
loadSource(video) {
|
|
1384
1367
|
return new Promise((resolve) => {
|
|
1385
1368
|
if (!this.config) {
|
|
1386
1369
|
return resolve();
|
|
@@ -1390,125 +1373,118 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1390
1373
|
this.hls = undefined;
|
|
1391
1374
|
}
|
|
1392
1375
|
this.resetPlaybackRate(video);
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1376
|
+
if (this.config.video_host === "youtube") {
|
|
1377
|
+
const onReady = () => {
|
|
1378
|
+
this.plyr.off("ready", onReady);
|
|
1379
|
+
this.ensureIframeAutoplayPermissions();
|
|
1380
|
+
const start = this.resolveStartTime(this.config.last_time, this.config.last_percent, this.plyr.duration);
|
|
1381
|
+
this.requestStartTimeSeek(start);
|
|
1382
|
+
if (this.shouldAutoplay()) {
|
|
1383
|
+
this.startAutoplayFlow();
|
|
1384
|
+
}
|
|
1385
|
+
else if (this.shouldBlockIframeAutoplay()) {
|
|
1386
|
+
this.stopRestrictedIframeAutoplay();
|
|
1387
|
+
}
|
|
1388
|
+
parent.postMessage("playerIsReadyToPlay", "*");
|
|
1389
|
+
parent.postMessage("duration:" + this.plyr.duration, "*");
|
|
1390
|
+
console.log("event: current_time " + this.plyr.currentTime);
|
|
1391
|
+
console.log("event: duration " + this.plyr.duration);
|
|
1392
|
+
console.log("event: ready");
|
|
1393
|
+
this.postCastEvent({
|
|
1394
|
+
event: "ready",
|
|
1395
|
+
duration: this.plyr.duration || 0,
|
|
1396
|
+
currentTime: this.plyr.currentTime || 0,
|
|
1397
|
+
});
|
|
1398
|
+
if (this.config.is_live) {
|
|
1399
|
+
this.plyr?.on("playing", function () {
|
|
1400
|
+
console.log("event: playing_live");
|
|
1401
|
+
parent.postMessage("event: playing_live", "*");
|
|
1402
|
+
});
|
|
1403
|
+
}
|
|
1404
|
+
if (this.config.mirror) {
|
|
1405
|
+
setTimeout(() => {
|
|
1406
|
+
document
|
|
1407
|
+
.querySelector(`.plyr__video-embed iframe`)
|
|
1408
|
+
?.classList.add("mirror");
|
|
1409
|
+
}, 1000);
|
|
1410
|
+
}
|
|
1411
|
+
};
|
|
1412
|
+
this.plyr.on("ready", onReady);
|
|
1413
|
+
}
|
|
1414
|
+
if (this.config.video_host === "youtube") {
|
|
1415
|
+
this.plyr.source = {
|
|
1416
|
+
type: "video",
|
|
1417
|
+
sources: [{ src: this.config.video_id, provider: "youtube" }],
|
|
1418
|
+
};
|
|
1419
|
+
}
|
|
1420
|
+
else if (this.config.video_host === "mp4") {
|
|
1421
|
+
this.plyr.source = {
|
|
1422
|
+
type: "video",
|
|
1423
|
+
sources: [{ src: this.config.video_external_id, type: "video/mp4" }],
|
|
1424
|
+
};
|
|
1425
|
+
}
|
|
1426
|
+
else if (this.config.video_host === "hls") {
|
|
1427
|
+
let sourceX = "";
|
|
1428
|
+
try {
|
|
1429
|
+
sourceX = atob(this.config.video_id || "");
|
|
1430
|
+
}
|
|
1431
|
+
catch (e) {
|
|
1432
|
+
sourceX = this.config.video_id || "";
|
|
1433
|
+
}
|
|
1434
|
+
const canNative = video.canPlayType("application/vnd.apple.mpegurl");
|
|
1435
|
+
if (canNative) {
|
|
1436
|
+
this.plyr.source = {
|
|
1437
|
+
type: "video",
|
|
1438
|
+
sources: [{ src: sourceX, type: "application/vnd.apple.mpegurl" }],
|
|
1439
|
+
};
|
|
1440
|
+
const onLoadedMeta = () => {
|
|
1441
|
+
const dur = this.plyr.duration || video.duration || 0;
|
|
1442
|
+
const start = this.resolveStartTime(this.config.last_time, this.config.last_percent, dur);
|
|
1443
|
+
console.log(start);
|
|
1444
|
+
this.requestStartTimeSeek(start, { video });
|
|
1445
|
+
this.startAutoplayFlow(video);
|
|
1446
|
+
video.removeEventListener("loadedmetadata", onLoadedMeta);
|
|
1447
|
+
};
|
|
1448
|
+
video.addEventListener("loadedmetadata", onLoadedMeta);
|
|
1449
|
+
}
|
|
1450
|
+
else if (Hls.isSupported()) {
|
|
1451
|
+
this.hls = new Hls({ enableWorker: true, lowLatencyMode: true });
|
|
1452
|
+
this.hls.attachMedia(video);
|
|
1453
|
+
this.hls.on(Hls.Events.MEDIA_ATTACHED, () => {
|
|
1454
|
+
this.hls.loadSource(sourceX);
|
|
1455
|
+
});
|
|
1456
|
+
this.hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
|
1457
|
+
const dur = video.duration || 0;
|
|
1458
|
+
const start = this.resolveStartTime(this.config.last_time, this.config.last_percent, dur);
|
|
1459
|
+
this.requestStartTimeSeek(start, { video });
|
|
1460
|
+
this.startAutoplayFlow(video);
|
|
1461
|
+
});
|
|
1462
|
+
this.hls.on(Hls.Events.ERROR, (_evt, data) => {
|
|
1463
|
+
if (data?.fatal) {
|
|
1464
|
+
switch (data.type) {
|
|
1465
|
+
case Hls.ErrorTypes.NETWORK_ERROR:
|
|
1466
|
+
this.hls.startLoad();
|
|
1467
|
+
break;
|
|
1468
|
+
case Hls.ErrorTypes.MEDIA_ERROR:
|
|
1469
|
+
this.hls.recoverMediaError();
|
|
1470
|
+
break;
|
|
1471
|
+
default:
|
|
1472
|
+
try {
|
|
1473
|
+
this.hls.destroy();
|
|
1474
|
+
}
|
|
1475
|
+
catch { }
|
|
1476
|
+
break;
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
});
|
|
1480
|
+
}
|
|
1481
|
+
else {
|
|
1482
|
+
this.plyr.source = { type: "video", sources: [{ src: sourceX }] };
|
|
1483
|
+
}
|
|
1405
1484
|
}
|
|
1406
1485
|
resolve();
|
|
1407
1486
|
});
|
|
1408
1487
|
}
|
|
1409
|
-
loadYoutubeSource(autoplayConfig) {
|
|
1410
|
-
const onReady = () => {
|
|
1411
|
-
this.plyr.off("ready", onReady);
|
|
1412
|
-
if (autoplayConfig.enabled) {
|
|
1413
|
-
this.startAutoplayFlow(undefined, autoplayConfig);
|
|
1414
|
-
}
|
|
1415
|
-
else if (autoplayConfig.blockIframe) {
|
|
1416
|
-
this.stopRestrictedIframeAutoplay(autoplayConfig);
|
|
1417
|
-
}
|
|
1418
|
-
parent.postMessage("playerIsReadyToPlay", "*");
|
|
1419
|
-
parent.postMessage("duration:" + this.plyr.duration, "*");
|
|
1420
|
-
console.log("event: current_time " + this.plyr.currentTime);
|
|
1421
|
-
console.log("event: duration " + this.plyr.duration);
|
|
1422
|
-
console.log("event: ready");
|
|
1423
|
-
this.postCastEvent({
|
|
1424
|
-
event: "ready",
|
|
1425
|
-
duration: this.plyr.duration || 0,
|
|
1426
|
-
currentTime: this.plyr.currentTime || 0,
|
|
1427
|
-
});
|
|
1428
|
-
if (this.isLivePlayback()) {
|
|
1429
|
-
this.ensureIframeAutoplayPermissions();
|
|
1430
|
-
this.applyStartTimeFromConfig(this.plyr.duration);
|
|
1431
|
-
this.plyr?.on("playing", function () {
|
|
1432
|
-
console.log("event: playing_live");
|
|
1433
|
-
parent.postMessage("event: playing_live", "*");
|
|
1434
|
-
});
|
|
1435
|
-
}
|
|
1436
|
-
if (this.config?.mirror) {
|
|
1437
|
-
setTimeout(() => {
|
|
1438
|
-
document
|
|
1439
|
-
.querySelector(`.plyr__video-embed iframe`)
|
|
1440
|
-
?.classList.add("mirror");
|
|
1441
|
-
}, 1000);
|
|
1442
|
-
}
|
|
1443
|
-
};
|
|
1444
|
-
this.plyr.on("ready", onReady);
|
|
1445
|
-
this.plyr.source = {
|
|
1446
|
-
type: "video",
|
|
1447
|
-
sources: [{ src: this.config?.video_id, provider: "youtube" }],
|
|
1448
|
-
};
|
|
1449
|
-
}
|
|
1450
|
-
loadMp4Source() {
|
|
1451
|
-
this.plyr.source = {
|
|
1452
|
-
type: "video",
|
|
1453
|
-
sources: [{ src: this.config?.video_external_id, type: "video/mp4" }],
|
|
1454
|
-
};
|
|
1455
|
-
}
|
|
1456
|
-
loadHlsSource(video, autoplayConfig) {
|
|
1457
|
-
let sourceX = "";
|
|
1458
|
-
try {
|
|
1459
|
-
sourceX = atob(this.config?.video_id || "");
|
|
1460
|
-
}
|
|
1461
|
-
catch (e) {
|
|
1462
|
-
sourceX = this.config?.video_id || "";
|
|
1463
|
-
}
|
|
1464
|
-
const canNative = video.canPlayType("application/vnd.apple.mpegurl");
|
|
1465
|
-
if (canNative) {
|
|
1466
|
-
this.plyr.source = {
|
|
1467
|
-
type: "video",
|
|
1468
|
-
sources: [{ src: sourceX, type: "application/vnd.apple.mpegurl" }],
|
|
1469
|
-
};
|
|
1470
|
-
const onLoadedMeta = () => {
|
|
1471
|
-
const dur = this.plyr.duration || video.duration || 0;
|
|
1472
|
-
console.log(this.applyStartTimeFromConfig(dur, video));
|
|
1473
|
-
this.startAutoplayFlow(video, autoplayConfig);
|
|
1474
|
-
video.removeEventListener("loadedmetadata", onLoadedMeta);
|
|
1475
|
-
};
|
|
1476
|
-
video.addEventListener("loadedmetadata", onLoadedMeta);
|
|
1477
|
-
return;
|
|
1478
|
-
}
|
|
1479
|
-
if (Hls.isSupported()) {
|
|
1480
|
-
this.hls = new Hls({ enableWorker: true, lowLatencyMode: true });
|
|
1481
|
-
this.hls.attachMedia(video);
|
|
1482
|
-
this.hls.on(Hls.Events.MEDIA_ATTACHED, () => {
|
|
1483
|
-
this.hls.loadSource(sourceX);
|
|
1484
|
-
});
|
|
1485
|
-
this.hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
|
1486
|
-
const dur = video.duration || 0;
|
|
1487
|
-
this.applyStartTimeFromConfig(dur, video);
|
|
1488
|
-
this.startAutoplayFlow(video, autoplayConfig);
|
|
1489
|
-
});
|
|
1490
|
-
this.hls.on(Hls.Events.ERROR, (_evt, data) => {
|
|
1491
|
-
if (data?.fatal) {
|
|
1492
|
-
switch (data.type) {
|
|
1493
|
-
case Hls.ErrorTypes.NETWORK_ERROR:
|
|
1494
|
-
this.hls.startLoad();
|
|
1495
|
-
break;
|
|
1496
|
-
case Hls.ErrorTypes.MEDIA_ERROR:
|
|
1497
|
-
this.hls.recoverMediaError();
|
|
1498
|
-
break;
|
|
1499
|
-
default:
|
|
1500
|
-
try {
|
|
1501
|
-
this.hls.destroy();
|
|
1502
|
-
}
|
|
1503
|
-
catch { }
|
|
1504
|
-
break;
|
|
1505
|
-
}
|
|
1506
|
-
}
|
|
1507
|
-
});
|
|
1508
|
-
return;
|
|
1509
|
-
}
|
|
1510
|
-
this.plyr.source = { type: "video", sources: [{ src: sourceX }] };
|
|
1511
|
-
}
|
|
1512
1488
|
resolveStartTime(last_time, last_percent, duration, opts = {}) {
|
|
1513
1489
|
if (this.shouldResetProgressToBeginning()) {
|
|
1514
1490
|
return 0;
|
|
@@ -1558,11 +1534,6 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1558
1534
|
}
|
|
1559
1535
|
return 0;
|
|
1560
1536
|
}
|
|
1561
|
-
applyStartTimeFromConfig(duration, video) {
|
|
1562
|
-
const start = this.resolveStartTime(this.config?.last_time, this.config?.last_percent, duration);
|
|
1563
|
-
this.requestStartTimeSeek(start, { video });
|
|
1564
|
-
return start;
|
|
1565
|
-
}
|
|
1566
1537
|
postCastEvent(payload) {
|
|
1567
1538
|
parent.postMessage(JSON.stringify(payload), "*");
|
|
1568
1539
|
}
|
|
@@ -1608,8 +1579,8 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1608
1579
|
}
|
|
1609
1580
|
if (this.recommendationBlockerActiveZone) {
|
|
1610
1581
|
try {
|
|
1611
|
-
this.recommendationBlockerActiveZone.removeEventListener("pointerdown", this.
|
|
1612
|
-
this.recommendationBlockerActiveZone.removeEventListener("click", this.
|
|
1582
|
+
this.recommendationBlockerActiveZone.removeEventListener("pointerdown", this.onTopBlockerPointerDown);
|
|
1583
|
+
this.recommendationBlockerActiveZone.removeEventListener("click", this.onRecommendationBlockerClick);
|
|
1613
1584
|
}
|
|
1614
1585
|
catch { }
|
|
1615
1586
|
}
|
|
@@ -1617,8 +1588,8 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1617
1588
|
this.recommendationBlockerActiveZone = null;
|
|
1618
1589
|
if (this.topClickBlocker?.parentElement) {
|
|
1619
1590
|
try {
|
|
1620
|
-
this.topClickBlocker.removeEventListener("pointerdown", this.
|
|
1621
|
-
this.topClickBlocker.removeEventListener("click", this.
|
|
1591
|
+
this.topClickBlocker.removeEventListener("pointerdown", this.onTopBlockerPointerDown);
|
|
1592
|
+
this.topClickBlocker.removeEventListener("click", this.onTopBlockerClick);
|
|
1622
1593
|
this.topClickBlocker.parentElement.removeChild(this.topClickBlocker);
|
|
1623
1594
|
}
|
|
1624
1595
|
catch { }
|