@edm-webplayer/webplayer-angular 0.1.31 → 0.1.33

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.
@@ -78,12 +78,19 @@ class PlyrPlayerComponent {
78
78
  recommendationBlocker;
79
79
  recommendationBlockerActiveZone;
80
80
  topClickBlocker;
81
+ gestureOverlay;
81
82
  menuObserver;
82
83
  playbackEnded = false;
83
84
  overlayBlockAll = false;
84
85
  endedPosterOverlay;
85
86
  fullscreenCleanup;
86
- onResize = () => this.updateRecommendationBlockerSafeZone();
87
+ interactionUnmuteCleanup;
88
+ pendingStartTime;
89
+ pendingGesturePlay = false;
90
+ onResize = () => {
91
+ this.updateRecommendationBlockerSafeZone();
92
+ this.updateGestureOverlaySafeZone();
93
+ };
87
94
  onTopBlockerPointerDown = (event) => {
88
95
  try {
89
96
  event.preventDefault();
@@ -119,6 +126,30 @@ class PlyrPlayerComponent {
119
126
  this.applyTheme(this.config.ui.colors);
120
127
  }
121
128
  }
129
+ flushPendingStartTime(target, success) {
130
+ const pending = this.pendingStartTime;
131
+ if (!pending) {
132
+ return;
133
+ }
134
+ const tolerance = 0.35;
135
+ if (Math.abs(pending.value - target) > tolerance) {
136
+ return;
137
+ }
138
+ const callbacks = pending.queue.slice();
139
+ pending.queue.length = 0;
140
+ if (success) {
141
+ this.pendingStartTime = undefined;
142
+ }
143
+ else {
144
+ pending.blockPlayback = false;
145
+ }
146
+ callbacks.forEach((cb) => {
147
+ try {
148
+ cb();
149
+ }
150
+ catch { }
151
+ });
152
+ }
122
153
  getControlsSafeZone() {
123
154
  const controls = (this.plyr?.elements?.controls ?? null);
124
155
  const menuHeight = this.getOpenMenuHeight();
@@ -143,7 +174,9 @@ class PlyrPlayerComponent {
143
174
  const host = this.config?.video_host;
144
175
  if (this.overlayBlockAll &&
145
176
  (host === 'youtube' || host === 'vimeo')) {
146
- return 0;
177
+ if (this.playbackEnded) {
178
+ return 0;
179
+ }
147
180
  }
148
181
  return this.getControlsSafeZone();
149
182
  }
@@ -340,13 +373,12 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join('\n')}
340
373
  this.updateTopClickBlockerSafeZone();
341
374
  }
342
375
  updateRecommendationBlockerSafeZone() {
343
- if (!this.recommendationBlockerActiveZone && !this.topClickBlocker)
344
- return;
345
- const safeZone = this.getOverlaySafeZone();
376
+ const overlaySafeZone = this.getOverlaySafeZone();
346
377
  if (this.recommendationBlockerActiveZone) {
347
- this.recommendationBlockerActiveZone.style.bottom = `${safeZone}px`;
378
+ this.recommendationBlockerActiveZone.style.bottom = `${overlaySafeZone}px`;
348
379
  }
349
- this.updateTopClickBlockerSafeZone(safeZone);
380
+ this.updateTopClickBlockerSafeZone(overlaySafeZone);
381
+ this.updateGestureOverlaySafeZone(this.getControlsSafeZone());
350
382
  }
351
383
  updateTopClickBlockerSafeZone(precomputed) {
352
384
  if (!this.topClickBlocker)
@@ -355,6 +387,13 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join('\n')}
355
387
  const safeZone = Math.max(0, safeZoneRaw);
356
388
  this.topClickBlocker.style.bottom = `${safeZone}px`;
357
389
  }
390
+ updateGestureOverlaySafeZone(precomputed) {
391
+ if (!this.gestureOverlay)
392
+ return;
393
+ const safeZoneRaw = typeof precomputed === 'number' ? precomputed : this.getControlsSafeZone();
394
+ const safeZone = Math.max(0, safeZoneRaw);
395
+ this.gestureOverlay.style.bottom = `${safeZone}px`;
396
+ }
358
397
  togglePlayback(force) {
359
398
  if (!this.plyr)
360
399
  return;
@@ -372,6 +411,9 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join('\n')}
372
411
  }
