unified-video-framework 1.4.160 → 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.
@@ -4329,6 +4329,217 @@ export class WebPlayer extends BasePlayer {
4329
4329
  @media screen and (max-width: 767px) {
4330
4330
  html, body {
4331
4331
  overflow-x: hidden;
4332
+ background: #000;
4333
+ }
4334
+
4335
+ /* Mobile Portrait Layout - Centered Player with Top/Bottom Black Areas */
4336
+ @media screen and (orientation: portrait) {
4337
+ .uvf-responsive-container {
4338
+ display: flex;
4339
+ flex-direction: column;
4340
+ height: 100vh;
4341
+ height: 100dvh;
4342
+ background: #000;
4343
+ overflow: hidden;
4344
+ position: fixed;
4345
+ top: 0;
4346
+ left: 0;
4347
+ width: 100vw;
4348
+ }
4349
+
4350
+ /* Top black area - 25% of viewport */
4351
+ .uvf-responsive-container::before {
4352
+ content: '';
4353
+ flex: 0 0 25vh;
4354
+ background: #000;
4355
+ pointer-events: none;
4356
+ }
4357
+
4358
+ /* Bottom black area - 25% of viewport */
4359
+ .uvf-responsive-container::after {
4360
+ content: '';
4361
+ flex: 0 0 25vh;
4362
+ background: #000;
4363
+ pointer-events: none;
4364
+ }
4365
+
4366
+ /* Centered video player wrapper - 50% of viewport */
4367
+ .uvf-responsive-container .uvf-player-wrapper {
4368
+ flex: 1;
4369
+ width: 100vw;
4370
+ display: flex;
4371
+ align-items: center;
4372
+ justify-content: center;
4373
+ background: #000;
4374
+ position: relative;
4375
+ }
4376
+
4377
+ /* Video container fills player wrapper */
4378
+ .uvf-responsive-container .uvf-video-container {
4379
+ width: 100%;
4380
+ height: 100%;
4381
+ position: relative;
4382
+ background: #000;
4383
+ border-radius: 0;
4384
+ overflow: hidden;
4385
+ }
4386
+
4387
+ /* Video element fills container */
4388
+ .uvf-responsive-container .uvf-video {
4389
+ width: 100%;
4390
+ height: 100%;
4391
+ object-fit: contain;
4392
+ background: #000;
4393
+ }
4394
+
4395
+ /* All controls positioned inside video container */
4396
+ .uvf-controls-bar {
4397
+ position: absolute !important;
4398
+ bottom: 0 !important;
4399
+ left: 0 !important;
4400
+ right: 0 !important;
4401
+ background: linear-gradient(to top, rgba(0,0,0,0.85) 0%, rgba(0,0,0,0.6) 60%, transparent 100%);
4402
+ padding: 12px 16px;
4403
+ padding-bottom: calc(12px + var(--uvf-safe-area-bottom));
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;
4410
+ /* Ensure hardware acceleration */
4411
+ -webkit-transform: translate3d(0,0,0);
4412
+ transform: translate3d(0,0,0);
4413
+ }
4414
+
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 */
4424
+ .uvf-progress-section {
4425
+ width: 100%;
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;
4448
+ }
4449
+
4450
+ /* Controls row alignment - ensure visibility */
4451
+ .uvf-controls-row {
4452
+ width: 100%;
4453
+ display: flex !important;
4454
+ align-items: center;
4455
+ justify-content: flex-start;
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;
4478
+ }
4479
+
4480
+ .uvf-control-btn svg {
4481
+ fill: #fff;
4482
+ opacity: 1;
4483
+ }
4484
+
4485
+ /* Right controls - ensure visibility */
4486
+ .uvf-right-controls {
4487
+ margin-left: auto;
4488
+ display: flex !important;
4489
+ align-items: center;
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;
4510
+ }
4511
+
4512
+ /* Center play button positioned within video */
4513
+ .uvf-center-play-container {
4514
+ position: absolute;
4515
+ top: 50%;
4516
+ left: 50%;
4517
+ transform: translate(-50%, -50%);
4518
+ z-index: 8;
4519
+ pointer-events: none;
4520
+ }
4521
+
4522
+ .uvf-center-play-btn {
4523
+ pointer-events: auto;
4524
+ }
4525
+
4526
+ /* Top controls within video */
4527
+ .uvf-top-controls {
4528
+ position: absolute;
4529
+ top: calc(12px + var(--uvf-safe-area-top));
4530
+ right: calc(16px + var(--uvf-safe-area-right));
4531
+ z-index: 9;
4532
+ }
4533
+
4534
+ /* Title bar within video */
4535
+ .uvf-title-bar {
4536
+ position: absolute;
4537
+ top: calc(12px + var(--uvf-safe-area-top));
4538
+ left: calc(16px + var(--uvf-safe-area-left));
4539
+ right: calc(80px + var(--uvf-safe-area-right));
4540
+ z-index: 9;
4541
+ padding: 8px 0;
4542
+ }
4332
4543
  }
4333
4544
 
4334
4545
  .uvf-player-wrapper {
@@ -4352,6 +4563,37 @@ export class WebPlayer extends BasePlayer {
4352
4563
  transform: translateZ(0);
4353
4564
  }
4354
4565
 
4566
+ /* Mobile controls optimization for touch */
4567
+ .uvf-control-btn {
4568
+ min-width: 44px;
4569
+ min-height: 44px;
4570
+ display: flex;
4571
+ align-items: center;
4572
+ justify-content: center;
4573
+ border-radius: 50%;
4574
+ transition: all 0.2s ease;
4575
+ background: rgba(255, 255, 255, 0.1);
4576
+ backdrop-filter: blur(8px);
4577
+ }
4578
+
4579
+ .uvf-control-btn:active {
4580
+ transform: scale(0.95);
4581
+ background: rgba(255, 255, 255, 0.2);
4582
+ }
4583
+
4584
+ /* Play/pause button prominence */
4585
+ .uvf-control-btn.play-pause {
4586
+ background: linear-gradient(135deg, var(--uvf-accent-1), var(--uvf-accent-2));
4587
+ min-width: 52px;
4588
+ min-height: 52px;
4589
+ box-shadow: 0 2px 8px rgba(0,0,0,0.3);
4590
+ }
4591
+
4592
+ .uvf-control-btn.play-pause:active {
4593
+ transform: scale(0.92);
4594
+ box-shadow: 0 1px 4px rgba(0,0,0,0.4);
4595
+ }
4596
+
4355
4597
  /* Fix for controls being cut off by virtual keyboard */
4356
4598
  .uvf-controls-bar {
4357
4599
  position: absolute !important;
@@ -4833,55 +5075,69 @@ export class WebPlayer extends BasePlayer {
4833
5075
  }
4834
5076
  }
4835
5077
 
4836
- /* Mobile devices (landscape) - Optimized for fullscreen viewing with safe areas */
5078
+ /* Mobile devices (landscape) - Fullscreen with controls inside video */
4837
5079
  @media screen and (max-width: 767px) and (orientation: landscape) {
4838
5080
  .uvf-responsive-container {
5081
+ position: fixed;
5082
+ top: 0;
5083
+ left: 0;
4839
5084
  width: 100vw !important;
4840
- height: calc(100vh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
5085
+ height: 100vh !important;
5086
+ height: 100dvh !important;
5087
+ background: #000;
5088
+ z-index: 9999;
5089
+ display: block; /* Override portrait flexbox */
4841
5090
  margin: 0;
4842
5091
  padding: 0;
4843
- position: relative;
4844
5092
  overflow: hidden;
4845
5093
  }
4846
5094
 
4847
- @supports (height: 100dvh) {
4848
- .uvf-responsive-container {
4849
- height: calc(100dvh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
4850
- }
5095
+ /* Remove pseudo-elements in landscape */
5096
+ .uvf-responsive-container::before,
5097
+ .uvf-responsive-container::after {
5098
+ display: none !important;
4851
5099
  }
4852
5100
 
4853
5101
  .uvf-responsive-container .uvf-player-wrapper {
4854
5102
  width: 100vw !important;
4855
- height: 100% !important;
4856
- min-height: calc(100vh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
4857
- }
4858
-
4859
- @supports (height: 100dvh) {
4860
- .uvf-responsive-container .uvf-player-wrapper {
4861
- min-height: calc(100dvh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
4862
- }
5103
+ height: 100vh !important;
5104
+ height: 100dvh !important;
5105
+ position: relative;
5106
+ display: block;
4863
5107
  }
4864
5108
 
4865
5109
  .uvf-responsive-container .uvf-video-container {
4866
5110
  width: 100vw !important;
4867
- height: 100% !important;
4868
- aspect-ratio: unset !important;
4869
- min-height: inherit;
5111
+ height: 100vh !important;
5112
+ height: 100dvh !important;
5113
+ position: relative;
5114
+ background: #000;
5115
+ overflow: hidden;
5116
+ }
5117
+
5118
+ .uvf-responsive-container .uvf-video {
5119
+ width: 100%;
5120
+ height: 100%;
5121
+ object-fit: contain;
5122
+ background: #000;
4870
5123
  }
4871
5124
 
4872
- /* Compact controls for landscape with safe area padding */
5125
+ /* Compact controls for landscape - positioned inside video container */
4873
5126
  .uvf-controls-bar {
4874
- position: absolute;
4875
- bottom: 0;
4876
- left: 0;
4877
- right: 0;
5127
+ position: absolute !important;
5128
+ bottom: 0 !important;
5129
+ left: 0 !important;
5130
+ right: 0 !important;
4878
5131
  padding: 10px 12px;
4879
5132
  padding-bottom: calc(10px + var(--uvf-safe-area-bottom));
4880
5133
  padding-left: calc(12px + var(--uvf-safe-area-left));
4881
5134
  padding-right: calc(12px + var(--uvf-safe-area-right));
4882
- background: linear-gradient(to top, var(--uvf-overlay-strong) 0%, var(--uvf-overlay-medium) 80%, var(--uvf-overlay-transparent) 100%);
5135
+ background: linear-gradient(to top, rgba(0,0,0,0.85) 0%, rgba(0,0,0,0.6) 60%, transparent 100%);
4883
5136
  box-sizing: border-box;
4884
5137
  z-index: 1000;
5138
+ /* Ensure hardware acceleration */
5139
+ -webkit-transform: translate3d(0,0,0);
5140
+ transform: translate3d(0,0,0);
4885
5141
  }
4886
5142
 
4887
5143
  .uvf-progress-section {
@@ -4917,16 +5173,36 @@ export class WebPlayer extends BasePlayer {
4917
5173
  height: 22px;
4918
5174
  }
4919
5175
 
4920
- /* Compact top controls with safe area padding */
5176
+ /* Compact top controls with safe area padding - inside video container */
4921
5177
  .uvf-top-controls {
5178
+ position: absolute;
4922
5179
  top: calc(8px + var(--uvf-safe-area-top));
4923
5180
  right: calc(12px + var(--uvf-safe-area-right));
4924
5181
  gap: 6px;
5182
+ z-index: 9;
5183
+ }
5184
+
5185
+ /* Center play button positioned within video container */
5186
+ .uvf-center-play-container {
5187
+ position: absolute;
5188
+ top: 50%;
5189
+ left: 50%;
5190
+ transform: translate(-50%, -50%);
5191
+ z-index: 8;
5192
+ pointer-events: none;
5193
+ }
5194
+
5195
+ .uvf-center-play-btn {
5196
+ pointer-events: auto;
4925
5197
  }
4926
5198
 
4927
5199
  .uvf-title-bar {
4928
- padding: 8px 12px;
4929
- padding-top: calc(8px + var(--uvf-safe-area-top));
5200
+ position: absolute;
5201
+ top: calc(8px + var(--uvf-safe-area-top));
5202
+ left: calc(12px + var(--uvf-safe-area-left));
5203
+ right: calc(80px + var(--uvf-safe-area-right));
5204
+ z-index: 9;
5205
+ padding: 8px 0;
4930
5206
  padding-left: calc(12px + var(--uvf-safe-area-left));
4931
5207
  padding-right: calc(12px + var(--uvf-safe-area-right));
4932
5208
  }
@@ -5114,13 +5390,234 @@ export class WebPlayer extends BasePlayer {
5114
5390
 
5115
5391
  /* Large screens - Enhanced desktop experience */
5116
5392
  @media screen and (min-width: 1024px) {
5393
+ /* Reset mobile portrait styles for desktop */
5117
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 */
5118
5399
  padding: 10px;
5119
5400
  }
5120
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 */
5121
5427
  .uvf-controls-bar {
5428
+ position: absolute !important;
5429
+ bottom: 0 !important;
5430
+ left: 0 !important;
5431
+ right: 0 !important;
5122
5432
  padding: 20px;
5123
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;
5124
5621
  }
5125
5622
 
5126
5623
  .uvf-progress-section {
@@ -8268,8 +8765,27 @@ export class WebPlayer extends BasePlayer {
8268
8765
  // Speed options
8269
8766
  settingsMenu.querySelectorAll('.speed-option').forEach(option => {
8270
8767
  option.addEventListener('click', (e) => {
8768
+ e.preventDefault();
8769
+ e.stopPropagation();
8770
+
8271
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
8272
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
8273
8789
  this.updateAccordionAfterSelection('speed');
8274
8790
  });
8275
8791
  });
@@ -8277,8 +8793,28 @@ export class WebPlayer extends BasePlayer {
8277
8793
  // Quality options
8278
8794
  settingsMenu.querySelectorAll('.quality-option').forEach(option => {
8279
8795
  option.addEventListener('click', (e) => {
8796
+ e.preventDefault();
8797
+ e.stopPropagation();
8798
+
8280
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
8281
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
8282
8818
  this.updateAccordionAfterSelection('quality');
8283
8819
  });
8284
8820
  });
@@ -8286,8 +8822,28 @@ export class WebPlayer extends BasePlayer {
8286
8822
  // Subtitle options
8287
8823
  settingsMenu.querySelectorAll('.subtitle-option').forEach(option => {
8288
8824
  option.addEventListener('click', (e) => {
8825
+ e.preventDefault();
8826
+ e.stopPropagation();
8827
+
8289
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
8290
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
8291
8847
  this.updateAccordionAfterSelection('subtitles');
8292
8848
  });
8293
8849
  });
@@ -8343,13 +8899,25 @@ export class WebPlayer extends BasePlayer {
8343
8899
  * Update accordion after user makes a selection
8344
8900
  */
8345
8901
  private updateAccordionAfterSelection(section: string): void {
8346
- // Just update the current values without closing
8347
- // 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
8348
8911
  setTimeout(() => {
8349
8912
  // Refresh the menu to update current values
8350
8913
  this.generateAccordionMenu();
8351
8914
  this.setupSettingsEventListeners();
8352
- }, 100);
8915
+ }, 50);
8916
+
8917
+ // Auto-hide the settings menu after selection (optional)
8918
+ setTimeout(() => {
8919
+ this.hideSettingsMenu();
8920
+ }, 150);
8353
8921
  }
8354
8922
 
8355
8923
  /**