upd
This commit is contained in:
@@ -192,6 +192,58 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Модалка редактирования метаданных -->
|
||||
<div id="edit-meta-modal" class="fixed inset-0 z-[60] hidden items-center justify-center" style="background:rgba(0,0,0,0.75)">
|
||||
<div class="card rounded-2xl w-full max-w-md mx-4 p-6 flex flex-col gap-4">
|
||||
<h3 class="font-semibold text-white text-base">✏️ Редактировать название</h3>
|
||||
<div class="flex flex-col gap-3">
|
||||
<div>
|
||||
<label class="text-xs text-gray-400 mb-1 block">Название (ru)</label>
|
||||
<input id="edit-meta-title-ru" type="text"
|
||||
class="w-full px-3 py-2 rounded-lg text-sm text-white border border-gray-700 focus:border-indigo-500 outline-none"
|
||||
style="background:#0f1117" placeholder="Название на русском">
|
||||
</div>
|
||||
<div>
|
||||
<label class="text-xs text-gray-400 mb-1 block">Полное название</label>
|
||||
<input id="edit-meta-title-full" type="text"
|
||||
class="w-full px-3 py-2 rounded-lg text-sm text-white border border-gray-700 focus:border-indigo-500 outline-none"
|
||||
style="background:#0f1117" placeholder="Полное название">
|
||||
</div>
|
||||
<p class="text-xs text-gray-500">⚠️ Папка не переименуется. Метаданные файлов обновятся автоматически.</p>
|
||||
</div>
|
||||
<div class="flex gap-3 justify-end mt-2">
|
||||
<button onclick="closeEditMeta()"
|
||||
class="px-4 py-2 rounded-lg text-sm text-gray-400 hover:text-white"
|
||||
style="background:#1e293b">Отмена</button>
|
||||
<button onclick="saveEditMeta()" id="edit-meta-save-btn"
|
||||
class="px-4 py-2 rounded-lg text-sm font-semibold text-white"
|
||||
style="background:#4f46e5">Сохранить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Модалка переименования папки -->
|
||||
<div id="rename-folder-modal" class="fixed inset-0 z-[60] hidden items-center justify-center" style="background:rgba(0,0,0,0.75)">
|
||||
<div class="card rounded-2xl w-full max-w-md mx-4 p-6 flex flex-col gap-4">
|
||||
<h3 class="font-semibold text-white text-base">📁 Переименовать папку</h3>
|
||||
<div>
|
||||
<label class="text-xs text-gray-400 mb-1 block">Новое имя папки</label>
|
||||
<input id="rename-folder-input" type="text"
|
||||
class="w-full px-3 py-2 rounded-lg text-sm text-white border border-gray-700 focus:border-indigo-500 outline-none"
|
||||
style="background:#0f1117" placeholder="Название папки">
|
||||
<p class="text-xs text-gray-500 mt-2">Специальные символы будут удалены. Пробелы заменятся на «_».</p>
|
||||
</div>
|
||||
<div class="flex gap-3 justify-end mt-2">
|
||||
<button onclick="closeRenameFolder()"
|
||||
class="px-4 py-2 rounded-lg text-sm text-gray-400 hover:text-white"
|
||||
style="background:#1e293b">Отмена</button>
|
||||
<button onclick="saveRenameFolder()" id="rename-folder-save-btn"
|
||||
class="px-4 py-2 rounded-lg text-sm font-semibold text-white"
|
||||
style="background:#4f46e5">Переименовать</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// ── State ────────────────────────────────────
|
||||
const state = {
|
||||
@@ -377,6 +429,34 @@ function handleEvent(msg) {
|
||||
// Ничего не делаем визуально — файлы обновлены на диске
|
||||
break;
|
||||
|
||||
case 'manga_meta_updated':
|
||||
if(state.mangas[msg.url]) {
|
||||
state.mangas[msg.url].title = msg.title;
|
||||
state.mangas[msg.url].title_ru = msg.title_ru;
|
||||
state.mangas[msg.url].title_full = msg.title_full;
|
||||
updateMangaRow(msg.url);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'manga_folder_renamed':
|
||||
if(state.mangas[msg.url]) {
|
||||
state.mangas[msg.url].folder_name = msg.folder_name;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'queue_positions': {
|
||||
// Обновляем queue_position для всех манг
|
||||
const pos = msg.positions || {};
|
||||
Object.values(state.mangas).forEach(m => {
|
||||
const newPos = pos[m.url] ?? null;
|
||||
if(m.queue_position !== newPos) {
|
||||
m.queue_position = newPos;
|
||||
updateMangaRow(m.url);
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case 'manga_done':
|
||||
if(state.mangas[msg.url]) {
|
||||
state.mangas[msg.url].status = 'done';
|
||||
@@ -948,7 +1028,7 @@ function _rowButtons(m) {
|
||||
${m.status === 'stopped' || m.status === 'failed'
|
||||
? `<button onclick="resumeManga('${u}')" title="Возобновить" style="background:#14532d;color:#86efac;padding:4px 12px;border-radius:6px;font-size:0.75rem;cursor:pointer">▶</button>`
|
||||
: ''}
|
||||
${!isActive
|
||||
${m.status === 'queued'
|
||||
? `<button onclick="prioritizeManga('${u}')" title="Загрузить первой" style="background:#312e81;color:#a5b4fc;padding:4px 8px;border-radius:6px;font-size:0.75rem;cursor:pointer">🚀</button>`
|
||||
: ''}
|
||||
<button onclick="deleteManga('${u}')" class="btn-danger" title="Удалить">✕</button>
|
||||
@@ -1185,6 +1265,17 @@ function renderModalBody(data) {
|
||||
</details>` : '<div class="text-xs text-gray-500 mb-3">Файлов на диске нет</div>'}
|
||||
|
||||
<div class="flex flex-wrap gap-2 mt-4 pt-4 border-t border-gray-800">
|
||||
<button onclick="openEditMeta('${escHtml(data.url)}')"
|
||||
class="flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-semibold transition-colors"
|
||||
style="background:#1e293b;color:#94a3b8;border:1px solid #334155">
|
||||
✏️ Редактировать название
|
||||
</button>
|
||||
${data.status !== 'downloading' ? `
|
||||
<button onclick="openRenameFolder('${escHtml(data.url)}', '${escHtml(data.folder_name || '')}')"
|
||||
class="flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-semibold transition-colors"
|
||||
style="background:#1e293b;color:#94a3b8;border:1px solid #334155">
|
||||
📁 Переименовать папку
|
||||
</button>` : ''}
|
||||
${data.status === 'done' ? `
|
||||
<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"
|
||||
@@ -1323,6 +1414,98 @@ function escHtml(s) {
|
||||
return String(s||'').replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"');
|
||||
}
|
||||
|
||||
// ── Edit Meta ────────────────────────────────
|
||||
let _editMetaUrl = null;
|
||||
|
||||
function openEditMeta(url) {
|
||||
_editMetaUrl = url;
|
||||
const m = state.mangas[url] || {};
|
||||
document.getElementById('edit-meta-title-ru').value = m.title_ru || m.title || '';
|
||||
document.getElementById('edit-meta-title-full').value = m.title_full || '';
|
||||
const modal = document.getElementById('edit-meta-modal');
|
||||
modal.classList.remove('hidden');
|
||||
modal.classList.add('flex');
|
||||
}
|
||||
|
||||
function closeEditMeta() {
|
||||
const modal = document.getElementById('edit-meta-modal');
|
||||
modal.classList.add('hidden');
|
||||
modal.classList.remove('flex');
|
||||
_editMetaUrl = null;
|
||||
}
|
||||
|
||||
async function saveEditMeta() {
|
||||
if(!_editMetaUrl) return;
|
||||
const btn = document.getElementById('edit-meta-save-btn');
|
||||
btn.disabled = true; btn.textContent = '⏳ Сохраняем...';
|
||||
const title_ru = document.getElementById('edit-meta-title-ru').value.trim();
|
||||
const title_full = document.getElementById('edit-meta-title-full').value.trim();
|
||||
try {
|
||||
const r = await fetch('/api/mangas/update_meta', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type':'application/json'},
|
||||
body: JSON.stringify({url: _editMetaUrl, title_ru, title_full}),
|
||||
});
|
||||
if(!r.ok) throw new Error(await r.text());
|
||||
// Update local state
|
||||
if(state.mangas[_editMetaUrl]) {
|
||||
state.mangas[_editMetaUrl].title = title_ru;
|
||||
state.mangas[_editMetaUrl].title_ru = title_ru;
|
||||
state.mangas[_editMetaUrl].title_full = title_full;
|
||||
}
|
||||
renderList();
|
||||
closeEditMeta();
|
||||
} catch(e) {
|
||||
alert('Ошибка: ' + e.message);
|
||||
} finally {
|
||||
btn.disabled = false; btn.textContent = 'Сохранить';
|
||||
}
|
||||
}
|
||||
|
||||
// ── Rename Folder ────────────────────────────
|
||||
let _renameFolderUrl = null;
|
||||
|
||||
function openRenameFolder(url, currentFolder) {
|
||||
_renameFolderUrl = url;
|
||||
const m = state.mangas[url] || {};
|
||||
const cur = currentFolder || m.folder_name || (m.title_ru || m.title || '').replace(/[^\w\s\-]/g,'').trim().replace(/ /g,'_');
|
||||
document.getElementById('rename-folder-input').value = cur;
|
||||
const modal = document.getElementById('rename-folder-modal');
|
||||
modal.classList.remove('hidden');
|
||||
modal.classList.add('flex');
|
||||
}
|
||||
|
||||
function closeRenameFolder() {
|
||||
const modal = document.getElementById('rename-folder-modal');
|
||||
modal.classList.add('hidden');
|
||||
modal.classList.remove('flex');
|
||||
_renameFolderUrl = null;
|
||||
}
|
||||
|
||||
async function saveRenameFolder() {
|
||||
if(!_renameFolderUrl) return;
|
||||
const btn = document.getElementById('rename-folder-save-btn');
|
||||
btn.disabled = true; btn.textContent = '⏳ Переименовываем...';
|
||||
const folder_name = document.getElementById('rename-folder-input').value.trim();
|
||||
try {
|
||||
const r = await fetch('/api/mangas/rename_folder', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type':'application/json'},
|
||||
body: JSON.stringify({url: _renameFolderUrl, folder_name}),
|
||||
});
|
||||
if(!r.ok) throw new Error((await r.json()).detail || await r.text());
|
||||
const data = await r.json();
|
||||
if(state.mangas[_renameFolderUrl]) {
|
||||
state.mangas[_renameFolderUrl].folder_name = data.folder_name;
|
||||
}
|
||||
closeRenameFolder();
|
||||
} catch(e) {
|
||||
alert('Ошибка: ' + e.message);
|
||||
} finally {
|
||||
btn.disabled = false; btn.textContent = 'Переименовать';
|
||||
}
|
||||
}
|
||||
|
||||
// ── Init ─────────────────────────────────────
|
||||
async function init() {
|
||||
_initDeleteModal();
|
||||
@@ -1344,6 +1527,12 @@ document.addEventListener('DOMContentLoaded', init);
|
||||
document.getElementById('modal').addEventListener('click', function(e) {
|
||||
if(e.target === this) closeModal();
|
||||
});
|
||||
document.getElementById('edit-meta-modal').addEventListener('click', function(e) {
|
||||
if(e.target === this) closeEditMeta();
|
||||
});
|
||||
document.getElementById('rename-folder-modal').addEventListener('click', function(e) {
|
||||
if(e.target === this) closeRenameFolder();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user