Commit Graph

7 Commits

Author SHA1 Message Date
DioCrafts d98e3117b2 feat: delta/instant upload + frontend UI/UX polish
Bundles the backend+frontend delta-upload (content-dedup) feature with a
batch of frontend fixes from this session.

Upload / dedup:
- Client-hashed delta & instant upload (deltaUpload, hashWasm vendor shim)
- Backend dedup batch endpoint (dedup_service, dedup_handler, routes)
- session store owned-hash helpers; unit tests + upload-strategy bench

Frontend UI/UX:
- Colour file-type icons in grid/list (per-type tinted tiles + glyph hue)
- Robust thumbnail fallback; PDFs now show their type icon (backend
  generates no PDF thumbnails) instead of a blank tile
- Fix PDF preview: load via a same-origin blob: iframe — the API URL is
  blocked by the global X-Frame-Options: DENY in the browser's framed
  PDF viewer, matching the existing CSP `frame-src blob:` design
- Groups: localized virtual-group description (no DB schema-note leak),
  add nav.groups to the 15 missing locales, fix primary-button contrast
- Repoint --color-text-light → --color-on-accent (was faint grey on accent)
- Nudge the admin role badge off the user-menu header divider

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 16:33:08 +02:00
Edouard Vanbelle b1e472224d refactor(frontend): apply formatter, linter 2026-06-20 02:47:07 +02:00
Edouard Vanbelle 77521eb913 feat(shares): restore userVignette 2026-06-20 02:13:23 +02:00
Claude 8794324c3d perf(frontend): virtualize grid views + the files browser (list & grid)
Extends windowing to the remaining O(n)-DOM surfaces: the card-grid view of
ResourceList (recent / favorites / shared / shared-with-me / trash / search) and
the main file browser (`files/[...path]`), in both list and grid layouts.

- VirtualList gains a real grid mode: its inner window carries the caller's grid
  class (`files-grid-view`) and lays out `columns` cards per windowed row. The
  row pitch is auto-measured (grid card height tracks column width via the 4/3
  aspect-ratio thumbnail) and re-measured on resize.
- `useVirtualWindow` now distinguishes scroll from resize and exposes a
  `resizeTick`, so size-dependent layout (the grid pitch) is recomputed only when
  it can actually change.
- `gridColumns(width)` (new util) mirrors the CSS `auto-fill` / `--grid-card-min`
  / gap so the windowed row count matches the browser's real wrapping exactly;
  shared by both grid callers.
- The files browser flattens folders-then-files into one discriminated `entries`
  list rendered through VirtualList (list: columns=1; grid: columns from width).
  Grouped (swimlane) views stay fully rendered, as before — they're bounded.

ResourceList GRID, headless Chromium (1280x900), synthetic rows, before/after:

  rows  | mount→paint | DOM nodes | JS heap | scroll frame | jank frames
  ------+-------------+-----------+---------+--------------+------------
   1000 | 979→75 ms   | 19k→879   | 16→3 MB | 16→17 ms     | 0→0
   5000 | 4005→67 ms  | 95k→879   | 72→3 MB | 37→17 ms     | 26→0
  20000 |12015→65 ms  | 380k→879  |281→7 MB |197→17 ms     |1249→19

Rendered DOM and heap are flat (O(visible)) regardless of dataset size; mount is
~185x faster and scroll holds ~60fps. Verified visually mid-scroll (5 columns,
4/3 thumbnail tiles, cards land at the expected indices). The files browser
shares the same VirtualList path (it can't be mounted headless — it depends on
$app routing/session — so it's validated via svelte-check + the production build
+ the shared, separately-benchmarked component).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M8Vb9QHmLZnEMzHz7MrFy6
2026-06-19 14:48:37 +00:00
Claude 5fdcf8cb56 perf(frontend): virtualize ResourceList rows (list view)
Large folders/collections rendered every row into the DOM, so memory and
scripting time grew linearly with item count. A 20k-row list took ~12.5s to
first paint, held ~380k DOM nodes / ~281MB JS heap, and scrolled at ~4fps.

Add a reusable, dependency-free `VirtualList` that windows rows against the
nearest scrollable ancestor (the existing `.content-area`), so the
single-scrollbar UX, sticky header and end-of-list sentinel are unchanged. It
reserves the full scroll height with a sized spacer and translates a small
window of rows; row height is auto-measured for the single-column case.

Wire it into ResourceList's flat list view (recent, favorites, shared,
shared-with-me, trash, search). Grouped sections and grid view are unchanged
for now and are the next callers of the same primitive.

Measured in headless Chromium (1280x900) with synthetic rows, before/after:

  rows  | mount→paint | DOM nodes | JS heap | scroll frame | jank frames
  ------+-------------+-----------+---------+--------------+------------
   1000 | 632→70 ms   | 19k→351   | 16→2 MB | 17→17 ms     | 0→0
   5000 | 4401→54 ms  | 95k→351   | 72→3 MB | 47→17 ms     | 136→0
  20000 | 12577→56 ms | 380k→351  |281→6 MB |258→17 ms     | 1443→0

Rendered DOM and heap are now flat (O(visible)) regardless of dataset size;
scroll holds 60fps with zero jank. Correctness verified by probing a mid-list
scroll (rows land at the expected indices, positioned within the viewport).

eslint: disable core `no-undef` for `.svelte` (TypeScript/svelte-check already
resolve identifiers, including `<script generics>` type params it can't see).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M8Vb9QHmLZnEMzHz7MrFy6
2026-06-19 14:00:56 +00:00
Bradley Nelson e6279da5ce svelte refactor 2026-06-17 22:30:56 -06:00
Bradley Nelson 89e14f8f9e visual continunity 2026-06-17 22:07:18 -06:00