upload: basic folder upload support

This commit is contained in:
Lukas Werner
2026-08-11 14:11:47 -07:00
parent 9644f101b3
commit c8ec356c3e
6 changed files with 80 additions and 32 deletions
+68 -27
View File
@@ -35,8 +35,9 @@ templ Upload(expirations []Expiry, uploadedLink string) {
</div>
<script>
let drop_zone = document.getElementById("drop_zone");
let desc = document.getElementById("desc");
let fileInput = document.getElementById("files");
let desc = document.getElementById("desc");
let fileInput = document.getElementById("files");
function updateDescription(len) {
desc.innerText = `${len} File`
if (len > 1) {
@@ -44,33 +45,73 @@ templ Upload(expirations []Expiry, uploadedLink string) {
}
desc.innerText += " Attached"
}
fileInput.addEventListener("change", () => {
updateDescription(fileInput.files.length)
});
drop_zone.addEventListener("click", function (ev) {
fileInput.click();
})
drop_zone.addEventListener("drop", function (ev) {
ev.preventDefault();
drop_zone.classList.remove('dragover');
const dt = ev.dataTransfer;
if (!dt) return
const files = Array.from(dt.files); // iterable
fileInput.addEventListener("change", () => {
updateDescription(fileInput.files.length);
});
const newDT = new DataTransfer();
files.forEach(f => newDT.items.add(f));
fileInput.files = newDT.files;
updateDescription(fileInput.files.length)
});
drop_zone.addEventListener("dragover", function (e) {
drop_zone.classList.add('dragover');
e.preventDefault();
});
drop_zone.addEventListener("dragleave", function (e) {
drop_zone.classList.remove('dragover');
e.preventDefault();
});
drop_zone.addEventListener("click", () => fileInput.click());
drop_zone.addEventListener("dragover", (e) => {
e.preventDefault();
drop_zone.classList.add('dragover');
});
drop_zone.addEventListener("dragleave", (e) => {
e.preventDefault();
drop_zone.classList.remove('dragover');
});
drop_zone.addEventListener("drop", async (ev) => {
ev.preventDefault();
drop_zone.classList.remove('dragover');
const items = ev.dataTransfer?.items;
if (!items) return;
const collected = [];
const readEntries = (reader) => new Promise((resolve, reject) => reader.readEntries(resolve, reject));
const getFile = (entry) => new Promise((resolve, reject) => entry.file(resolve, reject));
async function traverse(entry, path = "") {
if (entry.isFile) {
const file = await getFile(entry);
Object.defineProperty(file, "webkitRelativePath", {
value: path + file.name,
configurable: true });
collected.push(file);
} else if (entry.isDirectory) {
const reader = entry.createReader();
const prefix = path + entry.name + "/";
let entries;
do {
entries = await readEntries(reader);
for (const child of entries) {
await traverse(child, prefix);
}
} while (entries.length > 0);
}
}
const tasks = [];
for (let i = 0; i < items.length; i++) {
const entry = items[i].webkitGetAsEntry();
if (entry) {
tasks.push(traverse(entry));
} else {
const file = items[i].getAsFile();
if (file) collected.push(file);
}
}
await Promise.all(tasks);
const dt = new DataTransfer();
collected.forEach(f => dt.items.add(f));
fileInput.files = dt.files;
updateDescription(fileInput.files.length);
});
</script>
<style>.dragover {border-color: #00C950;}</style>
<div class="flex flex-col gap-3 w-full">