#295 + #296: resizable preview panel (native formats) + favorites #298

Merged
Cordy merged 6 commits from feat/pv57 into main 2026-08-20 20:59:27 +00:00
Owner

Closes-when-verified: #295, #296 (left open for dogfood per house process). Office formats follow in #297.

#295 — Preview panel:

  • Clicking a file row or its name opens a right-side panel (default 1/3 width, drag divider 280px–70%, width persisted; Escape/✕ closes, second click toggles, other rows swap in place). Row click no longer downloads — Download lives in the panel footer, row icon and row menu.
  • Formats: images/video/audio native, PDF via browser viewer in iframe, Markdown via built-in escape-first renderer, text/code as escaped <pre> (2 MB cap), everything else gets a file card.
  • Backend: ?inline=1 on the raw endpoint honoured only for a whitelisted extension set (internal/api/preview.go); SVG inline carries Content-Security-Policy: sandbox; HTML always stays attachment; all raw responses get X-Content-Type-Options: nosniff.

#296 — Favorites:

  • internal/favorites statestore (per-user, cap 200 with ErrLimit, folders allowed, re-star refreshes to front).
  • GET/POST/DELETE /api/v1/favorites (add Stats through the scoped store; list existence-filters).
  • Star toggle on every row + panel header (amber fill when on), Favorites sidebar view under Recents, i18n ×4.

Tests: TestInlineSafe, TestSetRawHeaders, TestSetToggleOrder, TestLimit, TestPersistenceRoundTrip.

Closes-when-verified: #295, #296 (left open for dogfood per house process). Office formats follow in #297. **#295 — Preview panel:** - Clicking a file row or its name opens a right-side panel (default 1/3 width, drag divider 280px–70%, width persisted; Escape/✕ closes, second click toggles, other rows swap in place). Row click no longer downloads — Download lives in the panel footer, row icon and row menu. - Formats: images/video/audio native, PDF via browser viewer in iframe, Markdown via built-in escape-first renderer, text/code as escaped `<pre>` (2 MB cap), everything else gets a file card. - Backend: `?inline=1` on the raw endpoint honoured only for a whitelisted extension set (`internal/api/preview.go`); SVG inline carries `Content-Security-Policy: sandbox`; HTML always stays attachment; all raw responses get `X-Content-Type-Options: nosniff`. **#296 — Favorites:** - `internal/favorites` statestore (per-user, cap 200 with `ErrLimit`, folders allowed, re-star refreshes to front). - `GET/POST/DELETE /api/v1/favorites` (add Stats through the scoped store; list existence-filters). - Star toggle on every row + panel header (amber fill when on), Favorites sidebar view under Recents, i18n ×4. Tests: `TestInlineSafe`, `TestSetRawHeaders`, `TestSetToggleOrder`, `TestLimit`, `TestPersistenceRoundTrip`.
fidelity fixes: teal grip, selected-row outline, name-cell star, favSet first-paint sync
Some checks failed
fix-pv57.yml / fidelity fixes: teal grip, selected-row outline, name-cell star, favSet first-paint sync (push) Failing after 0s
fix-pv57.yml / fidelity fixes: teal grip, selected-row outline, name-cell star, favSet first-paint sync (pull_request) Failing after 0s
ci / test-and-build (pull_request) Successful in 35s
fa8ca383ab
fix-pv57: single-line python strings (YAML block-scalar indent hazard)
All checks were successful
ci / test-and-build (pull_request) Successful in 35s
3b1ef83235
Cordy merged commit 92034daad6 into main 2026-08-20 20:59:27 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
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#298
No description provided.