mirror of
https://codeberg.org/PLG-Development/PLG-MuDiCS
synced 2026-07-06 00:47:09 +00:00
chore(display): add ai generated pdf.js integration (#58)
Co-authored-by: E44 <129310925+programmer-44@users.noreply.github.com> Reviewed-on: https://codeberg.org/PLG-Development/PLG-MuDiCS/pulls/58
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
package pkg
|
||||
|
||||
import "strings"
|
||||
|
||||
templ basicTemplate() {
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
@@ -115,6 +117,166 @@ templ deviceInfoTemplate(ip string, mac string, showQR bool) {
|
||||
}
|
||||
}
|
||||
|
||||
templ pdfTemplate(path string, serverOrigin string) {
|
||||
@basicTemplate() {
|
||||
<base href={ serverOrigin + "/" }/>
|
||||
|
||||
<div
|
||||
id="pdf"
|
||||
data-src={ "api/file/" + strings.Split(path, "/.local/share/plg-mudics/display")[1] }
|
||||
data-lib="static/pdfjs/pdf.min.mjs"
|
||||
data-worker="static/pdfjs/pdf.worker.min.mjs"
|
||||
></div>
|
||||
|
||||
<style>
|
||||
html,body,#pdf {
|
||||
margin:0;
|
||||
width:100%;
|
||||
height:100%;
|
||||
overflow:hidden;
|
||||
background:#000;
|
||||
}
|
||||
#pdf {
|
||||
display:grid;
|
||||
place-items:center;
|
||||
}
|
||||
#pdf canvas {
|
||||
grid-area:1/1;
|
||||
display:block;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="module">
|
||||
const host=document.querySelector("#pdf");
|
||||
const resolve=x=>new URL(x,document.baseURI).href;
|
||||
|
||||
const P=await import(resolve(host.dataset.lib));
|
||||
P.GlobalWorkerOptions.workerSrc=resolve(host.dataset.worker);
|
||||
|
||||
const pdf=await P.getDocument({
|
||||
url:resolve(host.dataset.src),
|
||||
useWasm:false
|
||||
}).promise;
|
||||
|
||||
const cache=new Map();
|
||||
let currentPage=1;
|
||||
let wantedPage=1;
|
||||
let requestNumber=0;
|
||||
|
||||
function renderPage(number) {
|
||||
if(cache.has(number)) return cache.get(number);
|
||||
|
||||
const promise=(async()=>{
|
||||
const page=await pdf.getPage(number);
|
||||
const original=page.getViewport({scale:1});
|
||||
const scale=Math.min(
|
||||
innerWidth/original.width,
|
||||
innerHeight/original.height
|
||||
);
|
||||
|
||||
// Use 1 on old hardware. Raise to 1.5 for sharper output.
|
||||
const pixelRatio=1;
|
||||
const viewport=page.getViewport({
|
||||
scale:scale*pixelRatio
|
||||
});
|
||||
|
||||
const canvas=document.createElement("canvas");
|
||||
canvas.width=Math.ceil(viewport.width);
|
||||
canvas.height=Math.ceil(viewport.height);
|
||||
canvas.style.width=`${viewport.width/pixelRatio}px`;
|
||||
canvas.style.height=`${viewport.height/pixelRatio}px`;
|
||||
|
||||
const task=page.render({
|
||||
canvasContext:canvas.getContext("2d"),
|
||||
viewport
|
||||
});
|
||||
|
||||
await task.promise;
|
||||
return canvas;
|
||||
})().catch(error=>{
|
||||
cache.delete(number);
|
||||
throw error;
|
||||
});
|
||||
|
||||
cache.set(number,promise);
|
||||
return promise;
|
||||
}
|
||||
|
||||
async function show(number) {
|
||||
wantedPage=Math.max(1,Math.min(pdf.numPages,number));
|
||||
const request=++requestNumber;
|
||||
const canvas=await renderPage(wantedPage);
|
||||
|
||||
// Ignore an obsolete result after multiple fast key presses.
|
||||
if(request!==requestNumber) return;
|
||||
|
||||
// The new canvas is already completely rendered.
|
||||
host.replaceChildren(canvas);
|
||||
currentPage=wantedPage;
|
||||
|
||||
pruneCache();
|
||||
preloadNeighbours();
|
||||
}
|
||||
|
||||
function preloadNeighbours() {
|
||||
const page=currentPage;
|
||||
|
||||
requestIdleCallback(async()=>{
|
||||
if(page+1<=pdf.numPages) {
|
||||
await renderPage(page+1);
|
||||
}
|
||||
if(page-1>=1) {
|
||||
await renderPage(page-1);
|
||||
}
|
||||
},{timeout:250});
|
||||
}
|
||||
|
||||
function pruneCache() {
|
||||
const keep=new Set([
|
||||
currentPage-1,
|
||||
currentPage,
|
||||
currentPage+1
|
||||
]);
|
||||
|
||||
for(const [number,promise] of cache) {
|
||||
if(keep.has(number)) continue;
|
||||
|
||||
cache.delete(number);
|
||||
promise.then(canvas=>{
|
||||
if(!canvas.isConnected) {
|
||||
canvas.width=0;
|
||||
canvas.height=0;
|
||||
}
|
||||
}).catch(()=>{});
|
||||
}
|
||||
}
|
||||
|
||||
addEventListener("keydown",event=>{
|
||||
if(event.key==="ArrowRight") {
|
||||
event.preventDefault();
|
||||
show(wantedPage+1);
|
||||
} else if(event.key==="ArrowLeft") {
|
||||
event.preventDefault();
|
||||
show(wantedPage-1);
|
||||
}
|
||||
});
|
||||
|
||||
addEventListener("resize",()=>{
|
||||
cache.clear();
|
||||
show(currentPage);
|
||||
});
|
||||
|
||||
window.pdfViewer={
|
||||
page:()=>currentPage,
|
||||
count:()=>pdf.numPages,
|
||||
show
|
||||
};
|
||||
|
||||
await show(1);
|
||||
</script>
|
||||
}
|
||||
}
|
||||
|
||||
templ startScreenTemplate(splashScreenHtml string, ip string, mac string, qrPath string) {
|
||||
@basicTemplate() {
|
||||
<div style="width: 100vw; height: 100vh; display: flex; flex-direction: row; justify-content: space-between;">
|
||||
|
||||
@@ -40,7 +40,12 @@ func OpenFile(path string) error {
|
||||
_ = imageTemplate(path).Render(context.Background(), &templateBuffer)
|
||||
err = browser.Browser.OpenHTML(templateBuffer.String())
|
||||
case "application/pdf":
|
||||
err = browser.Browser.OpenPDF(path)
|
||||
var templateBuffer bytes.Buffer
|
||||
err = pdfTemplate(path, "http://127.0.0.1:1323").Render(context.Background(), &templateBuffer)
|
||||
if err == nil {
|
||||
err = browser.Browser.OpenHTML(templateBuffer.String())
|
||||
}
|
||||
|
||||
case "application/vnd.openxmlformats-officedocument.presentationml.presentation", "application/vnd.oasis.opendocument.presentation":
|
||||
err = fileHandler.openFileWithApp(path)
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user