const SETTINGS_KEY = "warpbox.upload.settings.v1"; const el = { form: document.querySelector("#upload-form"), fileInput: document.querySelector("#file-upload"), dropSurface: document.querySelector("#drop-surface"), dropzone: document.querySelector("#dropzone"), fileList: document.querySelector("#file-list"), queueLabel: document.querySelector("#queue-label"), queueSize: document.querySelector("#queue-size"), limitHint: document.querySelector("#limit-hint"), boxSpaceText: document.querySelector("#box-space-text"), boxSpaceBar: document.querySelector("#box-space-bar"), overallBar: document.querySelector("#overall-bar"), overallPercent: document.querySelector("#overall-percent"), shareLink: document.querySelector("#share-link"), copyButton: document.querySelector("#copy-button"), startButton: document.querySelector("#start-button"), statusText: document.querySelector("#status-text"), toast: document.querySelector("#toast"), terminal: document.querySelector("#terminal-box"), copyCurlButton: document.querySelector("#copy-curl-button"), docPopup: document.querySelector("#doc-popup"), modalBackdrop: document.querySelector("#modal-backdrop"), docPopupTitle: document.querySelector("#doc-popup-title"), docPopupBody: document.querySelector("#doc-popup-body"), docPopupClose: document.querySelector("#doc-popup-close"), expiry: document.querySelector("#expiry-select"), password: document.querySelector("#password-input"), optionsForm: document.querySelector("#box-options-form"), maxViews: document.querySelector("#max-views"), boxName: document.querySelector("#box-name"), customSlug: document.querySelector("#custom-slug"), downloadPage: document.querySelector("#download-page"), allowZip: document.querySelector("#allow-zip"), allowPreview: document.querySelector("#allow-preview"), keepFilenames: document.querySelector("#keep-filenames"), privateBox: document.querySelector("#private-box"), apiKeyMode: document.querySelector("#api-key-mode"), apiKeyInput: document.querySelector("#api-key-input"), apiKeyRow: document.querySelector("#api-key-row"), apiKeyState: document.querySelector("#api-key-state"), }; const uploadsEnabled = el.form?.dataset.uploadsEnabled === "true"; const defaultRetention = el.form?.dataset.defaultRetention || "10s"; const maxFileBytes = numberFromDataset(el.form?.dataset.maxFileBytes); const maxBoxBytes = numberFromDataset(el.form?.dataset.maxBoxBytes); const oneTimeRetentionKey = "one-time"; let files = []; let shareUrl = ""; let uploadLocked = false; let statusTimer = null; let pendingDuplicateFiles = []; let apiKeyTimer = null; let completedImpactKeys = new Set(); let overallImpactDone = false; function numberFromDataset(value) { const number = Number.parseInt(value || "0", 10); return Number.isFinite(number) && number > 0 ? number : 0; } function formatBytes(bytes) { if (!bytes) return "0 B"; const units = ["B", "KB", "MB", "GB", "TB"]; let value = bytes; let unit = 0; while (value >= 1024 && unit < units.length - 1) { value /= 1024; unit += 1; } return `${value.toFixed(value >= 10 || unit === 0 ? 0 : 1)} ${units[unit]}`; } const htmlEscape = window.WarpBoxUI.htmlEscape; function shellQuote(value) { return `'${String(value).replaceAll("'", "'\\''")}'`; } function totalBytes() { return files.reduce((sum, item) => sum + item.file.size, 0); } function uploadedBytes() { return files.reduce((sum, item) => sum + item.loaded, 0); } function overallProgress() { const total = totalBytes(); return total ? Math.round((uploadedBytes() / total) * 100) : 0; } function oversizedFiles() { return maxFileBytes ? files.filter((item) => item.file.size > maxFileBytes) : []; } function isOverBoxQuota() { return maxBoxBytes ? totalBytes() > maxBoxBytes : false; } function hasQuotaError() { return isOverBoxQuota() || oversizedFiles().length > 0; } function normalizedFileName(name) { return String(name || "").trim().toLowerCase(); } function splitNameForIncrement(name) { const value = String(name || "file"); const dot = value.lastIndexOf("."); if (dot > 0 && dot < value.length - 1) return [value.slice(0, dot), value.slice(dot)]; return [value, ""]; } function nextIncrementedFileName(name, usedNames) { const [base, ext] = splitNameForIncrement(name); let index = 2; let candidate = `${base} (${index})${ext}`; while (usedNames.has(normalizedFileName(candidate))) { index += 1; candidate = `${base} (${index})${ext}`; } usedNames.add(normalizedFileName(candidate)); return candidate; } function makeQueuedFile(file, displayName = file.name) { return { file, displayName, loaded: 0, uploaded: false, failed: false, error: "", row: null, boxID: "", boxFile: null, previewURL: file.type?.startsWith("image/") ? URL.createObjectURL(file) : "", }; } function iconForFile(file) { const filename = file.name || ""; const mimeType = file.type || ""; const extension = filename.includes(".") ? filename.slice(filename.lastIndexOf(".")).toLowerCase() : ""; if (extension === ".exe") return "/static/img/icons/Program Files Icons - PNG/MSONSEXT.DLL_14_6-0.png"; if (mimeType.startsWith("image/")) return "/static/img/sprites/bitmap.png"; if (mimeType.startsWith("video/") || mimeType.startsWith("audio/")) return "/static/img/icons/netshow_notransm-1.png"; if (mimeType.startsWith("text/") || extension === ".md") return "/static/img/sprites/notepad_file-1.png"; if (mimeType.includes("zip") || mimeType.includes("compressed") || [".rar", ".7z", ".tar", ".gz"].includes(extension)) return "/static/img/icons/Windows Icons - PNG/zipfldr.dll_14_101-0.png"; if ([".ttf", ".otf", ".woff", ".woff2"].includes(extension)) return "/static/img/sprites/font.png"; if (extension === ".pdf") return "/static/img/sprites/journal.png"; if ([".html", ".css", ".js"].includes(extension)) return "/static/img/sprites/frame_web-0.png"; return "/static/img/icons/Windows Icons - PNG/ole2.dll_14_DEFICON.png"; }