Initial commit
This commit is contained in:
125
ui/options.js
Normal file
125
ui/options.js
Normal file
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* options.js - Einstellungsseite.
|
||||
*
|
||||
* Beim Speichern wird zusätzlich das Zugriffsrecht für genau die
|
||||
* eingetragene Adresse angefordert. Es steht bewusst nicht pauschal im
|
||||
* Manifest: Eine Erweiterung, die von Haus aus jede Adresse erreichen
|
||||
* darf, ist eine unnötig grosse Angriffsfläche.
|
||||
*/
|
||||
|
||||
import { ladeEinstellungen, speichereEinstellungen } from "../lib/settings.js";
|
||||
import { uebersetzeSeite, ruf, fehlerAnzeigen, meldungAnzeigen }
|
||||
from "./gemeinsam.js";
|
||||
|
||||
const $ = (id) => document.getElementById(id);
|
||||
const FELDER = ["baseUrl", "token", "versionLabel", "shareDays", "shareTag",
|
||||
"ignorierteKleiner"];
|
||||
|
||||
document.addEventListener("DOMContentLoaded", async () => {
|
||||
uebersetzeSeite();
|
||||
const s = await ladeEinstellungen();
|
||||
for (const f of FELDER) if ($(f)) $(f).value = s[f] ?? "";
|
||||
$("speichern").addEventListener("click", speichern);
|
||||
$("pruefen").addEventListener("click", pruefen);
|
||||
await rechtAnzeigen();
|
||||
});
|
||||
|
||||
/**
|
||||
* Zustand des Zugriffsrechts anzeigen.
|
||||
*
|
||||
* Es ist die häufigste Ursache für ein scheiterndes fetch, und ohne
|
||||
* Anzeige merkt man erst beim ersten Ablegen, dass es fehlt.
|
||||
*/
|
||||
async function rechtAnzeigen() {
|
||||
// Diese Anzeige ist Beiwerk. Fehlt das Element - etwa weil eine ältere
|
||||
// options.html geladen ist -, darf das nicht das Speichern verhindern.
|
||||
const ziel = $("recht");
|
||||
if (!ziel) return;
|
||||
const url = $("baseUrl").value.trim();
|
||||
if (!url) {
|
||||
ziel.textContent = "";
|
||||
return;
|
||||
}
|
||||
let origin;
|
||||
try {
|
||||
origin = new URL(url).origin + "/*";
|
||||
} catch {
|
||||
ziel.className = "fehler";
|
||||
ziel.textContent = browser.i18n.getMessage("errBadUrl") || "Ungültige Adresse.";
|
||||
return;
|
||||
}
|
||||
const erteilt = await browser.permissions.contains({ origins: [origin] });
|
||||
ziel.className = erteilt ? "hinweis" : "fehler";
|
||||
ziel.textContent = erteilt
|
||||
? `Zugriffsrecht erteilt für ${origin}`
|
||||
: `Zugriffsrecht fehlt für ${origin} — auf Speichern klicken.`;
|
||||
}
|
||||
|
||||
function gelesen() {
|
||||
return {
|
||||
baseUrl: $("baseUrl").value.trim().replace(/\/+$/, ""),
|
||||
token: $("token").value.trim(),
|
||||
versionLabel: $("versionLabel").value.trim() || "Thunderbird {datum}",
|
||||
shareDays: Number($("shareDays").value || 0),
|
||||
shareTag: $("shareTag").value.trim(),
|
||||
ignorierteKleiner: Number($("ignorierteKleiner").value || 0)
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Einstellungen speichern und das Zugriffsrecht anfordern.
|
||||
*
|
||||
* WICHTIG: permissions.request MUSS als erstes stehen, noch vor jedem
|
||||
* await. Der Aufruf ist nur aus einer Benutzeraktion heraus zulässig, und
|
||||
* diese Eigenschaft geht beim ersten await verloren - die Folge wäre
|
||||
* "permissions.request may only be called from a user input handler".
|
||||
*
|
||||
* Ein vorgeschaltetes permissions.contains() ist deshalb ausgeschlossen.
|
||||
* Das ist auch nicht nötig: request() löst keine Abfrage aus, wenn das
|
||||
* Recht bereits erteilt ist, sondern liefert sofort true.
|
||||
*/
|
||||
function speichern() {
|
||||
const werte = gelesen();
|
||||
|
||||
let origin;
|
||||
try {
|
||||
origin = new URL(werte.baseUrl).origin + "/*";
|
||||
} catch {
|
||||
fehlerAnzeigen(browser.i18n.getMessage("errBadUrl")
|
||||
|| "Ungültige Adresse. Erwartet wird https://rechner oder http://rechner.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Kein await davor. Die Auswertung läuft in der Zusage.
|
||||
browser.permissions.request({ origins: [origin] })
|
||||
.then(async (erteilt) => {
|
||||
if (!erteilt) {
|
||||
fehlerAnzeigen(browser.i18n.getMessage("errNoPermission")
|
||||
|| "Ohne Zugriffsrecht auf die Adresse kann die Erweiterung nicht arbeiten.");
|
||||
await rechtAnzeigen();
|
||||
return;
|
||||
}
|
||||
await speichereEinstellungen(werte);
|
||||
meldungAnzeigen(browser.i18n.getMessage("msgSaved") || "Gespeichert.");
|
||||
// Anzeige und Prüfung sind Beiwerk; ein Fehler darin soll nicht
|
||||
// aussehen, als wäre das Speichern gescheitert.
|
||||
try { await rechtAnzeigen(); } catch { /* egal */ }
|
||||
try { await pruefen(); } catch { /* egal */ }
|
||||
})
|
||||
.catch((err) => fehlerAnzeigen(err.message));
|
||||
}
|
||||
|
||||
async function pruefen() {
|
||||
$("status").className = "hinweis";
|
||||
$("status").textContent = "…";
|
||||
try {
|
||||
await speichereEinstellungen(gelesen());
|
||||
const treffer = await ruf("suchen", { query: "" });
|
||||
$("status").textContent =
|
||||
browser.i18n.getMessage("msgConnectionOk", [String(treffer.length)])
|
||||
|| `Verbindung steht (${treffer.length} Dokumente sichtbar).`;
|
||||
} catch (err) {
|
||||
$("status").className = "fehler";
|
||||
$("status").textContent = String(err.message).slice(0, 200);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user