Multi-Hoster-Upload/renderer
Administrator 335f365497 perf(recent): virtualize the Recent-uploads panel — the last non-virtual table (v3.3.104)
The v3.3.103 log (real 2464-job, 4-hoster batch ramping to 95 concurrent) confirmed
the statSync fix held (batch-start main spike 336→231ms with 10× more jobs) and the
whole 90s ramp to 95 active was pristine (event-loop mean ~11ms, fps=32,
longtasks=0). The one residual: rapidly clicking tabs DURING the 95-active upload
produced 210-221ms renderer long-tasks (proc=0ms → layout/paint, not JS).

Cause: the Recent-uploads panel rendered every sessionFilesData row (up to 2000)
into the DOM non-virtualized — the exact analog of the History table before it was
virtualized in v3.3.102. Switching to that view laid out ~2000 rows (~210ms on the
RDP VM).

Fix — virtualize renderRecentUploadsPanel, mirroring the queue/History pattern:
- The tbody gets only the visible rows plus top/bottom spacer <tr> sized from
  VIRTUAL_ROW_HEIGHT. A rAF-coalesced scroll handler and a ResizeObserver on
  .recent-files-table-wrap re-render the visible window (the ResizeObserver also
  serves as the show-trigger when the hidden panel gains size). _recentWorking holds
  the sorted set. The insertAdjacentHTML append-only fast path is dropped — a
  ~40-row window re-render is cheap, so every render just re-renders the window; on
  prepend (date desc) the scroll position is preserved (scrollTop=0 at top, else
  += added*ROW_HEIGHT).
- Selection stays correct: _buildRecentRowHtml already stamps the selected class
  from selectedRecentIds.has(row.order) per row, so an off-screen-selected row
  renders selected when scrolled into view; selectedRecentIds remains the source of
  truth and shift-select already reads the sort cache, not the DOM.
- styles.css gives .recent-file-row a fixed 28px height so the virtualization math
  is exact (the table already had table-layout:fixed, so no column-jump fix needed).
- _renderRecentVirtualRows returns early when there are no rows, so it never wipes
  the empty-state message.

Verified with Playwright at 2000 rows (bounded container): view-show layout drops
from ~118ms to ~2.4ms, the DOM stays at 29-39 rows, scrolling maps to the correct
rows, the scrollbar height is exact, an off-screen-selected row renders with the
selected class, and the row height is exactly 28. Every large table (Queue,
History, Recent) is now virtualized.

407 tests pass; clean Electron boot.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 03:15:44 +02:00
..
app.js perf(recent): virtualize the Recent-uploads panel — the last non-virtual table (v3.3.104) 2026-06-22 03:15:44 +02:00
drop-target.html feat: floating drop target window and English column labels 2026-03-12 04:11:01 +01:00
index.html fix(queue): completed files no longer reappear in the queue after restart 2026-06-19 04:35:27 +02:00
styles.css perf(recent): virtualize the Recent-uploads panel — the last non-virtual table (v3.3.104) 2026-06-22 03:15:44 +02:00