Ship the Go/SQLite API and Web UI, Chrome/Brave capture addon, Docker Compose, Pangolin reverse-proxy support, and a user-crontab watchdog so the binary stays running without systemd.
103 lines
3.3 KiB
JavaScript
103 lines
3.3 KiB
JavaScript
const backendUrlInput = document.getElementById("backendUrl");
|
|
const apiKeyInput = document.getElementById("apiKey");
|
|
const msg = document.getElementById("msg");
|
|
const blocklistEl = document.getElementById("blocklist");
|
|
const blockUserInput = document.getElementById("blockUserInput");
|
|
const blocklistStatus = document.getElementById("blocklistStatus");
|
|
|
|
function renderBlocklist(usernames) {
|
|
blocklistEl.innerHTML = "";
|
|
if (!usernames.length) {
|
|
const empty = document.createElement("li");
|
|
empty.className = "muted";
|
|
empty.textContent = "No blocked authors.";
|
|
blocklistEl.appendChild(empty);
|
|
return;
|
|
}
|
|
usernames.forEach((name) => {
|
|
const li = document.createElement("li");
|
|
const label = document.createElement("span");
|
|
label.textContent = name;
|
|
const remove = document.createElement("button");
|
|
remove.type = "button";
|
|
remove.textContent = "Remove";
|
|
remove.addEventListener("click", async () => {
|
|
blocklistStatus.textContent = "Syncing…";
|
|
try {
|
|
const list = await rcsRemoveBlocked(name);
|
|
renderBlocklist(list);
|
|
blocklistStatus.textContent = "Synced";
|
|
} catch (err) {
|
|
blocklistStatus.textContent = String(err && err.message ? err.message : err);
|
|
blocklistStatus.classList.add("error");
|
|
}
|
|
});
|
|
li.appendChild(label);
|
|
li.appendChild(remove);
|
|
blocklistEl.appendChild(li);
|
|
});
|
|
}
|
|
|
|
async function syncBlocklist() {
|
|
blocklistStatus.classList.remove("error");
|
|
blocklistStatus.textContent = "Syncing…";
|
|
try {
|
|
const list = await rcsPullBlocklist();
|
|
renderBlocklist(list);
|
|
blocklistStatus.textContent = `Synced (${list.length})`;
|
|
} catch (err) {
|
|
const cached = await rcsGetCachedBlocklist();
|
|
renderBlocklist(cached);
|
|
blocklistStatus.textContent = "Sync failed — showing cache. " + (err && err.message ? err.message : err);
|
|
blocklistStatus.classList.add("error");
|
|
}
|
|
}
|
|
|
|
chrome.storage.sync.get({ backendUrl: "", apiKey: "" }, (settings) => {
|
|
backendUrlInput.value = settings.backendUrl || "";
|
|
apiKeyInput.value = settings.apiKey || "";
|
|
if (settings.backendUrl) {
|
|
syncBlocklist();
|
|
} else {
|
|
rcsGetCachedBlocklist().then(renderBlocklist);
|
|
}
|
|
});
|
|
|
|
document.getElementById("save").addEventListener("click", async () => {
|
|
const backendUrl = backendUrlInput.value.trim().replace(/\/+$/, "");
|
|
const apiKey = apiKeyInput.value.trim();
|
|
try {
|
|
if (backendUrl) new URL(backendUrl);
|
|
} catch {
|
|
msg.textContent = "Invalid URL";
|
|
return;
|
|
}
|
|
if (backendUrl) {
|
|
try {
|
|
const origin = new URL(backendUrl).origin + "/*";
|
|
await chrome.permissions.request({ origins: [origin] });
|
|
} catch {
|
|
// ignore
|
|
}
|
|
}
|
|
await chrome.storage.sync.set({ backendUrl, apiKey });
|
|
msg.textContent = "Saved.";
|
|
if (backendUrl) await syncBlocklist();
|
|
});
|
|
|
|
document.getElementById("blockAdd").addEventListener("click", async () => {
|
|
const username = blockUserInput.value.trim();
|
|
if (!username) return;
|
|
blocklistStatus.classList.remove("error");
|
|
blocklistStatus.textContent = "Syncing…";
|
|
try {
|
|
const list = await rcsAddBlocked(username);
|
|
blockUserInput.value = "";
|
|
renderBlocklist(list);
|
|
blocklistStatus.textContent = "Synced";
|
|
} catch (err) {
|
|
blocklistStatus.textContent = String(err && err.message ? err.message : err);
|
|
blocklistStatus.classList.add("error");
|
|
}
|
|
});
|