better ui for new selectors on player

This commit is contained in:
2025-12-31 16:09:44 +01:00
parent 7b3c559d03
commit d07c8de452
4 changed files with 274 additions and 50 deletions

View File

@@ -495,6 +495,10 @@ const AnimePlayer = (function() {
els.video.appendChild(track);
});
}
const ICONS = {
settings: `<svg viewBox="0 0 24 24"><path d="M19.14,12.94c0.04-0.3,0.06-0.61,0.06-0.94c0-0.32-0.02-0.64-0.07-0.94l2.03-1.58c0.18-0.14,0.23-0.41,0.12-0.61 l-1.92-3.32c-0.12-0.22-0.37-0.29-0.59-0.22l-2.39,0.96c-0.5-0.38-1.03-0.7-1.62-0.94L14.4,2.81c-0.04-0.24-0.24-0.41-0.48-0.41 h-3.84c-0.24,0-0.43,0.17-0.47,0.41L9.25,5.35C8.66,5.59,8.12,5.92,7.63,6.29L5.24,5.33c-0.22-0.08-0.47,0-0.59,0.22L2.74,8.87 C2.62,9.08,2.66,9.34,2.86,9.48l2.03,1.58C4.84,11.36,4.8,11.69,4.8,12s0.02,0.64,0.07,0.94l-2.03,1.58 c-0.18,0.14-0.23,0.41-0.12,0.61l1.92,3.32c0.12,0.22,0.37,0.29,0.59,0.22l2.39-0.96c0.5,0.38,1.03,0.7,1.62,0.94l0.36,2.54 c0.05,0.24,0.24,0.41,0.48,0.41h3.84c0.24,0,0.44-0.17,0.47-0.41l0.36-2.54c0.59-0.24,1.13-0.56,1.62-0.94l2.39,0.96 c0.22,0.08,0.47,0,0.59-0.22l1.92-3.32c0.12-0.22,0.07-0.47-0.12-0.61L19.14,12.94z M12,15.6c-1.98,0-3.6-1.62-3.6-3.6 s1.62-3.6,3.6-3.6s3.6,1.62,3.6,3.6S13.98,15.6,12,15.6z"/></svg>`,
audio: `<svg viewBox="0 0 24 24"><path d="M12,2C6.48,2,2,6.48,2,12v6c0,2.21,1.79,4,4,4h1c1.1,0,2-0.9,2-2v-5c0-1.1-0.9-2-2-2H3v-1c0-4.97,4.03-9,9-9s9,4.03,9,9v1 h-4c-1.1,0-2,0.9-2,2v5c0,1.1,0.9,2,2,2h1c2.21,0,4-1.79,4-4v-6C22,6.48,17.52,2,12,2z"/></svg>`
};
function createQualitySelector(hls) {
const levels = hls.levels;
@@ -502,37 +506,64 @@ const AnimePlayer = (function() {
const plyrEl = els.video.closest('.plyr');
const controls = plyrEl.querySelector('.plyr__controls');
if (!controls) return;
if (controls.querySelector('#quality-select')) return;
if (!controls || controls.querySelector('#quality-control-wrapper')) return;
// 1. Crear el Wrapper
const wrapper = document.createElement('div');
wrapper.className = 'plyr__control';
wrapper.className = 'plyr__controls__item plyr__custom-select-wrapper';
wrapper.id = 'quality-control-wrapper';
// 2. Crear el Botón Visual (Fake)
const btn = document.createElement('div');
btn.className = 'plyr__custom-control-btn';
// Icono + Texto Inicial
btn.innerHTML = `${ICONS.settings} <span class="label-text">Auto</span>`;
// 3. Crear el Select Real (Invisible)
const select = document.createElement('select');
select.id = 'quality-select';
select.className = 'plyr__sr-only-select'; // Clase auxiliar si quieres depurar, sino usa el CSS wrapper
// AUTO
const auto = document.createElement('option');
auto.value = -1;
auto.textContent = 'Auto';
select.appendChild(auto);
// Opción AUTO
const autoOpt = document.createElement('option');
autoOpt.value = -1;
autoOpt.textContent = 'Auto';
select.appendChild(autoOpt);
// Opciones de Niveles
levels.forEach((l, i) => {
const opt = document.createElement('option');
opt.value = i;
opt.textContent = `${l.height}p`;
opt.textContent = `${l.height}p`; // Texto que sale en el dropdown nativo
select.appendChild(opt);
});
// Sincronizar estado inicial
select.value = hls.currentLevel;
updateLabel(select.value);
// Evento Change
select.onchange = () => {
hls.currentLevel = Number(select.value);
updateLabel(select.value);
};
function updateLabel(val) {
const index = Number(val);
let text = 'Auto';
if (index !== -1 && levels[index]) {
// Solo el número + p (ej: 720p)
text = `${levels[index].height}p`;
}
btn.innerHTML = `<span class="label-text">${text}</span>`;
}
wrapper.appendChild(select);
controls.insertBefore(wrapper, controls.children[4]);
wrapper.appendChild(btn);
// Insertar en controles Plyr (antes del botón de pantalla completa o ajustes)
// Insertamos antes del 5º elemento (usualmente settings o fullscreen)
const insertIndex = controls.children.length > 4 ? 4 : controls.children.length - 1;
controls.insertBefore(wrapper, controls.children[insertIndex]);
}
function createAudioSelector(hls) {
@@ -540,15 +571,20 @@ const AnimePlayer = (function() {
const plyrEl = els.video.closest('.plyr');
const controls = plyrEl.querySelector('.plyr__controls');
if (!controls) return;
if (controls.querySelector('#audio-select')) return;
if (!controls || controls.querySelector('#audio-control-wrapper')) return;
// 1. Wrapper
const wrapper = document.createElement('div');
wrapper.className = 'plyr__control';
wrapper.className = 'plyr__controls__item plyr__custom-select-wrapper';
wrapper.id = 'audio-control-wrapper';
// 2. Botón Visual
const btn = document.createElement('div');
btn.className = 'plyr__custom-control-btn';
btn.innerHTML = `<span class="label-text">Audio 1</span>`;
// 3. Select Invisible
const select = document.createElement('select');
select.id = 'audio-select';
hls.audioTracks.forEach((t, i) => {
const opt = document.createElement('option');
@@ -558,13 +594,37 @@ const AnimePlayer = (function() {
});
select.value = hls.audioTrack;
updateLabel(select.value);
select.onchange = () => {
hls.audioTrack = Number(select.value);
updateLabel(select.value);
};
function updateLabel(val) {
const index = Number(val);
const track = hls.audioTracks[index];
// Priorizamos el idioma (lang), luego el nombre
let rawText = track.lang || track.name || `A${index + 1}`;
// Tomamos solo las 2 primeras letras y las pasamos a Mayúsculas
let shortText = rawText.substring(0, 2).toUpperCase();
btn.querySelector('.label-text').innerText = shortText;
}
wrapper.appendChild(select);
controls.insertBefore(wrapper, controls.children[4]); // antes del volumen
wrapper.appendChild(btn);
// Insertar antes del selector de calidad si existe, o en la posición 4
const qualityWrapper = controls.querySelector('#quality-control-wrapper');
if(qualityWrapper) {
controls.insertBefore(wrapper, qualityWrapper);
} else {
const insertIndex = controls.children.length > 4 ? 4 : controls.children.length - 1;
controls.insertBefore(wrapper, controls.children[insertIndex]);
}
}
function initPlyr(enableAudio = false) {