Files UI: shared Quick Look viewer (files, photos, public links) #35

Closed
opened 2026-09-24 14:45:13 +00:00 by kayg · 4 comments
Owner

Owner decision (round 13, F1): one fullscreen viewer used everywhere.

  • Space or click opens it; arrow keys / swipe move between siblings; Esc closes.
  • Images: zoom/pan, EXIF; PDFs: pdf.js; audio/video: native players (with the photos transcode fallback when present); text/code: syntax highlighting; Markdown: rendered with the editor package (read-only here).
  • Right panel: linked notes for the object (DESIGN §9): shows backlinks and a block editor; the first keystroke creates Notes/<object-name>.md via the notes API.
  • Works for public links in read-only mode (no linked notes unless the link grants it).
  • calternal.js visual language (OverlaySurface, blur, spring motion); keyboard + screen reader accessible; reduced motion respected.

Design: DESIGN §9, §11, §28.

Context for the owning job

  • Repo: kayg/calternal (~/Developer/calternal). Read CLAUDE.md, CONTEXT.md and docs/DESIGN.md first; this issue's section is cited below.
  • Owner rules that always apply: file over app (plain files are the truth, the DB is an index); the server is the single writer; data loss is unacceptable; performance first, never at the cost of finesse; UI is the calternal.js design system (copy components verbatim, compare side by side with calternal.js reference screenshots; Claude does visual review); never ship sample/mock data; atomic commits; adversarial testing after API work; good enough, not perfect (merge blockers: crash/DoS, data loss, security, sync collisions).
  • Comment on this issue when you start (branch, base SHA), on each finding, when blocked, and when finished (head SHA + gate output). Never close it.
Owner decision (round 13, F1): one fullscreen viewer used everywhere. - Space or click opens it; arrow keys / swipe move between siblings; Esc closes. - Images: zoom/pan, EXIF; PDFs: pdf.js; audio/video: native players (with the photos transcode fallback when present); text/code: syntax highlighting; Markdown: rendered with the editor package (read-only here). - Right panel: **linked notes** for the object (DESIGN §9): shows backlinks and a block editor; the first keystroke creates `Notes/<object-name>.md` via the notes API. - Works for public links in read-only mode (no linked notes unless the link grants it). - calternal.js visual language (OverlaySurface, blur, spring motion); keyboard + screen reader accessible; reduced motion respected. Design: DESIGN §9, §11, §28. ## Context for the owning job - Repo: kayg/calternal (~/Developer/calternal). Read CLAUDE.md, CONTEXT.md and docs/DESIGN.md first; this issue's section is cited below. - Owner rules that always apply: file over app (plain files are the truth, the DB is an index); the server is the single writer; data loss is unacceptable; performance first, never at the cost of finesse; UI is the calternal.js design system (copy components verbatim, compare side by side with calternal.js reference screenshots; Claude does visual review); never ship sample/mock data; atomic commits; adversarial testing after API work; good enough, not perfect (merge blockers: crash/DoS, data loss, security, sync collisions). - Comment on this issue when you start (branch, base SHA), on each finding, when blocked, and when finished (head SHA + gate output). Never close it.
Author
Owner

Started (Claude files UI job). Branch worktree-agent-ac5763a033ac4a951, base afe8c7a. Scope: Files mode UI (Finder-style browser, Shared, Recent, Trash, shares and public links, Quick Look viewer, Sonner upload progress, public link page, resizable sidebar edge). Small Files API additions needed by the UI: item lookup by ID for /f/<item-id> deep links, a people list for picking share recipients, recent files, original path in Trash listings, owner name/size on public link info and public thumbnails for the gallery.

Started (Claude files UI job). Branch `worktree-agent-ac5763a033ac4a951`, base `afe8c7a`. Scope: Files mode UI (Finder-style browser, Shared, Recent, Trash, shares and public links, Quick Look viewer, Sonner upload progress, public link page, resizable sidebar edge). Small Files API additions needed by the UI: item lookup by ID for `/f/<item-id>` deep links, a people list for picking share recipients, recent files, original path in Trash listings, owner name/size on public link info and public thumbnails for the gallery.
Author
Owner

Finished (Claude files UI job). Branch worktree-agent-ac5763a033ac4a951, head d023c06 (base afe8c7a). Not pushed or merged.

Built on the real Files API:

  • Finder-style browser (/files?path=): list and grid remembered per folder, click / ⌘-click / shift-click, rubber-band, arrows + type-to-select, Enter / ⌘↓ open, ⌘↑ parent, Space Quick Look, F2 rename inline, ⌘⌫ / Delete to Trash with Undo, ⌘A, ⌘I info, ⌘⇧N new folder, ⌘⇧C copy link. Virtualized list and grid (only visible rows in the DOM). Context menu; drag to move onto folders, breadcrumbs and the sidebar tree (Undo toast); desktop drop of files and folders uploads through tus; live refresh from /api/v1/files/events.
  • Right info panel (resizable edge): metadata, shares and public links with view counts, versions (owner only: download, restore), linked notes.
  • Share dialog: people (viewer or editor) and public links with every option (custom or random name, view / download / file drop / edit / linked notes, expiry, password, download limit, presentation, hidden names), copy, edit, revoke.
  • Shared (grouped by person, write actions only with an editor grant, plus "Shared by you"), Recent, Trash (put back, empty with confirmation).
  • #35 Quick Look on OverlaySurface: zoom and pan images, pdf.js pages (lazy), native media, highlighted text and code, arrows and swipe, info and linked-notes side panel.
  • #36 upload progress: one Sonner toast in the calternal.js capsule that expands to the per-file list with pause, resume, retry, cancel; survives route changes; full-window drop target.
  • #37 public link page /s/<slug>: no chrome, password screen, file card, gallery for photo folders, list, file drop with progress.
  • #66 resizableEdge action in packages/ui, applied to the sidebar, the info panel and the Quick Look panel.
  • Touch: long-press selection mode with a bottom action bar, swipe left to copy the link, swipe right to select, action and info sheets.
  • Deep links /f/<item-id> (folder opens, file opens in Quick Look; missing items get one answer).