373
412
  const shouldPlay = typeof force === 'boolean' ? !!force : !this.plyr.playing;
374
413
  if (shouldPlay) {
414
+ if (this.deferUntilStartTimeSettles(() => this.togglePlayback(true))) {
415
+ return;
416
+ }
375
417
  if (ended) {
376
418
  try {
377
419
  if (typeof this.plyr.restart === 'function') {
@@ -386,6 +428,7 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join('\n')}
386
428
  this.playbackEnded = false;
387
429
  this.overlayBlockAll = false;
388
430
  this.updateRecommendationBlockerSafeZone();
431
+ this.hideGestureOverlay();
389
432
  try {
390
433
  const result = this.plyr.play?.();
391
434
  if (result && typeof result.catch === 'function') {
@@ -477,6 +520,380 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join('\n')}
477
520
  }
478
521
  return 'ontouchstart' in window;
479
522
  }
523
+ isIframeProvider() {
524
+ return this.config?.video_host === 'youtube' || this.config?.video_host === 'vimeo';
525
+ }
526
+ shouldAutoplay() {
527
+ return !!(this.config?.autoplay || this.config?.is_live);
528
+ }
529
+ requiresMutedAutoplay() {
530
+ return this.isIOSDevice();
531
+ }
532
+ setPlayerMutedState(muted, volume = 1, target) {
533
+ if (this.plyr) {
534
+ try {
535
+ this.plyr.muted = muted;
536
+ }
537
+ catch { }
538
+ if (!muted) {
539
+ try {
540
+ this.plyr.volume = volume;
541
+ }
542
+ catch { }
543
+ }
544
+ }
545
+ const media = target ?? this.videoRef?.nativeElement ?? null;
546
+ if (media) {
547
+ try {
548
+ media.muted = muted;
549
+ }
550
+ catch { }
551
+ if (!muted && typeof media.volume === 'number') {
552
+ try {
553
+ media.volume = volume;
554
+ }
555
+ catch { }
556
+ }
557
+ }
558
+ }
559
+ clearAutoplayUnlockListener() {
560
+ if (this.interactionUnmuteCleanup) {
561
+ try {
562
+ this.interactionUnmuteCleanup();
563
+ }
564
+ catch { }
565
+ this.interactionUnmuteCleanup = undefined;
566
+ }
567
+ }
568
+ ensureAutoplayUnlockListener() {
569
+ if (typeof window === 'undefined' ||
570
+ this.interactionUnmuteCleanup ||
571
+ !this.shouldAutoplay()) {
572
+ return;
573
+ }
574
+ const capture = true;
575
+ const handler = () => {
576
+ this.setPlayerMutedState(false);
577
+ try {
578
+ this.plyr?.play();
579
+ }
580
+ catch { }
581
+ this.clearAutoplayUnlockListener();
582
+ };
583
+ window.addEventListener('touchend', handler, capture);
584
+ window.addEventListener('pointerup', handler, capture);
585
+ window.addEventListener('click', handler, capture);
586
+ this.interactionUnmuteCleanup = () => {
587
+ window.removeEventListener('touchend', handler, capture);
588
+ window.removeEventListener('pointerup', handler, capture);
589
+ window.removeEventListener('click', handler, capture);
590
+ this.interactionUnmuteCleanup = undefined;
591
+ };
592
+ }
593
+ scheduleUserInteractionUnmute(video) {
594
+ this.unmuteAfterDelay(video || undefined);
595
+ this.ensureAutoplayUnlockListener();
596
+ }
597
+ requestStartTimeSeek(start, opts = {}) {
598
+ if (!(start > 0)) {
599
+ this.pendingStartTime = undefined;
600
+ return;
601
+ }
602
+ const video = opts.video ?? this.videoRef?.nativeElement ?? null;
603
+ const normalized = Math.max(0, start);
604
+ const tolerance = 0.35;
605
+ const pending = this.pendingStartTime;
606
+ if (pending && Math.abs(pending.value - normalized) <= tolerance) {
607
+ pending.video = video ?? pending.video;
608
+ pending.blockPlayback = true;
609
+ }
610
+ else {
611
+ const carryQueue = this.pendingStartTime?.queue ?? [];
612
+ this.pendingStartTime = {
613
+ value: normalized,
614
+ video,
615
+ queue: carryQueue,
616
+ blockPlayback: true,
617
+ };
618
+ }
619
+ this.applyStartTimeToCurrentSource(normalized, { video });
620
+ }
621
+ deferUntilStartTimeSettles(callback) {
622
+ if (!this.pendingStartTime || !this.pendingStartTime.blockPlayback)
623
+ return false;
624
+ this.pendingStartTime.queue.push(callback);
625
+ return true;
626
+ }
627
+ retryPendingStartTime() {
628
+ if (!this.pendingStartTime) {
629
+ return;
630
+ }
631
+ const { value, video } = this.pendingStartTime;
632
+ this.applyStartTimeToCurrentSource(value, {
633
+ video: video ?? this.videoRef?.nativeElement ?? null,
634
+ attempts: 3,
635
+ delayMs: 150,
636
+ });
637
+ }
638
+ applyStartTimeToCurrentSource(start, opts = {}) {
639
+ if (!this.plyr || !(start > 0)) {
640
+ return;
641
+ }
642
+ const video = opts.video ?? this.videoRef?.nativeElement ?? null;
643
+ let attempts = Math.max(1, opts.attempts ?? 6);
644
+ const delayMs = opts.delayMs ?? 250;
645
+ const tolerance = 0.35;
646
+ const scheduleRetry = () => {
647
+ attempts -= 1;
648
+ if (attempts > 0) {
649
+ setTimeout(trySeek, delayMs);
650
+ return;
651
+ }
652
+ this.flushPendingStartTime(start, false);
653
+ };
654
+ const verifyAfterAttempt = () => {
655
+ const current = this.plyr?.currentTime || 0;
656
+ if (Math.abs(current - start) <= tolerance) {
657
+ attempts = 0;
658
+ this.flushPendingStartTime(start, true);
659
+ return;
660
+ }
661
+ scheduleRetry();
662
+ };
663
+ const trySeek = () => {
664
+ if (!this.plyr)
665
+ return;
666
+ let maybePromise = null;
667
+ try {
668
+ const result = this.seekUsingHostAPI(start, video);
669
+ if (result && typeof result.then === 'function') {
670
+ maybePromise = result;
671
+ }
672
+ }
673
+ catch {
674
+ scheduleRetry();
675
+ return;
676
+ }
677
+ if (maybePromise) {
678
+ maybePromise
679
+ .then(() => verifyAfterAttempt())
680
+ .catch(() => scheduleRetry());
681
+ return;
682
+ }
683
+ verifyAfterAttempt();
684
+ };
685
+ trySeek();
686
+ }
687
+ seekUsingHostAPI(target, video) {
688
+ if (!Number.isFinite(target) || target < 0) {
689
+ return null;
690
+ }
691
+ if (this.config.video_host === 'vimeo') {
692
+ const embed = this.plyr?.embed;
693
+ if (embed && typeof embed.setCurrentTime === 'function') {
694
+ try {
695
+ return embed.setCurrentTime(target);
696
+ }
697
+ catch {
698
+ return null;
699
+ }
700
+ }
701
+ }
702
+ if (video) {
703
+ try {
704
+ video.currentTime = target;
705
+ }
706
+ catch { }
707
+ }
708
+ try {
709
+ this.plyr.currentTime = target;
710
+ }
711
+ catch { }
712
+ return null;
713
+ }
714
+ ensureGestureOverlay() {
715
+ if (this.gestureOverlay && this.gestureOverlay.isConnected) {
716
+ return this.gestureOverlay;
717
+ }
718
+ const wrapper = this.getVideoWrapper();
719
+ if (!wrapper) {
720
+ return null;
721
+ }
722
+ const overlay = this.document.createElement('button');
723
+ overlay.type = 'button';
724
+ overlay.className = 'plyr-gesture-overlay';
725
+ overlay.style.position = 'absolute';
726
+ overlay.style.top = '0';
727
+ overlay.style.left = '0';
728
+ overlay.style.right = '0';
729
+ overlay.style.bottom = '0';
730
+ overlay.style.width = '100%';
731
+ overlay.style.height = '100%';
732
+ overlay.style.display = 'none';
733
+ overlay.style.alignItems = 'center';
734
+ overlay.style.justifyContent = 'center';
735
+ overlay.style.padding = '0 16px';
736
+ overlay.style.background = 'rgba(0,0,0,0.35)';
737
+ overlay.style.backdropFilter = 'blur(1px)';
738
+ overlay.style.border = '0';
739
+ overlay.style.zIndex = '16';
740
+ overlay.style.color = 'var(--theme-text-color, #fff)';
741
+ overlay.style.fontSize = '14px';
742
+ overlay.style.fontWeight = '600';
743
+ overlay.style.textAlign = 'center';
744
+ overlay.style.cursor = 'pointer';
745
+ overlay.style.touchAction = 'manipulation';
746
+ overlay.style.pointerEvents = 'none';
747
+ overlay.textContent = 'Toque para reproduzir';
748
+ wrapper.appendChild(overlay);
749
+ this.gestureOverlay = overlay;
750
+ this.updateGestureOverlaySafeZone();
751
+ return overlay;
752
+ }
753
+ hideGestureOverlay() {
754
+ if (this.gestureOverlay) {
755
+ this.gestureOverlay.style.display = 'none';
756
+ this.gestureOverlay.style.pointerEvents = 'none';
757
+ }
758
+ this.pendingGesturePlay = false;
759
+ }
760
+ requestGestureToPlay(video) {
761
+ if (!this.isIframeProvider()) {
762
+ return;
763
+ }
764
+ if (this.pendingGesturePlay) {
765
+ return;
766
+ }
767
+ const overlay = this.ensureGestureOverlay();
768
+ if (!overlay) {
769
+ return;
770
+ }
771
+ this.pendingGesturePlay = true;
772
+ const media = video ?? this.videoRef?.nativeElement ?? null;
773
+ const onInteraction = (event) => {
774
+ try {
775
+ event.preventDefault();
776
+ }
777
+ catch { }
778
+ try {
779
+ event.stopPropagation();
780
+ }
781
+ catch { }
782
+ overlay.removeEventListener('click', onInteraction);
783
+ overlay.removeEventListener('touchend', onInteraction);
784
+ overlay.style.display = 'none';
785
+ this.pendingGesturePlay = false;
786
+ this.clearAutoplayUnlockListener();
787
+ this.setPlayerMutedState(this.requiresMutedAutoplay(), 1, media);
788
+ try {
789
+ const result = this.plyr?.play();
790
+ if (result && typeof result.catch === 'function') {
791
+ result.catch(() => {
792
+ this.requestGestureToPlay(media);
793
+ });
794
+ }
795
+ }
796
+ catch {
797
+ this.requestGestureToPlay(media);
798
+ }
799
+ };
800
+ overlay.addEventListener('click', onInteraction, { once: true });
801
+ overlay.addEventListener('touchend', onInteraction, { once: true });
802
+ this.updateGestureOverlaySafeZone();
803
+ overlay.style.pointerEvents = 'auto';
804
+ overlay.style.display = 'flex';
805
+ }
806
+ shouldShowGestureOverlayForError(error) {
807
+ if (!this.isIframeProvider()) {
808
+ return false;
809
+ }
810
+ if (!error) {
811
+ return true;
812
+ }
813
+ const err = error;
814
+ const name = typeof err.name === 'string' ? err.name.toLowerCase() : '';
815
+ const message = typeof err.message === 'string' ? err.message.toLowerCase() : '';
816
+ if (!name && !message) {
817
+ return true;
818
+ }
819
+ return (name.includes('notallowed') ||
820
+ name.includes('notallowederror') ||
821
+ name.includes('gesture') ||
822
+ message.includes('gesture') ||
823
+ message.includes('user interaction') ||
824
+ message.includes('user activation') ||
825
+ message.includes('without user') ||
826
+ message.includes('play() failed'));
827
+ }
828
+ startAutoplayFlow(video) {
829
+ if (!this.shouldAutoplay() || !this.plyr)
830
+ return;
831
+ if (this.deferUntilStartTimeSettles(() => this.startAutoplayFlow(video))) {
832
+ return;
833
+ }
834
+ const media = video ?? this.videoRef?.nativeElement ?? null;
835
+ const tryPlay = (muted) => {
836
+ this.setPlayerMutedState(muted, 1, media);
837
+ let playResult;
838
+ try {
839
+ playResult = this.plyr.play();
840
+ }
841
+ catch (error) {
842
+ if (!muted) {
843
+ tryPlay(true);
844
+ return;
845
+ }
846
+ if (media) {
847
+ try {
848
+ const nativePlay = media.play();
849
+ if (nativePlay && typeof nativePlay.catch === 'function') {
850
+ nativePlay.catch(() => { });
851
+ }
852
+ }
853
+ catch { }
854
+ }
855
+ this.scheduleUserInteractionUnmute(media);
856
+ if (this.shouldShowGestureOverlayForError(error)) {
857
+ this.requestGestureToPlay(media);
858
+ }
859
+ return;
860
+ }
861
+ if (playResult && typeof playResult.catch === 'function') {
862
+ playResult.catch((error) => {
863
+ if (!muted) {
864
+ tryPlay(true);
865
+ return;
866
+ }
867
+ if (media) {
868
+ try {
869
+ const nativePlay = media.play();
870
+ if (nativePlay && typeof nativePlay.catch === 'function') {
871
+ nativePlay.catch(() => { });
872
+ }
873
+ }
874
+ catch { }
875
+ }
876
+ this.scheduleUserInteractionUnmute(media);
877
+ if (this.shouldShowGestureOverlayForError(error)) {
878
+ this.requestGestureToPlay(media);
879
+ }
880
+ });
881
+ return;
882
+ }
883
+ if (muted) {
884
+ this.scheduleUserInteractionUnmute(media);
885
+ }
886
+ else {
887
+ this.clearAutoplayUnlockListener();
888
+ }
889
+ };
890
+ if (this.requiresMutedAutoplay()) {
891
+ tryPlay(true);
892
+ }
893
+ else {
894
+ tryPlay(false);
895
+ }
896
+ }
480
897
  setupControlsVisibility() {
481
898
  const container = this.plyr?.elements?.container;
482
899
  if (!container) {
@@ -632,11 +1049,13 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join('\n')}
632
1049
  orientationLocked = false;
633
1050
  };
634
1051
  const onEnterFullscreen = () => {
1052
+ console.log('event: enterfullscreen');
635
1053
  if (isPortrait()) {
636
1054
  lockLandscape();
637
1055
  }
638
1056
  };
639
1057
  const onExitFullscreen = () => {
1058
+ console.log('event: exitfullscreen');
640
1059
  unlockOrientation();
641
1060
  };
642
1061
  const onOrientationChange = () => {
@@ -663,12 +1082,28 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join('\n')}
663
1082
  this.fullscreenCleanup?.();
664
1083
  this.fullscreenCleanup = undefined;
665
1084
  this.plyr?.destroy();
1085
+ this.clearAutoplayUnlockListener();
1086
+ this.hideGestureOverlay();
666
1087
  this.recommendationBlocker = null;
667
1088
  const speedOptions = [1, 1.25, 1.5, 2];
668
1089
  const locale = this.resolveLocale();
669
1090
  const captionsLanguage = this.resolveCaptionsLanguage(locale) ?? 'pt';
670
1091
  const hideVimeoRecommendations = this.shouldHideVimeoRecommendations();
671
1092
  const vimeoPremium = Boolean(this.config?.vimeo_premium);
1093
+ const shouldAutoplay = this.shouldAutoplay();
1094
+ const startMuted = this.requiresMutedAutoplay();
1095
+ try {
1096
+ this.videoRef.nativeElement.muted = startMuted;
1097
+ }
1098
+ catch { }
1099
+ try {
1100
+ this.videoRef.nativeElement.playsInline = true;
1101
+ }
1102
+ catch { }
1103
+ try {
1104
+ this.videoRef.nativeElement.autoplay = shouldAutoplay;
1105
+ }
1106
+ catch { }
672
1107
  const vimeoOptions = {
673
1108
  byline: false,
674
1109
  portrait: false,
@@ -680,6 +1115,9 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join('\n')}
680
1115
  quality: "auto",
681
1116
  transparent: false,
682
1117
  };
1118
+ vimeoOptions.autoplay = shouldAutoplay;
1119
+ vimeoOptions.muted = startMuted;
1120
+ vimeoOptions.playsinline = true;
683
1121
  if (hideVimeoRecommendations) {
684
1122
  vimeoOptions.controls = false;
685
1123
  vimeoOptions.sidedock = 0;
@@ -695,6 +1133,9 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join('\n')}
695
1133
  youtubePlayerVars.playerVars = {
696
1134
  hl: locale,
697
1135
  cc_lang_pref: captionsLanguage || locale.split('-')[0]?.toLowerCase(),
1136
+ autoplay: shouldAutoplay ? 1 : 0,
1137
+ mute: startMuted ? 1 : 0,
1138
+ playsinline: 1,
698
1139
  };
699
1140
  if (captionsLanguage) {
700
1141
  youtubePlayerVars.playerVars.cc_load_policy = 1;
@@ -732,7 +1173,8 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join('\n')}
732
1173
  clickToPlay: true,
733
1174
  hideControls: false,
734
1175
  keyboard: { focused: true, global: false },
735
- muted: false,
1176
+ autoplay: shouldAutoplay,
1177
+ muted: startMuted,
736
1178
  };
