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.
- package/css/myetv-player.css +295 -15
- package/css/myetv-player.min.css +1 -1
- package/dist/myetv-player.js +353 -180
- package/dist/myetv-player.min.js +275 -159
- package/package.json +3 -1
- package/plugins/youtube/myetv-player-youtube-plugin.js +52 -45
package/dist/myetv-player.min.js
CHANGED
|
@@ -1170,13 +1170,31 @@ markPlayerReady() {
|
|
|
1170
1170
|
}
|
|
1171
1171
|
|
|
1172
1172
|
if (this.options.autoplay) {
|
|
1173
|
-
if (this.options.debug) console.log('
|
|
1173
|
+
if (this.options.debug) console.log('Autoplay enabled');
|
|
1174
1174
|
setTimeout(() => {
|
|
1175
|
-
this.video.play()
|
|
1176
|
-
|
|
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('
|
|
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.
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
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
|
-
|
|
1302
|
-
|
|
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
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
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.
|
|
1324
|
-
|
|
1327
|
+
if (this.topBarSubtitle) {
|
|
1328
|
+
this.topBarSubtitle.textContent = subtitle;
|
|
1329
|
+
} else if (subtitle && this.topBar) {
|
|
1325
1330
|
|
|
1326
|
-
|
|
1327
|
-
if (
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
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.
|
|
1352
|
+
if (this.topBar) {
|
|
1349
1353
|
if (persistent) {
|
|
1350
|
-
this.
|
|
1351
|
-
this.clearTitleTimeout();
|
|
1354
|
+
this.topBar.classList.add('persistent');
|
|
1352
1355
|
} else {
|
|
1353
|
-
this.
|
|
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.
|
|
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
|
-
|
|
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.
|
|
1376
|
-
|
|
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
|
-
|
|
3074
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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('
|
|
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('
|
|
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">
|
|
3392
|
-
<span
|
|
3393
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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')
|
|
3645
|
+
const speedLabel = this.t('playback_speed');
|
|
3543
3646
|
const currentSpeed = this.video ? this.video.playbackRate : 1;
|
|
3544
|
-
|
|
3545
|
-
|
|
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"
|
|
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')
|
|
3666
|
+
const subtitlesLabel = this.t('subtitles');
|
|
3561
3667
|
const currentTrack = this.currentSubtitleTrack;
|
|
3562
|
-
const currentLabel = this.subtitlesEnabled ?
|
|
3668
|
+
const currentLabel = this.subtitlesEnabled ?
|
|
3669
|
+
(currentTrack ? currentTrack.label : 'Unknown') :
|
|
3670
|
+
this.t('subtitles_off'); //
|
|
3563
3671
|
|
|
3564
|
-
menuHTML +=
|
|
3565
|
-
<div class="settings-
|
|
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"
|
|
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('
|
|
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
|
-
|
|
3635
|
-
const
|
|
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
|
|
3644
|
-
const containerRect = settingsMenu.parentElement.parentElement.getBoundingClientRect();
|
|
3754
|
+
const containerRect = this.container.getBoundingClientRect();
|
|
3645
3755
|
const btnRect = settingsBtn.getBoundingClientRect();
|
|
3646
|
-
|
|
3647
|
-
const
|
|
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
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
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 === '
|
|
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.
|
|
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 === '
|
|
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.
|
|
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
|
-
|
|
5909
|
-
|
|
5910
|
-
|
|
5911
|
-
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
|
|
5915
|
-
|
|
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
|
-
|
|
5936
|
-
|
|
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
|
-
|
|
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('
|
|
7682
|
+
this.updateLoadingText(t('loading'));
|
|
7567
7683
|
|
|
7568
7684
|
this.durationEl.textContent = "--:--";
|
|
7569
7685
|
|