@edm-webplayer/webplayer-angular 0.1.90 → 0.1.92
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,32 +90,13 @@ class PlyrPlayerComponent {
|
|
|
90
90
|
liveInteractionBlocker;
|
|
91
91
|
iosFullscreenCleanup;
|
|
92
92
|
pendingStartTime;
|
|
93
|
+
autoplayConfig;
|
|
93
94
|
onResize = () => {
|
|
94
95
|
this.updateRecommendationBlockerSafeZone();
|
|
95
96
|
};
|
|
96
|
-
|
|
97
|
-
if (event)
|
|
98
|
-
|
|
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) => {
|
|
97
|
+
consumeEvent = (event) => {
|
|
98
|
+
if (!event)
|
|
99
|
+
return;
|
|
119
100
|
try {
|
|
120
101
|
event.preventDefault();
|
|
121
102
|
}
|
|
@@ -195,6 +176,9 @@ class PlyrPlayerComponent {
|
|
|
195
176
|
}
|
|
196
177
|
return Math.max(this.overlayInteractionGapPx, this.getControlsSafeZone());
|
|
197
178
|
}
|
|
179
|
+
getOverlayGuardHeight() {
|
|
180
|
+
return Math.max(48, Math.ceil(this.getOverlaySafeZone()));
|
|
181
|
+
}
|
|
198
182
|
getOpenMenuHeight() {
|
|
199
183
|
const container = this.plyr?.elements?.container;
|
|
200
184
|
if (!container)
|
|
@@ -302,28 +286,32 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
302
286
|
return null;
|
|
303
287
|
const blocker = this.document.createElement("div");
|
|
304
288
|
blocker.className = "plyr-recommendation-blocker";
|
|
305
|
-
blocker.style
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
289
|
+
Object.assign(blocker.style, {
|
|
290
|
+
position: "absolute",
|
|
291
|
+
top: "0",
|
|
292
|
+
left: "0",
|
|
293
|
+
width: "100%",
|
|
294
|
+
height: "100%",
|
|
295
|
+
zIndex: "9",
|
|
296
|
+
pointerEvents: "none",
|
|
297
|
+
display: "none",
|
|
298
|
+
background: "rgba(0,0,0,0)",
|
|
299
|
+
cursor: "pointer",
|
|
300
|
+
});
|
|
315
301
|
const activeZone = this.document.createElement("div");
|
|
316
302
|
activeZone.className = "plyr-recommendation-blocker__zone";
|
|
317
|
-
activeZone.style
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
303
|
+
Object.assign(activeZone.style, {
|
|
304
|
+
position: "absolute",
|
|
305
|
+
top: "0",
|
|
306
|
+
left: "0",
|
|
307
|
+
width: "100%",
|
|
308
|
+
bottom: `20px`,
|
|
309
|
+
pointerEvents: "auto",
|
|
310
|
+
background: "rgba(0,0,0,0)",
|
|
311
|
+
cursor: "pointer",
|
|
312
|
+
});
|
|
313
|
+
activeZone.addEventListener("pointerdown", this.consumeEvent);
|
|
314
|
+
activeZone.addEventListener("click", this.consumeEvent);
|
|
327
315
|
blocker.appendChild(activeZone);
|
|
328
316
|
wrapper.appendChild(blocker);
|
|
329
317
|
this.recommendationBlocker = blocker;
|
|
@@ -363,18 +351,20 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
363
351
|
}
|
|
364
352
|
const blocker = this.document.createElement("div");
|
|
365
353
|
blocker.className = "plyr-top-click-blocker";
|
|
366
|
-
blocker.style
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
354
|
+
Object.assign(blocker.style, {
|
|
355
|
+
position: "absolute",
|
|
356
|
+
top: "0",
|
|
357
|
+
left: "0",
|
|
358
|
+
right: "0",
|
|
359
|
+
width: "100%",
|
|
360
|
+
zIndex: "12",
|
|
361
|
+
pointerEvents: "auto",
|
|
362
|
+
background: "rgba(0,0,0,0)",
|
|
363
|
+
touchAction: "none",
|
|
364
|
+
cursor: "default",
|
|
365
|
+
});
|
|
366
|
+
blocker.addEventListener("pointerdown", this.consumeEvent);
|
|
367
|
+
blocker.addEventListener("click", this.consumeEvent);
|
|
378
368
|
wrapper.appendChild(blocker);
|
|
379
369
|
this.topClickBlocker = blocker;
|
|
380
370
|
this.updateTopClickBlockerSafeZone();
|
|
@@ -382,8 +372,7 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
382
372
|
updateTopClickBlockerSafeZone() {
|
|
383
373
|
if (!this.topClickBlocker)
|
|
384
374
|
return;
|
|
385
|
-
|
|
386
|
-
this.topClickBlocker.style.height = `${height}px`;
|
|
375
|
+
this.topClickBlocker.style.height = `${this.getOverlayGuardHeight()}px`;
|
|
387
376
|
this.topClickBlocker.style.pointerEvents = this.overlayBlockAll
|
|
388
377
|
? "auto"
|
|
389
378
|
: "none";
|
|
@@ -501,12 +490,6 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
501
490
|
isIframeProvider() {
|
|
502
491
|
return this.config?.video_host === "youtube";
|
|
503
492
|
}
|
|
504
|
-
shouldDisableAutoplayForIOS() {
|
|
505
|
-
if (this.config?.is_live) {
|
|
506
|
-
return false;
|
|
507
|
-
}
|
|
508
|
-
return this.isIOSContext();
|
|
509
|
-
}
|
|
510
493
|
shouldResetProgressToBeginning() {
|
|
511
494
|
const host = this.config?.video_host;
|
|
512
495
|
if (host !== "youtube") {
|
|
@@ -594,59 +577,21 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
594
577
|
}
|
|
595
578
|
this.liveInteractionBlocker = null;
|
|
596
579
|
}
|
|
597
|
-
|
|
598
|
-
return !!
|
|
599
|
-
}
|
|
600
|
-
// Debug: disable qualquer tentativa de autoplay em todas as plataformas
|
|
601
|
-
isAutoplayDisabledForDebug() {
|
|
602
|
-
return true;
|
|
603
|
-
}
|
|
604
|
-
shouldPreventAutoplayFromResume() {
|
|
605
|
-
return this.isIOSContext() && this.hasResumeProgress();
|
|
606
|
-
}
|
|
607
|
-
hasResumeProgress() {
|
|
608
|
-
const rawTime = Number(this.config?.last_time);
|
|
609
|
-
if (Number.isFinite(rawTime) && rawTime > 0.5) {
|
|
610
|
-
return true;
|
|
611
|
-
}
|
|
612
|
-
const rawPercent = Number(this.config?.last_percent);
|
|
613
|
-
if (Number.isFinite(rawPercent) && rawPercent > 0.01) {
|
|
614
|
-
return true;
|
|
615
|
-
}
|
|
616
|
-
return false;
|
|
617
|
-
}
|
|
618
|
-
shouldAutoplay() {
|
|
619
|
-
if (this.isAutoplayDisabledForDebug()) {
|
|
620
|
-
return false;
|
|
621
|
-
}
|
|
622
|
-
if (this.config?.is_live) {
|
|
623
|
-
return true;
|
|
624
|
-
}
|
|
625
|
-
if (this.shouldPreventAutoplayFromResume()) {
|
|
626
|
-
return false;
|
|
627
|
-
}
|
|
628
|
-
if (this.shouldDisableAutoplayForIOS()) {
|
|
629
|
-
return false;
|
|
630
|
-
}
|
|
631
|
-
return this.wantsAutoplay();
|
|
632
|
-
}
|
|
633
|
-
requiresMutedAutoplay() {
|
|
634
|
-
if (this.isAutoplayDisabledForDebug()) {
|
|
635
|
-
return false;
|
|
636
|
-
}
|
|
637
|
-
if (this.config?.is_live && this.isIOSDevice()) {
|
|
638
|
-
return true;
|
|
639
|
-
}
|
|
640
|
-
if (!this.isIOSDevice() || this.shouldDisableAutoplayForIOS()) {
|
|
641
|
-
return false;
|
|
642
|
-
}
|
|
643
|
-
return this.wantsAutoplay();
|
|
644
|
-
}
|
|
645
|
-
shouldBlockIframeAutoplay() {
|
|
646
|
-
return this.shouldDisableAutoplayForIOS();
|
|
580
|
+
isLivePlayback() {
|
|
581
|
+
return !!this.config?.is_live;
|
|
647
582
|
}
|
|
648
|
-
|
|
649
|
-
|
|
583
|
+
getAutoplayConfig() {
|
|
584
|
+
const isLive = this.isLivePlayback();
|
|
585
|
+
const explicitAutoplay = !!this.config?.autoplay;
|
|
586
|
+
// No iOS autoplay para VOD; só permite live ou autoplay fora do contexto iOS
|
|
587
|
+
const enabled = isLive || (explicitAutoplay && !this.isIOSContext());
|
|
588
|
+
const startMuted = enabled && this.isIOSDevice();
|
|
589
|
+
const blockIframe = !isLive && this.isIOSContext();
|
|
590
|
+
this.autoplayConfig = { enabled, startMuted, blockIframe };
|
|
591
|
+
return this.autoplayConfig;
|
|
592
|
+
}
|
|
593
|
+
stopRestrictedIframeAutoplay(autoplayConfig = this.autoplayConfig ?? this.getAutoplayConfig()) {
|
|
594
|
+
if (!autoplayConfig.blockIframe) {
|
|
650
595
|
return;
|
|
651
596
|
}
|
|
652
597
|
this.clearAutoplayUnlockListener();
|
|
@@ -725,7 +670,8 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
725
670
|
const media = target ?? this.videoRef?.nativeElement ?? null;
|
|
726
671
|
const prevVideoMuted = media?.muted ?? false;
|
|
727
672
|
const prevPlyrMuted = !!this.plyr?.muted;
|
|
728
|
-
const
|
|
673
|
+
const autoplayConfig = this.autoplayConfig ?? this.getAutoplayConfig();
|
|
674
|
+
const shouldForceUnmute = !autoplayConfig.enabled;
|
|
729
675
|
try {
|
|
730
676
|
if (media) {
|
|
731
677
|
media.muted = true;
|
|
@@ -765,12 +711,11 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
765
711
|
this.interactionUnmuteCleanup = undefined;
|
|
766
712
|
}
|
|
767
713
|
}
|
|
768
|
-
ensureAutoplayUnlockListener() {
|
|
769
|
-
if (typeof window === "undefined" ||
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
this.isAutoplayDisabledForDebug()) {
|
|
714
|
+
ensureAutoplayUnlockListener(autoplayConfig = this.autoplayConfig ?? this.getAutoplayConfig()) {
|
|
715
|
+
if (typeof window === "undefined" || this.interactionUnmuteCleanup) {
|
|
716
|
+
return;
|
|
717
|
+
}
|
|
718
|
+
if (!autoplayConfig.enabled) {
|
|
774
719
|
return;
|
|
775
720
|
}
|
|
776
721
|
const capture = true;
|
|
@@ -778,6 +723,7 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
778
723
|
this.setPlayerMutedState(false);
|
|
779
724
|
try {
|
|
780
725
|
this.plyr?.play();
|
|
726
|
+
console.log("Autoplay unlocked via user interaction");
|
|
781
727
|
}
|
|
782
728
|
catch { }
|
|
783
729
|
this.clearAutoplayUnlockListener();
|
|
@@ -822,9 +768,11 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
822
768
|
iframe.setAttribute("allowfullscreen", "true");
|
|
823
769
|
iframe.setAttribute("data-keepplaying", "true");
|
|
824
770
|
}
|
|
825
|
-
scheduleUserInteractionUnmute(video) {
|
|
826
|
-
|
|
827
|
-
|
|
771
|
+
scheduleUserInteractionUnmute(video, autoplayConfig = this.autoplayConfig ?? this.getAutoplayConfig()) {
|
|
772
|
+
if (!autoplayConfig.enabled)
|
|
773
|
+
return;
|
|
774
|
+
this.unmuteAfterDelay(video || undefined, undefined, 1, autoplayConfig);
|
|
775
|
+
this.ensureAutoplayUnlockListener(autoplayConfig);
|
|
828
776
|
}
|
|
829
777
|
requestStartTimeSeek(start, opts = {}) {
|
|
830
778
|
if (!(start > 0)) {
|
|
@@ -936,11 +884,8 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
936
884
|
}
|
|
937
885
|
return null;
|
|
938
886
|
}
|
|
939
|
-
startAutoplayFlow(video) {
|
|
940
|
-
if (!this.
|
|
941
|
-
!this.plyr ||
|
|
942
|
-
this.shouldPreventAutoplayFromResume() ||
|
|
943
|
-
this.isAutoplayDisabledForDebug())
|
|
887
|
+
startAutoplayFlow(video, autoplayConfig = this.autoplayConfig ?? this.getAutoplayConfig()) {
|
|
888
|
+
if (!autoplayConfig.enabled || !this.plyr)
|
|
944
889
|
return;
|
|
945
890
|
if (this.deferUntilStartTimeSettles(() => this.startAutoplayFlow(video))) {
|
|
946
891
|
return;
|
|
@@ -951,7 +896,7 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
951
896
|
let playResult;
|
|
952
897
|
try {
|
|
953
898
|
playResult = this.plyr.play();
|
|
954
|
-
this.forceIframeAutoplayFallback();
|
|
899
|
+
this.forceIframeAutoplayFallback(autoplayConfig);
|
|
955
900
|
}
|
|
956
901
|
catch (error) {
|
|
957
902
|
if (!muted) {
|
|
@@ -967,7 +912,7 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
967
912
|
}
|
|
968
913
|
catch { }
|
|
969
914
|
}
|
|
970
|
-
this.scheduleUserInteractionUnmute(media);
|
|
915
|
+
this.scheduleUserInteractionUnmute(media, autoplayConfig);
|
|
971
916
|
return;
|
|
972
917
|
}
|
|
973
918
|
if (playResult &&
|
|
@@ -986,29 +931,26 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
986
931
|
}
|
|
987
932
|
catch { }
|
|
988
933
|
}
|
|
989
|
-
this.scheduleUserInteractionUnmute(media);
|
|
934
|
+
this.scheduleUserInteractionUnmute(media, autoplayConfig);
|
|
990
935
|
});
|
|
991
936
|
return;
|
|
992
937
|
}
|
|
993
938
|
if (muted) {
|
|
994
|
-
this.scheduleUserInteractionUnmute(media);
|
|
939
|
+
this.scheduleUserInteractionUnmute(media, autoplayConfig);
|
|
995
940
|
}
|
|
996
941
|
else {
|
|
997
942
|
this.clearAutoplayUnlockListener();
|
|
998
943
|
}
|
|
999
944
|
};
|
|
1000
|
-
if (
|
|
945
|
+
if (autoplayConfig.startMuted) {
|
|
1001
946
|
tryPlay(true);
|
|
1002
947
|
}
|
|
1003
948
|
else {
|
|
1004
949
|
tryPlay(false);
|
|
1005
950
|
}
|
|
1006
951
|
}
|
|
1007
|
-
forceIframeAutoplayFallback() {
|
|
1008
|
-
if (!this.
|
|
1009
|
-
!this.isIframeProvider() ||
|
|
1010
|
-
this.shouldPreventAutoplayFromResume() ||
|
|
1011
|
-
this.isAutoplayDisabledForDebug()) {
|
|
952
|
+
forceIframeAutoplayFallback(autoplayConfig = this.autoplayConfig ?? this.getAutoplayConfig()) {
|
|
953
|
+
if (!this.isLivePlayback() || !autoplayConfig.enabled || !this.isIframeProvider()) {
|
|
1012
954
|
return;
|
|
1013
955
|
}
|
|
1014
956
|
const embed = this.plyr?.embed;
|
|
@@ -1030,71 +972,79 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1030
972
|
return;
|
|
1031
973
|
}
|
|
1032
974
|
if (this.isTouchDevice()) {
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
const clearHideTimeout = () => {
|
|
1036
|
-
if (hideTimeout) {
|
|
1037
|
-
clearTimeout(hideTimeout);
|
|
1038
|
-
hideTimeout = null;
|
|
1039
|
-
}
|
|
1040
|
-
};
|
|
1041
|
-
const showControls = () => {
|
|
1042
|
-
container.classList.remove("plyr--auto-hide-controls");
|
|
1043
|
-
};
|
|
1044
|
-
const hideControls = () => {
|
|
1045
|
-
if (this.plyr?.playing) {
|
|
1046
|
-
container.classList.add("plyr--auto-hide-controls");
|
|
1047
|
-
}
|
|
1048
|
-
};
|
|
1049
|
-
const scheduleHide = () => {
|
|
1050
|
-
clearHideTimeout();
|
|
1051
|
-
if (!this.plyr?.playing)
|
|
1052
|
-
return;
|
|
1053
|
-
hideTimeout = setTimeout(() => hideControls(), HIDE_DELAY);
|
|
1054
|
-
};
|
|
1055
|
-
const onPlay = () => {
|
|
1056
|
-
showControls();
|
|
1057
|
-
this.overlayBlockAll = false;
|
|
1058
|
-
};
|
|
1059
|
-
const onPause = () => {
|
|
1060
|
-
clearHideTimeout();
|
|
1061
|
-
showControls();
|
|
1062
|
-
this.overlayBlockAll = true;
|
|
1063
|
-
this.updateTopClickBlockerSafeZone();
|
|
1064
|
-
this.topClickBlocker?.setAttribute("data-state", "paused");
|
|
1065
|
-
if (this.shouldEmitEndedOnPause()) {
|
|
1066
|
-
this.endedLoggedOnPause = true;
|
|
1067
|
-
console.log("event: ended");
|
|
1068
|
-
}
|
|
1069
|
-
};
|
|
1070
|
-
const onEnded = () => {
|
|
1071
|
-
clearHideTimeout();
|
|
1072
|
-
showControls();
|
|
1073
|
-
this.overlayBlockAll = true;
|
|
1074
|
-
this.updateTopClickBlockerSafeZone();
|
|
1075
|
-
this.topClickBlocker?.setAttribute("data-state", "ended");
|
|
1076
|
-
};
|
|
1077
|
-
const onUserInteraction = () => {
|
|
1078
|
-
showControls();
|
|
1079
|
-
scheduleHide();
|
|
1080
|
-
};
|
|
1081
|
-
this.plyr?.on?.("play", onPlay);
|
|
1082
|
-
this.plyr?.on?.("pause", onPause);
|
|
1083
|
-
this.plyr?.on?.("ended", onEnded);
|
|
1084
|
-
container.addEventListener("touchstart", onUserInteraction);
|
|
1085
|
-
container.addEventListener("click", onUserInteraction);
|
|
1086
|
-
this.controlsVisibilityCleanup = () => {
|
|
1087
|
-
clearHideTimeout();
|
|
1088
|
-
this.plyr?.off?.("play", onPlay);
|
|
1089
|
-
this.plyr?.off?.("pause", onPause);
|
|
1090
|
-
this.plyr?.off?.("ended", onEnded);
|
|
1091
|
-
container.removeEventListener("touchstart", onUserInteraction);
|
|
1092
|
-
container.removeEventListener("click", onUserInteraction);
|
|
1093
|
-
container.classList.remove("plyr--auto-hide-controls");
|
|
1094
|
-
};
|
|
1095
|
-
onPlay();
|
|
975
|
+
this.controlsVisibilityCleanup =
|
|
976
|
+
this.setupTouchControlsVisibility(container);
|
|
1096
977
|
return;
|
|
1097
978
|
}
|
|
979
|
+
this.controlsVisibilityCleanup =
|
|
980
|
+
this.setupDesktopControlsVisibility(container);
|
|
981
|
+
}
|
|
982
|
+
setupTouchControlsVisibility(container) {
|
|
983
|
+
const HIDE_DELAY = 2000;
|
|
984
|
+
let hideTimeout = null;
|
|
985
|
+
const clearHideTimeout = () => {
|
|
986
|
+
if (hideTimeout) {
|
|
987
|
+
clearTimeout(hideTimeout);
|
|
988
|
+
hideTimeout = null;
|
|
989
|
+
}
|
|
990
|
+
};
|
|
991
|
+
const showControls = () => {
|
|
992
|
+
container.classList.remove("plyr--auto-hide-controls");
|
|
993
|
+
};
|
|
994
|
+
const hideControls = () => {
|
|
995
|
+
if (this.plyr?.playing) {
|
|
996
|
+
container.classList.add("plyr--auto-hide-controls");
|
|
997
|
+
}
|
|
998
|
+
};
|
|
999
|
+
const scheduleHide = () => {
|
|
1000
|
+
clearHideTimeout();
|
|
1001
|
+
if (!this.plyr?.playing)
|
|
1002
|
+
return;
|
|
1003
|
+
hideTimeout = setTimeout(() => hideControls(), HIDE_DELAY);
|
|
1004
|
+
};
|
|
1005
|
+
const onPlay = () => {
|
|
1006
|
+
showControls();
|
|
1007
|
+
this.overlayBlockAll = false;
|
|
1008
|
+
};
|
|
1009
|
+
const onPause = () => {
|
|
1010
|
+
clearHideTimeout();
|
|
1011
|
+
showControls();
|
|
1012
|
+
this.overlayBlockAll = true;
|
|
1013
|
+
this.updateTopClickBlockerSafeZone();
|
|
1014
|
+
this.topClickBlocker?.setAttribute("data-state", "paused");
|
|
1015
|
+
if (this.shouldEmitEndedOnPause()) {
|
|
1016
|
+
this.endedLoggedOnPause = true;
|
|
1017
|
+
console.log("event: ended");
|
|
1018
|
+
}
|
|
1019
|
+
};
|
|
1020
|
+
const onEnded = () => {
|
|
1021
|
+
clearHideTimeout();
|
|
1022
|
+
showControls();
|
|
1023
|
+
this.overlayBlockAll = true;
|
|
1024
|
+
this.updateTopClickBlockerSafeZone();
|
|
1025
|
+
this.topClickBlocker?.setAttribute("data-state", "ended");
|
|
1026
|
+
};
|
|
1027
|
+
const onUserInteraction = () => {
|
|
1028
|
+
showControls();
|
|
1029
|
+
scheduleHide();
|
|
1030
|
+
};
|
|
1031
|
+
this.plyr?.on?.("play", onPlay);
|
|
1032
|
+
this.plyr?.on?.("pause", onPause);
|
|
1033
|
+
this.plyr?.on?.("ended", onEnded);
|
|
1034
|
+
container.addEventListener("touchstart", onUserInteraction);
|
|
1035
|
+
container.addEventListener("click", onUserInteraction);
|
|
1036
|
+
onPlay();
|
|
1037
|
+
return () => {
|
|
1038
|
+
clearHideTimeout();
|
|
1039
|
+
this.plyr?.off?.("play", onPlay);
|
|
1040
|
+
this.plyr?.off?.("pause", onPause);
|
|
1041
|
+
this.plyr?.off?.("ended", onEnded);
|
|
1042
|
+
container.removeEventListener("touchstart", onUserInteraction);
|
|
1043
|
+
container.removeEventListener("click", onUserInteraction);
|
|
1044
|
+
container.classList.remove("plyr--auto-hide-controls");
|
|
1045
|
+
};
|
|
1046
|
+
}
|
|
1047
|
+
setupDesktopControlsVisibility(container) {
|
|
1098
1048
|
let hovering = false;
|
|
1099
1049
|
const toggleClass = () => {
|
|
1100
1050
|
const playing = !!this.plyr?.playing;
|
|
@@ -1132,7 +1082,7 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1132
1082
|
container.addEventListener("focusin", onFocusIn);
|
|
1133
1083
|
container.addEventListener("focusout", onFocusOut);
|
|
1134
1084
|
toggleClass();
|
|
1135
|
-
|
|
1085
|
+
return () => {
|
|
1136
1086
|
this.plyr?.off?.("play", onPlay);
|
|
1137
1087
|
this.plyr?.off?.("pause", onPause);
|
|
1138
1088
|
this.plyr?.off?.("ended", onEnded);
|
|
@@ -1171,8 +1121,8 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1171
1121
|
const speedOptions = [1, 1.25, 1.5, 2];
|
|
1172
1122
|
const locale = this.resolveLocale();
|
|
1173
1123
|
const captionsLanguage = this.resolveCaptionsLanguage(locale) ?? "pt";
|
|
1174
|
-
const
|
|
1175
|
-
const startMuted =
|
|
1124
|
+
const autoplayConfig = this.getAutoplayConfig();
|
|
1125
|
+
const { enabled: shouldAutoplay, startMuted } = autoplayConfig;
|
|
1176
1126
|
try {
|
|
1177
1127
|
this.videoRef.nativeElement.muted = startMuted;
|
|
1178
1128
|
}
|
|
@@ -1183,10 +1133,10 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1183
1133
|
}
|
|
1184
1134
|
catch { }
|
|
1185
1135
|
try {
|
|
1186
|
-
|
|
1136
|
+
this.videoRef.nativeElement.autoplay = shouldAutoplay;
|
|
1187
1137
|
}
|
|
1188
1138
|
catch { }
|
|
1189
|
-
const isLive =
|
|
1139
|
+
const isLive = this.isLivePlayback();
|
|
1190
1140
|
const youtubePlayerVars = {
|
|
1191
1141
|
rel: 0,
|
|
1192
1142
|
modestbranding: 1,
|
|
@@ -1264,13 +1214,13 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1264
1214
|
window.removeEventListener("resize", this.onResize);
|
|
1265
1215
|
window.addEventListener("resize", this.onResize);
|
|
1266
1216
|
this.bindProgressEvents();
|
|
1267
|
-
this.loadSource(this.videoRef.nativeElement).then(() => {
|
|
1217
|
+
this.loadSource(this.videoRef.nativeElement, autoplayConfig).then(() => {
|
|
1268
1218
|
this.setupStartTime();
|
|
1269
1219
|
});
|
|
1270
1220
|
// Dispara o evento ready quando o player estiver pronto
|
|
1271
1221
|
this.plyr.on("ready", () => {
|
|
1272
|
-
|
|
1273
|
-
this.stopRestrictedIframeAutoplay();
|
|
1222
|
+
this.ensureIframeAutoplayPermissions();
|
|
1223
|
+
this.stopRestrictedIframeAutoplay(autoplayConfig);
|
|
1274
1224
|
this.ready.emit();
|
|
1275
1225
|
});
|
|
1276
1226
|
}
|
|
@@ -1362,8 +1312,8 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1362
1312
|
this.toggleRecommendationBlocker(true);
|
|
1363
1313
|
});
|
|
1364
1314
|
}
|
|
1365
|
-
unmuteAfterDelay(video, delayMs = 2000, volume = 1) {
|
|
1366
|
-
if (!
|
|
1315
|
+
unmuteAfterDelay(video, delayMs = 2000, volume = 1, autoplayConfig = this.autoplayConfig ?? this.getAutoplayConfig()) {
|
|
1316
|
+
if (!autoplayConfig.enabled)
|
|
1367
1317
|
return;
|
|
1368
1318
|
setTimeout(() => {
|
|
1369
1319
|
try {
|
|
@@ -1404,7 +1354,7 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1404
1354
|
catch { }
|
|
1405
1355
|
}
|
|
1406
1356
|
}
|
|
1407
|
-
loadSource(video) {
|
|
1357
|
+
loadSource(video, autoplayConfig) {
|
|
1408
1358
|
return new Promise((resolve) => {
|
|
1409
1359
|
if (!this.config) {
|
|
1410
1360
|
return resolve();
|
|
@@ -1414,124 +1364,125 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1414
1364
|
this.hls = undefined;
|
|
1415
1365
|
}
|
|
1416
1366
|
this.resetPlaybackRate(video);
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
if (this.shouldPreventAutoplayFromResume() || this.isAutoplayDisabledForDebug()) {
|
|
1430
|
-
this.stopRestrictedIframeAutoplay();
|
|
1431
|
-
}
|
|
1432
|
-
if (this.shouldPreventAutoplayFromResume()) {
|
|
1433
|
-
this.stopRestrictedIframeAutoplay();
|
|
1434
|
-
}
|
|
1435
|
-
parent.postMessage("playerIsReadyToPlay", "*");
|
|
1436
|
-
parent.postMessage("duration:" + this.plyr.duration, "*");
|
|
1437
|
-
console.log("event: current_time " + this.plyr.currentTime);
|
|
1438
|
-
console.log("event: duration " + this.plyr.duration);
|
|
1439
|
-
console.log("event: ready");
|
|
1440
|
-
this.postCastEvent({
|
|
1441
|
-
event: "ready",
|
|
1442
|
-
duration: this.plyr.duration || 0,
|
|
1443
|
-
currentTime: this.plyr.currentTime || 0,
|
|
1444
|
-
});
|
|
1445
|
-
if (this.config.is_live) {
|
|
1446
|
-
this.plyr?.on("playing", function () {
|
|
1447
|
-
console.log("event: playing_live");
|
|
1448
|
-
parent.postMessage("event: playing_live", "*");
|
|
1449
|
-
});
|
|
1450
|
-
}
|
|
1451
|
-
if (this.config.mirror) {
|
|
1452
|
-
setTimeout(() => {
|
|
1453
|
-
document
|
|
1454
|
-
.querySelector(`.plyr__video-embed iframe`)
|
|
1455
|
-
?.classList.add("mirror");
|
|
1456
|
-
}, 1000);
|
|
1457
|
-
}
|
|
1458
|
-
};
|
|
1459
|
-
this.plyr.on("ready", onReady);
|
|
1460
|
-
}
|
|
1461
|
-
if (this.config.video_host === "youtube") {
|
|
1462
|
-
this.plyr.source = {
|
|
1463
|
-
type: "video",
|
|
1464
|
-
sources: [{ src: this.config.video_id, provider: "youtube" }],
|
|
1465
|
-
};
|
|
1466
|
-
}
|
|
1467
|
-
else if (this.config.video_host === "mp4") {
|
|
1468
|
-
this.plyr.source = {
|
|
1469
|
-
type: "video",
|
|
1470
|
-
sources: [{ src: this.config.video_external_id, type: "video/mp4" }],
|
|
1471
|
-
};
|
|
1472
|
-
}
|
|
1473
|
-
else if (this.config.video_host === "hls") {
|
|
1474
|
-
let sourceX = "";
|
|
1475
|
-
try {
|
|
1476
|
-
sourceX = atob(this.config.video_id || "");
|
|
1477
|
-
}
|
|
1478
|
-
catch (e) {
|
|
1479
|
-
sourceX = this.config.video_id || "";
|
|
1480
|
-
}
|
|
1481
|
-
const canNative = video.canPlayType("application/vnd.apple.mpegurl");
|
|
1482
|
-
if (canNative) {
|
|
1483
|
-
this.plyr.source = {
|
|
1484
|
-
type: "video",
|
|
1485
|
-
sources: [{ src: sourceX, type: "application/vnd.apple.mpegurl" }],
|
|
1486
|
-
};
|
|
1487
|
-
const onLoadedMeta = () => {
|
|
1488
|
-
const dur = this.plyr.duration || video.duration || 0;
|
|
1489
|
-
const start = this.resolveStartTime(this.config.last_time, this.config.last_percent, dur);
|
|
1490
|
-
console.log(start);
|
|
1491
|
-
this.requestStartTimeSeek(start, { video });
|
|
1492
|
-
this.startAutoplayFlow(video);
|
|
1493
|
-
video.removeEventListener("loadedmetadata", onLoadedMeta);
|
|
1494
|
-
};
|
|
1495
|
-
video.addEventListener("loadedmetadata", onLoadedMeta);
|
|
1496
|
-
}
|
|
1497
|
-
else if (Hls.isSupported()) {
|
|
1498
|
-
this.hls = new Hls({ enableWorker: true, lowLatencyMode: true });
|
|
1499
|
-
this.hls.attachMedia(video);
|
|
1500
|
-
this.hls.on(Hls.Events.MEDIA_ATTACHED, () => {
|
|
1501
|
-
this.hls.loadSource(sourceX);
|
|
1502
|
-
});
|
|
1503
|
-
this.hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
|
1504
|
-
const dur = video.duration || 0;
|
|
1505
|
-
const start = this.resolveStartTime(this.config.last_time, this.config.last_percent, dur);
|
|
1506
|
-
this.requestStartTimeSeek(start, { video });
|
|
1507
|
-
this.startAutoplayFlow(video);
|
|
1508
|
-
});
|
|
1509
|
-
this.hls.on(Hls.Events.ERROR, (_evt, data) => {
|
|
1510
|
-
if (data?.fatal) {
|
|
1511
|
-
switch (data.type) {
|
|
1512
|
-
case Hls.ErrorTypes.NETWORK_ERROR:
|
|
1513
|
-
this.hls.startLoad();
|
|
1514
|
-
break;
|
|
1515
|
-
case Hls.ErrorTypes.MEDIA_ERROR:
|
|
1516
|
-
this.hls.recoverMediaError();
|
|
1517
|
-
break;
|
|
1518
|
-
default:
|
|
1519
|
-
try {
|
|
1520
|
-
this.hls.destroy();
|
|
1521
|
-
}
|
|
1522
|
-
catch { }
|
|
1523
|
-
break;
|
|
1524
|
-
}
|
|
1525
|
-
}
|
|
1526
|
-
});
|
|
1527
|
-
}
|
|
1528
|
-
else {
|
|
1529
|
-
this.plyr.source = { type: "video", sources: [{ src: sourceX }] };
|
|
1530
|
-
}
|
|
1367
|
+
const host = this.config.video_host;
|
|
1368
|
+
if (host === "youtube") {
|
|
1369
|
+
this.loadYoutubeSource(autoplayConfig);
|
|
1370
|
+
return resolve();
|
|
1371
|
+
}
|
|
1372
|
+
if (host === "mp4") {
|
|
1373
|
+
this.loadMp4Source();
|
|
1374
|
+
return resolve();
|
|
1375
|
+
}
|
|
1376
|
+
if (host === "hls") {
|
|
1377
|
+
this.loadHlsSource(video, autoplayConfig);
|
|
1378
|
+
return resolve();
|
|
1531
1379
|
}
|
|
1532
1380
|
resolve();
|
|
1533
1381
|
});
|
|
1534
1382
|
}
|
|
1383
|
+
loadYoutubeSource(autoplayConfig) {
|
|
1384
|
+
const onReady = () => {
|
|
1385
|
+
this.plyr.off("ready", onReady);
|
|
1386
|
+
this.ensureIframeAutoplayPermissions();
|
|
1387
|
+
this.applyStartTimeFromConfig(this.plyr.duration);
|
|
1388
|
+
if (autoplayConfig.enabled) {
|
|
1389
|
+
this.startAutoplayFlow(undefined, autoplayConfig);
|
|
1390
|
+
}
|
|
1391
|
+
else if (autoplayConfig.blockIframe) {
|
|
1392
|
+
this.stopRestrictedIframeAutoplay(autoplayConfig);
|
|
1393
|
+
}
|
|
1394
|
+
parent.postMessage("playerIsReadyToPlay", "*");
|
|
1395
|
+
parent.postMessage("duration:" + this.plyr.duration, "*");
|
|
1396
|
+
console.log("event: current_time " + this.plyr.currentTime);
|
|
1397
|
+
console.log("event: duration " + this.plyr.duration);
|
|
1398
|
+
console.log("event: ready");
|
|
1399
|
+
this.postCastEvent({
|
|
1400
|
+
event: "ready",
|
|
1401
|
+
duration: this.plyr.duration || 0,
|
|
1402
|
+
currentTime: this.plyr.currentTime || 0,
|
|
1403
|
+
});
|
|
1404
|
+
if (this.isLivePlayback()) {
|
|
1405
|
+
this.plyr?.on("playing", function () {
|
|
1406
|
+
console.log("event: playing_live");
|
|
1407
|
+
parent.postMessage("event: playing_live", "*");
|
|
1408
|
+
});
|
|
1409
|
+
}
|
|
1410
|
+
if (this.config?.mirror) {
|
|
1411
|
+
setTimeout(() => {
|
|
1412
|
+
document
|
|
1413
|
+
.querySelector(`.plyr__video-embed iframe`)
|
|
1414
|
+
?.classList.add("mirror");
|
|
1415
|
+
}, 1000);
|
|
1416
|
+
}
|
|
1417
|
+
};
|
|
1418
|
+
this.plyr.on("ready", onReady);
|
|
1419
|
+
this.plyr.source = {
|
|
1420
|
+
type: "video",
|
|
1421
|
+
sources: [{ src: this.config?.video_id, provider: "youtube" }],
|
|
1422
|
+
};
|
|
1423
|
+
}
|
|
1424
|
+
loadMp4Source() {
|
|
1425
|
+
this.plyr.source = {
|
|
1426
|
+
type: "video",
|
|
1427
|
+
sources: [{ src: this.config?.video_external_id, type: "video/mp4" }],
|
|
1428
|
+
};
|
|
1429
|
+
}
|
|
1430
|
+
loadHlsSource(video, autoplayConfig) {
|
|
1431
|
+
let sourceX = "";
|
|
1432
|
+
try {
|
|
1433
|
+
sourceX = atob(this.config?.video_id || "");
|
|
1434
|
+
}
|
|
1435
|
+
catch (e) {
|
|
1436
|
+
sourceX = this.config?.video_id || "";
|
|
1437
|
+
}
|
|
1438
|
+
const canNative = video.canPlayType("application/vnd.apple.mpegurl");
|
|
1439
|
+
if (canNative) {
|
|
1440
|
+
this.plyr.source = {
|
|
1441
|
+
type: "video",
|
|
1442
|
+
sources: [{ src: sourceX, type: "application/vnd.apple.mpegurl" }],
|
|
1443
|
+
};
|
|
1444
|
+
const onLoadedMeta = () => {
|
|
1445
|
+
const dur = this.plyr.duration || video.duration || 0;
|
|
1446
|
+
console.log(this.applyStartTimeFromConfig(dur, video));
|
|
1447
|
+
this.startAutoplayFlow(video, autoplayConfig);
|
|
1448
|
+
video.removeEventListener("loadedmetadata", onLoadedMeta);
|
|
1449
|
+
};
|
|
1450
|
+
video.addEventListener("loadedmetadata", onLoadedMeta);
|
|
1451
|
+
return;
|
|
1452
|
+
}
|
|
1453
|
+
if (Hls.isSupported()) {
|
|
1454
|
+
this.hls = new Hls({ enableWorker: true, lowLatencyMode: true });
|
|
1455
|
+
this.hls.attachMedia(video);
|
|
1456
|
+
this.hls.on(Hls.Events.MEDIA_ATTACHED, () => {
|
|
1457
|
+
this.hls.loadSource(sourceX);
|
|
1458
|
+
});
|
|
1459
|
+
this.hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
|
1460
|
+
const dur = video.duration || 0;
|
|
1461
|
+
this.applyStartTimeFromConfig(dur, video);
|
|
1462
|
+
this.startAutoplayFlow(video, autoplayConfig);
|
|
1463
|
+
});
|
|
1464
|
+
this.hls.on(Hls.Events.ERROR, (_evt, data) => {
|
|
1465
|
+
if (data?.fatal) {
|
|
1466
|
+
switch (data.type) {
|
|
1467
|
+
case Hls.ErrorTypes.NETWORK_ERROR:
|
|
1468
|
+
this.hls.startLoad();
|
|
1469
|
+
break;
|
|
1470
|
+
case Hls.ErrorTypes.MEDIA_ERROR:
|
|
1471
|
+
this.hls.recoverMediaError();
|
|
1472
|
+
break;
|
|
1473
|
+
default:
|
|
1474
|
+
try {
|
|
1475
|
+
this.hls.destroy();
|
|
1476
|
+
}
|
|
1477
|
+
catch { }
|
|
1478
|
+
break;
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
});
|
|
1482
|
+
return;
|
|
1483
|
+
}
|
|
1484
|
+
this.plyr.source = { type: "video", sources: [{ src: sourceX }] };
|
|
1485
|
+
}
|
|
1535
1486
|
resolveStartTime(last_time, last_percent, duration, opts = {}) {
|
|
1536
1487
|
if (this.shouldResetProgressToBeginning()) {
|
|
1537
1488
|
return 0;
|
|
@@ -1581,6 +1532,11 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1581
1532
|
}
|
|
1582
1533
|
return 0;
|
|
1583
1534
|
}
|
|
1535
|
+
applyStartTimeFromConfig(duration, video) {
|
|
1536
|
+
const start = this.resolveStartTime(this.config?.last_time, this.config?.last_percent, duration);
|
|
1537
|
+
this.requestStartTimeSeek(start, { video });
|
|
1538
|
+
return start;
|
|
1539
|
+
}
|
|
1584
1540
|
postCastEvent(payload) {
|
|
1585
1541
|
parent.postMessage(JSON.stringify(payload), "*");
|
|
1586
1542
|
}
|
|
@@ -1626,8 +1582,8 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1626
1582
|
}
|
|
1627
1583
|
if (this.recommendationBlockerActiveZone) {
|
|
1628
1584
|
try {
|
|
1629
|
-
this.recommendationBlockerActiveZone.removeEventListener("pointerdown", this.
|
|
1630
|
-
this.recommendationBlockerActiveZone.removeEventListener("click", this.
|
|
1585
|
+
this.recommendationBlockerActiveZone.removeEventListener("pointerdown", this.consumeEvent);
|
|
1586
|
+
this.recommendationBlockerActiveZone.removeEventListener("click", this.consumeEvent);
|
|
1631
1587
|
}
|
|
1632
1588
|
catch { }
|
|
1633
1589
|
}
|
|
@@ -1635,8 +1591,8 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
|
|
|
1635
1591
|
this.recommendationBlockerActiveZone = null;
|
|
1636
1592
|
if (this.topClickBlocker?.parentElement) {
|
|
1637
1593
|
try {
|
|
1638
|
-
this.topClickBlocker.removeEventListener("pointerdown", this.
|
|
1639
|
-
this.topClickBlocker.removeEventListener("click", this.
|
|
1594
|
+
this.topClickBlocker.removeEventListener("pointerdown", this.consumeEvent);
|
|
1595
|
+
this.topClickBlocker.removeEventListener("click", this.consumeEvent);
|
|
1640
1596
|
this.topClickBlocker.parentElement.removeChild(this.topClickBlocker);
|
|
1641
1597
|
}
|
|
1642
1598
|
catch { }
|