737
1179
  plyrOptions.hl = locale;
738
1180
  if (captionsLanguage) {
@@ -760,8 +1202,7 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join('\n')}
760
1202
  const apply = () => {
761
1203
  const dur = this.plyr.duration || 0;
762
1204
  const start = this.resolveStartTime(this.config.last_time, this.config.last_percent, dur);
763
- if (start > 0)
764
- this.plyr.currentTime = start;
1205
+ this.requestStartTimeSeek(start);
765
1206
  this.plyr.off("ready", apply);
766
1207
  };
767
1208
  this.plyr.on("ready", apply);
@@ -790,12 +1231,15 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join('\n')}
790
1231
  });
791
1232
  };
792
1233
  this.plyr?.on?.("play", () => {
1234
+ this.retryPendingStartTime();
1235
+ this.hideGestureOverlay();
793
1236
  this.clearVimeoEndedState();
794
1237
  this.playbackEnded = false;
795
1238
  this.overlayBlockAll = false;
796
1239
  this.updateRecommendationBlockerSafeZone();
797
1240
  this.toggleRecommendationBlocker(false);
798
1241
  parent.postMessage('playing_video', "*");
1242
+ console.log('event: playing_video');
799
1243
  this.postCastEvent({ event: 'play', currentTime: this.plyr.currentTime || 0 });
800
1244
  });
