unified-video-framework 1.4.209 → 1.4.211
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.
- package/package.json +1 -1
- package/packages/core/dist/BasePlayer.d.ts +6 -5
- package/packages/core/dist/BasePlayer.d.ts.map +1 -1
- package/packages/core/dist/BasePlayer.js.map +1 -1
- package/packages/core/dist/VideoPlayer.js +1 -1
- package/packages/core/dist/VideoPlayer.js.map +1 -1
- package/packages/core/dist/interfaces/IVideoPlayer.d.ts +5 -3
- package/packages/core/dist/interfaces/IVideoPlayer.d.ts.map +1 -1
- package/packages/core/dist/interfaces.d.ts +26 -1
- package/packages/core/dist/interfaces.d.ts.map +1 -1
- package/packages/core/src/BasePlayer.ts +5 -5
- package/packages/core/src/VideoPlayer.ts +1 -1
- package/packages/core/src/interfaces/IVideoPlayer.ts +6 -3
- package/packages/core/src/interfaces.ts +60 -26
- package/packages/web/dist/WebPlayer.d.ts +8 -0
- package/packages/web/dist/WebPlayer.d.ts.map +1 -1
- package/packages/web/dist/WebPlayer.js +541 -36
- package/packages/web/dist/WebPlayer.js.map +1 -1
- package/packages/web/dist/react/WebPlayerView.d.ts +24 -0
- package/packages/web/dist/react/WebPlayerView.d.ts.map +1 -1
- package/packages/web/dist/react/WebPlayerView.js +8 -0
- package/packages/web/dist/react/WebPlayerView.js.map +1 -1
- package/packages/web/dist/react/components/EPGOverlay-improved-positioning.d.ts.map +1 -1
- package/packages/web/dist/react/components/EPGOverlay-improved-positioning.js +0 -8
- package/packages/web/dist/react/components/EPGOverlay-improved-positioning.js.map +1 -1
- package/packages/web/dist/react/components/EPGOverlay.d.ts.map +1 -1
- package/packages/web/dist/react/components/EPGOverlay.js +0 -8
- package/packages/web/dist/react/components/EPGOverlay.js.map +1 -1
- package/packages/web/src/WebPlayer.ts +632 -41
- package/packages/web/src/react/WebPlayerView.tsx +39 -0
- package/packages/web/src/react/components/EPGOverlay-improved-positioning.tsx +0 -8
- package/packages/web/src/react/components/EPGOverlay.tsx +0 -8
|
@@ -3253,7 +3253,7 @@ export class WebPlayer extends BasePlayer {
|
|
|
3253
3253
|
margin-left: 10px;
|
|
3254
3254
|
}
|
|
3255
3255
|
|
|
3256
|
-
/* Top Bar Container - Contains Title (left) and Controls (right) */
|
|
3256
|
+
/* Top Bar Container - Contains Navigation + Title (left) and Controls (right) */
|
|
3257
3257
|
.uvf-top-bar {
|
|
3258
3258
|
position: absolute;
|
|
3259
3259
|
top: 0;
|
|
@@ -3270,16 +3270,97 @@ export class WebPlayer extends BasePlayer {
|
|
|
3270
3270
|
transition: all 0.3s ease;
|
|
3271
3271
|
}
|
|
3272
3272
|
|
|
3273
|
+
/* Left side container for navigation + title */
|
|
3274
|
+
.uvf-left-side {
|
|
3275
|
+
display: flex;
|
|
3276
|
+
align-items: center;
|
|
3277
|
+
gap: 12px;
|
|
3278
|
+
flex: 1;
|
|
3279
|
+
max-width: 70%;
|
|
3280
|
+
}
|
|
3281
|
+
|
|
3282
|
+
/* Navigation controls container */
|
|
3283
|
+
.uvf-navigation-controls {
|
|
3284
|
+
display: flex;
|
|
3285
|
+
align-items: center;
|
|
3286
|
+
gap: 8px;
|
|
3287
|
+
flex-shrink: 0;
|
|
3288
|
+
}
|
|
3289
|
+
|
|
3290
|
+
/* Navigation button styles */
|
|
3291
|
+
.uvf-nav-btn {
|
|
3292
|
+
width: 40px;
|
|
3293
|
+
height: 40px;
|
|
3294
|
+
min-width: 40px;
|
|
3295
|
+
min-height: 40px;
|
|
3296
|
+
border-radius: 50%;
|
|
3297
|
+
background: rgba(0, 0, 0, 0.6);
|
|
3298
|
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
3299
|
+
color: white;
|
|
3300
|
+
cursor: pointer;
|
|
3301
|
+
display: flex;
|
|
3302
|
+
align-items: center;
|
|
3303
|
+
justify-content: center;
|
|
3304
|
+
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
3305
|
+
backdrop-filter: blur(8px);
|
|
3306
|
+
position: relative;
|
|
3307
|
+
overflow: hidden;
|
|
3308
|
+
}
|
|
3309
|
+
|
|
3310
|
+
.uvf-nav-btn:hover {
|
|
3311
|
+
background: rgba(255, 255, 255, 0.15);
|
|
3312
|
+
border-color: rgba(255, 255, 255, 0.4);
|
|
3313
|
+
transform: scale(1.05);
|
|
3314
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
|
3315
|
+
}
|
|
3316
|
+
|
|
3317
|
+
.uvf-nav-btn:active {
|
|
3318
|
+
transform: scale(0.95);
|
|
3319
|
+
}
|
|
3320
|
+
|
|
3321
|
+
.uvf-nav-btn svg {
|
|
3322
|
+
width: 20px;
|
|
3323
|
+
height: 20px;
|
|
3324
|
+
fill: currentColor;
|
|
3325
|
+
transition: all 0.2s ease;
|
|
3326
|
+
}
|
|
3327
|
+
|
|
3328
|
+
.uvf-nav-btn:hover svg {
|
|
3329
|
+
transform: scale(1.1);
|
|
3330
|
+
}
|
|
3331
|
+
|
|
3332
|
+
/* Back button specific styles */
|
|
3333
|
+
#uvf-back-btn {
|
|
3334
|
+
background: rgba(0, 0, 0, 0.7);
|
|
3335
|
+
}
|
|
3336
|
+
|
|
3337
|
+
#uvf-back-btn:hover {
|
|
3338
|
+
background: rgba(255, 255, 255, 0.2);
|
|
3339
|
+
border-color: var(--uvf-accent-1, #ff0000);
|
|
3340
|
+
}
|
|
3341
|
+
|
|
3342
|
+
/* Close button specific styles */
|
|
3343
|
+
#uvf-close-btn {
|
|
3344
|
+
background: rgba(220, 53, 69, 0.8);
|
|
3345
|
+
border-color: rgba(220, 53, 69, 0.6);
|
|
3346
|
+
}
|
|
3347
|
+
|
|
3348
|
+
#uvf-close-btn:hover {
|
|
3349
|
+
background: rgba(220, 53, 69, 1);
|
|
3350
|
+
border-color: rgba(220, 53, 69, 1);
|
|
3351
|
+
box-shadow: 0 4px 12px rgba(220, 53, 69, 0.4);
|
|
3352
|
+
}
|
|
3353
|
+
|
|
3273
3354
|
.uvf-player-wrapper:hover .uvf-top-bar,
|
|
3274
3355
|
.uvf-player-wrapper.controls-visible .uvf-top-bar {
|
|
3275
3356
|
opacity: 1;
|
|
3276
3357
|
transform: translateY(0);
|
|
3277
3358
|
}
|
|
3278
3359
|
|
|
3279
|
-
/* Title Bar -
|
|
3360
|
+
/* Title Bar - After navigation buttons */
|
|
3280
3361
|
.uvf-title-bar {
|
|
3281
|
-
flex:
|
|
3282
|
-
|
|
3362
|
+
flex: 1;
|
|
3363
|
+
min-width: 0; /* Allow shrinking */
|
|
3283
3364
|
}
|
|
3284
3365
|
|
|
3285
3366
|
/* Top Controls - Right side of top bar */
|
|
@@ -3294,33 +3375,112 @@ export class WebPlayer extends BasePlayer {
|
|
|
3294
3375
|
.uvf-title-content {
|
|
3295
3376
|
display: flex;
|
|
3296
3377
|
align-items: center;
|
|
3297
|
-
|
|
3378
|
+
width: 100%;
|
|
3379
|
+
min-width: 0; /* Allow shrinking */
|
|
3298
3380
|
}
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
border: 1px solid rgba(255,255,255,0.25);
|
|
3306
|
-
background: rgba(255,255,255,0.05);
|
|
3381
|
+
|
|
3382
|
+
.uvf-title-text {
|
|
3383
|
+
display: flex;
|
|
3384
|
+
flex-direction: column;
|
|
3385
|
+
min-width: 0; /* Allow shrinking */
|
|
3386
|
+
flex: 1;
|
|
3307
3387
|
}
|
|
3308
|
-
|
|
3388
|
+
|
|
3309
3389
|
.uvf-video-title {
|
|
3310
3390
|
color: var(--uvf-text-primary);
|
|
3311
|
-
font-size: 18px;
|
|
3391
|
+
font-size: clamp(14px, 2.5vw, 18px); /* Responsive font size */
|
|
3312
3392
|
font-weight: 600;
|
|
3313
3393
|
text-shadow: 0 2px 4px rgba(0,0,0,0.5);
|
|
3394
|
+
line-height: 1.3;
|
|
3395
|
+
overflow: hidden;
|
|
3396
|
+
text-overflow: ellipsis;
|
|
3397
|
+
white-space: nowrap;
|
|
3398
|
+
max-width: 100%;
|
|
3399
|
+
cursor: pointer;
|
|
3400
|
+
transition: color 0.3s ease;
|
|
3401
|
+
position: relative;
|
|
3402
|
+
}
|
|
3403
|
+
|
|
3404
|
+
.uvf-video-title:hover {
|
|
3405
|
+
color: var(--uvf-accent-1, #ff0000);
|
|
3314
3406
|
}
|
|
3315
3407
|
|
|
3316
3408
|
.uvf-video-subtitle {
|
|
3317
3409
|
color: var(--uvf-text-secondary);
|
|
3318
|
-
font-size: 13px;
|
|
3319
|
-
margin-top:
|
|
3320
|
-
max-width: min(70vw, 900px);
|
|
3410
|
+
font-size: clamp(11px, 1.8vw, 13px); /* Responsive font size */
|
|
3411
|
+
margin-top: 2px;
|
|
3321
3412
|
overflow: hidden;
|
|
3322
3413
|
text-overflow: ellipsis;
|
|
3323
3414
|
white-space: nowrap;
|
|
3415
|
+
max-width: 100%;
|
|
3416
|
+
opacity: 0.9;
|
|
3417
|
+
line-height: 1.4;
|
|
3418
|
+
cursor: pointer;
|
|
3419
|
+
transition: opacity 0.3s ease;
|
|
3420
|
+
position: relative;
|
|
3421
|
+
}
|
|
3422
|
+
|
|
3423
|
+
.uvf-video-subtitle:hover {
|
|
3424
|
+
opacity: 1;
|
|
3425
|
+
}
|
|
3426
|
+
|
|
3427
|
+
/* Tooltip for long text */
|
|
3428
|
+
.uvf-text-tooltip {
|
|
3429
|
+
position: absolute;
|
|
3430
|
+
bottom: 100%;
|
|
3431
|
+
left: 0;
|
|
3432
|
+
background: rgba(0, 0, 0, 0.9);
|
|
3433
|
+
color: white;
|
|
3434
|
+
padding: 8px 12px;
|
|
3435
|
+
border-radius: 6px;
|
|
3436
|
+
font-size: 13px;
|
|
3437
|
+
line-height: 1.4;
|
|
3438
|
+
max-width: 400px;
|
|
3439
|
+
word-wrap: break-word;
|
|
3440
|
+
white-space: normal;
|
|
3441
|
+
z-index: 1000;
|
|
3442
|
+
opacity: 0;
|
|
3443
|
+
visibility: hidden;
|
|
3444
|
+
transform: translateY(-5px);
|
|
3445
|
+
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
3446
|
+
pointer-events: none;
|
|
3447
|
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
3448
|
+
backdrop-filter: blur(8px);
|
|
3449
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
|
|
3450
|
+
}
|
|
3451
|
+
|
|
3452
|
+
.uvf-text-tooltip::before {
|
|
3453
|
+
content: '';
|
|
3454
|
+
position: absolute;
|
|
3455
|
+
top: 100%;
|
|
3456
|
+
left: 12px;
|
|
3457
|
+
border: 5px solid transparent;
|
|
3458
|
+
border-top-color: rgba(0, 0, 0, 0.9);
|
|
3459
|
+
}
|
|
3460
|
+
|
|
3461
|
+
.uvf-text-tooltip.show {
|
|
3462
|
+
opacity: 1;
|
|
3463
|
+
visibility: visible;
|
|
3464
|
+
transform: translateY(0);
|
|
3465
|
+
}
|
|
3466
|
+
|
|
3467
|
+
/* Multi-line title option for desktop */
|
|
3468
|
+
.uvf-video-title.multiline {
|
|
3469
|
+
white-space: normal;
|
|
3470
|
+
display: -webkit-box;
|
|
3471
|
+
-webkit-line-clamp: 2;
|
|
3472
|
+
-webkit-box-orient: vertical;
|
|
3473
|
+
line-height: 1.2;
|
|
3474
|
+
max-height: 2.4em;
|
|
3475
|
+
}
|
|
3476
|
+
|
|
3477
|
+
.uvf-video-subtitle.multiline {
|
|
3478
|
+
white-space: normal;
|
|
3479
|
+
display: -webkit-box;
|
|
3480
|
+
-webkit-line-clamp: 3;
|
|
3481
|
+
-webkit-box-orient: vertical;
|
|
3482
|
+
line-height: 1.3;
|
|
3483
|
+
max-height: 3.9em;
|
|
3324
3484
|
}
|
|
3325
3485
|
|
|
3326
3486
|
/* Above seekbar section with time and branding */
|
|
@@ -3399,7 +3559,21 @@ export class WebPlayer extends BasePlayer {
|
|
|
3399
3559
|
}
|
|
3400
3560
|
}
|
|
3401
3561
|
|
|
3562
|
+
/* Ultra small screens */
|
|
3402
3563
|
@media (max-width: 480px) {
|
|
3564
|
+
.uvf-video-title {
|
|
3565
|
+
font-size: clamp(11px, 3.5vw, 14px) !important;
|
|
3566
|
+
}
|
|
3567
|
+
|
|
3568
|
+
.uvf-video-subtitle {
|
|
3569
|
+
font-size: clamp(9px, 2.5vw, 11px) !important;
|
|
3570
|
+
-webkit-line-clamp: 1; /* Single line on very small screens */
|
|
3571
|
+
}
|
|
3572
|
+
|
|
3573
|
+
.uvf-left-side {
|
|
3574
|
+
max-width: 80%;
|
|
3575
|
+
}
|
|
3576
|
+
|
|
3403
3577
|
.uvf-above-seekbar-section {
|
|
3404
3578
|
margin-bottom: 5px;
|
|
3405
3579
|
}
|
|
@@ -3787,14 +3961,55 @@ export class WebPlayer extends BasePlayer {
|
|
|
3787
3961
|
}
|
|
3788
3962
|
|
|
3789
3963
|
|
|
3790
|
-
/* Mobile
|
|
3964
|
+
/* Mobile responsive styles for navigation buttons */
|
|
3965
|
+
@media screen and (max-width: 767px) {
|
|
3966
|
+
.uvf-nav-btn {
|
|
3967
|
+
width: 36px;
|
|
3968
|
+
height: 36px;
|
|
3969
|
+
min-width: 36px;
|
|
3970
|
+
min-height: 36px;
|
|
3971
|
+
}
|
|
3972
|
+
|
|
3973
|
+
.uvf-nav-btn svg {
|
|
3974
|
+
width: 18px;
|
|
3975
|
+
height: 18px;
|
|
3976
|
+
}
|
|
3977
|
+
|
|
3978
|
+
.uvf-navigation-controls {
|
|
3979
|
+
gap: 6px;
|
|
3980
|
+
}
|
|
3981
|
+
|
|
3982
|
+
.uvf-left-side {
|
|
3983
|
+
gap: 8px;
|
|
3984
|
+
max-width: 75%;
|
|
3985
|
+
}
|
|
3986
|
+
|
|
3987
|
+
/* Mobile title adjustments */
|
|
3988
|
+
.uvf-video-title {
|
|
3989
|
+
font-size: clamp(12px, 3vw, 16px) !important;
|
|
3990
|
+
line-height: 1.2;
|
|
3991
|
+
}
|
|
3992
|
+
|
|
3993
|
+
.uvf-video-subtitle {
|
|
3994
|
+
font-size: clamp(10px, 2.2vw, 12px) !important;
|
|
3995
|
+
margin-top: 1px;
|
|
3996
|
+
/* Allow wrapping on mobile if needed */
|
|
3997
|
+
white-space: normal;
|
|
3998
|
+
display: -webkit-box;
|
|
3999
|
+
-webkit-line-clamp: 2;
|
|
4000
|
+
-webkit-box-orient: vertical;
|
|
4001
|
+
overflow: hidden;
|
|
4002
|
+
}
|
|
4003
|
+
}
|
|
4004
|
+
|
|
4005
|
+
/* Mobile portrait - hide skip buttons, ensure top bar syncs with controls */
|
|
3791
4006
|
@media screen and (max-width: 767px) and (orientation: portrait) {
|
|
3792
4007
|
#uvf-skip-back,
|
|
3793
4008
|
#uvf-skip-forward {
|
|
3794
4009
|
display: none !important;
|
|
3795
4010
|
}
|
|
3796
4011
|
|
|
3797
|
-
/*
|
|
4012
|
+
/* Top bar structure */
|
|
3798
4013
|
.uvf-top-bar {
|
|
3799
4014
|
display: flex !important;
|
|
3800
4015
|
z-index: 10 !important;
|
|
@@ -3804,8 +4019,13 @@ export class WebPlayer extends BasePlayer {
|
|
|
3804
4019
|
display: flex !important;
|
|
3805
4020
|
}
|
|
3806
4021
|
|
|
3807
|
-
/*
|
|
3808
|
-
.uvf-player-wrapper:hover .uvf-top-bar
|
|
4022
|
+
/* Disable hover effect on mobile - use only controls-visible class */
|
|
4023
|
+
.uvf-player-wrapper:hover .uvf-top-bar {
|
|
4024
|
+
opacity: 0 !important;
|
|
4025
|
+
transform: translateY(-10px) !important;
|
|
4026
|
+
}
|
|
4027
|
+
|
|
4028
|
+
/* Show top bar ONLY when controls are visible */
|
|
3809
4029
|
.uvf-player-wrapper.controls-visible .uvf-top-bar {
|
|
3810
4030
|
opacity: 1 !important;
|
|
3811
4031
|
transform: translateY(0) !important;
|
|
@@ -3941,6 +4161,18 @@ export class WebPlayer extends BasePlayer {
|
|
|
3941
4161
|
height: 16px;
|
|
3942
4162
|
}
|
|
3943
4163
|
|
|
4164
|
+
/* Disable hover effect on mobile landscape - use only controls-visible class */
|
|
4165
|
+
.uvf-player-wrapper:hover .uvf-top-bar {
|
|
4166
|
+
opacity: 0 !important;
|
|
4167
|
+
transform: translateY(-10px) !important;
|
|
4168
|
+
}
|
|
4169
|
+
|
|
4170
|
+
/* Show top bar ONLY when controls are visible */
|
|
4171
|
+
.uvf-player-wrapper.controls-visible .uvf-top-bar {
|
|
4172
|
+
opacity: 1 !important;
|
|
4173
|
+
transform: translateY(0) !important;
|
|
4174
|
+
}
|
|
4175
|
+
|
|
3944
4176
|
/* Top bar in fullscreen landscape */
|
|
3945
4177
|
.uvf-player-wrapper.uvf-fullscreen .uvf-top-bar,
|
|
3946
4178
|
.uvf-player-wrapper.uvf-fullscreen .uvf-video-container .uvf-top-bar,
|
|
@@ -3954,6 +4186,31 @@ export class WebPlayer extends BasePlayer {
|
|
|
3954
4186
|
|
|
3955
4187
|
/* Tablet devices - Enhanced UX with desktop features */
|
|
3956
4188
|
@media screen and (min-width: 768px) and (max-width: 1023px) {
|
|
4189
|
+
/* Tablet navigation and title adjustments */
|
|
4190
|
+
.uvf-nav-btn {
|
|
4191
|
+
width: 38px;
|
|
4192
|
+
height: 38px;
|
|
4193
|
+
min-width: 38px;
|
|
4194
|
+
min-height: 38px;
|
|
4195
|
+
}
|
|
4196
|
+
|
|
4197
|
+
.uvf-nav-btn svg {
|
|
4198
|
+
width: 19px;
|
|
4199
|
+
height: 19px;
|
|
4200
|
+
}
|
|
4201
|
+
|
|
4202
|
+
.uvf-left-side {
|
|
4203
|
+
max-width: 70%;
|
|
4204
|
+
}
|
|
4205
|
+
|
|
4206
|
+
.uvf-video-title {
|
|
4207
|
+
font-size: clamp(15px, 2.2vw, 17px) !important;
|
|
4208
|
+
}
|
|
4209
|
+
|
|
4210
|
+
.uvf-video-subtitle {
|
|
4211
|
+
font-size: clamp(12px, 1.8vw, 13px) !important;
|
|
4212
|
+
}
|
|
4213
|
+
|
|
3957
4214
|
.uvf-controls-bar {
|
|
3958
4215
|
padding: 18px 16px;
|
|
3959
4216
|
background: linear-gradient(to top, var(--uvf-overlay-strong) 0%, var(--uvf-overlay-medium) 70%, var(--uvf-overlay-transparent) 100%);
|
|
@@ -4486,6 +4743,40 @@ export class WebPlayer extends BasePlayer {
|
|
|
4486
4743
|
}
|
|
4487
4744
|
}
|
|
4488
4745
|
|
|
4746
|
+
/* Desktop styles for title and navigation */
|
|
4747
|
+
@media screen and (min-width: 1024px) {
|
|
4748
|
+
.uvf-left-side {
|
|
4749
|
+
max-width: 65%; /* More space for title on desktop */
|
|
4750
|
+
}
|
|
4751
|
+
|
|
4752
|
+
.uvf-video-title {
|
|
4753
|
+
font-size: clamp(16px, 1.8vw, 20px) !important;
|
|
4754
|
+
font-weight: 700; /* Bolder on desktop */
|
|
4755
|
+
}
|
|
4756
|
+
|
|
4757
|
+
.uvf-video-subtitle {
|
|
4758
|
+
font-size: clamp(13px, 1.4vw, 15px) !important;
|
|
4759
|
+
margin-top: 3px;
|
|
4760
|
+
}
|
|
4761
|
+
|
|
4762
|
+
/* Allow hover effects on desktop */
|
|
4763
|
+
.uvf-title-bar:hover .uvf-video-title {
|
|
4764
|
+
color: var(--uvf-accent-1, #ff0000);
|
|
4765
|
+
transition: color 0.3s ease;
|
|
4766
|
+
}
|
|
4767
|
+
}
|
|
4768
|
+
|
|
4769
|
+
/* Ultra-wide screens */
|
|
4770
|
+
@media screen and (min-width: 1440px) {
|
|
4771
|
+
.uvf-video-title {
|
|
4772
|
+
font-size: clamp(18px, 1.6vw, 22px) !important;
|
|
4773
|
+
}
|
|
4774
|
+
|
|
4775
|
+
.uvf-video-subtitle {
|
|
4776
|
+
font-size: clamp(14px, 1.2vw, 16px) !important;
|
|
4777
|
+
}
|
|
4778
|
+
}
|
|
4779
|
+
|
|
4489
4780
|
/* Paywall Desktop */
|
|
4490
4781
|
@media screen and (min-width: 1024px) {
|
|
4491
4782
|
.uvf-paywall-modal {
|
|
@@ -4544,6 +4835,100 @@ export class WebPlayer extends BasePlayer {
|
|
|
4544
4835
|
container.appendChild(brandingContainer);
|
|
4545
4836
|
this.debugLog('Framework branding added');
|
|
4546
4837
|
}
|
|
4838
|
+
createNavigationButtons(container) {
|
|
4839
|
+
const navigationConfig = this.config.navigation;
|
|
4840
|
+
if (!navigationConfig)
|
|
4841
|
+
return;
|
|
4842
|
+
const { backButton, closeButton } = navigationConfig;
|
|
4843
|
+
if (backButton?.enabled) {
|
|
4844
|
+
const backBtn = document.createElement('button');
|
|
4845
|
+
backBtn.className = 'uvf-control-btn uvf-nav-btn';
|
|
4846
|
+
backBtn.id = 'uvf-back-btn';
|
|
4847
|
+
backBtn.title = backButton.title || 'Back';
|
|
4848
|
+
backBtn.setAttribute('aria-label', backButton.ariaLabel || 'Go back');
|
|
4849
|
+
const backIcon = this.getNavigationIcon(backButton.icon || 'arrow', backButton.customIcon);
|
|
4850
|
+
backBtn.innerHTML = backIcon;
|
|
4851
|
+
backBtn.addEventListener('click', async (e) => {
|
|
4852
|
+
e.preventDefault();
|
|
4853
|
+
e.stopPropagation();
|
|
4854
|
+
if (backButton.onClick) {
|
|
4855
|
+
await backButton.onClick();
|
|
4856
|
+
}
|
|
4857
|
+
else if (backButton.href) {
|
|
4858
|
+
if (backButton.replace) {
|
|
4859
|
+
window.history.replaceState(null, '', backButton.href);
|
|
4860
|
+
}
|
|
4861
|
+
else {
|
|
4862
|
+
window.location.href = backButton.href;
|
|
4863
|
+
}
|
|
4864
|
+
}
|
|
4865
|
+
else {
|
|
4866
|
+
window.history.back();
|
|
4867
|
+
}
|
|
4868
|
+
this.emit('navigationBackClicked');
|
|
4869
|
+
});
|
|
4870
|
+
container.appendChild(backBtn);
|
|
4871
|
+
}
|
|
4872
|
+
if (closeButton?.enabled) {
|
|
4873
|
+
const closeBtn = document.createElement('button');
|
|
4874
|
+
closeBtn.className = 'uvf-control-btn uvf-nav-btn';
|
|
4875
|
+
closeBtn.id = 'uvf-close-btn';
|
|
4876
|
+
closeBtn.title = closeButton.title || 'Close';
|
|
4877
|
+
closeBtn.setAttribute('aria-label', closeButton.ariaLabel || 'Close player');
|
|
4878
|
+
const closeIcon = this.getNavigationIcon(closeButton.icon || 'x', closeButton.customIcon);
|
|
4879
|
+
closeBtn.innerHTML = closeIcon;
|
|
4880
|
+
closeBtn.addEventListener('click', async (e) => {
|
|
4881
|
+
e.preventDefault();
|
|
4882
|
+
e.stopPropagation();
|
|
4883
|
+
if (closeButton.onClick) {
|
|
4884
|
+
await closeButton.onClick();
|
|
4885
|
+
}
|
|
4886
|
+
else {
|
|
4887
|
+
if (closeButton.exitFullscreen && this.isFullscreen()) {
|
|
4888
|
+
await this.exitFullscreen();
|
|
4889
|
+
}
|
|
4890
|
+
if (closeButton.closeModal) {
|
|
4891
|
+
const playerWrapper = this.container?.querySelector('.uvf-player-wrapper');
|
|
4892
|
+
if (playerWrapper) {
|
|
4893
|
+
playerWrapper.style.display = 'none';
|
|
4894
|
+
}
|
|
4895
|
+
}
|
|
4896
|
+
}
|
|
4897
|
+
this.emit('navigationCloseClicked');
|
|
4898
|
+
});
|
|
4899
|
+
container.appendChild(closeBtn);
|
|
4900
|
+
}
|
|
4901
|
+
}
|
|
4902
|
+
getNavigationIcon(iconType, customIcon) {
|
|
4903
|
+
if (customIcon) {
|
|
4904
|
+
if (customIcon.startsWith('http') || customIcon.includes('.')) {
|
|
4905
|
+
return `<img src="${customIcon}" alt="" style="width: 20px; height: 20px;" />`;
|
|
4906
|
+
}
|
|
4907
|
+
return customIcon;
|
|
4908
|
+
}
|
|
4909
|
+
switch (iconType) {
|
|
4910
|
+
case 'arrow':
|
|
4911
|
+
return `<svg viewBox="0 0 24 24">
|
|
4912
|
+
<path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.42-1.41L7.83 13H20v-2z" fill="currentColor"/>
|
|
4913
|
+
</svg>`;
|
|
4914
|
+
case 'chevron':
|
|
4915
|
+
return `<svg viewBox="0 0 24 24">
|
|
4916
|
+
<path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z" fill="currentColor"/>
|
|
4917
|
+
</svg>`;
|
|
4918
|
+
case 'x':
|
|
4919
|
+
return `<svg viewBox="0 0 24 24">
|
|
4920
|
+
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" fill="currentColor"/>
|
|
4921
|
+
</svg>`;
|
|
4922
|
+
case 'close':
|
|
4923
|
+
return `<svg viewBox="0 0 24 24">
|
|
4924
|
+
<path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z" fill="currentColor"/>
|
|
4925
|
+
</svg>`;
|
|
4926
|
+
default:
|
|
4927
|
+
return `<svg viewBox="0 0 24 24">
|
|
4928
|
+
<path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.42-1.41L7.83 13H20v-2z" fill="currentColor"/>
|
|
4929
|
+
</svg>`;
|
|
4930
|
+
}
|
|
4931
|
+
}
|
|
4547
4932
|
createCustomControls(container) {
|
|
4548
4933
|
const topGradient = document.createElement('div');
|
|
4549
4934
|
topGradient.className = 'uvf-top-gradient';
|
|
@@ -4553,18 +4938,24 @@ export class WebPlayer extends BasePlayer {
|
|
|
4553
4938
|
container.appendChild(controlsGradient);
|
|
4554
4939
|
const topBar = document.createElement('div');
|
|
4555
4940
|
topBar.className = 'uvf-top-bar';
|
|
4941
|
+
const leftSide = document.createElement('div');
|
|
4942
|
+
leftSide.className = 'uvf-left-side';
|
|
4943
|
+
const navigationControls = document.createElement('div');
|
|
4944
|
+
navigationControls.className = 'uvf-navigation-controls';
|
|
4945
|
+
this.createNavigationButtons(navigationControls);
|
|
4946
|
+
leftSide.appendChild(navigationControls);
|
|
4556
4947
|
const titleBar = document.createElement('div');
|
|
4557
4948
|
titleBar.className = 'uvf-title-bar';
|
|
4558
4949
|
titleBar.innerHTML = `
|
|
4559
4950
|
<div class="uvf-title-content">
|
|
4560
|
-
<img class="uvf-video-thumb" id="uvf-video-thumb" alt="thumbnail" style="display:none;" />
|
|
4561
4951
|
<div class="uvf-title-text">
|
|
4562
4952
|
<div class=\"uvf-video-title\" id=\"uvf-video-title\" style=\"display:none;\"></div>
|
|
4563
4953
|
<div class=\"uvf-video-subtitle\" id=\"uvf-video-description\" style=\"display:none;\"></div>
|
|
4564
4954
|
</div>
|
|
4565
4955
|
</div>
|
|
4566
4956
|
`;
|
|
4567
|
-
|
|
4957
|
+
leftSide.appendChild(titleBar);
|
|
4958
|
+
topBar.appendChild(leftSide);
|
|
4568
4959
|
const topControls = document.createElement('div');
|
|
4569
4960
|
topControls.className = 'uvf-top-controls';
|
|
4570
4961
|
topControls.innerHTML = `
|
|
@@ -5225,11 +5616,13 @@ export class WebPlayer extends BasePlayer {
|
|
|
5225
5616
|
break;
|
|
5226
5617
|
case 'ArrowLeft':
|
|
5227
5618
|
e.preventDefault();
|
|
5619
|
+
e.stopImmediatePropagation();
|
|
5228
5620
|
this.seek(Math.max(0, this.video.currentTime - 10));
|
|
5229
5621
|
shortcutText = '-10s';
|
|
5230
5622
|
break;
|
|
5231
5623
|
case 'ArrowRight':
|
|
5232
5624
|
e.preventDefault();
|
|
5625
|
+
e.stopImmediatePropagation();
|
|
5233
5626
|
this.seek(Math.min(this.video.duration, this.video.currentTime + 10));
|
|
5234
5627
|
shortcutText = '+10s';
|
|
5235
5628
|
break;
|
|
@@ -6210,7 +6603,7 @@ export class WebPlayer extends BasePlayer {
|
|
|
6210
6603
|
autoSkip: this.chapterConfig.userPreferences?.autoSkipIntro || false,
|
|
6211
6604
|
onChapterChange: (chapter) => {
|
|
6212
6605
|
this.debugLog('Core chapter changed:', chapter?.title || 'none');
|
|
6213
|
-
this.emit('
|
|
6606
|
+
this.emit('onChapterchange', chapter);
|
|
6214
6607
|
},
|
|
6215
6608
|
onSegmentEntered: (segment) => {
|
|
6216
6609
|
this.debugLog('Core segment entered:', segment.title);
|
|
@@ -7323,6 +7716,123 @@ export class WebPlayer extends BasePlayer {
|
|
|
7323
7716
|
this.showNotification('Share failed');
|
|
7324
7717
|
}
|
|
7325
7718
|
}
|
|
7719
|
+
isTextTruncated(element) {
|
|
7720
|
+
return element.scrollWidth > element.offsetWidth || element.scrollHeight > element.offsetHeight;
|
|
7721
|
+
}
|
|
7722
|
+
showTextTooltip(element, text) {
|
|
7723
|
+
const existingTooltip = element.querySelector('.uvf-text-tooltip');
|
|
7724
|
+
if (existingTooltip) {
|
|
7725
|
+
existingTooltip.remove();
|
|
7726
|
+
}
|
|
7727
|
+
const tooltip = document.createElement('div');
|
|
7728
|
+
tooltip.className = 'uvf-text-tooltip';
|
|
7729
|
+
tooltip.textContent = text;
|
|
7730
|
+
element.appendChild(tooltip);
|
|
7731
|
+
setTimeout(() => {
|
|
7732
|
+
tooltip.classList.add('show');
|
|
7733
|
+
}, 100);
|
|
7734
|
+
}
|
|
7735
|
+
hideTextTooltip(element) {
|
|
7736
|
+
const tooltip = element.querySelector('.uvf-text-tooltip');
|
|
7737
|
+
if (tooltip) {
|
|
7738
|
+
tooltip.classList.remove('show');
|
|
7739
|
+
setTimeout(() => {
|
|
7740
|
+
if (tooltip.parentElement) {
|
|
7741
|
+
tooltip.remove();
|
|
7742
|
+
}
|
|
7743
|
+
}, 300);
|
|
7744
|
+
}
|
|
7745
|
+
}
|
|
7746
|
+
setupTextTooltips() {
|
|
7747
|
+
const titleElement = document.getElementById('uvf-video-title');
|
|
7748
|
+
const descElement = document.getElementById('uvf-video-description');
|
|
7749
|
+
if (titleElement) {
|
|
7750
|
+
titleElement.addEventListener('mouseenter', () => {
|
|
7751
|
+
const titleText = (this.source?.metadata?.title || '').toString().trim();
|
|
7752
|
+
if (this.isTextTruncated(titleElement) && titleText) {
|
|
7753
|
+
this.showTextTooltip(titleElement, titleText);
|
|
7754
|
+
}
|
|
7755
|
+
});
|
|
7756
|
+
titleElement.addEventListener('mouseleave', () => {
|
|
7757
|
+
this.hideTextTooltip(titleElement);
|
|
7758
|
+
});
|
|
7759
|
+
titleElement.addEventListener('touchstart', () => {
|
|
7760
|
+
const titleText = (this.source?.metadata?.title || '').toString().trim();
|
|
7761
|
+
if (this.isTextTruncated(titleElement) && titleText) {
|
|
7762
|
+
this.showTextTooltip(titleElement, titleText);
|
|
7763
|
+
setTimeout(() => {
|
|
7764
|
+
this.hideTextTooltip(titleElement);
|
|
7765
|
+
}, 3000);
|
|
7766
|
+
}
|
|
7767
|
+
});
|
|
7768
|
+
}
|
|
7769
|
+
if (descElement) {
|
|
7770
|
+
descElement.addEventListener('mouseenter', () => {
|
|
7771
|
+
const descText = (this.source?.metadata?.description || '').toString().trim();
|
|
7772
|
+
if (this.isTextTruncated(descElement) && descText) {
|
|
7773
|
+
this.showTextTooltip(descElement, descText);
|
|
7774
|
+
}
|
|
7775
|
+
});
|
|
7776
|
+
descElement.addEventListener('mouseleave', () => {
|
|
7777
|
+
this.hideTextTooltip(descElement);
|
|
7778
|
+
});
|
|
7779
|
+
descElement.addEventListener('touchstart', () => {
|
|
7780
|
+
const descText = (this.source?.metadata?.description || '').toString().trim();
|
|
7781
|
+
if (this.isTextTruncated(descElement) && descText) {
|
|
7782
|
+
this.showTextTooltip(descElement, descText);
|
|
7783
|
+
setTimeout(() => {
|
|
7784
|
+
this.hideTextTooltip(descElement);
|
|
7785
|
+
}, 3000);
|
|
7786
|
+
}
|
|
7787
|
+
});
|
|
7788
|
+
}
|
|
7789
|
+
}
|
|
7790
|
+
smartTruncateText(text, maxWords = 12) {
|
|
7791
|
+
const words = text.split(' ');
|
|
7792
|
+
if (words.length <= maxWords) {
|
|
7793
|
+
return { truncated: text, needsTooltip: false };
|
|
7794
|
+
}
|
|
7795
|
+
const truncated = words.slice(0, maxWords).join(' ') + '...';
|
|
7796
|
+
return { truncated, needsTooltip: true };
|
|
7797
|
+
}
|
|
7798
|
+
applySmartTextDisplay(titleEl, descEl, titleText, descText) {
|
|
7799
|
+
const isDesktop = window.innerWidth >= 1024;
|
|
7800
|
+
const isMobile = window.innerWidth < 768;
|
|
7801
|
+
if (titleEl && titleText) {
|
|
7802
|
+
const wordCount = titleText.split(' ').length;
|
|
7803
|
+
if (isDesktop && wordCount > 8 && wordCount <= 15) {
|
|
7804
|
+
titleEl.classList.add('multiline');
|
|
7805
|
+
titleEl.textContent = titleText;
|
|
7806
|
+
}
|
|
7807
|
+
else if (wordCount > 12) {
|
|
7808
|
+
const maxWords = isMobile ? 8 : isDesktop ? 12 : 10;
|
|
7809
|
+
const { truncated } = this.smartTruncateText(titleText, maxWords);
|
|
7810
|
+
titleEl.textContent = truncated;
|
|
7811
|
+
titleEl.classList.remove('multiline');
|
|
7812
|
+
}
|
|
7813
|
+
else {
|
|
7814
|
+
titleEl.textContent = titleText;
|
|
7815
|
+
titleEl.classList.remove('multiline');
|
|
7816
|
+
}
|
|
7817
|
+
}
|
|
7818
|
+
if (descEl && descText) {
|
|
7819
|
+
const wordCount = descText.split(' ').length;
|
|
7820
|
+
if (isDesktop && wordCount > 15 && wordCount <= 25) {
|
|
7821
|
+
descEl.classList.add('multiline');
|
|
7822
|
+
descEl.textContent = descText;
|
|
7823
|
+
}
|
|
7824
|
+
else if (wordCount > 20) {
|
|
7825
|
+
const maxWords = isMobile ? 12 : isDesktop ? 18 : 15;
|
|
7826
|
+
const { truncated } = this.smartTruncateText(descText, maxWords);
|
|
7827
|
+
descEl.textContent = truncated;
|
|
7828
|
+
descEl.classList.remove('multiline');
|
|
7829
|
+
}
|
|
7830
|
+
else {
|
|
7831
|
+
descEl.textContent = descText;
|
|
7832
|
+
descEl.classList.remove('multiline');
|
|
7833
|
+
}
|
|
7834
|
+
}
|
|
7835
|
+
}
|
|
7326
7836
|
updateMetadataUI() {
|
|
7327
7837
|
try {
|
|
7328
7838
|
const md = this.source?.metadata || {};
|
|
@@ -7333,28 +7843,23 @@ export class WebPlayer extends BasePlayer {
|
|
|
7333
7843
|
const titleText = (md.title || '').toString().trim();
|
|
7334
7844
|
const descText = (md.description || '').toString().trim();
|
|
7335
7845
|
const thumbUrl = (md.thumbnailUrl || '').toString().trim();
|
|
7846
|
+
this.applySmartTextDisplay(titleEl, descEl, titleText, descText);
|
|
7336
7847
|
if (titleEl) {
|
|
7337
|
-
titleEl.textContent = titleText;
|
|
7338
7848
|
titleEl.style.display = titleText ? 'block' : 'none';
|
|
7339
7849
|
}
|
|
7340
7850
|
if (descEl) {
|
|
7341
|
-
descEl.textContent = descText;
|
|
7342
7851
|
descEl.style.display = descText ? 'block' : 'none';
|
|
7343
7852
|
}
|
|
7344
7853
|
if (thumbEl) {
|
|
7345
|
-
|
|
7346
|
-
thumbEl.src = thumbUrl;
|
|
7347
|
-
thumbEl.style.display = 'block';
|
|
7348
|
-
}
|
|
7349
|
-
else {
|
|
7350
|
-
thumbEl.removeAttribute('src');
|
|
7351
|
-
thumbEl.style.display = 'none';
|
|
7352
|
-
}
|
|
7854
|
+
thumbEl.style.display = 'none';
|
|
7353
7855
|
}
|
|
7354
|
-
const hasAny = !!(titleText || descText
|
|
7856
|
+
const hasAny = !!(titleText || descText);
|
|
7355
7857
|
if (titleBar) {
|
|
7356
7858
|
titleBar.style.display = hasAny ? '' : 'none';
|
|
7357
7859
|
}
|
|
7860
|
+
setTimeout(() => {
|
|
7861
|
+
this.setupTextTooltips();
|
|
7862
|
+
}, 100);
|
|
7358
7863
|
}
|
|
7359
7864
|
catch (_) { }
|
|
7360
7865
|
}
|