"use strict"; const rows = document.getElementById("rows"); const nameInput = document.getElementById("name"); const createBtn = document.getElementById("create"); const errorEl = document.getElementById("error"); const statusEl = document.getElementById("status"); const portInput = document.getElementById("port"); const savePortBtn = document.getElementById("save-port"); const modal = document.getElementById("secret-modal"); const secretEl = document.getElementById("secret"); const copyBtn = document.getElementById("copy"); const closeBtn = document.getElementById("close"); function applyStatus(info) { if (info && info.listenPort) { portInput.value = String(info.listenPort); } if (info && info.bindError) { statusEl.textContent = `Could not listen on ${info.listenPort}: ${info.bindError}`; return; } statusEl.textContent = info && info.hostUp ? `This add-on is ready on 127.0.0.1:${info.listenPort} while Firefox is open.` : "You can issue and revoke secrets here anytime."; } function showError(text) { errorEl.hidden = !text; errorEl.textContent = text || ""; } function render(clients) { if (!clients.length) { rows.innerHTML = 'No clients yet. Generate a secret to get started.'; return; } rows.innerHTML = ""; for (const client of clients) { const tr = document.createElement("tr"); tr.innerHTML = ` ${escapeHtml(client.name)} ${escapeHtml(client.created || "")} ${escapeHtml(client.last_used || "never")} `; rows.appendChild(tr); } } function escapeHtml(value) { return String(value) .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """); } async function refresh() { render(await listClients()); try { applyStatus(await browser.runtime.sendMessage({ type: "status" })); } catch (err) { statusEl.textContent = "You can issue and revoke secrets here anytime."; } } savePortBtn.addEventListener("click", async () => { showError(""); try { applyStatus(await browser.runtime.sendMessage({ type: "set-port", port: portInput.value })); } catch (err) { showError(err.message); } }); createBtn.addEventListener("click", async () => { showError(""); try { const created = await createClient(nameInput.value.trim()); nameInput.value = ""; secretEl.value = created.token; modal.showModal(); await refresh(); } catch (err) { showError(err.message); } }); rows.addEventListener("click", async (event) => { const id = event.target && event.target.getAttribute("data-revoke"); if (!id) { return; } showError(""); try { await revokeClient(id); await refresh(); } catch (err) { showError(err.message); } }); copyBtn.addEventListener("click", async () => { try { await navigator.clipboard.writeText(secretEl.value); copyBtn.textContent = "Copied"; } catch (err) { showError(err.message); } }); closeBtn.addEventListener("click", () => { secretEl.value = ""; copyBtn.textContent = "Copy"; modal.close(); }); refresh().catch((err) => showError(err.message));