Multi-Hoster-Upload/package.json
Administrator d5bb97aefe perf(history): virtualize the History table — kill the last tab-switch layout cost (v3.3.102)
v3.3.101's gate removed the get-history parse on tab switch, but the log still
showed tab clicks at ~216ms with a ~197ms renderer long-task and NO get-history
(proc=0ms → pure browser layout, not JS). Cause: `.view{display:none}` ->
`.active{display:flex}` and the History table built up to 2000 non-virtualized
<tr>, so making the view visible laid out 2000 rows (~197ms on the RDP VM). The
queue was already virtualized; the History table was the only large non-virtual
one.

Measured the options with Playwright on the real DOM (this machine; the user's VM
is ~1.7x slower):
- current 2000 rows (auto layout): 118ms
- content-visibility + table-layout:fixed: 117ms (no help — rows still laid out)
- cap to 300 rows: 16ms, but rejected: History rows are per-file-per-hoster, so a
  single 1280-file batch is ~3840 rows and a small cap would hide a recent batch's
  links
- virtualize (40 visible of 2000): 2.3ms

Fix — virtualize renderHistoryTable, mirroring the queue's _renderVirtualRows:
- The header is always rendered; tbody#historyBody gets only the visible rows plus
  top/bottom spacer <tr> sized from VIRTUAL_ROW_HEIGHT. A rAF-coalesced scroll
  handler and a ResizeObserver on #historyContainer re-render the visible window;
  the ResizeObserver also serves as the show-trigger (a hidden 0x0 container that
  gains size on tab activation re-renders at the correct height). Sorting resets
  scrollTop and re-renders; the copy-link / sort-header click delegation is
  unchanged. _historyWorking holds the sorted working set.
- styles.css: .history-table gets table-layout:fixed plus scoped column widths so
  columns do not jump as rows scroll in and out. This is scoped to .history-table
  and does not touch the .col-* classes the queue shares.

Verified end-to-end with Playwright at 6000 rows: show cost 1.1ms (was 118ms), DOM
stays 32-42 rows, scroll maps to the right rows (top/middle/bottom), scrollbar
height exact, column widths stable, rows update on scroll. All rows remain
scrollable (no UX loss); the show cost drops ~100x.

407 tests pass; clean Electron boot.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 20:04:10 +02:00

57 lines
1.4 KiB
JSON

{
"name": "multi-hoster-uploader",
"version": "3.3.102",
"description": "Upload files to doodstream, voe, vidmoly, byse simultaneously",
"main": "main.js",
"scripts": {
"start": "electron .",
"test": "node --test tests/*.test.js tests/ui-smoke.js",
"dist": "electron-builder --win",
"release:win": "electron-builder --publish never --win nsis portable",
"release:gitea": "node scripts/release_gitea.mjs"
},
"dependencies": {
"chokidar": "^3.6.0",
"undici": "^7.16.0",
"ws": "^8.19.0"
},
"devDependencies": {
"electron": "^41.3.0",
"electron-builder": "^26.8.1",
"eslint": "^10.1.0",
"eslint-plugin-security": "^4.0.0",
"rcedit": "^4.0.1"
},
"build": {
"appId": "com.multihoster.uploader",
"productName": "Multi-Hoster-Upload",
"directories": {
"buildResources": "assets",
"output": "release"
},
"files": [
"main.js",
"preload.js",
"lib/**/*",
"renderer/**/*",
"assets/app_icon.ico",
"assets/app_icon.png"
],
"win": {
"target": [
"nsis",
"portable"
],
"icon": "assets/app_icon.ico",
"signAndEditExecutable": false
},
"nsis": {
"oneClick": false,
"perMachine": false,
"allowToChangeInstallationDirectory": true,
"createDesktopShortcut": true
},
"afterPack": "scripts/afterPack.cjs"
}
}