Version banner, File locations section, final CSP (no unsafe-inline styles, frame-src none, object-src none)
The MTR viewer draws PDFs with pdf.js instead of an iframe the server's frame-ancestors refused. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -1,12 +1,25 @@
|
||||
import { assetsApi, blobUrl } from "../api/assets";
|
||||
import type { PacketPage } from "../api/types";
|
||||
import { Sheet } from "../components/Sheet";
|
||||
import { useLoad } from "../lib/useLoad";
|
||||
import { DrawingViewer } from "../packet/DrawingViewer";
|
||||
|
||||
/** Shows an MTR file: a PDF in a frame, an image as itself, and a link to open it in a new tab. */
|
||||
/** The pages of a stored PDF, for DrawingViewer: the asset's page count, else one page. */
|
||||
function pdfPages(url: string, count: number | null): PacketPage[] {
|
||||
const n = count && count > 0 ? Math.floor(count) : 1;
|
||||
return Array.from({ length: n }, (_, i) => ({ n: i + 1, pn: i + 1, type: "info", asset_id: null, dwg: null, rev: null, void: null, url }));
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows an MTR file: a PDF drawn by pdf.js, an image as itself, and a link to open it in a new tab.
|
||||
* No frame: the CSP has frame-src 'none', and the file's own frame-ancestors 'none' would refuse one anyway.
|
||||
*/
|
||||
export function MtrViewer({ assetId, title, onClose }: { assetId: string; title: string; onClose: () => void }) {
|
||||
const [meta] = useLoad((s) => assetsApi.get(assetId, s), assetId);
|
||||
const url = blobUrl(assetId);
|
||||
const mime = meta.state === "ok" ? meta.data.mime : null;
|
||||
const pdf = meta.state === "ok" && mime === "application/pdf";
|
||||
const image = !!mime?.startsWith("image/");
|
||||
return (
|
||||
<Sheet title={title} onClose={onClose} wide>
|
||||
<div className="sheet-acts start">
|
||||
@@ -19,10 +32,10 @@ export function MtrViewer({ assetId, title, onClose }: { assetId: string; title:
|
||||
</button>
|
||||
</div>
|
||||
{meta.state === "loading" ? <div className="empty slim">Loading</div> : null}
|
||||
{mime?.startsWith("image/") ? (
|
||||
<img className="mtrimg" src={url} alt={title} />
|
||||
) : meta.state !== "loading" ? (
|
||||
<iframe className="mtrframe" src={url} title={title} />
|
||||
{image ? <img className="mtrimg" src={url} alt={title} /> : null}
|
||||
{pdf ? <DrawingViewer pages={pdfPages(url, meta.data.pages)} /> : null}
|
||||
{meta.state !== "loading" && !pdf && !image ? (
|
||||
<div className="callout flush">This file cannot be shown here. Open it in a new tab.</div>
|
||||
) : null}
|
||||
</Sheet>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user