From 73693fc3818aac9edc6cd275ea2fffc5469f7b91 Mon Sep 17 00:00:00 2001 From: sylyx Date: Fri, 5 Jun 2026 09:03:48 +0200 Subject: [PATCH] =?UTF-8?q?Feature:=20=E2=80=9Ebereits=20abgelegt"-Erkennu?= =?UTF-8?q?ng=20+=20Dedup=20=C3=BCber=20Message-ID=20(v0.10.0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Erster C2O-Parität-Schritt. Die RFC822-Message-ID wird normalisiert ins Feld EML_ID geschrieben und zur Dubletten-Erkennung genutzt. - mail.js: rfcMessageId aus den Mail-Headern - docuware.js: normalizeMessageId, cabinetFieldNames, getSearchDialogId, findByMessageId (DialogExpression, Format gem. Postman-Collection), documentViewUrl - background.js: ✓-Badge am Nachrichten-Button beim Öffnen (Suche im Standard- schrank, Cache, archive:done-Refresh); lädt dafür lib/docuware.js - dialog: EML_ID beim Upload mitschreiben; „bereits abgelegt"-Banner mit „Dokument öffnen"; Dubletten-Warnung beim Ablegen (warnen, „Trotzdem ablegen") UX-Entscheidung: Prüfung beim Öffnen (1 Schrank) + Duplikat warnen/erlauben. Schema bestätigt (EML_ID existiert). TB-Runtime-Test steht noch aus. Co-Authored-By: Claude Opus 4.8 --- background/background.js | 71 +++++++++++++++++++++++++++ dialog/dialog.css | 10 ++++ dialog/dialog.html | 18 +++++++ dialog/dialog.js | 102 +++++++++++++++++++++++++++++++++++++++ lib/docuware.js | 83 +++++++++++++++++++++++++++++++ lib/mail.js | 7 +++ manifest.json | 7 ++- 7 files changed, 296 insertions(+), 2 deletions(-) diff --git a/background/background.js b/background/background.js index 8a6a6e3..eb2d470 100644 --- a/background/background.js +++ b/background/background.js @@ -35,9 +35,80 @@ browser.runtime.onMessage.addListener((msg) => { 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) { + ARCHIVED_CACHE.set(`${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 } + +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 }; + ARCHIVED_CACHE.set(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]; // Pro Nachricht ein eigenes Ablagefenster (leicht versetzt gestapelt). diff --git a/dialog/dialog.css b/dialog/dialog.css index 59840d4..664415e 100644 --- a/dialog/dialog.css +++ b/dialog/dialog.css @@ -63,6 +63,16 @@ footer { border-top: 1px solid #e5e7eb; padding: 10px 18px; background: #fafafa; .err { color: #b91c1c; } .ok { color: #15803d; } .field.invalid input, .field.invalid textarea, .field.invalid select { border-color: #b91c1c; } +/* „Bereits abgelegt"-Banner */ +.banner { + display: flex; align-items: center; gap: 10px; + background: #ecfdf5; border: 1px solid #6ee7b7; color: #065f46; + border-radius: 4px; padding: 7px 10px; margin-bottom: 10px; font-size: 12px; +} +.banner[hidden] { display: none; } +.banner .banner-text { flex: 1; } +.banner .link { color: #065f46; text-decoration: underline; } + /* Passwort-Abfrage (Sitzungs-Login, nicht gespeichert) */ .overlay { position: fixed; inset: 0; background: rgba(0, 0, 0, .35); diff --git a/dialog/dialog.html b/dialog/dialog.html index b8a29de..aab2629 100644 --- a/dialog/dialog.html +++ b/dialog/dialog.html @@ -20,6 +20,10 @@
+
@@ -48,6 +52,20 @@
+ + +