diff --git a/src/editor.ts b/src/editor.ts index cbfd0d5..84916f5 100644 --- a/src/editor.ts +++ b/src/editor.ts @@ -143,7 +143,7 @@ function clientJs(publicUrl: string, docJson: string): string { return ` const PUBLIC_URL = "${publicUrl}"; const DOC = ${docJson}; -let pages = DOC ? DOC.pages.map(p => ({ markdown: p.markdown, image_key: p.image_key })) : []; +let pages = DOC ? DOC.pages.map(p => ({ markdown: p.markdown, image_key: p.image_key, file: null, objectUrl: "" })) : []; let draggedIndex = null; const titleEl = document.getElementById("title"); @@ -167,34 +167,43 @@ function toast(msg){ toast._t = setTimeout(() => t.classList.remove("show"), 1800); } -async function uploadFile(file, index) { +function hasImage(p) { + return !!(p.image_key || p.objectUrl); +} + +function previewSrc(p) { + return p.objectUrl || ("/i/" + p.image_key); +} + +function stageFile(file, index) { + if (pages[index].objectUrl) URL.revokeObjectURL(pages[index].objectUrl); + pages[index].file = file; + pages[index].objectUrl = URL.createObjectURL(file); +} + +async function uploadFile(file) { const fd = new FormData(); fd.append("file", file); const res = await fetch("/upload", { method: "POST", body: fd }); const data = await res.json(); - if (data.success) { - pages[index].image_key = data.key; - render(); - toast("Scan uploaded"); - } else { - toast("Upload failed"); - } + if (!data.success) throw new Error("Upload failed"); + return data.key; } -async function uploadFiles(files, startIndex) { +function addFiles(files, startIndex) { let index = startIndex; const dateEl = document.getElementById("date"); for (const file of files) { while (index >= pages.length) { - pages.push({ markdown: "", image_key: "" }); + pages.push({ markdown: "", image_key: "", file: null, objectUrl: "" }); } - while (index < pages.length && pages[index].image_key) { + while (index < pages.length && hasImage(pages[index])) { index++; while (index >= pages.length) { - pages.push({ markdown: "", image_key: "" }); + pages.push({ markdown: "", image_key: "", file: null, objectUrl: "" }); } } - await uploadFile(file, index); + stageFile(file, index); // Prefill date from first file's lastModified if (!dateEl.value && file.lastModified) { const d = new Date(file.lastModified); @@ -202,8 +211,8 @@ async function uploadFiles(files, startIndex) { } index++; } - if (pages.length === 0 || pages[pages.length - 1].image_key) { - pages.push({ markdown: "", image_key: "" }); + if (pages.length === 0 || hasImage(pages[pages.length - 1])) { + pages.push({ markdown: "", image_key: "", file: null, objectUrl: "" }); } render(); } @@ -226,7 +235,7 @@ function parseAndDistribute(text, startIndex) { let pageIdx = startIndex; for (const section of sections) { // Find the next page with an image starting from pageIdx - while (pageIdx < pages.length && !pages[pageIdx].image_key) pageIdx++; + while (pageIdx < pages.length && !hasImage(pages[pageIdx])) pageIdx++; if (pageIdx >= pages.length) break; // drop extras pages[pageIdx].markdown = section; pageIdx++; @@ -245,7 +254,7 @@ function render(){ const container = document.getElementById("pages"); container.innerHTML = pages.map((p, i) => { - if (!p.image_key) { + if (!hasImage(p)) { return \`