function runUploadAction(action) { const actions = { browse: () => el.fileInput?.click(), "start-upload": () => startUpload(), "copy-link": () => copyText("Share URL", shareUrl, shareUrl), clear: () => confirmClearQueue(), "toggle-delete-once": () => { if (!el.expiry?.querySelector(`option[value="${oneTimeRetentionKey}"]`)) return; el.expiry.value = isOneTimeDownloadSelected() ? defaultRetention : oneTimeRetentionKey; syncZipForRetention(); saveSettings(); syncMenuChecks(); updateTerminal(); }, "random-password": () => randomPassword(), "random-box-name": () => randomBoxName(), "clear-password": () => { if (!el.password || uploadLocked) return; el.password.value = ""; saveSettings(); updateTerminal(); }, "toggle-page": () => { if (!el.downloadPage || uploadLocked) return; el.downloadPage.checked = !el.downloadPage.checked; saveSettings(); syncMenuChecks(); }, help: () => openDoc("faq"), "side-help": () => { openDoc("faq"); showToast("Terminal help opened. Copy the command and feed it files."); }, "coming-soon": () => showToast("Coming Soon, not implemented just yet."), "fake-close": () => showToast("Close button denied. The upload window is staying open.", "warning"), minimize: () => showToast("Minimize requested. WarpBox stays visible so your queue is safe."), "toggle-fit": () => { document.body.classList.toggle("fit-window"); showToast("Maximize requested. The pixel rectangle feels important now."); }, "side-close": () => showToast("Box Options refuses to leave. Settings stay visible."), "side-folder-close": () => showToast("The folder window saw that click and chose denial."), }; actions[action]?.(); } document.addEventListener("click", (event) => { if (announceDisabledReason(event)) return; const menuButton = event.target.closest(".menu-button"); if (menuButton) { const item = menuButton.closest(".menu-item"); const isOpen = item.classList.contains("is-open"); closeMenus(); item.classList.toggle("is-open", !isOpen); menuButton.setAttribute("aria-expanded", String(!isOpen)); return; } const action = event.target.closest("[data-action]")?.dataset.action; if (action) { closeMenus(); runUploadAction(action); return; } const doc = event.target.closest("[data-doc]")?.dataset.doc; if (doc) { openDoc(doc); return; } const remove = event.target.closest("[data-remove]"); if (remove) { removeFile(Number(remove.dataset.remove)); return; } if (event.target.id === "duplicate-append") appendPendingDuplicates(); if (event.target.id === "duplicate-skip") { pendingDuplicateFiles = []; closeDoc(); showToast("Duplicate files skipped."); } if (event.target.id === "confirm-clear-yes") { closeDoc(); clearQueue(); } if (event.target.id === "confirm-clear-no" || event.target.id === "fallback-close") closeDoc(); if (!event.target.closest(".menu-item")) { closeMenus(); } }); document.addEventListener("mousedown", (event) => { announceDisabledReason(event); }, true); document.querySelectorAll(".menu-item").forEach((item) => { item.addEventListener("mouseenter", () => { if (!document.querySelector(".menu-item.is-open")) return; closeMenus(); item.classList.add("is-open"); item.querySelector(".menu-button")?.setAttribute("aria-expanded", "true"); }); }); el.fileInput?.addEventListener("change", () => addFiles(el.fileInput.files)); [el.dropSurface, el.dropzone].filter(Boolean).forEach((target) => { target.addEventListener("dragover", (event) => { event.preventDefault(); el.dropzone?.classList.add("is-dragging"); }); target.addEventListener("dragleave", () => el.dropzone?.classList.remove("is-dragging")); target.addEventListener("drop", (event) => { event.preventDefault(); el.dropzone?.classList.remove("is-dragging"); addFiles(event.dataTransfer.files); }); }); el.dropzone?.addEventListener("keydown", (event) => { if (event.key === "Enter" || event.key === " ") { event.preventDefault(); el.fileInput?.click(); } }); el.form?.addEventListener("submit", (event) => { event.preventDefault(); startUpload(); }); el.copyButton?.addEventListener("click", () => copyText("Share URL", shareUrl, shareUrl)); el.copyCurlButton?.addEventListener("click", () => copyText("cURL command", getCurlCommand({ full: true }))); el.docPopupClose?.addEventListener("click", closeDoc); el.modalBackdrop?.addEventListener("click", closeDoc); el.maxViews?.addEventListener("wheel", (event) => { if (el.maxViews.disabled || el.maxViews.readOnly) return; event.preventDefault(); const delta = event.deltaY < 0 ? 1 : -1; const modifier = event.ctrlKey && event.shiftKey ? 50 : event.shiftKey ? 15 : event.ctrlKey ? 5 : 1; const min = Number.parseInt(el.maxViews.min || "1", 10); const max = Number.parseInt(el.maxViews.max || "9999", 10); const current = Number.parseInt(el.maxViews.value || String(min), 10); el.maxViews.value = String(Math.max(min, Math.min(max, current + (delta * modifier)))); saveSettings(); updateTerminal(); }); el.apiKeyInput?.addEventListener("keydown", (event) => { const allowed = event.ctrlKey || event.metaKey || event.altKey || [ "Tab", "Shift", "Control", "Alt", "Meta", "Escape", "ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown", "Home", "End", "PageUp", "PageDown", ].includes(event.key); if (allowed) return; event.preventDefault(); showToast("Only pasting the API key is supported.", "warning"); setStatus("Only pasting the API key is supported"); }); el.apiKeyInput?.addEventListener("paste", () => { setTimeout(validateApiKeyField, 0); }); [el.expiry, el.password, el.maxViews, el.boxName, el.customSlug, el.downloadPage, el.allowZip, el.allowPreview, el.keepFilenames, el.privateBox, el.apiKeyMode, el.apiKeyInput].filter(Boolean).forEach((control) => { control.addEventListener("input", () => { if (control === el.boxName) syncSlugFromName(); if (control === el.customSlug) { const clean = sanitizeSlugInput(el.customSlug.value); if (el.customSlug.value !== clean) el.customSlug.value = clean; el.customSlug.dataset.auto = "false"; } if (control === el.apiKeyInput) validateApiKeyField(); saveSettings(); updateTerminal(); }); control.addEventListener("change", () => { if (control === el.expiry) syncZipForRetention(); if (control === el.apiKeyMode) syncApiKeyField(); saveSettings(); syncMenuChecks(); updateTerminal(); }); }); document.addEventListener("keydown", (event) => { if (event.key === "Escape") { closeDoc(); closeMenus(); } if (event.key === "F1") { event.preventDefault(); openDoc("faq"); } if (event.ctrlKey && !event.shiftKey && !event.altKey) { const key = event.key.toLowerCase(); if (key === "o") { event.preventDefault(); el.fileInput?.click(); } if (key === "u") { event.preventDefault(); startUpload(); } if (key === "k") { event.preventDefault(); copyText("cURL command", getCurlCommand({ full: true })); } if (key === "l") { event.preventDefault(); copyText("Share URL", shareUrl, shareUrl); } } }); window.addEventListener("beforeunload", () => { files.forEach((item) => { if (item.previewURL) URL.revokeObjectURL(item.previewURL); }); });