Small API additions in crates/plugins/files (with a test and adversarial probes): GET /files/items/{id}, /files/people, /files/recent, original_path on Trash entries, owner name / kind / size on public link info, GET /public/{slug}/thumb.

Gates: bun run check 0 errors, 0 warnings; bun run test 91 passed; bun run build done; check-generated.sh clean; cargo fmt --check, cargo clippy -p calternal-plugin-files --all-targets -D warnings, cargo test -p calternal-plugin-files 40 passed; bun e2e/files.mjs FILES E2E PASSED.

Known gaps: Markdown in Quick Look shows highlighted source (the editor package fails the web app's strict type check); linked notes have a "New note" button, not an inline editor yet; widths are stored in browser storage until settings.json lands; a 10k-entry folder is limited by the server listing (each page re-lists the directory); view-only public links cannot preview file bytes (the public download route needs the download permission); hidden file names break subfolder browsing on public links.

Finished (Claude files UI job). Branch `worktree-agent-ac5763a033ac4a951`, head `d023c06` (base `afe8c7a`). Not pushed or merged. Built on the real Files API: - Finder-style browser (`/files?path=`): list and grid remembered per folder, click / ⌘-click / shift-click, rubber-band, arrows + type-to-select, Enter / ⌘↓ open, ⌘↑ parent, Space Quick Look, F2 rename inline, ⌘⌫ / Delete to Trash with Undo, ⌘A, ⌘I info, ⌘⇧N new folder, ⌘⇧C copy link. Virtualized list and grid (only visible rows in the DOM). Context menu; drag to move onto folders, breadcrumbs and the sidebar tree (Undo toast); desktop drop of files and folders uploads through tus; live refresh from `/api/v1/files/events`. - Right info panel (resizable edge): metadata, shares and public links with view counts, versions (owner only: download, restore), linked notes. - Share dialog: people (viewer or editor) and public links with every option (custom or random name, view / download / file drop / edit / linked notes, expiry, password, download limit, presentation, hidden names), copy, edit, revoke. - Shared (grouped by person, write actions only with an editor grant, plus "Shared by you"), Recent, Trash (put back, empty with confirmation). - #35 Quick Look on OverlaySurface: zoom and pan images, pdf.js pages (lazy), native media, highlighted text and code, arrows and swipe, info and linked-notes side panel. - #36 upload progress: one Sonner toast in the calternal.js capsule that expands to the per-file list with pause, resume, retry, cancel; survives route changes; full-window drop target. - #37 public link page `/s/<slug>`: no chrome, password screen, file card, gallery for photo folders, list, file drop with progress. - #66 `resizableEdge` action in packages/ui, applied to the sidebar, the info panel and the Quick Look panel. - Touch: long-press selection mode with a bottom action bar, swipe left to copy the link, swipe right to select, action and info sheets. - Deep links `/f/<item-id>` (folder opens, file opens in Quick Look; missing items get one answer). Small API additions in crates/plugins/files (with a test and adversarial probes): `GET /files/items/{id}`, `/files/people`, `/files/recent`, `original_path` on Trash entries, owner name / kind / size on public link info, `GET /public/{slug}/thumb`. Gates: `bun run check` 0 errors, 0 warnings; `bun run test` 91 passed; `bun run build` done; `check-generated.sh` clean; `cargo fmt --check`, `cargo clippy -p calternal-plugin-files --all-targets -D warnings`, `cargo test -p calternal-plugin-files` 40 passed; `bun e2e/files.mjs` FILES E2E PASSED. Known gaps: Markdown in Quick Look shows highlighted source (the editor package fails the web app's strict type check); linked notes have a "New note" button, not an inline editor yet; widths are stored in browser storage until settings.json lands; a 10k-entry folder is limited by the server listing (each page re-lists the directory); view-only public links cannot preview file bytes (the public download route needs the download permission); hidden file names break subfolder browsing on public links.
Author
Owner

Hygiene review: the shared viewer report still lists Markdown as source text and says view-only public links cannot preview file bytes. Both are part of this issue’s viewer scope, so #35 stays open.

Hygiene review: the shared viewer report still lists Markdown as source text and says view-only public links cannot preview file bytes. Both are part of this issue’s viewer scope, so #35 stays open.
Author
Owner

Fixed in 1a403871d (Merge Files mode UI, on origin/dev); apps/web/e2e/files.mjs covers keyboard selection, Quick Look and PDF rendering, and apps/web/e2e/share.mjs covers the visitor viewer.

Fixed in 1a403871d (Merge Files mode UI, on origin/dev); apps/web/e2e/files.mjs covers keyboard selection, Quick Look and PDF rendering, and apps/web/e2e/share.mjs covers the visitor viewer.
kayg closed this issue 2026-10-03 12:53:05 +00:00
Sign in to join this conversation.
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
kayg/calternal#35
No description provided.