unified-video-framework 1.4.446 → 1.4.448
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/interfaces.d.ts +14 -0
- package/packages/core/dist/interfaces.d.ts.map +1 -1
- package/packages/core/dist/version.d.ts +1 -1
- package/packages/core/dist/version.js +1 -1
- package/packages/core/src/interfaces.ts +24 -0
- package/packages/core/src/version.ts +1 -1
- package/packages/web/dist/WebPlayer.d.ts +364 -0
- package/packages/web/dist/WebPlayer.d.ts.map +1 -1
- package/packages/web/dist/WebPlayer.js +347 -7
- package/packages/web/dist/WebPlayer.js.map +1 -1
- package/packages/web/dist/chapters/ChapterManager.js +3 -3
- package/packages/web/dist/chapters/SkipButtonController.js +1 -1
- package/packages/web/dist/chapters/index.js +7 -7
- package/packages/web/dist/index.js +4 -4
- package/packages/web/dist/paywall/PaywallController.js +1 -1
- package/packages/web/dist/react/EPG.js +6 -6
- package/packages/web/dist/react/WebPlayerView.d.ts +399 -0
- package/packages/web/dist/react/WebPlayerView.d.ts.map +1 -1
- package/packages/web/dist/react/WebPlayerView.js +19 -6
- package/packages/web/dist/react/WebPlayerView.js.map +1 -1
- package/packages/web/dist/react/WebPlayerViewWithEPG.js +2 -2
- package/packages/web/dist/react/components/ChapterProgress.js +1 -1
- package/packages/web/dist/react/components/EPGOverlay-improved-positioning.js +5 -5
- package/packages/web/dist/react/components/EPGOverlay.js +5 -5
- package/packages/web/dist/react/components/EPGProgramDetails.js +1 -1
- package/packages/web/dist/react/components/EPGProgramGrid.js +1 -1
- package/packages/web/dist/react/components/EPGTimelineHeader.js +1 -1
- package/packages/web/dist/react/components/SkipButton.js +1 -1
- package/packages/web/dist/react/examples/google-ads-example.js +1 -1
- package/packages/web/dist/react/types/ThumbnailPreviewTypes.d.ts +26 -0
- package/packages/web/dist/react/types/ThumbnailPreviewTypes.d.ts.map +1 -0
- package/packages/web/dist/react/types/ThumbnailPreviewTypes.js +2 -0
- package/packages/web/dist/react/types/ThumbnailPreviewTypes.js.map +1 -0
- package/packages/web/dist/test/epg-test.js +1 -1
- package/packages/web/src/WebPlayer.ts +432 -4
- package/packages/web/src/react/WebPlayerView.tsx +21 -2
- package/packages/web/src/react/types/ThumbnailPreviewTypes.ts +62 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { BasePlayer } from
|
|
2
|
-
import { ChapterManager as CoreChapterManager } from
|
|
3
|
-
import { ChapterManager } from
|
|
4
|
-
import YouTubeExtractor from
|
|
5
|
-
import { DRMManager, DRMErrorHandler } from
|
|
1
|
+
import { BasePlayer } from '../../core/dist/BasePlayer.js';
|
|
2
|
+
import { ChapterManager as CoreChapterManager } from '../../core/dist/index.js';
|
|
3
|
+
import { ChapterManager } from './chapters/ChapterManager.js';
|
|
4
|
+
import YouTubeExtractor from './utils/YouTubeExtractor.js';
|
|
5
|
+
import { DRMManager, DRMErrorHandler } from './drm/index.js';
|
|
6
6
|
export class WebPlayer extends BasePlayer {
|
|
7
7
|
constructor() {
|
|
8
8
|
super(...arguments);
|
|
@@ -112,6 +112,11 @@ export class WebPlayer extends BasePlayer {
|
|
|
112
112
|
this.MAX_HLS_ERROR_RETRIES = 3;
|
|
113
113
|
this.lastDuration = 0;
|
|
114
114
|
this.isDetectedAsLive = false;
|
|
115
|
+
this.thumbnailPreviewConfig = null;
|
|
116
|
+
this.thumbnailEntries = [];
|
|
117
|
+
this.preloadedThumbnails = new Map();
|
|
118
|
+
this.currentThumbnailUrl = null;
|
|
119
|
+
this.thumbnailPreviewEnabled = false;
|
|
115
120
|
this.autoplayAttempted = false;
|
|
116
121
|
this.youtubePlayer = null;
|
|
117
122
|
this.youtubePlayerReady = false;
|
|
@@ -134,6 +139,169 @@ export class WebPlayer extends BasePlayer {
|
|
|
134
139
|
console.warn(`[WebPlayer] ${message}`, ...args);
|
|
135
140
|
}
|
|
136
141
|
}
|
|
142
|
+
initializeThumbnailPreview(config) {
|
|
143
|
+
if (!config || !config.generationImage) {
|
|
144
|
+
this.thumbnailPreviewEnabled = false;
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
this.thumbnailPreviewConfig = config;
|
|
148
|
+
this.thumbnailPreviewEnabled = config.enabled !== false;
|
|
149
|
+
this.thumbnailEntries = this.transformThumbnailData(config.generationImage);
|
|
150
|
+
this.debugLog('Thumbnail preview initialized:', {
|
|
151
|
+
enabled: this.thumbnailPreviewEnabled,
|
|
152
|
+
entries: this.thumbnailEntries.length
|
|
153
|
+
});
|
|
154
|
+
if (config.style) {
|
|
155
|
+
this.applyThumbnailStyles(config.style);
|
|
156
|
+
}
|
|
157
|
+
if (config.preloadImages !== false && this.thumbnailEntries.length > 0) {
|
|
158
|
+
this.preloadThumbnailImages();
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
transformThumbnailData(generationImage) {
|
|
162
|
+
const entries = [];
|
|
163
|
+
for (const [url, timeRange] of Object.entries(generationImage)) {
|
|
164
|
+
const parts = timeRange.split('-');
|
|
165
|
+
if (parts.length === 2) {
|
|
166
|
+
const startTime = parseFloat(parts[0]);
|
|
167
|
+
const endTime = parseFloat(parts[1]);
|
|
168
|
+
if (!isNaN(startTime) && !isNaN(endTime)) {
|
|
169
|
+
entries.push({ url, startTime, endTime });
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
entries.sort((a, b) => a.startTime - b.startTime);
|
|
174
|
+
return entries;
|
|
175
|
+
}
|
|
176
|
+
findThumbnailForTime(time) {
|
|
177
|
+
if (this.thumbnailEntries.length === 0)
|
|
178
|
+
return null;
|
|
179
|
+
let left = 0;
|
|
180
|
+
let right = this.thumbnailEntries.length - 1;
|
|
181
|
+
let result = null;
|
|
182
|
+
while (left <= right) {
|
|
183
|
+
const mid = Math.floor((left + right) / 2);
|
|
184
|
+
const entry = this.thumbnailEntries[mid];
|
|
185
|
+
if (time >= entry.startTime && time < entry.endTime) {
|
|
186
|
+
return entry;
|
|
187
|
+
}
|
|
188
|
+
else if (time < entry.startTime) {
|
|
189
|
+
right = mid - 1;
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
left = mid + 1;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if (left > 0 && left <= this.thumbnailEntries.length) {
|
|
196
|
+
const prevEntry = this.thumbnailEntries[left - 1];
|
|
197
|
+
if (time >= prevEntry.startTime && time < prevEntry.endTime) {
|
|
198
|
+
return prevEntry;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return result;
|
|
202
|
+
}
|
|
203
|
+
preloadThumbnailImages() {
|
|
204
|
+
this.debugLog('Preloading', this.thumbnailEntries.length, 'thumbnail images');
|
|
205
|
+
for (const entry of this.thumbnailEntries) {
|
|
206
|
+
if (this.preloadedThumbnails.has(entry.url))
|
|
207
|
+
continue;
|
|
208
|
+
const img = new Image();
|
|
209
|
+
img.onload = () => {
|
|
210
|
+
this.preloadedThumbnails.set(entry.url, img);
|
|
211
|
+
this.debugLog('Preloaded thumbnail:', entry.url);
|
|
212
|
+
};
|
|
213
|
+
img.onerror = () => {
|
|
214
|
+
this.debugWarn('Failed to preload thumbnail:', entry.url);
|
|
215
|
+
};
|
|
216
|
+
img.src = entry.url;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
applyThumbnailStyles(style) {
|
|
220
|
+
if (!style)
|
|
221
|
+
return;
|
|
222
|
+
const wrapper = document.getElementById('uvf-thumbnail-preview');
|
|
223
|
+
const imageWrapper = wrapper?.querySelector('.uvf-thumbnail-preview-image-wrapper');
|
|
224
|
+
if (imageWrapper) {
|
|
225
|
+
if (style.width) {
|
|
226
|
+
imageWrapper.style.width = `${style.width}px`;
|
|
227
|
+
}
|
|
228
|
+
if (style.height) {
|
|
229
|
+
imageWrapper.style.height = `${style.height}px`;
|
|
230
|
+
}
|
|
231
|
+
if (style.borderRadius !== undefined) {
|
|
232
|
+
imageWrapper.style.borderRadius = `${style.borderRadius}px`;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
updateThumbnailPreview(e) {
|
|
237
|
+
if (!this.thumbnailPreviewEnabled || this.thumbnailEntries.length === 0) {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
const progressBar = document.getElementById('uvf-progress-bar');
|
|
241
|
+
const thumbnailPreview = document.getElementById('uvf-thumbnail-preview');
|
|
242
|
+
const thumbnailImage = document.getElementById('uvf-thumbnail-image');
|
|
243
|
+
const thumbnailTime = document.getElementById('uvf-thumbnail-time');
|
|
244
|
+
if (!progressBar || !thumbnailPreview || !thumbnailImage || !this.video) {
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
const rect = progressBar.getBoundingClientRect();
|
|
248
|
+
const x = e.clientX - rect.left;
|
|
249
|
+
const percent = Math.max(0, Math.min(1, x / rect.width));
|
|
250
|
+
const time = percent * this.video.duration;
|
|
251
|
+
const entry = this.findThumbnailForTime(time);
|
|
252
|
+
if (entry) {
|
|
253
|
+
thumbnailPreview.classList.add('visible');
|
|
254
|
+
const thumbnailWidth = 160;
|
|
255
|
+
const halfWidth = thumbnailWidth / 2;
|
|
256
|
+
const minX = halfWidth;
|
|
257
|
+
const maxX = rect.width - halfWidth;
|
|
258
|
+
const clampedX = Math.max(minX, Math.min(maxX, x));
|
|
259
|
+
thumbnailPreview.style.left = `${clampedX}px`;
|
|
260
|
+
if (this.currentThumbnailUrl !== entry.url) {
|
|
261
|
+
this.currentThumbnailUrl = entry.url;
|
|
262
|
+
thumbnailImage.classList.remove('loaded');
|
|
263
|
+
const preloaded = this.preloadedThumbnails.get(entry.url);
|
|
264
|
+
if (preloaded) {
|
|
265
|
+
thumbnailImage.src = preloaded.src;
|
|
266
|
+
thumbnailImage.classList.add('loaded');
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
thumbnailImage.onload = () => {
|
|
270
|
+
thumbnailImage.classList.add('loaded');
|
|
271
|
+
};
|
|
272
|
+
thumbnailImage.src = entry.url;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
if (thumbnailTime && this.thumbnailPreviewConfig?.showTimeInThumbnail !== false) {
|
|
276
|
+
thumbnailTime.textContent = this.formatTime(time);
|
|
277
|
+
thumbnailTime.style.display = 'block';
|
|
278
|
+
}
|
|
279
|
+
else if (thumbnailTime) {
|
|
280
|
+
thumbnailTime.style.display = 'none';
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
this.hideThumbnailPreview();
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
hideThumbnailPreview() {
|
|
288
|
+
const thumbnailPreview = document.getElementById('uvf-thumbnail-preview');
|
|
289
|
+
if (thumbnailPreview) {
|
|
290
|
+
thumbnailPreview.classList.remove('visible');
|
|
291
|
+
}
|
|
292
|
+
this.currentThumbnailUrl = null;
|
|
293
|
+
}
|
|
294
|
+
setThumbnailPreview(config) {
|
|
295
|
+
if (!config) {
|
|
296
|
+
this.thumbnailPreviewEnabled = false;
|
|
297
|
+
this.thumbnailPreviewConfig = null;
|
|
298
|
+
this.thumbnailEntries = [];
|
|
299
|
+
this.preloadedThumbnails.clear();
|
|
300
|
+
this.hideThumbnailPreview();
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
this.initializeThumbnailPreview(config);
|
|
304
|
+
}
|
|
137
305
|
async initialize(container, config) {
|
|
138
306
|
console.log('WebPlayer.initialize called with config:', config);
|
|
139
307
|
if (config) {
|
|
@@ -196,6 +364,10 @@ export class WebPlayer extends BasePlayer {
|
|
|
196
364
|
console.log('YouTube native controls config found:', config.youtubeNativeControls);
|
|
197
365
|
this.youtubeNativeControls = config.youtubeNativeControls;
|
|
198
366
|
}
|
|
367
|
+
if (config && config.thumbnailPreview) {
|
|
368
|
+
console.log('Thumbnail preview config found:', config.thumbnailPreview);
|
|
369
|
+
this.initializeThumbnailPreview(config.thumbnailPreview);
|
|
370
|
+
}
|
|
199
371
|
await super.initialize(container, config);
|
|
200
372
|
}
|
|
201
373
|
async setupPlayer() {
|
|
@@ -4321,7 +4493,37 @@ export class WebPlayer extends BasePlayer {
|
|
|
4321
4493
|
top: 2px; /* Center on the 4px hover progress bar (2px from top) */
|
|
4322
4494
|
transform: translate(-50%, -50%) scale(1);
|
|
4323
4495
|
}
|
|
4324
|
-
|
|
4496
|
+
|
|
4497
|
+
/* Prevent text selection during seekbar drag */
|
|
4498
|
+
.uvf-player-wrapper.seeking {
|
|
4499
|
+
user-select: none;
|
|
4500
|
+
-webkit-user-select: none;
|
|
4501
|
+
-moz-user-select: none;
|
|
4502
|
+
-ms-user-select: none;
|
|
4503
|
+
}
|
|
4504
|
+
|
|
4505
|
+
/* Maintain expanded seekbar state during drag (same as hover) */
|
|
4506
|
+
.uvf-progress-bar-wrapper.dragging .uvf-progress-bar {
|
|
4507
|
+
height: 4px;
|
|
4508
|
+
background: rgba(255, 255, 255, 0.2);
|
|
4509
|
+
border-radius: 6px;
|
|
4510
|
+
transform: scaleY(1.1);
|
|
4511
|
+
}
|
|
4512
|
+
|
|
4513
|
+
.uvf-progress-bar-wrapper.dragging .uvf-progress-handle {
|
|
4514
|
+
opacity: 1;
|
|
4515
|
+
top: 2px;
|
|
4516
|
+
transform: translate(-50%, -50%) scale(1);
|
|
4517
|
+
}
|
|
4518
|
+
|
|
4519
|
+
.uvf-progress-bar-wrapper.dragging .uvf-progress-buffered {
|
|
4520
|
+
border-radius: 6px;
|
|
4521
|
+
}
|
|
4522
|
+
|
|
4523
|
+
.uvf-progress-bar-wrapper.dragging .uvf-progress-filled {
|
|
4524
|
+
border-radius: 6px;
|
|
4525
|
+
}
|
|
4526
|
+
|
|
4325
4527
|
.uvf-progress-handle:hover {
|
|
4326
4528
|
transform: translate(-50%, -50%) scale(1.2);
|
|
4327
4529
|
box-shadow: 0 3px 12px rgba(0, 0, 0, 0.4);
|
|
@@ -4376,7 +4578,122 @@ export class WebPlayer extends BasePlayer {
|
|
|
4376
4578
|
opacity: 1;
|
|
4377
4579
|
transform: translateX(-50%) translateY(0);
|
|
4378
4580
|
}
|
|
4379
|
-
|
|
4581
|
+
|
|
4582
|
+
/* Thumbnail Preview */
|
|
4583
|
+
.uvf-thumbnail-preview {
|
|
4584
|
+
position: absolute;
|
|
4585
|
+
bottom: 100%;
|
|
4586
|
+
left: 0;
|
|
4587
|
+
margin-bottom: 12px;
|
|
4588
|
+
display: flex;
|
|
4589
|
+
flex-direction: column;
|
|
4590
|
+
align-items: center;
|
|
4591
|
+
pointer-events: none;
|
|
4592
|
+
z-index: 25;
|
|
4593
|
+
opacity: 0;
|
|
4594
|
+
transform: translateX(-50%) translateY(8px);
|
|
4595
|
+
transition: opacity 0.15s ease, transform 0.15s ease;
|
|
4596
|
+
}
|
|
4597
|
+
|
|
4598
|
+
.uvf-thumbnail-preview.visible {
|
|
4599
|
+
opacity: 1;
|
|
4600
|
+
transform: translateX(-50%) translateY(0);
|
|
4601
|
+
}
|
|
4602
|
+
|
|
4603
|
+
.uvf-thumbnail-preview-container {
|
|
4604
|
+
position: relative;
|
|
4605
|
+
background: rgba(0, 0, 0, 0.9);
|
|
4606
|
+
border-radius: 8px;
|
|
4607
|
+
padding: 4px;
|
|
4608
|
+
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.1);
|
|
4609
|
+
backdrop-filter: blur(12px);
|
|
4610
|
+
-webkit-backdrop-filter: blur(12px);
|
|
4611
|
+
}
|
|
4612
|
+
|
|
4613
|
+
.uvf-thumbnail-preview-image-wrapper {
|
|
4614
|
+
position: relative;
|
|
4615
|
+
width: 160px;
|
|
4616
|
+
height: 90px;
|
|
4617
|
+
border-radius: 6px;
|
|
4618
|
+
overflow: hidden;
|
|
4619
|
+
background: rgba(30, 30, 30, 0.95);
|
|
4620
|
+
}
|
|
4621
|
+
|
|
4622
|
+
.uvf-thumbnail-preview-image {
|
|
4623
|
+
width: 100%;
|
|
4624
|
+
height: 100%;
|
|
4625
|
+
object-fit: cover;
|
|
4626
|
+
display: block;
|
|
4627
|
+
opacity: 0;
|
|
4628
|
+
transition: opacity 0.2s ease;
|
|
4629
|
+
}
|
|
4630
|
+
|
|
4631
|
+
.uvf-thumbnail-preview-image.loaded {
|
|
4632
|
+
opacity: 1;
|
|
4633
|
+
}
|
|
4634
|
+
|
|
4635
|
+
.uvf-thumbnail-preview-loading {
|
|
4636
|
+
position: absolute;
|
|
4637
|
+
top: 50%;
|
|
4638
|
+
left: 50%;
|
|
4639
|
+
transform: translate(-50%, -50%);
|
|
4640
|
+
width: 24px;
|
|
4641
|
+
height: 24px;
|
|
4642
|
+
border: 2px solid rgba(255, 255, 255, 0.2);
|
|
4643
|
+
border-top-color: var(--uvf-accent-1, #ff5722);
|
|
4644
|
+
border-radius: 50%;
|
|
4645
|
+
animation: uvf-spin 0.8s linear infinite;
|
|
4646
|
+
}
|
|
4647
|
+
|
|
4648
|
+
.uvf-thumbnail-preview-image.loaded + .uvf-thumbnail-preview-loading {
|
|
4649
|
+
display: none;
|
|
4650
|
+
}
|
|
4651
|
+
|
|
4652
|
+
.uvf-thumbnail-preview-time {
|
|
4653
|
+
position: absolute;
|
|
4654
|
+
bottom: 6px;
|
|
4655
|
+
left: 50%;
|
|
4656
|
+
transform: translateX(-50%);
|
|
4657
|
+
background: rgba(0, 0, 0, 0.85);
|
|
4658
|
+
color: #fff;
|
|
4659
|
+
font-size: 12px;
|
|
4660
|
+
font-weight: 600;
|
|
4661
|
+
padding: 3px 8px;
|
|
4662
|
+
border-radius: 4px;
|
|
4663
|
+
white-space: nowrap;
|
|
4664
|
+
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
|
|
4665
|
+
backdrop-filter: blur(4px);
|
|
4666
|
+
-webkit-backdrop-filter: blur(4px);
|
|
4667
|
+
}
|
|
4668
|
+
|
|
4669
|
+
.uvf-thumbnail-preview-arrow {
|
|
4670
|
+
width: 0;
|
|
4671
|
+
height: 0;
|
|
4672
|
+
border-left: 8px solid transparent;
|
|
4673
|
+
border-right: 8px solid transparent;
|
|
4674
|
+
border-top: 8px solid rgba(0, 0, 0, 0.9);
|
|
4675
|
+
margin-top: -1px;
|
|
4676
|
+
}
|
|
4677
|
+
|
|
4678
|
+
/* Hide regular time tooltip when thumbnail preview is visible */
|
|
4679
|
+
.uvf-thumbnail-preview.visible ~ .uvf-time-tooltip {
|
|
4680
|
+
opacity: 0 !important;
|
|
4681
|
+
pointer-events: none;
|
|
4682
|
+
}
|
|
4683
|
+
|
|
4684
|
+
/* Responsive thumbnail sizes */
|
|
4685
|
+
@media (max-width: 768px) {
|
|
4686
|
+
.uvf-thumbnail-preview-image-wrapper {
|
|
4687
|
+
width: 120px;
|
|
4688
|
+
height: 68px;
|
|
4689
|
+
}
|
|
4690
|
+
|
|
4691
|
+
.uvf-thumbnail-preview-time {
|
|
4692
|
+
font-size: 11px;
|
|
4693
|
+
padding: 2px 6px;
|
|
4694
|
+
}
|
|
4695
|
+
}
|
|
4696
|
+
|
|
4380
4697
|
/* Chapter Markers */
|
|
4381
4698
|
.uvf-chapter-marker {
|
|
4382
4699
|
position: absolute;
|
|
@@ -7390,6 +7707,16 @@ export class WebPlayer extends BasePlayer {
|
|
|
7390
7707
|
<div class="uvf-progress-filled" id="uvf-progress-filled"></div>
|
|
7391
7708
|
<div class="uvf-progress-handle" id="uvf-progress-handle"></div>
|
|
7392
7709
|
</div>
|
|
7710
|
+
<div class="uvf-thumbnail-preview" id="uvf-thumbnail-preview">
|
|
7711
|
+
<div class="uvf-thumbnail-preview-container">
|
|
7712
|
+
<div class="uvf-thumbnail-preview-image-wrapper">
|
|
7713
|
+
<img class="uvf-thumbnail-preview-image" id="uvf-thumbnail-image" alt="Preview" />
|
|
7714
|
+
<div class="uvf-thumbnail-preview-loading"></div>
|
|
7715
|
+
</div>
|
|
7716
|
+
<div class="uvf-thumbnail-preview-time" id="uvf-thumbnail-time">00:00</div>
|
|
7717
|
+
</div>
|
|
7718
|
+
<div class="uvf-thumbnail-preview-arrow"></div>
|
|
7719
|
+
</div>
|
|
7393
7720
|
<div class="uvf-time-tooltip" id="uvf-time-tooltip">00:00</div>
|
|
7394
7721
|
`;
|
|
7395
7722
|
progressSection.appendChild(progressBar);
|
|
@@ -7708,6 +8035,8 @@ export class WebPlayer extends BasePlayer {
|
|
|
7708
8035
|
progressBar?.addEventListener('mousedown', (e) => {
|
|
7709
8036
|
this.isDragging = true;
|
|
7710
8037
|
this.showTimeTooltip = true;
|
|
8038
|
+
progressBar.classList.add('dragging');
|
|
8039
|
+
this.playerWrapper?.classList.add('seeking');
|
|
7711
8040
|
this.seekToPosition(e);
|
|
7712
8041
|
this.updateTimeTooltip(e);
|
|
7713
8042
|
});
|
|
@@ -7718,16 +8047,20 @@ export class WebPlayer extends BasePlayer {
|
|
|
7718
8047
|
if (!this.isDragging) {
|
|
7719
8048
|
this.showTimeTooltip = false;
|
|
7720
8049
|
this.hideTimeTooltip();
|
|
8050
|
+
this.hideThumbnailPreview();
|
|
7721
8051
|
}
|
|
7722
8052
|
});
|
|
7723
8053
|
progressBar?.addEventListener('mousemove', (e) => {
|
|
7724
8054
|
if (this.showTimeTooltip) {
|
|
7725
8055
|
this.updateTimeTooltip(e);
|
|
8056
|
+
this.updateThumbnailPreview(e);
|
|
7726
8057
|
}
|
|
7727
8058
|
});
|
|
7728
8059
|
progressBar?.addEventListener('touchstart', (e) => {
|
|
7729
8060
|
e.preventDefault();
|
|
7730
8061
|
this.isDragging = true;
|
|
8062
|
+
progressBar.classList.add('dragging');
|
|
8063
|
+
this.playerWrapper?.classList.add('seeking');
|
|
7731
8064
|
const touch = e.touches[0];
|
|
7732
8065
|
const mouseEvent = new MouseEvent('mousedown', {
|
|
7733
8066
|
clientX: touch.clientX,
|
|
@@ -7742,6 +8075,7 @@ export class WebPlayer extends BasePlayer {
|
|
|
7742
8075
|
if (this.isDragging && progressBar) {
|
|
7743
8076
|
this.seekToPosition(e);
|
|
7744
8077
|
this.updateTimeTooltip(e);
|
|
8078
|
+
this.updateThumbnailPreview(e);
|
|
7745
8079
|
}
|
|
7746
8080
|
});
|
|
7747
8081
|
document.addEventListener('touchmove', (e) => {
|
|
@@ -7766,21 +8100,27 @@ export class WebPlayer extends BasePlayer {
|
|
|
7766
8100
|
}
|
|
7767
8101
|
if (this.isDragging) {
|
|
7768
8102
|
this.isDragging = false;
|
|
8103
|
+
progressBar?.classList.remove('dragging');
|
|
8104
|
+
this.playerWrapper?.classList.remove('seeking');
|
|
7769
8105
|
const handle = document.getElementById('uvf-progress-handle');
|
|
7770
8106
|
handle?.classList.remove('dragging');
|
|
7771
8107
|
if (progressBar && !progressBar.matches(':hover')) {
|
|
7772
8108
|
this.showTimeTooltip = false;
|
|
7773
8109
|
this.hideTimeTooltip();
|
|
8110
|
+
this.hideThumbnailPreview();
|
|
7774
8111
|
}
|
|
7775
8112
|
}
|
|
7776
8113
|
});
|
|
7777
8114
|
document.addEventListener('touchend', () => {
|
|
7778
8115
|
if (this.isDragging) {
|
|
7779
8116
|
this.isDragging = false;
|
|
8117
|
+
progressBar?.classList.remove('dragging');
|
|
8118
|
+
this.playerWrapper?.classList.remove('seeking');
|
|
7780
8119
|
const handle = document.getElementById('uvf-progress-handle');
|
|
7781
8120
|
handle?.classList.remove('dragging');
|
|
7782
8121
|
this.showTimeTooltip = false;
|
|
7783
8122
|
this.hideTimeTooltip();
|
|
8123
|
+
this.hideThumbnailPreview();
|
|
7784
8124
|
}
|
|
7785
8125
|
});
|
|
7786
8126
|
this.video.addEventListener('timeupdate', () => {
|