"use strict"; const statusEl = document.getElementById("status"); const listEl = document.getElementById("urlList"); const openHistoryBtn = document.getElementById("openHistoryBtn"); const clearBtn = document.getElementById("clearBtn"); function setStatus(message) { statusEl.textContent = message; } function isUserCancelledError(result) { const error = result && typeof result.error === "string" ? result.error.toLowerCase() : ""; return error.includes("canceled by the user") || error.includes("cancelled by the user"); } function entryLabel(entry) { return entry && entry.fullUrl ? "full candidate" : "preview fallback"; } function formatMeta(entry) { const packName = entry && entry.packName ? entry.packName : "n/a"; const key = entry && entry.key ? entry.key : "n/a"; const bpm = entry && entry.bpm ? entry.bpm : "n/a"; return { packName, key, bpm }; } function formatTags(entry) { if (!entry || !Array.isArray(entry.tags) || !entry.tags.length) { return "No tags"; } const maxTags = 5; const tags = entry.tags.slice(0, maxTags); const suffix = entry.tags.length > maxTags ? ` +${entry.tags.length - maxTags}` : ""; return tags.join(" • ") + suffix; } function createDownloadIcon() { const ns = "http://www.w3.org/2000/svg"; const svg = document.createElementNS(ns, "svg"); svg.setAttribute("viewBox", "0 0 24 24"); svg.setAttribute("width", "22"); svg.setAttribute("height", "22"); svg.setAttribute("aria-hidden", "true"); const arrow = document.createElementNS(ns, "path"); arrow.setAttribute("d", "M12 4v10m0 0l4-4m-4 4l-4-4"); arrow.setAttribute("fill", "none"); arrow.setAttribute("stroke", "currentColor"); arrow.setAttribute("stroke-width", "2"); arrow.setAttribute("stroke-linecap", "round"); arrow.setAttribute("stroke-linejoin", "round"); const tray = document.createElementNS(ns, "path"); tray.setAttribute("d", "M4 18v1a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-1"); tray.setAttribute("fill", "none"); tray.setAttribute("stroke", "currentColor"); tray.setAttribute("stroke-width", "2"); tray.setAttribute("stroke-linecap", "round"); tray.setAttribute("stroke-linejoin", "round"); svg.appendChild(arrow); svg.appendChild(tray); return svg; } function buildRow(entry) { const li = document.createElement("li"); li.className = "url-item"; const meta = formatMeta(entry); const head = document.createElement("div"); head.className = "item-head"; const cover = document.createElement("img"); cover.className = "cover-image"; cover.src = entry.coverImageUrl || "logo-single.png"; cover.alt = "Cover art"; cover.loading = "lazy"; const info = document.createElement("div"); info.className = "item-info"; const title = document.createElement("p"); title.className = "item-title"; title.textContent = entry.fileName || entry.sampleId || "(unknown filename)"; const sub = document.createElement("p"); sub.className = "item-sub"; sub.textContent = `${meta.packName} • ${entryLabel(entry)}`; const tags = document.createElement("p"); tags.className = "item-tags"; tags.textContent = formatTags(entry); const badges = document.createElement("div"); badges.className = "item-badges"; const keyBadge = document.createElement("span"); keyBadge.className = "badge"; keyBadge.textContent = `Key ${meta.key}`; const bpmBadge = document.createElement("span"); bpmBadge.className = "badge"; bpmBadge.textContent = `BPM ${meta.bpm}`; badges.appendChild(keyBadge); badges.appendChild(bpmBadge); info.appendChild(title); info.appendChild(sub); info.appendChild(tags); info.appendChild(badges); const download = document.createElement("button"); download.type = "button"; download.className = "download-icon-btn"; download.setAttribute("aria-label", "Download sample"); download.setAttribute("title", "Download sample"); download.appendChild(createDownloadIcon()); download.addEventListener("click", async () => { const result = await browser.runtime.sendMessage({ type: "DOWNLOAD_ENTRY", entry }); if (!result || !result.ok) { if (isUserCancelledError(result)) { return; } window.alert((result && result.error) || "Download failed."); return; } setStatus(result.mode === "full" ? "Downloaded full file URL." : "Downloaded decoded preview fallback."); }); head.appendChild(cover); head.appendChild(info); head.appendChild(download); li.appendChild(head); return li; } async function loadCapturedUrls() { const response = await browser.runtime.sendMessage({ type: "GET_HISTORY" }); if (!response || !response.ok) { setStatus("Unable to load captured samples."); return; } listEl.innerHTML = ""; const entries = Array.isArray(response.history) ? response.history : []; if (!entries.length) { setStatus("No captured samples yet."); return; } setStatus(`Captured samples: ${entries.length}`); for (const entry of entries) { listEl.appendChild(buildRow(entry)); } } openHistoryBtn.addEventListener("click", async () => { await browser.runtime.sendMessage({ type: "OPEN_HISTORY" }); window.close(); }); if (clearBtn) { clearBtn.addEventListener("click", async () => { const confirmed = window.confirm("Clear all captured samples and history?"); if (!confirmed) { return; } const result = await browser.runtime.sendMessage({ type: "CLEAR_CAPTURED_STATE" }); if (!result || !result.ok) { setStatus("Unable to clear captured samples."); return; } await loadCapturedUrls(); setStatus("Captured samples cleared."); }); } loadCapturedUrls().catch(() => { setStatus("Unexpected error while loading URLs."); });