mirror of
https://github.com/KohakuBlueleaf/KohakuHub.git
synced 2026-07-16 10:42:49 -05:00
Image rows inside an indexed-tar listing now lazily decode a small
preview in place of the static placeholder icon. The work is gated
on visibility (IntersectionObserver), bandwidth-aware (per-format
strategy chain), and globally togglable (localStorage-persisted).
Strategy chain — first non-null wins:
1. jpeg-exif Range-read first 64 KB; parse JPEG markers;
extract APP1 / IFD1 thumbnail JPEG. Saves
up to 99% of bandwidth on EXIF-bearing JPEGs.
2. small-image ≤ 256 KB images: full read + canvas resize.
3. medium-image 256 KB – 5 MB images: full read + canvas
resize (head bytes from #1 are reused via
a shared ExtractionContext).
> 5 MB no strategy matches → placeholder stays.
The chain is registered in `_STRATEGIES`, so future formats
(video first-frame, etc.) plug in by appending another entry.
Pure-client end to end: no backend thumbnail service, no extra API.
Concurrency capped at 4 in flight; an LRU of 100 thumbnail blob URLs
caches across folder navigation and revokes the oldest when evicted.
A toolbar switch in the panel persists the user's choice via
localStorage (key: kohaku-tar-thumbnail-enabled). Default ON; OFF
short-circuits everything — no IO subscription, no Range read, no
cache lookup.
Failure semantics: every error path (network 5xx, decode failure,
abort) silently falls back to the placeholder. Never a thrown
render, never a toast. The user just sees the same icon they would
have seen pre-feature.
Test fixtures generated via scripts/dev/generate_preview_test_fixtures.py:
- with_exif_thumb.jpg — JPEG carrying an embedded thumbnail in
APP1 / IFD1, exercises the EXIF probe success path.
- no_exif_thumb.jpg — same visual, EXIF stripped, exercises
the parser's null-return + caller's strategy fall-through.
Coverage on the new modules:
TarMemberThumbnail.vue 100% / 100%
TarBrowserPanel.vue 99.42% / 84.72% (was 95.98%)
tar-thumbnail.js 78.98% / 75.75% (canvas-decode path
is jsdom-untestable)
Total UI suite: 363 passing across 40 files.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>