Sync-Fix, Dateinamen mit Leerzeichen, E-Mail-Dropdown, Defaults-System
- Fix: Pull überschreibt lokale Vorlagen nicht mehr (Merge statt Replace) - Fix: toFilename behält Leerzeichen und Groß-/Kleinschreibung - E-Mail in Settings ist jetzt ein Dropdown mit TB-Identitäten - Optionale defaults.local.js für vorkonfigurierte Verbindungsdaten (.gitignored)
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
defaults.local.js
|
||||||
@@ -203,13 +203,13 @@ class SyncManager {
|
|||||||
|
|
||||||
static toFilename(name) {
|
static toFilename(name) {
|
||||||
return name
|
return name
|
||||||
.toLowerCase()
|
|
||||||
.replace(/[äÄ]/g, 'ae')
|
.replace(/[äÄ]/g, 'ae')
|
||||||
.replace(/[öÖ]/g, 'oe')
|
.replace(/[öÖ]/g, 'oe')
|
||||||
.replace(/[üÜ]/g, 'ue')
|
.replace(/[üÜ]/g, 'ue')
|
||||||
.replace(/ß/g, 'ss')
|
.replace(/ß/g, 'ss')
|
||||||
.replace(/[^a-z0-9]+/g, '-')
|
.replace(/[/\\:*?"<>|]/g, '-')
|
||||||
.replace(/^-+|-+$/g, '');
|
.replace(/^[\s.-]+|[\s.-]+$/g, '')
|
||||||
|
.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -291,7 +291,13 @@ class SyncManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.saveLocalTemplates(newTemplates);
|
// Merge: keep local-only templates that aren't now on the server
|
||||||
|
const existingTemplates = await this.getLocalTemplates();
|
||||||
|
const pulledFilenames = new Set(newTemplates.map(t => SyncManager.toFilename(t.name).toLowerCase()));
|
||||||
|
const localOnly = existingTemplates.filter(t => !t.remotePath && !pulledFilenames.has(SyncManager.toFilename(t.name).toLowerCase()));
|
||||||
|
|
||||||
|
const merged = [...newTemplates, ...localOnly];
|
||||||
|
await this.saveLocalTemplates(merged);
|
||||||
syncState.fileShas = newShas;
|
syncState.fileShas = newShas;
|
||||||
await this.saveSyncState(syncState);
|
await this.saveSyncState(syncState);
|
||||||
|
|
||||||
|
|||||||
@@ -976,8 +976,10 @@
|
|||||||
<input type="text" id="sync-author-name" placeholder="z.B. Max Mustermann">
|
<input type="text" id="sync-author-name" placeholder="z.B. Max Mustermann">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="sync-author-email">Deine E-Mail (optional)</label>
|
<label for="sync-author-email">Deine E-Mail</label>
|
||||||
<input type="text" id="sync-author-email" placeholder="z.B. max@hotel-park-soltau.de">
|
<select id="sync-author-email" style="width:100%;">
|
||||||
|
<option value="">— Bitte wählen —</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -1060,6 +1062,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script src="../defaults.local.js" onerror=""></script>
|
||||||
<script src="templates_options.js"></script>
|
<script src="templates_options.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1366,10 +1366,34 @@ document.getElementById('footer-save-button').addEventListener('click', async ()
|
|||||||
|
|
||||||
// ── Sync Settings UI ──
|
// ── Sync Settings UI ──
|
||||||
|
|
||||||
|
async function populateEmailDropdown() {
|
||||||
|
const select = document.getElementById('sync-author-email');
|
||||||
|
const accounts = await browser.accounts.list();
|
||||||
|
const emails = new Set();
|
||||||
|
for (const account of accounts) {
|
||||||
|
for (const identity of account.identities) {
|
||||||
|
if (identity.email && !emails.has(identity.email)) {
|
||||||
|
emails.add(identity.email);
|
||||||
|
const opt = document.createElement('option');
|
||||||
|
opt.value = identity.email;
|
||||||
|
opt.textContent = identity.email;
|
||||||
|
select.appendChild(opt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function loadSyncConfig() {
|
async function loadSyncConfig() {
|
||||||
try {
|
try {
|
||||||
const result = await browser.storage.local.get(SYNC_CONFIG_KEY);
|
const result = await browser.storage.local.get(SYNC_CONFIG_KEY);
|
||||||
const config = result[SYNC_CONFIG_KEY];
|
let config = result[SYNC_CONFIG_KEY];
|
||||||
|
|
||||||
|
// First launch: apply defaults from defaults.local.js if available
|
||||||
|
if (!config && typeof DEFAULT_SYNC_CONFIG !== 'undefined') {
|
||||||
|
config = { ...DEFAULT_SYNC_CONFIG };
|
||||||
|
await browser.storage.local.set({ [SYNC_CONFIG_KEY]: config });
|
||||||
|
}
|
||||||
|
|
||||||
if (config) {
|
if (config) {
|
||||||
document.getElementById('sync-url').value = config.baseUrl || '';
|
document.getElementById('sync-url').value = config.baseUrl || '';
|
||||||
document.getElementById('sync-owner').value = config.owner || '';
|
document.getElementById('sync-owner').value = config.owner || '';
|
||||||
@@ -1640,6 +1664,7 @@ window.addEventListener('load', async () => {
|
|||||||
const templates = await getTemplates();
|
const templates = await getTemplates();
|
||||||
renderTemplates(templates);
|
renderTemplates(templates);
|
||||||
updateTplSyncIndicator();
|
updateTplSyncIndicator();
|
||||||
|
await populateEmailDropdown();
|
||||||
loadSyncConfig();
|
loadSyncConfig();
|
||||||
await loadIdentities();
|
await loadIdentities();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user