Fix page detection and add floating progress popup
✨ Improvements: - Enhanced page detection to support 'X pages' pattern - Added comprehensive logging for debugging - Implemented floating progress popup on page - Added show/hide progress message handlers - Better error handling and logging for image extraction - Fixed popup to display real-time progress 🐛 Fixed: - Page detection now works for both 'Showing X of Y images' and 'X pages' patterns - Downloads should now work correctly with proper page iteration - Added visible feedback via floating popup 🔍 Debugging: - Added console logs for page detection - Logs show total pages found and images extracted - Each page is logged during processing
This commit is contained in:
128
content.js
128
content.js
@@ -9,6 +9,85 @@
|
||||
// Map para almacenar metadatos completos de manga por ID
|
||||
let mangaMetadata = new Map();
|
||||
|
||||
// Crear popup flotante de progreso
|
||||
function createFloatingProgressPopup() {
|
||||
// Remover popup anterior si existe
|
||||
const existingPopup = document.getElementById('mass-downloader-progress-popup');
|
||||
if (existingPopup) {
|
||||
existingPopup.remove();
|
||||
}
|
||||
|
||||
const popup = document.createElement('div');
|
||||
popup.id = 'mass-downloader-progress-popup';
|
||||
popup.style.cssText = `
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 400px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
padding: 25px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 10px 40px rgba(0,0,0,0.5);
|
||||
z-index: 10001;
|
||||
font-family: Arial, sans-serif;
|
||||
display: none;
|
||||
`;
|
||||
|
||||
popup.innerHTML = `
|
||||
<div style="text-align: center; margin-bottom: 15px;">
|
||||
<h3 style="margin: 0 0 10px 0; font-size: 18px;">📦 Descargando Manga</h3>
|
||||
<div id="progress-title" style="font-size: 14px; opacity: 0.9; max-height: 40px; overflow: hidden;">Preparando descarga...</div>
|
||||
</div>
|
||||
<div style="background: rgba(255,255,255,0.3); height: 12px; border-radius: 6px; overflow: hidden;">
|
||||
<div id="progress-bar-fill" style="height: 100%; width: 0%; background: white; transition: width 0.3s ease;"></div>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between; margin-top: 8px; font-size: 13px;">
|
||||
<span id="progress-count">0 / 0</span>
|
||||
<span id="progress-percent">0%</span>
|
||||
</div>
|
||||
<div id="progress-status" style="margin-top: 10px; font-size: 12px; opacity: 0.8; text-align: center;"></div>
|
||||
`;
|
||||
|
||||
document.body.appendChild(popup);
|
||||
return popup;
|
||||
}
|
||||
|
||||
// Actualizar progreso
|
||||
function updateProgress(current, total, title, status) {
|
||||
const popup = document.getElementById('mass-downloader-progress-popup') || createFloatingProgressPopup();
|
||||
const percent = total > 0 ? Math.round((current / total) * 100) : 0;
|
||||
|
||||
const titleEl = document.getElementById('progress-title');
|
||||
const countEl = document.getElementById('progress-count');
|
||||
const percentEl = document.getElementById('progress-percent');
|
||||
const statusEl = document.getElementById('progress-status');
|
||||
const barEl = document.getElementById('progress-bar-fill');
|
||||
|
||||
if (titleEl) titleEl.textContent = title || 'Descargando...';
|
||||
if (countEl) countEl.textContent = `${current} / ${total}`;
|
||||
if (percentEl) percentEl.textContent = `${percent}%`;
|
||||
if (statusEl) statusEl.textContent = status || '';
|
||||
if (barEl) barEl.style.width = `${percent}%`;
|
||||
|
||||
popup.style.display = 'block';
|
||||
}
|
||||
|
||||
// Ocultar progreso
|
||||
function hideProgress() {
|
||||
const popup = document.getElementById('mass-downloader-progress-popup');
|
||||
if (popup) {
|
||||
setTimeout(() => {
|
||||
popup.style.opacity = '0';
|
||||
popup.style.transition = 'opacity 0.5s ease';
|
||||
setTimeout(() => {
|
||||
popup.remove();
|
||||
}, 500);
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
// Escuchar mensajes del popup
|
||||
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||
if (request.action === 'getSelectedMangas') {
|
||||
@@ -33,6 +112,12 @@
|
||||
} else if (request.action === 'extractAllMangas') {
|
||||
const allMangas = extractAllMangasFromPage();
|
||||
sendResponse({ mangas: allMangas });
|
||||
} else if (request.action === 'showProgress') {
|
||||
updateProgress(request.current, request.total, request.title, request.status);
|
||||
sendResponse({ success: true });
|
||||
} else if (request.action === 'hideProgress') {
|
||||
hideProgress();
|
||||
sendResponse({ success: true });
|
||||
}
|
||||
return true;
|
||||
});
|
||||
@@ -78,31 +163,65 @@
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(html, 'text/html');
|
||||
|
||||
// Detectar páginas
|
||||
// Detectar páginas - Múltiples patrones
|
||||
let actualTotalPages = 1;
|
||||
console.log('🔍 Iniciando detección de páginas para:', manga.title);
|
||||
|
||||
const pageInfo = doc.querySelector('.gpc, .gt, #gdn + span');
|
||||
|
||||
if (pageInfo) {
|
||||
const pageText = pageInfo.textContent.trim();
|
||||
const pageMatch = pageText.match(/Showing\s+1\s*-\s*\d+\s+of\s+(\d+)\s+images/i);
|
||||
console.log('🔍 Page info encontrado:', pageText);
|
||||
|
||||
// Patrón 1: "Showing 1 - 20 of 220 images"
|
||||
let pageMatch = pageText.match(/Showing\s+1\s*-\s*\d+\s+of\s+(\d+)\s+images/i);
|
||||
if (pageMatch) {
|
||||
const totalImages = parseInt(pageMatch[1]);
|
||||
actualTotalPages = Math.ceil(totalImages / 20);
|
||||
console.log(`✓ Patrón "Showing": ${totalImages} imágenes = ${actualTotalPages} páginas`);
|
||||
} else {
|
||||
// Patrón 2: "5 pages" o "X pages"
|
||||
pageMatch = pageText.match(/(\d+)\s+pages?/i);
|
||||
if (pageMatch) {
|
||||
actualTotalPages = parseInt(pageMatch[1]);
|
||||
console.log(`✓ Patrón "pages": ${actualTotalPages} páginas`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Procesar todas las páginas
|
||||
// Fallback: Buscar en todo el documento
|
||||
if (actualTotalPages === 1) {
|
||||
const allText = doc.body.textContent;
|
||||
const pageMatch = allText.match(/(\d+)\s+pages?/i);
|
||||
if (pageMatch) {
|
||||
actualTotalPages = parseInt(pageMatch[1]);
|
||||
console.log(`✓ Fallback: Encontradas ${actualTotalPages} páginas en el documento`);
|
||||
} else {
|
||||
console.log('⚠️ No se detectaron múltiples páginas, asumiendo 1 página');
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`📄 Total páginas a procesar: ${actualTotalPages}`);
|
||||
|
||||
// Procesar todas las páginas
|
||||
for (let page = 1; page <= actualTotalPages; page++) {
|
||||
const pageUrl = page === 1 ? baseUrl : `${baseUrl}?p=${page}`;
|
||||
console.log(`📄 Procesando página ${page}/${actualTotalPages}: ${pageUrl}`);
|
||||
|
||||
const pageResponse = await fetch(pageUrl, {
|
||||
credentials: 'include'
|
||||
});
|
||||
|
||||
if (!pageResponse.ok) continue;
|
||||
if (!pageResponse.ok) {
|
||||
console.error(`❌ Error ${pageResponse.status} en página ${page}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const pageHtml = await pageResponse.text();
|
||||
const pageDoc = parser.parseFromString(pageHtml, 'text/html');
|
||||
|
||||
const links = pageDoc.querySelectorAll('a[href*="/s/"]');
|
||||
console.log(`✓ Página ${page}: Encontrados ${links.length} enlaces de imagen`);
|
||||
links.forEach(link => {
|
||||
const href = link.href;
|
||||
if (href && href.includes('/s/')) {
|
||||
@@ -118,6 +237,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`✅ Total de imágenes encontradas: ${imageUrls.length}`);
|
||||
return imageUrls;
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
|
||||
26
popup.js
26
popup.js
@@ -70,11 +70,30 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||
|
||||
showProgress(0, selectedMangas.length, 'Iniciando descargas...');
|
||||
|
||||
// Mostrar popup flotante en la página
|
||||
chrome.tabs.sendMessage(tab.id, {
|
||||
action: 'showProgress',
|
||||
current: 0,
|
||||
total: selectedMangas.length,
|
||||
title: 'Preparando...',
|
||||
status: 'Iniciando descargas...'
|
||||
});
|
||||
|
||||
try {
|
||||
// Descargar cada manga secuencialmente
|
||||
for (let i = 0; i < selectedMangas.length; i++) {
|
||||
const manga = selectedMangas[i];
|
||||
showProgress(i + 1, selectedMangas.length, `Descargando: ${manga.title.substring(0, 30)}...`);
|
||||
const title = manga.title ? manga.title.substring(0, 50) : 'Manga sin título';
|
||||
showProgress(i + 1, selectedMangas.length, `Descargando: ${title}...`);
|
||||
|
||||
// Actualizar popup flotante
|
||||
chrome.tabs.sendMessage(tab.id, {
|
||||
action: 'showProgress',
|
||||
current: i,
|
||||
total: selectedMangas.length,
|
||||
title: title,
|
||||
status: `Descargando manga ${i + 1} de ${selectedMangas.length}...`
|
||||
});
|
||||
|
||||
try {
|
||||
// Obtener URLs de imágenes
|
||||
@@ -98,6 +117,11 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||
showProgress(selectedMangas.length, selectedMangas.length, '¡Completado!');
|
||||
statusElement.className = 'status success';
|
||||
|
||||
// Ocultar popup flotante
|
||||
chrome.tabs.sendMessage(tab.id, {
|
||||
action: 'hideProgress'
|
||||
});
|
||||
|
||||
// Limpiar selección después de 3 segundos
|
||||
setTimeout(() => {
|
||||
chrome.tabs.sendMessage(tab.id, { action: 'clearSelection' }, async () => {
|
||||
|
||||
Reference in New Issue
Block a user