perf: Optimize list rendering with partial DOM updates - Preserve existing card DOM elements (no image flicker) - Update only changed fields (progress, status, speed) - Add/remove cards only when necessary - Reorder cards to match server order
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
title: "GDM"
|
title: "GDM"
|
||||||
package_name: gommi_downloader_manager
|
package_name: gommi_downloader_manager
|
||||||
version: '0.2.22'
|
version: '0.2.23'
|
||||||
description: FlaskFarm 범용 다운로더 큐 - YouTube, 애니24, 링크애니, Anilife 지원
|
description: FlaskFarm 범용 다운로더 큐 - YouTube, 애니24, 링크애니, Anilife 지원
|
||||||
developer: projectdx
|
developer: projectdx
|
||||||
home: https://gitea.yommi.duckdns.org/projectdx/gommi_downloader_manager
|
home: https://gitea.yommi.duckdns.org/projectdx/gommi_downloader_manager
|
||||||
|
|||||||
@@ -798,18 +798,7 @@
|
|||||||
const container = document.getElementById('download_list');
|
const container = document.getElementById('download_list');
|
||||||
if (!container) return;
|
if (!container) return;
|
||||||
|
|
||||||
// Save expanded card IDs before re-rendering
|
// Handle empty state
|
||||||
const expandedIds = [];
|
|
||||||
container.querySelectorAll('.dl-card.expanded').forEach(function(card) {
|
|
||||||
expandedIds.push(card.id);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Save checked checkbox IDs before re-rendering
|
|
||||||
const checkedIds = [];
|
|
||||||
container.querySelectorAll('.dl-select-checkbox:checked').forEach(function(cb) {
|
|
||||||
checkedIds.push(cb.dataset.id);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!items || items.length === 0) {
|
if (!items || items.length === 0) {
|
||||||
container.innerHTML = `
|
container.innerHTML = `
|
||||||
<div class="empty-state">
|
<div class="empty-state">
|
||||||
@@ -819,30 +808,96 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let html = '';
|
// Build a map of incoming items by ID
|
||||||
items.forEach(function(item) {
|
const itemMap = {};
|
||||||
html += createDownloadCard(item);
|
items.forEach(item => itemMap[`card_${item.id}`] = item);
|
||||||
});
|
|
||||||
container.innerHTML = html;
|
|
||||||
|
|
||||||
// Restore expanded state
|
// Get existing cards
|
||||||
expandedIds.forEach(function(cardId) {
|
const existingCards = container.querySelectorAll('.dl-card');
|
||||||
const card = document.getElementById(cardId);
|
const existingIds = new Set();
|
||||||
if (card) card.classList.add('expanded');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Restore checkbox state
|
// Update existing cards or mark for removal
|
||||||
checkedIds.forEach(function(id) {
|
existingCards.forEach(card => {
|
||||||
const cb = container.querySelector('.dl-select-checkbox[data-id="' + id + '"]');
|
const cardId = card.id;
|
||||||
if (cb) {
|
existingIds.add(cardId);
|
||||||
cb.checked = true;
|
|
||||||
const card = cb.closest('.dl-card');
|
if (itemMap[cardId]) {
|
||||||
if (card) card.classList.add('selected');
|
// Card exists - do partial update (progress, speed, status only)
|
||||||
|
const item = itemMap[cardId];
|
||||||
|
updateCardInPlace(card, item);
|
||||||
|
} else {
|
||||||
|
// Card no longer in list - remove it
|
||||||
|
card.remove();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Update selected count
|
// Add new cards that don't exist yet
|
||||||
updateSelectedCount();
|
items.forEach(item => {
|
||||||
|
const cardId = `card_${item.id}`;
|
||||||
|
if (!existingIds.has(cardId)) {
|
||||||
|
const tempDiv = document.createElement('div');
|
||||||
|
tempDiv.innerHTML = createDownloadCard(item);
|
||||||
|
const newCard = tempDiv.firstElementChild;
|
||||||
|
container.appendChild(newCard);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Reorder cards to match server order
|
||||||
|
items.forEach((item, index) => {
|
||||||
|
const card = document.getElementById(`card_${item.id}`);
|
||||||
|
if (card && card !== container.children[index]) {
|
||||||
|
container.insertBefore(card, container.children[index]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// In-place update without DOM replacement (preserves images)
|
||||||
|
function updateCardInPlace(card, item) {
|
||||||
|
const percent = (item.progress && !isNaN(item.progress)) ? item.progress : 0;
|
||||||
|
const status = item.status || 'pending';
|
||||||
|
const statusClass = `status-${status}`;
|
||||||
|
|
||||||
|
// Update progress bar
|
||||||
|
const progressFill = card.querySelector('.dl-progress-fill');
|
||||||
|
if (progressFill) progressFill.style.width = `${percent}%`;
|
||||||
|
|
||||||
|
// Update percentage text
|
||||||
|
const percentText = card.querySelector('.dl-percent-big');
|
||||||
|
if (percentText) percentText.innerHTML = `${percent}<small>%</small>`;
|
||||||
|
|
||||||
|
// Update speed
|
||||||
|
const speedText = card.querySelector('.dl-speed-text');
|
||||||
|
if (speedText) speedText.textContent = item.speed || '';
|
||||||
|
|
||||||
|
// Update status pill
|
||||||
|
const statusPill = card.querySelector('.dl-status-pill');
|
||||||
|
if (statusPill) {
|
||||||
|
statusPill.className = `dl-status-pill ${statusClass}`;
|
||||||
|
const statusTextNode = statusPill.childNodes[statusPill.childNodes.length - 1];
|
||||||
|
if (statusTextNode) {
|
||||||
|
statusTextNode.textContent = status.charAt(0).toUpperCase() + status.slice(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update card background class
|
||||||
|
card.className = card.className.replace(/status-\w+/g, '').trim();
|
||||||
|
card.classList.add(statusClass);
|
||||||
|
if (card.classList.contains('expanded')) card.classList.add('expanded');
|
||||||
|
if (card.classList.contains('selected')) card.classList.add('selected');
|
||||||
|
|
||||||
|
// Update title if changed
|
||||||
|
const titleEl = card.querySelector('.dl-filename');
|
||||||
|
const newTitle = item.title || item.filename || item.url || 'No Title';
|
||||||
|
if (titleEl && titleEl.textContent !== newTitle) {
|
||||||
|
titleEl.textContent = newTitle;
|
||||||
|
titleEl.title = newTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update thumbnail only if src changed
|
||||||
|
const thumbEl = card.querySelector('.dl-thumb');
|
||||||
|
if (thumbEl && item.thumbnail && thumbEl.src !== item.thumbnail) {
|
||||||
|
thumbEl.src = item.thumbnail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createDownloadCard(item) {
|
function createDownloadCard(item) {
|
||||||
|
|||||||
Reference in New Issue
Block a user