801
1245
  this.plyr?.on?.("timeupdate", onTimeUpdate);
@@ -813,6 +1257,7 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join('\n')}
813
1257
  this.playbackEnded = true;
814
1258
  this.overlayBlockAll = true;
815
1259
  this.updateRecommendationBlockerSafeZone();
1260
+ console.log('event: ended');
816
1261
  parent.postMessage('event: ended', "*");
817
1262
  this.postCastEvent({ event: 'ended', currentTime: this.plyr.currentTime || 0 });
818
1263
  this.progressService.ended$.next();
@@ -821,7 +1266,7 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join('\n')}
821
1266
  });
822
1267
  }
823
1268
  unmuteAfterDelay(video, delayMs = 2000, volume = 1) {
824
- if (!this.config.autoplay)
1269
+ if (!this.shouldAutoplay())
825
1270
  return;
826
1271
  setTimeout(() => {
827
1272
  try {
@@ -876,13 +1321,8 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join('\n')}
876
1321
  const onReady = () => {
877
1322
  this.plyr.off("ready", onReady);
878
1323
  const start = this.resolveStartTime(this.config.last_time, this.config.last_percent, this.plyr.duration);
879
- if (start > 0)
880
- this.plyr.currentTime = start;
881
- if (this.config.autoplay || this.config.is_live) {
882
- setTimeout(() => {
883
- this.plyr.play();
884
- }, 1500);
885
- }
1324
+ this.requestStartTimeSeek(start);
1325
+ this.startAutoplayFlow();
886
1326
  parent.postMessage('playerIsReadyToPlay', "*");
887
1327
  parent.postMessage('duration:' + this.plyr.duration, "*");
888
1328
  console.log('event: current_time ' + this.plyr.currentTime);
@@ -944,35 +1384,8 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join('\n')}
944
1384
  const onLoadedMeta = () => {
945
1385
  const dur = this.plyr.duration || video.duration || 0;
946
1386
  const start = this.resolveStartTime(this.config.last_time, this.config.last_percent, dur);
947
- if (start > 0) {
948
- try {
949
- this.plyr.currentTime = start;
950
- }
951
- catch {
952
- try {
953
- video.currentTime = start;
954
- }
955
- catch { }
956
- }
957
- }
958
- if (this.config.autoplay) {
959
- try {
960
- video.muted = true;
961
- }
962
- catch { }
963
- setTimeout(() => {
964
- try {
965
- this.plyr.play();
966
- }
967
- catch {
968
- try {
969
- video.play();
970
- }
971
- catch { }
972
- }
973
- this.unmuteAfterDelay(video);
974
- }, 250);
975
- }
1387
+ this.requestStartTimeSeek(start, { video });
1388
+ this.startAutoplayFlow(video);
976
1389
  video.removeEventListener("loadedmetadata", onLoadedMeta);
977
1390
  };
978
1391
  video.addEventListener("loadedmetadata", onLoadedMeta);
@@ -986,17 +1399,8 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join('\n')}
986
1399
  this.hls.on(Hls.Events.MANIFEST_PARSED, () => {
987
1400
  const dur = video.duration || 0;
988
1401
  const start = this.resolveStartTime(this.config.last_time, this.config.last_percent, dur);
989
- if (start > 0) {
990
- try {
991
- video.currentTime = start;
992
- }
993
- catch { }
994
- }
995
- if (this.config.autoplay) {
996
- video.muted = true;
997
- video.play().catch(() => { });
998
- this.unmuteAfterDelay(video);
999
- }
1402
+ this.requestStartTimeSeek(start, { video });
1403
+ this.startAutoplayFlow(video);
1000
1404
  });
1001
1405
  this.hls.on(Hls.Events.ERROR, (_evt, data) => {
1002
1406
  if (data?.fatal) {
@@ -1085,6 +1489,7 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join('\n')}
1085
1489
  this.hls?.destroy();
1086
1490
  this.controlsVisibilityCleanup?.();
1087
1491
  this.controlsVisibilityCleanup = undefined;
1492
+ this.clearAutoplayUnlockListener();
1088
1493
  const container = this.plyr?.elements?.container;
1089
1494
  container?.classList.remove("plyr--vimeo-ended");
1090
1495
  if (this.recommendationBlocker?.parentElement) {
@@ -1111,6 +1516,14 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join('\n')}
1111
1516
  catch { }
1112
1517
  }
1113
1518
  this.topClickBlocker = null;
1519
+ if (this.gestureOverlay?.parentElement) {
1520
+ try {
1521
+ this.gestureOverlay.parentElement.removeChild(this.gestureOverlay);
1522
+ }
1523
+ catch { }
1524
+ }
1525
+ this.gestureOverlay = null;
1526
+ this.pendingGesturePlay = false;
1114
1527
  this.menuObserver?.disconnect();
1115
1528
  this.menuObserver = undefined;
1116
1529
  window.removeEventListener('resize', this.onResize);