Update metadata

This commit is contained in:
2026-05-03 15:18:09 +03:00
parent 93eff68b8d
commit 6c0958b92e
3 changed files with 265 additions and 99 deletions

View File

@@ -222,6 +222,19 @@
</div>
<div id="users-list" class="flex flex-col gap-2"></div>
</div>
<!-- Обновить все метаданные (только admin) -->
<div id="refresh-all-section" class="hidden px-5 py-4 border-t border-gray-800">
<h3 class="text-sm font-semibold text-gray-300 uppercase tracking-wider mb-1">Обновить все метаданные</h3>
<p class="text-xs text-gray-500 mb-3">Запускает браузер для каждой скачанной манги: обновляет обложку, синопсис, жанры и метаданные в файлах CBZ/PDF/EPUB.</p>
<div class="flex items-center gap-3 flex-wrap">
<button id="refresh-all-btn" onclick="refreshAllMeta()"
class="text-xs px-4 py-2 rounded-lg font-semibold text-white"
style="background:#312e81;border:1px solid #4338ca;color:#a78bfa">
🔄 Обновить все метаданные
</button>
<div id="refresh-all-status" class="text-xs text-gray-400 hidden"></div>
</div>
</div>
<!-- Смена своего пароля -->
<div id="chpwd-section" class="px-5 py-4 border-t border-gray-800">
<h3 class="text-sm font-semibold text-gray-300 uppercase tracking-wider mb-3">Сменить пароль</h3>
@@ -703,6 +716,18 @@ function handleEvent(msg) {
_updateMetaBtn(msg.url, msg.failed === -1 ? 'error' : 'done');
break;
case 'refresh_all_started':
_handleRefreshAllStarted(msg);
break;
case 'refresh_all_progress':
_handleRefreshAllProgress(msg);
break;
case 'refresh_all_done':
_handleRefreshAllDone(msg);
break;
case 'manga_meta_updated':
if(state.mangas[msg.url]) {
state.mangas[msg.url].title = msg.title;
@@ -812,7 +837,7 @@ function switchTab(tab) {
document.getElementById('manga-filters').classList.toggle('hidden', tab !== 'mangas');
if(tab === 'history') loadHistory();
if(tab === 'news') { newsUnreadCount = 0; updateNewsBadge(); loadNews(); }
if(tab === 'settings') { loadSources(); showUsersSection(); }
if(tab === 'settings') { loadSources(); showUsersSection(); showRefreshAllSection(); }
}
function updateNewsBadge() {
@@ -1132,6 +1157,11 @@ function showUsersSection() {
}
}
function showRefreshAllSection() {
const el = document.getElementById('refresh-all-section');
if(el) el.classList.toggle('hidden', !isAdmin());
}
async function loadUsers() {
if(!isAdmin()) return;
try {
@@ -1654,7 +1684,7 @@ function _updateMetaBtn(url, result) {
btn.style.color = '#4ade80';
btn.style.borderColor = '#166534';
setTimeout(() => {
btn.innerHTML = '🏷 Обновить метатеги';
btn.innerHTML = '🏷 Обновить метаданные';
btn.style.color = '#a78bfa';
btn.style.borderColor = '#312e81';
}, 2500);
@@ -1664,12 +1694,12 @@ function _updateMetaBtn(url, result) {
btn.style.color = '#f87171';
btn.style.borderColor = '#7f1d1d';
setTimeout(() => {
btn.innerHTML = '🏷 Обновить метатеги';
btn.innerHTML = '🏷 Обновить метаданные';
btn.style.color = '#a78bfa';
btn.style.borderColor = '#312e81';
}, 3000);
} else {
btn.innerHTML = '🏷 Обновить метатеги';
btn.innerHTML = '🏷 Обновить метаданные';
btn.disabled = false;
btn.style.color = '#a78bfa';
btn.style.borderColor = '#312e81';
@@ -1691,6 +1721,46 @@ async function refreshMetaModal(url) {
// Спиннер появится через WS meta_refresh_started, исчезнет через meta_refreshed
}
async function refreshAllMeta() {
const btn = document.getElementById('refresh-all-btn');
const status = document.getElementById('refresh-all-status');
const r = await fetch('/api/mangas/refresh_all_meta', {method:'POST'});
if(!r.ok) {
const err = await r.json().catch(() => ({}));
if(status) { status.textContent = err.detail || 'Ошибка запуска'; status.classList.remove('hidden'); status.style.color = '#f87171'; }
return;
}
if(btn) { btn.disabled = true; btn.textContent = '⏳ Запускаем...'; }
if(status) { status.textContent = 'Инициализация...'; status.classList.remove('hidden'); status.style.color = '#94a3b8'; }
}
function _handleRefreshAllStarted(data) {
const btn = document.getElementById('refresh-all-btn');
const status = document.getElementById('refresh-all-status');
if(btn) { btn.disabled = true; btn.textContent = '⏳ Обновляем...'; }
if(status) { status.textContent = `0 / ${data.total}`; status.classList.remove('hidden'); status.style.color = '#94a3b8'; }
}
function _handleRefreshAllProgress(data) {
const status = document.getElementById('refresh-all-status');
if(status) {
const title = data.title ? `${data.title}` : '';
status.textContent = `${data.done + 1} / ${data.total}${title}`;
status.style.color = '#94a3b8';
}
}
function _handleRefreshAllDone(data) {
const btn = document.getElementById('refresh-all-btn');
const status = document.getElementById('refresh-all-status');
if(btn) { btn.disabled = false; btn.textContent = '🔄 Обновить все метаданные'; }
if(status) {
status.textContent = `Готово: ${data.total} манг, обновлено файлов: ${data.total_updated}`;
status.style.color = '#4ade80';
status.classList.remove('hidden');
}
}
async function forceRedownload(url, closeModalAfter = false) {
if(!confirm('Скачать заново ВСЕ главы? Уже скачанные файлы будут перезаписаны.')) return;
const r = await fetch('/api/mangas/force_redownload?url='+encodeURIComponent(url), {method:'POST'});
@@ -2236,7 +2306,7 @@ function renderModalBody(data) {
<button id="modal-refresh-meta-btn" onclick="refreshMetaModal('${escHtml(data.url)}')"
class="flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-semibold transition-colors"
style="background:#1e1b4b;color:#a78bfa;border:1px solid #312e81">
🏷 Обновить метатеги
🏷 Обновить метаданные
</button>` : ''}
${data.status !== 'downloading' && data.status !== 'queued' && isAdmin() ? `
<button onclick="forceRedownloadModal('${escHtml(data.url)}')"