Slideshow folders can include PDFs
PDFs in a slideshow folder now play alongside images and Word documents: a one-page PDF is shown whole, a longer one fits the width and scrolls through its pages during docInterval (first 30 pages - rendering a huge PDF for a few seconds on screen isn't worth the time and memory). - kiosk-app/pdf-render.mjs renders pages to canvases with pdf.js (pdfjs-dist ^6.3.289, new kiosk-app dependency): no viewer toolbar, and the slideshow's existing auto-scroll works on it. pdf.js >= 4.2.67 is required (CVE-2024-4367: older versions could run script embedded in a crafted PDF); isEvalSupported:false too. It's a module because pdf.js only ships as one - confirmed to load (with its worker) from file:// in Electron 44. - Hands pdf.js a copy of the bytes: it transfers the buffer it's given, which would break the cached copy the next time round. - slideshow.js lists .pdf as a document type; the title-request handler serves any listed non-image item (still only from that folder). - provision_install_app now copies kiosk-app/*.mjs as well - without it pdf-render.mjs would never reach an installed kiosk. Tested with the real main.js on Electron 44.5.1 under Xvfb + Openbox, app files copied with provision_install_app's own glob: a photo, a one-page PDF, a three-page PDF and a .docx played in order, twice round; the one-page PDF shown whole, the three-page one scrolled through all pages. Offline bundle rebuilt with pdfjs-dist (437 MB total, +22 MB). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Cjz8a58eB5P9sUweqd3NHm
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
<script src="node_modules/jszip/dist/jszip.min.js"></script>
|
||||
<script src="node_modules/docx-preview/dist/docx-preview.min.js"></script>
|
||||
<script src="docx-render.js"></script>
|
||||
<script type="module" src="pdf-render.mjs"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="slide" id="a"></div>
|
||||
@@ -91,7 +92,7 @@
|
||||
async function prepare(layer, item) {
|
||||
layer.innerHTML = '';
|
||||
layer.scrollTop = 0;
|
||||
layer.classList.toggle('doc', item.type === 'docx');
|
||||
layer.classList.toggle('doc', item.type !== 'image');
|
||||
if (item.type === 'image') {
|
||||
const img = new Image();
|
||||
img.style.objectFit = state.options.fit;
|
||||
@@ -103,6 +104,14 @@
|
||||
layer.appendChild(img);
|
||||
return;
|
||||
}
|
||||
if (item.type === 'pdf') {
|
||||
if (!window.KioskPdf) throw new Error('PDF renderer missing');
|
||||
const bytes = await getDocBytes(item);
|
||||
const box = document.createElement('div');
|
||||
layer.appendChild(box);
|
||||
await KioskPdf.render(bytes, box, window.innerWidth, window.innerHeight);
|
||||
return;
|
||||
}
|
||||
if (!KioskDocx.available()) throw new Error('Word document viewer missing');
|
||||
const bytes = await getDocBytes(item);
|
||||
const zoomEl = document.createElement('div');
|
||||
@@ -161,10 +170,11 @@
|
||||
// Free the old slide (a rendered document can be large) once faded out.
|
||||
setTimeout(() => { if (!old.classList.contains('show')) old.innerHTML = ''; },
|
||||
state.options.transition * 1000 + 100);
|
||||
const seconds = item.type === 'docx' ? state.options.docInterval : state.options.interval;
|
||||
if (item.type === 'docx') autoScroll(back, seconds);
|
||||
const isDoc = item.type !== 'image';
|
||||
const seconds = isDoc ? state.options.docInterval : state.options.interval;
|
||||
if (isDoc) autoScroll(back, seconds);
|
||||
// A lone document still cycles, so its scroll starts over from the top.
|
||||
if (order.length > 1 || item.type === 'docx') timer = setTimeout(next, seconds * 1000);
|
||||
if (order.length > 1 || isDoc) timer = setTimeout(next, seconds * 1000);
|
||||
}
|
||||
|
||||
window.kioskSlideshow = {
|
||||
@@ -182,7 +192,7 @@
|
||||
if (!s.items.length) {
|
||||
order = [];
|
||||
generation++;
|
||||
showMessage(s.exists ? `No images or documents in ${s.dir}` : `Folder not found: ${s.dir}`);
|
||||
showMessage(s.exists ? `No images, documents or PDFs in ${s.dir}` : `Folder not found: ${s.dir}`);
|
||||
return;
|
||||
}
|
||||
if (sameItems && !first) return;
|
||||
@@ -195,8 +205,8 @@
|
||||
pos = keep;
|
||||
clearTimeout(timer);
|
||||
const it = order[pos];
|
||||
const seconds = it.type === 'docx' ? s.options.docInterval : s.options.interval;
|
||||
if (order.length > 1 || it.type === 'docx') timer = setTimeout(next, seconds * 1000);
|
||||
const seconds = it.type !== 'image' ? s.options.docInterval : s.options.interval;
|
||||
if (order.length > 1 || it.type !== 'image') timer = setTimeout(next, seconds * 1000);
|
||||
} else {
|
||||
pos = -1;
|
||||
next();
|
||||
|
||||
Reference in New Issue
Block a user