myetv-player 1.1.3 → 1.1.4
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/css/myetv-player.css +44 -0
- package/css/myetv-player.min.css +1 -1
- package/dist/myetv-player.js +122 -51
- package/dist/myetv-player.min.js +102 -43
- package/package.json +2 -1
- package/plugins/youtube/myetv-player-youtube-plugin.js +378 -130
- package/scss/_menus.scss +49 -0
- package/src/controls.js +122 -51
|
@@ -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,56 @@
|
|
|
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
|
+
const originalSpeedOption = settingsMenu.querySelector('[data-action="speed"]');
|
|
371
|
+
if (originalSpeedOption) {
|
|
372
|
+
originalSpeedOption.style.display = 'none';
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
327
376
|
// Add subtitles option to settings menu
|
|
328
377
|
if (settingsMenu) {
|
|
329
378
|
let subtitlesWrapper = settingsMenu.querySelector('.yt-subtitles-wrapper');
|
|
@@ -345,121 +394,236 @@
|
|
|
345
394
|
// Create trigger
|
|
346
395
|
const trigger = document.createElement('div');
|
|
347
396
|
trigger.className = 'quality-option';
|
|
397
|
+
trigger.style.fontSize = '10px';
|
|
348
398
|
trigger.textContent = subtitlesText;
|
|
349
399
|
|
|
350
|
-
//
|
|
351
|
-
const
|
|
352
|
-
|
|
353
|
-
|
|
400
|
+
// Add arrow indicator
|
|
401
|
+
const arrow = document.createElement('span');
|
|
402
|
+
arrow.textContent = ' ▼';
|
|
403
|
+
arrow.style.cssText = 'font-size: 8px; transition: transform 0.2s;';
|
|
404
|
+
trigger.appendChild(arrow);
|
|
405
|
+
|
|
406
|
+
// Container for expanded options
|
|
407
|
+
const optionsContainer = document.createElement('div');
|
|
408
|
+
optionsContainer.className = 'yt-subtitles-options';
|
|
409
|
+
optionsContainer.style.cssText = `
|
|
354
410
|
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
|
-
|
|
411
|
+
padding-left: 15px;
|
|
412
|
+
margin-top: 4px;
|
|
413
|
+
`;
|
|
414
|
+
|
|
415
|
+
// Function to rebuild options from main menu
|
|
416
|
+
const rebuildOptions = () => {
|
|
417
|
+
const mainSubtitlesMenu = this.api.container.querySelector('.subtitles-menu');
|
|
418
|
+
if (!mainSubtitlesMenu) return;
|
|
419
|
+
|
|
420
|
+
// Clone all options from main menu
|
|
421
|
+
optionsContainer.innerHTML = '';
|
|
422
|
+
const options = mainSubtitlesMenu.querySelectorAll('.subtitles-option');
|
|
423
|
+
|
|
424
|
+
options.forEach(option => {
|
|
425
|
+
const clonedOption = option.cloneNode(true);
|
|
426
|
+
clonedOption.style.cssText = `
|
|
427
|
+
padding: 6px 12px;
|
|
428
|
+
cursor: pointer;
|
|
429
|
+
color: white;
|
|
430
|
+
font-size: 10px;
|
|
431
|
+
white-space: normal;
|
|
432
|
+
word-wrap: break-word;
|
|
433
|
+
opacity: 0.8;
|
|
434
|
+
transition: opacity 0.2s;
|
|
435
|
+
`;
|
|
436
|
+
|
|
437
|
+
// Highlight selected option
|
|
438
|
+
if (option.classList.contains('selected')) {
|
|
439
|
+
clonedOption.style.opacity = '1';
|
|
440
|
+
clonedOption.style.fontWeight = 'bold';
|
|
381
441
|
}
|
|
382
|
-
|
|
442
|
+
|
|
443
|
+
// Hover effect
|
|
444
|
+
clonedOption.addEventListener('mouseenter', () => {
|
|
445
|
+
clonedOption.style.opacity = '1';
|
|
446
|
+
});
|
|
447
|
+
clonedOption.addEventListener('mouseleave', () => {
|
|
448
|
+
if (!option.classList.contains('selected')) {
|
|
449
|
+
clonedOption.style.opacity = '0.8';
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
// Add click handler
|
|
454
|
+
clonedOption.addEventListener('click', (e) => {
|
|
455
|
+
e.stopPropagation();
|
|
456
|
+
|
|
457
|
+
// Trigger click on original option
|
|
458
|
+
option.click();
|
|
459
|
+
|
|
460
|
+
// Rebuild to update selection
|
|
461
|
+
setTimeout(() => {
|
|
462
|
+
rebuildOptions();
|
|
463
|
+
}, 50);
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
optionsContainer.appendChild(clonedOption);
|
|
467
|
+
});
|
|
383
468
|
};
|
|
384
469
|
|
|
385
|
-
//
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
470
|
+
// Toggle expanded/collapsed state
|
|
471
|
+
let isExpanded = false;
|
|
472
|
+
trigger.addEventListener('click', (e) => {
|
|
473
|
+
e.stopPropagation();
|
|
474
|
+
|
|
475
|
+
isExpanded = !isExpanded;
|
|
476
|
+
|
|
477
|
+
if (isExpanded) {
|
|
478
|
+
rebuildOptions();
|
|
479
|
+
optionsContainer.style.display = 'block';
|
|
480
|
+
arrow.style.transform = 'rotate(180deg)';
|
|
481
|
+
} else {
|
|
482
|
+
optionsContainer.style.display = 'none';
|
|
483
|
+
arrow.style.transform = 'rotate(0deg)';
|
|
484
|
+
}
|
|
394
485
|
});
|
|
395
|
-
submenu.appendChild(offOption);
|
|
396
486
|
|
|
397
|
-
//
|
|
398
|
-
|
|
399
|
-
|
|
487
|
+
// Assemble
|
|
488
|
+
subtitlesWrapper.appendChild(trigger);
|
|
489
|
+
subtitlesWrapper.appendChild(optionsContainer);
|
|
490
|
+
settingsMenu.insertBefore(subtitlesWrapper, settingsMenu.firstChild);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// Add speed option to settings menu
|
|
494
|
+
let speedWrapper = settingsMenu.querySelector('.yt-speed-wrapper');
|
|
495
|
+
|
|
496
|
+
if (!speedWrapper) {
|
|
497
|
+
// Get i18n text - use 'playback_speed' key
|
|
498
|
+
let speedText = 'Playback speed';
|
|
499
|
+
if (this.api.player && this.api.player.t) {
|
|
500
|
+
speedText = this.api.player.t('playback_speed');
|
|
501
|
+
} else if (this.player && this.player.t) {
|
|
502
|
+
speedText = this.player.t('playback_speed');
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// Create wrapper
|
|
506
|
+
speedWrapper = document.createElement('div');
|
|
507
|
+
speedWrapper.className = 'yt-speed-wrapper';
|
|
508
|
+
speedWrapper.style.cssText = 'position: relative; display: block;';
|
|
509
|
+
|
|
510
|
+
// Create trigger
|
|
511
|
+
const trigger = document.createElement('div');
|
|
512
|
+
trigger.className = 'quality-option';
|
|
513
|
+
trigger.style.fontSize = '10px';
|
|
514
|
+
|
|
515
|
+
// Get current speed
|
|
516
|
+
const getCurrentSpeed = () => {
|
|
517
|
+
if (this.ytPlayer && this.ytPlayer.getPlaybackRate) {
|
|
518
|
+
return this.ytPlayer.getPlaybackRate();
|
|
519
|
+
}
|
|
520
|
+
return 1;
|
|
521
|
+
};
|
|
522
|
+
|
|
523
|
+
trigger.textContent = `${speedText}: ${getCurrentSpeed()}x`;
|
|
524
|
+
|
|
525
|
+
// Add arrow indicator
|
|
526
|
+
const arrow = document.createElement('span');
|
|
527
|
+
arrow.textContent = ' ▼';
|
|
528
|
+
arrow.style.cssText = 'font-size: 8px; transition: transform 0.2s;';
|
|
529
|
+
trigger.appendChild(arrow);
|
|
530
|
+
|
|
531
|
+
// Container for expanded options
|
|
532
|
+
const optionsContainer = document.createElement('div');
|
|
533
|
+
optionsContainer.className = 'yt-speed-options';
|
|
534
|
+
optionsContainer.style.cssText = `
|
|
535
|
+
display: none;
|
|
536
|
+
padding-left: 15px;
|
|
537
|
+
margin-top: 4px;
|
|
538
|
+
`;
|
|
539
|
+
|
|
540
|
+
// Available speeds
|
|
541
|
+
const speeds = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2];
|
|
542
|
+
|
|
543
|
+
// Function to rebuild options
|
|
544
|
+
const rebuildOptions = () => {
|
|
545
|
+
optionsContainer.innerHTML = '';
|
|
546
|
+
const currentSpeed = getCurrentSpeed();
|
|
547
|
+
|
|
548
|
+
speeds.forEach(speed => {
|
|
400
549
|
const option = document.createElement('div');
|
|
401
|
-
option.
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
550
|
+
option.style.cssText = `
|
|
551
|
+
padding: 6px 12px;
|
|
552
|
+
cursor: pointer;
|
|
553
|
+
color: white;
|
|
554
|
+
font-size: 10px;
|
|
555
|
+
white-space: normal;
|
|
556
|
+
word-wrap: break-word;
|
|
557
|
+
opacity: 0.8;
|
|
558
|
+
transition: opacity 0.2s;
|
|
559
|
+
`;
|
|
560
|
+
option.textContent = `${speed}x`;
|
|
561
|
+
|
|
562
|
+
// Highlight selected option
|
|
563
|
+
if (Math.abs(speed - currentSpeed) < 0.01) {
|
|
564
|
+
option.style.opacity = '1';
|
|
565
|
+
option.style.fontWeight = 'bold';
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// Hover effect
|
|
569
|
+
option.addEventListener('mouseenter', () => {
|
|
570
|
+
option.style.opacity = '1';
|
|
571
|
+
});
|
|
572
|
+
option.addEventListener('mouseleave', () => {
|
|
573
|
+
if (Math.abs(speed - getCurrentSpeed()) >= 0.01) {
|
|
574
|
+
option.style.opacity = '0.8';
|
|
575
|
+
}
|
|
408
576
|
});
|
|
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
577
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
if (hideTimeout) clearTimeout(hideTimeout);
|
|
429
|
-
submenu.style.display = 'block';
|
|
430
|
-
});
|
|
578
|
+
// Add click handler
|
|
579
|
+
option.addEventListener('click', (e) => {
|
|
580
|
+
e.stopPropagation();
|
|
431
581
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
});
|
|
582
|
+
if (this.ytPlayer && this.ytPlayer.setPlaybackRate) {
|
|
583
|
+
this.ytPlayer.setPlaybackRate(speed);
|
|
584
|
+
}
|
|
436
585
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
isHoveringSubmenu = true;
|
|
440
|
-
if (hideTimeout) clearTimeout(hideTimeout);
|
|
441
|
-
submenu.style.display = 'block';
|
|
442
|
-
});
|
|
586
|
+
// Update trigger text
|
|
587
|
+
trigger.childNodes[0].textContent = `${speedText}: ${speed}x`;
|
|
443
588
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
589
|
+
// Rebuild to update selection
|
|
590
|
+
setTimeout(() => {
|
|
591
|
+
rebuildOptions();
|
|
592
|
+
}, 50);
|
|
593
|
+
});
|
|
594
|
+
|
|
595
|
+
optionsContainer.appendChild(option);
|
|
596
|
+
});
|
|
597
|
+
};
|
|
448
598
|
|
|
449
|
-
//
|
|
599
|
+
// Toggle expanded/collapsed state
|
|
600
|
+
let isExpanded = false;
|
|
450
601
|
trigger.addEventListener('click', (e) => {
|
|
451
602
|
e.stopPropagation();
|
|
452
|
-
|
|
453
|
-
|
|
603
|
+
|
|
604
|
+
isExpanded = !isExpanded;
|
|
605
|
+
|
|
606
|
+
if (isExpanded) {
|
|
607
|
+
rebuildOptions();
|
|
608
|
+
optionsContainer.style.display = 'block';
|
|
609
|
+
arrow.style.transform = 'rotate(180deg)';
|
|
454
610
|
} else {
|
|
455
|
-
|
|
611
|
+
optionsContainer.style.display = 'none';
|
|
612
|
+
arrow.style.transform = 'rotate(0deg)';
|
|
456
613
|
}
|
|
457
614
|
});
|
|
458
615
|
|
|
459
616
|
// Assemble
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
617
|
+
speedWrapper.appendChild(trigger);
|
|
618
|
+
speedWrapper.appendChild(optionsContainer);
|
|
619
|
+
|
|
620
|
+
// Insert after subtitles wrapper
|
|
621
|
+
const subtitlesWrapper = settingsMenu.querySelector('.yt-subtitles-wrapper');
|
|
622
|
+
if (subtitlesWrapper) {
|
|
623
|
+
subtitlesWrapper.insertAdjacentElement('afterend', speedWrapper);
|
|
624
|
+
} else {
|
|
625
|
+
settingsMenu.insertBefore(speedWrapper, settingsMenu.firstChild);
|
|
626
|
+
}
|
|
463
627
|
}
|
|
464
628
|
}
|
|
465
629
|
} else {
|
|
@@ -468,12 +632,34 @@ width: fit-content;
|
|
|
468
632
|
subtitlesBtn.style.display = '';
|
|
469
633
|
}
|
|
470
634
|
|
|
635
|
+
// Reset settings menu styles
|
|
636
|
+
if (settingsMenu) {
|
|
637
|
+
settingsMenu.style.maxHeight = '';
|
|
638
|
+
settingsMenu.style.overflowY = '';
|
|
639
|
+
settingsMenu.style.overflowX = '';
|
|
640
|
+
settingsMenu.style.scrollbarWidth = '';
|
|
641
|
+
settingsMenu.style.scrollbarColor = '';
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
// Show original speed option again
|
|
645
|
+
if (settingsMenu) {
|
|
646
|
+
const originalSpeedOption = settingsMenu.querySelector('[data-action="speed"]');
|
|
647
|
+
if (originalSpeedOption) {
|
|
648
|
+
originalSpeedOption.style.display = '';
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
|
|
471
652
|
// Remove from settings
|
|
472
653
|
if (settingsMenu) {
|
|
473
654
|
const subtitlesWrapper = settingsMenu.querySelector('.yt-subtitles-wrapper');
|
|
474
655
|
if (subtitlesWrapper) {
|
|
475
656
|
subtitlesWrapper.remove();
|
|
476
657
|
}
|
|
658
|
+
|
|
659
|
+
const speedWrapper = settingsMenu.querySelector('.yt-speed-wrapper');
|
|
660
|
+
if (speedWrapper) {
|
|
661
|
+
speedWrapper.remove();
|
|
662
|
+
}
|
|
477
663
|
}
|
|
478
664
|
}
|
|
479
665
|
}
|
|
@@ -1210,16 +1396,21 @@ startBufferMonitoring() {
|
|
|
1210
1396
|
setTimeout(() => this.setQuality(this.options.quality), 1000);
|
|
1211
1397
|
}
|
|
1212
1398
|
|
|
1213
|
-
//
|
|
1399
|
+
// Update player watermark with channel data
|
|
1214
1400
|
if (this.options.enableChannelWatermark) {
|
|
1215
1401
|
this.updatePlayerWatermark();
|
|
1216
1402
|
}
|
|
1217
1403
|
|
|
1218
|
-
//
|
|
1404
|
+
// Set auto caption language
|
|
1219
1405
|
if (this.options.autoCaptionLanguage) {
|
|
1220
1406
|
setTimeout(() => this.setAutoCaptionLanguage(), 1500);
|
|
1221
1407
|
}
|
|
1222
1408
|
|
|
1409
|
+
// Check initial caption state AFTER captions are loaded and menu is built
|
|
1410
|
+
setTimeout(() => {
|
|
1411
|
+
this.checkInitialCaptionState();
|
|
1412
|
+
}, 2500); // Dopo che tutto è stato inizializzato
|
|
1413
|
+
|
|
1223
1414
|
this.api.triggerEvent('youtubeplugin:playerready', {});
|
|
1224
1415
|
|
|
1225
1416
|
}
|
|
@@ -2177,13 +2368,13 @@ startBufferMonitoring() {
|
|
|
2177
2368
|
if (this.api.player.options.debug) console.log('[YT Plugin] Subtitles control created');
|
|
2178
2369
|
this.buildSubtitlesMenu();
|
|
2179
2370
|
this.bindSubtitlesButton();
|
|
2180
|
-
this.checkInitialCaptionState();
|
|
2371
|
+
//this.checkInitialCaptionState();
|
|
2181
2372
|
this.startCaptionStateMonitoring();
|
|
2182
2373
|
}
|
|
2183
2374
|
|
|
2184
2375
|
/**
|
|
2185
|
-
|
|
2186
|
-
|
|
2376
|
+
* Build the subtitles menu
|
|
2377
|
+
*/
|
|
2187
2378
|
buildSubtitlesMenu() {
|
|
2188
2379
|
const subtitlesMenu = this.api.container.querySelector('.subtitles-menu');
|
|
2189
2380
|
if (!subtitlesMenu) return;
|
|
@@ -2219,22 +2410,22 @@ startBufferMonitoring() {
|
|
|
2219
2410
|
});
|
|
2220
2411
|
subtitlesMenu.appendChild(option);
|
|
2221
2412
|
});
|
|
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
2413
|
}
|
|
2236
2414
|
|
|
2237
|
-
//
|
|
2415
|
+
// SEMPRE aggiungi l'opzione Auto-generated (sia con che senza tracklist)
|
|
2416
|
+
const autoOption = document.createElement('div');
|
|
2417
|
+
autoOption.className = 'subtitles-option';
|
|
2418
|
+
autoOption.textContent = 'Auto-generated';
|
|
2419
|
+
autoOption.dataset.id = 'auto';
|
|
2420
|
+
autoOption.addEventListener('click', (e) => {
|
|
2421
|
+
e.stopPropagation();
|
|
2422
|
+
this.enableAutoCaptions();
|
|
2423
|
+
this.updateMenuSelection('auto');
|
|
2424
|
+
subtitlesMenu.classList.remove('show');
|
|
2425
|
+
});
|
|
2426
|
+
subtitlesMenu.appendChild(autoOption);
|
|
2427
|
+
|
|
2428
|
+
// Always add Auto-translate (both with and without tracklist)
|
|
2238
2429
|
const translateOption = document.createElement('div');
|
|
2239
2430
|
translateOption.className = 'subtitles-option translate-option';
|
|
2240
2431
|
translateOption.textContent = 'Auto-translate';
|
|
@@ -2524,27 +2715,69 @@ startBufferMonitoring() {
|
|
|
2524
2715
|
}
|
|
2525
2716
|
|
|
2526
2717
|
/**
|
|
2527
|
-
|
|
2528
|
-
|
|
2718
|
+
* Check initial caption state
|
|
2719
|
+
*/
|
|
2529
2720
|
checkInitialCaptionState() {
|
|
2530
2721
|
setTimeout(() => {
|
|
2531
2722
|
try {
|
|
2532
2723
|
const currentTrack = this.ytPlayer.getOption('captions', 'track');
|
|
2724
|
+
|
|
2533
2725
|
if (currentTrack && currentTrack.languageCode) {
|
|
2534
2726
|
this.captionsEnabled = true;
|
|
2535
|
-
|
|
2727
|
+
|
|
2728
|
+
// erify if translation is active
|
|
2729
|
+
if (currentTrack.translationLanguage) {
|
|
2730
|
+
this.currentTranslation = currentTrack.translationLanguage.languageCode;
|
|
2731
|
+
|
|
2732
|
+
// when translation is active, set currentCaption to null
|
|
2733
|
+
this.updateMenuSelection('auto');
|
|
2734
|
+
|
|
2735
|
+
// specify translation submenu selection after a short delay
|
|
2736
|
+
setTimeout(() => {
|
|
2737
|
+
const translationMenu = this.api.container.querySelector('.translation-menu');
|
|
2738
|
+
if (translationMenu) {
|
|
2739
|
+
translationMenu.querySelectorAll('.subtitles-option').forEach(option => {
|
|
2740
|
+
option.classList.remove('selected');
|
|
2741
|
+
});
|
|
2742
|
+
|
|
2743
|
+
const selectedTranslation = translationMenu.querySelector(`[data-id="translate-${this.currentTranslation}"]`);
|
|
2744
|
+
if (selectedTranslation) {
|
|
2745
|
+
selectedTranslation.classList.add('selected');
|
|
2746
|
+
}
|
|
2747
|
+
}
|
|
2748
|
+
}, 100);
|
|
2749
|
+
} else {
|
|
2750
|
+
// find current caption track index
|
|
2751
|
+
const captionIndex = this.availableCaptions.findIndex(
|
|
2752
|
+
cap => cap.languageCode === currentTrack.languageCode
|
|
2753
|
+
);
|
|
2754
|
+
|
|
2755
|
+
if (captionIndex >= 0) {
|
|
2756
|
+
this.currentCaption = currentTrack.languageCode;
|
|
2757
|
+
this.updateMenuSelection(`caption-${captionIndex}`);
|
|
2758
|
+
} else {
|
|
2759
|
+
// Se non trovato nella lista, è auto-generated
|
|
2760
|
+
this.updateMenuSelection('auto');
|
|
2761
|
+
}
|
|
2762
|
+
}
|
|
2763
|
+
|
|
2764
|
+
// activate button
|
|
2765
|
+
const subtitlesBtn = this.api.container.querySelector('.subtitles-btn');
|
|
2766
|
+
if (subtitlesBtn) {
|
|
2767
|
+
subtitlesBtn.classList.add('active');
|
|
2768
|
+
}
|
|
2536
2769
|
} else {
|
|
2537
2770
|
this.updateMenuSelection('off');
|
|
2538
2771
|
}
|
|
2539
2772
|
} catch (e) {
|
|
2540
2773
|
this.updateMenuSelection('off');
|
|
2541
2774
|
}
|
|
2542
|
-
},
|
|
2775
|
+
}, 2000);
|
|
2543
2776
|
}
|
|
2544
2777
|
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2778
|
+
/**
|
|
2779
|
+
* Monitor caption state
|
|
2780
|
+
*/
|
|
2548
2781
|
startCaptionStateMonitoring() {
|
|
2549
2782
|
if (this.captionStateCheckInterval) {
|
|
2550
2783
|
clearInterval(this.captionStateCheckInterval);
|
|
@@ -2554,7 +2787,6 @@ startBufferMonitoring() {
|
|
|
2554
2787
|
try {
|
|
2555
2788
|
const currentTrack = this.ytPlayer.getOption('captions', 'track');
|
|
2556
2789
|
const wasEnabled = this.captionsEnabled;
|
|
2557
|
-
|
|
2558
2790
|
this.captionsEnabled = !!(currentTrack && currentTrack.languageCode);
|
|
2559
2791
|
|
|
2560
2792
|
if (wasEnabled !== this.captionsEnabled) {
|
|
@@ -2562,8 +2794,24 @@ startBufferMonitoring() {
|
|
|
2562
2794
|
if (subtitlesBtn) {
|
|
2563
2795
|
if (this.captionsEnabled) {
|
|
2564
2796
|
subtitlesBtn.classList.add('active');
|
|
2797
|
+
|
|
2798
|
+
// update current caption/translation
|
|
2799
|
+
if (currentTrack.translationLanguage) {
|
|
2800
|
+
this.currentTranslation = currentTrack.translationLanguage.languageCode;
|
|
2801
|
+
this.updateMenuSelection(`translate-${this.currentTranslation}`);
|
|
2802
|
+
} else {
|
|
2803
|
+
const captionIndex = this.availableCaptions.findIndex(
|
|
2804
|
+
cap => cap.languageCode === currentTrack.languageCode
|
|
2805
|
+
);
|
|
2806
|
+
if (captionIndex >= 0) {
|
|
2807
|
+
this.updateMenuSelection(`caption-${captionIndex}`);
|
|
2808
|
+
} else {
|
|
2809
|
+
this.updateMenuSelection('auto');
|
|
2810
|
+
}
|
|
2811
|
+
}
|
|
2565
2812
|
} else {
|
|
2566
2813
|
subtitlesBtn.classList.remove('active');
|
|
2814
|
+
this.updateMenuSelection('off');
|
|
2567
2815
|
}
|
|
2568
2816
|
}
|
|
2569
2817
|
}
|