@edm-webplayer/webplayer-angular 0.1.76 → 0.1.78

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.
@@ -88,6 +88,7 @@ class PlyrPlayerComponent {
88
88
  interactionUnmuteCleanup;
89
89
  endedLoggedOnPause = false;
90
90
  liveInteractionBlocker;
91
+ iosFullscreenCleanup;
91
92
  pendingStartTime;
92
93
  onResize = () => {
93
94
  this.updateRecommendationBlockerSafeZone();
@@ -446,6 +447,51 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
446
447
  }
447
448
  return "ontouchstart" in window;
448
449
  }
450
+ applyInlineAttributes(videoElement, isIOS) {
451
+ try {
452
+ videoElement.setAttribute("playsinline", "true");
453
+ videoElement.setAttribute("webkit-playsinline", "true");
454
+ if (isIOS) {
455
+ videoElement.setAttribute("x5-playsinline", "true");
456
+ videoElement.setAttribute("x5-video-player-type", "h5");
457
+ }
458
+ }
459
+ catch { }
460
+ }
461
+ bindIOSFullscreenLogging(videoElement, isIOS) {
462
+ this.removeIOSFullscreenLogging();
463
+ if (!isIOS)
464
+ return;
465
+ const logEvent = (name) => {
466
+ console.log(`event: ${name}`);
467
+ try {
468
+ parent.postMessage(`event: ${name}`, "*");
469
+ }
470
+ catch { }
471
+ };
472
+ const onEnter = () => logEvent("webkit_enterfullscreen");
473
+ const onExit = () => logEvent("webkit_exitfullscreen");
474
+ try {
475
+ videoElement.addEventListener("webkitbeginfullscreen", onEnter);
476
+ videoElement.addEventListener("webkitendfullscreen", onExit);
477
+ this.iosFullscreenCleanup = () => {
478
+ try {
479
+ videoElement.removeEventListener("webkitbeginfullscreen", onEnter);
480
+ videoElement.removeEventListener("webkitendfullscreen", onExit);
481
+ }
482
+ catch { }
483
+ this.iosFullscreenCleanup = undefined;
484
+ };
485
+ }
486
+ catch { }
487
+ }
488
+ removeIOSFullscreenLogging() {
489
+ try {
490
+ this.iosFullscreenCleanup?.();
491
+ }
492
+ catch { }
493
+ this.iosFullscreenCleanup = undefined;
494
+ }
449
495
  isIframeProvider() {
450
496
  return this.config?.video_host === "youtube";
451
497
  }
@@ -1071,6 +1117,10 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
1071
1117
  setupPlayer() {
1072
1118
  if (!this.videoRef)
1073
1119
  return;
1120
+ const videoEl = this.videoRef.nativeElement;
1121
+ const isIOS = this.isIOSContext();
1122
+ this.applyInlineAttributes(videoEl, isIOS);
1123
+ this.removeIOSFullscreenLogging();
1074
1124
  this.hls?.destroy();
1075
1125
  this.controlsVisibilityCleanup?.();
1076
1126
  this.controlsVisibilityCleanup = undefined;
@@ -1125,13 +1175,16 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
1125
1175
  "airplay",
1126
1176
  "fullscreen",
1127
1177
  ];
1178
+ const controls = isLive || !isIOS
1179
+ ? defaultControls
1180
+ : defaultControls.filter((c) => c !== "fullscreen");
1128
1181
  const liveControls = [];
1129
1182
  const plyrOptions = {
1130
- controls: isLive ? liveControls : defaultControls,
1183
+ controls: isLive ? liveControls : controls,
1131
1184
  fullscreen: {
1132
- enabled: true,
1133
- fallback: true,
1134
- iosNative: !isLive,
1185
+ enabled: !isIOS,
1186
+ fallback: !isIOS,
1187
+ iosNative: true,
1135
1188
  container: null,
1136
1189
  },
1137
1190
  i18n: {
@@ -1160,6 +1213,7 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
1160
1213
  }
1161
1214
  this.updateLiveInteractionBlocker(isLive);
1162
1215
  this.bindFullscreenBehavior();
1216
+ this.bindIOSFullscreenLogging(videoEl, isIOS);
1163
1217
  this.setupControlsVisibility();
1164
1218
  this.ensureTopClickBlocker();
1165
1219
  this.observeMenuChanges();
@@ -1544,6 +1598,7 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join("\n")}
1544
1598
  this.menuObserver?.disconnect();
1545
1599
  this.menuObserver = undefined;
1546
1600
  window.removeEventListener("resize", this.onResize);
1601
+ this.removeIOSFullscreenLogging();
1547
1602
  this.plyr?.destroy();
1548
1603
  window.removeEventListener("message", this.onCastMessage);
1549
1604
  }
