// Hintergrund-Skript: Button + Kontextmenü, öffnet den Ablage-Dialog. // Zusätzlich Auth-Broker: hält den OAuth-Token nur im Speicher dieser TB-Sitzung // (siehe auth.js). Das Passwort wird einmalig zum Login durchgereicht, daraus ein // Token geholt und sofort verworfen – es wird NIE gespeichert. const DIALOG_URL = "dialog/dialog.html"; // Auth-Broker: Dialog-/Optionsfenster fragen hier den Sitzungs-Token an bzw. // melden sich mit dem Passwort an. So muss das Passwort nur 1x pro Sitzung getippt // werden und liegt nirgends auf der Platte. browser.runtime.onMessage.addListener((msg) => { if (!msg || !msg.type) return undefined; if (msg.type === "auth:status") { return Promise.resolve({ hasToken: Auth.hasValidToken(), token: Auth.currentToken() }); } if (msg.type === "auth:logon") { return (async () => { try { const settings = await Settings.get(); if (!settings.serverUrl) throw new Error("Keine DocuWare-Server-URL konfiguriert."); Auth.reset(); const r = await Auth.logon({ ...settings, password: msg.password || "" }); // Passwort wird hier verworfen – nur der Token bleibt im Speicher. return { ok: true, mode: r.mode, token: Auth.currentToken() }; } catch (e) { return { ok: false, error: String((e && e.message) || e) }; } })(); } // Sitzung verwerfen. Immer: Token + Badge-Cache (der Cache ist serverspezifisch // und würde sonst ein ✓ aus der alten Verbindung weiterzeigen). // scope:"server" = die Server-URL hat sich geändert -> zusätzlich die gecachte // Schrankliste wegwerfen, denn deren GUIDs gehören zum alten Server. if (msg.type === "auth:logout") { Auth.reset(); ARCHIVED_CACHE.clear(); if (msg.scope === "server") { return browser.storage.local .remove("cabinets") .catch(() => {}) .then(() => ({ ok: true })); } return Promise.resolve({ ok: true }); } // Dialog meldet eine erfolgreiche Ablage -> Badge-Cache aktualisieren, damit // die Mail beim nächsten Anzeigen sofort als „abgelegt" erscheint. if (msg.type === "archive:done") { const mid = DocuWare.normalizeMessageId(msg.rfcMessageId); if (mid && msg.cabinetId) { cacheArchived(`${mid}|${msg.cabinetId}`, { found: true, docId: msg.docId || null }); } return Promise.resolve({ ok: true }); } return undefined; }); // --- „Bereits abgelegt"-Badge am Nachrichten-Button ------------------------ // Beim Anzeigen einer Mail im Standard-Schrank nach der Message-ID suchen und das // Ergebnis als Badge (✓) am messageDisplayAction-Button zeigen. Pro Message-ID + // Schrank wird das Ergebnis im Speicher gecacht (eine Suche pro Mail). const ARCHIVED_CACHE = new Map(); // "messageId|cabinetId" -> { found, docId } const ARCHIVED_CACHE_MAX = 500; // Obergrenze: Thunderbird-Sitzungen laufen wochenlang // Schreibt in den Badge-Cache und hält ihn klein (ältester Eintrag fliegt raus – // Map-Iteration ist Einfügereihenfolge). function cacheArchived(key, info) { if (ARCHIVED_CACHE.size >= ARCHIVED_CACHE_MAX && !ARCHIVED_CACHE.has(key)) { ARCHIVED_CACHE.delete(ARCHIVED_CACHE.keys().next().value); } ARCHIVED_CACHE.set(key, info); } async function rfcMessageIdOf(messageId) { try { const full = await browser.messages.getFull(messageId); const h = full && full.headers && full.headers["message-id"]; if (Array.isArray(h) && h.length) return String(h[0]).trim(); } catch (_) {} return ""; } function setBadge(tabId, found) { try { browser.messageDisplayAction.setBadgeText({ tabId, text: found ? "✓" : "" }); browser.messageDisplayAction.setTitle({ tabId, title: found ? "Bereits in DocuWare abgelegt – klicken zum Prüfen/Ablegen" : "In DocuWare ablegen", }); if (found && browser.messageDisplayAction.setBadgeBackgroundColor) { browser.messageDisplayAction.setBadgeBackgroundColor({ tabId, color: "#0e8a8a" }); } } catch (_) {} } async function updateArchivedBadge(tab, message) { const tabId = tab.id; try { if (!Auth.hasValidToken()) return setBadge(tabId, false); // ohne Login keine Suche const settings = await Settings.get(); if (!settings.serverUrl || !settings.defaultCabinetId) return setBadge(tabId, false); const mid = DocuWare.normalizeMessageId(await rfcMessageIdOf(message.id)); if (!mid) return setBadge(tabId, false); const key = `${mid}|${settings.defaultCabinetId}`; let info = ARCHIVED_CACHE.get(key); if (!info) { const hit = await DocuWare.findByMessageId(settings, settings.defaultCabinetId, mid).catch( () => null ); info = { found: !!hit, docId: hit ? hit.id : null }; cacheArchived(key, info); } setBadge(tabId, info.found); } catch (_) { setBadge(tabId, false); } } browser.messageDisplay.onMessagesDisplayed.addListener((tab, displayed) => { const msgs = Array.isArray(displayed) ? displayed : (displayed && displayed.messages) || []; if (msgs.length === 1) updateArchivedBadge(tab, msgs[0]); else setBadge(tab.id, false); // bei Mehrfachauswahl keine eindeutige Aussage }); function openDialog(messageIds) { const ids = (Array.isArray(messageIds) ? messageIds : [messageIds]) .map((id) => parseInt(id, 10)) .filter((n) => !isNaN(n)); if (!ids.length) return; // EIN Ablagefenster für die gesamte Auswahl – dialog.js arbeitet die Liste // nacheinander ab (Fortschritt „Mail 3/20"). Früher wurde pro Nachricht ein // eigenes Fenster geöffnet, was bei größerer Auswahl unbrauchbar war. const url = browser.runtime.getURL(`${DIALOG_URL}?messageIds=${ids.join(",")}`); browser.windows.create({ url, type: "popup", width: 720, height: 820, left: 100, top: 80 }); } // Button in der geöffneten Nachricht browser.messageDisplayAction.onClicked.addListener(async (tab) => { const msg = await browser.messageDisplay.getDisplayedMessage(tab.id); if (msg) openDialog([msg.id]); }); // Kontextmenü-Eintrag in der Nachrichtenliste browser.menus.create({ id: "docuware-archive", title: "In DocuWare ablegen", contexts: ["message_list"], }); browser.menus.onClicked.addListener((info) => { if (info.menuItemId !== "docuware-archive") return; const msgs = info.selectedMessages && info.selectedMessages.messages; if (msgs && msgs.length > 0) openDialog(msgs.map((m) => m.id)); }); // Tastenkürzel (Strg+Alt+I): angezeigte bzw. alle markierten Nachrichten ablegen. browser.commands.onCommand.addListener(async (command) => { if (command !== "open-archive-dialog") return; const ids = await currentMessageIds(); if (ids.length) openDialog(ids); }); // Ermittelt die "aktiven" Nachrichten: erst die im Reader angezeigte, sonst // alle im Nachrichtenlisten-Tab markierten. async function currentMessageIds() { try { const [tab] = await browser.tabs.query({ active: true, currentWindow: true }); if (tab) { const shown = await browser.messageDisplay .getDisplayedMessage(tab.id) .catch(() => null); if (shown) return [shown.id]; } const sel = await browser.mailTabs.getSelectedMessages().catch(() => null); if (sel && sel.messages && sel.messages.length) return sel.messages.map((m) => m.id); } catch (_) {} return []; }