feat(files): a file that is not media opens in a viewer — an image, a PDF, text as text
- GET /api/files/{id}/preview: an allow-list on the stored extension (downloads/preview.py) picks
image / PDF / text; served inline under `CSP: sandbox; frame-ancestors 'self'`, the type from the
table; HTML and SVG arrive as plain text; a text is its first 1 MiB (X-Preview-Truncated), sent
as UTF-8 whatever it was written in (BOM, UTF-8, else cp1250); a NUL means binary: 415
- the list says which preview each file gets (asset.preview); FE/BE contract on kinds and header
- the viewer (shared dialog shell): ← / → through the list's such files in its order, Save, open in
a tab, the file's menu; one stage height for every kind; a no-preview card offers the file
- the name, the card's picture and the menu's Preview open it; an image up to 8 MB is its own
thumbnail
This commit is contained in:
@@ -37,6 +37,7 @@ export type KeyScope =
|
||||
| "ytPlayer"
|
||||
| "plexPlayer"
|
||||
| "mediaPlayer"
|
||||
| "fileViewer"
|
||||
| "plexBrowse";
|
||||
|
||||
const PAGE_LEVEL: ReadonlySet<KeyScope> = new Set<KeyScope>([
|
||||
@@ -234,6 +235,10 @@ export const SHORTCUTS = [
|
||||
},
|
||||
{ id: "mute", scope: "mediaPlayer", keys: ["m"], labelKey: "keys.mute" },
|
||||
|
||||
// --- the Files viewer: through the list's files that are not media ---------------------------
|
||||
{ id: "prevFile", scope: "fileViewer", keys: ["ArrowLeft"], labelKey: "keys.file" },
|
||||
{ id: "nextFile", scope: "fileViewer", keys: ["ArrowRight"], labelKey: "keys.file" },
|
||||
|
||||
// --- the Plex browser (drill-down) ----------------------------------------------------------
|
||||
{ id: "back", scope: "plexBrowse", keys: ["Backspace"], labelKey: "keys.browseBack" },
|
||||
] as const satisfies readonly Shortcut[];
|
||||
|
||||
Reference in New Issue
Block a user