(function () { function ensureActionBar() { const ribbon = document.querySelector(".ribbon"); if (!ribbon || document.querySelector(".mail-actionbar")) return; const bar = document.createElement("div"); bar.className = "mail-actionbar"; 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); }); })(); (function () { const handleWidth = 6; function storageKey(container) { if (container.classList.contains("transfer-workbench")) return "mail-graveyard-transfer-widths-v1"; if (container.classList.contains("four-pane")) return "mail-graveyard-four-pane-widths-v1"; return "mail-graveyard-pane-widths-v2"; } function minWidths(container) { const count = panes(container).length; if (container.classList.contains("transfer-workbench")) return [220, 240, 320, 240, 220]; if (count === 4) return [160, 220, 280, 280]; return [160, 220, 300]; } function panes(container) { return Array.from(container.querySelectorAll(".pane")); } function widthsFromDOM(container) { return panes(container).map((pane) => Math.round(pane.getBoundingClientRect().width)); } function clampWidths(widths, total) { const mins = minWidths(this); const next = widths.map((w, i) => Math.max(mins[i] || mins[mins.length - 1], Math.round(w || mins[i] || mins[mins.length - 1]))); const minTotal = mins.slice(0, next.length).reduce((a, b) => a + b, 0); const max = Math.max(total - handleWidth * (next.length - 1), minTotal); const sum = next.reduce((a, b) => a + b, 0); if (sum > max) { let extra = sum - max; for (let i = next.length - 1; i >= 0 && extra > 0; i--) { const canTake = Math.max(0, next[i] - (mins[i] || mins[mins.length - 1])); const take = Math.min(canTake, extra); next[i] -= take; extra -= take; } } return next; } function applyWidths(container, widths) { const total = container.getBoundingClientRect().width; const w = clampWidths.call(container, widths, total); const columns = []; w.forEach((width, index) => { columns.push(index === w.length - 1 ? `minmax(${width}px, 1fr)` : `${width}px`); if (index < w.length - 1) columns.push(`${handleWidth}px`); }); container.style.gridTemplateColumns = columns.join(" "); localStorage.setItem(storageKey(container), JSON.stringify(w)); } function restore(container) { try { const saved = JSON.parse(localStorage.getItem(storageKey(container)) || "null"); if (Array.isArray(saved) && saved.length === panes(container).length) { applyWidths(container, saved); } } catch (_) { localStorage.removeItem(storageKey(container)); } } function bind(container) { if (!container || container.dataset.resizeBound === "1") return; container.dataset.resizeBound = "1"; restore(container); container.querySelectorAll(".pane-resizer").forEach((handle) => { handle.addEventListener("pointerdown", (event) => { if (window.matchMedia("(max-width: 820px)").matches) return; event.preventDefault(); handle.setPointerCapture(event.pointerId); handle.classList.add("dragging"); document.body.classList.add("resizing"); const index = Number(handle.dataset.resizeIndex || 0); const startX = event.clientX; const start = widthsFromDOM(container); function move(moveEvent) { const delta = moveEvent.clientX - startX; const next = start.slice(); const mins = minWidths(container); const left = Math.max(mins[index], start[index] + delta); const used = left - start[index]; const right = Math.max(mins[index + 1], start[index + 1] - used); const actual = start[index + 1] - right; next[index] = start[index] + actual; next[index + 1] = right; applyWidths(container, next); } function up(upEvent) { handle.releasePointerCapture(upEvent.pointerId); handle.classList.remove("dragging"); document.body.classList.remove("resizing"); window.removeEventListener("pointermove", move); window.removeEventListener("pointerup", up); } window.addEventListener("pointermove", move); window.addEventListener("pointerup", up); }); }); } function bindAll() { document.querySelectorAll(".transfer-workbench, .four-pane, .three-pane").forEach(bind); } window.addEventListener("DOMContentLoaded", bindAll); document.addEventListener("htmx:afterSwap", bindAll); })(); (function () { function closeAll() { document.querySelectorAll(".ribbon-menu.open").forEach((menu) => { menu.classList.remove("open"); const button = menu.querySelector("[data-ribbon-menu-toggle]"); if (button) button.setAttribute("aria-expanded", "false"); }); } document.addEventListener("click", (event) => { const button = event.target.closest("[data-ribbon-menu-toggle]"); if (button) { const menu = button.closest(".ribbon-menu"); const willOpen = !menu.classList.contains("open"); closeAll(); menu.classList.toggle("open", willOpen); button.setAttribute("aria-expanded", willOpen ? "true" : "false"); return; } if (!event.target.closest(".ribbon-menu")) closeAll(); }); document.addEventListener("keydown", (event) => { if (event.key === "Escape") closeAll(); }); })(); (function () { function setOpen(open) { document.body.classList.toggle("backstage-open", open); document.querySelectorAll("[data-backstage-toggle]").forEach((button) => { button.setAttribute("aria-expanded", open ? "true" : "false"); }); } document.addEventListener("click", (event) => { const toggle = event.target.closest("[data-backstage-toggle]"); if (toggle) { setOpen(!document.body.classList.contains("backstage-open")); return; } if (event.target.closest("[data-backstage-close]")) { setOpen(false); } }); document.addEventListener("keydown", (event) => { if (event.key === "Escape") setOpen(false); }); })(); (function () { function rowPayload(row) { return { source: row.dataset.source || "", folder: row.dataset.folder || "", index: row.dataset.index || "" }; } document.addEventListener("dragstart", (event) => { const row = event.target.closest(".msg-row[draggable='true']"); if (!row || !event.dataTransfer) return; event.dataTransfer.effectAllowed = "copy"; event.dataTransfer.setData("application/json", JSON.stringify(rowPayload(row))); event.dataTransfer.setData("text/plain", `${row.dataset.source || ""}/${row.dataset.folder || ""}#${row.dataset.index || ""}`); row.classList.add("dragging"); }); document.addEventListener("dragend", (event) => { const row = event.target.closest(".msg-row"); if (row) row.classList.remove("dragging"); }); document.addEventListener("dragover", (event) => { const zone = event.target.closest("[data-drop-target='manual-copy']"); if (!zone) return; event.preventDefault(); zone.classList.add("drag-over"); if (event.dataTransfer) event.dataTransfer.dropEffect = "copy"; }); document.addEventListener("dragleave", (event) => { const zone = event.target.closest("[data-drop-target='manual-copy']"); if (zone) zone.classList.remove("drag-over"); }); document.addEventListener("drop", async (event) => { const zone = event.target.closest("[data-drop-target='manual-copy']"); if (!zone) return; event.preventDefault(); zone.classList.remove("drag-over"); let payload = {}; try { payload = JSON.parse(event.dataTransfer.getData("application/json") || "{}"); } catch (_) { payload = {}; } if (!payload.source) { payload = { source: zone.dataset.source || "", folder: zone.dataset.folder || "", index: zone.dataset.index || "" }; } const select = document.querySelector("#target-account-select"); const form = new URLSearchParams(); form.set("source", payload.source); form.set("folder", payload.folder); form.set("index", payload.index); form.set("target_account", select ? select.value : ""); zone.textContent = "Kopiere..."; const response = await fetch("/view/manual-copy", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8" }, body: form.toString() }); const html = await response.text(); document.querySelector("#read").innerHTML = html; }); })(); (function () { function ensureModal() { let modal = document.getElementById("mailPreviewModal"); if (modal) return modal; modal = document.createElement("div"); modal.className = "mail-modal"; modal.id = "mailPreviewModal"; modal.setAttribute("role", "dialog"); modal.setAttribute("aria-modal", "true"); modal.setAttribute("aria-label", "Mail-Grossansicht"); modal.innerHTML = `