mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 13:01:00 +00:00
feat(documents): preview thumbnails in the vault overview
Render a small JPEG preview for each stored document and show it at the card's leading edge, falling back to the kind icon when none exists. - Generate previews in the background on upload (new document-thumbnail pg-boss queue) plus a boot-time corpus backfill for existing documents; upload never blocks on or fails because of it. Images are downscaled via @napi-rs/canvas, a PDF's first page is rasterised then downscaled, every other type is skipped. Generation never throws. - Store the preview encrypted at rest in a 1:1 DocumentThumbnail side table (migration 0236) so the list/detail queries that omit the original blob never drag the preview either. Same AES-256-GCM string codec + fail-closed decrypt as the content index; wired into the key-rotation walk. - Serve it through an owner-scoped GET /api/documents/inbound/[id]/thumbnail (auth + module gate + userId-scoped query + fail-closed decrypt), always image/jpeg + nosniff + private, no-store; 404 on miss. The card renders an authed lazy <img>, onError falls back to the icon. - Add hasThumbnail to the document DTO so the card only fetches a preview that exists. Also drop the "search looks inside your documents" caption from the overview (the index-all prompt stays) and the per-card searchable marker; both were noise. Remove the now-unused i18n keys across all six locales.
This commit is contained in:
1 parent
54c78b527e
commit
ee76672798
34 files changed
+1342
-160
No files matched your search
@@ -614,6 +614,19 @@ async function main() {
|
||||
results.push(result);
|
||||
}
|
||||
|
||||
// ───── Document preview thumbnails (Bytes column) ─────
|
||||
// The small JPEG preview, stored as the `encrypt()`-string-as-UTF-8 Bytes
|
||||
// shape (base64 of the JPEG) — the same codec as the content index — so the
|
||||
// shared Bytes walk re-encrypts it under the active key. NOT NULL, so every
|
||||
// thumbnail row rotates.
|
||||
results.push(
|
||||
await rotateBytesColumn(
|
||||
"DocumentThumbnail",
|
||||
"thumbnailEncrypted",
|
||||
prisma.documentThumbnail,
|
||||
),
|
||||
);
|
||||
|
||||
console.log("\n=== Rotation summary ===");
|
||||
let totalRotated = 0;
|
||||
let totalErrors = 0;
|
||||
|
||||
Reference in new issue
Block a user