import { api, escapeAttr, escapeHtml } from "../core.js"; import { widgetAnmelden, widgetsLaden, widgetsZeichnen } from "./rahmen.js"; /* ── Das Bild ────────────────────────────────────────────────────────────── * * Genau **ein** Bild je Nutzer, hochgeladen oder verlinkt. Ein neues ersetzt * das alte, ohne Verwaltung und ohne Liste — das ist der ganze Reiz: Es ist * das erste Widget, das nichts abfragt, sondern etwas *ist*. * * Hochgeladen wird zum eigenen Server; verlinkt wird auf eine fremde Adresse. * Der Unterschied ist keiner der Bequemlichkeit: Ein Link holt bei jedem * Aufbau des Schreibtischs etwas von woanders, ein Upload nie. * * DAS WIDGET ZEIGT, DIE EINSTELLUNGEN STELLEN EIN. * * Hochladen, Verlinken und Entfernen standen erst im Widget selbst. Das ist die * Ausnahme gewesen, nicht die Regel: Der Ort des Wetters wird auch nicht in der * Wetterkachel gesucht. Ein Schild auf dem Schreibtisch, das zu drei Vierteln * aus Knöpfen besteht, zeigt vor allem sich selbst. * * Also: Das Widget zeigt nur noch das Bild. Die Knöpfe stehen unter * *Einstellungen → Bild* — dieselbe Datei, aber ein zweiter Ausgang * (`bildFormularHtml` / `bildFormularMontieren`), den os.js einhängt. */ const LEER = "Kein Bild — unter Einstellungen → Bild hochladen oder verlinken."; const FORM_ID = "bildForm"; let art = ""; // "datei" | "link" | "" let quelle = ""; let stand = ""; // Meldung im Einstellungsfeld let linkAuf = false; let kaputt = false; // die Adresse liefert kein Bild widgetAnmelden({ id: "bild", titel: "bild", // Das Bild soll beim Neuzeichnen nicht neu geladen werden — ein Bild, das // alle zwei Minuten kurz weiß aufblitzt, wäre schlechter als keines. stabil: true, async laden() { const d = await api("/api/image/info"); art = (d && d.art) || ""; quelle = (d && d.url) || ""; kaputt = false; }, inhalt() { if (kaputt) { return `

${ art === "link" ? "Adresse liefert kein Bild" : "Bild nicht lesbar" }

`; } return `
${ quelle ? `` : `

${LEER}

` }
`; }, montiert(el) { // Ein Bild, das nicht kommt, soll es sagen — bei einem Link ist das der // Normalfall des Tages, an dem die fremde Seite umzieht. el.querySelector(".bildw-bild")?.addEventListener("error", () => { kaputt = true; melden(art === "link" ? "Adresse liefert kein Bild" : "Bild nicht lesbar"); neu(); }); }, }); /* ── Der Ausgang in die Einstellungen ──────────────────────────────────── */ /** Das Feld für *Einstellungen → Bild*. os.js hängt es ein, kennt es aber nicht. */ export function bildFormularHtml() { return `
${formInhalt()}
`; } /** Nach dem Einhängen verdrahten. */ export function bildFormularMontieren(root) { const el = root.querySelector(`#${FORM_ID}`); if (el) verdrahte(el); } function formInhalt() { const vorschau = quelle ? `` : `kein bild`; return `
${vorschau}
${quelle ? `` : ""}
${escapeHtml(stand)}
${ linkAuf ? `
` : "" }`; } function verdrahte(el) { const datei = el.querySelector(".bildw-datei"); el.querySelector(".bildw-waehlen").addEventListener("click", () => datei.click()); datei.addEventListener("change", () => datei.files[0] && hochladen(datei.files[0])); el.querySelector(".bildw-link").addEventListener("click", () => { linkAuf = !linkAuf; formNeu(); }); const url = el.querySelector(".bildw-url"); if (url) { url.focus(); const setzen = () => linkSetzen(url.value.trim()); el.querySelector(".bildw-uebernehmen").addEventListener("click", setzen); url.addEventListener("keydown", (e) => { if (e.key === "Enter") { e.preventDefault(); setzen(); } }); } el.querySelector(".bildw-weg")?.addEventListener("click", () => linkSetzen("")); } /** Das Einstellungsfeld neu zeichnen — es steht nicht unter dem Widget-Rahmen. */ function formNeu() { const el = document.getElementById(FORM_ID); if (!el) return; el.innerHTML = formInhalt(); verdrahte(el); } async function hochladen(file) { melden("lädt hoch …"); try { await api("/api/image", { method: "POST", body: file, headers: { "Content-Type": file.type || "application/octet-stream" } }); linkAuf = false; await widgetsLaden("bild"); melden(""); } catch (e) { melden(e.message); } formNeu(); } async function linkSetzen(adresse) { melden(adresse ? "übernehme …" : "entferne …"); try { await api("/api/image", { method: "PUT", body: JSON.stringify({ url: adresse }) }); linkAuf = false; await widgetsLaden("bild"); melden(""); } catch (e) { melden(e.message); } formNeu(); } function melden(s) { stand = s; const el = document.querySelector(`#${FORM_ID} .w-stand`); if (el) el.textContent = s; } /** Neu zeichnen — stabile Widgets lässt der Rahmen sonst in Ruhe. */ function neu() { document.querySelectorAll('[data-widget="bild"]').forEach((el) => delete el.dataset.zustand); widgetsZeichnen(); }