#484: server-side tile thumbnails + permanent tile actions (wave B) #511

Merged
Cordy merged 2 commits from fix-484 into main 2026-09-12 18:50:01 +00:00
Owner

Second wave of the approved file-browser mockup.

Backendinternal/preview.Thumber + GET /api/v1/thumb:

  • Downscaled JPEG renditions, 480px longest edge, quality 80; JPEG EXIF orientation honoured (bounded APP1/TIFF parser, transform applied post-downscale so copies stay small); PNG/GIF/WebP/BMP decoded too (new dep golang.org/x/image).
  • Disk cache keyed by the same per-version preview.CacheKey, in preview-cache/thumbs, 100 MB oldest-evicted, singleflight per key — same anatomy as the converter cache.
  • Memory bounded three ways: 32 MB source cap at the API, 24 MP pixel cap read from the header before decoding (decompression bombs refused), one decode at a time.
  • Scope-checked via the caller's h.Store; ETag = version key with If-None-Match → 304; honest 415/413/422 for non-images.
  • TDD: 6 tests witnessed red first (downscale, cache-hit-doesn't-read-source, non-image refusal, bomb refusal, EXIF parse, rotation applied).

Frontend (mockup variant 3): image tiles lazy-load /api/v1/thumb over the type icon (object-fit: cover; decode failure keeps the icon), checkbox permanently visible with the white halo on photos, and every tile gains the star + kebab in the name row — tiles previously had no actions at all (#509).

Second wave of the approved file-browser mockup. **Backend** — `internal/preview.Thumber` + `GET /api/v1/thumb`: - Downscaled JPEG renditions, 480px longest edge, quality 80; JPEG **EXIF orientation honoured** (bounded APP1/TIFF parser, transform applied post-downscale so copies stay small); PNG/GIF/WebP/BMP decoded too (new dep `golang.org/x/image`). - Disk cache keyed by the same per-version `preview.CacheKey`, in `preview-cache/thumbs`, 100 MB oldest-evicted, singleflight per key — same anatomy as the converter cache. - Memory bounded three ways: 32 MB source cap at the API, 24 MP pixel cap read from the header **before** decoding (decompression bombs refused), one decode at a time. - Scope-checked via the caller's `h.Store`; ETag = version key with If-None-Match → 304; honest 415/413/422 for non-images. - TDD: 6 tests witnessed red first (downscale, cache-hit-doesn't-read-source, non-image refusal, bomb refusal, EXIF parse, rotation applied). **Frontend** (mockup variant 3): image tiles lazy-load `/api/v1/thumb` over the type icon (`object-fit: cover`; decode failure keeps the icon), checkbox permanently visible with the white halo on photos, and every tile gains the star + kebab in the name row — tiles previously had no actions at all (#509).
Cordy merged commit 37a0c058d7 into main 2026-09-12 18:50:01 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: Cordy/Cairn#511
No description provided.