unified-video-framework 1.4.120 → 1.4.122

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.
@@ -113,7 +113,7 @@ export class WebPlayer extends BasePlayer {
113
113
  const videoContainer = document.createElement('div');
114
114
  videoContainer.className = 'uvf-video-container';
115
115
 
116
- // Create video element
116
+ // Create video element with enhanced mobile optimization
117
117
  this.video = document.createElement('video');
118
118
  this.video.className = 'uvf-video';
119
119
  this.video.controls = false; // We'll use custom controls
@@ -123,6 +123,26 @@ export class WebPlayer extends BasePlayer {
123
123
  this.video.playsInline = this.config.playsInline ?? true;
124
124
  this.video.preload = this.config.preload ?? 'metadata';
125
125
 
126
+ // Enhanced mobile attributes
127
+ this.video.setAttribute('webkit-playsinline', 'true');
128
+ this.video.setAttribute('playsinline', 'true');
129
+ this.video.setAttribute('x-webkit-airplay', 'allow');
130
+ this.video.setAttribute('disablepictureinpicture', 'false');
131
+
132
+ // Mobile-specific video attributes for better performance
133
+ this.video.style.objectFit = 'contain';
134
+ this.video.style.objectPosition = 'center';
135
+ this.video.style.backgroundColor = '#000';
136
+
137
+ // Touch and interaction optimizations
138
+ this.video.style.touchAction = 'manipulation';
139
+ (this.video.style as any).webkitTouchCallout = 'none';
140
+ (this.video.style as any).webkitTapHighlightColor = 'transparent';
141
+
142
+ // Hardware acceleration
143
+ this.video.style.transform = 'translateZ(0)';
144
+ this.video.style.willChange = 'transform';
145
+
126
146
  if (this.config.crossOrigin) {
127
147
  this.video.crossOrigin = this.config.crossOrigin;
128
148
  }
@@ -1793,20 +1813,160 @@ export class WebPlayer extends BasePlayer {
1793
1813
  aspect-ratio: 16 / 9;
1794
1814
  background: radial-gradient(ellipse at center, #1a1a2e 0%, #000 100%);
1795
1815
  overflow: hidden;
1796
- display: flex;
1797
- align-items: center;
1798
- justify-content: center;
1799
1816
  }
1800
1817
 
1801
1818
  .uvf-video {
1802
- display: block;
1803
- max-width: 100%;
1804
- max-height: 100%;
1819
+ position: absolute;
1820
+ top: 0;
1821
+ left: 0;
1805
1822
  width: 100%;
1806
1823
  height: 100%;
1807
1824
  background: #000;
1808
1825
  object-fit: contain;
1809
1826
  object-position: center;
1827
+
1828
+ /* Enhanced mobile optimization */
1829
+ -webkit-playsinline: true;
1830
+ playsinline: true;
1831
+
1832
+ /* Prevent unwanted interactions on mobile */
1833
+ -webkit-user-select: none;
1834
+ -moz-user-select: none;
1835
+ -ms-user-select: none;
1836
+ user-select: none;
1837
+
1838
+ /* Smooth rendering and hardware acceleration */
1839
+ -webkit-transform: translateZ(0);
1840
+ transform: translateZ(0);
1841
+ will-change: transform;
1842
+
1843
+ /* Touch action optimization */
1844
+ touch-action: manipulation;
1845
+
1846
+ /* Prevent context menu on long press */
1847
+ -webkit-touch-callout: none;
1848
+ -webkit-tap-highlight-color: transparent;
1849
+
1850
+ /* Ensure consistent rendering across browsers */
1851
+ image-rendering: -webkit-optimize-contrast;
1852
+ image-rendering: crisp-edges;
1853
+ }
1854
+
1855
+ /* Enhanced mobile-specific video optimizations with safe areas */
1856
+ @media screen and (max-width: 767px) {
1857
+ .uvf-video {
1858
+ /* Safe area considerations for video content */
1859
+ margin-top: env(safe-area-inset-top, 0px);
1860
+ margin-bottom: env(safe-area-inset-bottom, 0px);
1861
+ margin-left: env(safe-area-inset-left, 0px);
1862
+ margin-right: env(safe-area-inset-right, 0px);
1863
+
1864
+ /* Adjust video area to account for safe zones */
1865
+ max-height: calc(100% - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px));
1866
+ max-width: calc(100% - env(safe-area-inset-left, 0px) - env(safe-area-inset-right, 0px));
1867
+
1868
+ /* Enhanced object positioning for mobile */
1869
+ object-position: center center;
1870
+
1871
+ /* Prevent video stretching on mobile */
1872
+ min-width: 0;
1873
+ min-height: 0;
1874
+
1875
+ /* Mobile-specific rendering optimizations */
1876
+ -webkit-transform: translate3d(0, 0, 0);
1877
+ transform: translate3d(0, 0, 0);
1878
+
1879
+ /* Optimize for mobile performance */
1880
+ backface-visibility: hidden;
1881
+ -webkit-backface-visibility: hidden;
1882
+
1883
+ /* Prevent video from being affected by orientation changes */
1884
+ -webkit-transform-style: preserve-3d;
1885
+ transform-style: preserve-3d;
1886
+ }
1887
+
1888
+ /* Portrait orientation specific adjustments */
1889
+ @media (orientation: portrait) {
1890
+ .uvf-video {
1891
+ /* Ensure video doesn't get cut off in portrait */
1892
+ max-height: calc(100vh - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px) - 120px);
1893
+ }
1894
+ }
1895
+
1896
+ /* Landscape orientation specific adjustments */
1897
+ @media (orientation: landscape) {
1898
+ .uvf-video {
1899
+ /* Full height usage in landscape mode */
1900
+ max-height: calc(100vh - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px) - 80px);
1901
+ max-width: calc(100vw - env(safe-area-inset-left, 0px) - env(safe-area-inset-right, 0px));
1902
+ }
1903
+ }
1904
+
1905
+ /* High DPI display optimizations */
1906
+ @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
1907
+ .uvf-video {
1908
+ /* Enhanced rendering for retina displays */
1909
+ image-rendering: -webkit-optimize-contrast;
1910
+ -webkit-font-smoothing: antialiased;
1911
+ -moz-osx-font-smoothing: grayscale;
1912
+ }
1913
+ }
1914
+
1915
+ /* iOS Safari specific video optimizations */
1916
+ @supports (-webkit-appearance: none) {
1917
+ .uvf-video {
1918
+ /* iOS-specific video handling */
1919
+ -webkit-mask-image: -webkit-radial-gradient(circle, white 100%, black 100%);
1920
+
1921
+ /* Prevent iOS Safari video rendering issues */
1922
+ -webkit-transform: translateZ(0);
1923
+ transform: translateZ(0);
1924
+
1925
+ /* iOS safe area integration */
1926
+ padding-top: env(safe-area-inset-top, 0px);
1927
+ padding-bottom: env(safe-area-inset-bottom, 0px);
1928
+ padding-left: env(safe-area-inset-left, 0px);
1929
+ padding-right: env(safe-area-inset-right, 0px);
1930
+
1931
+ /* Account for padding in dimensions */
1932
+ box-sizing: border-box;
1933
+ height: calc(100% - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px));
1934
+ width: calc(100% - env(safe-area-inset-left, 0px) - env(safe-area-inset-right, 0px));
1935
+ }
1936
+ }
1937
+
1938
+ /* Android Chrome specific optimizations */
1939
+ @media screen and (max-width: 767px) and (-webkit-min-device-pixel-ratio: 1) {
1940
+ .uvf-video {
1941
+ /* Android-specific optimizations */
1942
+ -webkit-transform: translateZ(0);
1943
+ transform: translateZ(0);
1944
+
1945
+ /* Handle Android navigation gestures */
1946
+ margin-bottom: max(env(safe-area-inset-bottom, 0px), 16px);
1947
+ }
1948
+ }
1949
+ }
1950
+
1951
+ /* Video fullscreen enhancements */
1952
+ .uvf-player-wrapper.uvf-fullscreen .uvf-video {
1953
+ /* Fullscreen-specific video optimizations */
1954
+ width: 100vw !important;
1955
+ height: 100vh !important;
1956
+ max-width: 100vw;
1957
+ max-height: 100vh;
1958
+
1959
+ /* Account for safe areas in fullscreen */
1960
+ padding-top: env(safe-area-inset-top, 0px);
1961
+ padding-bottom: env(safe-area-inset-bottom, 0px);
1962
+ padding-left: env(safe-area-inset-left, 0px);
1963
+ padding-right: env(safe-area-inset-right, 0px);
1964
+ box-sizing: border-box;
1965
+
1966
+ /* Optimize fullscreen rendering */
1967
+ -webkit-transform: translateZ(0);
1968
+ transform: translateZ(0);
1969
+ will-change: transform;
1810
1970
  }
