unified-video-framework 1.4.166 → 1.4.167
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.
|
@@ -21,7 +21,6 @@ export class WebPlayer extends BasePlayer {
|
|
|
21
21
|
this.currentSubtitle = 'off';
|
|
22
22
|
this.currentPlaybackRate = 1;
|
|
23
23
|
this.isDragging = false;
|
|
24
|
-
this.isSettingsOpen = false;
|
|
25
24
|
this.settingsConfig = {
|
|
26
25
|
enabled: true,
|
|
27
26
|
speed: true,
|
|
@@ -53,16 +52,6 @@ export class WebPlayer extends BasePlayer {
|
|
|
53
52
|
this.hasTriedButtonFallback = false;
|
|
54
53
|
this.lastUserInteraction = 0;
|
|
55
54
|
this.showTimeTooltip = false;
|
|
56
|
-
this.lastTapTime = 0;
|
|
57
|
-
this.tapCount = 0;
|
|
58
|
-
this.tapTimeout = null;
|
|
59
|
-
this.longPressTimer = null;
|
|
60
|
-
this.longPressActive = false;
|
|
61
|
-
this.longPressStartTime = 0;
|
|
62
|
-
this.originalPlaybackRate = 1;
|
|
63
|
-
this.dominantColor = '#ff0000';
|
|
64
|
-
this.accentColor = '#ff4d4f';
|
|
65
|
-
this.surfaceTint = 'rgba(255, 0, 0, 0.08)';
|
|
66
55
|
this.autoplayCapabilities = {
|
|
67
56
|
canAutoplay: false,
|
|
68
57
|
canAutoplayMuted: false,
|
|
@@ -240,26 +229,6 @@ export class WebPlayer extends BasePlayer {
|
|
|
240
229
|
catch (_) { }
|
|
241
230
|
this.setupCastContextSafe();
|
|
242
231
|
this.updateMetadataUI();
|
|
243
|
-
this.enableMaterialYouMobileIfNeeded();
|
|
244
|
-
}
|
|
245
|
-
enableMaterialYouMobileIfNeeded() {
|
|
246
|
-
const isMobile = this.isMobileDevice();
|
|
247
|
-
const isPortrait = window.innerHeight > window.innerWidth;
|
|
248
|
-
if (isMobile && isPortrait && this.playerWrapper) {
|
|
249
|
-
this.debugLog('Enabling Material You mobile layout');
|
|
250
|
-
this.playerWrapper.classList.add('uvf-material-you-mobile');
|
|
251
|
-
window.addEventListener('resize', () => {
|
|
252
|
-
const isNowPortrait = window.innerHeight > window.innerWidth;
|
|
253
|
-
if (this.playerWrapper) {
|
|
254
|
-
if (isMobile && isNowPortrait) {
|
|
255
|
-
this.playerWrapper.classList.add('uvf-material-you-mobile');
|
|
256
|
-
}
|
|
257
|
-
else {
|
|
258
|
-
this.playerWrapper.classList.remove('uvf-material-you-mobile');
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
232
|
}
|
|
264
233
|
setupVideoEventListeners() {
|
|
265
234
|
if (!this.video)
|
|
@@ -337,7 +306,6 @@ export class WebPlayer extends BasePlayer {
|
|
|
337
306
|
this.state.duration = this.video.duration || 0;
|
|
338
307
|
this.debugLog('Metadata loaded - duration:', this.video.duration);
|
|
339
308
|
this.updateTimeDisplay();
|
|
340
|
-
this.renderChapterMarkersOnProgressBar();
|
|
341
309
|
this.emit('onLoadedMetadata', {
|
|
342
310
|
duration: this.video.duration || 0,
|
|
343
311
|
width: this.video.videoWidth || 0,
|
|
@@ -1907,8 +1875,6 @@ export class WebPlayer extends BasePlayer {
|
|
|
1907
1875
|
--uvf-scrollbar-thumb-hover-start: rgba(255,0,0,0.5);
|
|
1908
1876
|
--uvf-scrollbar-thumb-hover-end: rgba(255,0,0,0.6);
|
|
1909
1877
|
--uvf-firefox-scrollbar-color: rgba(255,255,255,0.25);
|
|
1910
|
-
/* Material You surface tint */
|
|
1911
|
-
--uvf-surface-tint: rgba(255, 0, 0, 0.08);
|
|
1912
1878
|
}
|
|
1913
1879
|
|
|
1914
1880
|
/* Player focus styles for better UX */
|
|
@@ -3964,15 +3930,24 @@ export class WebPlayer extends BasePlayer {
|
|
|
3964
3930
|
}
|
|
3965
3931
|
|
|
3966
3932
|
/* Enhanced Responsive Media Queries with UX Best Practices */
|
|
3967
|
-
|
|
3968
|
-
/* Material You Mobile Portrait Layout - 25% Black + 50% Video + 25% Black */
|
|
3933
|
+
/* Mobile devices (portrait) - Material You Design (25-50-25 Layout) */
|
|
3969
3934
|
@media screen and (max-width: 767px) and (orientation: portrait) {
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3935
|
+
.uvf-responsive-container {
|
|
3936
|
+
padding: 0;
|
|
3937
|
+
width: 100vw !important;
|
|
3938
|
+
height: 100vh;
|
|
3939
|
+
height: 100dvh;
|
|
3940
|
+
margin: 0;
|
|
3941
|
+
position: fixed;
|
|
3942
|
+
top: 0;
|
|
3943
|
+
left: 0;
|
|
3944
|
+
overflow: hidden;
|
|
3945
|
+
}
|
|
3946
|
+
|
|
3947
|
+
.uvf-responsive-container .uvf-player-wrapper {
|
|
3948
|
+
width: 100vw !important;
|
|
3973
3949
|
height: 100vh;
|
|
3974
3950
|
height: 100dvh;
|
|
3975
|
-
width: 100vw;
|
|
3976
3951
|
position: fixed;
|
|
3977
3952
|
top: 0;
|
|
3978
3953
|
left: 0;
|
|
@@ -3982,8 +3957,8 @@ export class WebPlayer extends BasePlayer {
|
|
|
3982
3957
|
overflow: hidden;
|
|
3983
3958
|
}
|
|
3984
3959
|
|
|
3985
|
-
|
|
3986
|
-
|
|
3960
|
+
/* Video container occupies middle 50% */
|
|
3961
|
+
.uvf-responsive-container .uvf-video-container {
|
|
3987
3962
|
height: 50vh;
|
|
3988
3963
|
height: 50dvh;
|
|
3989
3964
|
width: 100vw;
|
|
@@ -3991,22 +3966,20 @@ export class WebPlayer extends BasePlayer {
|
|
|
3991
3966
|
margin-top: 25vh;
|
|
3992
3967
|
margin-top: 25dvh;
|
|
3993
3968
|
aspect-ratio: unset !important;
|
|
3994
|
-
/* Match existing theme background */
|
|
3995
3969
|
background: radial-gradient(ellipse at center, #1a1a2e 0%, #000 100%);
|
|
3996
|
-
/* Material Design elevation */
|
|
3997
3970
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4),
|
|
3998
3971
|
0 4px 16px rgba(0, 0, 0, 0.3),
|
|
3999
3972
|
0 2px 8px rgba(0, 0, 0, 0.2);
|
|
4000
3973
|
}
|
|
4001
3974
|
|
|
4002
|
-
.uvf-
|
|
3975
|
+
.uvf-video {
|
|
4003
3976
|
width: 100%;
|
|
4004
3977
|
height: 100%;
|
|
4005
3978
|
object-fit: contain;
|
|
4006
3979
|
}
|
|
4007
3980
|
|
|
4008
|
-
/* Top black section (25%) - Tap zone
|
|
4009
|
-
.uvf-player-wrapper
|
|
3981
|
+
/* Top black section (25%) - Tap zone */
|
|
3982
|
+
.uvf-player-wrapper::before {
|
|
4010
3983
|
content: '';
|
|
4011
3984
|
position: absolute;
|
|
4012
3985
|
top: 0;
|
|
@@ -4020,8 +3993,8 @@ export class WebPlayer extends BasePlayer {
|
|
|
4020
3993
|
touch-action: manipulation;
|
|
4021
3994
|
}
|
|
4022
3995
|
|
|
4023
|
-
/* Bottom black section (25%) -
|
|
4024
|
-
.uvf-player-wrapper
|
|
3996
|
+
/* Bottom black section (25%) - Controls area */
|
|
3997
|
+
.uvf-player-wrapper::after {
|
|
4025
3998
|
content: '';
|
|
4026
3999
|
position: absolute;
|
|
4027
4000
|
bottom: 0;
|
|
@@ -4038,7 +4011,7 @@ export class WebPlayer extends BasePlayer {
|
|
|
4038
4011
|
}
|
|
4039
4012
|
|
|
4040
4013
|
/* Material surface container for controls */
|
|
4041
|
-
.uvf-
|
|
4014
|
+
.uvf-controls-bar {
|
|
4042
4015
|
position: absolute;
|
|
4043
4016
|
bottom: 0;
|
|
4044
4017
|
left: 0;
|
|
@@ -4053,13 +4026,12 @@ export class WebPlayer extends BasePlayer {
|
|
|
4053
4026
|
display: flex;
|
|
4054
4027
|
flex-direction: column;
|
|
4055
4028
|
justify-content: flex-end;
|
|
4056
|
-
/* Material Design surface with tint */
|
|
4057
4029
|
backdrop-filter: blur(24px);
|
|
4058
4030
|
-webkit-backdrop-filter: blur(24px);
|
|
4059
4031
|
}
|
|
4060
4032
|
|
|
4061
4033
|
/* Material surface tint overlay */
|
|
4062
|
-
.uvf-
|
|
4034
|
+
.uvf-controls-bar::before {
|
|
4063
4035
|
content: '';
|
|
4064
4036
|
position: absolute;
|
|
4065
4037
|
inset: 0;
|
|
@@ -4070,87 +4042,53 @@ export class WebPlayer extends BasePlayer {
|
|
|
4070
4042
|
}
|
|
4071
4043
|
|
|
4072
4044
|
/* Progress bar with chapter markers */
|
|
4073
|
-
.uvf-
|
|
4045
|
+
.uvf-progress-section {
|
|
4074
4046
|
margin-bottom: 12px;
|
|
4075
4047
|
position: relative;
|
|
4076
4048
|
}
|
|
4077
4049
|
|
|
4078
|
-
.uvf-
|
|
4050
|
+
.uvf-progress-bar-wrapper {
|
|
4079
4051
|
padding: 12px 0;
|
|
4080
4052
|
position: relative;
|
|
4081
4053
|
}
|
|
4082
4054
|
|
|
4083
|
-
.uvf-
|
|
4055
|
+
.uvf-progress-bar {
|
|
4084
4056
|
height: 4px;
|
|
4085
4057
|
background: rgba(255, 255, 255, 0.2);
|
|
4086
4058
|
border-radius: 4px;
|
|
4087
4059
|
position: relative;
|
|
4088
4060
|
overflow: visible;
|
|
4089
|
-
/* Material elevation */
|
|
4090
4061
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
|
|
4091
4062
|
}
|
|
4092
4063
|
|
|
4093
|
-
.uvf-
|
|
4064
|
+
.uvf-progress-filled {
|
|
4094
4065
|
background: var(--uvf-accent-1, #ff0000);
|
|
4095
4066
|
box-shadow: 0 0 8px var(--uvf-accent-1, #ff0000);
|
|
4096
4067
|
}
|
|
4097
4068
|
|
|
4098
|
-
.uvf-
|
|
4069
|
+
.uvf-progress-handle {
|
|
4099
4070
|
width: 20px;
|
|
4100
4071
|
height: 20px;
|
|
4101
4072
|
background: var(--uvf-accent-1, #ff0000);
|
|
4102
|
-
/* Material Design state layer */
|
|
4103
4073
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3),
|
|
4104
4074
|
0 0 0 0 var(--uvf-accent-1, #ff0000);
|
|
4105
4075
|
transition: box-shadow 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
4106
4076
|
}
|
|
4107
4077
|
|
|
4108
|
-
.uvf-
|
|
4078
|
+
.uvf-progress-handle:active {
|
|
4109
4079
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4),
|
|
4110
4080
|
0 0 0 12px rgba(255, 0, 0, 0.15);
|
|
4111
4081
|
transform: translate(-50%, -50%) scale(1.2);
|
|
4112
4082
|
}
|
|
4113
4083
|
|
|
4114
|
-
/* Chapter markers on progress bar */
|
|
4115
|
-
.uvf-chapter-marker {
|
|
4116
|
-
position: absolute;
|
|
4117
|
-
top: 0;
|
|
4118
|
-
height: 100%;
|
|
4119
|
-
width: 3px;
|
|
4120
|
-
background: rgba(255, 255, 255, 0.4);
|
|
4121
|
-
border-radius: 2px;
|
|
4122
|
-
transform: translateX(-50%);
|
|
4123
|
-
pointer-events: none;
|
|
4124
|
-
z-index: 1;
|
|
4125
|
-
transition: all 0.2s ease;
|
|
4126
|
-
}
|
|
4127
|
-
|
|
4128
|
-
.uvf-chapter-marker.intro {
|
|
4129
|
-
background: #4CAF50;
|
|
4130
|
-
}
|
|
4131
|
-
|
|
4132
|
-
.uvf-chapter-marker.recap {
|
|
4133
|
-
background: #FFC107;
|
|
4134
|
-
}
|
|
4135
|
-
|
|
4136
|
-
.uvf-chapter-marker.credits {
|
|
4137
|
-
background: #9C27B0;
|
|
4138
|
-
}
|
|
4139
|
-
|
|
4140
|
-
.uvf-progress-bar-wrapper:hover .uvf-chapter-marker {
|
|
4141
|
-
width: 4px;
|
|
4142
|
-
opacity: 1;
|
|
4143
|
-
}
|
|
4144
|
-
|
|
4145
4084
|
/* Material Design control buttons */
|
|
4146
|
-
.uvf-
|
|
4085
|
+
.uvf-control-btn {
|
|
4147
4086
|
width: 48px;
|
|
4148
4087
|
height: 48px;
|
|
4149
4088
|
min-width: 48px;
|
|
4150
4089
|
min-height: 48px;
|
|
4151
4090
|
background: rgba(255, 255, 255, 0.12);
|
|
4152
4091
|
border-radius: 24px;
|
|
4153
|
-
/* Material elevation level 1 */
|
|
4154
4092
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12),
|
|
4155
4093
|
0 1px 2px rgba(0, 0, 0, 0.24);
|
|
4156
4094
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
@@ -4159,7 +4097,7 @@ export class WebPlayer extends BasePlayer {
|
|
|
4159
4097
|
}
|
|
4160
4098
|
|
|
4161
4099
|
/* Material ripple effect */
|
|
4162
|
-
.uvf-
|
|
4100
|
+
.uvf-control-btn::before {
|
|
4163
4101
|
content: '';
|
|
4164
4102
|
position: absolute;
|
|
4165
4103
|
inset: 0;
|
|
@@ -4169,24 +4107,22 @@ export class WebPlayer extends BasePlayer {
|
|
|
4169
4107
|
transition: opacity 0.2s ease;
|
|
4170
4108
|
}
|
|
4171
4109
|
|
|
4172
|
-
.uvf-
|
|
4110
|
+
.uvf-control-btn:active::before {
|
|
4173
4111
|
opacity: 1;
|
|
4174
4112
|
}
|
|
4175
4113
|
|
|
4176
|
-
.uvf-
|
|
4177
|
-
/* Material elevation level 2 */
|
|
4114
|
+
.uvf-control-btn:active {
|
|
4178
4115
|
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16),
|
|
4179
4116
|
0 3px 6px rgba(0, 0, 0, 0.23);
|
|
4180
4117
|
transform: scale(0.95);
|
|
4181
4118
|
}
|
|
4182
4119
|
|
|
4183
|
-
.uvf-
|
|
4120
|
+
.uvf-control-btn.play-pause {
|
|
4184
4121
|
width: 56px;
|
|
4185
4122
|
height: 56px;
|
|
4186
4123
|
min-width: 56px;
|
|
4187
4124
|
min-height: 56px;
|
|
4188
4125
|
border-radius: 28px;
|
|
4189
|
-
/* Material elevated button */
|
|
4190
4126
|
background: linear-gradient(135deg,
|
|
4191
4127
|
var(--uvf-accent-1, #ff0000),
|
|
4192
4128
|
var(--uvf-accent-2, #ff4d4f));
|
|
@@ -4195,21 +4131,31 @@ export class WebPlayer extends BasePlayer {
|
|
|
4195
4131
|
0 0 0 0 var(--uvf-accent-1, #ff0000);
|
|
4196
4132
|
}
|
|
4197
4133
|
|
|
4198
|
-
.uvf-
|
|
4134
|
+
.uvf-control-btn.play-pause:active {
|
|
4199
4135
|
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.25),
|
|
4200
4136
|
0 4px 8px rgba(0, 0, 0, 0.20),
|
|
4201
4137
|
0 0 0 8px rgba(255, 0, 0, 0.12);
|
|
4202
4138
|
}
|
|
4203
4139
|
|
|
4140
|
+
.uvf-control-btn svg {
|
|
4141
|
+
width: 20px;
|
|
4142
|
+
height: 20px;
|
|
4143
|
+
}
|
|
4144
|
+
|
|
4145
|
+
.uvf-control-btn.play-pause svg {
|
|
4146
|
+
width: 24px;
|
|
4147
|
+
height: 24px;
|
|
4148
|
+
}
|
|
4149
|
+
|
|
4204
4150
|
/* Controls row with Material spacing */
|
|
4205
|
-
.uvf-
|
|
4151
|
+
.uvf-controls-row {
|
|
4206
4152
|
gap: 16px;
|
|
4207
4153
|
padding: 0;
|
|
4208
4154
|
align-items: center;
|
|
4209
4155
|
}
|
|
4210
4156
|
|
|
4211
4157
|
/* Time display with Material surface */
|
|
4212
|
-
.uvf-
|
|
4158
|
+
.uvf-time-display {
|
|
4213
4159
|
background: rgba(255, 255, 255, 0.1);
|
|
4214
4160
|
backdrop-filter: blur(8px);
|
|
4215
4161
|
border-radius: 16px;
|
|
@@ -4217,101 +4163,20 @@ export class WebPlayer extends BasePlayer {
|
|
|
4217
4163
|
font-size: 13px;
|
|
4218
4164
|
font-weight: 500;
|
|
4219
4165
|
font-feature-settings: 'tnum';
|
|
4220
|
-
/* Material elevation */
|
|
4221
4166
|
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
|
4222
4167
|
}
|
|
4223
4168
|
|
|
4224
|
-
/*
|
|
4225
|
-
.uvf-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
height: 80px;
|
|
4231
|
-
background: rgba(255, 255, 255, 0.2);
|
|
4232
|
-
backdrop-filter: blur(10px);
|
|
4233
|
-
border-radius: 40px;
|
|
4234
|
-
display: flex;
|
|
4235
|
-
align-items: center;
|
|
4236
|
-
justify-content: center;
|
|
4237
|
-
pointer-events: none;
|
|
4238
|
-
opacity: 0;
|
|
4239
|
-
z-index: 100;
|
|
4240
|
-
transition: opacity 0.3s ease;
|
|
4241
|
-
/* Material elevation level 3 */
|
|
4242
|
-
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19),
|
|
4243
|
-
0 6px 6px rgba(0, 0, 0, 0.23);
|
|
4244
|
-
}
|
|
4245
|
-
|
|
4246
|
-
.uvf-doubletap-indicator.left {
|
|
4247
|
-
left: 15%;
|
|
4248
|
-
}
|
|
4249
|
-
|
|
4250
|
-
.uvf-doubletap-indicator.right {
|
|
4251
|
-
right: 15%;
|
|
4252
|
-
}
|
|
4253
|
-
|
|
4254
|
-
.uvf-doubletap-indicator.active {
|
|
4255
|
-
opacity: 1;
|
|
4256
|
-
animation: doubletap-pulse 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
|
4257
|
-
}
|
|
4258
|
-
|
|
4259
|
-
@keyframes doubletap-pulse {
|
|
4260
|
-
0% {
|
|
4261
|
-
transform: translateY(-50%) scale(0.8);
|
|
4262
|
-
opacity: 0;
|
|
4263
|
-
}
|
|
4264
|
-
50% {
|
|
4265
|
-
transform: translateY(-50%) scale(1.1);
|
|
4266
|
-
opacity: 1;
|
|
4267
|
-
}
|
|
4268
|
-
100% {
|
|
4269
|
-
transform: translateY(-50%) scale(1);
|
|
4270
|
-
opacity: 1;
|
|
4271
|
-
}
|
|
4272
|
-
}
|
|
4273
|
-
|
|
4274
|
-
.uvf-doubletap-indicator svg {
|
|
4275
|
-
width: 40px;
|
|
4276
|
-
height: 40px;
|
|
4277
|
-
fill: #fff;
|
|
4278
|
-
}
|
|
4279
|
-
|
|
4280
|
-
/* Long-press 2x speed indicator */
|
|
4281
|
-
.uvf-longpress-indicator {
|
|
4282
|
-
position: absolute;
|
|
4283
|
-
top: 50%;
|
|
4284
|
-
left: 50%;
|
|
4285
|
-
transform: translate(-50%, -50%);
|
|
4286
|
-
background: rgba(0, 0, 0, 0.8);
|
|
4287
|
-
backdrop-filter: blur(16px);
|
|
4288
|
-
padding: 16px 24px;
|
|
4289
|
-
border-radius: 24px;
|
|
4290
|
-
color: #fff;
|
|
4291
|
-
font-size: 18px;
|
|
4292
|
-
font-weight: 600;
|
|
4293
|
-
pointer-events: none;
|
|
4294
|
-
opacity: 0;
|
|
4295
|
-
z-index: 100;
|
|
4296
|
-
transition: opacity 0.2s ease;
|
|
4297
|
-
/* Material elevation level 4 */
|
|
4298
|
-
box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25),
|
|
4299
|
-
0 10px 10px rgba(0, 0, 0, 0.22);
|
|
4300
|
-
}
|
|
4301
|
-
|
|
4302
|
-
.uvf-longpress-indicator.active {
|
|
4303
|
-
opacity: 1;
|
|
4304
|
-
}
|
|
4305
|
-
|
|
4306
|
-
/* Hide desktop elements in Material You mode */
|
|
4307
|
-
.uvf-player-wrapper.uvf-material-you-mobile .uvf-top-controls,
|
|
4308
|
-
.uvf-player-wrapper.uvf-material-you-mobile .uvf-title-bar,
|
|
4309
|
-
.uvf-player-wrapper.uvf-material-you-mobile .uvf-volume-control {
|
|
4169
|
+
/* Hide desktop elements */
|
|
4170
|
+
.uvf-top-controls,
|
|
4171
|
+
.uvf-title-bar,
|
|
4172
|
+
.uvf-volume-control,
|
|
4173
|
+
#uvf-skip-back,
|
|
4174
|
+
#uvf-skip-forward {
|
|
4310
4175
|
display: none !important;
|
|
4311
4176
|
}
|
|
4312
4177
|
|
|
4313
4178
|
/* Optimize settings button for Material You */
|
|
4314
|
-
|
|
4179
|
+
#uvf-settings-btn {
|
|
4315
4180
|
width: 48px !important;
|
|
4316
4181
|
height: 48px !important;
|
|
4317
4182
|
min-width: 48px !important;
|
|
@@ -4319,405 +4184,6 @@ export class WebPlayer extends BasePlayer {
|
|
|
4319
4184
|
border-radius: 24px !important;
|
|
4320
4185
|
}
|
|
4321
4186
|
}
|
|
4322
|
-
|
|
4323
|
-
/* Mobile devices (portrait) - Enhanced UX with Safe Areas */
|
|
4324
|
-
@media screen and (max-width: 767px) and (orientation: portrait) {
|
|
4325
|
-
.uvf-responsive-container {
|
|
4326
|
-
padding: 0;
|
|
4327
|
-
width: 100vw !important;
|
|
4328
|
-
height: calc(100vh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
|
|
4329
|
-
margin: 0;
|
|
4330
|
-
position: relative;
|
|
4331
|
-
overflow: hidden;
|
|
4332
|
-
}
|
|
4333
|
-
|
|
4334
|
-
@supports (height: 100dvh) {
|
|
4335
|
-
.uvf-responsive-container {
|
|
4336
|
-
height: calc(100dvh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
|
|
4337
|
-
}
|
|
4338
|
-
}
|
|
4339
|
-
|
|
4340
|
-
.uvf-responsive-container .uvf-player-wrapper {
|
|
4341
|
-
width: 100vw !important;
|
|
4342
|
-
height: 100% !important;
|
|
4343
|
-
min-height: calc(100vh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
|
|
4344
|
-
}
|
|
4345
|
-
|
|
4346
|
-
@supports (height: 100dvh) {
|
|
4347
|
-
.uvf-responsive-container .uvf-player-wrapper {
|
|
4348
|
-
min-height: calc(100dvh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
|
|
4349
|
-
}
|
|
4350
|
-
}
|
|
4351
|
-
|
|
4352
|
-
.uvf-responsive-container .uvf-video-container {
|
|
4353
|
-
width: 100vw !important;
|
|
4354
|
-
height: 100% !important;
|
|
4355
|
-
aspect-ratio: unset !important;
|
|
4356
|
-
min-height: inherit;
|
|
4357
|
-
}
|
|
4358
|
-
|
|
4359
|
-
/* Enhanced mobile controls bar with safe area padding - iOS Safari specific fixes */
|
|
4360
|
-
.uvf-controls-bar {
|
|
4361
|
-
position: absolute !important;
|
|
4362
|
-
bottom: 0 !important;
|
|
4363
|
-
left: 0 !important;
|
|
4364
|
-
right: 0 !important;
|
|
4365
|
-
padding: 16px 12px;
|
|
4366
|
-
padding-bottom: calc(16px + var(--uvf-safe-area-bottom, 0px));
|
|
4367
|
-
padding-left: calc(12px + var(--uvf-safe-area-left, 0px));
|
|
4368
|
-
padding-right: calc(12px + var(--uvf-safe-area-right, 0px));
|
|
4369
|
-
background: linear-gradient(to top, var(--uvf-overlay-strong) 0%, var(--uvf-overlay-medium) 80%, var(--uvf-overlay-transparent) 100%);
|
|
4370
|
-
box-sizing: border-box;
|
|
4371
|
-
z-index: 1000 !important;
|
|
4372
|
-
/* iOS Safari specific fixes */
|
|
4373
|
-
transform: translateZ(0);
|
|
4374
|
-
-webkit-transform: translateZ(0);
|
|
4375
|
-
will-change: transform;
|
|
4376
|
-
/* Ensure proper stacking */
|
|
4377
|
-
isolation: isolate;
|
|
4378
|
-
}
|
|
4379
|
-
|
|
4380
|
-
.uvf-progress-section {
|
|
4381
|
-
margin-bottom: 16px;
|
|
4382
|
-
}
|
|
4383
|
-
|
|
4384
|
-
/* Mobile-first responsive controls layout */
|
|
4385
|
-
.uvf-controls-row {
|
|
4386
|
-
gap: 8px;
|
|
4387
|
-
flex-wrap: nowrap;
|
|
4388
|
-
align-items: center;
|
|
4389
|
-
justify-content: space-between;
|
|
4390
|
-
position: relative;
|
|
4391
|
-
width: 100%;
|
|
4392
|
-
}
|
|
4393
|
-
|
|
4394
|
-
/* Left side controls group */
|
|
4395
|
-
.uvf-left-controls {
|
|
4396
|
-
display: flex;
|
|
4397
|
-
align-items: center;
|
|
4398
|
-
gap: 8px;
|
|
4399
|
-
flex-shrink: 0;
|
|
4400
|
-
}
|
|
4401
|
-
|
|
4402
|
-
/* Center controls group */
|
|
4403
|
-
.uvf-center-controls {
|
|
4404
|
-
display: flex;
|
|
4405
|
-
align-items: center;
|
|
4406
|
-
gap: 8px;
|
|
4407
|
-
flex: 1;
|
|
4408
|
-
justify-content: center;
|
|
4409
|
-
}
|
|
4410
|
-
|
|
4411
|
-
/* Mobile control groups reordering */
|
|
4412
|
-
.uvf-controls-row .uvf-control-btn.play-pause,
|
|
4413
|
-
.uvf-controls-row #uvf-skip-back,
|
|
4414
|
-
.uvf-controls-row #uvf-skip-forward {
|
|
4415
|
-
order: 1;
|
|
4416
|
-
}
|
|
4417
|
-
|
|
4418
|
-
.uvf-controls-row .uvf-volume-control {
|
|
4419
|
-
order: 2;
|
|
4420
|
-
}
|
|
4421
|
-
|
|
4422
|
-
.uvf-controls-row .uvf-time-display:not(.uvf-above-seekbar) {
|
|
4423
|
-
order: 3;
|
|
4424
|
-
margin-left: auto;
|
|
4425
|
-
margin-right: 8px;
|
|
4426
|
-
}
|
|
4427
|
-
|
|
4428
|
-
.uvf-controls-row .uvf-right-controls {
|
|
4429
|
-
order: 4;
|
|
4430
|
-
margin-left: 0;
|
|
4431
|
-
}
|
|
4432
|
-
|
|
4433
|
-
/* Touch-friendly control sizing (minimum 44px touch target) */
|
|
4434
|
-
.uvf-control-btn {
|
|
4435
|
-
width: 44px;
|
|
4436
|
-
height: 44px;
|
|
4437
|
-
min-width: 44px;
|
|
4438
|
-
min-height: 44px;
|
|
4439
|
-
border-radius: 22px;
|
|
4440
|
-
background: rgba(255,255,255,0.15);
|
|
4441
|
-
backdrop-filter: blur(8px);
|
|
4442
|
-
}
|
|
4443
|
-
|
|
4444
|
-
.uvf-control-btn.play-pause {
|
|
4445
|
-
width: 52px;
|
|
4446
|
-
height: 52px;
|
|
4447
|
-
min-width: 52px;
|
|
4448
|
-
min-height: 52px;
|
|
4449
|
-
border-radius: 26px;
|
|
4450
|
-
background: linear-gradient(135deg, var(--uvf-accent-1), var(--uvf-accent-2));
|
|
4451
|
-
box-shadow: 0 4px 12px rgba(var(--uvf-accent-1), 0.3);
|
|
4452
|
-
}
|
|
4453
|
-
|
|
4454
|
-
.uvf-control-btn svg {
|
|
4455
|
-
width: 20px;
|
|
4456
|
-
height: 20px;
|
|
4457
|
-
}
|
|
4458
|
-
|
|
4459
|
-
.uvf-control-btn.play-pause svg {
|
|
4460
|
-
width: 24px;
|
|
4461
|
-
height: 24px;
|
|
4462
|
-
}
|
|
4463
|
-
|
|
4464
|
-
/* Skip buttons with clear visual hierarchy */
|
|
4465
|
-
#uvf-skip-back,
|
|
4466
|
-
#uvf-skip-forward {
|
|
4467
|
-
background: rgba(255,255,255,0.12);
|
|
4468
|
-
}
|
|
4469
|
-
|
|
4470
|
-
#uvf-skip-back svg,
|
|
4471
|
-
#uvf-skip-forward svg {
|
|
4472
|
-
width: 22px;
|
|
4473
|
-
height: 22px;
|
|
4474
|
-
}
|
|
4475
|
-
|
|
4476
|
-
/* Mobile time display - compact but readable */
|
|
4477
|
-
.uvf-time-display:not(.uvf-above-seekbar) {
|
|
4478
|
-
font-size: 12px;
|
|
4479
|
-
font-weight: 600;
|
|
4480
|
-
padding: 0 6px;
|
|
4481
|
-
text-align: center;
|
|
4482
|
-
background: rgba(0,0,0,0.3);
|
|
4483
|
-
border-radius: 12px;
|
|
4484
|
-
text-shadow: 0 1px 3px rgba(0,0,0,0.8);
|
|
4485
|
-
flex-shrink: 0;
|
|
4486
|
-
}
|
|
4487
|
-
|
|
4488
|
-
/* Above-seekbar time display for mobile */
|
|
4489
|
-
.uvf-time-display.uvf-above-seekbar {
|
|
4490
|
-
font-size: 12px !important;
|
|
4491
|
-
font-weight: 500 !important;
|
|
4492
|
-
padding: 3px 6px !important;
|
|
4493
|
-
background: rgba(0,0,0,0.4) !important;
|
|
4494
|
-
border-radius: 10px !important;
|
|
4495
|
-
text-shadow: 0 1px 2px rgba(0,0,0,0.8) !important;
|
|
4496
|
-
backdrop-filter: blur(4px) !important;
|
|
4497
|
-
border: 1px solid rgba(255,255,255,0.1) !important;
|
|
4498
|
-
}
|
|
4499
|
-
|
|
4500
|
-
/* Simplified volume control for mobile */
|
|
4501
|
-
.uvf-volume-control {
|
|
4502
|
-
order: 3;
|
|
4503
|
-
position: relative;
|
|
4504
|
-
}
|
|
4505
|
-
|
|
4506
|
-
/* Hide volume panel on mobile - use device controls */
|
|
4507
|
-
.uvf-volume-panel {
|
|
4508
|
-
display: none;
|
|
4509
|
-
}
|
|
4510
|
-
|
|
4511
|
-
/* Mobile volume button as simple mute toggle */
|
|
4512
|
-
.uvf-volume-control .uvf-control-btn {
|
|
4513
|
-
width: 44px;
|
|
4514
|
-
height: 44px;
|
|
4515
|
-
}
|
|
4516
|
-
|
|
4517
|
-
/* Compact right controls for mobile */
|
|
4518
|
-
.uvf-right-controls {
|
|
4519
|
-
gap: 6px;
|
|
4520
|
-
display: flex;
|
|
4521
|
-
align-items: center;
|
|
4522
|
-
flex-shrink: 0;
|
|
4523
|
-
position: relative;
|
|
4524
|
-
z-index: 10;
|
|
4525
|
-
}
|
|
4526
|
-
|
|
4527
|
-
/* Ensure settings container is visible */
|
|
4528
|
-
.uvf-right-controls > div[style*="position: relative"],
|
|
4529
|
-
.uvf-settings-container {
|
|
4530
|
-
display: flex !important;
|
|
4531
|
-
position: relative !important;
|
|
4532
|
-
align-items: center !important;
|
|
4533
|
-
justify-content: center !important;
|
|
4534
|
-
min-width: 44px !important;
|
|
4535
|
-
min-height: 44px !important;
|
|
4536
|
-
}
|
|
4537
|
-
|
|
4538
|
-
/* Remove quality badge completely - not essential */
|
|
4539
|
-
.uvf-quality-badge {
|
|
4540
|
-
display: none !important;
|
|
4541
|
-
}
|
|
4542
|
-
|
|
4543
|
-
/* Settings menu - hidden by default, accessible via menu */
|
|
4544
|
-
.uvf-settings-menu {
|
|
4545
|
-
min-width: 160px;
|
|
4546
|
-
bottom: 60px;
|
|
4547
|
-
right: 12px;
|
|
4548
|
-
font-size: 14px;
|
|
4549
|
-
max-height: 50vh;
|
|
4550
|
-
}
|
|
4551
|
-
|
|
4552
|
-
.uvf-settings-option {
|
|
4553
|
-
padding: 12px 16px;
|
|
4554
|
-
font-size: 14px;
|
|
4555
|
-
min-height: 44px;
|
|
4556
|
-
display: flex;
|
|
4557
|
-
align-items: center;
|
|
4558
|
-
}
|
|
4559
|
-
|
|
4560
|
-
.uvf-settings-option:hover {
|
|
4561
|
-
background: rgba(255,255,255,0.15);
|
|
4562
|
-
padding-left: 20px;
|
|
4563
|
-
}
|
|
4564
|
-
|
|
4565
|
-
/* Simplified settings - hide complex options */
|
|
4566
|
-
.uvf-settings-group:first-child .uvf-settings-option[data-speed="0.5"],
|
|
4567
|
-
.uvf-settings-group:first-child .uvf-settings-option[data-speed="0.75"],
|
|
4568
|
-
.uvf-settings-group:first-child .uvf-settings-option[data-speed="2"] {
|
|
4569
|
-
display: none;
|
|
4570
|
-
}
|
|
4571
|
-
}
|
|
4572
|
-
|
|
4573
|
-
/* Enhanced top controls for mobile with safe area support */
|
|
4574
|
-
.uvf-top-controls {
|
|
4575
|
-
position: absolute;
|
|
4576
|
-
top: calc(12px + var(--uvf-safe-area-top));
|
|
4577
|
-
right: calc(12px + var(--uvf-safe-area-right));
|
|
4578
|
-
display: flex;
|
|
4579
|
-
align-items: center;
|
|
4580
|
-
gap: 8px;
|
|
4581
|
-
z-index: 10;
|
|
4582
|
-
}
|
|
4583
|
-
|
|
4584
|
-
/* Touch-friendly top buttons */
|
|
4585
|
-
.uvf-top-btn {
|
|
4586
|
-
width: 44px;
|
|
4587
|
-
height: 44px;
|
|
4588
|
-
min-width: 44px;
|
|
4589
|
-
min-height: 44px;
|
|
4590
|
-
background: rgba(0,0,0,0.7);
|
|
4591
|
-
backdrop-filter: blur(10px);
|
|
4592
|
-
border: 1px solid rgba(255,255,255,0.2);
|
|
4593
|
-
}
|
|
4594
|
-
|
|
4595
|
-
.uvf-top-btn svg {
|
|
4596
|
-
width: 20px;
|
|
4597
|
-
height: 20px;
|
|
4598
|
-
}
|
|
4599
|
-
|
|
4600
|
-
/* Share button - keep visible on all devices */
|
|
4601
|
-
#uvf-share-btn {
|
|
4602
|
-
display: flex;
|
|
4603
|
-
}
|
|
4604
|
-
|
|
4605
|
-
/* Enhanced title bar for mobile with safe area support */
|
|
4606
|
-
.uvf-title-bar {
|
|
4607
|
-
padding: 12px;
|
|
4608
|
-
padding-top: calc(12px + var(--uvf-safe-area-top));
|
|
4609
|
-
padding-left: calc(12px + var(--uvf-safe-area-left));
|
|
4610
|
-
padding-right: calc(12px + var(--uvf-safe-area-right));
|
|
4611
|
-
}
|
|
4612
|
-
|
|
4613
|
-
.uvf-video-title {
|
|
4614
|
-
font-size: 16px;
|
|
4615
|
-
font-weight: 700;
|
|
4616
|
-
line-height: 1.2;
|
|
4617
|
-
}
|
|
4618
|
-
|
|
4619
|
-
.uvf-video-subtitle {
|
|
4620
|
-
font-size: 12px;
|
|
4621
|
-
margin-top: 4px;
|
|
4622
|
-
opacity: 0.8;
|
|
4623
|
-
}
|
|
4624
|
-
|
|
4625
|
-
.uvf-video-thumb {
|
|
4626
|
-
width: 48px;
|
|
4627
|
-
height: 48px;
|
|
4628
|
-
border-radius: 6px;
|
|
4629
|
-
}
|
|
4630
|
-
|
|
4631
|
-
/* Touch-optimized center play button - uses same themed style as desktop */
|
|
4632
|
-
.uvf-center-play-btn {
|
|
4633
|
-
width: clamp(72px, 18vw, 96px);
|
|
4634
|
-
height: clamp(72px, 18vw, 96px);
|
|
4635
|
-
background: linear-gradient(135deg, var(--uvf-accent-1), var(--uvf-accent-2));
|
|
4636
|
-
border: 0;
|
|
4637
|
-
box-shadow: 0 10px 30px var(--uvf-accent-1-20);
|
|
4638
|
-
}
|
|
4639
|
-
|
|
4640
|
-
.uvf-center-play-btn:hover {
|
|
4641
|
-
transform: scale(1.06);
|
|
4642
|
-
filter: saturate(1.08) brightness(1.05);
|
|
4643
|
-
box-shadow: 0 14px 36px var(--uvf-accent-1-20);
|
|
4644
|
-
}
|
|
4645
|
-
|
|
4646
|
-
.uvf-center-play-btn svg {
|
|
4647
|
-
width: clamp(28px, 5.2vw, 38px);
|
|
4648
|
-
height: clamp(28px, 5.2vw, 38px);
|
|
4649
|
-
margin-left: 4px;
|
|
4650
|
-
}
|
|
4651
|
-
|
|
4652
|
-
/* Enhanced progress bar for touch */
|
|
4653
|
-
.uvf-progress-bar {
|
|
4654
|
-
height: 3px;
|
|
4655
|
-
margin-bottom: 12px;
|
|
4656
|
-
border-radius: 4px;
|
|
4657
|
-
background: rgba(255,255,255,0.15);
|
|
4658
|
-
position: relative;
|
|
4659
|
-
}
|
|
4660
|
-
|
|
4661
|
-
/* Larger touch target for progress bar */
|
|
4662
|
-
.uvf-progress-bar-wrapper::before {
|
|
4663
|
-
content: '';
|
|
4664
|
-
position: absolute;
|
|
4665
|
-
top: -10px;
|
|
4666
|
-
left: 0;
|
|
4667
|
-
right: 0;
|
|
4668
|
-
bottom: -10px;
|
|
4669
|
-
z-index: 1;
|
|
4670
|
-
}
|
|
4671
|
-
|
|
4672
|
-
.uvf-progress-handle {
|
|
4673
|
-
width: 18px;
|
|
4674
|
-
height: 18px;
|
|
4675
|
-
background: #fff;
|
|
4676
|
-
box-shadow: 0 2px 8px rgba(0,0,0,0.3);
|
|
4677
|
-
}
|
|
4678
|
-
|
|
4679
|
-
.uvf-progress-bar-wrapper:active .uvf-progress-handle {
|
|
4680
|
-
transform: translate(-50%, -50%) scale(1.2);
|
|
4681
|
-
}
|
|
4682
|
-
|
|
4683
|
-
/* Mobile accessibility improvements */
|
|
4684
|
-
.uvf-control-btn,
|
|
4685
|
-
.uvf-top-btn {
|
|
4686
|
-
position: relative;
|
|
4687
|
-
overflow: visible;
|
|
4688
|
-
}
|
|
4689
|
-
|
|
4690
|
-
/* Enhanced focus states for mobile */
|
|
4691
|
-
.uvf-control-btn:focus,
|
|
4692
|
-
.uvf-top-btn:focus {
|
|
4693
|
-
outline: 2px solid var(--uvf-accent-1);
|
|
4694
|
-
outline-offset: 2px;
|
|
4695
|
-
}
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
/* Show PiP on all devices - modern mobile browsers support it well */
|
|
4699
|
-
#uvf-pip-btn {
|
|
4700
|
-
display: block;
|
|
4701
|
-
background: rgba(255,255,255,0.12);
|
|
4702
|
-
border: 1px solid rgba(255,255,255,0.1);
|
|
4703
|
-
}
|
|
4704
|
-
|
|
4705
|
-
/* Essential controls in right section - Settings, PiP, and Fullscreen only */
|
|
4706
|
-
.uvf-right-controls > *:not(#uvf-settings-btn):not(#uvf-fullscreen-btn):not(#uvf-pip-btn) {
|
|
4707
|
-
display: none;
|
|
4708
|
-
}
|
|
4709
|
-
|
|
4710
|
-
/* Ensure settings button is always visible and properly sized on mobile */
|
|
4711
|
-
#uvf-settings-btn {
|
|
4712
|
-
display: flex !important;
|
|
4713
|
-
width: 44px !important;
|
|
4714
|
-
height: 44px !important;
|
|
4715
|
-
min-width: 44px !important;
|
|
4716
|
-
min-height: 44px !important;
|
|
4717
|
-
backdrop-filter: blur(8px) !important;
|
|
4718
|
-
border-radius: 22px !important;
|
|
4719
|
-
align-items: center !important;
|
|
4720
|
-
justify-content: center !important;
|
|
4721
4187
|
}
|
|
4722
4188
|
|
|
4723
4189
|
#uvf-settings-btn svg {
|
|
@@ -5614,21 +5080,6 @@ export class WebPlayer extends BasePlayer {
|
|
|
5614
5080
|
shortcutIndicator.className = 'uvf-shortcut-indicator';
|
|
5615
5081
|
shortcutIndicator.id = 'uvf-shortcut-indicator';
|
|
5616
5082
|
container.appendChild(shortcutIndicator);
|
|
5617
|
-
const doubleTapLeft = document.createElement('div');
|
|
5618
|
-
doubleTapLeft.className = 'uvf-doubletap-indicator left';
|
|
5619
|
-
doubleTapLeft.id = 'uvf-doubletap-left';
|
|
5620
|
-
doubleTapLeft.innerHTML = '<svg viewBox="0 0 24 24"><path d="M11 18V6l-8.5 6 8.5 6zm.5-6l8.5 6V6l-8.5 6z"/></svg><div style="margin-top:4px;font-size:14px;font-weight:600;">-10s</div>';
|
|
5621
|
-
container.appendChild(doubleTapLeft);
|
|
5622
|
-
const doubleTapRight = document.createElement('div');
|
|
5623
|
-
doubleTapRight.className = 'uvf-doubletap-indicator right';
|
|
5624
|
-
doubleTapRight.id = 'uvf-doubletap-right';
|
|
5625
|
-
doubleTapRight.innerHTML = '<svg viewBox="0 0 24 24"><path d="M4 18l8.5-6L4 6v12zm9-12v12l8.5-6L13 6z"/></svg><div style="margin-top:4px;font-size:14px;font-weight:600;">+10s</div>';
|
|
5626
|
-
container.appendChild(doubleTapRight);
|
|
5627
|
-
const longPressIndicator = document.createElement('div');
|
|
5628
|
-
longPressIndicator.className = 'uvf-longpress-indicator';
|
|
5629
|
-
longPressIndicator.id = 'uvf-longpress-indicator';
|
|
5630
|
-
longPressIndicator.textContent = '2x';
|
|
5631
|
-
container.appendChild(longPressIndicator);
|
|
5632
5083
|
const controlsBar = document.createElement('div');
|
|
5633
5084
|
controlsBar.className = 'uvf-controls-bar';
|
|
5634
5085
|
controlsBar.id = 'uvf-controls';
|
|
@@ -5861,7 +5312,7 @@ export class WebPlayer extends BasePlayer {
|
|
|
5861
5312
|
});
|
|
5862
5313
|
centerPlay?.addEventListener('click', () => this.togglePlayPause());
|
|
5863
5314
|
playPauseBtn?.addEventListener('click', () => this.togglePlayPause());
|
|
5864
|
-
this.
|
|
5315
|
+
this.video.addEventListener('click', () => this.togglePlayPause());
|
|
5865
5316
|
this.video.addEventListener('play', () => {
|
|
5866
5317
|
const playIcon = document.getElementById('uvf-play-icon');
|
|
5867
5318
|
const pauseIcon = document.getElementById('uvf-pause-icon');
|
|
@@ -6154,12 +5605,7 @@ export class WebPlayer extends BasePlayer {
|
|
|
6154
5605
|
this.debugLog('Settings menu classes before toggle:', Array.from(settingsMenu?.classList || []).join(' '));
|
|
6155
5606
|
settingsMenu?.classList.toggle('active');
|
|
6156
5607
|
if (settingsMenu) {
|
|
6157
|
-
|
|
6158
|
-
if (activating) {
|
|
6159
|
-
this.isSettingsOpen = true;
|
|
6160
|
-
this.showControls();
|
|
6161
|
-
if (this.hideControlsTimeout)
|
|
6162
|
-
clearTimeout(this.hideControlsTimeout);
|
|
5608
|
+
if (settingsMenu.classList.contains('active')) {
|
|
6163
5609
|
settingsMenu.style.display = 'block';
|
|
6164
5610
|
settingsMenu.style.visibility = 'visible';
|
|
6165
5611
|
settingsMenu.style.opacity = '1';
|
|
@@ -6176,12 +5622,10 @@ export class WebPlayer extends BasePlayer {
|
|
|
6176
5622
|
this.debugLog('Applied fallback styles to show menu');
|
|
6177
5623
|
}
|
|
6178
5624
|
else {
|
|
6179
|
-
this.isSettingsOpen = false;
|
|
6180
5625
|
settingsMenu.style.display = 'none';
|
|
6181
5626
|
settingsMenu.style.visibility = 'hidden';
|
|
6182
5627
|
settingsMenu.style.opacity = '0';
|
|
6183
5628
|
this.debugLog('Applied fallback styles to hide menu');
|
|
6184
|
-
this.scheduleHideControls();
|
|
6185
5629
|
}
|
|
6186
5630
|
}
|
|
6187
5631
|
this.debugLog('Settings menu classes after toggle:', Array.from(settingsMenu?.classList || []).join(' '));
|
|
@@ -6209,19 +5653,6 @@ export class WebPlayer extends BasePlayer {
|
|
|
6209
5653
|
this.hideSettingsMenu();
|
|
6210
5654
|
}
|
|
6211
5655
|
});
|
|
6212
|
-
if (settingsMenu) {
|
|
6213
|
-
const keepAlive = () => {
|
|
6214
|
-
if (!this.isSettingsOpen)
|
|
6215
|
-
return;
|
|
6216
|
-
this.showControls();
|
|
6217
|
-
if (this.hideControlsTimeout)
|
|
6218
|
-
clearTimeout(this.hideControlsTimeout);
|
|
6219
|
-
};
|
|
6220
|
-
settingsMenu.addEventListener('mouseenter', keepAlive);
|
|
6221
|
-
settingsMenu.addEventListener('mousemove', keepAlive);
|
|
6222
|
-
settingsMenu.addEventListener('touchstart', keepAlive, { passive: true });
|
|
6223
|
-
settingsMenu.addEventListener('touchmove', keepAlive, { passive: true });
|
|
6224
|
-
}
|
|
6225
5656
|
document.addEventListener('keydown', (e) => {
|
|
6226
5657
|
if (e.key === 'Escape' && settingsMenu?.classList.contains('active')) {
|
|
6227
5658
|
this.hideSettingsMenu();
|
|
@@ -6662,187 +6093,6 @@ export class WebPlayer extends BasePlayer {
|
|
|
6662
6093
|
this.mute();
|
|
6663
6094
|
}
|
|
6664
6095
|
}
|
|
6665
|
-
setupMaterialYouGestures(wrapper) {
|
|
6666
|
-
if (!wrapper || !this.video)
|
|
6667
|
-
return;
|
|
6668
|
-
const doubleTapLeft = document.getElementById('uvf-doubletap-left');
|
|
6669
|
-
const doubleTapRight = document.getElementById('uvf-doubletap-right');
|
|
6670
|
-
const longPressIndicator = document.getElementById('uvf-longpress-indicator');
|
|
6671
|
-
const videoElement = this.video;
|
|
6672
|
-
const videoContainer = wrapper.querySelector('.uvf-video-container');
|
|
6673
|
-
if (!videoContainer)
|
|
6674
|
-
return;
|
|
6675
|
-
videoContainer.addEventListener('touchstart', (e) => {
|
|
6676
|
-
const touchEvent = e;
|
|
6677
|
-
const touch = touchEvent.touches[0];
|
|
6678
|
-
if (!touch || !videoElement)
|
|
6679
|
-
return;
|
|
6680
|
-
this.longPressStartTime = Date.now();
|
|
6681
|
-
this.longPressTimer = setTimeout(() => {
|
|
6682
|
-
this.longPressActive = true;
|
|
6683
|
-
this.originalPlaybackRate = videoElement.playbackRate;
|
|
6684
|
-
videoElement.playbackRate = 2.0;
|
|
6685
|
-
if (longPressIndicator) {
|
|
6686
|
-
longPressIndicator.classList.add('active');
|
|
6687
|
-
}
|
|
6688
|
-
}, 500);
|
|
6689
|
-
}, { passive: true });
|
|
6690
|
-
videoContainer.addEventListener('touchend', (e) => {
|
|
6691
|
-
const touchEvent = e;
|
|
6692
|
-
const touch = touchEvent.changedTouches[0];
|
|
6693
|
-
if (!touch || !videoElement)
|
|
6694
|
-
return;
|
|
6695
|
-
if (this.longPressTimer) {
|
|
6696
|
-
clearTimeout(this.longPressTimer);
|
|
6697
|
-
this.longPressTimer = null;
|
|
6698
|
-
}
|
|
6699
|
-
if (this.longPressActive) {
|
|
6700
|
-
videoElement.playbackRate = this.originalPlaybackRate;
|
|
6701
|
-
this.longPressActive = false;
|
|
6702
|
-
if (longPressIndicator) {
|
|
6703
|
-
longPressIndicator.classList.remove('active');
|
|
6704
|
-
}
|
|
6705
|
-
return;
|
|
6706
|
-
}
|
|
6707
|
-
const now = Date.now();
|
|
6708
|
-
const timeSinceLastTap = now - this.lastTapTime;
|
|
6709
|
-
if (timeSinceLastTap < 300) {
|
|
6710
|
-
if (this.tapTimeout) {
|
|
6711
|
-
clearTimeout(this.tapTimeout);
|
|
6712
|
-
this.tapTimeout = null;
|
|
6713
|
-
}
|
|
6714
|
-
const rect = videoContainer.getBoundingClientRect();
|
|
6715
|
-
const x = touch.clientX - rect.left;
|
|
6716
|
-
const isLeftSide = x < rect.width / 2;
|
|
6717
|
-
if (isLeftSide) {
|
|
6718
|
-
this.seek(videoElement.currentTime - 10);
|
|
6719
|
-
if (doubleTapLeft) {
|
|
6720
|
-
doubleTapLeft.classList.add('active');
|
|
6721
|
-
setTimeout(() => {
|
|
6722
|
-
doubleTapLeft.classList.remove('active');
|
|
6723
|
-
}, 400);
|
|
6724
|
-
}
|
|
6725
|
-
}
|
|
6726
|
-
else {
|
|
6727
|
-
this.seek(videoElement.currentTime + 10);
|
|
6728
|
-
if (doubleTapRight) {
|
|
6729
|
-
doubleTapRight.classList.add('active');
|
|
6730
|
-
setTimeout(() => {
|
|
6731
|
-
doubleTapRight.classList.remove('active');
|
|
6732
|
-
}, 400);
|
|
6733
|
-
}
|
|
6734
|
-
}
|
|
6735
|
-
this.tapCount = 0;
|
|
6736
|
-
this.lastTapTime = 0;
|
|
6737
|
-
}
|
|
6738
|
-
else {
|
|
6739
|
-
this.tapCount = 1;
|
|
6740
|
-
this.lastTapTime = now;
|
|
6741
|
-
this.tapTimeout = setTimeout(() => {
|
|
6742
|
-
if (this.tapCount === 1) {
|
|
6743
|
-
this.toggleControls();
|
|
6744
|
-
}
|
|
6745
|
-
this.tapCount = 0;
|
|
6746
|
-
}, 300);
|
|
6747
|
-
}
|
|
6748
|
-
}, { passive: true });
|
|
6749
|
-
videoContainer.addEventListener('touchmove', () => {
|
|
6750
|
-
if (this.longPressTimer) {
|
|
6751
|
-
clearTimeout(this.longPressTimer);
|
|
6752
|
-
this.longPressTimer = null;
|
|
6753
|
-
}
|
|
6754
|
-
}, { passive: true });
|
|
6755
|
-
videoContainer.addEventListener('touchcancel', () => {
|
|
6756
|
-
if (this.longPressTimer) {
|
|
6757
|
-
clearTimeout(this.longPressTimer);
|
|
6758
|
-
this.longPressTimer = null;
|
|
6759
|
-
}
|
|
6760
|
-
if (this.longPressActive && videoElement) {
|
|
6761
|
-
videoElement.playbackRate = this.originalPlaybackRate;
|
|
6762
|
-
this.longPressActive = false;
|
|
6763
|
-
if (longPressIndicator) {
|
|
6764
|
-
longPressIndicator.classList.remove('active');
|
|
6765
|
-
}
|
|
6766
|
-
}
|
|
6767
|
-
}, { passive: true });
|
|
6768
|
-
}
|
|
6769
|
-
toggleControls() {
|
|
6770
|
-
const wrapper = this.container?.querySelector('.uvf-player-wrapper');
|
|
6771
|
-
if (wrapper) {
|
|
6772
|
-
if (wrapper.classList.contains('controls-visible')) {
|
|
6773
|
-
this.hideControls();
|
|
6774
|
-
}
|
|
6775
|
-
else {
|
|
6776
|
-
this.showControls();
|
|
6777
|
-
if (this.state.isPlaying) {
|
|
6778
|
-
this.scheduleHideControls();
|
|
6779
|
-
}
|
|
6780
|
-
}
|
|
6781
|
-
}
|
|
6782
|
-
}
|
|
6783
|
-
applyDynamicTheming(primaryColor) {
|
|
6784
|
-
if (!this.playerWrapper)
|
|
6785
|
-
return;
|
|
6786
|
-
const color = primaryColor || this.dominantColor;
|
|
6787
|
-
const rgb = this.hexToRgb(color);
|
|
6788
|
-
if (rgb) {
|
|
6789
|
-
this.playerWrapper.style.setProperty('--uvf-accent-1', color);
|
|
6790
|
-
this.playerWrapper.style.setProperty('--uvf-accent-2', this.lightenColor(color, 10));
|
|
6791
|
-
this.playerWrapper.style.setProperty('--uvf-surface-tint', `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.08)`);
|
|
6792
|
-
this.debugLog(`Applied dynamic theming with color: ${color}`);
|
|
6793
|
-
}
|
|
6794
|
-
}
|
|
6795
|
-
hexToRgb(hex) {
|
|
6796
|
-
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
6797
|
-
return result ? {
|
|
6798
|
-
r: parseInt(result[1], 16),
|
|
6799
|
-
g: parseInt(result[2], 16),
|
|
6800
|
-
b: parseInt(result[3], 16)
|
|
6801
|
-
} : null;
|
|
6802
|
-
}
|
|
6803
|
-
lightenColor(hex, percent) {
|
|
6804
|
-
const rgb = this.hexToRgb(hex);
|
|
6805
|
-
if (!rgb)
|
|
6806
|
-
return hex;
|
|
6807
|
-
const amount = Math.floor(255 * (percent / 100));
|
|
6808
|
-
const r = Math.min(255, rgb.r + amount);
|
|
6809
|
-
const g = Math.min(255, rgb.g + amount);
|
|
6810
|
-
const b = Math.min(255, rgb.b + amount);
|
|
6811
|
-
return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;
|
|
6812
|
-
}
|
|
6813
|
-
renderChapterMarkersOnProgressBar() {
|
|
6814
|
-
if (!this.video || !this.chapterConfig.enabled || !this.chapterConfig.showChapterMarkers) {
|
|
6815
|
-
return;
|
|
6816
|
-
}
|
|
6817
|
-
const progressBar = document.querySelector('.uvf-progress-bar');
|
|
6818
|
-
if (!progressBar)
|
|
6819
|
-
return;
|
|
6820
|
-
const existingMarkers = progressBar.querySelectorAll('.uvf-chapter-marker');
|
|
6821
|
-
existingMarkers.forEach(marker => marker.remove());
|
|
6822
|
-
const chapters = this.chapterConfig.data;
|
|
6823
|
-
if (!chapters || !Array.isArray(chapters) || chapters.length === 0) {
|
|
6824
|
-
return;
|
|
6825
|
-
}
|
|
6826
|
-
const duration = this.video.duration;
|
|
6827
|
-
if (!duration || duration === 0)
|
|
6828
|
-
return;
|
|
6829
|
-
chapters.forEach((chapter) => {
|
|
6830
|
-
if (!chapter.startTime && chapter.startTime !== 0)
|
|
6831
|
-
return;
|
|
6832
|
-
const marker = document.createElement('div');
|
|
6833
|
-
marker.className = 'uvf-chapter-marker';
|
|
6834
|
-
if (chapter.type) {
|
|
6835
|
-
marker.classList.add(chapter.type.toLowerCase());
|
|
6836
|
-
}
|
|
6837
|
-
const percent = (chapter.startTime / duration) * 100;
|
|
6838
|
-
marker.style.left = `${percent}%`;
|
|
6839
|
-
if (chapter.title) {
|
|
6840
|
-
marker.setAttribute('title', chapter.title);
|
|
6841
|
-
}
|
|
6842
|
-
progressBar.appendChild(marker);
|
|
6843
|
-
});
|
|
6844
|
-
this.debugLog(`Rendered ${chapters.length} chapter markers on progress bar`);
|
|
6845
|
-
}
|
|
6846
6096
|
isMobileDevice() {
|
|
6847
6097
|
const userAgent = navigator.userAgent.toLowerCase();
|
|
6848
6098
|
const mobileKeywords = ['android', 'iphone', 'ipad', 'ipod', 'blackberry', 'windows phone', 'mobile'];
|
|
@@ -6956,8 +6206,6 @@ export class WebPlayer extends BasePlayer {
|
|
|
6956
6206
|
hideControls() {
|
|
6957
6207
|
if (!this.state.isPlaying)
|
|
6958
6208
|
return;
|
|
6959
|
-
if (this.isSettingsOpen)
|
|
6960
|
-
return;
|
|
6961
6209
|
const wrapper = this.container?.querySelector('.uvf-player-wrapper');
|
|
6962
6210
|
if (wrapper) {
|
|
6963
6211
|
wrapper.classList.remove('controls-visible');
|
|
@@ -6967,13 +6215,11 @@ export class WebPlayer extends BasePlayer {
|
|
|
6967
6215
|
scheduleHideControls() {
|
|
6968
6216
|
if (!this.state.isPlaying)
|
|
6969
6217
|
return;
|
|
6970
|
-
if (this.isSettingsOpen)
|
|
6971
|
-
return;
|
|
6972
6218
|
if (this.hideControlsTimeout)
|
|
6973
6219
|
clearTimeout(this.hideControlsTimeout);
|
|
6974
6220
|
const timeout = this.isFullscreen() ? 4000 : 3000;
|
|
6975
6221
|
this.hideControlsTimeout = setTimeout(() => {
|
|
6976
|
-
if (this.state.isPlaying && !this.controlsContainer?.matches(':hover')
|
|
6222
|
+
if (this.state.isPlaying && !this.controlsContainer?.matches(':hover')) {
|
|
6977
6223
|
this.hideControls();
|
|
6978
6224
|
}
|
|
6979
6225
|
}, timeout);
|
|
@@ -8010,7 +7256,6 @@ export class WebPlayer extends BasePlayer {
|
|
|
8010
7256
|
if (!settingsMenu)
|
|
8011
7257
|
return;
|
|
8012
7258
|
settingsMenu.classList.remove('active');
|
|
8013
|
-
this.isSettingsOpen = false;
|
|
8014
7259
|
settingsMenu.style.display = 'none';
|
|
8015
7260
|
settingsMenu.style.visibility = 'hidden';
|
|
8016
7261
|
settingsMenu.style.opacity = '0';
|
|
@@ -8018,7 +7263,6 @@ export class WebPlayer extends BasePlayer {
|
|
|
8018
7263
|
item.classList.remove('expanded');
|
|
8019
7264
|
});
|
|
8020
7265
|
this.debugLog('Settings menu hidden via hideSettingsMenu()');
|
|
8021
|
-
this.scheduleHideControls();
|
|
8022
7266
|
}
|
|
8023
7267
|
updateAccordionAfterSelection(section) {
|
|
8024
7268
|
setTimeout(() => {
|