diff --git a/VERIFY.md b/VERIFY.md new file mode 100644 index 0000000..4c15892 --- /dev/null +++ b/VERIFY.md @@ -0,0 +1,48 @@ +# Verifizierungs-Checkliste + +Nach Thunderbird-Updates, Plugin-Änderungen oder Deployments diese Punkte prüfen. + +## Vorlagen — Sync & Anzeige +- [ ] Pull überschreibt lokale Vorlagen nicht (Merge statt Replace) — importierte Vorlagen dürfen nach Sync nicht verschwinden +- [ ] Vorlagen mit Leerzeichen im Titel werden korrekt erstellt, gesynct und angezeigt (kein Duplikat) +- [ ] Scope-Badge (Persönlich/Abteilung/Alle) zeigt den richtigen Wert — Abteilungsvorlagen dürfen nicht als "Privat" erscheinen +- [ ] Scope-Badge umschalten funktioniert (Warnung bei Downgrade, altes File wird gelöscht, neues wird gepusht) +- [ ] Sync-Dots sind grün nach Pull (nicht grau/unknown) — Hashes müssen korrekt geschrieben werden +- [ ] Background SHA-Check alle 5s läuft, voller Pull nur bei Änderung +- [ ] UI refreshed automatisch wenn Background-Sync neue Templates pullt + +## Signaturen +- [ ] Signaturen-Tab lädt beim Öffnen automatisch die erste Identität + deren Signatur +- [ ] Kein "Bitte wählen" Placeholder im Identity-Dropdown +- [ ] Signatur-Sync-Status ist grün beim Öffnen (nicht grau) +- [ ] `attachSignature: false` wird gesetzt — alte Datei-basierte Signaturen werden deaktiviert +- [ ] Footer (Banner) lädt korrekt als eingebettete data-URI, nicht als Datei-Referenz +- [ ] Signatur-Quelle "= andere E-Mail" funktioniert (Kopie von anderer Identität) + +## Settings / Verbindung +- [ ] E-Mail ist ein Dropdown mit TB-Identitäten (kein Freitext) +- [ ] Token-Feld hat Show/Hide Toggle +- [ ] `defaults.local.json` wird beim ersten Start geladen (wenn in XPI vorhanden) +- [ ] Ohne `defaults.local.json` funktioniert Plugin normal (manuell konfigurieren) +- [ ] Auto-Detection via `_config/abteilungen.json` erkennt Abteilung + E-Mail +- [ ] Abteilungsname wird im Scope-Badge und Editor-Dropdown angezeigt (nicht generisch "Abteilung") + +## Popup (Compose-Fenster) +- [ ] Vorlagen-Popup öffnet, zeigt alle Vorlagen +- [ ] Template-Insertion funktioniert (HTML wird korrekt eingefügt) +- [ ] Prefix-Dropdown ("Textbaustein voranstellen") funktioniert + +## UX-Elemente +- [ ] Toast-Benachrichtigungen erscheinen bei Sync/Push/Pull/Fehler +- [ ] Spinner bei Sync-Operationen sichtbar +- [ ] Custom Delete-Modal statt browser confirm() +- [ ] Offline-Banner erscheint bei fehlender Verbindung +- [ ] Collapsible-Sections sind visuell klickbar (Hintergrund + Hover) +- [ ] Template-Name Inline-Validierung (leer + Duplikat) +- [ ] Checkbox-Klick auf Template-Name toggelt Checkbox + +## API / Gitea +- [ ] `toFilename()` behält Leerzeichen und Groß-/Kleinschreibung +- [ ] `_benutzer/`, `_config/` werden aus Department-Liste gefiltert +- [ ] Persönliche Vorlagen syncen in `_benutzer/{email}/` +- [ ] `checkRemoteShas()` inkludiert persönlichen Ordner diff --git a/lib/gitea-sync.js b/lib/gitea-sync.js index 53c5288..a346d99 100644 --- a/lib/gitea-sync.js +++ b/lib/gitea-sync.js @@ -544,7 +544,8 @@ class SyncManager { await browser.identities.update(identity.id, { signature: fullSig, - signatureIsPlainText: false + signatureIsPlainText: false, + attachSignature: false }); updated++; } @@ -784,6 +785,19 @@ async function updateSyncHashes() { for (const t of templates) { data.tpl[t.id] = simpleHashBg(t.content || ''); } + + // Also update signature hashes from Thunderbird identities + try { + const accounts = await browser.accounts.list(); + data.sig = data.sig || {}; + for (const account of accounts) { + const identities = await browser.identities.list(account.id); + for (const identity of identities) { + data.sig[identity.email.toLowerCase()] = simpleHashBg(identity.signature || ''); + } + } + } catch (_) {} + await browser.storage.local.set({ [HASH_STORAGE_KEY_BG]: data }); } diff --git a/templates-reply-hotel.xpi b/templates-reply-hotel.xpi index 67c21da..3092204 100644 Binary files a/templates-reply-hotel.xpi and b/templates-reply-hotel.xpi differ diff --git a/templates_options/templates_options.js b/templates_options/templates_options.js index 6c4399e..6456c4c 100644 --- a/templates_options/templates_options.js +++ b/templates_options/templates_options.js @@ -1193,7 +1193,8 @@ document.getElementById('sig-save-button').addEventListener('click', async () => await browser.identities.update(identityId, { signature: fullSignature, - signatureIsPlainText: false + signatureIsPlainText: false, + attachSignature: false }); if (identity) identity.signature = fullSignature; @@ -1674,17 +1675,30 @@ window.addEventListener('load', async () => { loadSyncConfig(); await loadIdentities(); + // Always init sig hashes from current identities + if (allIdentities.length > 0) { + for (const id of allIdentities) { + sigSyncedHashes[id.email.toLowerCase()] = simpleHash(id.signature || ''); + } + saveSyncHashes(); + } + updateSigSyncIndicator(); + checkForServerUpdates(); setInterval(checkForServerUpdates, 30000); - // Auto-refresh UI when background sync updates hashes (fires after templates + hashes are both written) + // Auto-refresh UI when background sync updates storage + let refreshing = false; browser.storage.onChanged.addListener(async (changes, area) => { - if (area !== 'local') return; - if (changes[HASH_STORAGE_KEY]) { + if (area !== 'local' || refreshing) return; + if (changes[HASH_STORAGE_KEY] || changes[TEMPLATE_STORAGE_KEY]) { + refreshing = true; await loadSyncHashes(); const templates = await getTemplates(); renderTemplates(templates); updateTplSyncIndicator(); + updateSigSyncIndicator(); + refreshing = false; } }); });