From 2e9d62cf95a1953365e647501e902dfd8a52c265 Mon Sep 17 00:00:00 2001 From: Marco Morath Date: Mon, 21 Sep 2026 21:44:35 +0200 Subject: [PATCH] =?UTF-8?q?Anpassungen=20f=C3=BCr=20ATN-Listing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 95 ++++++++++-- _locales/de/messages.json | 43 ------ _locales/en/messages.json | 43 ------ _locales/fr/messages.json | 43 ------ background.js | 142 +++++++++--------- build.sh | 67 ++++++--- icons/paperless-insert.svg | 12 -- icons/paperless-insert_16.png | Bin 885 -> 6655 bytes icons/paperless-insert_32.png | Bin 2012 -> 7782 bytes icons/paperless-insert_64.png | Bin 3864 -> 0 bytes icons/paperless-logo.svg | 9 -- icons/paperless-logo_16.png | Bin 680 -> 6450 bytes icons/paperless-logo_32.png | Bin 1186 -> 6956 bytes icons/paperless-logo_64.png | Bin 1927 -> 7697 bytes icons/paperless-share.svg | 15 -- icons/paperless-share_16.png | Bin 883 -> 0 bytes icons/paperless-share_32.png | Bin 2142 -> 0 bytes icons/paperless-share_64.png | Bin 4504 -> 0 bytes icons/paperless-store.svg | 14 -- icons/paperless-store_16.png | Bin 889 -> 6659 bytes icons/paperless-store_32.png | Bin 2060 -> 7830 bytes icons/paperless-store_64.png | Bin 4073 -> 0 bytes manifest.json | 3 +- ui/classify.html | 54 ------- ui/classify.js | 262 ---------------------------------- ui/insert.html | 3 +- 26 files changed, 207 insertions(+), 598 deletions(-) delete mode 100644 icons/paperless-insert.svg delete mode 100644 icons/paperless-insert_64.png delete mode 100644 icons/paperless-logo.svg delete mode 100644 icons/paperless-share.svg delete mode 100644 icons/paperless-share_16.png delete mode 100644 icons/paperless-share_32.png delete mode 100644 icons/paperless-share_64.png delete mode 100644 icons/paperless-store.svg delete mode 100644 icons/paperless-store_64.png delete mode 100644 ui/classify.html delete mode 100644 ui/classify.js diff --git a/README.md b/README.md index ba4c90d..1211a6f 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ WebExtensions, LibreOffice UNO. |---|---|---| | Kontextmenü am Anhang | Anhang in Paperless ablegen | ausgewählte Anhänge als Dokument | | Kontextmenü in der Nachrichtenliste | E-Mail in Paperless ablegen | als PDF mit eingebettetem Original, wahlweise als `.eml` | +| Beides | Ablauf | Dateiauswahl, dann je Datei Ziel und Klassifizierung | | Schaltfläche im Nachrichtenfenster | dasselbe für die angezeigte Nachricht | | | Schaltfläche im Verfassenfenster | Aus Paperless einfügen | als Anhang oder als Freigabelink | @@ -46,13 +47,45 @@ alle Anhänge im Original. Es geht also nichts verloren, auch wenn die Darstellung nicht originalgetreu ist. Wer lieber die Rohfassung will, stellt das in den Einstellungen um oder -nimmt das Häkchen im Ablegen-Dialog heraus. +wählt im ersten Fenster je Datei „Original ablegen". **Titel aus dem Betreff.** Präfixe wie `AW:` oder `Fwd:` werden entfernt — sie tragen im Archiv nichts bei und stören beim Sortieren. -**Klassifizierung direkt danach.** Sonst trägt ein neues Dokument nur den -Titel, und nachträglich macht man es erfahrungsgemäß nicht mehr. +**Zwei Schritte, dann je Datei einer.** + +``` +Fenster 1 Welche Dateien sollen abgelegt werden? + [x] Rechnung.pdf (•) Original ( ) PDF aufbereiten + [x] Anschreiben.html (•) Original ( ) PDF aufbereiten + +Fenster 2 Je Datei: Ziel und Klassifizierung + ┌─ Ziel ──────────┐ ┌─ Klassifizierung ─┐ + │ ( ) Neu │ │ Titel [.......] │ + │ (•) An bestehen-│ │ Erstellt[....] │ + │ des anhängen│ │ Korresp.[.......] │ + │ [suche] │ │ Typ [.......] │ + │ Trefferliste │ │ Tags [suche] │ + └─────────────────┘ └───────────────────┘ +``` + +Die Trennung hat einen praktischen Grund: **Ziel und Klassifizierung sind +je Datei verschieden.** Ein einzelner Dialog für alle würde die Angaben +der ersten Datei auf alle übertragen — bei einer Rechnung samt +Lastschriftmandat wäre das falsch. + +**Klassifizierung des Ziels wird übernommen.** Wählt man ein bestehendes +Dokument aus der Trefferliste, stehen Titel, Datum, Korrespondent, Typ und +Tags schon im rechten Kasten und lassen sich anpassen. Eine neue Version +gehört inhaltlich zum selben Vorgang; die Angaben neu einzutippen wäre +Arbeit für nichts, und ein abweichender Korrespondent brächte die Version +vom Original weg. + +**Ein Aufruf je Datei.** Bewusst nicht alle in einem Durchgang: Manifest V3 +beendet die Ereignisseite, sobald sie untätig scheint, und ein Aufruf über +zehn Anhänge lief regelmäßig in `Receiving end does not exist`. Nebeneffekt: +Der Fortschritt ist sichtbar, und scheitert eine Datei, sind die übrigen +trotzdem abgelegt. ### Warum kein originalgetreues Abbild @@ -173,7 +206,7 @@ Dauerhaft: ``` Add-ons-Verwaltung → Zahnrad → Add-on aus Datei installieren -→ paperless-thunderbird-1.0.0.xpi +→ paperless-connector-.xpi ``` --- @@ -228,7 +261,7 @@ bei der LibreOffice-Fassung, weil hier **keine fremden Dokumente geöffnet** werden — der heikelste Punkt entfällt. Die wichtigsten Maßnahmen: - Zugriffsrecht nur für die eingetragene Adresse, zur Laufzeit erbeten -- Nur die fünf tatsächlich benötigten Berechtigungen — `compose.send` war +- Nur die sechs tatsächlich benötigten Berechtigungen — `compose.send` war im ersten Entwurf enthalten, ohne je benutzt zu werden, und ist entfernt - Nur `http` und `https` als Basisadresse - Dateinamen aus Anhängen werden bereinigt — sie stammen vom Absender @@ -248,9 +281,11 @@ background.js Menüs, Schaltflächen, Vermittlung lib/ client.js REST-Client (fetch, FormData) settings.js Einstellungen, Dateinamen, Hilfsmittel + pdf.js PDF-Erzeuger ohne Fremdbibliothek + mailpdf.js Aufbereitung einer Nachricht ui/ - store.html/.js Ablegen: Anhänge oder ganze Nachricht - classify.html/.js Klassifizierung direkt danach + store.html/.js Schritt 1: welche Dateien + schritt.html/.js Schritt 2: Ziel und Klassifizierung je Datei insert.html/.js Einfügen als Anhang oder Link options.html/.js Verbindung einrichten gemeinsam.js/.css geteilte Hilfsmittel @@ -259,11 +294,28 @@ icons/ ``` Die Dialoge sprechen **nicht** selbst mit Paperless, sondern lassen die -Ereignisseite arbeiten. Dort hängt die zur Laufzeit erteilte Berechtigung; -ein Dialogfenster müsste sie sonst erneut erbitten. +Ereignisseite arbeiten. So liegen Token und Verbindungslogik an einer +Stelle, und die Dialoge bleiben reine Oberfläche. + +Damit die Ereignisseite währenddessen nicht beendet wird, hält jeder +Dialog eine offene Verbindung dorthin und sendet alle 15 Sekunden ein +Lebenszeichen. Manifest V3 räumt sie sonst mitten im Vorgang ab — +Wartezeiten zählen dort nicht als Ereignis. --- +### Eine Stolperstelle bei der Gestaltung + +Die Dialoge sind auf feste Fensterhöhe mit blätternden Listen ausgelegt. +Drei Dinge mussten dafür stimmen, und jedes einzelne führte für sich zum +Überlauf: + +| | | +|---|---| +| `height: 100vh` am Body | mit `min-height` wächst die Seite über das Fenster hinaus | +| kein `fieldset` als Flex-Behälter | dessen innerer anonymer Kasten löst `height: 100%` nicht auf — deshalb `
` | +| kein `flex-wrap` bei den Spalten | mit Umbruch bemisst sich die Zeilenhöhe nach dem Inhalt, nicht nach dem Behälter | + ## Vor einer Veröffentlichung | Datei | Was | @@ -274,6 +326,28 @@ ein Dialogfenster müsste sie sonst erneut erbitten. Die Kennung sollte einer Domain folgen, die dir gehört. Aktuell steht dort `paperless@example.org`. +### Anforderungen der Prüfung auf addons.thunderbird.net + +Aus der Ablehnung von 1.16.0 übernommen, seit 1.16.1 umgesetzt: + +- **Kein async-Listener an `runtime.onMessage`.** Ein async-Listener + gibt immer ein Promise zurück und beansprucht damit jede Nachricht. Der + Listener prüft deshalb synchron Absender und Befehl und gibt nur für + bekannte Befehle das Promise zurück, sonst `false`. Neue Befehle kommen + in die Tabelle `BEFEHLE` in `background.js`. +- **Keine ungenutzten Dateien im Paket.** `build.sh` packt nur die in + `DATEIEN` aufgeführten Dateien und weist auf alles andere im Quellbaum + hin. `make_icons.py` erzeugt weiterhin alle Symbole samt SVG — im Paket + landen nur die sieben, die Manifest und Code verwenden. +- **Beschreibung mit Bedienungsanleitung und Bildschirmfotos** auf der + Add-on-Seite, siehe `ATN-BESCHREIBUNG.md`. +- Vor dem Hochladen den Linter laufen lassen: + ```bash + git clone https://github.com/thunderbird/webext-linter + cd webext-linter && npm install + node verify.js /pfad/zu/paperless-connector-.xpi + ``` + --- ## Lizenz @@ -288,6 +362,3 @@ schließt jede Gewährleistung aus. Vor dem ersten produktiven Einsatz: eine Testnachricht ablegen und in Paperless nachsehen, ob Titel, Datum und Anhänge stimmen. - -Es wird weder eine Gewähr noch eine Haftung übernommen. Für entstandene -Schäden haftet der jeweilige Anwender. Die Nutzun erfolgt auf eigenes Risiko. diff --git a/_locales/de/messages.json b/_locales/de/messages.json index 926ee2a..5257776 100644 --- a/_locales/de/messages.json +++ b/_locales/de/messages.json @@ -26,9 +26,6 @@ "storeHintPreselect": { "message": "Kleine Bilder und Signaturen sind vorab abgewählt — sie sind meist Teil der Nachricht, keine eigenen Dokumente." }, - "storeWholeMessage": { - "message": "Die vollständige Nachricht als .eml" - }, "storeAttachmentsInside": { "message": "Die $1 Anhänge bleiben darin enthalten.", "placeholders": { @@ -46,26 +43,9 @@ "storeTargetExisting": { "message": "Als neue Version an ein bestehendes anhängen" }, - "storeHintTitleMulti": { - "message": "Bei mehreren Dateien wird der Titel um den Dateinamen ergänzt." - }, - "storeClassifyAfter": { - "message": "Nach dem Ablegen die Klassifizierung bearbeiten" - }, "classifyTitle": { "message": "Klassifizierung bearbeiten" }, - "classifyHintNew": { - "message": "Unbekannte Korrespondenten und Dokumenttypen werden angelegt." - }, - "classifyMoreStored": { - "message": "$1 Dateien abgelegt", - "placeholders": { - "1": { - "content": "$1" - } - } - }, "insertTitle": { "message": "Aus Paperless einfügen" }, @@ -235,9 +215,6 @@ "errNoPermission": { "message": "Ohne Zugriffsrecht auf die Adresse kann die Erweiterung nicht arbeiten." }, - "linkLabel": { - "message": "Datei" - }, "linkValidUntil": { "message": "Link gültig bis $1", "placeholders": { @@ -279,12 +256,6 @@ "optionsHintMailFormat": { "message": "Das PDF ist lesbar und durchsuchbar; HTML-Nachrichten werden dabei als Text gesetzt. Die Originalnachricht steckt als Datei im PDF, es geht also nichts verloren." }, - "storeWholePdf": { - "message": "Die Nachricht als PDF, mit eingebettetem Original" - }, - "storeAsPdf": { - "message": "Als PDF aufbereiten, Original und Anhänge einbetten" - }, "fieldPdfFontSize": { "message": "Schriftgröße" }, @@ -321,9 +292,6 @@ "artPdfUnavailable": { "message": "Für dieses Format nicht möglich - nur Textdateien lassen sich aufbereiten." }, - "btnSkipAll": { - "message": "Alle überspringen" - }, "classifyProgress": { "message": "$1 von $2", "placeholders": { @@ -335,17 +303,6 @@ } } }, - "msgUploadingOf": { - "message": "Wird abgelegt … $1 von $2", - "placeholders": { - "1": { - "content": "$1" - }, - "2": { - "content": "$2" - } - } - }, "stepTitle": { "message": "In Paperless ablegen" }, diff --git a/_locales/en/messages.json b/_locales/en/messages.json index d9aaa1f..82eb0e7 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -26,9 +26,6 @@ "storeHintPreselect": { "message": "Small images and signatures are deselected — they usually belong to the message, not to the content." }, - "storeWholeMessage": { - "message": "The complete message as .eml" - }, "storeAttachmentsInside": { "message": "The $1 attachments remain inside it.", "placeholders": { @@ -46,26 +43,9 @@ "storeTargetExisting": { "message": "Append as a new version to an existing document" }, - "storeHintTitleMulti": { - "message": "With several files the title is extended by the file name." - }, - "storeClassifyAfter": { - "message": "Edit the classification after storing" - }, "classifyTitle": { "message": "Edit classification" }, - "classifyHintNew": { - "message": "Unknown correspondents and document types will be created." - }, - "classifyMoreStored": { - "message": "$1 files stored", - "placeholders": { - "1": { - "content": "$1" - } - } - }, "insertTitle": { "message": "Insert from Paperless" }, @@ -235,9 +215,6 @@ "errNoPermission": { "message": "Without access permission for the address the extension cannot work." }, - "linkLabel": { - "message": "File" - }, "linkValidUntil": { "message": "Link valid until $1", "placeholders": { @@ -279,12 +256,6 @@ "optionsHintMailFormat": { "message": "The PDF is readable and searchable; HTML messages are rendered as text. The original message is embedded in the PDF, so nothing is lost." }, - "storeWholePdf": { - "message": "The message as PDF, with the original embedded" - }, - "storeAsPdf": { - "message": "Prepare as PDF, embedding original and attachments" - }, "fieldPdfFontSize": { "message": "Font size" }, @@ -321,9 +292,6 @@ "artPdfUnavailable": { "message": "Not possible for this format - only text files can be prepared." }, - "btnSkipAll": { - "message": "Skip all" - }, "classifyProgress": { "message": "$1 of $2", "placeholders": { @@ -335,17 +303,6 @@ } } }, - "msgUploadingOf": { - "message": "Storing … $1 of $2", - "placeholders": { - "1": { - "content": "$1" - }, - "2": { - "content": "$2" - } - } - }, "stepTitle": { "message": "Store in Paperless" }, diff --git a/_locales/fr/messages.json b/_locales/fr/messages.json index c042878..5eb3b7c 100644 --- a/_locales/fr/messages.json +++ b/_locales/fr/messages.json @@ -26,9 +26,6 @@ "storeHintPreselect": { "message": "Les petites images et les signatures sont décochées — elles font partie du message, pas du contenu." }, - "storeWholeMessage": { - "message": "Le message complet au format .eml" - }, "storeAttachmentsInside": { "message": "Les $1 pièces jointes y restent incluses.", "placeholders": { @@ -46,26 +43,9 @@ "storeTargetExisting": { "message": "Ajouter comme nouvelle version à un document existant" }, - "storeHintTitleMulti": { - "message": "Avec plusieurs fichiers, le titre est complété par le nom du fichier." - }, - "storeClassifyAfter": { - "message": "Modifier le classement après l'enregistrement" - }, "classifyTitle": { "message": "Modifier le classement" }, - "classifyHintNew": { - "message": "Les correspondants et types de document inconnus seront créés." - }, - "classifyMoreStored": { - "message": "$1 fichiers enregistrés", - "placeholders": { - "1": { - "content": "$1" - } - } - }, "insertTitle": { "message": "Insérer depuis Paperless" }, @@ -235,9 +215,6 @@ "errNoPermission": { "message": "Sans droit d'accès à l'adresse, l'extension ne peut pas fonctionner." }, - "linkLabel": { - "message": "Fichier" - }, "linkValidUntil": { "message": "Lien valable jusqu'au $1", "placeholders": { @@ -279,12 +256,6 @@ "optionsHintMailFormat": { "message": "Le PDF est lisible et consultable ; les messages HTML y sont rendus sous forme de texte. Le message d'origine est intégré au PDF, rien n'est perdu." }, - "storeWholePdf": { - "message": "Le message en PDF, avec l'original intégré" - }, - "storeAsPdf": { - "message": "Préparer en PDF, avec l'original et les pièces jointes intégrés" - }, "fieldPdfFontSize": { "message": "Taille de police" }, @@ -321,9 +292,6 @@ "artPdfUnavailable": { "message": "Impossible pour ce format - seuls les fichiers texte peuvent être préparés." }, - "btnSkipAll": { - "message": "Tout ignorer" - }, "classifyProgress": { "message": "$1 sur $2", "placeholders": { @@ -335,17 +303,6 @@ } } }, - "msgUploadingOf": { - "message": "Enregistrement … $1 sur $2", - "placeholders": { - "1": { - "content": "$1" - }, - "2": { - "content": "$2" - } - } - }, "stepTitle": { "message": "Enregistrer dans Paperless" }, diff --git a/background.js b/background.js index 2d7e24c..35c1b82 100644 --- a/background.js +++ b/background.js @@ -315,81 +315,81 @@ browser.runtime.onConnect.addListener((port) => { }); }); -browser.runtime.onMessage.addListener(async (nachricht, absender) => { - // Nur Nachrichten aus dieser Erweiterung annehmen. Thunderbird lässt - // fremde Absender hier zwar ohnehin nicht durch, solange kein - // externally_connectable gesetzt ist - die Prüfung kostet nichts und - // hält die Zusicherung explizit. - if (absender?.id && absender.id !== browser.runtime.id) { - return { ok: false, fehler: "Fremder Absender" }; - } +/* + * Befehle aus den Dialogen. + * + * Der Listener selbst ist bewusst NICHT async: Ein async-Listener liefert + * immer ein Promise zurück und beansprucht damit jede Nachricht - auch + * solche, die gar nicht für ihn bestimmt sind. Stattdessen prüft er + * synchron, ob die Nachricht aus dieser Erweiterung stammt und einen + * bekannten Befehl trägt, und gibt nur dann das Promise des Handlers + * zurück. Alles andere lehnt er mit false ab, sodass andere Empfänger + * antworten können. + * Siehe https://webextension-api.thunderbird.net/en/mv3/guides/runtimeMessaging.html + */ +const BEFEHLE = { + auftrag: async (n) => auftraege.get(n.nummer) || null, + + einstellungen: async () => ladeEinstellungen(), + + berechtigungPruefen: async () => berechtigungPruefen(), + + suchen: async (n) => (await client()).search(n.query), + + dokument: async (n) => (await client()).document(n.id), + + versionen: async (n) => { + const c = await client(); + return c.versions(await c.document(n.id)); + }, + + stammdaten: async () => { + const c = await client(); + const [tags, korr, typen] = await Promise.all( + [c.tags(), c.correspondents(), c.documentTypes()]); + return { tags, korr, typen }; + }, + + schrittOeffnen: async (n) => { + await dialogOeffnen("schritt", n.auftrag); + return undefined; + }, + + dateiListe: async (n) => dateiListe(n.auftrag), + + ablegenEine: async (n) => ablegenEine(n), + + klassifizieren: async (n) => { + const c = await client(); + const payload = { ...n.payload }; + payload.correspondent = await aufloesen(c, "correspondents/", n.korrName); + payload.document_type = await aufloesen(c, "document_types/", n.typName); + await c.patchDocument(n.id, payload); + return undefined; + }, + + anhaengen: async (n) => anhaengenAnEntwurf(n), + + freigabelink: async (n) => freigabelink(n), +}; + +async function befehlAusfuehren(handler, nachricht) { try { - switch (nachricht?.befehl) { - case "auftrag": - return { ok: true, daten: auftraege.get(nachricht.nummer) || null }; - - case "einstellungen": - return { ok: true, daten: await ladeEinstellungen() }; - - case "berechtigungPruefen": - return { ok: true, daten: await berechtigungPruefen() }; - - case "suchen": { - const c = await client(); - return { ok: true, daten: await c.search(nachricht.query) }; - } - - case "dokument": { - const c = await client(); - return { ok: true, daten: await c.document(nachricht.id) }; - } - - case "versionen": { - const c = await client(); - const doc = await c.document(nachricht.id); - return { ok: true, daten: await c.versions(doc) }; - } - - case "stammdaten": { - const c = await client(); - const [tags, korr, typen] = await Promise.all( - [c.tags(), c.correspondents(), c.documentTypes()]); - return { ok: true, daten: { tags, korr, typen } }; - } - - case "schrittOeffnen": - await dialogOeffnen("schritt", nachricht.auftrag); - return { ok: true }; - - case "dateiListe": - return { ok: true, daten: dateiListe(nachricht.auftrag) }; - - case "ablegenEine": - return { ok: true, daten: await ablegenEine(nachricht) }; - - case "klassifizieren": { - const c = await client(); - const payload = { ...nachricht.payload }; - payload.correspondent = await aufloesen( - c, "correspondents/", nachricht.korrName); - payload.document_type = await aufloesen( - c, "document_types/", nachricht.typName); - await c.patchDocument(nachricht.id, payload); - return { ok: true }; - } - - case "anhaengen": - return { ok: true, daten: await anhaengenAnEntwurf(nachricht) }; - - case "freigabelink": - return { ok: true, daten: await freigabelink(nachricht) }; - - default: - return { ok: false, fehler: `Unbekannter Befehl: ${nachricht?.befehl}` }; - } + const daten = await handler(nachricht); + return daten === undefined ? { ok: true } : { ok: true, daten }; } catch (err) { return { ok: false, fehler: String(err?.message || err) }; } +} + +browser.runtime.onMessage.addListener((nachricht, absender) => { + // Nur Nachrichten aus dieser Erweiterung mit bekanntem Befehl annehmen. + if (absender?.id !== browser.runtime.id) return false; + const befehl = nachricht?.befehl; + if (typeof befehl !== "string" || !Object.hasOwn(BEFEHLE, befehl)) { + return false; + } + return befehlAusfuehren(BEFEHLE[befehl], nachricht); }); async function client() { diff --git a/build.sh b/build.sh index 4bb52d6..4aa6c04 100644 --- a/build.sh +++ b/build.sh @@ -11,18 +11,45 @@ NAME="paperless-connector" VERSION="$(sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' manifest.json | head -1)" OUT="${NAME}-${VERSION}.xpi" -# Vollständigkeit prüfen. zip überspringt fehlende Pfade stillschweigend - -# ohne diese Prüfung entstünde ein Paket, das sich nicht laden lässt. +# Paketinhalt als feste Liste. Nur was hier steht, landet in der .xpi - +# so geraten keine Altlasten (alte Dialoge, ungenutzte Symbole, Quell-SVGs +# aus make_icons.py) ins Paket. addons.thunderbird.net lehnt Pakete mit +# ungenutzten Dateien ab. +DATEIEN=" +manifest.json +background.js +LICENSE +lib/client.js +lib/settings.js +lib/pdf.js +lib/mailpdf.js +ui/gemeinsam.css +ui/gemeinsam.js +ui/store.html +ui/store.js +ui/schritt.html +ui/schritt.js +ui/insert.html +ui/insert.js +ui/options.html +ui/options.js +_locales/de/messages.json +_locales/en/messages.json +_locales/fr/messages.json +icons/paperless-logo_16.png +icons/paperless-logo_32.png +icons/paperless-logo_64.png +icons/paperless-store_16.png +icons/paperless-store_32.png +icons/paperless-insert_16.png +icons/paperless-insert_32.png +" + +# Vollständigkeit prüfen. zip überspringt fehlende Pfade nicht immer +# lautstark - ohne diese Prüfung entstünde ein Paket, das sich nicht +# laden lässt. FEHLT="" -for f in manifest.json background.js \ - lib/client.js lib/settings.js lib/pdf.js lib/mailpdf.js \ - ui/store.html ui/store.js ui/schritt.html ui/schritt.js \ - ui/insert.html ui/insert.js ui/options.html ui/options.js \ - ui/gemeinsam.js ui/gemeinsam.css \ - _locales/de/messages.json _locales/en/messages.json \ - _locales/fr/messages.json \ - icons/paperless-logo_64.png -do +for f in $DATEIEN; do [ -e "$f" ] || FEHLT="$FEHLT $f\n" done if [ -n "$FEHLT" ]; then @@ -32,14 +59,18 @@ if [ -n "$FEHLT" ]; then exit 1 fi -rm -f "$OUT" +# Umgekehrte Prüfung: Dateien im Quellbaum, die nicht im Paket landen. +# Nur ein Hinweis - README, build.sh usw. gehören bewusst nicht hinein. +for f in $(find lib ui icons _locales -type f | sort); do + case " $(echo $DATEIEN) " in + *" $f "*) ;; + *) echo "Hinweis: nicht im Paket: $f" >&2 ;; + esac +done -zip -r -q "$OUT" \ - manifest.json background.js \ - lib ui icons _locales \ - LICENSE \ - -x "*.oxt" "*.xpi" "build.sh" "README.md" "SICHERHEIT.md" \ - "make_icons.py" "*/.*" +rm -f "$OUT" +# shellcheck disable=SC2086 +zip -q -X "$OUT" $DATEIEN if ! unzip -l "$OUT" | grep -q 'manifest.json'; then echo "ABBRUCH: manifest.json fehlt im erzeugten Paket." >&2 diff --git a/icons/paperless-insert.svg b/icons/paperless-insert.svg deleted file mode 100644 index a58fab3..0000000 --- a/icons/paperless-insert.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/icons/paperless-insert_16.png b/icons/paperless-insert_16.png index d8af0b867343efa92641ff8f0044f1df255cd0ad..932f28558118558119e4613cbbb2a85c4b7c4b8d 100644 GIT binary patch literal 6655 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 delta 11 Scmexw{FQBj^5(T-LCgRlsRXP5 diff --git a/icons/paperless-insert_32.png b/icons/paperless-insert_32.png index 323ab4b0d191d5538fe94ac8410e1df9092ab9dd..473037e7d58bf3b5d8c844caceff0a448b4b1eff 100644 GIT binary patch literal 7782 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 - - - - - - - - diff --git a/icons/paperless-logo_16.png b/icons/paperless-logo_16.png index cca5463ab363443e4049b8cb414b57502b93f295..4537592c024f5e6cd6efd14f5ecc1a569e4556d5 100644 GIT binary patch literal 6450 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 - - - - - - - - - - - - - - diff --git a/icons/paperless-share_16.png b/icons/paperless-share_16.png deleted file mode 100644 index 8bb01366e3acd91c902b1eaea463f1016f37433c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 883 zcmV-(1C0EMP)LiP6D`pg>ZQck1jL5=;6rH@qO?tbnK^SgXZG1X45h{gSF-Xy{VOZ$ zU%#m8xbLN;>olhlOFjt6Z3qkkLV@tDjj_9*y*zl?p#zIiH2;E1IEk&zjXTe?oDlsag8zhzZ@AK^<-Pb zRCcVNsBN!}uKHVnL`a!)a}tnXR^}Z>?69hh)#TTeS8Q{X8LR57E2kH6TSQrwg_Cud z{C$d4CWW%psyW~HsfboE^Wi0x&ZNE8lkHotUccI8UNh&#Z$dDNR>j2uZZ6;A-OmPC zc9yX$tKd;cT+gMhdLyTg^5hTSx6yqvS~VZ?qk!Y?Y#KK=SCuVHV)Zc>>f%2F6(aPuC4Xbtg!0TvR=go=tt=CYh>+oc!N zY4ghX_`&{`7Ok|_*g>1d2ey#T7DDuWpLJ!G?D^m$<`(`Y6p5gXq4%-J>1uey0;ufi z(GSLAPpM!q%pW)Yv{d@S8=^8LQ0CPVkTy15yq!yS1ZLu0Y1L;GtUg2T}iG8+YWKV zaZrWY8UXS-k2Dq%k9$f>aJA;>$SBoiQEH-5#=4(pa&8_cm*buBaW<@7D->G$b|9ny zZ3iQ(C8~{;)48RQ_rDpF!DyMtx*ktH{1C%kT>xfydYZ!x4MLTyiP_&@xoG7+aV_oV zk+SeiUOvy!=KahkxAXPPuaw#$My98!j+O#&qODD|*43R5RR=b7Cv(Ydsih?!L19~1 zkjaQATH4J}&$;@yE?n6B<;;vpd!8t>ZU2RMTpy^fe?th-_YVT1gSYcmvqt~`002ov JPDHLkV1fszu=oG~ diff --git a/icons/paperless-share_32.png b/icons/paperless-share_32.png deleted file mode 100644 index 959b8f8903a0a46ec4422a2cd25d52b45c3aa907..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2142 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%0D+c*-*4W`+(nD{DuL!9A8+r zjPa+RF0QDp1;_wDan4;L-)W+yphy^%PkBU9m^e%p>m0ZI{O9a#ZYJw_C$;!O6f$P; zAU=E9<%ChtPN7OljJ1SOz-KSNoKZD36vL3T=P`fD681JVse~Oa25yt@*b4~REkh}d zL!hMO@ilAs-G&YH%VvpA!f4S_QVJq28#WB3R4ms!sKofjjYBHM6}7drlmjY#pY8Sa zeD%5K+KvO9g?r`kc!I{-lO7$NBndPYi#)J=Ik`;cgcmP_Kubw$5MaZQv->3H^<)9fzkqB5V2CE3c4F1kRDnBXQ1QoQ+dP#L`$MIbB~UFu1ak z`)ADHmPr?r_0xn=fak^PFpPr3-{~BFD$Q?RUC&>3?V=);Y8O2g%B6FBd+9?g{NEqZFW>)!g^(1I)^d^2XN~0LAFMzK!PWx@SiffvnGOJmgdz_X z3iw)+^*l;ZL?H;sr_(eSi)2zB|9Z(}zI@eH49-^(Mgd^)bc$uK{sSD$8Z-8Y=RdP? z1D{#?6sp6mKL@0gVt;cpf7-sCkBl2fmno1=rK!kPQkkj5xDx|FNkwELt{gv&l;;8P zr`KPnp;&AWf05|ZANs~KFQ7~!fP;R~S5{6e- z10oK0onl{e6W?F?91CB1iKcRye%UP6IiB6LiDer$0N_bUrSBsWHaN=cRf^3A4j?+~ z1*DJ^N(B~Na|_eQO(mU5pKuM3LQoC@#-BUBUGs0Lt3xY=OA2CLYb$q5nZo=@lPLuy zWa9n1B#(zz4w!A@X0!C~K%@C|y4_odYl%B1LpZ=wiZ>e? zI8-bi8-Vx#B4F}}iHtk@{BBc!yBizPD$dEsTKc5Z+;s7USQi&N)zR@0f*=f#Qt{m8 zO?>&czhlj=T~wyi?J3leMT~RDCD+@)KUgSmprxhj6tLD(4oWB`PnP}gbgJD{^^(O4 zAqb73rZUIr`6?vtmr%Tn=Mx zeDtOi`vW9QYn#D_>yNw$rjHjtormq&&Sg#e9y<2 zxbb=XhL7>gEjRQ2^UkBCT&6V$&`Bs4!jJ>4tsH1=r4WWFDLPH<&=^jys$xJc*Yf~4 z=h_)$)Sy8)=VB^!4qqwuHaBziqmT0I_3H_ZjW13kc;U6pT=U~cSop_3Qi==^-x8UA z?g*Z~`DT9pi5nR^crf*a0*49(#ta(7UDKv<*R*Mj8B{|`5sYD3=t(Iw_QF30o?JcUsILIw0jPrwe-tonKFEMdxzQ^ zWe{WI!Z-JV3n&J`5rwMF@y&Q1`Ls_qX72pULpj_8nZeXc5;x{urxw?nDYn zIV=-|Wo*LlT1s$^FbcT!(n}dXWC*Rv^R$#Smr7hwTg%XX{V>+LUSa`@N)+BFFT9W; zRaKOYIVwNfBI51xwGE6uzE3`r=9laK!KCkfpNChiBBfJD<$9Y0mQpdT_H2ql>=wI( zEpEH~@-~_my-I^NaenWdI+dnEpxUg2j^Qj+mAq&)wWho@7CLX`Mg^XT>0lkXhzVt{;}+qi)jx4lk2ou;8!WZ|4S4Da9HI8eYw;G3Ox zgRgA;JLM=Mio$jpJGEnh_*`JZITP?apOG~+EWGYIZdkmSs%*C1$UG6ZDWw#j_}P;z z`InC~wf3AN{{G_DEqrpxlT@Tq>~Ct~o~y3ny7SL>)>WSbnAhr6q1%=E7xA~L6+Y81c8Z2Db1oaYq)vI60)fjX{}GF(UFOtprqu( zW5+V%yb-Y*v}rTHdi7O8V`wfGx#Nl}`0lmW5*ZU}r99vsA;g2uIo&A$F$aror9vqc z^^Nu1HhTdN-tquJ6q3>&zumZz1xuImW@97$6NBS;qoFNwno6a_cMxb5Q(;PLzB+Rz z|2}03#@bLx=>ZQ5Ar`cq5-Wh*sH%&E67O|~kAN*;9j+S();en|(iQgkzpk(?#TGl` z!uMLho-<$ob1t|*Y^|$f-R|8O=SX|ran%NwY*wZ3lk+4oKGF<6{)dEhG+{>>WW=?)fDOS#Nz2M(|$NsmICj242ig9cGsUCp@z2Qo01 qYyaNJ7@LT!Wx$<6h^?L75&Az|etzg - - - - - - - - - - - - - diff --git a/icons/paperless-store_16.png b/icons/paperless-store_16.png index 9f0cfa5264759b434c3254497dd2d932c6cd34c3..39630155b75c084f909a9479df710b6c369094c9 100644 GIT binary patch literal 6659 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 delta 11 ScmbPc+aoYRdGlJam+Sx=TLg&! diff --git a/icons/paperless-store_64.png b/icons/paperless-store_64.png deleted file mode 100644 index 7b76fbfb91d37e6fa6779fa385197a0b4cc161ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4073 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 - - - - Klassifizierung bearbeiten - - - -

