unified-video-framework 1.4.163 → 1.4.165
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.
|
@@ -51,6 +51,9 @@ export class WebPlayer extends BasePlayer {
|
|
|
51
51
|
private currentPlaybackRate = 1;
|
|
52
52
|
private isDragging: boolean = false;
|
|
53
53
|
|
|
54
|
+
// Settings menu state guard to keep controls interactive while open
|
|
55
|
+
private isSettingsOpen: boolean = false;
|
|
56
|
+
|
|
54
57
|
// Settings configuration
|
|
55
58
|
private settingsConfig = {
|
|
56
59
|
enabled: true, // Show settings button
|
|
@@ -4398,244 +4401,61 @@ export class WebPlayer extends BasePlayer {
|
|
|
4398
4401
|
}
|
|
4399
4402
|
|
|
4400
4403
|
/* Enhanced Responsive Media Queries with UX Best Practices */
|
|
4401
|
-
/* Mobile
|
|
4404
|
+
/* Mobile devices (portrait) - Enhanced UX with Safe Areas */
|
|
4402
4405
|
@media screen and (max-width: 767px) and (orientation: portrait) {
|
|
4403
|
-
/* CENTERED LAYOUT: 25% top black + 50% player + 25% bottom black */
|
|
4404
4406
|
.uvf-responsive-container {
|
|
4405
|
-
display: flex;
|
|
4406
|
-
flex-direction: column;
|
|
4407
|
-
height: 100vh;
|
|
4408
|
-
height: 100dvh;
|
|
4409
|
-
background: #000;
|
|
4410
|
-
overflow: hidden;
|
|
4411
|
-
position: fixed;
|
|
4412
|
-
top: 0;
|
|
4413
|
-
left: 0;
|
|
4414
|
-
width: 100vw;
|
|
4415
4407
|
padding: 0;
|
|
4408
|
+
width: 100vw !important;
|
|
4409
|
+
height: calc(100vh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
|
|
4416
4410
|
margin: 0;
|
|
4411
|
+
position: relative;
|
|
4412
|
+
overflow: hidden;
|
|
4417
4413
|
}
|
|
4418
4414
|
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
background: #000;
|
|
4424
|
-
pointer-events: none;
|
|
4425
|
-
}
|
|
4426
|
-
|
|
4427
|
-
/* BOTTOM BLACK AREA - 25% of viewport - COMPLETELY EMPTY */
|
|
4428
|
-
.uvf-responsive-container::after {
|
|
4429
|
-
content: '';
|
|
4430
|
-
flex: 0 0 25vh;
|
|
4431
|
-
background: #000;
|
|
4432
|
-
pointer-events: none;
|
|
4415
|
+
@supports (height: 100dvh) {
|
|
4416
|
+
.uvf-responsive-container {
|
|
4417
|
+
height: calc(100dvh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
|
|
4418
|
+
}
|
|
4433
4419
|
}
|
|
4434
4420
|
|
|
4435
|
-
/* CENTERED VIDEO PLAYER WRAPPER - 50% of viewport */
|
|
4436
4421
|
.uvf-responsive-container .uvf-player-wrapper {
|
|
4437
|
-
|
|
4438
|
-
|
|
4439
|
-
|
|
4440
|
-
align-items: center;
|
|
4441
|
-
justify-content: center;
|
|
4442
|
-
background: #000;
|
|
4443
|
-
position: relative;
|
|
4444
|
-
overflow: hidden; /* CRITICAL: Ensure nothing extends beyond this area */
|
|
4422
|
+
width: 100vw !important;
|
|
4423
|
+
height: 100% !important;
|
|
4424
|
+
min-height: calc(100vh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
|
|
4445
4425
|
}
|
|
4446
4426
|
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
position: relative;
|
|
4452
|
-
background: #000;
|
|
4453
|
-
border-radius: 0;
|
|
4454
|
-
overflow: hidden;
|
|
4427
|
+
@supports (height: 100dvh) {
|
|
4428
|
+
.uvf-responsive-container .uvf-player-wrapper {
|
|
4429
|
+
min-height: calc(100dvh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
|
|
4430
|
+
}
|
|
4455
4431
|
}
|
|
4456
4432
|
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
background: #000;
|
|
4433
|
+
.uvf-responsive-container .uvf-video-container {
|
|
4434
|
+
width: 100vw !important;
|
|
4435
|
+
height: 100% !important;
|
|
4436
|
+
aspect-ratio: unset !important;
|
|
4437
|
+
min-height: inherit;
|
|
4463
4438
|
}
|
|
4464
4439
|
|
|
4465
|
-
/*
|
|
4440
|
+
/* Enhanced mobile controls bar with safe area padding - iOS Safari specific fixes */
|
|
4466
4441
|
.uvf-controls-bar {
|
|
4467
4442
|
position: absolute !important;
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
padding: 12px
|
|
4475
|
-
|
|
4476
|
-
z-index: 1000;
|
|
4477
|
-
/* Ensure controls are visible and contained */
|
|
4478
|
-
opacity: 1 !important;
|
|
4479
|
-
visibility: visible !important;
|
|
4480
|
-
display: flex !important;
|
|
4481
|
-
flex-direction: column !important;
|
|
4482
|
-
/* Hardware acceleration */
|
|
4483
|
-
-webkit-transform: translate3d(0,0,0);
|
|
4484
|
-
transform: translate3d(0,0,0);
|
|
4485
|
-
/* CRITICAL: Prevent any overflow into black areas */
|
|
4486
|
-
max-height: calc(100% - 40px); /* Leave 20px margin from top and bottom */
|
|
4487
|
-
max-width: calc(100% - 32px); /* Leave 16px margin from left and right */
|
|
4488
|
-
box-sizing: border-box;
|
|
4489
|
-
/* Visual containment indicators */
|
|
4490
|
-
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
4491
|
-
backdrop-filter: blur(10px);
|
|
4492
|
-
contain: layout style paint; /* CSS containment */
|
|
4493
|
-
}
|
|
4494
|
-
|
|
4495
|
-
/* Force controls and all child elements to stay within video container */
|
|
4496
|
-
.uvf-responsive-container .uvf-controls-bar {
|
|
4497
|
-
opacity: 1 !important;
|
|
4498
|
-
visibility: visible !important;
|
|
4499
|
-
transform: translateY(0) !important;
|
|
4500
|
-
pointer-events: auto !important;
|
|
4501
|
-
/* Ensure no child elements extend beyond container */
|
|
4502
|
-
contain: layout style paint;
|
|
4503
|
-
}
|
|
4504
|
-
|
|
4505
|
-
/* Ensure all child elements of controls stay within bounds */
|
|
4506
|
-
.uvf-responsive-container .uvf-controls-bar * {
|
|
4507
|
-
max-width: 100%;
|
|
4443
|
+
bottom: 0 !important;
|
|
4444
|
+
left: 0 !important;
|
|
4445
|
+
right: 0 !important;
|
|
4446
|
+
padding: 16px 12px;
|
|
4447
|
+
padding-bottom: calc(16px + var(--uvf-safe-area-bottom, 0px));
|
|
4448
|
+
padding-left: calc(12px + var(--uvf-safe-area-left, 0px));
|
|
4449
|
+
padding-right: calc(12px + var(--uvf-safe-area-right, 0px));
|
|
4450
|
+
background: linear-gradient(to top, var(--uvf-overlay-strong) 0%, var(--uvf-overlay-medium) 80%, var(--uvf-overlay-transparent) 100%);
|
|
4508
4451
|
box-sizing: border-box;
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
visibility: visible !important;
|
|
4517
|
-
display: block !important;
|
|
4518
|
-
}
|
|
4519
|
-
|
|
4520
|
-
/* Progress bar styling */
|
|
4521
|
-
.uvf-progress-bar-wrapper {
|
|
4522
|
-
opacity: 1 !important;
|
|
4523
|
-
visibility: visible !important;
|
|
4524
|
-
}
|
|
4525
|
-
|
|
4526
|
-
.uvf-progress-bar {
|
|
4527
|
-
height: 4px;
|
|
4528
|
-
background: rgba(255, 255, 255, 0.3);
|
|
4529
|
-
border-radius: 2px;
|
|
4530
|
-
}
|
|
4531
|
-
|
|
4532
|
-
.uvf-progress-filled {
|
|
4533
|
-
background: var(--uvf-accent-1, #8B5CF6);
|
|
4534
|
-
height: 100%;
|
|
4535
|
-
border-radius: 2px;
|
|
4536
|
-
}
|
|
4537
|
-
|
|
4538
|
-
/* Controls row alignment - ensure visibility */
|
|
4539
|
-
.uvf-controls-row {
|
|
4540
|
-
width: 100%;
|
|
4541
|
-
display: flex !important;
|
|
4542
|
-
align-items: center;
|
|
4543
|
-
justify-content: flex-start;
|
|
4544
|
-
gap: 12px;
|
|
4545
|
-
opacity: 1 !important;
|
|
4546
|
-
visibility: visible !important;
|
|
4547
|
-
margin-top: 8px;
|
|
4548
|
-
}
|
|
4549
|
-
|
|
4550
|
-
/* Time display visibility */
|
|
4551
|
-
.uvf-time-display {
|
|
4552
|
-
color: #fff;
|
|
4553
|
-
font-size: 12px;
|
|
4554
|
-
font-weight: 500;
|
|
4555
|
-
opacity: 1 !important;
|
|
4556
|
-
visibility: visible !important;
|
|
4557
|
-
display: block !important;
|
|
4558
|
-
}
|
|
4559
|
-
|
|
4560
|
-
/* Control buttons visibility */
|
|
4561
|
-
.uvf-control-btn {
|
|
4562
|
-
min-width: 44px;
|
|
4563
|
-
min-height: 44px;
|
|
4564
|
-
display: flex !important;
|
|
4565
|
-
align-items: center;
|
|
4566
|
-
justify-content: center;
|
|
4567
|
-
border-radius: 50%;
|
|
4568
|
-
background: rgba(255, 255, 255, 0.1);
|
|
4569
|
-
backdrop-filter: blur(8px);
|
|
4570
|
-
color: #fff;
|
|
4571
|
-
opacity: 1 !important;
|
|
4572
|
-
visibility: visible !important;
|
|
4573
|
-
transition: all 0.2s ease;
|
|
4574
|
-
}
|
|
4575
|
-
|
|
4576
|
-
.uvf-control-btn:active {
|
|
4577
|
-
transform: scale(0.95);
|
|
4578
|
-
background: rgba(255, 255, 255, 0.2);
|
|
4579
|
-
}
|
|
4580
|
-
|
|
4581
|
-
/* Play/pause button prominence */
|
|
4582
|
-
.uvf-control-btn.play-pause {
|
|
4583
|
-
background: linear-gradient(135deg, var(--uvf-accent-1), var(--uvf-accent-2));
|
|
4584
|
-
min-width: 52px;
|
|
4585
|
-
min-height: 52px;
|
|
4586
|
-
box-shadow: 0 2px 8px rgba(0,0,0,0.3);
|
|
4587
|
-
}
|
|
4588
|
-
|
|
4589
|
-
.uvf-control-btn.play-pause:active {
|
|
4590
|
-
transform: scale(0.92);
|
|
4591
|
-
box-shadow: 0 1px 4px rgba(0,0,0,0.4);
|
|
4592
|
-
}
|
|
4593
|
-
|
|
4594
|
-
.uvf-control-btn svg {
|
|
4595
|
-
fill: #fff;
|
|
4596
|
-
opacity: 1;
|
|
4597
|
-
}
|
|
4598
|
-
|
|
4599
|
-
/* Right controls */
|
|
4600
|
-
.uvf-right-controls {
|
|
4601
|
-
margin-left: auto;
|
|
4602
|
-
display: flex !important;
|
|
4603
|
-
align-items: center;
|
|
4604
|
-
gap: 8px;
|
|
4605
|
-
opacity: 1 !important;
|
|
4606
|
-
visibility: visible !important;
|
|
4607
|
-
}
|
|
4608
|
-
|
|
4609
|
-
/* Center play button positioned within video */
|
|
4610
|
-
.uvf-center-play-container {
|
|
4611
|
-
position: absolute;
|
|
4612
|
-
top: 50%;
|
|
4613
|
-
left: 50%;
|
|
4614
|
-
transform: translate(-50%, -50%);
|
|
4615
|
-
z-index: 8;
|
|
4616
|
-
pointer-events: none;
|
|
4617
|
-
}
|
|
4618
|
-
|
|
4619
|
-
.uvf-center-play-btn {
|
|
4620
|
-
pointer-events: auto;
|
|
4621
|
-
}
|
|
4622
|
-
|
|
4623
|
-
/* Top controls within video */
|
|
4624
|
-
.uvf-top-controls {
|
|
4625
|
-
position: absolute;
|
|
4626
|
-
top: calc(12px + var(--uvf-safe-area-top));
|
|
4627
|
-
right: calc(16px + var(--uvf-safe-area-right));
|
|
4628
|
-
z-index: 9;
|
|
4629
|
-
}
|
|
4630
|
-
|
|
4631
|
-
/* Title bar within video */
|
|
4632
|
-
.uvf-title-bar {
|
|
4633
|
-
position: absolute;
|
|
4634
|
-
top: calc(12px + var(--uvf-safe-area-top));
|
|
4635
|
-
left: calc(16px + var(--uvf-safe-area-left));
|
|
4636
|
-
right: calc(80px + var(--uvf-safe-area-right));
|
|
4637
|
-
z-index: 9;
|
|
4638
|
-
padding: 8px 0;
|
|
4452
|
+
z-index: 1000 !important;
|
|
4453
|
+
/* iOS Safari specific fixes */
|
|
4454
|
+
transform: translateZ(0);
|
|
4455
|
+
-webkit-transform: translateZ(0);
|
|
4456
|
+
will-change: transform;
|
|
4457
|
+
/* Ensure proper stacking */
|
|
4458
|
+
isolation: isolate;
|
|
4639
4459
|
}
|
|
4640
4460
|
|
|
4641
4461
|
.uvf-progress-section {
|
|
@@ -6574,7 +6394,12 @@ export class WebPlayer extends BasePlayer {
|
|
|
6574
6394
|
|
|
6575
6395
|
// Force visibility if menu is active, hide if not active
|
|
6576
6396
|
if (settingsMenu) {
|
|
6577
|
-
|
|
6397
|
+
const activating = settingsMenu.classList.contains('active');
|
|
6398
|
+
if (activating) {
|
|
6399
|
+
this.isSettingsOpen = true;
|
|
6400
|
+
// Keep controls visible and interactive while menu is open
|
|
6401
|
+
this.showControls();
|
|
6402
|
+
if (this.hideControlsTimeout) clearTimeout(this.hideControlsTimeout);
|
|
6578
6403
|
settingsMenu.style.display = 'block';
|
|
6579
6404
|
settingsMenu.style.visibility = 'visible';
|
|
6580
6405
|
settingsMenu.style.opacity = '1';
|
|
@@ -6590,10 +6415,13 @@ export class WebPlayer extends BasePlayer {
|
|
|
6590
6415
|
settingsMenu.style.padding = '10px 0';
|
|
6591
6416
|
this.debugLog('Applied fallback styles to show menu');
|
|
6592
6417
|
} else {
|
|
6418
|
+
this.isSettingsOpen = false;
|
|
6593
6419
|
settingsMenu.style.display = 'none';
|
|
6594
6420
|
settingsMenu.style.visibility = 'hidden';
|
|
6595
6421
|
settingsMenu.style.opacity = '0';
|
|
6596
6422
|
this.debugLog('Applied fallback styles to hide menu');
|
|
6423
|
+
// After closing, allow auto-hide again if playing
|
|
6424
|
+
this.scheduleHideControls();
|
|
6597
6425
|
}
|
|
6598
6426
|
}
|
|
6599
6427
|
|
|
@@ -6633,6 +6461,19 @@ export class WebPlayer extends BasePlayer {
|
|
|
6633
6461
|
}
|
|
6634
6462
|
});
|
|
6635
6463
|
|
|
6464
|
+
// Keep controls active while interacting with settings menu
|
|
6465
|
+
if (settingsMenu) {
|
|
6466
|
+
const keepAlive = () => {
|
|
6467
|
+
if (!this.isSettingsOpen) return;
|
|
6468
|
+
this.showControls();
|
|
6469
|
+
if (this.hideControlsTimeout) clearTimeout(this.hideControlsTimeout);
|
|
6470
|
+
};
|
|
6471
|
+
settingsMenu.addEventListener('mouseenter', keepAlive);
|
|
6472
|
+
settingsMenu.addEventListener('mousemove', keepAlive);
|
|
6473
|
+
settingsMenu.addEventListener('touchstart', keepAlive, { passive: true } as any);
|
|
6474
|
+
settingsMenu.addEventListener('touchmove', keepAlive, { passive: true } as any);
|
|
6475
|
+
}
|
|
6476
|
+
|
|
6636
6477
|
// Add Escape key handler for settings menu
|
|
6637
6478
|
document.addEventListener('keydown', (e) => {
|
|
6638
6479
|
if (e.key === 'Escape' && settingsMenu?.classList.contains('active')) {
|
|
@@ -7284,6 +7125,8 @@ export class WebPlayer extends BasePlayer {
|
|
|
7284
7125
|
|
|
7285
7126
|
private hideControls(): void {
|
|
7286
7127
|
if (!this.state.isPlaying) return;
|
|
7128
|
+
// Never hide controls while settings menu is open
|
|
7129
|
+
if (this.isSettingsOpen) return;
|
|
7287
7130
|
|
|
7288
7131
|
const wrapper = this.container?.querySelector('.uvf-player-wrapper');
|
|
7289
7132
|
if (wrapper) {
|
|
@@ -7294,12 +7137,14 @@ export class WebPlayer extends BasePlayer {
|
|
|
7294
7137
|
|
|
7295
7138
|
private scheduleHideControls(): void {
|
|
7296
7139
|
if (!this.state.isPlaying) return;
|
|
7140
|
+
// Do not schedule auto-hide while settings are open
|
|
7141
|
+
if (this.isSettingsOpen) return;
|
|
7297
7142
|
|
|
7298
7143
|
if (this.hideControlsTimeout) clearTimeout(this.hideControlsTimeout);
|
|
7299
7144
|
// Use longer timeout in fullscreen for better UX
|
|
7300
7145
|
const timeout = this.isFullscreen() ? 4000 : 3000;
|
|
7301
7146
|
this.hideControlsTimeout = setTimeout(() => {
|
|
7302
|
-
if (this.state.isPlaying && !this.controlsContainer?.matches(':hover')) {
|
|
7147
|
+
if (this.state.isPlaying && !this.controlsContainer?.matches(':hover') && !this.isSettingsOpen) {
|
|
7303
7148
|
this.hideControls();
|
|
7304
7149
|
}
|
|
7305
7150
|
}, timeout);
|
|
@@ -8508,6 +8353,7 @@ export class WebPlayer extends BasePlayer {
|
|
|
8508
8353
|
if (!settingsMenu) return;
|
|
8509
8354
|
|
|
8510
8355
|
settingsMenu.classList.remove('active');
|
|
8356
|
+
this.isSettingsOpen = false;
|
|
8511
8357
|
|
|
8512
8358
|
// Apply fallback styles to ensure menu is hidden
|
|
8513
8359
|
settingsMenu.style.display = 'none';
|
|
@@ -8520,6 +8366,8 @@ export class WebPlayer extends BasePlayer {
|
|
|
8520
8366
|
});
|
|
8521
8367
|
|
|
8522
8368
|
this.debugLog('Settings menu hidden via hideSettingsMenu()');
|
|
8369
|
+
// Resume auto-hide if appropriate
|
|
8370
|
+
this.scheduleHideControls();
|
|
8523
8371
|
}
|
|
8524
8372
|
|
|
8525
8373
|
/**
|