// retoor <retoor@molodetz.nl>
import { Http } from "./Http.js";
export class ZipDownloader {
constructor() {
this.pollMs = 1500;
this.maxPolls = 200;
this.active = new Set();
document.addEventListener("click", (event) => {
const trigger = event.target.closest("[data-zip-download]");
if (!trigger) return;
event.preventDefault();
this.start(trigger.dataset.zipDownload);
});
}
async start(enqueueUrl) {
if (this.active.has(enqueueUrl)) return;
this.active.add(enqueueUrl);
window.app.toast.show("Preparing download...", { type: "info", ms: 4000 });
try {
const job = await Http.postJson(enqueueUrl, {});
await this.poll(job.status_url);
} catch (err) {
window.app.toast.show("Could not start the download", { type: "error" });
} finally {
this.active.delete(enqueueUrl);
}
}
poll(statusUrl) {
return new Promise((resolve) => {
let attempts = 0;
const timer = setInterval(async () => {
attempts += 1;
if (attempts > this.maxPolls) {
clearInterval(timer);
window.app.toast.show("Download timed out", { type: "error" });
resolve();
return;
}
let status;
try {
status = await Http.getJson(statusUrl);
} catch {
return;
}
if (status.status === "done") {
clearInterval(timer);
this.trigger(status.download_url);
window.app.toast.show("Download ready", { type: "success" });
resolve();
} else if (status.status === "failed") {
clearInterval(timer);
window.app.toast.show("Zip failed: " + (status.error || "unknown error"), { type: "error" });
resolve();
}
}, this.pollMs);
});
}
trigger(url) {
const link = document.createElement("a");
link.href = url;
link.download = "";
document.body.appendChild(link);
link.click();
link.remove();
}
}