Klassifizierung bearbeiten

-
- - - - - - - - - - - - - - - -
- - -
-
-
- -
-
- -
- Unbekannte Korrespondenten und Dokumenttypen werden angelegt. -
- -
- -
- - - -
- - - - diff --git a/ui/classify.js b/ui/classify.js deleted file mode 100644 index e712a1c..0000000 --- a/ui/classify.js +++ /dev/null @@ -1,262 +0,0 @@ -/** - * classify.js - Klassifizierung eines gerade abgelegten Dokuments. - * - * Wird unmittelbar nach dem Ablegen aufgerufen. Ohne diesen Schritt trägt - * ein neues Dokument nur den Titel, und nachträglich macht man es - * erfahrungsgemäß nicht mehr. - */ - -import { kurz } from "../lib/settings.js"; -import { uebersetzeSeite, ruf, fehlerAnzeigen, meldungAnzeigen } - from "./gemeinsam.js"; - -const $ = (id) => document.getElementById(id); -let dokumentId = null; -let alleTags = []; - -// Bei mehreren abgelegten Dateien wird jede einzeln klassifiziert. -// Andernfalls trüge nur die erste eine sinnvolle Zuordnung, und die -// übrigen fielen später als unklassifiziert auf - wenn überhaupt. -let liste = []; -let stelle = 0; - -// Gewählte Tags als Menge. Bewusst getrennt vom angezeigten Zustand der -// Kontrollkästchen: Der Filter blendet Zeilen aus, die Auswahl darf davon -// nicht berührt werden. -const gewaehlt = new Set(); - -document.addEventListener("DOMContentLoaded", start); - -async function start() { - uebersetzeSeite(); - const p = new URLSearchParams(location.search); - - // "ids" für mehrere, "id" für den Einzelfall - letzteres bleibt für - // Aufrufe aus anderen Stellen erhalten. - const roh = p.get("ids") || p.get("id") || ""; - liste = roh.split(",").map((x) => Number(x)).filter(Boolean); - stelle = 0; - - $("ueberspringen").addEventListener("click", weiter); - $("abbrechenAlle").addEventListener("click", () => window.close()); - $("speichern").addEventListener("click", speichern); - - if (!liste.length) { - fehlerAnzeigen("Kein Dokument angegeben."); - return; - } - - try { - const stamm = await ruf("stammdaten"); - alleTags = stamm.tags; - fuelleListe("korrListe", stamm.korr); - fuelleListe("typListe", stamm.typen); - zustand.korr = stamm.korr; - zustand.typen = stamm.typen; - } catch (err) { - fehlerAnzeigen(err.message); - return; - } - - await anzeigen(); -} - -const zustand = { korr: [], typen: [] }; - -/** Das Dokument an der aktuellen Stelle laden und darstellen. */ -async function anzeigen() { - dokumentId = liste[stelle]; - $("speichern").disabled = false; - $("ueberspringen").disabled = false; - meldungAnzeigen(""); - - // Der Knopf zum Abbrechen aller weiteren ist nur sinnvoll, wenn noch - // welche folgen. - $("abbrechenAlle").hidden = liste.length < 2; - - try { - const doc = await ruf("dokument", { id: dokumentId }); - - const zaehler = liste.length > 1 - ? ` · ${browser.i18n.getMessage("classifyProgress", - [String(stelle + 1), String(liste.length)]) - || `${stelle + 1} von ${liste.length}`}` - : ""; - $("quelle").textContent = `#${dokumentId} · ${kurz(doc.title, 60)}` - + zaehler; - - $("titel").value = doc.title || ""; - $("erstellt").value = (doc.created || "").slice(0, 10); - $("korr").value = nameVon(zustand.korr, doc.correspondent); - $("typ").value = nameVon(zustand.typen, doc.document_type); - zeigeTags(doc.tags || []); - if ($("tagSuche")) $("tagSuche").value = ""; - } catch (err) { - fehlerAnzeigen(err.message); - } -} - -/** Zum nächsten Dokument, oder schliessen. */ -async function weiter() { - stelle += 1; - if (stelle >= liste.length) { - window.close(); - return; - } - await anzeigen(); -} - -function fuelleListe(id, eintraege) { - const dl = $(id); - dl.replaceChildren(); - for (const e of eintraege) { - const o = document.createElement("option"); - o.value = e.name; - dl.append(o); - } -} - -function nameVon(liste, id) { - return liste.find((x) => x.id === id)?.name || ""; -} - -function zeigeTags(gesetzt) { - for (const id of gesetzt) gewaehlt.add(Number(id)); - const feld = $("tagSuche"); - if (feld) { - feld.addEventListener("input", zeichneTags); - // Eingabetaste soll den Dialog nicht abschicken, sondern beim - // einzigen Treffer diesen umschalten - das ist beim Tippen der - // erwartete Ablauf. - feld.addEventListener("keydown", (e) => { - if (e.key !== "Enter") return; - e.preventDefault(); - const treffer = gefilterteTags(); - if (treffer.length === 1) { - umschalten(treffer[0].id); - feld.value = ""; - zeichneTags(); - } - }); - } - zeichneTags(); -} - -/** Tags, die zum aktuellen Filter passen und noch nicht gewählt sind. */ -function gefilterteTags() { - const filter = ($("tagSuche")?.value || "").trim().toLowerCase(); - return alleTags.filter((t) => { - if (gewaehlt.has(Number(t.id))) return false; - if (!filter) return true; - return String(t.name).toLowerCase().includes(filter); - }); -} - -function umschalten(id) { - const n = Number(id); - if (gewaehlt.has(n)) gewaehlt.delete(n); - else gewaehlt.add(n); -} - -/** - * Tagliste zeichnen. - * - * Zwei Bereiche: oben die gewählten, darunter die übrigen. Die gewählten - * bleiben immer sichtbar, auch wenn der Filter sie ausschliesst - sonst - * verliert man beim Suchen den Überblick, was bereits angehakt ist. - */ -function zeichneTags() { - const filter = ($("tagSuche")?.value || "").trim().toLowerCase(); - - const oben = $("tagsGewaehlt"); - oben.replaceChildren(); - const gewaehlteListe = alleTags - .filter((t) => gewaehlt.has(Number(t.id))) - .sort((a, b) => String(a.name).localeCompare(String(b.name), "de")); - for (const tag of gewaehlteListe) { - oben.append(tagZeile(tag, true, "")); - } - - const unten = $("tags"); - unten.replaceChildren(); - const rest = gefilterteTags() - .sort((a, b) => String(a.name).localeCompare(String(b.name), "de")); - for (const tag of rest) { - unten.append(tagZeile(tag, false, filter)); - } - - const leer = $("tagsLeer"); - if (leer) leer.style.display = (rest.length === 0 && filter) ? "" : "none"; -} - -function tagZeile(tag, istGewaehlt, filter) { - const zeile = document.createElement("div"); - zeile.className = "wahl"; - - const box = document.createElement("input"); - box.type = "checkbox"; - box.id = `t${tag.id}`; - box.value = String(tag.id); - box.checked = istGewaehlt; - box.addEventListener("change", () => { - umschalten(tag.id); - zeichneTags(); - }); - - const bez = document.createElement("label"); - bez.htmlFor = box.id; - beschriftungSetzen(bez, String(tag.name), filter); - - zeile.append(box, bez); - return zeile; -} - -/** - * Beschriftung mit hervorgehobenem Treffer. - * - * Aufbau über createElement und textContent, nicht über innerHTML - ein - * Tagname stammt aus Paperless und damit mittelbar aus fremden Quellen. - */ -function beschriftungSetzen(el, name, filter) { - el.replaceChildren(); - if (!filter) { - el.textContent = name; - return; - } - const pos = name.toLowerCase().indexOf(filter); - if (pos < 0) { - el.textContent = name; - return; - } - el.append(document.createTextNode(name.slice(0, pos))); - const treffer = document.createElement("span"); - treffer.className = "trefferHervor"; - treffer.textContent = name.slice(pos, pos + filter.length); - el.append(treffer); - el.append(document.createTextNode(name.slice(pos + filter.length))); -} - -async function speichern() { - $("speichern").disabled = true; - meldungAnzeigen(browser.i18n.getMessage("msgSaving") || "Wird gespeichert …"); - try { - // Aus der Menge lesen, nicht aus den Kästchen: Gefilterte Zeilen - // sind gar nicht im Dokument, ihre Auswahl ginge sonst verloren. - const tags = [...gewaehlt]; - const payload = { title: $("titel").value.trim(), tags }; - const erstellt = $("erstellt").value.trim(); - if (erstellt) payload.created = erstellt; - - await ruf("klassifizieren", { - id: dokumentId, - payload, - korrName: $("korr").value.trim(), - typName: $("typ").value.trim() - }); - meldungAnzeigen(browser.i18n.getMessage("msgSaved") || "Gespeichert."); - setTimeout(weiter, 600); - } catch (err) { - fehlerAnzeigen(err.message); - $("speichern").disabled = false; - } -} diff --git a/ui/insert.html b/ui/insert.html index ce7d005..cb67eb2 100644 --- a/ui/insert.html +++ b/ui/insert.html @@ -29,7 +29,7 @@
-
+
@@ -68,6 +68,7 @@
Der Link ist ohne Anmeldung abrufbar. 0 Tage bedeutet unbegrenzt. + Leeres Tag-Feld bedeutet: keine Kennzeichnung setzen.
Nr