diff --git a/src/js/settings.js b/src/js/settings.js index 5bfdefc..8827ec8 100644 --- a/src/js/settings.js +++ b/src/js/settings.js @@ -80,6 +80,8 @@ function openThemeModal() { document.addEventListener('keydown', _themeTrap); const first = _focusable(modal)[0]; if (first) first.focus(); + syncCustomPickers(); + document.getElementById('themeBuilderPanel').classList.toggle('hidden', settings.theme !== 'custom'); } function closeThemeModal() { const overlay = document.getElementById('themeOverlay'); @@ -462,7 +464,11 @@ function applySettings() { const langEl = document.getElementById('settingLanguage'); if (langEl) langEl.value = settings.language || 'auto'; - applyTheme(settings.theme || 'nebula', !!settings.bgUrl); + if (settings.theme === 'custom') { + applyCustomTheme(settings.customTheme); + } else { + applyTheme(settings.theme || 'nebula', !!settings.bgUrl); + } if (settings.bgUrl && isValidBgUrl(settings.bgUrl)) { document.getElementById('bgLayer').style.backgroundImage = `url('${settings.bgUrl}')`; @@ -489,10 +495,25 @@ function bindSettingsEvents() { const themeCards = document.querySelectorAll('.theme-card'); function selectThemeCard(card) { const name = card.dataset.value; - if (!name || name === settings.theme) return Promise.resolve(); + if (!name) return Promise.resolve(); + + // Custom: VOR dem name===settings.theme-Guard, damit ein Re-Klick das Panel wieder oeffnet. + if (name === 'custom') { + settings.theme = 'custom'; + if (!settings.customTheme) settings.customTheme = { ...CUSTOM_DEFAULTS }; + themeCards.forEach(c => c.setAttribute('aria-pressed', c === card ? 'true' : 'false')); + applyCustomTheme(settings.customTheme); // setzt data-theme + Inline-Vars; bgUrl UNANGETASTET (Koexistenz) + syncCustomPickers(); + document.getElementById('themeBuilderPanel').classList.remove('hidden'); + return saveSettings(); + } + + if (name === settings.theme) return Promise.resolve(); settings.theme = name; settings.bgUrl = ''; document.getElementById('bgUrlInput').value = ''; + clearCustomTheme(); // Inline-Vars weg beim Rueckwechsel auf ein Preset + document.getElementById('themeBuilderPanel').classList.add('hidden'); // aria-pressed synchron halten — applyTheme/switchTheme pflegt nur die .active-Klasse, nicht ARIA themeCards.forEach(c => c.setAttribute('aria-pressed', c === card ? 'true' : 'false')); switchTheme(name); // WICHTIG: switchTheme aus Phase 4 (View-Transition-Wrapper), NICHT applyTheme direkt — sonst geht der Theme-Fade verloren @@ -508,6 +529,31 @@ function bindSettingsEvents() { }); }); + // Theme-Builder Picker + const TB_PICKERS = [['tbAccent', 'accent'], ['tbBg', 'bgPrimary'], ['tbBoard', 'bgBoard'], + ['tbText', 'textPrimary'], ['tbTextSec', 'textSecondary'], ['tbTextMuted', 'textMuted']]; + TB_PICKERS.forEach(([id, key]) => { + const el = document.getElementById(id); + if (!el) return; + el.addEventListener('input', () => { // live waehrend des Ziehens + if (!settings.customTheme) settings.customTheme = { ...CUSTOM_DEFAULTS }; + settings.customTheme[key] = el.value; + settings.theme = 'custom'; + applyCustomTheme(settings.customTheme); + }); + el.addEventListener('change', () => saveSettings()); // persistiert beim Loslassen/Schliessen + }); + + const tbReset = document.getElementById('tbReset'); + if (tbReset) { + tbReset.addEventListener('click', async () => { + settings.customTheme = { ...CUSTOM_DEFAULTS }; + applyCustomTheme(settings.customTheme); + syncCustomPickers(); + await saveSettings(); + }); + } + // Accordion initialisieren initAccordion(); @@ -639,6 +685,7 @@ function bindSettingsEvents() { hideExtra: false, visibleCount: 10, bgUrl: '', theme: 'nebula', showSearch: true, searchEngine: 'google', toolbarPos: 'right', imageRefEnabled: false, language: 'auto', customTheme: null }; + clearCustomTheme(); await saveBoards(); await saveTrash(); await saveSettings();