first commit

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-20 11:05:58 +02:00
co-authored by Claude Opus 5
commit 99757361ef
15 changed files with 3020 additions and 0 deletions
+96
View File
@@ -0,0 +1,96 @@
"use strict";
const DEFAULTS = {
url: "ws://127.0.0.1:17655",
autoConnect: true,
token: ""
};
const LABELS = {
connected: "Mit der Tray-App verbunden",
connecting: "Verbindungsaufbau …",
disconnected: "Nicht verbunden"
};
const urlEl = document.getElementById("url");
const tokenEl = document.getElementById("token");
const autoEl = document.getElementById("autoConnect");
const savedEl = document.getElementById("saved");
const dotEl = document.getElementById("dot");
const stateEl = document.getElementById("state");
const statusUrlEl = document.getElementById("statusUrl");
const sinceEl = document.getElementById("since");
const statusErrEl = document.getElementById("statusErr");
/* ------------------------------------------------------- Verbindungsanzeige */
/** Verstrichene Zeit seit dem Verbindungsaufbau, in Worten. */
function elapsed(since) {
const seconds = Math.max(0, Math.round((Date.now() - since) / 1000));
if (seconds < 60) return `${seconds} s`;
const minutes = Math.floor(seconds / 60);
if (minutes < 60) return `${minutes} min`;
const hours = Math.floor(minutes / 60);
return `${hours} h ${minutes % 60} min`;
}
let lastStatus = null;
function renderStatus(status) {
if (!status) return;
lastStatus = status;
dotEl.className = "dot " + status.state;
stateEl.textContent = LABELS[status.state] || status.state;
statusUrlEl.textContent = status.url;
if (status.state === "connected" && status.connectedSince) {
const time = new Date(status.connectedSince).toLocaleTimeString();
sinceEl.textContent = `${time} (${elapsed(status.connectedSince)})`;
} else {
sinceEl.textContent = "";
}
// Im verbundenen Zustand ist ein alter Fehlertext nur noch verwirrend.
statusErrEl.textContent = status.state === "connected" ? "" : (status.lastError || "");
}
browser.runtime.onMessage.addListener((msg) => {
if (msg && msg.type === "statusChanged") renderStatus(msg.status);
});
// Die Dauer laeuft weiter, ohne dass sich der Zustand aendert.
setInterval(() => {
if (lastStatus && lastStatus.state === "connected") renderStatus(lastStatus);
}, 10000);
browser.runtime.sendMessage({ cmd: "getStatus" }).then(renderStatus);
/* ------------------------------------------------------------ Einstellungen */
async function restore() {
const cfg = await browser.storage.local.get(DEFAULTS);
urlEl.value = cfg.url;
tokenEl.value = cfg.token;
autoEl.checked = !!cfg.autoConnect;
}
document.getElementById("save").addEventListener("click", async () => {
const url = urlEl.value.trim() || DEFAULTS.url;
if (!/^wss?:\/\//i.test(url)) {
savedEl.style.color = "#d1242f";
savedEl.textContent = "URL muss mit ws:// oder wss:// beginnen";
return;
}
await browser.storage.local.set({
url,
token: tokenEl.value.trim(),
autoConnect: autoEl.checked
});
savedEl.style.color = "#2ea043";
savedEl.textContent = "Gespeichert";
setTimeout(() => (savedEl.textContent = ""), 2000);
});
restore();