1811
1971
 
1812
1972
  .uvf-watermark-layer {
@@ -2966,158 +3126,70 @@ export class WebPlayer extends BasePlayer {
2966
3126
  }
2967
3127
  }
2968
3128
 
2969
- /* Mobile-First Responsive Video Player Layout */
2970
-
2971
- /* Mobile devices (all orientations) - Base mobile styles */
2972
- @media screen and (max-width: 767px) {
2973
- /* Force full viewport usage with proper safe area handling */
3129
+ /* Enhanced Responsive Media Queries with UX Best Practices */
3130
+ /* Mobile devices (portrait) - Enhanced UX with Safe Areas */
3131
+ @media screen and (max-width: 767px) and (orientation: portrait) {
2974
3132
  .uvf-responsive-container {
2975
- position: fixed !important;
2976
- top: 0;
2977
- left: 0;
3133
+ padding: 0;
2978
3134
  width: 100vw !important;
2979
- height: 100vh !important;
2980
- height: calc(100vh - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px));
3135
+ height: calc(100vh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
2981
3136
  margin: 0;
2982
- padding: 0;
3137
+ position: relative;
2983
3138
  overflow: hidden;
2984
- z-index: 1000;
2985
3139
  }
2986
3140
 
2987
- /* Modern viewport support */
2988
3141
  @supports (height: 100dvh) {
2989
3142
  .uvf-responsive-container {
2990
- height: 100dvh !important;
2991
- height: calc(100dvh - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px));
3143
+ height: calc(100dvh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
2992
3144
  }
2993
3145
  }
2994
3146
 
2995
- /* Player wrapper fills container completely */
2996
3147
  .uvf-responsive-container .uvf-player-wrapper {
2997
- position: absolute;
2998
- top: 0;
2999
- left: 0;
3000
- width: 100% !important;
3148
+ width: 100vw !important;
3001
3149
  height: 100% !important;
3002
- max-width: none;
3003
- max-height: none;
3004
- display: flex;
3005
- flex-direction: column;
3150
+ min-height: calc(100vh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
3151
+ }
3152
+
3153
+ @supports (height: 100dvh) {
3154
+ .uvf-responsive-container .uvf-player-wrapper {
3155
+ min-height: calc(100dvh - var(--uvf-safe-area-top) - var(--uvf-safe-area-bottom));
3156
+ }
3006
3157
  }
3007
3158
 
3008
- /* Video container optimized for mobile centering */
3009
3159
  .uvf-responsive-container .uvf-video-container {
3010
- position: relative;
3011
- width: 100% !important;
3160
+ width: 100vw !important;
3012
3161
  height: 100% !important;
3013
- flex: 1;
3014
3162
  aspect-ratio: unset !important;
3015
- display: flex;
3016
- align-items: center;
3017
- justify-content: center;
3018
- background: #000;
3019
- overflow: hidden;
3020
- }
3021
-
3022
- /* Perfectly centered mobile video */
3023
- .uvf-responsive-container .uvf-video {
3024
- position: relative;
3025
- display: block;
3026
- width: 100%;
3027
- height: 100%;
3028
- max-width: 100%;
3029
- max-height: 100%;
3030
- object-fit: contain;
3031
- object-position: center center;
3032
- background: transparent;
3163
+ min-height: inherit;
3033
3164
  }
3034
3165
 
3035
- /* Mobile controls positioned with safe areas */
3166
+ /* Enhanced mobile controls bar with safe area padding */
3036
3167
  .uvf-controls-bar {
3037
- position: absolute !important;
3038
- bottom: env(safe-area-inset-bottom, 0px);
3039
- left: env(safe-area-inset-left, 0px);
3040
- right: env(safe-area-inset-right, 0px);
3041
- width: auto;
3042
- padding: 16px;
3043
- padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px));
3044
- padding-left: calc(16px + env(safe-area-inset-left, 0px));
3045
- padding-right: calc(16px + env(safe-area-inset-right, 0px));
3046
- background: linear-gradient(to top, rgba(0,0,0,0.9) 0%, rgba(0,0,0,0.6) 70%, transparent 100%);
3047
- backdrop-filter: blur(10px);
3048
- -webkit-backdrop-filter: blur(10px);
3168
+ position: absolute;
3169
+ bottom: 0;
3170
+ left: 0;
3171
+ right: 0;
3172
+ padding: 16px 12px;
3173
+ padding-bottom: calc(16px + var(--uvf-safe-area-bottom));
3174
+ padding-left: calc(12px + var(--uvf-safe-area-left));
3175
+ padding-right: calc(12px + var(--uvf-safe-area-right));
3176
+ background: linear-gradient(to top, var(--uvf-overlay-strong) 0%, var(--uvf-overlay-medium) 80%, var(--uvf-overlay-transparent) 100%);
3049
3177
  box-sizing: border-box;
3050
- z-index: 2000;
3051
- opacity: 1;
3052
- transform: none;
3053
- }
3054
-
3055
- /* Top controls with safe area */
3056
- .uvf-top-controls {
3057
- position: absolute !important;
3058
- top: calc(16px + env(safe-area-inset-top, 0px));
3059
- right: calc(16px + env(safe-area-inset-right, 0px));
3060
- z-index: 2000;
3178
+ z-index: 1000;
3061
3179
  }
3062
3180
 
3063
- /* Title bar with safe area */
3064
- .uvf-title-bar {
3065
- position: absolute !important;
3066
- top: calc(16px + env(safe-area-inset-top, 0px));
3067
- left: calc(16px + env(safe-area-inset-left, 0px));
3068
- right: calc(120px + env(safe-area-inset-right, 0px));
3069
- z-index: 2000;
3070
- }
3071
- }
3072
-
3073
- /* Mobile Portrait - Optimized vertical layout */
3074
- @media screen and (max-width: 767px) and (orientation: portrait) {
3075
-
3076
3181
  .uvf-progress-section {
3077
3182
  margin-bottom: 16px;
3078
3183
  }
3079
3184
 
3080
- /* Mobile-optimized controls layout */
3185
+ /* Mobile-first responsive controls layout */
3081
3186
  .uvf-controls-row {
3082
- display: flex;
3187
+ gap: 8px;
3188
+ flex-wrap: nowrap;
3083
3189
  align-items: center;
3084
3190
  justify-content: space-between;
3085
- width: 100%;
3086
- gap: 12px;
3087
- flex-wrap: nowrap;
3088
3191
  position: relative;
3089
- min-height: 52px;
3090
- }
3091
-
3092
- /* Ensure controls are always visible */
3093
- .uvf-controls-row > * {
3094
- flex-shrink: 0;
3095
- display: flex;
3096
- align-items: center;
3097
- }
3098
-
3099
- /* Control groups with proper flex behavior */
3100
- .uvf-left-controls {
3101
- display: flex;
3102
- align-items: center;
3103
- gap: 8px;
3104
- flex: 0 0 auto;
3105
- }
3106
-
3107
- .uvf-center-controls {
3108
- display: flex;
3109
- align-items: center;
3110
- gap: 8px;
3111
- flex: 1 1 auto;
3112
- justify-content: center;
3113
- min-width: 0;
3114
- }
3115
-
3116
- .uvf-right-controls {
3117
- display: flex !important;
3118
- align-items: center;
3119
- gap: 8px;
3120
- flex: 0 0 auto;
3192
+ width: 100%;
3121
3193
  }
3122
3194
 
3123
3195
  /* Left side controls group */
@@ -3245,68 +3317,26 @@ export class WebPlayer extends BasePlayer {
3245
3317
  display: none !important;
3246
3318
  }
3247
3319
 
3248
- /* Enhanced mobile settings menu */
3320
+ /* Settings menu - hidden by default, accessible via menu */
3249
3321
  .uvf-settings-menu {
3250
- position: fixed !important;
3251
- bottom: calc(80px + env(safe-area-inset-bottom, 0px));
3252
- right: calc(16px + env(safe-area-inset-right, 0px));
3253
- min-width: 200px;
3254
- max-width: 280px;
3255
- max-height: 60vh;
3256
- background: rgba(0,0,0,0.95);
3257
- backdrop-filter: blur(20px);
3258
- -webkit-backdrop-filter: blur(20px);
3259
- border: 1px solid rgba(255,255,255,0.2);
3260
- border-radius: 12px;
3261
- box-shadow: 0 10px 40px rgba(0,0,0,0.3);
3262
- z-index: 3000;
3263
- overflow: hidden;
3322
+ min-width: 160px;
3323
+ bottom: 60px;
3324
+ right: 12px;
3264
3325
  font-size: 14px;
3265
- opacity: 0;
3266
- transform: translateY(10px) scale(0.95);
3267
- transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
3268
- pointer-events: none;
3269
- }
3270
-
3271
- .uvf-settings-menu.active {
3272
- opacity: 1;
3273
- transform: translateY(0) scale(1);
3274
- pointer-events: auto;
3326
+ max-height: 50vh;
3275
3327
  }
3276
3328
 
3277
- /* Touch-optimized settings options */
3278
3329
  .uvf-settings-option {
3279
- padding: 16px 20px;
3280
- font-size: 16px;
3281
- min-height: 56px;
3330
+ padding: 12px 16px;
3331
+ font-size: 14px;
3332
+ min-height: 44px;
3282
3333
  display: flex;
3283
3334
  align-items: center;
3284
- cursor: pointer;
3285
- transition: all 0.2s ease;
3286
- border: none;
3287
- background: transparent;
3288
- color: #fff;
3289
- width: 100%;
3290
- text-align: left;
3291
3335
  }
3292
3336
 
3293
- .uvf-settings-option:hover,
3294
- .uvf-settings-option:focus {
3337
+ .uvf-settings-option:hover {
3295
3338
  background: rgba(255,255,255,0.15);
3296
- }
3297
-
3298
- .uvf-settings-option.active {
3299
- background: rgba(255,77,79,0.2);
3300
- color: #ff4d4f;
3301
- }
3302
-
3303
- /* Settings groups with proper spacing */
3304
- .uvf-settings-group {
3305
- border-bottom: 1px solid rgba(255,255,255,0.1);
3306
- }
3307
-
3308
- .uvf-settings-group:last-child {
3309
- border-bottom: none;
3339
+ padding-left: 20px;
3310
3340
  }
3311
3341
 
3312
3342
  /* Simplified settings - hide complex options */
@@ -3447,46 +3477,11 @@ export class WebPlayer extends BasePlayer {
3447
3477
  display: block;
3448
3478
  }
3449
3479
 
3450
- /* Ensure settings button is always visible and functional */
3451
- #uvf-settings-btn {
3452
- display: flex !important;
3453
- align-items: center;
3454
- justify-content: center;
3455
- width: 44px;
3456
- height: 44px;
3457
- min-width: 44px;
3458
- min-height: 44px;
3459
- background: rgba(255,255,255,0.15);
3460
- backdrop-filter: blur(8px);
3461
- border: 1px solid rgba(255,255,255,0.2);
3462
- border-radius: 22px;
3463
- transition: all 0.2s ease;
3464
- }
3465
-
3466
- #uvf-settings-btn:hover {
3467
- background: rgba(255,255,255,0.25);
3468
- transform: scale(1.05);
3469
- }
3470
-
3471
- #uvf-settings-btn svg {
3472
- width: 20px;
3473
- height: 20px;
3474
- fill: #fff;
3475
- }
3476
-
3477
3480
  /* Essential controls in right section - Settings, PiP, and Fullscreen only */
3478
3481
  .uvf-right-controls > *:not(#uvf-settings-btn):not(#uvf-fullscreen-btn):not(#uvf-pip-btn) {
3479
3482
  display: none;
3480
3483
  }
3481
3484
 
3482
- /* Make sure right controls are properly spaced */
3483
- .uvf-right-controls {
3484
- display: flex;
3485
- align-items: center;
3486
- gap: 8px;
3487
- flex-shrink: 0;
3488
- }
3489
-
3490
3485
  /* Hide skip buttons on small mobile devices to save space */
3491
3486
  @media screen and (max-width: 480px) {
3492
3487
  #uvf-skip-back,