myetv-player 1.6.2 → 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.
@@ -1170,13 +1170,31 @@ markPlayerReady() {
1170
1170
  }
1171
1171
 
1172
1172
  if (this.options.autoplay) {
1173
- if (this.options.debug) console.log('🎬 Autoplay enabled');
1173
+ if (this.options.debug) console.log('Autoplay enabled');
1174
1174
  setTimeout(() => {
1175
- this.video.play().catch(error => {
1176
- if (this.options.debug) console.warn('⚠️ Autoplay blocked:', error);
1175
+ this.video.play()
1176
+ .then(() => {
1177
+
1178
+ if (this.options.debug) console.log('Autoplay started successfully');
1179
+ })
1180
+ .catch(error => {
1181
+
1182
+ if (this.options.debug) console.warn('Autoplay blocked', error);
1183
+
1184
+ if (this.options.autoHide && this.autoHideInitialized) {
1185
+
1186
+ this.showControlsNow();
1187
+
1188
+ this.resetAutoHideTimer();
1189
+
1190
+ if (this.options.debug) {
1191
+ console.log('Auto-hide timer started (autoplay blocked - video paused)');
1192
+ }
1193
+ }
1177
1194
  });
1178
1195
  }, 100);
1179
1196
  }
1197
+
1180
1198
  }, 200);
1181
1199
 
1182
1200
  }, 100);
@@ -1200,10 +1218,7 @@ createPlayerStructure() {
1200
1218
  this.createControls();
1201
1219
  this.createBrandLogo();
1202
1220
  this.detectPlaylist();
1203
-
1204
- if (this.options.showTitleOverlay) {
1205
- this.createTitleOverlay();
1206
- }
1221
+ this.createTopBar();
1207
1222
  }
1208
1223
 
