myetv-player 1.1.3 → 1.1.5
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/README.md +14 -0
- package/css/myetv-player.css +65 -0
- package/css/myetv-player.min.css +1 -1
- package/dist/myetv-player.js +229 -99
- package/dist/myetv-player.min.js +167 -72
- package/package.json +3 -1
- package/plugins/vimeo/myetv-player-vimeo.js +223 -0
- package/plugins/youtube/myetv-player-youtube-plugin.js +484 -244
- package/scss/_controls.scss +21 -0
- package/scss/_menus.scss +49 -0
- package/src/controls.js +212 -83
- package/src/core.js +17 -16
|
@@ -271,42 +271,46 @@
|
|
|
271
271
|
* Set auto caption language on player initialization
|
|
272
272
|
*/
|
|
273
273
|
setAutoCaptionLanguage() {
|
|
274
|
-
if (!this.options.autoCaptionLanguage || !this.ytPlayer)
|
|
275
|
-
return;
|
|
276
|
-
}
|
|
274
|
+
if (!this.options.autoCaptionLanguage || !this.ytPlayer) return;
|
|
277
275
|
|
|
278
276
|
try {
|
|
279
277
|
if (this.api.player.options.debug) {
|
|
280
|
-
console.log('
|
|
278
|
+
console.log('YT Plugin: Setting auto caption language to', this.options.autoCaptionLanguage);
|
|
281
279
|
}
|
|
282
280
|
|
|
283
281
|
this.ytPlayer.setOption('captions', 'reload', true);
|
|
284
282
|
this.ytPlayer.loadModule('captions');
|
|
285
|
-
|
|
286
283
|
this.ytPlayer.setOption('captions', 'track', {
|
|
287
|
-
|
|
284
|
+
translationLanguage: { languageCode: this.options.autoCaptionLanguage }
|
|
288
285
|
});
|
|
289
286
|
|
|
290
287
|
this.captionsEnabled = true;
|
|
288
|
+
this.currentTranslation = this.options.autoCaptionLanguage;
|
|
291
289
|
|
|
292
290
|
const subtitlesBtn = this.api.container.querySelector('.subtitles-btn');
|
|
293
291
|
if (subtitlesBtn) {
|
|
294
292
|
subtitlesBtn.classList.add('active');
|
|
295
293
|
}
|
|
296
294
|
|
|
295
|
+
// update menu selection after a short delay
|
|
296
|
+
setTimeout(() => {
|
|
297
|
+
this.updateMenuSelection(`translate-${this.options.autoCaptionLanguage}`);
|
|
298
|
+
}, 500);
|
|
299
|
+
|
|
297
300
|
if (this.api.player.options.debug) {
|
|
298
|
-
console.log('
|
|
301
|
+
console.log('YT Plugin: Auto caption language set successfully');
|
|
299
302
|
}
|
|
300
|
-
|
|
301
303
|
} catch (error) {
|
|
302
304
|
if (this.api.player.options.debug) {
|
|
303
|
-
console.error('
|
|
305
|
+
console.error('YT Plugin: Error setting auto caption language', error);
|
|
304
306
|
}
|
|
305
307
|
}
|
|
306
308
|
}
|
|
307
309
|
|
|
310
|
+
/**
|
|
311
|
+
* Handle responsive layout for mobile settings
|
|
312
|
+
*/
|
|
308
313
|
handleResponsiveLayout() {
|
|
309
|
-
|
|
310
314
|
const containerWidth = this.api.container.offsetWidth;
|
|
311
315
|
const pipBtn = this.api.container.querySelector('.pip-btn');
|
|
312
316
|
const subtitlesBtn = this.api.container.querySelector('.subtitles-btn');
|
|
@@ -319,11 +323,66 @@
|
|
|
319
323
|
|
|
320
324
|
// Breakpoint at 600px
|
|
321
325
|
if (containerWidth < 600) {
|
|
326
|
+
// Add max-height and scroll to settings menu on mobile
|
|
327
|
+
if (settingsMenu) {
|
|
328
|
+
const playerHeight = this.api.container.offsetHeight;
|
|
329
|
+
const maxMenuHeight = playerHeight - 100; // Leave 100px margin from top/bottom
|
|
330
|
+
|
|
331
|
+
settingsMenu.style.maxHeight = `${maxMenuHeight}px`;
|
|
332
|
+
settingsMenu.style.overflowY = 'auto';
|
|
333
|
+
settingsMenu.style.overflowX = 'hidden';
|
|
334
|
+
|
|
335
|
+
// Add scrollbar styling
|
|
336
|
+
if (!document.getElementById('yt-settings-scrollbar-style')) {
|
|
337
|
+
const scrollbarStyle = document.createElement('style');
|
|
338
|
+
scrollbarStyle.id = 'yt-settings-scrollbar-style';
|
|
339
|
+
scrollbarStyle.textContent = `
|
|
340
|
+
.settings-menu::-webkit-scrollbar {
|
|
341
|
+
width: 6px;
|
|
342
|
+
}
|
|
343
|
+
.settings-menu::-webkit-scrollbar-track {
|
|
344
|
+
background: rgba(255,255,255,0.05);
|
|
345
|
+
border-radius: 3px;
|
|
346
|
+
}
|
|
347
|
+
.settings-menu::-webkit-scrollbar-thumb {
|
|
348
|
+
background: rgba(255,255,255,0.3);
|
|
349
|
+
border-radius: 3px;
|
|
350
|
+
}
|
|
351
|
+
.settings-menu::-webkit-scrollbar-thumb:hover {
|
|
352
|
+
background: rgba(255,255,255,0.5);
|
|
353
|
+
}
|
|
354
|
+
`;
|
|
355
|
+
document.head.appendChild(scrollbarStyle);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Firefox scrollbar
|
|
359
|
+
settingsMenu.style.scrollbarWidth = 'thin';
|
|
360
|
+
settingsMenu.style.scrollbarColor = 'rgba(255,255,255,0.3) transparent';
|
|
361
|
+
}
|
|
362
|
+
|
|
322
363
|
// Hide subtitles button
|
|
323
364
|
if (subtitlesBtn) {
|
|
324
365
|
subtitlesBtn.style.display = 'none';
|
|
325
366
|
}
|
|
326
367
|
|
|
368
|
+
// Hide original speed menu option from settings (if exists)
|
|
369
|
+
if (settingsMenu) {
|
|
370
|
+
// Hide old non-expandable speed option
|
|
371
|
+
const originalSpeedOption = settingsMenu.querySelector('[data-action="speed"]');
|
|
372
|
+
if (originalSpeedOption) {
|
|
373
|
+
originalSpeedOption.style.display = 'none';
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// Hide new expandable speed option
|
|
377
|
+
const expandableSpeedWrapper = settingsMenu.querySelector('[data-action="speed-expand"]');
|
|
378
|
+
if (expandableSpeedWrapper) {
|
|
379
|
+
const wrapper = expandableSpeedWrapper.closest('.settings-expandable-wrapper');
|
|
380
|
+
if (wrapper) {
|
|
381
|
+
wrapper.style.display = 'none';
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
327
386
|
// Add subtitles option to settings menu
|
|
328
387
|
if (settingsMenu) {
|
|
329
388
|
let subtitlesWrapper = settingsMenu.querySelector('.yt-subtitles-wrapper');
|
|
@@ -345,121 +404,236 @@
|
|
|
345
404
|
// Create trigger
|
|
346
405
|
const trigger = document.createElement('div');
|
|
347
406
|
trigger.className = 'quality-option';
|
|
407
|
+
trigger.style.fontSize = '10px';
|
|
348
408
|
trigger.textContent = subtitlesText;
|
|
349
409
|
|
|
350
|
-
//
|
|
351
|
-
const
|
|
352
|
-
|
|
353
|
-
|
|
410
|
+
// Add arrow indicator
|
|
411
|
+
const arrow = document.createElement('span');
|
|
412
|
+
arrow.textContent = ' ▼';
|
|
413
|
+
arrow.style.cssText = 'font-size: 8px; transition: transform 0.2s;';
|
|
414
|
+
trigger.appendChild(arrow);
|
|
415
|
+
|
|
416
|
+
// Container for expanded options
|
|
417
|
+
const optionsContainer = document.createElement('div');
|
|
418
|
+
optionsContainer.className = 'yt-subtitles-options';
|
|
419
|
+
optionsContainer.style.cssText = `
|
|
354
420
|
display: none;
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
421
|
+
padding-left: 15px;
|
|
422
|
+
margin-top: 4px;
|
|
423
|
+
`;
|
|
424
|
+
|
|
425
|
+
// Function to rebuild options from main menu
|
|
426
|
+
const rebuildOptions = () => {
|
|
427
|
+
const mainSubtitlesMenu = this.api.container.querySelector('.subtitles-menu');
|
|
428
|
+
if (!mainSubtitlesMenu) return;
|
|
429
|
+
|
|
430
|
+
// Clone all options from main menu
|
|
431
|
+
optionsContainer.innerHTML = '';
|
|
432
|
+
const options = mainSubtitlesMenu.querySelectorAll('.subtitles-option');
|
|
433
|
+
|
|
434
|
+
options.forEach(option => {
|
|
435
|
+
const clonedOption = option.cloneNode(true);
|
|
436
|
+
clonedOption.style.cssText = `
|
|
437
|
+
padding: 6px 12px;
|
|
438
|
+
cursor: pointer;
|
|
439
|
+
color: white;
|
|
440
|
+
font-size: 10px;
|
|
441
|
+
white-space: normal;
|
|
442
|
+
word-wrap: break-word;
|
|
443
|
+
opacity: 0.8;
|
|
444
|
+
transition: opacity 0.2s;
|
|
445
|
+
`;
|
|
446
|
+
|
|
447
|
+
// Highlight selected option
|
|
448
|
+
if (option.classList.contains('selected')) {
|
|
449
|
+
clonedOption.style.opacity = '1';
|
|
450
|
+
clonedOption.style.fontWeight = 'bold';
|
|
381
451
|
}
|
|
382
|
-
|
|
452
|
+
|
|
453
|
+
// Hover effect
|
|
454
|
+
clonedOption.addEventListener('mouseenter', () => {
|
|
455
|
+
clonedOption.style.opacity = '1';
|
|
456
|
+
});
|
|
457
|
+
clonedOption.addEventListener('mouseleave', () => {
|
|
458
|
+
if (!option.classList.contains('selected')) {
|
|
459
|
+
clonedOption.style.opacity = '0.8';
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
// Add click handler
|
|
464
|
+
clonedOption.addEventListener('click', (e) => {
|
|
465
|
+
e.stopPropagation();
|
|
466
|
+
|
|
467
|
+
// Trigger click on original option
|
|
468
|
+
option.click();
|
|
469
|
+
|
|
470
|
+
// Rebuild to update selection
|
|
471
|
+
setTimeout(() => {
|
|
472
|
+
rebuildOptions();
|
|
473
|
+
}, 50);
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
optionsContainer.appendChild(clonedOption);
|
|
477
|
+
});
|
|
383
478
|
};
|
|
384
479
|
|
|
385
|
-
//
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
480
|
+
// Toggle expanded/collapsed state
|
|
481
|
+
let isExpanded = false;
|
|
482
|
+
trigger.addEventListener('click', (e) => {
|
|
483
|
+
e.stopPropagation();
|
|
484
|
+
|
|
485
|
+
isExpanded = !isExpanded;
|
|
486
|
+
|
|
487
|
+
if (isExpanded) {
|
|
488
|
+
rebuildOptions();
|
|
489
|
+
optionsContainer.style.display = 'block';
|
|
490
|
+
arrow.style.transform = 'rotate(180deg)';
|
|
491
|
+
} else {
|
|
492
|
+
optionsContainer.style.display = 'none';
|
|
493
|
+
arrow.style.transform = 'rotate(0deg)';
|
|
494
|
+
}
|
|
394
495
|
});
|
|
395
|
-
submenu.appendChild(offOption);
|
|
396
496
|
|
|
397
|
-
//
|
|
398
|
-
|
|
399
|
-
|
|
497
|
+
// Assemble
|
|
498
|
+
subtitlesWrapper.appendChild(trigger);
|
|
499
|
+
subtitlesWrapper.appendChild(optionsContainer);
|
|
500
|
+
settingsMenu.insertBefore(subtitlesWrapper, settingsMenu.firstChild);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// Add speed option to settings menu
|
|
504
|
+
let speedWrapper = settingsMenu.querySelector('.yt-speed-wrapper');
|
|
505
|
+
|
|
506
|
+
if (!speedWrapper) {
|
|
507
|
+
// Get i18n text - use 'playback_speed' key
|
|
508
|
+
let speedText = 'Playback speed';
|
|
509
|
+
if (this.api.player && this.api.player.t) {
|
|
510
|
+
speedText = this.api.player.t('playback_speed');
|
|
511
|
+
} else if (this.player && this.player.t) {
|
|
512
|
+
speedText = this.player.t('playback_speed');
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
// Create wrapper
|
|
516
|
+
speedWrapper = document.createElement('div');
|
|
517
|
+
speedWrapper.className = 'yt-speed-wrapper';
|
|
518
|
+
speedWrapper.style.cssText = 'position: relative; display: block;';
|
|
519
|
+
|
|
520
|
+
// Create trigger
|
|
521
|
+
const trigger = document.createElement('div');
|
|
522
|
+
trigger.className = 'quality-option';
|
|
523
|
+
trigger.style.fontSize = '10px';
|
|
524
|
+
|
|
525
|
+
// Get current speed
|
|
526
|
+
const getCurrentSpeed = () => {
|
|
527
|
+
if (this.ytPlayer && this.ytPlayer.getPlaybackRate) {
|
|
528
|
+
return this.ytPlayer.getPlaybackRate();
|
|
529
|
+
}
|
|
530
|
+
return 1;
|
|
531
|
+
};
|
|
532
|
+
|
|
533
|
+
trigger.textContent = `${speedText}: ${getCurrentSpeed()}x`;
|
|
534
|
+
|
|
535
|
+
// Add arrow indicator
|
|
536
|
+
const arrow = document.createElement('span');
|
|
537
|
+
arrow.textContent = ' ▼';
|
|
538
|
+
arrow.style.cssText = 'font-size: 8px; transition: transform 0.2s;';
|
|
539
|
+
trigger.appendChild(arrow);
|
|
540
|
+
|
|
541
|
+
// Container for expanded options
|
|
542
|
+
const optionsContainer = document.createElement('div');
|
|
543
|
+
optionsContainer.className = 'yt-speed-options';
|
|
544
|
+
optionsContainer.style.cssText = `
|
|
545
|
+
display: none;
|
|
546
|
+
padding-left: 15px;
|
|
547
|
+
margin-top: 4px;
|
|
548
|
+
`;
|
|
549
|
+
|
|
550
|
+
// Available speeds
|
|
551
|
+
const speeds = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2];
|
|
552
|
+
|
|
553
|
+
// Function to rebuild options
|
|
554
|
+
const rebuildOptions = () => {
|
|
555
|
+
optionsContainer.innerHTML = '';
|
|
556
|
+
const currentSpeed = getCurrentSpeed();
|
|
557
|
+
|
|
558
|
+
speeds.forEach(speed => {
|
|
400
559
|
const option = document.createElement('div');
|
|
401
|
-
option.
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
560
|
+
option.style.cssText = `
|
|
561
|
+
padding: 6px 12px;
|
|
562
|
+
cursor: pointer;
|
|
563
|
+
color: white;
|
|
564
|
+
font-size: 10px;
|
|
565
|
+
white-space: normal;
|
|
566
|
+
word-wrap: break-word;
|
|
567
|
+
opacity: 0.8;
|
|
568
|
+
transition: opacity 0.2s;
|
|
569
|
+
`;
|
|
570
|
+
option.textContent = `${speed}x`;
|
|
571
|
+
|
|
572
|
+
// Highlight selected option
|
|
573
|
+
if (Math.abs(speed - currentSpeed) < 0.01) {
|
|
574
|
+
option.style.opacity = '1';
|
|
575
|
+
option.style.fontWeight = 'bold';
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
// Hover effect
|
|
579
|
+
option.addEventListener('mouseenter', () => {
|
|
580
|
+
option.style.opacity = '1';
|
|
581
|
+
});
|
|
582
|
+
option.addEventListener('mouseleave', () => {
|
|
583
|
+
if (Math.abs(speed - getCurrentSpeed()) >= 0.01) {
|
|
584
|
+
option.style.opacity = '0.8';
|
|
585
|
+
}
|
|
408
586
|
});
|
|
409
|
-
submenu.appendChild(option);
|
|
410
|
-
});
|
|
411
|
-
} else {
|
|
412
|
-
// Add Auto option
|
|
413
|
-
const autoOption = document.createElement('div');
|
|
414
|
-
autoOption.className = 'quality-option';
|
|
415
|
-
autoOption.textContent = 'On (Auto)';
|
|
416
|
-
autoOption.style.cssText = 'padding: 8px 16px; cursor: pointer; color: white;';
|
|
417
|
-
autoOption.addEventListener('click', () => {
|
|
418
|
-
if (this.enableAutoCaptions) this.enableAutoCaptions();
|
|
419
|
-
submenu.style.display = 'none';
|
|
420
|
-
settingsMenu.classList.remove('show');
|
|
421
|
-
});
|
|
422
|
-
submenu.appendChild(autoOption);
|
|
423
|
-
}
|
|
424
587
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
if (hideTimeout) clearTimeout(hideTimeout);
|
|
429
|
-
submenu.style.display = 'block';
|
|
430
|
-
});
|
|
588
|
+
// Add click handler
|
|
589
|
+
option.addEventListener('click', (e) => {
|
|
590
|
+
e.stopPropagation();
|
|
431
591
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
});
|
|
592
|
+
if (this.ytPlayer && this.ytPlayer.setPlaybackRate) {
|
|
593
|
+
this.ytPlayer.setPlaybackRate(speed);
|
|
594
|
+
}
|
|
436
595
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
isHoveringSubmenu = true;
|
|
440
|
-
if (hideTimeout) clearTimeout(hideTimeout);
|
|
441
|
-
submenu.style.display = 'block';
|
|
442
|
-
});
|
|
596
|
+
// Update trigger text
|
|
597
|
+
trigger.childNodes[0].textContent = `${speedText}: ${speed}x`;
|
|
443
598
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
599
|
+
// Rebuild to update selection
|
|
600
|
+
setTimeout(() => {
|
|
601
|
+
rebuildOptions();
|
|
602
|
+
}, 50);
|
|
603
|
+
});
|
|
604
|
+
|
|
605
|
+
optionsContainer.appendChild(option);
|
|
606
|
+
});
|
|
607
|
+
};
|
|
448
608
|
|
|
449
|
-
//
|
|
609
|
+
// Toggle expanded/collapsed state
|
|
610
|
+
let isExpanded = false;
|
|
450
611
|
trigger.addEventListener('click', (e) => {
|
|
451
612
|
e.stopPropagation();
|
|
452
|
-
|
|
453
|
-
|
|
613
|
+
|
|
614
|
+
isExpanded = !isExpanded;
|
|
615
|
+
|
|
616
|
+
if (isExpanded) {
|
|
617
|
+
rebuildOptions();
|
|
618
|
+
optionsContainer.style.display = 'block';
|
|
619
|
+
arrow.style.transform = 'rotate(180deg)';
|
|
454
620
|
} else {
|
|
455
|
-
|
|
621
|
+
optionsContainer.style.display = 'none';
|
|
622
|
+
arrow.style.transform = 'rotate(0deg)';
|
|
456
623
|
}
|
|
457
624
|
});
|
|
458
625
|
|
|
459
626
|
// Assemble
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
627
|
+
speedWrapper.appendChild(trigger);
|
|
628
|
+
speedWrapper.appendChild(optionsContainer);
|
|
629
|
+
|
|
630
|
+
// Insert after subtitles wrapper
|
|
631
|
+
const subtitlesWrapper = settingsMenu.querySelector('.yt-subtitles-wrapper');
|
|
632
|
+
if (subtitlesWrapper) {
|
|
633
|
+
subtitlesWrapper.insertAdjacentElement('afterend', speedWrapper);
|
|
634
|
+
} else {
|
|
635
|
+
settingsMenu.insertBefore(speedWrapper, settingsMenu.firstChild);
|
|
636
|
+
}
|
|
463
637
|
}
|
|
464
638
|
}
|
|
465
639
|
} else {
|
|
@@ -468,12 +642,43 @@ width: fit-content;
|
|
|
468
642
|
subtitlesBtn.style.display = '';
|
|
469
643
|
}
|
|
470
644
|
|
|
645
|
+
// Reset settings menu styles
|
|
646
|
+
if (settingsMenu) {
|
|
647
|
+
settingsMenu.style.maxHeight = '';
|
|
648
|
+
settingsMenu.style.overflowY = '';
|
|
649
|
+
settingsMenu.style.overflowX = '';
|
|
650
|
+
settingsMenu.style.scrollbarWidth = '';
|
|
651
|
+
settingsMenu.style.scrollbarColor = '';
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
// Show original speed option again
|
|
655
|
+
if (settingsMenu) {
|
|
656
|
+
const originalSpeedOption = settingsMenu.querySelector('[data-action="speed"]');
|
|
657
|
+
if (originalSpeedOption) {
|
|
658
|
+
originalSpeedOption.style.display = '';
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
// Show expandable speed option again
|
|
662
|
+
const expandableSpeedWrapper = settingsMenu.querySelector('[data-action="speed-expand"]');
|
|
663
|
+
if (expandableSpeedWrapper) {
|
|
664
|
+
const wrapper = expandableSpeedWrapper.closest('.settings-expandable-wrapper');
|
|
665
|
+
if (wrapper) {
|
|
666
|
+
wrapper.style.display = '';
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
|
|
471
671
|
// Remove from settings
|
|
472
672
|
if (settingsMenu) {
|
|
473
673
|
const subtitlesWrapper = settingsMenu.querySelector('.yt-subtitles-wrapper');
|
|
474
674
|
if (subtitlesWrapper) {
|
|
475
675
|
subtitlesWrapper.remove();
|
|
476
676
|
}
|
|
677
|
+
|
|
678
|
+
const speedWrapper = settingsMenu.querySelector('.yt-speed-wrapper');
|
|
679
|
+
if (speedWrapper) {
|
|
680
|
+
speedWrapper.remove();
|
|
681
|
+
}
|
|
477
682
|
}
|
|
478
683
|
}
|
|
479
684
|
}
|
|
@@ -1210,16 +1415,21 @@ startBufferMonitoring() {
|
|
|
1210
1415
|
setTimeout(() => this.setQuality(this.options.quality), 1000);
|
|
1211
1416
|
}
|
|
1212
1417
|
|
|
1213
|
-
//
|
|
1418
|
+
// Update player watermark with channel data
|
|
1214
1419
|
if (this.options.enableChannelWatermark) {
|
|
1215
1420
|
this.updatePlayerWatermark();
|
|
1216
1421
|
}
|
|
1217
1422
|
|
|
1218
|
-
//
|
|
1423
|
+
// Set auto caption language
|
|
1219
1424
|
if (this.options.autoCaptionLanguage) {
|
|
1220
1425
|
setTimeout(() => this.setAutoCaptionLanguage(), 1500);
|
|
1221
1426
|
}
|
|
1222
1427
|
|
|
1428
|
+
// Check initial caption state AFTER captions are loaded and menu is built
|
|
1429
|
+
setTimeout(() => {
|
|
1430
|
+
this.checkInitialCaptionState();
|
|
1431
|
+
}, 2500); // Dopo che tutto è stato inizializzato
|
|
1432
|
+
|
|
1223
1433
|
this.api.triggerEvent('youtubeplugin:playerready', {});
|
|
1224
1434
|
|
|
1225
1435
|
}
|
|
@@ -2177,13 +2387,13 @@ startBufferMonitoring() {
|
|
|
2177
2387
|
if (this.api.player.options.debug) console.log('[YT Plugin] Subtitles control created');
|
|
2178
2388
|
this.buildSubtitlesMenu();
|
|
2179
2389
|
this.bindSubtitlesButton();
|
|
2180
|
-
this.checkInitialCaptionState();
|
|
2390
|
+
//this.checkInitialCaptionState();
|
|
2181
2391
|
this.startCaptionStateMonitoring();
|
|
2182
2392
|
}
|
|
2183
2393
|
|
|
2184
2394
|
/**
|
|
2185
|
-
|
|
2186
|
-
|
|
2395
|
+
* Build the subtitles menu
|
|
2396
|
+
*/
|
|
2187
2397
|
buildSubtitlesMenu() {
|
|
2188
2398
|
const subtitlesMenu = this.api.container.querySelector('.subtitles-menu');
|
|
2189
2399
|
if (!subtitlesMenu) return;
|
|
@@ -2219,22 +2429,22 @@ startBufferMonitoring() {
|
|
|
2219
2429
|
});
|
|
2220
2430
|
subtitlesMenu.appendChild(option);
|
|
2221
2431
|
});
|
|
2222
|
-
} else {
|
|
2223
|
-
// Auto-caption only (without tracklist)
|
|
2224
|
-
const autoOption = document.createElement('div');
|
|
2225
|
-
autoOption.className = 'subtitles-option';
|
|
2226
|
-
autoOption.textContent = 'Auto-generated';
|
|
2227
|
-
autoOption.dataset.id = 'auto';
|
|
2228
|
-
autoOption.addEventListener('click', (e) => {
|
|
2229
|
-
e.stopPropagation();
|
|
2230
|
-
this.enableAutoCaptions();
|
|
2231
|
-
this.updateMenuSelection('auto');
|
|
2232
|
-
subtitlesMenu.classList.remove('show');
|
|
2233
|
-
});
|
|
2234
|
-
subtitlesMenu.appendChild(autoOption);
|
|
2235
2432
|
}
|
|
2236
2433
|
|
|
2237
|
-
//
|
|
2434
|
+
// SEMPRE aggiungi l'opzione Auto-generated (sia con che senza tracklist)
|
|
2435
|
+
const autoOption = document.createElement('div');
|
|
2436
|
+
autoOption.className = 'subtitles-option';
|
|
2437
|
+
autoOption.textContent = 'Auto-generated';
|
|
2438
|
+
autoOption.dataset.id = 'auto';
|
|
2439
|
+
autoOption.addEventListener('click', (e) => {
|
|
2440
|
+
e.stopPropagation();
|
|
2441
|
+
this.enableAutoCaptions();
|
|
2442
|
+
this.updateMenuSelection('auto');
|
|
2443
|
+
subtitlesMenu.classList.remove('show');
|
|
2444
|
+
});
|
|
2445
|
+
subtitlesMenu.appendChild(autoOption);
|
|
2446
|
+
|
|
2447
|
+
// Always add Auto-translate (both with and without tracklist)
|
|
2238
2448
|
const translateOption = document.createElement('div');
|
|
2239
2449
|
translateOption.className = 'subtitles-option translate-option';
|
|
2240
2450
|
translateOption.textContent = 'Auto-translate';
|
|
@@ -2524,27 +2734,69 @@ startBufferMonitoring() {
|
|
|
2524
2734
|
}
|
|
2525
2735
|
|
|
2526
2736
|
/**
|
|
2527
|
-
|
|
2528
|
-
|
|
2737
|
+
* Check initial caption state
|
|
2738
|
+
*/
|
|
2529
2739
|
checkInitialCaptionState() {
|
|
2530
2740
|
setTimeout(() => {
|
|
2531
2741
|
try {
|
|
2532
2742
|
const currentTrack = this.ytPlayer.getOption('captions', 'track');
|
|
2743
|
+
|
|
2533
2744
|
if (currentTrack && currentTrack.languageCode) {
|
|
2534
2745
|
this.captionsEnabled = true;
|
|
2535
|
-
|
|
2746
|
+
|
|
2747
|
+
// erify if translation is active
|
|
2748
|
+
if (currentTrack.translationLanguage) {
|
|
2749
|
+
this.currentTranslation = currentTrack.translationLanguage.languageCode;
|
|
2750
|
+
|
|
2751
|
+
// when translation is active, set currentCaption to null
|
|
2752
|
+
this.updateMenuSelection('auto');
|
|
2753
|
+
|
|
2754
|
+
// specify translation submenu selection after a short delay
|
|
2755
|
+
setTimeout(() => {
|
|
2756
|
+
const translationMenu = this.api.container.querySelector('.translation-menu');
|
|
2757
|
+
if (translationMenu) {
|
|
2758
|
+
translationMenu.querySelectorAll('.subtitles-option').forEach(option => {
|
|
2759
|
+
option.classList.remove('selected');
|
|
2760
|
+
});
|
|
2761
|
+
|
|
2762
|
+
const selectedTranslation = translationMenu.querySelector(`[data-id="translate-${this.currentTranslation}"]`);
|
|
2763
|
+
if (selectedTranslation) {
|
|
2764
|
+
selectedTranslation.classList.add('selected');
|
|
2765
|
+
}
|
|
2766
|
+
}
|
|
2767
|
+
}, 100);
|
|
2768
|
+
} else {
|
|
2769
|
+
// find current caption track index
|
|
2770
|
+
const captionIndex = this.availableCaptions.findIndex(
|
|
2771
|
+
cap => cap.languageCode === currentTrack.languageCode
|
|
2772
|
+
);
|
|
2773
|
+
|
|
2774
|
+
if (captionIndex >= 0) {
|
|
2775
|
+
this.currentCaption = currentTrack.languageCode;
|
|
2776
|
+
this.updateMenuSelection(`caption-${captionIndex}`);
|
|
2777
|
+
} else {
|
|
2778
|
+
// Se non trovato nella lista, è auto-generated
|
|
2779
|
+
this.updateMenuSelection('auto');
|
|
2780
|
+
}
|
|
2781
|
+
}
|
|
2782
|
+
|
|
2783
|
+
// activate button
|
|
2784
|
+
const subtitlesBtn = this.api.container.querySelector('.subtitles-btn');
|
|
2785
|
+
if (subtitlesBtn) {
|
|
2786
|
+
subtitlesBtn.classList.add('active');
|
|
2787
|
+
}
|
|
2536
2788
|
} else {
|
|
2537
2789
|
this.updateMenuSelection('off');
|
|
2538
2790
|
}
|
|
2539
2791
|
} catch (e) {
|
|
2540
2792
|
this.updateMenuSelection('off');
|
|
2541
2793
|
}
|
|
2542
|
-
},
|
|
2794
|
+
}, 2000);
|
|
2543
2795
|
}
|
|
2544
2796
|
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2797
|
+
/**
|
|
2798
|
+
* Monitor caption state
|
|
2799
|
+
*/
|
|
2548
2800
|
startCaptionStateMonitoring() {
|
|
2549
2801
|
if (this.captionStateCheckInterval) {
|
|
2550
2802
|
clearInterval(this.captionStateCheckInterval);
|
|
@@ -2554,7 +2806,6 @@ startBufferMonitoring() {
|
|
|
2554
2806
|
try {
|
|
2555
2807
|
const currentTrack = this.ytPlayer.getOption('captions', 'track');
|
|
2556
2808
|
const wasEnabled = this.captionsEnabled;
|
|
2557
|
-
|
|
2558
2809
|
this.captionsEnabled = !!(currentTrack && currentTrack.languageCode);
|
|
2559
2810
|
|
|
2560
2811
|
if (wasEnabled !== this.captionsEnabled) {
|
|
@@ -2562,8 +2813,24 @@ startBufferMonitoring() {
|
|
|
2562
2813
|
if (subtitlesBtn) {
|
|
2563
2814
|
if (this.captionsEnabled) {
|
|
2564
2815
|
subtitlesBtn.classList.add('active');
|
|
2816
|
+
|
|
2817
|
+
// update current caption/translation
|
|
2818
|
+
if (currentTrack.translationLanguage) {
|
|
2819
|
+
this.currentTranslation = currentTrack.translationLanguage.languageCode;
|
|
2820
|
+
this.updateMenuSelection(`translate-${this.currentTranslation}`);
|
|
2821
|
+
} else {
|
|
2822
|
+
const captionIndex = this.availableCaptions.findIndex(
|
|
2823
|
+
cap => cap.languageCode === currentTrack.languageCode
|
|
2824
|
+
);
|
|
2825
|
+
if (captionIndex >= 0) {
|
|
2826
|
+
this.updateMenuSelection(`caption-${captionIndex}`);
|
|
2827
|
+
} else {
|
|
2828
|
+
this.updateMenuSelection('auto');
|
|
2829
|
+
}
|
|
2830
|
+
}
|
|
2565
2831
|
} else {
|
|
2566
2832
|
subtitlesBtn.classList.remove('active');
|
|
2833
|
+
this.updateMenuSelection('off');
|
|
2567
2834
|
}
|
|
2568
2835
|
}
|
|
2569
2836
|
}
|
|
@@ -2883,7 +3150,7 @@ startBufferMonitoring() {
|
|
|
2883
3150
|
}
|
|
2884
3151
|
};
|
|
2885
3152
|
|
|
2886
|
-
// Override pause method
|
|
3153
|
+
// Override pause method
|
|
2887
3154
|
const originalPause = this.player.pause;
|
|
2888
3155
|
this.player.pause = () => {
|
|
2889
3156
|
if (this.ytPlayer && this.ytPlayer.pauseVideo) {
|
|
@@ -2955,15 +3222,13 @@ startBufferMonitoring() {
|
|
|
2955
3222
|
// Override mute toggle
|
|
2956
3223
|
const originalToggleMute = this.player.toggleMute;
|
|
2957
3224
|
this.player.toggleMute = () => {
|
|
2958
|
-
if (this.ytPlayer && this.ytPlayer.isMuted
|
|
3225
|
+
if (this.ytPlayer && this.ytPlayer.isMuted) {
|
|
2959
3226
|
const isMuted = this.ytPlayer.isMuted();
|
|
2960
|
-
|
|
2961
3227
|
if (isMuted) {
|
|
2962
3228
|
this.ytPlayer.unMute();
|
|
2963
3229
|
} else {
|
|
2964
3230
|
this.ytPlayer.mute();
|
|
2965
3231
|
}
|
|
2966
|
-
|
|
2967
3232
|
this.updateMuteButtonState(!isMuted);
|
|
2968
3233
|
|
|
2969
3234
|
if (!isMuted) {
|
|
@@ -2977,97 +3242,6 @@ startBufferMonitoring() {
|
|
|
2977
3242
|
}
|
|
2978
3243
|
};
|
|
2979
3244
|
|
|
2980
|
-
// Volume tooltip events for YouTube
|
|
2981
|
-
if (this.api.player.volumeSlider) {
|
|
2982
|
-
const volumeSlider = this.api.player.volumeSlider;
|
|
2983
|
-
const volumeContainer = this.api.container.querySelector('.volume-container');
|
|
2984
|
-
|
|
2985
|
-
// Remove existing listeners to avoid duplicates
|
|
2986
|
-
const newVolumeSlider = volumeSlider.cloneNode(true);
|
|
2987
|
-
volumeSlider.parentNode.replaceChild(newVolumeSlider, volumeSlider);
|
|
2988
|
-
this.api.player.volumeSlider = newVolumeSlider;
|
|
2989
|
-
|
|
2990
|
-
// Update tooltip on input (slider drag)
|
|
2991
|
-
newVolumeSlider.addEventListener('input', (e) => {
|
|
2992
|
-
const value = parseFloat(e.target.value);
|
|
2993
|
-
this.player.updateVolume(value);
|
|
2994
|
-
|
|
2995
|
-
// Update tooltip position and text during drag
|
|
2996
|
-
if (this.api.player.updateVolumeTooltipPosition) {
|
|
2997
|
-
this.api.player.updateVolumeTooltipPosition(value / 100);
|
|
2998
|
-
}
|
|
2999
|
-
if (this.api.player.updateVolumeTooltip) {
|
|
3000
|
-
this.api.player.updateVolumeTooltip();
|
|
3001
|
-
}
|
|
3002
|
-
});
|
|
3003
|
-
|
|
3004
|
-
// Update tooltip position on mousemove over slider
|
|
3005
|
-
newVolumeSlider.addEventListener('mousemove', (e) => {
|
|
3006
|
-
const rect = newVolumeSlider.getBoundingClientRect();
|
|
3007
|
-
const mouseX = e.clientX - rect.left;
|
|
3008
|
-
const percentage = Math.max(0, Math.min(1, mouseX / rect.width));
|
|
3009
|
-
|
|
3010
|
-
// Update tooltip position as mouse moves
|
|
3011
|
-
if (this.api.player.updateVolumeTooltipPosition) {
|
|
3012
|
-
this.api.player.updateVolumeTooltipPosition(percentage);
|
|
3013
|
-
}
|
|
3014
|
-
|
|
3015
|
-
// Update tooltip text to show value under mouse
|
|
3016
|
-
const volumeTooltip = this.api.container.querySelector('.volume-tooltip');
|
|
3017
|
-
if (volumeTooltip) {
|
|
3018
|
-
volumeTooltip.textContent = Math.round(percentage * 100) + '%';
|
|
3019
|
-
}
|
|
3020
|
-
});
|
|
3021
|
-
|
|
3022
|
-
// Show/hide tooltip on hover
|
|
3023
|
-
if (volumeContainer) {
|
|
3024
|
-
volumeContainer.addEventListener('mouseenter', () => {
|
|
3025
|
-
const volumeTooltip = this.api.container.querySelector('.volume-tooltip');
|
|
3026
|
-
if (volumeTooltip) {
|
|
3027
|
-
volumeTooltip.classList.add('visible');
|
|
3028
|
-
}
|
|
3029
|
-
});
|
|
3030
|
-
|
|
3031
|
-
volumeContainer.addEventListener('mouseleave', () => {
|
|
3032
|
-
const volumeTooltip = this.api.container.querySelector('.volume-tooltip');
|
|
3033
|
-
if (volumeTooltip) {
|
|
3034
|
-
volumeTooltip.classList.remove('visible');
|
|
3035
|
-
}
|
|
3036
|
-
});
|
|
3037
|
-
}
|
|
3038
|
-
|
|
3039
|
-
if (this.api.player.options.debug) {
|
|
3040
|
-
console.log('[YT Plugin] Volume tooltip events bound');
|
|
3041
|
-
}
|
|
3042
|
-
}
|
|
3043
|
-
|
|
3044
|
-
// Override playback speed
|
|
3045
|
-
const originalChangeSpeed = this.player.changeSpeed;
|
|
3046
|
-
if (originalChangeSpeed) {
|
|
3047
|
-
this.player.changeSpeed = (e) => {
|
|
3048
|
-
if (!e.target.classList.contains('speed-option')) return;
|
|
3049
|
-
|
|
3050
|
-
const speed = parseFloat(e.target.getAttribute('data-speed'));
|
|
3051
|
-
|
|
3052
|
-
if (this.ytPlayer && this.ytPlayer.setPlaybackRate && speed > 0) {
|
|
3053
|
-
this.ytPlayer.setPlaybackRate(speed);
|
|
3054
|
-
|
|
3055
|
-
const speedBtn = this.api.container.querySelector('.speed-btn');
|
|
3056
|
-
if (speedBtn) speedBtn.textContent = `${speed}x`;
|
|
3057
|
-
|
|
3058
|
-
const speedMenu = this.api.container.querySelector('.speed-menu');
|
|
3059
|
-
if (speedMenu) {
|
|
3060
|
-
speedMenu.querySelectorAll('.speed-option').forEach(option => {
|
|
3061
|
-
option.classList.remove('active');
|
|
3062
|
-
});
|
|
3063
|
-
e.target.classList.add('active');
|
|
3064
|
-
}
|
|
3065
|
-
} else {
|
|
3066
|
-
originalChangeSpeed.call(this.player, e);
|
|
3067
|
-
}
|
|
3068
|
-
};
|
|
3069
|
-
}
|
|
3070
|
-
|
|
3071
3245
|
// Override progress bar seeking
|
|
3072
3246
|
if (this.api.player.progressContainer) {
|
|
3073
3247
|
const progressContainer = this.api.player.progressContainer;
|
|
@@ -3082,7 +3256,22 @@ startBufferMonitoring() {
|
|
|
3082
3256
|
// Create tooltip for seek preview
|
|
3083
3257
|
const seekTooltip = document.createElement('div');
|
|
3084
3258
|
seekTooltip.className = 'yt-seek-tooltip';
|
|
3085
|
-
seekTooltip.style.cssText =
|
|
3259
|
+
seekTooltip.style.cssText = `
|
|
3260
|
+
position: absolute;
|
|
3261
|
+
bottom: calc(100% + 10px);
|
|
3262
|
+
left: 0;
|
|
3263
|
+
background: rgba(28,28,28,0.95);
|
|
3264
|
+
color: #fff;
|
|
3265
|
+
padding: 6px 10px;
|
|
3266
|
+
border-radius: 3px;
|
|
3267
|
+
font-size: 13px;
|
|
3268
|
+
font-weight: 500;
|
|
3269
|
+
white-space: nowrap;
|
|
3270
|
+
pointer-events: none;
|
|
3271
|
+
visibility: hidden;
|
|
3272
|
+
z-index: 99999;
|
|
3273
|
+
box-shadow: 0 2px 8px rgba(0,0,0,0.3);
|
|
3274
|
+
`;
|
|
3086
3275
|
newProgressContainer.appendChild(seekTooltip);
|
|
3087
3276
|
|
|
3088
3277
|
// Format time function for tooltip
|
|
@@ -3100,25 +3289,32 @@ startBufferMonitoring() {
|
|
|
3100
3289
|
let isSeeking = false;
|
|
3101
3290
|
|
|
3102
3291
|
const handleSeek = (e) => {
|
|
3103
|
-
if (!this.ytPlayer || !this.ytPlayer.getDuration) return;
|
|
3292
|
+
if (!this.ytPlayer || !this.ytPlayer.getDuration()) return;
|
|
3104
3293
|
|
|
3105
3294
|
const rect = newProgressContainer.getBoundingClientRect();
|
|
3106
|
-
|
|
3295
|
+
|
|
3296
|
+
// Support both mouse and touch events
|
|
3297
|
+
const clientX = e.clientX !== undefined ? e.clientX :
|
|
3298
|
+
(e.touches && e.touches[0] ? e.touches[0].clientX :
|
|
3299
|
+
(e.changedTouches && e.changedTouches[0] ? e.changedTouches[0].clientX : 0));
|
|
3300
|
+
|
|
3301
|
+
const clickX = clientX - rect.left;
|
|
3107
3302
|
const percentage = Math.max(0, Math.min(1, clickX / rect.width));
|
|
3108
3303
|
const duration = this.ytPlayer.getDuration();
|
|
3109
3304
|
const targetTime = percentage * duration;
|
|
3110
3305
|
|
|
3111
3306
|
this.ytPlayer.seekTo(targetTime, true);
|
|
3112
3307
|
|
|
3113
|
-
const progress = percentage * 100
|
|
3308
|
+
const progress = percentage * 100;
|
|
3114
3309
|
if (this.api.player.progressFilled) {
|
|
3115
|
-
this.api.player.progressFilled.style.width = progress
|
|
3310
|
+
this.api.player.progressFilled.style.width = `${progress}%`;
|
|
3116
3311
|
}
|
|
3117
3312
|
if (this.api.player.progressHandle) {
|
|
3118
|
-
this.api.player.progressHandle.style.left = progress
|
|
3313
|
+
this.api.player.progressHandle.style.left = `${progress}%`;
|
|
3119
3314
|
}
|
|
3120
3315
|
};
|
|
3121
3316
|
|
|
3317
|
+
// MOUSE EVENTS
|
|
3122
3318
|
newProgressContainer.addEventListener('mousedown', (e) => {
|
|
3123
3319
|
isSeeking = true;
|
|
3124
3320
|
handleSeek(e);
|
|
@@ -3130,7 +3326,7 @@ startBufferMonitoring() {
|
|
|
3130
3326
|
}
|
|
3131
3327
|
|
|
3132
3328
|
// Show tooltip with timestamp
|
|
3133
|
-
if (!isSeeking && this.ytPlayer && this.ytPlayer.getDuration) {
|
|
3329
|
+
if (!isSeeking && this.ytPlayer && this.ytPlayer.getDuration()) {
|
|
3134
3330
|
const rect = newProgressContainer.getBoundingClientRect();
|
|
3135
3331
|
const mouseX = e.clientX - rect.left;
|
|
3136
3332
|
const percentage = Math.max(0, Math.min(1, mouseX / rect.width));
|
|
@@ -3138,7 +3334,7 @@ startBufferMonitoring() {
|
|
|
3138
3334
|
const time = percentage * duration;
|
|
3139
3335
|
|
|
3140
3336
|
seekTooltip.textContent = formatTimeForTooltip(time);
|
|
3141
|
-
seekTooltip.style.left = mouseX
|
|
3337
|
+
seekTooltip.style.left = `${mouseX}px`;
|
|
3142
3338
|
seekTooltip.style.visibility = 'visible';
|
|
3143
3339
|
}
|
|
3144
3340
|
});
|
|
@@ -3151,10 +3347,50 @@ startBufferMonitoring() {
|
|
|
3151
3347
|
isSeeking = false;
|
|
3152
3348
|
});
|
|
3153
3349
|
|
|
3350
|
+
// TOUCH EVENTS - AGGIUNTI QUI!
|
|
3351
|
+
newProgressContainer.addEventListener('touchstart', (e) => {
|
|
3352
|
+
e.preventDefault(); // scroll prevention during drag
|
|
3353
|
+
isSeeking = true;
|
|
3354
|
+
handleSeek(e);
|
|
3355
|
+
}, { passive: false });
|
|
3356
|
+
|
|
3357
|
+
newProgressContainer.addEventListener('touchmove', (e) => {
|
|
3358
|
+
e.preventDefault(); // scroll prevention during drag
|
|
3359
|
+
|
|
3360
|
+
if (isSeeking) {
|
|
3361
|
+
handleSeek(e);
|
|
3362
|
+
}
|
|
3363
|
+
|
|
3364
|
+
// Show tooltip with timestamp during touch
|
|
3365
|
+
if (!isSeeking && this.ytPlayer && this.ytPlayer.getDuration()) {
|
|
3366
|
+
const rect = newProgressContainer.getBoundingClientRect();
|
|
3367
|
+
const touch = e.touches[0];
|
|
3368
|
+
const touchX = touch.clientX - rect.left;
|
|
3369
|
+
const percentage = Math.max(0, Math.min(1, touchX / rect.width));
|
|
3370
|
+
const duration = this.ytPlayer.getDuration();
|
|
3371
|
+
const time = percentage * duration;
|
|
3372
|
+
|
|
3373
|
+
seekTooltip.textContent = formatTimeForTooltip(time);
|
|
3374
|
+
seekTooltip.style.left = `${touchX}px`;
|
|
3375
|
+
seekTooltip.style.visibility = 'visible';
|
|
3376
|
+
}
|
|
3377
|
+
}, { passive: false });
|
|
3378
|
+
|
|
3379
|
+
newProgressContainer.addEventListener('touchend', () => {
|
|
3380
|
+
isSeeking = false;
|
|
3381
|
+
seekTooltip.style.visibility = 'hidden';
|
|
3382
|
+
});
|
|
3383
|
+
|
|
3384
|
+
newProgressContainer.addEventListener('touchcancel', () => {
|
|
3385
|
+
isSeeking = false;
|
|
3386
|
+
seekTooltip.style.visibility = 'hidden';
|
|
3387
|
+
});
|
|
3388
|
+
|
|
3389
|
+
// CLICK EVENT
|
|
3154
3390
|
newProgressContainer.addEventListener('click', handleSeek);
|
|
3155
|
-
}
|
|
3156
3391
|
|
|
3157
|
-
|
|
3392
|
+
this.bindVolumeSlider();
|
|
3393
|
+
}
|
|
3158
3394
|
|
|
3159
3395
|
// Time update interval
|
|
3160
3396
|
if (this.timeUpdateInterval) {
|
|
@@ -3175,14 +3411,13 @@ startBufferMonitoring() {
|
|
|
3175
3411
|
} else {
|
|
3176
3412
|
// For regular videos, calculate normally
|
|
3177
3413
|
progress = (currentTime / duration) * 100;
|
|
3178
|
-
}
|
|
3179
3414
|
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3415
|
+
// Check if live badge exists = it's a live stream
|
|
3416
|
+
const liveBadge = this.api.container.querySelector('.live-badge');
|
|
3417
|
+
if (liveBadge) {
|
|
3418
|
+
// Force 100% for live streams
|
|
3419
|
+
progress = 100;
|
|
3420
|
+
}
|
|
3186
3421
|
}
|
|
3187
3422
|
|
|
3188
3423
|
this.api.player.progressFilled.style.width = `${progress}%`;
|
|
@@ -3194,8 +3429,13 @@ startBufferMonitoring() {
|
|
|
3194
3429
|
const currentTimeEl = this.api.container.querySelector('.current-time');
|
|
3195
3430
|
const durationEl = this.api.container.querySelector('.duration');
|
|
3196
3431
|
|
|
3197
|
-
if (currentTimeEl)
|
|
3198
|
-
|
|
3432
|
+
if (currentTimeEl) {
|
|
3433
|
+
currentTimeEl.textContent = this.formatTime(currentTime);
|
|
3434
|
+
}
|
|
3435
|
+
|
|
3436
|
+
if (durationEl && duration) {
|
|
3437
|
+
durationEl.textContent = this.formatTime(duration);
|
|
3438
|
+
}
|
|
3199
3439
|
}
|
|
3200
3440
|
}, 250);
|
|
3201
3441
|
}
|