"use strict"; const api = { async get(url) { const r = await fetch(url, { credentials: "same-origin" }); return r.json(); }, async post(url, formData) { const r = await fetch(url, { method: "POST", body: formData, credentials: "same-origin", }); return { ok: r.ok, status: r.status, data: await r.json().catch(() => ({})) }; }, }; // --- Headerbar (eingeloggt?) --- let loggedIn = false; async function refreshHeader() { const h = await api.get("/auth/headerbar"); loggedIn = !!h.loggedin; const bar = document.getElementById("headerbar"); document.getElementById("auth-box").hidden = loggedIn; document.getElementById("compose").hidden = !loggedIn; if (loggedIn) { bar.innerHTML = ``; document.getElementById("logout-btn").addEventListener("click", async () => { await api.get("/auth/logout"); await refreshHeader(); }); } else { bar.innerHTML = ""; } } // --- Login --- document.getElementById("login-form").addEventListener("submit", async (e) => { e.preventDefault(); const res = await api.post("/auth/login", new FormData(e.target)); const msg = document.getElementById("auth-msg"); if (res.ok) { msg.textContent = ""; await refreshHeader(); } else { msg.textContent = res.data.error || "Login fehlgeschlagen."; } }); // --- Neuer Beitrag --- document.getElementById("entry-form").addEventListener("submit", async (e) => { e.preventDefault(); const res = await api.post("/entry/create", new FormData(e.target)); const msg = document.getElementById("entry-msg"); if (res.ok) { msg.textContent = ""; e.target.reset(); resetFeed(); } else { msg.textContent = res.data.error || "Beitrag fehlgeschlagen."; } }); // --- Feed mit Infinite Scroll --- let page = 0; let loading = false; let done = false; function renderEntry(e) { const el = document.createElement("article"); el.className = "entry"; const when = new Date(e.created_at * 1000).toLocaleString("de-DE"); let media = ""; if (e.filepath && e.filepath !== "none") { media = ``; } el.innerHTML = `
${escapeHtml(e.username)} ยท ${when}
${linkify(e.content)}
${media} `; return el; } async function loadMore() { if (loading || done) return; loading = true; const entries = await api.get(`/entry/feed/${page}`); const feed = document.getElementById("feed"); if (!entries.length) { done = true; const end = document.createElement("p"); end.className = "end"; end.textContent = "YOU REACHED THE END!"; feed.appendChild(end); } else { entries.forEach((e) => feed.appendChild(renderEntry(e))); page++; } loading = false; } function resetFeed() { page = 0; done = false; document.getElementById("feed").innerHTML = ""; loadMore(); } const observer = new IntersectionObserver((items) => { if (items.some((i) => i.isIntersecting)) loadMore(); }); observer.observe(document.getElementById("sentinel")); // --- Helpers --- function escapeHtml(s) { const d = document.createElement("div"); d.textContent = s ?? ""; return d.innerHTML; } function linkify(s) { const escaped = escapeHtml(s); const url = /https?:\/\/[^\s<]+/g; return escaped .replace(url, (m) => `${m}`) .replace(/\n/g, "
"); } // --- Start --- refreshHeader(); loadMore();