238 lines
8.1 KiB
JavaScript
238 lines
8.1 KiB
JavaScript
|
|
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);
|
||
|
|
});
|
||
|
|
});
|