Skip to content

Web: image thumbnails (no full download) + large-folder memoization - #80

Merged
ehsan6sha merged 1 commit into
mainfrom
feat/web-thumbnails
Jun 22, 2026
Merged

Web: image thumbnails (no full download) + large-folder memoization#80
ehsan6sha merged 1 commit into
mainfrom
feat/web-thumbnails

Conversation

@ehsan6sha

Copy link
Copy Markdown
Member

What

Lazy image thumbnails in the web file grids (category tabs + Cloud Files) without downloading whole files, plus a large-folder perf quick-win.

How

  • ~10 KB JPEG generated client-side at upload (ui codec downscale → image pkg JPEG), stored as an encrypted sidecar in a parallel <bucket>-thumbs bucket — the grid fetches ~10 KB, never the full file.
    • Why a separate bucket: listObjects loads the whole bucket forest; same-bucket sidecars would double that load and risk the 20 k listing-cache cap — worsening large folders. The sibling bucket keeps the main listing at N; its thumb forest loads once, lazily.
  • Never fetch thousands: WebThumbnailService = in-memory LRU + encrypted IndexedDB + a concurrency-capped (5) queue + in-flight de-dup + negative cache; the fetch is 10 s-bounded and a missing -thumbs bucket is marked absent (no doomed per-image burst on a pre-feature bucket). WebThumb widget: instant on a cache hit, else a 250 ms debounce so fast-scrolled-past rows never fetch; cancels on dispose. A miss → icon (never a full download).
  • Existing files: backfilled on view (bytes already downloaded), gated to the user's own writable bucket. Thumb follows on rename/move, removed on delete. *-thumbs hidden from the bucket list. Caches cleared on sign-out (clearAll/deactivate).
  • Images only (videos/docs keep icons).
  • Perf: memoize deriveCloudFolderView (was re-scanning the whole flat list every build + every rename-dialog keystroke).

Verification

  • flutter analyze clean across all touched files; flutter build web --release green. The folder-tree unit tests still pass; the thumbnail service is web-only (JS-interop crypto), so its concurrency/cache logic isn't VM-unit-testable — reviewed by the advisor instead (semaphore verified correct), and the two gaps it flagged are fixed: a 10 s fetch timeout, a bucket-level negative cache, and sign-out cache clearing.

⚠️ Live-verify (web, signed in)

  1. Upload a new image → row shows a thumbnail; DevTools Network shows a small (~10 KB) …-thumbs fetch, not the full file.
  2. Open a large image folder + scroll fast → only a handful of thumb requests fire (≤5 concurrent; scrolled-past rows don't fetch); scroll back → instant.
  3. A pre-existing image → icon until opened once; after opening, its thumbnail appears.
  4. Rename / move / delete → thumbnail follows / disappears; no *-thumbs bucket appears in the Cloud Files bucket list.

Bumps web version to v1.11.4.17.

🤖 Generated with Claude Code

Adds lazy image thumbnails to the web file grids without downloading whole
files, plus a large-folder perf quick-win.

Thumbnails:
- A tiny (~10KB) JPEG is generated client-side at upload (ui-codec downscale →
  image-package JPEG) and stored as an encrypted sidecar in a parallel
  `<bucket>-thumbs` bucket — the grid fetches ~10KB, never the full file.
  (Same-bucket sidecars were rejected: they'd double the forest the listing
  loads + risk the 20k listing-cache cap, worsening large folders.)
- WebThumbnailService: in-memory LRU + encrypted IndexedDB cache (reuses the
  recents AES-GCM/HKDF/Hive scheme) + a concurrency-capped (5) queue +
  in-flight de-dup + a negative cache; the fetch is 10s-bounded and a missing
  `-thumbs` bucket is marked absent (no doomed per-image burst on a pre-feature
  bucket). WebThumb widget: instant on a cache hit, else a 250ms debounce so
  fast-scrolled-past rows never fetch; cancels on dispose. A miss → icon (never
  a full download).
- Existing files: backfilled on view (bytes already downloaded), gated to the
  user's own writable bucket. Thumb follows on rename/move, removed on delete.
  `*-thumbs` buckets hidden from the Cloud Files bucket list. Thumb caches are
  cleared on sign-out (clearAll/deactivate, like the recents cache).
- Images only (videos/docs keep icons). Encryption: thumbs use the proven
  uploadObject path and live at a different key than their file, so a share
  never includes a thumb.

Perf: memoize deriveCloudFolderView in the Cloud Files screen (was re-scanning
the whole flat list every build + every rename-dialog keystroke).

Bumps web app version to v1.11.4.17.

NOTE (live-verify): grid shows a small ~10KB thumb fetch (not the full file);
fast scroll fires <=5 fetches; an existing image gets a thumb after first open;
no *-thumbs bucket appears in the Cloud Files bucket list.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@ehsan6sha
ehsan6sha merged commit 706ab6b into main Jun 22, 2026
1 check passed
ehsan6sha added a commit that referenced this pull request Jun 22, 2026
…mports)

Brings the parallel Web Cloud Files (#76/#78/#80/#81) + multi-language landing (#69-73) work into the MCP integration branch. Sole conflict was the import block in fula_api_service.dart - kept both sides (AI-connections + secure_storage AND cloud_folder_marker). web_bucket_screen.dart auto-merged with all 6 P14.1 downloadBySourceBucket routing edits intact. flutter analyze: 0 errors app-wide.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0161UGEJmTpM6DM2cVZyV6Ev
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant