unified-video-framework 1.4.161 → 1.4.162

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.
@@ -4402,32 +4402,111 @@ export class WebPlayer extends BasePlayer {
4402
4402
  padding: 12px 16px;
4403
4403
  padding-bottom: calc(12px + var(--uvf-safe-area-bottom));
4404
4404
  z-index: 1000;
4405
+ /* Ensure controls are always visible */
4406
+ opacity: 1 !important;
4407
+ visibility: visible !important;
4408
+ display: flex !important;
4409
+ flex-direction: column !important;
4405
4410
  /* Ensure hardware acceleration */
4406
4411
  -webkit-transform: translate3d(0,0,0);
4407
4412
  transform: translate3d(0,0,0);
4408
4413
  }
4409
4414
 
4410
- /* Progress section */
4415
+ /* Force controls visibility on mobile portrait */
4416
+ .uvf-responsive-container .uvf-controls-bar {
4417
+ opacity: 1 !important;
4418
+ visibility: visible !important;
4419
+ transform: translateY(0) !important;
4420
+ pointer-events: auto !important;
4421
+ }
4422
+
4423
+ /* Progress section - ensure visibility */
4411
4424
  .uvf-progress-section {
4412
4425
  width: 100%;
4413
4426
  margin-bottom: 8px;
4427
+ opacity: 1 !important;
4428
+ visibility: visible !important;
4429
+ display: block !important;
4430
+ }
4431
+
4432
+ /* Progress bar styling */
4433
+ .uvf-progress-bar-wrapper {
4434
+ opacity: 1 !important;
4435
+ visibility: visible !important;
4436
+ }
4437
+
4438
+ .uvf-progress-bar {
4439
+ height: 4px;
4440
+ background: rgba(255, 255, 255, 0.3);
4441
+ border-radius: 2px;
4442
+ }
4443
+
4444
+ .uvf-progress-filled {
4445
+ background: var(--uvf-accent-1, #8B5CF6);
4446
+ height: 100%;
4447
+ border-radius: 2px;
4414
4448
  }
4415
4449
 
4416
- /* Controls row alignment */
4450
+ /* Controls row alignment - ensure visibility */
4417
4451
  .uvf-controls-row {
4418
4452
  width: 100%;
4419
- display: flex;
4453
+ display: flex !important;
4420
4454
  align-items: center;
4421
4455
  justify-content: flex-start;
4422
4456
  gap: 12px;
4457
+ opacity: 1 !important;
4458
+ visibility: visible !important;
4459
+ margin-top: 8px;
4460
+ }
4461
+
4462
+ /* Time display visibility */
4463
+ .uvf-time-display {
4464
+ color: #fff;
4465
+ font-size: 12px;
4466
+ font-weight: 500;
4467
+ opacity: 1 !important;
4468
+ visibility: visible !important;
4469
+ display: block !important;
4470
+ }
4471
+
4472
+ /* Control buttons visibility */
4473
+ .uvf-control-btn {
4474
+ opacity: 1 !important;
4475
+ visibility: visible !important;
4476
+ display: flex !important;
4477
+ color: #fff;
4423
4478
  }
4424
4479
 
4425
- /* Right controls */
4480
+ .uvf-control-btn svg {
4481
+ fill: #fff;
4482
+ opacity: 1;
4483
+ }
4484
+
4485
+ /* Right controls - ensure visibility */
4426
4486
  .uvf-right-controls {
4427
4487
  margin-left: auto;
4428
- display: flex;
4488
+ display: flex !important;
4429
4489
  align-items: center;
4430
4490
  gap: 8px;
4491
+ opacity: 1 !important;
4492
+ visibility: visible !important;
4493
+ }
4494
+
4495
+ /* Force controls to be always visible in portrait mode */
4496
+ .uvf-responsive-container .uvf-player-wrapper.uvf-controls-visible .uvf-controls-bar,
4497
+ .uvf-responsive-container .uvf-player-wrapper:hover .uvf-controls-bar,
4498
+ .uvf-responsive-container .uvf-controls-bar {
4499
+ opacity: 1 !important;
4500
+ transform: translateY(0) !important;
4501
+ visibility: visible !important;
4502
+ display: flex !important;
4503
+ pointer-events: auto !important;
4504
+ }
4505
+
4506
+ /* Ensure all child elements are visible */
4507
+ .uvf-responsive-container .uvf-controls-bar * {
4508
+ opacity: 1 !important;
4509
+ visibility: visible !important;
4431
4510
  }
4432
4511
 
4433
4512
  /* Center play button positioned within video */
@@ -5311,13 +5390,234 @@ export class WebPlayer extends BasePlayer {
5311
5390
 
5312
5391
  /* Large screens - Enhanced desktop experience */
5313
5392
  @media screen and (min-width: 1024px) {
5393
+ /* Reset mobile portrait styles for desktop */
5314
5394
  .uvf-responsive-container {
5395
+ display: block !important; /* Override mobile flexbox */
5396
+ position: relative !important; /* Override mobile fixed */
5397
+ height: auto !important; /* Override mobile viewport height */
5398
+ background: transparent !important; /* Override mobile black background */
5315
5399
  padding: 10px;
5316
5400
  }
5317
5401
 
5402
+ /* Remove mobile pseudo-elements on desktop */
5403
+ .uvf-responsive-container::before,
5404
+ .uvf-responsive-container::after {
5405
+ display: none !important;
5406
+ }
5407
+
5408
+ /* Desktop player wrapper */
5409
+ .uvf-responsive-container .uvf-player-wrapper {
5410
+ width: 100% !important; /* Override mobile width */
5411
+ height: auto !important; /* Override mobile height */
5412
+ display: block !important; /* Override mobile flexbox */
5413
+ position: relative !important;
5414
+ max-width: none; /* Allow full width if needed */
5415
+ }
5416
+
5417
+ /* Desktop video container */
5418
+ .uvf-responsive-container .uvf-video-container {
5419
+ width: 100% !important;
5420
+ height: auto !important;
5421
+ position: relative;
5422
+ aspect-ratio: 16/9; /* Maintain desktop aspect ratio */
5423
+ background: #000;
5424
+ }
5425
+
5426
+ /* Desktop controls positioning */
5318
5427
  .uvf-controls-bar {
5428
+ position: absolute !important;
5429
+ bottom: 0 !important;
5430
+ left: 0 !important;
5431
+ right: 0 !important;
5319
5432
  padding: 20px;
5320
5433
  background: linear-gradient(to top, var(--uvf-overlay-strong) 0%, var(--uvf-overlay-medium) 60%, var(--uvf-overlay-transparent) 100%);
5434
+ /* Reset mobile overrides for desktop */
5435
+ opacity: 0; /* Default hidden state on desktop */
5436
+ transform: translateY(10px); /* Default hidden position */
5437
+ transition: all 0.3s ease;
5438
+ }
5439
+
5440
+ /* Desktop hover behavior */
5441
+ .uvf-player-wrapper:hover .uvf-controls-bar,
5442
+ .uvf-player-wrapper.controls-visible .uvf-controls-bar {
5443
+ opacity: 1 !important;
5444
+ transform: translateY(0) !important;
5445
+ }
5446
+
5447
+ /* Desktop progress section */
5448
+ .uvf-progress-section {
5449
+ margin-bottom: 15px;
5450
+ width: 100%;
5451
+ }
5452
+
5453
+ /* Desktop controls row */
5454
+ .uvf-controls-row {
5455
+ display: flex;
5456
+ align-items: center;
5457
+ justify-content: flex-start;
5458
+ gap: 14px;
5459
+ width: 100%;
5460
+ }
5461
+
5462
+ /* Desktop control buttons */
5463
+ .uvf-control-btn {
5464
+ width: 40px;
5465
+ height: 40px;
5466
+ min-width: 40px;
5467
+ min-height: 40px;
5468
+ display: flex;
5469
+ align-items: center;
5470
+ justify-content: center;
5471
+ border: none;
5472
+ border-radius: 50%;
5473
+ background: rgba(255, 255, 255, 0.1);
5474
+ color: #fff;
5475
+ cursor: pointer;
5476
+ transition: all 0.2s cubic-bezier(0.4, 0.0, 0.2, 1);
5477
+ backdrop-filter: blur(8px);
5478
+ }
5479
+
5480
+ .uvf-control-btn:hover {
5481
+ transform: scale(1.1);
5482
+ background: rgba(255, 255, 255, 0.2);
5483
+ }
5484
+
5485
+ .uvf-control-btn.play-pause {
5486
+ width: 50px;
5487
+ height: 50px;
5488
+ min-width: 50px;
5489
+ min-height: 50px;
5490
+ background: linear-gradient(135deg, var(--uvf-accent-1), var(--uvf-accent-2));
5491
+ box-shadow: 0 2px 8px rgba(0,0,0,0.2);
5492
+ }
5493
+
5494
+ .uvf-control-btn.play-pause:hover {
5495
+ transform: scale(1.08);
5496
+ box-shadow: 0 4px 12px rgba(0,0,0,0.3);
5497
+ }
5498
+
5499
+ .uvf-control-btn svg {
5500
+ width: 20px;
5501
+ height: 20px;
5502
+ fill: #fff;
5503
+ }
5504
+
5505
+ .uvf-control-btn.play-pause svg {
5506
+ width: 24px;
5507
+ height: 24px;
5508
+ }
5509
+
5510
+ /* Desktop right controls */
5511
+ .uvf-right-controls {
5512
+ margin-left: auto;
5513
+ display: flex;
5514
+ align-items: center;
5515
+ gap: 8px;
5516
+ }
5517
+
5518
+ /* Desktop time display */
5519
+ .uvf-time-display {
5520
+ color: #fff;
5521
+ font-size: 14px;
5522
+ font-weight: 500;
5523
+ padding: 0 10px;
5524
+ }
5525
+
5526
+ /* Desktop volume control */
5527
+ .uvf-volume-panel {
5528
+ display: flex !important; /* Show volume slider on desktop */
5529
+ align-items: center;
5530
+ gap: 8px;
5531
+ }
5532
+
5533
+ .uvf-volume-slider {
5534
+ width: 80px;
5535
+ height: 4px;
5536
+ background: rgba(255, 255, 255, 0.3);
5537
+ border-radius: 2px;
5538
+ cursor: pointer;
5539
+ }
5540
+
5541
+ /* Desktop settings and other controls */
5542
+ .uvf-quality-badge {
5543
+ display: block;
5544
+ background: rgba(255, 255, 255, 0.1);
5545
+ color: #fff;
5546
+ padding: 4px 8px;
5547
+ border-radius: 4px;
5548
+ font-size: 11px;
5549
+ font-weight: 500;
5550
+ }
5551
+
5552
+ /* Desktop progress bar */
5553
+ .uvf-progress-bar {
5554
+ height: 2px;
5555
+ background: rgba(255, 255, 255, 0.2);
5556
+ border-radius: 4px;
5557
+ cursor: pointer;
5558
+ transition: height 0.2s ease;
5559
+ }
5560
+
5561
+ .uvf-progress-bar-wrapper:hover .uvf-progress-bar {
5562
+ height: 4px;
5563
+ }
5564
+
5565
+ .uvf-progress-filled {
5566
+ background: var(--uvf-accent-1, #8B5CF6);
5567
+ height: 100%;
5568
+ border-radius: 4px;
5569
+ }
5570
+
5571
+ .uvf-progress-handle {
5572
+ width: 12px;
5573
+ height: 12px;
5574
+ background: #fff;
5575
+ border-radius: 50%;
5576
+ position: absolute;
5577
+ top: 50%;
5578
+ transform: translateY(-50%);
5579
+ cursor: grab;
5580
+ opacity: 0;
5581
+ transition: opacity 0.2s ease;
5582
+ }
5583
+
5584
+ .uvf-progress-bar-wrapper:hover .uvf-progress-handle {
5585
+ opacity: 1;
5586
+ }
5587
+
5588
+ /* Desktop center play button */
5589
+ .uvf-center-play-container {
5590
+ position: absolute;
5591
+ top: 50%;
5592
+ left: 50%;
5593
+ transform: translate(-50%, -50%);
5594
+ z-index: 8;
5595
+ }
5596
+
5597
+ .uvf-center-play-btn {
5598
+ width: clamp(56px, 10vw, 72px);
5599
+ height: clamp(56px, 10vw, 72px);
5600
+ background: linear-gradient(135deg, var(--uvf-accent-1), var(--uvf-accent-2));
5601
+ border: none;
5602
+ border-radius: 50%;
5603
+ display: flex;
5604
+ align-items: center;
5605
+ justify-content: center;
5606
+ cursor: pointer;
5607
+ box-shadow: 0 4px 16px rgba(0,0,0,0.3);
5608
+ transition: all 0.25s ease;
5609
+ }
5610
+
5611
+ .uvf-center-play-btn:hover {
5612
+ transform: scale(1.1);
5613
+ box-shadow: 0 6px 20px rgba(0,0,0,0.4);
5614
+ }
5615
+
5616
+ .uvf-center-play-btn svg {
5617
+ width: clamp(24px, 4vw, 30px);
5618
+ height: clamp(24px, 4vw, 30px);
5619
+ fill: #fff;
5620
+ margin-left: 2px;
5321
5621
  }
5322
5622
 
5323
5623
  .uvf-progress-section {
@@ -8465,8 +8765,27 @@ export class WebPlayer extends BasePlayer {
8465
8765
  // Speed options
8466
8766
  settingsMenu.querySelectorAll('.speed-option').forEach(option => {
8467
8767
  option.addEventListener('click', (e) => {
8768
+ e.preventDefault();
8769
+ e.stopPropagation();
8770
+
8468
8771
  const speed = parseFloat((e.target as HTMLElement).dataset.speed || '1');
8772
+
8773
+ // Update active state immediately
8774
+ this.updateSettingsActiveStates('speed-option', e.target as HTMLElement);
8775
+
8776
+ // Set the speed
8469
8777
  this.setPlaybackRateFromSettings(speed);
8778
+
8779
+ // Update the accordion header text immediately
8780
+ const speedLabel = speed === 1 ? 'Normal' : `${speed}x`;
8781
+ const accordionCurrent = option.closest('.uvf-accordion-item')?.querySelector('.uvf-accordion-current');
8782
+ if (accordionCurrent) {
8783
+ accordionCurrent.textContent = speedLabel;
8784
+ }
8785
+
8786
+ this.debugLog(`Speed selected: ${speed}x`);
8787
+
8788
+ // Update accordion after selection
8470
8789
  this.updateAccordionAfterSelection('speed');
8471
8790
  });
8472
8791
  });
@@ -8474,8 +8793,28 @@ export class WebPlayer extends BasePlayer {
8474
8793
  // Quality options
8475
8794
  settingsMenu.querySelectorAll('.quality-option').forEach(option => {
8476
8795
  option.addEventListener('click', (e) => {
8796
+ e.preventDefault();
8797
+ e.stopPropagation();
8798
+
8477
8799
  const quality = (e.target as HTMLElement).dataset.quality || 'auto';
8800
+
8801
+ // Update active state immediately
8802
+ this.updateSettingsActiveStates('quality-option', e.target as HTMLElement);
8803
+
8804
+ // Set the quality
8478
8805
  this.setQualityFromSettings(quality);
8806
+
8807
+ // Update the accordion header text immediately
8808
+ const qualityItem = this.availableQualities.find(q => q.value === quality);
8809
+ const qualityLabel = qualityItem ? qualityItem.label : 'Auto';
8810
+ const accordionCurrent = option.closest('.uvf-accordion-item')?.querySelector('.uvf-accordion-current');
8811
+ if (accordionCurrent) {
8812
+ accordionCurrent.textContent = qualityLabel;
8813
+ }
8814
+
8815
+ this.debugLog(`Quality selected: ${quality} (${qualityLabel})`);
8816
+
8817
+ // Update accordion after selection
8479
8818
  this.updateAccordionAfterSelection('quality');
8480
8819
  });
8481
8820
  });
@@ -8483,8 +8822,28 @@ export class WebPlayer extends BasePlayer {
8483
8822
  // Subtitle options
8484
8823
  settingsMenu.querySelectorAll('.subtitle-option').forEach(option => {
8485
8824
  option.addEventListener('click', (e) => {
8825
+ e.preventDefault();
8826
+ e.stopPropagation();
8827
+
8486
8828
  const subtitle = (e.target as HTMLElement).dataset.subtitle || 'off';
8829
+
8830
+ // Update active state immediately
8831
+ this.updateSettingsActiveStates('subtitle-option', e.target as HTMLElement);
8832
+
8833
+ // Set the subtitle
8487
8834
  this.setSubtitle(subtitle);
8835
+
8836
+ // Update the accordion header text immediately
8837
+ const subtitleItem = this.availableSubtitles.find(s => s.value === subtitle);
8838
+ const subtitleLabel = subtitleItem ? subtitleItem.label : 'Off';
8839
+ const accordionCurrent = option.closest('.uvf-accordion-item')?.querySelector('.uvf-accordion-current');
8840
+ if (accordionCurrent) {
8841
+ accordionCurrent.textContent = subtitleLabel;
8842
+ }
8843
+
8844
+ this.debugLog(`Subtitle selected: ${subtitle} (${subtitleLabel})`);
8845
+
8846
+ // Update accordion after selection
8488
8847
  this.updateAccordionAfterSelection('subtitles');
8489
8848
  });
8490
8849
  });
@@ -8540,13 +8899,25 @@ export class WebPlayer extends BasePlayer {
8540
8899
  * Update accordion after user makes a selection
8541
8900
  */
8542
8901
  private updateAccordionAfterSelection(section: string): void {
8543
- // Just update the current values without closing
8544
- // User can manually close or it will close when they click outside
8902
+ // Close the accordion section after selection
8903
+ const settingsMenu = document.getElementById('uvf-settings-menu');
8904
+ if (settingsMenu) {
8905
+ settingsMenu.querySelectorAll('.uvf-accordion-item.expanded').forEach(item => {
8906
+ item.classList.remove('expanded');
8907
+ });
8908
+ }
8909
+
8910
+ // Update the current values and refresh the menu
8545
8911
  setTimeout(() => {
8546
8912
  // Refresh the menu to update current values
8547
8913
  this.generateAccordionMenu();
8548
8914
  this.setupSettingsEventListeners();
8549
- }, 100);
8915
+ }, 50);
8916
+
8917
+ // Auto-hide the settings menu after selection (optional)
8918
+ setTimeout(() => {
8919
+ this.hideSettingsMenu();
8920
+ }, 150);
8550
8921
  }
8551
8922
 
8552
8923
  /**