Auto-Update über Gitea einrichten + Web-Editor + Sync-Verbesserungen
- Thunderbird Auto-Update: update_url im Manifest, updates.json, release.sh - .xpi neu gebaut (mit update_url, ohne defaults.local.json/Token) - README + CLAUDE.md: Auto-Update-Doku, Repo muss public bleiben - web-editor/ (Node/Docker WYSIWYG-Editor) hinzugefügt - gitea-sync.js + templates_options: bestehende Anpassungen Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -250,6 +250,9 @@ class SyncManager {
|
||||
const folders = [SHARED_FOLDER];
|
||||
if (this.department) folders.push(this.department);
|
||||
if (this.authorEmail) folders.push(`${USER_FOLDER}/${this.authorEmail}`);
|
||||
// Signatur-Bausteine mitüberwachen, damit Footer-/Header-Änderungen
|
||||
// auf dem Server den Hintergrund-Sync (pullSignatures) auslösen.
|
||||
folders.push('signatures/footers', 'signatures/headers');
|
||||
|
||||
for (const folder of folders) {
|
||||
const files = await this.client.listDir(folder);
|
||||
@@ -461,25 +464,50 @@ class SyncManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Load footer for editing (returns HTML)
|
||||
* Resolve the footer file path for a given scope.
|
||||
* - 'shared' → signatures/footers/_default.html (gilt für alle Abteilungen)
|
||||
* - 'department' → signatures/footers/{department}.html
|
||||
*/
|
||||
async loadFooter() {
|
||||
footerPathForScope(scope) {
|
||||
if (scope === 'shared') return 'signatures/footers/_default.html';
|
||||
if (!this.department) throw new Error('Keine Abteilung ausgewählt');
|
||||
return `signatures/footers/${this.department}.html`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load footer for editing (returns HTML).
|
||||
* - scope 'shared'/'department': lädt genau diese Datei (kein Fallback,
|
||||
* damit der Editor den echten Inhalt der gewählten Ebene zeigt).
|
||||
* - ohne scope: Fallback-Kette (Abteilung → gemeinsam) für die
|
||||
* automatische Anwendung an die Signatur.
|
||||
*/
|
||||
async loadFooter(scope) {
|
||||
if (!this.isConfigured) throw new Error('Sync nicht konfiguriert');
|
||||
|
||||
if (scope === 'shared' || scope === 'department') {
|
||||
const filepath = this.footerPathForScope(scope);
|
||||
const fileData = await this.client.getFile(filepath);
|
||||
const html = (fileData && fileData.content) ? GiteaClient.fromBase64(fileData.content) : '';
|
||||
return { success: true, html, scope };
|
||||
}
|
||||
|
||||
const footer = await this.pullFooter();
|
||||
return { success: true, html: footer };
|
||||
}
|
||||
|
||||
/**
|
||||
* Push footer for current department to signatures/footers/{department}.html
|
||||
* Push footer to the chosen scope:
|
||||
* - 'shared' → signatures/footers/_default.html
|
||||
* - 'department' → signatures/footers/{department}.html
|
||||
*/
|
||||
async pushFooter(html) {
|
||||
async pushFooter(html, scope) {
|
||||
if (!this.isConfigured) throw new Error('Sync nicht konfiguriert');
|
||||
if (!this.config.authorName) throw new Error('Bitte Name eintragen');
|
||||
if (!this.department) throw new Error('Keine Abteilung ausgewählt');
|
||||
|
||||
const filepath = `signatures/footers/${this.department}.html`;
|
||||
const commitMsg = `Signatur-Footer ${this.department} - von ${this.config.authorName}`;
|
||||
const targetScope = (scope === 'shared') ? 'shared' : 'department';
|
||||
const filepath = this.footerPathForScope(targetScope);
|
||||
const label = targetScope === 'shared' ? 'gemeinsam' : this.department;
|
||||
const commitMsg = `Signatur-Footer ${label} - von ${this.config.authorName}`;
|
||||
|
||||
const existing = await this.client.getFile(filepath);
|
||||
|
||||
@@ -492,8 +520,10 @@ class SyncManager {
|
||||
await this.client.createFile(filepath, html, commitMsg);
|
||||
}
|
||||
|
||||
await browser.storage.local.set({ 'sig_footer_cache': html });
|
||||
return { success: true };
|
||||
// Refresh cache with the footer that actually applies (Abteilung gewinnt
|
||||
// vor gemeinsam) — nicht zwingend das gerade gespeicherte html.
|
||||
await this.pullFooter();
|
||||
return { success: true, scope: targetScope };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -544,15 +574,29 @@ class SyncManager {
|
||||
targetFile = headerMap[personalName] || null;
|
||||
}
|
||||
|
||||
if (!targetFile) continue; // No header file yet — user hasn't set up signature
|
||||
let header = null;
|
||||
if (targetFile) {
|
||||
const fileData = await this.client.getFile(targetFile.path);
|
||||
if (fileData) header = GiteaClient.fromBase64(fileData.content);
|
||||
}
|
||||
|
||||
const fileData = await this.client.getFile(targetFile.path);
|
||||
if (!fileData) continue;
|
||||
// Fallback: kein Server-Header → lokalen Header aus der aktuellen
|
||||
// Signatur verwenden, damit der Footer trotzdem angewandt wird.
|
||||
if (header === null) {
|
||||
const existing = identity.signature || '';
|
||||
const localHeader = SyncManager.extractHeader(existing);
|
||||
// Leere, nie eingerichtete Konten nicht mit reinem Footer versehen
|
||||
if (!localHeader.trim() && !existing.includes(SyncManager.FOOTER_SEPARATOR)) continue;
|
||||
header = localHeader;
|
||||
}
|
||||
|
||||
const header = GiteaClient.fromBase64(fileData.content);
|
||||
loadedHeaders[email] = header;
|
||||
const fullSig = SyncManager.combineSignature(header, footer);
|
||||
|
||||
// Nur schreiben, wenn sich etwas ändert (vermeidet unnötige Writes
|
||||
// bei jedem Hintergrund-Sync)
|
||||
if (fullSig === identity.signature) continue;
|
||||
|
||||
await browser.identities.update(identity.id, {
|
||||
signature: fullSig,
|
||||
signatureIsPlainText: false,
|
||||
@@ -854,10 +898,10 @@ browser.runtime.onMessage.addListener(async (msg, sender) => {
|
||||
return await syncManager.loadSignatureTemplate();
|
||||
|
||||
case 'loadFooter':
|
||||
return await syncManager.loadFooter();
|
||||
return await syncManager.loadFooter(msg.scope);
|
||||
|
||||
case 'pushFooter':
|
||||
return await syncManager.pushFooter(msg.html);
|
||||
return await syncManager.pushFooter(msg.html, msg.scope);
|
||||
|
||||
case 'autoDetect':
|
||||
const config = await syncManager.autoDetect();
|
||||
|
||||
Reference in New Issue
Block a user