myetv-player 1.6.3 → 1.6.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.
@@ -1304,10 +1304,6 @@ createPlayerStructure() {
1304
1304
  this.createControls();
1305
1305
  this.createBrandLogo();
1306
1306
  this.detectPlaylist();
1307
-
1308
- if (this.options.showTitleOverlay) {
1309
- this.createTitleOverlay();
1310
- }
1311
1307
  this.createTopBar();
1312
1308
  }
1313
1309
 
@@ -1332,37 +1328,6 @@ createLoadingOverlay() {
1332
1328
  this.loadingOverlay = overlay;
1333
1329
  }
1334
1330
 
1335
- createTitleOverlay() {
1336
- const overlay = document.createElement('div');
1337
- overlay.className = 'title-overlay';
1338
- overlay.id = 'titleOverlay-' + this.getUniqueId();
1339
-
1340
- const titleText = document.createElement('h2');
1341
- titleText.className = 'title-text';
1342
- titleText.textContent = this.decodeHTMLEntities(this.options.videoTitle) || '';
1343
- overlay.appendChild(titleText);
1344
-
1345
- // add subtitles
1346
- if (this.options.videoSubtitle) {
1347
- const subtitleText = document.createElement('p');
1348
- subtitleText.className = 'subtitle-text';
1349
- subtitleText.textContent = this.decodeHTMLEntities(this.options.videoSubtitle);
1350
- overlay.appendChild(subtitleText);
1351
- }
1352
-
1353
- if (this.controls) {
1354
- this.container.insertBefore(overlay, this.controls);
1355
- } else {
1356
- this.container.appendChild(overlay);
1357
- }
1358
-
1359
- this.titleOverlay = overlay;
1360
-
1361
- if (this.options.persistentTitle && this.options.videoTitle) {
1362
- this.showTitleOverlay();
1363
- }
1364
- }
1365
-
1366
1331
  updateTooltips() {
1367
1332
  if (!this.controls) return;
1368
1333
 
@@ -1405,27 +1370,44 @@ setLanguage(lang) {
1405
1370
  return false;
1406
1371
  }
1407
1372
 
1373
+ /**
1374
+ * Set video title
1375
+ * @param {string} title - Video title
1376
+ * @returns {Object} this
1377
+ */
1408
1378
  setVideoTitle(title) {
1409
- this.options.videoTitle = title || '';
1379
+ this.options.videoTitle = title;
1410
1380
 
1411
- if (this.titleOverlay) {
1412
- const titleElement = this.titleOverlay.querySelector('.title-text');
1413
- if (titleElement) {
1414
- titleElement.textContent = this.decodeHTMLEntities(this.options.videoTitle);
1381
+ if (this.topBarTitle) {
1382
+ this.topBarTitle.textContent = this.decodeHTMLEntities(title);
1383
+
1384
+ // show top bar if title overlay is enabled
1385
+ if (title && this.options.showTitleOverlay) {
1386
+ const titleSection = this.topBar.querySelector('.top-bar-title');
1387
+ if (titleSection) {
1388
+ titleSection.style.display = '';
1389
+ }
1415
1390
  }
1391
+ } else if (this.topBar && title) {
1392
+ // create title section
1393
+ const titleSection = this.topBar.querySelector('.top-bar-title');
1394
+ if (!titleSection) {
1395
+ const newTitleSection = document.createElement('div');
1396
+ newTitleSection.className = 'top-bar-title';
1416
1397
 
1417
- if (title) {
1418
- this.showTitleOverlay();
1398
+ const titleElement = document.createElement('h3');
1399
+ titleElement.className = 'video-title';
1400
+ titleElement.textContent = this.decodeHTMLEntities(title);
1401
+ newTitleSection.appendChild(titleElement);
1419
1402
 
1420
- if (!this.options.persistentTitle) {
1421
- this.clearTitleTimeout();
1422
- this.titleTimeout = setTimeout(() => {
1423
- this.hideTitleOverlay();
1424
- }, 3000);
1425
- }
1403
+ const settingsControl = this.topBar.querySelector('.settings-control');
1404
+ this.topBar.insertBefore(newTitleSection, settingsControl);
1405
+
1406
+ this.topBarTitle = titleElement;
1426
1407
  }
1427
1408
  }
1428
1409
 
1410
+ if (this.options.debug) console.log('Video title set:', title);
1429
1411
  return this;
1430
1412
  }
1431
1413
 
@@ -1434,23 +1416,23 @@ getVideoTitle() {
1434
1416
  }
1435
1417
 
1436
1418
  setVideoSubtitle(subtitle) {
1437
- this.options.videoSubtitle = subtitle || '';
1438
-
1439
- if (this.titleOverlay) {
1440
- let subtitleElement = this.titleOverlay.querySelector('.subtitle-text');
1419
+ this.options.videoSubtitle = subtitle;
1441
1420
 
1442
- if (subtitle) {
1443
- if (!subtitleElement) {
1444
- subtitleElement = document.createElement('p');
1445
- subtitleElement.className = 'subtitle-text';
1446
- this.titleOverlay.appendChild(subtitleElement);
1447
- }
1448
- subtitleElement.textContent = subtitle;
1449
- } else if (subtitleElement) {
1450
- subtitleElement.remove();
1421
+ if (this.topBarSubtitle) {
1422
+ this.topBarSubtitle.textContent = subtitle;
1423
+ } else if (subtitle && this.topBar) {
1424
+ // Create subtitle element
1425
+ const titleSection = this.topBar.querySelector('.top-bar-title');
1426
+ if (titleSection) {
1427
+ const subtitleEl = document.createElement('span');
1428
+ subtitleEl.className = 'video-subtitle';
1429
+ subtitleEl.textContent = subtitle;
1430
+ titleSection.appendChild(subtitleEl);
1431
+ this.topBarSubtitle = subtitleEl;
1451
1432
  }
1452
1433
  }
1453
1434
 
1435
+ if (this.options.debug) console.log('Video subtitle set:', subtitle);
1454
1436
  return this;
1455
1437
  }
1456
1438
 
@@ -1458,41 +1440,65 @@ getVideoSubtitle() {
1458
1440
  return this.options.videoSubtitle;
1459
1441
  }
1460
1442
 
1443
+ /**
1444
+ * Set persistent title (always visible)
1445
+ * @param {boolean} persistent - If true, title stays visible
1446
+ * @returns {Object} this
1447
+ */
1461
1448
  setPersistentTitle(persistent) {
1462
1449
  this.options.persistentTitle = persistent;
1463
1450
 
1464
- if (this.titleOverlay && this.options.videoTitle) {
1451
+ if (this.topBar) {
1465
1452
  if (persistent) {
1466
- this.showTitleOverlay();
1467
- this.clearTitleTimeout();
1453
+ this.topBar.classList.add('persistent');
1468
1454
  } else {
1469
- this.titleOverlay.classList.remove('persistent');
1470
- if (this.titleOverlay.classList.contains('show')) {
1471
- this.clearTitleTimeout();
1472
- this.titleTimeout = setTimeout(() => {
1473
- this.hideTitleOverlay();
1474
- }, 3000);
1475
- }
1455
+ this.topBar.classList.remove('persistent');
1476
1456
  }
1477
1457
  }
1478
1458
 
1479
1459
  return this;
1480
1460
  }
1481
1461
 
1462
+ /**
1463
+ * Enable title overlay (shows top bar with title)
1464
+ * @returns {Object} this
1465
+ */
1482
1466
  enableTitleOverlay() {
1483
- if (!this.titleOverlay && !this.options.showTitleOverlay) {
1484
- this.options.showTitleOverlay = true;
1485
- this.createTitleOverlay();
1467
+ if (!this.topBar) {
1468
+ if (this.options.debug) console.warn('Top bar not available');
1469
+ return this;
1486
1470
  }
1471
+
1472
+ this.options.showTitleOverlay = true;
1473
+
1474
+ // show top bar
1475
+ if (this.options.videoTitle) {
1476
+ const titleSection = this.topBar.querySelector('.top-bar-title');
1477
+ if (titleSection) {
1478
+ titleSection.style.display = '';
1479
+ }
1480
+ }
1481
+
1482
+ if (this.options.debug) console.log('Title overlay enabled');
1487
1483
  return this;
1488
1484
  }
1489
1485
 
1486
+ /**
1487
+ * Disable title overlay (hides top bar)
1488
+ * @returns {Object} this
1489
+ */
1490
1490
  disableTitleOverlay() {
1491
- if (this.titleOverlay) {
1492
- this.titleOverlay.remove();
1493
- this.titleOverlay = null;
1494
- }
1491
+ if (!this.topBar) return this;
1492
+
1495
1493
  this.options.showTitleOverlay = false;
1494
+
1495
+ // hide top bar
1496
+ const titleSection = this.topBar.querySelector('.top-bar-title');
1497
+ if (titleSection) {
1498
+ titleSection.style.display = 'none';
1499
+ }
1500
+
1501
+ if (this.options.debug) console.log('Title overlay disabled');
1496
1502
  return this;
1497
1503
  }
1498
1504
 
@@ -1619,8 +1625,7 @@ setupMenuToggles() {
1619
1625
 
1620
1626
  /**
1621
1627
  * Create integrated top bar with settings menu
1622
- * Netflix/Prime Video style top bar with title and settings on opposite sides
1623
- * This does NOT replace the existing title-overlay system
1628
+ * Respects showTitleOverlay, videoTitle, videoSubtitle, persistentTitle options
1624
1629
  * @returns {void}
1625
1630
  */
1626
1631
  createTopBar() {
@@ -1629,49 +1634,45 @@ createTopBar() {
1629
1634
  // Create top bar element
1630
1635
  const topBar = document.createElement('div');
1631
1636
  topBar.className = 'player-top-bar';
1632
- topBar.id = `topBar_${this.getUniqueId()}`;
1637
+ topBar.id = `topBar${this.getUniqueId()}`;
1633
1638
 
1634
- // Left section: Title (if enabled)
1635
- if (this.options.showTitleOverlay && this.options.videoTitle) {
1636
- const titleSection = document.createElement('div');
1637
- titleSection.className = 'top-bar-title';
1639
+ // Left section - Title (ALWAYS create structure)
1640
+ const titleSection = document.createElement('div');
1641
+ titleSection.className = 'top-bar-title';
1638
1642
 
1639
- // Main title
1640
- const titleElement = document.createElement('h3');
1641
- titleElement.className = 'video-title';
1642
- titleElement.textContent = this.decodeHTMLEntities(this.options.videoTitle);
1643
- titleSection.appendChild(titleElement);
1643
+ // Main title
1644
+ const titleElement = document.createElement('h3');
1645
+ titleElement.className = 'video-title';
1646
+ titleElement.textContent = this.options.videoTitle ? this.decodeHTMLEntities(this.options.videoTitle) : '';
1647
+ titleSection.appendChild(titleElement);
1644
1648
 
1645
- // Optional subtitle
1646
- if (this.options.videoSubtitle) {
1647
- const subtitleElement = document.createElement('span');
1648
- subtitleElement.className = 'video-subtitle';
1649
- subtitleElement.textContent = this.decodeHTMLEntities(this.options.videoSubtitle);
1650
- titleSection.appendChild(subtitleElement);
1651
- }
1649
+ // Optional subtitle (if present)
1650
+ if (this.options.videoSubtitle) {
1651
+ const subtitleElement = document.createElement('span');
1652
+ subtitleElement.className = 'video-subtitle';
1653
+ subtitleElement.textContent = this.decodeHTMLEntities(this.options.videoSubtitle);
1654
+ titleSection.appendChild(subtitleElement);
1655
+ }
1652
1656
 
1653
- topBar.appendChild(titleSection);
1654
- } else {
1655
- // Spacer if no title
1656
- const spacer = document.createElement('div');
1657
- spacer.className = 'top-bar-spacer';
1658
- topBar.appendChild(spacer);
1657
+ // Hide title section if showTitleOverlay is false
1658
+ if (!this.options.showTitleOverlay || !this.options.videoTitle) {
1659
+ titleSection.style.display = 'none';
1659
1660
  }
1660
1661
 
1661
- // Right section: Settings control
1662
+ topBar.appendChild(titleSection);
1663
+
1664
+ // Right section - Settings control
1662
1665
  const settingsControl = document.createElement('div');
1663
1666
  settingsControl.className = 'settings-control settings-top-bar';
1664
1667
 
1665
1668
  // Settings button
1666
1669
  const settingsBtn = document.createElement('button');
1667
1670
  settingsBtn.className = 'control-btn settings-btn';
1668
- settingsBtn.setAttribute('data-tooltip', 'settings_menu'); // ✅ Correct: underscore
1671
+ settingsBtn.setAttribute('data-tooltip', 'settingsmenu');
1669
1672
 
1670
1673
  const icon = document.createElement('span');
1671
1674
  icon.className = 'icon';
1672
- icon.innerHTML = `<svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor">
1673
- <path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"/>
1674
- </svg>`;
1675
+ icon.innerHTML = `<svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor"><path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"/></svg>`;
1675
1676
  settingsBtn.appendChild(icon);
1676
1677
 
1677
1678
  // Settings menu
@@ -1682,6 +1683,11 @@ createTopBar() {
1682
1683
  settingsControl.appendChild(settingsMenu);
1683
1684
  topBar.appendChild(settingsControl);
1684
1685
 
1686
+ // Add persistent class if persistentTitle is enabled
1687
+ if (this.options.persistentTitle) {
1688
+ topBar.classList.add('persistent');
1689
+ }
1690
+
1685
1691
  // Insert top bar as first child in container
1686
1692
  this.container.insertBefore(topBar, this.container.firstChild);
1687
1693
 
@@ -1691,7 +1697,11 @@ createTopBar() {
1691
1697
  this.topBarSubtitle = topBar.querySelector('.video-subtitle');
1692
1698
 
1693
1699
  if (this.options.debug) {
1694
- console.log('Top bar created with integrated settings');
1700
+ console.log('Top bar created with integrated settings', {
1701
+ showTitle: this.options.showTitleOverlay,
1702
+ persistent: this.options.persistentTitle,
1703
+ opacity: this.options.titleOverlayOpacity
1704
+ });
1695
1705
  }
1696
1706
  }
1697
1707
 
@@ -3501,10 +3511,8 @@ resetAutoHideTimer() {
3501
3511
  return;
3502
3512
  }
3503
3513
 
3504
- // Only block timer if video is paused AND user explicitly paused it
3505
- // Don't block if paused due to autoplay blocked (currentTime === 0 and no interaction yet)
3514
+ // Allow timer if video is paused at start (autoplay blocked)
3506
3515
  if (this.video && this.video.paused) {
3507
- // Allow timer if this is initial pause (autoplay blocked scenario)
3508
3516
  const isInitialPause = this.video.currentTime === 0 && !this.video.ended;
3509
3517
 
3510
3518
  if (!isInitialPause) {
@@ -3513,17 +3521,21 @@ resetAutoHideTimer() {
3513
3521
  }
3514
3522
 
3515
3523
  if (this.autoHideDebug && this.options.debug) {
3516
- console.log('Video paused but at start - allowing timer (autoplay blocked scenario)');
3524
+ console.log('Video paused but at start - allowing timer (autoplay blocked)');
3517
3525
  }
3518
3526
  }
3519
3527
 
3520
- // Start timer...
3528
+ // Start timer
3521
3529
  this.autoHideTimer = setTimeout(() => {
3522
- if (this.autoHideDebug && this.options.debug) console.log(`Timer expired after ${this.options.autoHideDelay}ms - hiding controls`);
3530
+ if (this.autoHideDebug && this.options.debug) {
3531
+ console.log(`Timer expired after ${this.options.autoHideDelay}ms - hiding controls`);
3532
+ }
3523
3533
  this.hideControlsNow();
3524
3534
  }, this.options.autoHideDelay);
3525
3535
 
3526
- if (this.autoHideDebug && this.options.debug) console.log(`Auto-hide timer started (${this.options.autoHideDelay}ms)`);
3536
+ if (this.autoHideDebug && this.options.debug) {
3537
+ console.log(`Auto-hide timer started (${this.options.autoHideDelay}ms)`);
3538
+ }
3527
3539
  }
3528
3540
 
3529
3541
  showControlsNow() {
@@ -3617,9 +3629,7 @@ clearControlsTimeout() {
3617
3629
 
3618
3630
  // Default controlbar styles injection
3619
3631
  injectDefaultControlbarStyles() {
3620
- if (document.getElementById('default-controlbar-styles')) {
3621
- return;
3622
- }
3632
+ if (document.getElementById('default-controlbar-styles')) return;
3623
3633
 
3624
3634
  const controlBarOpacity = Math.max(0, Math.min(1, this.options.controlBarOpacity));
3625
3635
  const titleOverlayOpacity = Math.max(0, Math.min(1, this.options.titleOverlayOpacity));
@@ -3641,7 +3651,7 @@ injectDefaultControlbarStyles() {
3641
3651
  min-height: 60px;
3642
3652
  padding-bottom: 10px;
3643
3653
  }
3644
-
3654
+
3645
3655
  .video-wrapper:not(.youtube-active):not(.vimeo-active):not(.facebook-active) .title-overlay {
3646
3656
  background: linear-gradient(
3647
3657
  to bottom,
@@ -3656,8 +3666,12 @@ injectDefaultControlbarStyles() {
3656
3666
  min-height: 80px;
3657
3667
  padding-top: 20px;
3658
3668
  }
3669
+
3670
+ /* ✅ NEW: Set CSS custom property for top bar opacity */
3671
+ .video-wrapper {
3672
+ --player-topbar-opacity: ${titleOverlayOpacity};
3673
+ }
3659
3674
  `;
3660
-
3661
3675
  document.head.appendChild(style);
3662
3676
  }
3663
3677
 
@@ -6620,35 +6634,35 @@ bindChapterEvents() {
6620
6634
  }
6621
6635
 
6622
6636
  /**
6623
- * Update chapter name in title overlay dynamically
6637
+ * Update chapter name in top bar subtitle dynamically
6638
+ * Shows current chapter title as subtitle in the top bar
6624
6639
  */
6625
6640
  updateChapterInTitleOverlay() {
6626
6641
  if (!this.video || !this.chapters || this.chapters.length === 0) return;
6627
6642
 
6628
- const titleOverlay = this.container ? this.container.querySelector('.title-overlay') : null;
6629
- if (!titleOverlay) return;
6630
-
6631
- // Find or create chapter name element
6632
- let chapterElement = titleOverlay.querySelector('.chapter-name');
6633
- if (!chapterElement) {
6634
- chapterElement = document.createElement('div');
6635
- chapterElement.className = 'chapter-name';
6636
- chapterElement.style.cssText = `
6637
- font-size: 13px;
6638
- font-weight: 500;
6639
- color: rgba(255, 255, 255, 0.9);
6640
- margin-top: 6px;
6641
- max-width: 400px;
6642
- overflow: hidden;
6643
- text-overflow: ellipsis;
6644
- white-space: nowrap;
6645
- `;
6646
- titleOverlay.appendChild(chapterElement);
6643
+ // Use topBar instead of old titleOverlay
6644
+ if (!this.topBar) return;
6645
+
6646
+ // Find or create subtitle element in top bar
6647
+ let subtitleElement = this.topBar.querySelector('.video-subtitle');
6648
+
6649
+ if (!subtitleElement) {
6650
+ // Create subtitle element if it doesn't exist
6651
+ const titleSection = this.topBar.querySelector('.top-bar-title');
6652
+ if (!titleSection) return;
6653
+
6654
+ subtitleElement = document.createElement('span');
6655
+ subtitleElement.className = 'video-subtitle';
6656
+ titleSection.appendChild(subtitleElement);
6657
+
6658
+ // Save reference
6659
+ this.topBarSubtitle = subtitleElement;
6647
6660
  }
6648
6661
 
6649
6662
  // Find current chapter
6650
6663
  const currentTime = this.video.currentTime;
6651
6664
  let currentChapter = null;
6665
+
6652
6666
  for (let i = this.chapters.length - 1; i >= 0; i--) {
6653
6667
  if (currentTime >= this.chapters[i].time) {
6654
6668
  currentChapter = this.chapters[i];
@@ -6656,12 +6670,22 @@ updateChapterInTitleOverlay() {
6656
6670
  }
6657
6671
  }
6658
6672
 
6659
- // Update or hide chapter name
6673
+ // Update subtitle with chapter title or hide if no chapter
6660
6674
  if (currentChapter) {
6661
- chapterElement.textContent = currentChapter.title;
6662
- chapterElement.style.display = 'block';
6675
+ subtitleElement.textContent = currentChapter.title;
6676
+ subtitleElement.style.display = 'block';
6663
6677
  } else {
6664
- chapterElement.style.display = 'none';
6678
+ // Se non c'è un capitolo attivo, mostra il sottotitolo originale o nascondi
6679
+ if (this.options.videoSubtitle) {
6680
+ subtitleElement.textContent = this.options.videoSubtitle;
6681
+ subtitleElement.style.display = 'block';
6682
+ } else {
6683
+ subtitleElement.style.display = 'none';
6684
+ }
6685
+ }
6686
+
6687
+ if (this.options.debug) {
6688
+ console.log('Chapter overlay updated:', currentChapter ? currentChapter.title : 'No chapter');
6665
6689
  }
6666
6690
  }
6667
6691