@@ -1578,6 +1633,7 @@ class VimeoPlayerComponent {
1578
1633
  startTimeApplied = false;
1579
1634
  pendingStartTime;
1580
1635
  endedLoggedOnPause = false;
1636
+ iosFullscreenCleanup;
1581
1637
  onCastMessage = (event) => {
1582
1638
  let data = event.data;
1583
1639
  if (typeof data === 'string') {
@@ -1623,6 +1679,9 @@ class VimeoPlayerComponent {
1623
1679
  if (!this.videoRef) {
1624
1680
  return;
1625
1681
  }
1682
+ const videoElement = this.videoRef.nativeElement;
1683
+ const isIOS = this.isIOSContext();
1684
+ this.applyInlineAttributes(videoElement, isIOS);
1626
1685
  this.plyr?.destroy();
1627
1686
  this.startTimeApplied = false;
1628
1687
  this.pendingStartTime = undefined;
@@ -1631,21 +1690,22 @@ class VimeoPlayerComponent {
1631
1690
  const shouldAutoplay = false;
1632
1691
  const startMuted = shouldAutoplay;
1633
1692
  const speedOptions = [1, 1.25, 1.5, 2];
1693
+ const baseControls = [
1694
+ 'play-large',
1695
+ 'play',
1696
+ 'progress',
1697
+ 'current-time',
1698
+ 'duration',
1699
+ 'mute',
1700
+ 'volume',
1701
+ 'captions',
1702
+ 'settings',
1703
+ 'pip',
1704
+ 'airplay',
1705
+ 'fullscreen',
1706
+ ];
1634
1707
  const options = {
1635
- controls: [
1636
- 'play-large',
1637
- 'play',
1638
- 'progress',
1639
- 'current-time',
1640
- 'duration',
1641
- 'mute',
1642
- 'volume',
1643
- 'captions',
1644
- 'settings',
1645
- 'pip',
1646
- 'airplay',
1647
- 'fullscreen',
1648
- ],
1708
+ controls: isIOS ? baseControls.filter((c) => c !== 'fullscreen') : baseControls,
1649
1709
  clickToPlay: true,
1650
1710
  autoplay: shouldAutoplay,
1651
1711
  muted: startMuted,
@@ -1659,8 +1719,8 @@ class VimeoPlayerComponent {
1659
1719
  options: speedOptions,
1660
1720
  },
1661
1721
  fullscreen: {
1662
- enabled: true,
1663
- fallback: true,
1722
+ enabled: !isIOS,
1723
+ fallback: !isIOS,
1664
1724
  iosNative: true,
1665
1725
  container: null,
1666
1726
  },
@@ -1669,18 +1729,19 @@ class VimeoPlayerComponent {
1669
1729
  autopause: true,
1670
1730
  autoplay: shouldAutoplay,
1671
1731
  muted: startMuted,
1672
- playsinline: !this.isIOSDevice(),
1732
+ playsinline: true,
1673
1733
  byline: false,
1674
1734
  portrait: false,
1675
1735
  title: false,
1676
1736
  pip: false,
1677
1737
  controls: false,
1678
1738
  };
1679
- this.plyr = new Plyr.default(this.videoRef.nativeElement, options);
1739
+ this.plyr = new Plyr.default(videoElement, options);
1680
1740
  this.plyr.source = {
1681
1741
  type: 'video',
1682
1742
  sources: [{ src: this.config.video_id, provider: 'vimeo' }],
1683
1743
  };
1744
+ this.bindIOSFullscreenLogging(videoElement, isIOS);
1684
1745
  this.bindEvents();
1685
1746
  }
1686
1747
  bindEvents() {
@@ -1856,6 +1917,7 @@ class VimeoPlayerComponent {
1856
1917
  }
1857
1918
  ngOnDestroy() {
1858
1919
  this.plyr?.destroy();
1920
+ this.removeIOSFullscreenLogging();
1859
1921
  if (typeof window !== 'undefined') {
1860
1922
  window.removeEventListener('message', this.onCastMessage);
1861
1923
  }
@@ -2036,6 +2098,51 @@ ${allPairs.map(([n, v]) => ` ${n}: ${v};`).join('\n')}
2036
2098
  this.unlockPlayerInteraction();
2037
2099
  };
2038
2100
  }
2101
+ applyInlineAttributes(videoElement, isIOS) {
2102
+ try {
2103
+ videoElement.setAttribute('playsinline', 'true');
2104
+ videoElement.setAttribute('webkit-playsinline', 'true');
2105
+ if (isIOS) {
2106
+ videoElement.setAttribute('x5-playsinline', 'true');
2107
+ videoElement.setAttribute('x5-video-player-type', 'h5');
2108
+ }
2109
+ }
2110
+ catch { }
2111
+ }
2112
+ bindIOSFullscreenLogging(videoElement, isIOS) {
2113
+ this.removeIOSFullscreenLogging();
2114
+ if (!isIOS)
2115
+ return;
2116
+ const logEvent = (name) => {
2117
+ console.log(`event: ${name}`);
2118
+ try {
2119
+ parent.postMessage(`event: ${name}`, '*');
2120
+ }
2121
+ catch { }
2122
+ };
2123
+ const onEnter = () => logEvent('webkit_enterfullscreen');
2124
+ const onExit = () => logEvent('webkit_exitfullscreen');
2125
+ try {
2126
+ videoElement.addEventListener('webkitbeginfullscreen', onEnter);
2127
+ videoElement.addEventListener('webkitendfullscreen', onExit);
2128
+ this.iosFullscreenCleanup = () => {
2129
+ try {
2130
+ videoElement.removeEventListener('webkitbeginfullscreen', onEnter);
2131
+ videoElement.removeEventListener('webkitendfullscreen', onExit);
2132
+ }
2133
+ catch { }
2134
+ this.iosFullscreenCleanup = undefined;
2135
+ };
2136
+ }
2137
+ catch { }
2138
+ }
2139
+ removeIOSFullscreenLogging() {
2140
+ try {
2141
+ this.iosFullscreenCleanup?.();
2142
+ }
2143
+ catch { }
2144
+ this.iosFullscreenCleanup = undefined;
2145
+ }
2039
2146
  unlockPlayerInteraction() {
2040
2147
  try {
2041
2148
  const controls = this.plyr?.elements?.controls;
@@ -2386,8 +2493,19 @@ class ScaleupPlayerComponent {
2386
2493
  loadScaleupPlayer() {
2387
2494
  const videoId = this.config.video_id;
2388
2495
  const lastTime = Math.max(0, Math.floor(Number(this.config.last_time) || 0));
2496
+ const isIOS = this.isIOSContext();
2389
2497
  const eventsList = "controlsdisabled,controlsenabled,dispose,durationchange,ended,enterFullWindow,enterpictureinpicture,error,exitFullWindow,firstplay,fullscreenchange,leavepictureinpicture,loadedmetadata,loadstart,pause,play,playerreset,playerresize,playing,posterchange,progress,ratechange,ready,resize,seeked,seeking,textdata,timeupdate,useractive,userinactive,volumechange,waiting";
2390
- const scaleupSrc = `https://player.scaleup.com.br/embed/${videoId}?seekTo=${lastTime}&events=${eventsList}&autoplay=${this.config.autoplay}`;
2498
+ const params = new URLSearchParams({
2499
+ seekTo: String(lastTime),
2500
+ events: eventsList,
2501
+ autoplay: String(!!this.config.autoplay),
2502
+ });
2503
+ if (isIOS) {
2504
+ params.set("iosNativeFullscreen", "1");
2505
+ params.set("disableFullscreenControls", "1");
2506
+ params.set("playsinline", "1");
2507
+ }
2508
+ const scaleupSrc = `https://player.scaleup.com.br/embed/${videoId}?${params.toString()}`;
2391
2509
  const host = this.elementRef.nativeElement;
2392
2510
  if (this.scaleupIframe) {
2393
2511
  this.scaleupIframe.remove();
@@ -2439,6 +2557,12 @@ class ScaleupPlayerComponent {
2439
2557
  .toLowerCase();
2440
2558
  if (!type)
2441
2559
  return;
2560
+ if (type.includes("fullscreen") || type.includes("fullwindow")) {
2561
+ try {
2562
+ console.log(`scaleup event: ${type}`);
2563
+ }
2564
+ catch { }
2565
+ }
2442
2566
  const t = Number((data.currentTime ?? data.time ?? data.position) || 0);
2443
2567
  const d = Number((data.duration ?? data.totalDuration) || 0);
2444
2568
  const p = d > 0 ? +((t / d) * 100).toFixed(2) : 0;
@@ -2474,6 +2598,31 @@ class ScaleupPlayerComponent {
2474
2598
  this.scaleupMessageHandler = undefined;
2475
2599
  }
2476
2600
  }
2601
+ isIOSDevice() {
2602
+ if (typeof navigator === "undefined")
2603
+ return false;
2604
+ const ua = navigator.userAgent || "";
2605
+ const iOS = /iPad|iPhone|iPod/.test(ua);
2606
+ const iPadOS = navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1;
2607
+ return iOS || iPadOS;
2608
+ }
2609
+ isIOSContext() {
2610
+ if (this.isIOSDevice()) {
2611
+ return true;
2612
+ }
2613
+ if (typeof window === "undefined") {
2614
+ return false;
2615
+ }
2616
+ try {
2617
+ const params = new URLSearchParams(window.location.search);
2618
+ const os = params.get("os");
2619
+ if (os && os.toLowerCase() === "ios") {
2620
+ return true;
2621
+ }
2622
+ }
2623
+ catch { }
2624
+ return false;
2625
+ }
2477
2626
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ScaleupPlayerComponent, deps: [{ token: i0.ElementRef }, { token: WebplayerProgressService }], target: i0.ɵɵFactoryTarget.Component });
2478
2627
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: ScaleupPlayerComponent, isStandalone: true, selector: "app-scaleup-player", inputs: { config: "config" }, outputs: { ready: "ready" }, usesOnChanges: true, ngImport: i0, template: '', isInline: true, styles: [":host{display:block;width:100%;height:100%;position:relative}:host ::ng-deep iframe[src*=\"scaleup.com.br\"]{position:absolute!important;top:0!important;left:0!important;width:100%!important;height:100%!important;border:none!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
2479
2628
  }