unified-video-framework 1.4.459 → 1.4.461

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.
@@ -1838,12 +1838,17 @@ export class WebPlayer extends BasePlayer {
1838
1838
  iv_load_policy: 3, // Hide annotations
1839
1839
  modestbranding: 1, // Minimal YouTube branding
1840
1840
  rel: 0, // Don't show related videos
1841
- showinfo: 0, // Hide video info
1841
+ showinfo: 0, // Hide video info (deprecated but keep for older players)
1842
+ autohide: 1, // Auto-hide controls after delay
1843
+ cc_load_policy: 0, // Don't show captions by default
1844
+ playsinline: 1, // Play inline on mobile
1842
1845
  autoplay: this.config.autoPlay ? 1 : 0,
1843
1846
  mute: this.config.muted ? 1 : 0,
1844
1847
  loop: this.config.loop ? 1 : 0, // Enable/disable loop
1845
1848
  playlist: this.config.loop ? videoId : undefined, // Required for loop to work with single video
1846
- widget_referrer: window.location.href // Hide YouTube recommendations
1849
+ widget_referrer: window.location.href, // Hide YouTube recommendations
1850
+ origin: window.location.origin, // Required for security
1851
+ enablejsapi: 1 // Enable JavaScript API
1847
1852
  },
1848
1853
  events: {
1849
1854
  onReady: () => this.onYouTubePlayerReady(),
@@ -2688,12 +2693,27 @@ export class WebPlayer extends BasePlayer {
2688
2693
  private updateTimeTooltip(e: MouseEvent): void {
2689
2694
  const progressBar = document.getElementById('uvf-progress-bar');
2690
2695
  const tooltip = document.getElementById('uvf-time-tooltip');
2691
- if (!progressBar || !tooltip || !this.video) return;
2696
+ if (!progressBar || !tooltip) return;
2697
+
2698
+ // Get duration from YouTube player or regular video
2699
+ let duration: number;
2700
+ if (this.youtubePlayer && this.youtubePlayerReady) {
2701
+ duration = this.youtubePlayer.getDuration();
2702
+ } else if (this.video) {
2703
+ duration = this.video.duration;
2704
+ } else {
2705
+ return; // No video source available
2706
+ }
2707
+
2708
+ // Validate duration
2709
+ if (!isFinite(duration) || isNaN(duration) || duration <= 0) {
2710
+ return;
2711
+ }
2692
2712
 
2693
2713
  const rect = progressBar.getBoundingClientRect();
2694
2714
  const x = Math.max(0, Math.min(e.clientX - rect.left, rect.width));
2695
2715
  const percent = (x / rect.width);
2696
- const time = percent * this.video.duration;
2716
+ const time = percent * duration;
2697
2717
 
2698
2718
  // Update tooltip content and position
2699
2719
  tooltip.textContent = this.formatTime(time);
@@ -4596,6 +4616,42 @@ export class WebPlayer extends BasePlayer {
4596
4616
  this.playerWrapper.classList.add('uvf-fullscreen');
4597
4617
  this.emit('onFullscreenChanged', true);
4598
4618
 
4619
+ // Force YouTube custom controls to be visible in fullscreen
4620
+ if (this.isYouTubeCustomControlsMode) {
4621
+ const controlsBar = document.getElementById('uvf-controls') as HTMLElement;
4622
+ const topBar = document.querySelector('.uvf-top-bar') as HTMLElement;
4623
+
4624
+ if (controlsBar) {
4625
+ controlsBar.style.position = 'fixed';
4626
+ controlsBar.style.bottom = '0';
4627
+ controlsBar.style.left = '0';
4628
+ controlsBar.style.right = '0';
4629
+ controlsBar.style.zIndex = '2147483645';
4630
+ controlsBar.style.display = 'flex';
4631
+ controlsBar.style.flexDirection = 'column';
4632
+ controlsBar.style.visibility = 'visible';
4633
+ controlsBar.style.opacity = '1';
4634
+ controlsBar.style.pointerEvents = 'auto';
4635
+ controlsBar.style.transform = 'translateY(0)';
4636
+ }
4637
+
4638
+ if (topBar) {
4639
+ topBar.style.position = 'fixed';
4640
+ topBar.style.top = '0';
4641
+ topBar.style.left = '0';
4642
+ topBar.style.right = '0';
4643
+ topBar.style.zIndex = '2147483645';
4644
+ topBar.style.display = 'flex';
4645
+ topBar.style.visibility = 'visible';
4646
+ topBar.style.opacity = '1';
4647
+ topBar.style.pointerEvents = 'auto';
4648
+ topBar.style.transform = 'translateY(0)';
4649
+ }
4650
+
4651
+ // Keep controls always visible in YouTube fullscreen
4652
+ this.playerWrapper?.classList.add('controls-visible');
4653
+ }
4654
+
4599
4655
  // Lock to landscape orientation on mobile devices
4600
4656
  await this.lockOrientationLandscape();
4601
4657
  } else {
@@ -7812,7 +7868,34 @@ export class WebPlayer extends BasePlayer {
7812
7868
  transform: translateY(-10px) !important;
7813
7869
  pointer-events: none;
7814
7870
  }
7815
-
7871
+
7872
+ /* YouTube custom controls in fullscreen - CRITICAL FIX for all devices */
7873
+ /* This rule applies regardless of device/orientation */
7874
+ .uvf-player-wrapper.youtube-custom-controls-mode.uvf-fullscreen .uvf-controls-bar,
7875
+ .uvf-player-wrapper.youtube-custom-controls-mode.uvf-fullscreen .uvf-top-bar {
7876
+ position: fixed !important;
7877
+ z-index: 2147483645 !important;
7878
+ visibility: visible !important;
7879
+ opacity: 1 !important;
7880
+ pointer-events: auto !important;
7881
+ transform: translateY(0) !important;
7882
+ }
7883
+
7884
+ .uvf-player-wrapper.youtube-custom-controls-mode.uvf-fullscreen .uvf-controls-bar {
7885
+ bottom: 0 !important;
7886
+ left: 0 !important;
7887
+ right: 0 !important;
7888
+ display: flex !important;
7889
+ flex-direction: column !important;
7890
+ }
7891
+
7892
+ .uvf-player-wrapper.youtube-custom-controls-mode.uvf-fullscreen .uvf-top-bar {
7893
+ top: 0 !important;
7894
+ left: 0 !important;
7895
+ right: 0 !important;
7896
+ display: flex !important;
7897
+ }
7898
+
7816
7899
  /* Fullscreen specific styles - DESKTOP AND LANDSCAPE ONLY */
7817
7900
  /* Mobile portrait uses Material You layout in fullscreen */
7818
7901
  @media not all and (max-width: 767px) and (orientation: portrait) {
@@ -7923,6 +8006,38 @@ export class WebPlayer extends BasePlayer {
7923
8006
  opacity: 1;
7924
8007
  transform: translateY(0);
7925
8008
  }
8009
+
8010
+ /* Ensure YouTube custom controls are visible in fullscreen */
8011
+ .uvf-player-wrapper.youtube-custom-controls-mode.uvf-fullscreen .uvf-controls-bar {
8012
+ position: fixed !important;
8013
+ bottom: 0 !important;
8014
+ left: 0 !important;
8015
+ right: 0 !important;
8016
+ z-index: 2147483645 !important;
8017
+ display: flex !important;
8018
+ flex-direction: column !important;
8019
+ visibility: visible !important;
8020
+ opacity: 1 !important;
8021
+ pointer-events: auto !important;
8022
+ }
8023
+
8024
+ .uvf-player-wrapper.youtube-custom-controls-mode.uvf-fullscreen .uvf-top-bar {
8025
+ position: fixed !important;
8026
+ top: 0 !important;
8027
+ left: 0 !important;
8028
+ right: 0 !important;
8029
+ z-index: 2147483645 !important;
8030
+ display: flex !important;
8031
+ visibility: visible !important;
8032
+ opacity: 1 !important;
8033
+ pointer-events: auto !important;
8034
+ }
8035
+
8036
+ /* Keep controls always visible in fullscreen for YouTube */
8037
+ .uvf-player-wrapper.youtube-custom-controls-mode.uvf-fullscreen .uvf-controls-bar,
8038
+ .uvf-player-wrapper.youtube-custom-controls-mode.uvf-fullscreen .uvf-top-bar {
8039
+ transform: translateY(0) !important;
8040
+ }
7926
8041
  }
7927
8042
 
7928
8043
  /* Safe Area Variables - Support for modern mobile devices */
@@ -10810,9 +10925,18 @@ export class WebPlayer extends BasePlayer {
10810
10925
  const progressBar = document.querySelector('.uvf-progress-bar') as HTMLElement;
10811
10926
  const progressFilled = document.getElementById('uvf-progress-filled') as HTMLElement;
10812
10927
  const progressHandle = document.getElementById('uvf-progress-handle') as HTMLElement;
10813
- if (!progressBar || !this.video) return;
10928
+ if (!progressBar) return;
10929
+
10930
+ // Get duration from YouTube player or regular video
10931
+ let duration: number;
10932
+ if (this.youtubePlayer && this.youtubePlayerReady) {
10933
+ duration = this.youtubePlayer.getDuration();
10934
+ } else if (this.video) {
10935
+ duration = this.video.duration;
10936
+ } else {
10937
+ return; // No video source available
10938
+ }
10814
10939
 
10815
- const duration = this.video.duration;
10816
10940
  // Validate duration before calculating seek time
10817
10941
  if (!isFinite(duration) || isNaN(duration) || duration <= 0) {
10818
10942
  this.debugWarn('Invalid video duration, cannot seek via progress bar');