diff --git a/docs/projects.md b/docs/projects.md index 3139542..2177363 100644 --- a/docs/projects.md +++ b/docs/projects.md @@ -40,6 +40,8 @@ A file explorer rooted at the project folder: - Click a **folder** to navigate into it. - The listing **updates by itself**: if another member or the assistant creates, renames or deletes a file while you're looking at a folder, the change appears within a second — no refresh needed. +For **PDF** files, the viewer shows the whole document as one continuous scroll — every page, in order, on phone, tablet and computer alike. A small toolbar on top gives zoom out / zoom in and tells you which page you are on (`3 / 12`). The text stays selectable and copiable where the PDF itself has real text. Pages are drawn as you reach them, so a long document opens quickly instead of making you wait for the last page. If you'd rather open it in another app, the **download** button in the header saves the original file. + For **Markdown** files (`.md`), if you have write access the viewer has two tabs: - **View** — the rendered document (the default). diff --git a/web/components/shared/file-viewer-base.js b/web/components/shared/file-viewer-base.js index b47d177..6905a81 100644 --- a/web/components/shared/file-viewer-base.js +++ b/web/components/shared/file-viewer-base.js @@ -4,6 +4,7 @@ import { keyed } from 'lit/directives/keyed.js'; import { LightElement, renderMarkdown } from '../../lib/base.js'; import { fileWatcher } from '../../lib/file-watcher.js'; import { t } from '../../lib/i18n.js'; +import './pdf-view.js'; // registers ; pdf.js itself is imported lazily /** * Shared file-viewer engine. Holds all of the fetch / kind-detection / @@ -554,17 +555,20 @@ export class FileViewerBase extends LightElement { return html`
${this._path}
`; } if (this._kind === 'pdf' && this._blobUrl) { - // `keyed` re-creates the iframe element on every new blob URL: the first - // navigation of a fresh iframe replaces its history slot instead of - // pushing one — whereas re-assigning `src` on an existing iframe pushes - // a joint session-history entry each time (during the watch-reload loop - // that buried the back button under hundreds of blob: entries). - return keyed(this._blobUrl, html``); + // Drawn by (pdf.js on canvas), never by the browser's built-in + // viewer in an `); + // Successfully compiled server-side — render the resulting PDF exactly as + // a native .pdf is rendered (see the note above). + return html``; } if (this._kind === 'svg' && this._blobUrl) { // `allow-same-origin` (and nothing else) is required so the iframe can load diff --git a/web/components/shared/pdf-view.js b/web/components/shared/pdf-view.js new file mode 100644 index 0000000..9933b16 --- /dev/null +++ b/web/components/shared/pdf-view.js @@ -0,0 +1,410 @@ +import { html, nothing } from 'lit'; +import { LightElement } from '../../lib/base.js'; +import { t } from '../../lib/i18n.js'; + +/** + * `` — a continuous, scrollable PDF renderer built on the + * vendored pdf.js. + * + * It exists because the obvious implementation — `