diff --git a/renderer/app.js b/renderer/app.js index 028d7d2..1db0935 100644 --- a/renderer/app.js +++ b/renderer/app.js @@ -900,11 +900,17 @@ function scheduleRecentRender() { // Toggle the .selected class on existing rows without rebuilding the table. // Used on click/selection changes — O(rendered rows) instead of O(total rows × sort). +// Uses getElementsByClassName for the live HTMLCollection (DOM-cached after the +// first call, auto-tracks insertions/removals on tbody) instead of running a +// fresh querySelectorAll on every click. At 200 visible rows that's the +// difference between paying for a tree walk per click vs reading a memoized +// list that the engine already maintains. function applyQueueSelectionClasses() { const tbody = document.getElementById('queueBody'); if (!tbody) return; - const rows = tbody.querySelectorAll('.queue-row'); - for (const tr of rows) { + const rows = tbody.getElementsByClassName('queue-row'); + for (let i = 0; i < rows.length; i++) { + const tr = rows[i]; tr.classList.toggle('selected', selectedJobIds.has(tr.dataset.jobId)); } } @@ -912,8 +918,9 @@ function applyQueueSelectionClasses() { function applyRecentSelectionClasses() { const tbody = document.getElementById('recentFilesBody'); if (!tbody) return; - const rows = tbody.querySelectorAll('.recent-file-row'); - for (const tr of rows) { + const rows = tbody.getElementsByClassName('recent-file-row'); + for (let i = 0; i < rows.length; i++) { + const tr = rows[i]; const order = parseInt(tr.dataset.order, 10); tr.classList.toggle('selected', selectedRecentIds.has(order)); } diff --git a/tasks/todo.md b/tasks/todo.md index 0a2e728..8282bdb 100644 --- a/tasks/todo.md +++ b/tasks/todo.md @@ -5,12 +5,10 @@ - ✅ 3.3.1 — `removeFromQueueOnDone` coalesced via microtask (kein O(N²) mehr bei done-Bursts) - ✅ 3.3.2 — `fileuploader.log` Auto-Rotation bei 50 MB (max 3 Backups: .1 .2 .3) - ✅ 3.3.3 — `_jobLogCollector` Cap auf 1000 tracked jobs (FIFO-eviction beim Überschreiten) +- ✅ 3.3.4 — `applyQueueSelectionClasses` + `applyRecentSelectionClasses` nutzen `getElementsByClassName` (live HTMLCollection statt querySelectorAll re-query bei jedem Klick) ## Open items (priorisiert) -### Performance -- [ ] **`applyQueueSelectionClasses`** (renderer/app.js:891) — `tbody.querySelectorAll` bei jedem Klick. Bei 5000-Jobs-Queue O(N) per click. Cache last rendered range. - ### Code-Qualität - [ ] **Test-Coverage für 3.3.0** — keine Tests für die queue-cap-prune-Logik in handleBatchDone, sortQueueJobs dynamic-throttle, log-error-recovery.