|
// 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();
|
|
}
|
|
}
|