diff --git a/backend/00-router.go b/backend/00-router.go index 5626022..51995be 100644 --- a/backend/00-router.go +++ b/backend/00-router.go @@ -73,8 +73,8 @@ func renderStartPage(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, ` Mail-Graveyard - - + +
@@ -121,9 +121,9 @@ func renderShell(w http.ResponseWriter, r *http.Request, active, readingPane str fmt.Fprintf(w, ` Mail-Graveyard - + - +
@@ -697,9 +697,9 @@ func renderAccountsPage(w http.ResponseWriter, r *http.Request, accounts []Accou fmt.Fprintf(w, ` Konten-Verwaltung - Mail-Graveyard - + - +
@@ -743,9 +743,9 @@ func renderArchivesPage(w http.ResponseWriter, r *http.Request, archives []strin fmt.Fprintf(w, ` Archiv-mbox Verwaltung - Mail-Graveyard - + - +
@@ -791,9 +791,9 @@ func renderUsersPage(w http.ResponseWriter, r *http.Request, users []AppUser, ed fmt.Fprintf(w, ` Benutzerverwaltung - Mail-Graveyard - + - +
@@ -865,9 +865,9 @@ func renderTransferPage(w http.ResponseWriter, r *http.Request, mode transferMod fmt.Fprintf(w, ` %s - Mail-Graveyard - + - +
@@ -1317,9 +1317,9 @@ func renderSourceEmailBoxPage(w http.ResponseWriter, r *http.Request, accounts [ fmt.Fprintf(w, ` Quell-Postfach - Mail-Graveyard - + - +
@@ -1361,9 +1361,9 @@ func renderTargetEmailBoxPage(w http.ResponseWriter, r *http.Request, accounts [ fmt.Fprintf(w, ` Ziel-Postfach - Mail-Graveyard - + - +
diff --git a/frontend-js/dist/app.js b/frontend-js/dist/app.js index dffa2e4..e0b930c 100644 --- a/frontend-js/dist/app.js +++ b/frontend-js/dist/app.js @@ -8,26 +8,106 @@ bar.innerHTML = ` - + - - + + - - - - - + + + + + `; ribbon.insertAdjacentElement("afterend", bar); } + function selectedPreview() { + const read = document.querySelector("#read .read-body, #transfer-preview .read-body, .pane-read .read-body"); + if (!read || read.querySelector(".ef-empty")) return null; + const subject = read.querySelector(".read-subject")?.textContent?.trim() || ""; + const meta = read.querySelector(".read-meta")?.innerText || ""; + const body = read.querySelector(".read-pre")?.innerText || ""; + const from = (meta.match(/Von:\s*(.+)/i) || [])[1]?.trim() || document.querySelector(".msg-row.active .msg-from")?.textContent?.trim() || ""; + const date = (meta.match(/Datum:\s*(.+)/i) || [])[1]?.trim() || document.querySelector(".msg-row.active .msg-date")?.textContent?.trim() || ""; + return { subject, from, date, body }; + } + + function prefixedSubject(prefix, subject) { + const clean = subject || ""; + if (new RegExp(`^${prefix}:`, "i").test(clean)) return clean; + return `${prefix}: ${clean || "(ohne Betreff)"}`; + } + + function openMailto(mail) { + const params = new URLSearchParams(); + if (mail.subject) params.set("subject", mail.subject); + if (mail.body) params.set("body", mail.body); + window.location.href = `mailto:${encodeURIComponent(mail.to || "")}?${params.toString()}`; + } + + function quoteBody(message) { + const lines = (message.body || "").split(/\r?\n/).map((line) => `> ${line}`).join("\n"); + return `\n\nAm ${message.date || "unbekanntes Datum"} schrieb ${message.from || "unbekannter Absender"}:\n${lines}`; + } + + function forwardBody(message) { + return `\n\n---------- Weitergeleitete Nachricht ----------\nVon: ${message.from || ""}\nDatum: ${message.date || ""}\nBetreff: ${message.subject || ""}\n\n${message.body || ""}`; + } + + function applyListSearch(term) { + const q = term.trim().toLowerCase(); + document.querySelectorAll(".msg-row").forEach((row) => { + row.hidden = q !== "" && !row.textContent.toLowerCase().includes(q); + }); + } + + function runSearch(input) { + const existing = document.querySelector(".searchbar .search-input"); + const form = existing?.closest("form"); + if (existing && form && input.value.trim()) { + existing.value = input.value; + form.requestSubmit(); + return; + } + applyListSearch(input.value); + } + document.addEventListener("DOMContentLoaded", ensureActionBar); document.addEventListener("click", (event) => { + const row = event.target.closest(".msg-row"); + if (!row) return; + row.closest(".pane")?.querySelectorAll(".msg-row.active").forEach((item) => item.classList.remove("active")); + row.classList.add("active"); + }); + document.addEventListener("click", (event) => { + if (event.target.closest("[data-action-new]")) { + openMailto({ to: "", subject: "", body: "" }); + } if (event.target.closest("[data-action-refresh]")) window.location.reload(); + if (event.target.closest("[data-action-reply]")) { + const message = selectedPreview(); + if (!message) { + window.alert("Bitte zuerst eine Nachricht waehlen."); + return; + } + openMailto({ to: message.from, subject: prefixedSubject("Re", message.subject), body: quoteBody(message) }); + } + if (event.target.closest("[data-action-forward]")) { + const message = selectedPreview(); + if (!message) { + window.alert("Bitte zuerst eine Nachricht waehlen."); + return; + } + openMailto({ to: "", subject: prefixedSubject("Fw", message.subject), body: forwardBody(message) }); + } + }); + document.addEventListener("input", (event) => { + const input = event.target.closest("[data-action-search]"); + if (input) runSearch(input); }); })(); diff --git a/frontend-js/dist/style.css b/frontend-js/dist/style.css index db4e342..802bc40 100644 --- a/frontend-js/dist/style.css +++ b/frontend-js/dist/style.css @@ -231,6 +231,14 @@ body.ol2013 { border-color: #ff9d34; } .action-btn.muted { color: #d7e8f5; } +.action-btn:disabled { + cursor: default; + opacity: .58; +} +.action-btn:disabled:hover { + background: transparent; + border-color: transparent; +} .action-separator { width: 1px; height: 26px;