(function() { const M = window.MusicRoom; document.addEventListener("DOMContentLoaded", () => { const uploadBtn = M.$("#btn-upload"); const fileInput = M.$("#file-input"); const dropzone = M.$("#upload-dropzone"); const libraryPanel = M.$("#library-panel"); const progressEl = M.$("#upload-progress"); const progressBar = progressEl?.querySelector(".upload-progress-bar"); const progressText = progressEl?.querySelector(".upload-progress-text"); if (!uploadBtn || !fileInput || !dropzone) return; // Click upload button opens file dialog uploadBtn.onclick = () => { if (!M.currentUser) { M.showToast("Sign in to upload"); return; } fileInput.click(); }; // File input change fileInput.onchange = () => { if (fileInput.files.length > 0) { uploadFiles(fileInput.files); fileInput.value = ""; } }; // Drag and drop on library panel let dragCounter = 0; libraryPanel.ondragenter = (e) => { if (!M.currentUser) return; if (!e.dataTransfer.types.includes("Files")) return; e.preventDefault(); dragCounter++; dropzone.classList.remove("hidden"); }; libraryPanel.ondragleave = (e) => { e.preventDefault(); dragCounter--; if (dragCounter === 0) { dropzone.classList.add("hidden"); } }; libraryPanel.ondragover = (e) => { if (!M.currentUser) return; if (!e.dataTransfer.types.includes("Files")) return; e.preventDefault(); e.dataTransfer.dropEffect = "copy"; }; libraryPanel.ondrop = (e) => { e.preventDefault(); dragCounter = 0; dropzone.classList.add("hidden"); if (!M.currentUser) { M.showToast("Sign in to upload"); return; } const files = e.dataTransfer.files; if (files.length > 0) { uploadFiles(files); } }; function showProgress(current, total, filename) { if (!progressEl) return; const pct = Math.round((current / total) * 100); progressBar.style.width = pct + "%"; progressText.textContent = `Uploading ${current}/${total}: ${filename}`; progressEl.classList.remove("hidden"); uploadBtn.classList.add("hidden"); } function hideProgress() { if (!progressEl) return; progressEl.classList.add("hidden"); uploadBtn.classList.remove("hidden"); } async function uploadFiles(files) { const validExts = [".mp3", ".ogg", ".flac", ".wav", ".m4a", ".aac", ".opus", ".wma", ".mp4"]; const audioFiles = [...files].filter(f => { const ext = f.name.toLowerCase().match(/\.[^.]+$/)?.[0]; return ext && validExts.includes(ext); }); if (audioFiles.length === 0) { M.showToast("No valid audio files"); return; } let uploaded = 0; let failed = 0; let duplicates = 0; const total = audioFiles.length; for (let i = 0; i < audioFiles.length; i++) { const file = audioFiles[i]; showProgress(i + 1, total, file.name); try { const formData = new FormData(); formData.append("file", file); const res = await fetch("/api/upload", { method: "POST", body: formData }); if (res.ok) { uploaded++; } else if (res.status === 409) { // File already exists M.showToast(`Already uploaded: ${file.name}`, "warning"); duplicates++; } else { const err = await res.json().catch(() => ({})); console.error(`Upload failed for ${file.name}:`, err.error || res.status); failed++; } } catch (e) { console.error(`Upload error for ${file.name}:`, e); failed++; } } hideProgress(); if (uploaded > 0) { M.showToast(`Uploaded ${uploaded} track${uploaded > 1 ? 's' : ''}${failed > 0 ? `, ${failed} failed` : ''}`); } else { M.showToast(`Upload failed`); } } }); })();