better handling on web player for local
This commit is contained in:
@@ -121,8 +121,8 @@ const AnimePlayer = (function() {
|
||||
const closeBtn = document.getElementById('close-player-btn');
|
||||
if(closeBtn) closeBtn.addEventListener('click', closePlayer);
|
||||
|
||||
if(els.prevBtn) els.prevBtn.addEventListener('click', () => playEpisode(_currentEpisode - 1));
|
||||
if(els.nextBtn) els.nextBtn.addEventListener('click', () => playEpisode(_currentEpisode + 1));
|
||||
if(els.prevBtn) els.prevBtn.onclick = () => playEpisode(_currentEpisode - 1);
|
||||
if(els.nextBtn) els.nextBtn.onclick = () => playEpisode(_currentEpisode + 1);
|
||||
|
||||
if (!document.getElementById('skip-overlay-btn')) {
|
||||
const btn = document.createElement('button');
|
||||
@@ -249,17 +249,12 @@ const AnimePlayer = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
function playEpisode(episodeNumber) {
|
||||
async function playEpisode(episodeNumber) {
|
||||
const targetEp = parseInt(episodeNumber);
|
||||
if (targetEp < 1 || targetEp > _totalEpisodes) return;
|
||||
|
||||
_currentEpisode = targetEp;
|
||||
|
||||
if (els.downloadBtn) {
|
||||
els.downloadBtn.style.display = _isLocal ? 'none' : 'flex';
|
||||
resetDownloadButtonIcon();
|
||||
}
|
||||
|
||||
if(els.epTitle) els.epTitle.innerText = `Episode ${targetEp}`;
|
||||
if(els.prevBtn) els.prevBtn.disabled = (_currentEpisode <= 1);
|
||||
if(els.nextBtn) els.nextBtn.disabled = (_currentEpisode >= _totalEpisodes);
|
||||
@@ -269,6 +264,7 @@ const AnimePlayer = (function() {
|
||||
_skipBtn.classList.remove('is-next');
|
||||
}
|
||||
|
||||
// Actualizar URL y Botones
|
||||
const newUrl = new URL(window.location);
|
||||
newUrl.searchParams.set('episode', targetEp);
|
||||
window.history.pushState({}, '', newUrl);
|
||||
@@ -276,19 +272,100 @@ const AnimePlayer = (function() {
|
||||
if(els.playerWrapper) els.playerWrapper.style.display = 'block';
|
||||
document.body.classList.add('stop-scrolling');
|
||||
|
||||
// Pausar trailer si existe
|
||||
const trailer = document.querySelector('#trailer-player iframe');
|
||||
if(trailer) trailer.contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}', '*');
|
||||
|
||||
_rpcActive = false;
|
||||
|
||||
if (els.extSelect.value === 'local') {
|
||||
loadStream();
|
||||
return;
|
||||
// Mostrar carga mientras verificamos disponibilidad
|
||||
setLoading("Checking availability...");
|
||||
|
||||
// --- LÓGICA DE AUTO-DETECCIÓN LOCAL ---
|
||||
let shouldPlayLocal = false;
|
||||
|
||||
try {
|
||||
// Consultamos a la API si ESTE episodio específico existe localmente
|
||||
const check = await fetch(`/api/library/${_animeId}/units`);
|
||||
const data = await check.json();
|
||||
|
||||
// Buscamos el episodio en la respuesta
|
||||
const localUnit = data.units ? data.units.find(u => u.number === targetEp) : null;
|
||||
|
||||
if (localUnit) {
|
||||
shouldPlayLocal = true;
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn("Availability check failed:", e);
|
||||
// Si falla el check (ej: error de red), mantenemos el modo actual por seguridad
|
||||
shouldPlayLocal = (els.extSelect.value === 'local');
|
||||
}
|
||||
if (els.serverSelect.options.length === 0) {
|
||||
handleExtensionChange(true);
|
||||
} else {
|
||||
|
||||
if (shouldPlayLocal) {
|
||||
els.manualMatchBtn.style.display = 'none';
|
||||
}
|
||||
else{
|
||||
els.manualMatchBtn.style.display = 'flex';
|
||||
|
||||
}
|
||||
|
||||
if (shouldPlayLocal) {
|
||||
// CASO 1: El episodio EXISTE localmente
|
||||
console.log(`Episode ${targetEp} found locally. Switching to Local.`);
|
||||
|
||||
// 1. Asegurar que 'local' está en el dropdown y seleccionarlo
|
||||
let localOption = els.extSelect.querySelector('option[value="local"]');
|
||||
if (!localOption) {
|
||||
localOption = document.createElement('option');
|
||||
localOption.value = 'local';
|
||||
localOption.innerText = 'Local';
|
||||
els.extSelect.appendChild(localOption);
|
||||
}
|
||||
els.extSelect.value = 'local';
|
||||
|
||||
// 2. Ocultar controles que no son para local
|
||||
if(els.subDubToggle) els.subDubToggle.style.display = 'none';
|
||||
if(els.serverSelect) els.serverSelect.style.display = 'none';
|
||||
|
||||
// 3. Cargar stream
|
||||
loadStream();
|
||||
|
||||
} else {
|
||||
// CASO 2: El episodio NO existe localmente (es Remoto)
|
||||
|
||||
// Si estábamos en modo 'local', tenemos que cambiar a una extensión
|
||||
if (els.extSelect.value === 'local') {
|
||||
console.log(`Episode ${targetEp} not local. Switching to Extension.`);
|
||||
|
||||
// 1. Quitar la opción local para evitar errores (opcional)
|
||||
const localOption = els.extSelect.querySelector('option[value="local"]');
|
||||
if (localOption) localOption.remove();
|
||||
|
||||
// 2. Restaurar la fuente original (Anilist, Gogo, etc)
|
||||
// Usamos _entrySource, pero si era 'local', forzamos 'anilist' para evitar bucle
|
||||
let fallbackSource = (_entrySource !== 'local') ? _entrySource : 'anilist';
|
||||
|
||||
// Verificar si esa fuente existe en el select, si no, usar la primera disponible
|
||||
if (!els.extSelect.querySelector(`option[value="${fallbackSource}"]`)) {
|
||||
if (els.extSelect.options.length > 0) {
|
||||
fallbackSource = els.extSelect.options[0].value;
|
||||
}
|
||||
}
|
||||
els.extSelect.value = fallbackSource;
|
||||
|
||||
// 3. Como cambiamos de Local -> Extensión, necesitamos cargar los servidores de nuevo
|
||||
// handleExtensionChange(true) se encarga de cargar settings, servers y luego hacer play.
|
||||
handleExtensionChange(true);
|
||||
|
||||
} else {
|
||||
// Ya estábamos en modo remoto.
|
||||
// Si por alguna razón no hay servidores cargados, recargamos la extensión.
|
||||
if (els.serverSelect.options.length === 0) {
|
||||
handleExtensionChange(true);
|
||||
} else {
|
||||
loadStream();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -600,16 +677,18 @@ const AnimePlayer = (function() {
|
||||
|
||||
async function handleExtensionChange(shouldPlay = true) {
|
||||
const selectedExt = els.extSelect.value;
|
||||
if (els.manualMatchBtn) {
|
||||
// Si es local, lo ocultamos. Si es extensión, lo mostramos.
|
||||
els.manualMatchBtn.style.display = (selectedExt === 'local') ? 'none' : 'flex';
|
||||
}
|
||||
|
||||
if (selectedExt === 'local') {
|
||||
els.subDubToggle.style.display = 'none';
|
||||
els.serverSelect.style.display = 'none';
|
||||
if (shouldPlay && _currentEpisode > 0) loadStream();
|
||||
return;
|
||||
}
|
||||
if (els.manualMatchBtn) {
|
||||
// No mostrar en local, sí en extensiones
|
||||
els.manualMatchBtn.style.display = (selectedExt === 'local') ? 'none' : 'flex';
|
||||
}
|
||||
|
||||
_manualExtensionId = null;
|
||||
|
||||
setLoading("Loading Extension Settings...");
|
||||
@@ -679,40 +758,65 @@ const AnimePlayer = (function() {
|
||||
_isLocal = false;
|
||||
_rawVideoData = null;
|
||||
}
|
||||
|
||||
if (currentExt === 'local') {
|
||||
try {
|
||||
|
||||
const localId = await getLocalEntryId();
|
||||
if (!localId) {
|
||||
setLoading("Local entry not found in library.");
|
||||
|
||||
// Paso 1: Obtener lista de archivos
|
||||
const check = await fetch(`/api/library/${_animeId}/units`);
|
||||
const data = await check.json();
|
||||
|
||||
// Paso 2: Buscar si el episodio actual existe
|
||||
const targetUnit = data.units ? data.units.find(u => u.number === parseInt(_currentEpisode)) : null;
|
||||
|
||||
// Paso 3: Si NO existe localmente
|
||||
if (!targetUnit) {
|
||||
console.log(`Episode ${_currentEpisode} not found locally. Removing option.`);
|
||||
|
||||
const localOption = els.extSelect.querySelector('option[value="local"]');
|
||||
if (localOption) localOption.remove();
|
||||
|
||||
const fallbackSource = (_entrySource === 'local') ? 'anilist' : _entrySource;
|
||||
|
||||
if (els.extSelect.querySelector(`option[value="${fallbackSource}"]`)) {
|
||||
els.extSelect.value = fallbackSource;
|
||||
} else if (els.extSelect.options.length > 0) {
|
||||
els.extSelect.selectedIndex = 0;
|
||||
}
|
||||
|
||||
handleExtensionChange(true);
|
||||
return;
|
||||
}
|
||||
const check = await fetch(`/api/library/anime/${localId}/episodes`);
|
||||
const eps = await check.json();
|
||||
|
||||
if (!eps.includes(_currentEpisode)) {
|
||||
els.extSelect.value = _entrySource;
|
||||
return loadStream();
|
||||
}
|
||||
|
||||
const ext = localUrl.split('.').pop().toLowerCase();
|
||||
const ext = targetUnit.format || targetUnit.name.split('.').pop().toLowerCase();
|
||||
|
||||
// Validación de formato para reproductor web
|
||||
if (!['mp4'].includes(ext)) {
|
||||
setLoading(
|
||||
`Currently the web player only supports mp4 files.`
|
||||
`Format '${ext}' not supported in web player. Use MPV.`
|
||||
);
|
||||
// Aseguramos que el botón de MPV tenga la data necesaria aunque falle el web player
|
||||
_rawVideoData = {
|
||||
url: targetUnit.path, // O la URL de stream correspondiente
|
||||
headers: {}
|
||||
};
|
||||
if (els.mpvBtn) els.mpvBtn.style.display = 'flex';
|
||||
return;
|
||||
}
|
||||
|
||||
const localUrl = `/api/library/stream/${targetUnit.id}`;
|
||||
|
||||
_rawVideoData = {
|
||||
url: window.location.origin + localUrl,
|
||||
url: localUrl, // O window.location.origin + localUrl si es relativa
|
||||
headers: {}
|
||||
};
|
||||
_currentSubtitles = [];
|
||||
|
||||
initVideoPlayer(localUrl, 'mp4');
|
||||
|
||||
} catch(e) {
|
||||
console.error(e);
|
||||
setLoading("Local Error: " + e.message);
|
||||
}
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user