1209
1224
  createInitialLoading() {
@@ -1227,51 +1242,29 @@ createLoadingOverlay() {
1227
1242
  this.loadingOverlay = overlay;
1228
1243
  }
1229
1244
 
1230
- createTitleOverlay() {
1231
- const overlay = document.createElement('div');
1232
- overlay.className = 'title-overlay';
1233
- overlay.id = 'titleOverlay-' + this.getUniqueId();
1234
-
1235
- const titleText = document.createElement('h2');
1236
- titleText.className = 'title-text';
1237
- titleText.textContent = this.decodeHTMLEntities(this.options.videoTitle) || '';
1238
- overlay.appendChild(titleText);
1239
-
1240
- if (this.options.videoSubtitle) {
1241
- const subtitleText = document.createElement('p');
1242
- subtitleText.className = 'subtitle-text';
1243
- subtitleText.textContent = this.decodeHTMLEntities(this.options.videoSubtitle);
1244
- overlay.appendChild(subtitleText);
1245
- }
1246
-
1247
- if (this.controls) {
1248
- this.container.insertBefore(overlay, this.controls);
1249
- } else {
1250
- this.container.appendChild(overlay);
1251
- }
1252
-
1253
- this.titleOverlay = overlay;
1254
-
1255
- if (this.options.persistentTitle && this.options.videoTitle) {
1256
- this.showTitleOverlay();
1257
- }
1258
- }
1259
-
1260
1245
  updateTooltips() {
1261
1246
  if (!this.controls) return;
1262
1247
 
1263
1248
  try {
1249
+
1264
1250
  this.controls.querySelectorAll('[data-tooltip]').forEach(element => {
1265
1251
  const key = element.getAttribute('data-tooltip');
1266
1252
  element.title = this.t(key);
1267
1253
  });
1268
1254
 
1255
+ if (this.topBar) {
1256
+ this.topBar.querySelectorAll('[data-tooltip]').forEach(element => {
1257
+ const key = element.getAttribute('data-tooltip');
1258
+ element.title = this.t(key);
1259
+ });
1260
+ }
1261
+
1269
1262
  const autoOption = this.controls.querySelector('.quality-option[data-quality="auto"]');
1270
1263
  if (autoOption) {
1271
1264
  autoOption.textContent = this.t('auto');
1272
1265
  }
1273
1266
  } catch (error) {
1274
- if (this.options.debug) console.warn('Errore aggiornamento tooltip:', error);
1267
+ if (this.options.debug) console.warn('Tooltip update error', error);
1275
1268
  }
1276
1269
  }
1277
1270
 
@@ -1290,26 +1283,37 @@ setLanguage(lang) {
1290
1283
  }
1291
1284
 
1292
1285
  setVideoTitle(title) {
1293
- this.options.videoTitle = title || '';
1286
+ this.options.videoTitle = title;
1294
1287
 
1295
- if (this.titleOverlay) {
1296
- const titleElement = this.titleOverlay.querySelector('.title-text');
1297
- if (titleElement) {
1298
- titleElement.textContent = this.decodeHTMLEntities(this.options.videoTitle);
1288
+ if (this.topBarTitle) {
1289
+ this.topBarTitle.textContent = this.decodeHTMLEntities(title);
1290
+
1291
+ if (title && this.options.showTitleOverlay) {
1292
+ const titleSection = this.topBar.querySelector('.top-bar-title');
1293
+ if (titleSection) {
1294
+ titleSection.style.display = '';
1295
+ }
1299
1296
  }
1297
+ } else if (this.topBar && title) {
1300
1298
 
1301
- if (title) {
1302
- this.showTitleOverlay();
1299
+ const titleSection = this.topBar.querySelector('.top-bar-title');
1300
+ if (!titleSection) {
1301
+ const newTitleSection = document.createElement('div');
1302
+ newTitleSection.className = 'top-bar-title';
1303
1303
 
1304
- if (!this.options.persistentTitle) {
1305
- this.clearTitleTimeout();
1306
- this.titleTimeout = setTimeout(() => {
1307
- this.hideTitleOverlay();
1308
- }, 3000);
1309
- }
1304
+ const titleElement = document.createElement('h3');
1305
+ titleElement.className = 'video-title';
1306
+ titleElement.textContent = this.decodeHTMLEntities(title);
1307
+ newTitleSection.appendChild(titleElement);
1308
+
1309
+ const settingsControl = this.topBar.querySelector('.settings-control');
1310
+ this.topBar.insertBefore(newTitleSection, settingsControl);
1311
+
1312
+ this.topBarTitle = titleElement;
1310
1313
  }
1311
1314
  }
1312
1315
 
1316
+ if (this.options.debug) console.log('Video title set:', title);
1313
1317
  return this;
1314
1318
  }
1315
1319
 
@@ -1318,23 +1322,23 @@ getVideoTitle() {
1318
1322
  }
1319
1323
 
1320
1324
  setVideoSubtitle(subtitle) {
1321
- this.options.videoSubtitle = subtitle || '';
1325
+ this.options.videoSubtitle = subtitle;
1322
1326
 
1323
- if (this.titleOverlay) {
1324
- let subtitleElement = this.titleOverlay.querySelector('.subtitle-text');
1327
+ if (this.topBarSubtitle) {
1328
+ this.topBarSubtitle.textContent = subtitle;
1329
+ } else if (subtitle && this.topBar) {
1325
1330
 
1326
- if (subtitle) {
1327
- if (!subtitleElement) {
1328
- subtitleElement = document.createElement('p');
1329
- subtitleElement.className = 'subtitle-text';
1330
- this.titleOverlay.appendChild(subtitleElement);
1331
- }
1332
- subtitleElement.textContent = subtitle;
1333
- } else if (subtitleElement) {
1334
- subtitleElement.remove();
1331
+ const titleSection = this.topBar.querySelector('.top-bar-title');
1332
+ if (titleSection) {
1333
+ const subtitleEl = document.createElement('span');
1334
+ subtitleEl.className = 'video-subtitle';
1335
+ subtitleEl.textContent = subtitle;
1336
+ titleSection.appendChild(subtitleEl);
1337
+ this.topBarSubtitle = subtitleEl;
1335
1338
  }
1336
1339
  }
1337
1340
 
1341
+ if (this.options.debug) console.log('Video subtitle set:', subtitle);
1338
1342
  return this;
1339
1343
  }
1340
1344
 
@@ -1345,18 +1349,11 @@ getVideoSubtitle() {
1345
1349
  setPersistentTitle(persistent) {
1346
1350
  this.options.persistentTitle = persistent;
1347
1351
 
1348
- if (this.titleOverlay && this.options.videoTitle) {
1352
+ if (this.topBar) {
1349
1353
  if (persistent) {
1350
- this.showTitleOverlay();
1351
- this.clearTitleTimeout();
1354
+ this.topBar.classList.add('persistent');
1352
1355
  } else {
1353
- this.titleOverlay.classList.remove('persistent');
1354
- if (this.titleOverlay.classList.contains('show')) {
1355
- this.clearTitleTimeout();
1356
- this.titleTimeout = setTimeout(() => {
1357
- this.hideTitleOverlay();
1358
- }, 3000);
1359
- }
1356
+ this.topBar.classList.remove('persistent');
1360
1357
  }
1361
1358
  }
1362
1359
 
@@ -1364,19 +1361,35 @@ setPersistentTitle(persistent) {
1364
1361
  }
1365
1362
 
1366
1363
  enableTitleOverlay() {
1367
- if (!this.titleOverlay && !this.options.showTitleOverlay) {
1364
+ if (!this.topBar) {
1365
+ if (this.options.debug) console.warn('Top bar not available');
1366
+ return this;
1367
+ }
1368
+
1368
1369
  this.options.showTitleOverlay = true;
1369
- this.createTitleOverlay();
1370
+
1371
+ if (this.options.videoTitle) {
1372
+ const titleSection = this.topBar.querySelector('.top-bar-title');
1373
+ if (titleSection) {
1374
+ titleSection.style.display = '';
1375
+ }
1370
1376
  }
1377
+
1378
+ if (this.options.debug) console.log('Title overlay enabled');
1371
1379
  return this;
1372
1380
  }
1373
1381
 
1374
1382
  disableTitleOverlay() {
1375
- if (this.titleOverlay) {
1376
- this.titleOverlay.remove();
1377
- this.titleOverlay = null;
1378
- }
1383
+ if (!this.topBar) return this;
1384
+
1379
1385
  this.options.showTitleOverlay = false;
1386
+
1387
+ const titleSection = this.topBar.querySelector('.top-bar-title');
1388
+ if (titleSection) {
1389
+ titleSection.style.display = 'none';
1390
+ }
1391
+
1392
+ if (this.options.debug) console.log('Title overlay disabled');
1380
1393
  return this;
1381
1394
  }
1382
1395
 
@@ -1418,6 +1431,9 @@ initializeElements() {
1418
1431
  this.qualityMenu = this.controls?.querySelector('.quality-menu');
1419
1432
  this.subtitlesMenu = this.controls?.querySelector('.subtitles-menu');
1420
1433
 
1434
+ this.settingsBtn = this.container?.querySelector('.settings-btn');
1435
+ this.settingsMenu = this.container?.querySelector('.settings-menu');
1436
+
1421
1437
  if (this.progressHandle && this.options.seekHandleShape) {
1422
1438
  this.setSeekHandleShape(this.options.seekHandleShape);
1423
1439
  }
@@ -1495,6 +1511,72 @@ setupMenuToggles() {
1495
1511
  }
1496
1512
  }
1497
1513
 
1514
+ createTopBar() {
1515
+ if (!this.container) return;
1516
+
1517
+ const topBar = document.createElement('div');
1518
+ topBar.className = 'player-top-bar';
1519
+ topBar.id = `topBar${this.getUniqueId()}`;
1520
+
1521
+ const titleSection = document.createElement('div');
1522
+ titleSection.className = 'top-bar-title';
1523
+
1524
+ const titleElement = document.createElement('h3');
1525
+ titleElement.className = 'video-title';
1526
+ titleElement.textContent = this.options.videoTitle ? this.decodeHTMLEntities(this.options.videoTitle) : '';
1527
+ titleSection.appendChild(titleElement);
1528
+
1529
+ if (this.options.videoSubtitle) {
1530
+ const subtitleElement = document.createElement('span');
1531
+ subtitleElement.className = 'video-subtitle';
1532
+ subtitleElement.textContent = this.decodeHTMLEntities(this.options.videoSubtitle);
1533
+ titleSection.appendChild(subtitleElement);
1534
+ }
1535
+
1536
+ if (!this.options.showTitleOverlay || !this.options.videoTitle) {
1537
+ titleSection.style.display = 'none';
1538
+ }
1539
+
1540
+ topBar.appendChild(titleSection);
1541
+
1542
+ const settingsControl = document.createElement('div');
1543
+ settingsControl.className = 'settings-control settings-top-bar';
1544
+
1545
+ const settingsBtn = document.createElement('button');
1546
+ settingsBtn.className = 'control-btn settings-btn';
1547
+ settingsBtn.setAttribute('data-tooltip', 'settingsmenu');
1548
+
1549
+ const icon = document.createElement('span');
1550
+ icon.className = 'icon';
1551
+ 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>`;
1552
+ settingsBtn.appendChild(icon);
1553
+
1554
+ const settingsMenu = document.createElement('div');
1555
+ settingsMenu.className = 'settings-menu';
1556
+
1557
+ settingsControl.appendChild(settingsBtn);
1558
+ settingsControl.appendChild(settingsMenu);
1559
+ topBar.appendChild(settingsControl);
1560
+
1561
+ if (this.options.persistentTitle) {
1562
+ topBar.classList.add('persistent');
1563
+ }
1564
+
1565
+ this.container.insertBefore(topBar, this.container.firstChild);
1566
+
1567
+ this.topBar = topBar;
1568
+ this.topBarTitle = topBar.querySelector('.video-title');
1569
+ this.topBarSubtitle = topBar.querySelector('.video-subtitle');
1570
+
1571
+ if (this.options.debug) {
1572
+ console.log('Top bar created with integrated settings', {
1573
+ showTitle: this.options.showTitleOverlay,
1574
+ persistent: this.options.persistentTitle,
1575
+ opacity: this.options.titleOverlayOpacity
1576
+ });
1577
+ }
1578
+ }
1579
+
1498
1580
  restartVideo() {
1499
1581
  if (!this.video) return this;
1500
1582
 
@@ -2606,12 +2688,30 @@ addEventListener(eventType, callback) {
2606
2688
  this.pauseIcon.classList.remove('hidden');
2607
2689
  }
2608
2690
 
2691
+ if (this.options.autoHide && this.autoHideInitialized) {
2692
+ if (this.options.debug) console.log('Video playing - reset auto-hide timer');
2693
+ this.showControlsNow();
2694
+ this.resetAutoHideTimer();
2695
+ }
2696
+
2609
2697
  this.triggerEvent('playing', {
2610
2698
  currentTime: this.getCurrentTime(),
2611
2699
  duration: this.getDuration()
2612
2700
  });
2613
2701
  });
2614
2702
 
2703
+ this.video.addEventListener('pause', () => {
2704
+ if (this.options.autoHide && this.autoHideInitialized) {
2705
+ if (this.options.debug) console.log('Video paused - show controls and cancel timer');
2706
+ this.showControlsNow();
2707
+
2708
+ if (this.autoHideTimer) {
2709
+ clearTimeout(this.autoHideTimer);
2710
+ this.autoHideTimer = null;
2711
+ }
2712
+ }
2713
+ });
2714
+
2615
2715
  this.video.addEventListener('waiting', () => {
2616
2716
  if (!this.isChangingQuality) {
2617
2717
  this.showLoading();
@@ -3061,30 +3161,35 @@ resetAutoHideTimer() {
3061
3161
  this.autoHideTimer = null;
3062
3162
  }
3063
3163
 
3064
- const isTouchDevice = 'ontouchstart' in window || navigator.maxTouchPoints > 0;
3164
+ const isTouchDevice = ('ontouchstart' in window) || (navigator.maxTouchPoints > 0);
3165
+
3065
3166
  if (this.mouseOverControls && !isTouchDevice) {
3066
- if (this.autoHideDebug) {
3067
- if (this.options.debug) console.log('Not starting timer - mouse on controls');
3068
- }
3167
+ if (this.autoHideDebug && this.options.debug) console.log('Not starting timer - mouse on controls');
3069
3168
  return;
3070
3169
  }
3071
3170
 
3072
3171
  if (this.video && this.video.paused) {
3073
- if (this.autoHideDebug) {
3074
- if (this.options.debug) console.log('Not starting timer - video paused');
3075
- }
3172
+ const isInitialPause = this.video.currentTime === 0 && !this.video.ended;
3173
+
3174
+ if (!isInitialPause) {
3175
+ if (this.autoHideDebug && this.options.debug) console.log('Not starting timer - video paused by user');
3076
3176
  return;
3077
3177
  }
3078
3178
 
3179
+ if (this.autoHideDebug && this.options.debug) {
3180
+ console.log('Video paused but at start - allowing timer (autoplay blocked)');
3181
+ }
3182
+ }
3183
+
3079
3184
  this.autoHideTimer = setTimeout(() => {
3080
- if (this.autoHideDebug) {
3081
- if (this.options.debug) console.log(`Timer expired after ${this.options.autoHideDelay}ms - nascondo controlli`);
3185
+ if (this.autoHideDebug && this.options.debug) {
3186
+ console.log(`Timer expired after ${this.options.autoHideDelay}ms - hiding controls`);
3082
3187
  }
3083
3188
  this.hideControlsNow();
3084
3189
  }, this.options.autoHideDelay);
3085
3190
 
3086
- if (this.autoHideDebug) {
3087
- if (this.options.debug) console.log(`Auto-hide timer started: ${this.options.autoHideDelay}ms`);
3191
+ if (this.autoHideDebug && this.options.debug) {
3192
+ console.log(`Auto-hide timer started (${this.options.autoHideDelay}ms)`);
3088
3193
  }
3089
3194
  }
3090
3195
 
@@ -3108,7 +3213,7 @@ showControlsNow() {
3108
3213
 
3109
3214
  this.showCursor();
3110
3215
 
3111
- if (this.autoHideDebug && this.options.debug) console.log('Controls shown');
3216
+ if (this.autoHideDebug && this.options.debug) console.log('Controls shown');
3112
3217
  }
3113
3218
  }
3114
3219
 
@@ -3144,7 +3249,7 @@ hideControlsNow() {
3144
3249
 
3145
3250
  this.hideCursor();
3146
3251
 
3147
- if (this.autoHideDebug && this.options.debug) console.log('Controls hidden');
3252
+ if (this.autoHideDebug && this.options.debug) console.log('Controls hidden');
3148
3253
  }
3149
3254
  }
3150
3255
 
@@ -3169,9 +3274,7 @@ clearControlsTimeout() {
3169
3274
  }
3170
3275
 
3171
3276
  injectDefaultControlbarStyles() {
3172
- if (document.getElementById('default-controlbar-styles')) {
3173
- return;
3174
- }
3277
+ if (document.getElementById('default-controlbar-styles')) return;
3175
3278
 
3176
3279
  const controlBarOpacity = Math.max(0, Math.min(1, this.options.controlBarOpacity));
3177
3280
  const titleOverlayOpacity = Math.max(0, Math.min(1, this.options.titleOverlayOpacity));
@@ -3193,7 +3296,7 @@ injectDefaultControlbarStyles() {
3193
3296
  min-height: 60px;
3194
3297
  padding-bottom: 10px;
3195
3298
  }
3196
-
3299
+
3197
3300
  .video-wrapper:not(.youtube-active):not(.vimeo-active):not(.facebook-active) .title-overlay {
3198
3301
  background: linear-gradient(
3199
3302
  to bottom,
@@ -3208,8 +3311,11 @@ injectDefaultControlbarStyles() {
3208
3311
  min-height: 80px;
3209
3312
  padding-top: 20px;
3210
3313
  }
3211
- `;
3212
3314
 
3315
+ .video-wrapper {
3316
+ --player-topbar-opacity: ${titleOverlayOpacity};
3317
+ }
3318
+ `;
3213
3319
  document.head.appendChild(style);
3214
3320
  }
3215
3321
 
@@ -3388,10 +3494,9 @@ createControls() {
3388
3494
  </div>
3389
3495
 
3390
3496
  <div class="time-display">
3391
- <span class="current-time">0:00</span>
3392
- <span>/</span>
3393
- <span class="duration">0:00</span>
3394
- </div>
3497
+ <span class="current-time">00:00</span>
3498
+ <span class="duration">00:00</span>
3499
+ </div>
3395
3500
  </div>
3396
3501
 
3397
3502
  <div class="controls-right">
@@ -3402,13 +3507,6 @@ createControls() {
3402
3507
  <span class="icon"><svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor"><path d="M12.5 4v8l-7-4zm-8 0v8l7-4z"/></svg></span>
3403
3508
  </button>
3404
3509
 
3405
- <div class="settings-control">
3406
- <button class="control-btn settings-btn" data-tooltip="settings_menu">
3407
- <span class="icon"><svg viewBox="0 0 24 24" width="16" height="16" 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></span>
3408
- </button>
3409
- <div class="settings-menu"></div>
3410
- </div>
3411
-
3412
3510
  ${(this.options.showQualitySelector && this.originalSources && this.originalSources.length > 1) || this.options.adaptiveQualityControl ? `
3413
3511
  <div class="quality-control">
3414
3512
  <button class="control-btn quality-btn" data-tooltip="video_quality">
@@ -3519,7 +3617,9 @@ checkScreenSize() {
3519
3617
  }
3520
3618
 
3521
3619
  updateSettingsMenuVisibility() {
3522
- const settingsControl = this.controls?.querySelector('.settings-control');
3620
+
3621
+ const settingsControl = this.container?.querySelector('.settings-control');
3622
+
3523
3623
  if (!settingsControl) return;
3524
3624
 
3525
3625
  settingsControl.style.display = 'block';
@@ -3528,23 +3628,28 @@ updateSettingsMenuVisibility() {
3528
3628
 
3529
3629
  const speedControl = this.controls.querySelector('.speed-control');
3530
3630
  const subtitlesControl = this.controls.querySelector('.subtitles-control');
3631
+
3531
3632
  if (speedControl) speedControl.style.display = 'none';
3532
3633
  if (subtitlesControl) subtitlesControl.style.display = 'none';
3533
3634
  }
3534
3635
 
3535
3636
  populateSettingsMenu() {
3536
- const settingsMenu = this.controls?.querySelector('.settings-menu');
3637
+
3638
+ const settingsMenu = this.container?.querySelector('.settings-menu');
3639
+
3537
3640
  if (!settingsMenu) return;
3538
3641
 
3539
3642
  let menuHTML = '';
3540
3643
 
3541
3644
  if (this.options.showSpeedControl) {
3542
- const speedLabel = this.t('playback_speed') || 'Playback Speed';
3645
+ const speedLabel = this.t('playback_speed');
3543
3646
  const currentSpeed = this.video ? this.video.playbackRate : 1;
3544
- menuHTML += `<div class="settings-expandable-wrapper">
3545
- <div class="settings-option expandable-trigger" data-action="speed-expand">
3647
+
3648
+ menuHTML += `
3649
+ <div class="settings-expandable-wrapper">
3650
+ <div class="settings-option expandable-trigger" data-action="speed_expand">
3546
3651
  <span class="settings-option-label">${speedLabel} <strong>${currentSpeed}x</strong></span>
3547
- <span class="expand-arrow">▶</span>
3652
+ <span class="expand-arrow">▼</span>
3548
3653
  </div>
3549
3654
  <div class="settings-expandable-content" style="display: none;">`;
3550
3655
 
@@ -3553,22 +3658,26 @@ populateSettingsMenu() {
3553
3658
  const isActive = Math.abs(speed - currentSpeed) < 0.01;
3554
3659
  menuHTML += `<div class="settings-suboption ${isActive ? 'active' : ''}" data-speed="${speed}">${speed}x</div>`;
3555
3660
  });
3661
+
3556
3662
  menuHTML += `</div></div>`;
3557
3663
  }
3558
3664
 
3559
3665
  if (this.options.showSubtitles && this.textTracks && this.textTracks.length > 0) {
3560
- const subtitlesLabel = this.t('subtitles') || 'Subtitles';
3666
+ const subtitlesLabel = this.t('subtitles');
3561
3667
  const currentTrack = this.currentSubtitleTrack;
3562
- const currentLabel = this.subtitlesEnabled ? (currentTrack ? currentTrack.label : 'Unknown') : (this.t('subtitlesoff') || 'Off');
3668
+ const currentLabel = this.subtitlesEnabled ?
3669
+ (currentTrack ? currentTrack.label : 'Unknown') :
3670
+ this.t('subtitles_off'); //
3563
3671
 
3564
- menuHTML += `<div class="settings-expandable-wrapper">
3565
- <div class="settings-option expandable-trigger" data-action="subtitles-expand">
3672
+ menuHTML += `
3673
+ <div class="settings-expandable-wrapper">
3674
+ <div class="settings-option expandable-trigger" data-action="subtitles_expand">
3566
3675
  <span class="settings-option-label">${subtitlesLabel} <strong>${currentLabel}</strong></span>
3567
- <span class="expand-arrow">▶</span>
3676
+ <span class="expand-arrow">▼</span>
3568
3677
  </div>
3569
3678
  <div class="settings-expandable-content" style="display: none;">`;
3570
3679
 
3571
- menuHTML += `<div class="settings-suboption ${!this.subtitlesEnabled ? 'active' : ''}" data-track="off">${this.t('subtitlesoff') || 'Off'}</div>`;
3680
+ menuHTML += `<div class="settings-suboption ${!this.subtitlesEnabled ? 'active' : ''}" data-track="off">${this.t('subtitles_off')}</div>`;
3572
3681
 
3573
3682
  this.textTracks.forEach((trackData, index) => {
3574
3683
  const isActive = this.currentSubtitleTrack === trackData.track;
@@ -3631,8 +3740,10 @@ addSettingsMenuScrollbar() {
3631
3740
  }
3632
3741
 
3633
3742
  bindSettingsMenuEvents() {
3634
- const settingsBtn = this.controls?.querySelector('.settings-btn');
3635
- const settingsMenu = this.controls?.querySelector('.settings-menu');
3743
+
3744
+ const settingsBtn = this.container?.querySelector('.settings-btn');
3745
+ const settingsMenu = this.container?.querySelector('.settings-menu');
3746
+
3636
3747
  if (!settingsMenu || !settingsBtn) return;
3637
3748
 
3638
3749
  settingsBtn.addEventListener('click', (e) => {
@@ -3640,27 +3751,30 @@ bindSettingsMenuEvents() {
3640
3751
  settingsMenu.classList.toggle('active');
3641
3752
 
3642
3753
  if (settingsMenu.classList.contains('active')) {
3643
- const settingsBtn = document.querySelector('.settings-btn');
3644
- const containerRect = settingsMenu.parentElement.parentElement.getBoundingClientRect();
3754
+ const containerRect = this.container.getBoundingClientRect();
3645
3755
  const btnRect = settingsBtn.getBoundingClientRect();
3646
- const spaceBelow = containerRect.bottom - btnRect.bottom;
3647
- const maxMenuHeight = Math.max(100, Math.min(250, spaceBelow - 20));
3756
+
3757
+ const spaceBelow = containerRect.bottom - btnRect.bottom - 30; // 30px margin
3758
+
3759
+ const maxMenuHeight = Math.max(300, Math.min(600, spaceBelow));
3648
3760
 
3649
3761
  settingsMenu.style.maxHeight = `${maxMenuHeight}px`;
3650
3762
  settingsMenu.style.overflowY = 'auto';
3651
3763
  settingsMenu.style.overflowX = 'hidden';
3652
- } else {
3653
- settingsMenu.style.maxHeight = 'none';
3654
- settingsMenu.style.overflowY = 'visible';
3764
+
3765
+ if (this.options.debug) {
3766
+ console.log(`Settings menu opened: height=${maxMenuHeight}px (available=${spaceBelow}px)`);
3655
3767
  }
3768
+ } else {
3656
3769
 
3770
+ settingsMenu.style.maxHeight = '600px'; // Default max height
3771
+ settingsMenu.style.overflowY = 'auto';
3772
+ }
3657
3773
  });
3658
3774
 
3659
3775
  document.addEventListener('click', (e) => {
3660
3776
  if (!settingsBtn?.contains(e.target) && !settingsMenu?.contains(e.target)) {
3661
3777
  settingsMenu?.classList.remove('active');
3662
- settingsMenu.style.maxHeight = 'none';
3663
- settingsMenu.style.overflowY = 'visible';
3664
3778
  }
3665
3779
  });
3666
3780
 
@@ -3700,7 +3814,7 @@ bindSettingsMenuEvents() {
3700
3814
  const trigger = wrapper.querySelector('.expandable-trigger');
3701
3815
  const action = trigger.getAttribute('data-action');
3702
3816
 
3703
- if (action === 'speed-expand') {
3817
+ if (action === 'speed_expand') {
3704
3818
  const speed = parseFloat(e.target.getAttribute('data-speed'));
3705
3819
  if (speed && speed > 0 && this.video && !this.isChangingQuality) {
3706
3820
  this.video.playbackRate = speed;
@@ -3711,12 +3825,12 @@ bindSettingsMenuEvents() {
3711
3825
  const label = trigger.querySelector('.settings-option-label');
3712
3826
  if (label) {
3713
3827
  const speedLabel = this.t('playback_speed') || 'Playback Speed';
3714
- label.textContent = `${speedLabel}: ${speed}x`;
3828
+ label.innerHTML = `${speedLabel} <strong>${speed}x</strong>`;
3715
3829
  }
3716
3830
 
3717
3831
  this.triggerEvent('speedchange', { speed, previousSpeed: this.video.playbackRate });
3718
3832
  }
3719
- } else if (action === 'subtitles-expand') {
3833
+ } else if (action === 'subtitles_expand') {
3720
3834
  const trackData = e.target.getAttribute('data-track');
3721
3835
  if (trackData === 'off') {
3722
3836
  this.disableSubtitles();
@@ -3731,7 +3845,7 @@ bindSettingsMenuEvents() {
3731
3845
  const label = trigger.querySelector('.settings-option-label');
3732
3846
  if (label) {
3733
3847
  const subtitlesLabel = this.t('subtitles') || 'Subtitles';
3734
- label.textContent = `${subtitlesLabel}: ${e.target.textContent}`;
3848
+ label.innerHTML = `${subtitlesLabel} <strong>${e.target.textContent}</strong>`;
3735
3849
  }
3736
3850
  }
3737
3851
  }
@@ -5903,28 +6017,22 @@ bindChapterEvents() {
5903
6017
  }
5904
6018
 
5905
6019
  updateChapterInTitleOverlay() {
5906
- if (!this.video || !this.chapters || this.chapters.length === 0) return;
6020
+ if (!this.video || !this.chapters || this.chapters.length === 0) return;
6021
+ if (!this.topBar) return;
6022
+ let subtitleElement = this.topBar.querySelector('.video-subtitle');
5907
6023
 
5908
- const titleOverlay = this.container ? this.container.querySelector('.title-overlay') : null;
5909
- if (!titleOverlay) return;
5910
- let chapterElement = titleOverlay.querySelector('.chapter-name');
5911
- if (!chapterElement) {
5912
- chapterElement = document.createElement('div');
5913
- chapterElement.className = 'chapter-name';
5914
- chapterElement.style.cssText = `
5915
- font-size: 13px;
5916
- font-weight: 500;
5917
- color: rgba(255, 255, 255, 0.9);
5918
- margin-top: 6px;
5919
- max-width: 400px;
5920
- overflow: hidden;
5921
- text-overflow: ellipsis;
5922
- white-space: nowrap;
5923
- `;
5924
- titleOverlay.appendChild(chapterElement);
6024
+ if (!subtitleElement) {
6025
+ const titleSection = this.topBar.querySelector('.top-bar-title');
6026
+ if (!titleSection) return;
6027
+
6028
+ subtitleElement = document.createElement('span');
6029
+ subtitleElement.className = 'video-subtitle';
6030
+ titleSection.appendChild(subtitleElement);
6031
+ this.topBarSubtitle = subtitleElement;
5925
6032
  }
5926
6033
  const currentTime = this.video.currentTime;
5927
6034
  let currentChapter = null;
6035
+
5928
6036
  for (let i = this.chapters.length - 1; i >= 0; i--) {
5929
6037
  if (currentTime >= this.chapters[i].time) {
5930
6038
  currentChapter = this.chapters[i];
@@ -5932,10 +6040,19 @@ updateChapterInTitleOverlay() {
5932
6040
  }
5933
6041
  }
5934
6042
  if (currentChapter) {
5935
- chapterElement.textContent = currentChapter.title;
5936
- chapterElement.style.display = 'block';
6043
+ subtitleElement.textContent = currentChapter.title;
6044
+ subtitleElement.style.display = 'block';
6045
+ } else {
6046
+ if (this.options.videoSubtitle) {
6047
+ subtitleElement.textContent = this.options.videoSubtitle;
6048
+ subtitleElement.style.display = 'block';
5937
6049
  } else {
5938
- chapterElement.style.display = 'none';
6050
+ subtitleElement.style.display = 'none';
6051
+ }
6052
+ }
6053
+
6054
+ if (this.options.debug) {
6055
+ console.log('Chapter overlay updated:', currentChapter ? currentChapter.title : 'No chapter');
5939
6056
  }
5940
6057
  }
5941
6058
 
@@ -7549,8 +7666,7 @@ updateTimeDisplay() {
7549
7666
  }
7550
7667
  }
7551
7668
  const fallback = {
7552
- 'loading': 'Loading...',
7553
- 'encodinginprogress': 'Encoding in progress...'
7669
+ 'loading': 'Loading...'
7554
7670
  };
7555
7671
  return fallback[key] || key;
7556
7672
  };
@@ -7563,7 +7679,7 @@ updateTimeDisplay() {
7563
7679
  this.durationEl.classList.add('loading-state');
7564
7680
  } else if (isDurationInvalid) {
7565
7681
 
7566
- this.updateLoadingText(t('encodinginprogress'));
7682
+ this.updateLoadingText(t('loading'));
7567
7683
 
7568
7684
  this.durationEl.textContent = "--:--";
7569
7685