// ===================================================================== // Theme configuration and dark/light toggle for Shaarli Pro. // Keeps theme/mode preferences client-side without creating bookmarks. // Used by the dark/light switch AND the theme picker (tools.html). // ===================================================================== (function () { 'use strict'; const STORAGE_KEY = 'shaarit_themes_config'; function readConfig() { try { const raw = localStorage.getItem(STORAGE_KEY); if (!raw) return null; const parsed = JSON.parse(raw); return (parsed && typeof parsed === 'object') ? parsed : null; } catch (e) { return null; } } function writeConfig(config) { try { localStorage.setItem(STORAGE_KEY, JSON.stringify(config)); return true; } catch (e) { return false; } } // Merge partial updates into the persisted config and save to localStorage. function save(partial) { const base = readConfig() || {}; const config = Object.assign( { version: 2, themes: [], default: 'DEFAULT', mode: 'dark' }, base, partial || {} ); const ok = writeConfig(config); return Promise.resolve({ ok, config }); } // Reads the current persisted config from localStorage (no write). function load() { return Promise.resolve(readConfig()); } // Kept for backward compatibility with older callers. function findCandidates() { return Promise.resolve([]); } window.ShaaritThemeConfig = { save, load, findCandidates }; })(); document.addEventListener('DOMContentLoaded', () => { 'use strict'; const themeCheckbox = document.getElementById('theme-toggle-checkbox'); const themeIconLight = document.getElementById('theme-icon-light'); const themeLabelSpan = document.querySelector('.theme-toggle-label span'); const i18n = window.ShaarliProI18n || { t: function (k) { return k; } }; function checkThemeRestrictions() { const themeId = localStorage.getItem('shaarit_theme_id') || 'DEFAULT'; const darkOnlyThemes = ['LINEAR', 'SPOTIFY', 'NOTION', 'DISCORD', 'DRACULA', 'ONE_DARK_PRO', 'TOKYO_NIGHT', 'NORD', 'NIGHT_OWL', 'ANTHRACITE', 'CYBERPUNK', 'NAVY_ELEGANCE', 'EARTHY']; return darkOnlyThemes.indexOf(themeId) !== -1; } function updateTheme(theme) { // Enforce dark mode if the theme only supports dark if (checkThemeRestrictions()) { theme = 'dark'; } document.documentElement.setAttribute('data-theme', theme); localStorage.setItem('theme', theme); if (themeCheckbox) { themeCheckbox.checked = theme === 'dark'; // Disable the checkbox if restricted to dark mode themeCheckbox.disabled = checkThemeRestrictions(); themeCheckbox.closest('.theme-switch').style.opacity = themeCheckbox.disabled ? '0.5' : '1'; } if (themeIconLight) { themeIconLight.className = theme === 'dark' ? 'mdi mdi-weather-night' : 'mdi mdi-weather-sunny'; } if (themeLabelSpan) { themeLabelSpan.textContent = theme === 'dark' ? i18n.t('Dark Mode') : i18n.t('Light Mode'); } } async function syncModeToBookmark(mode) { try { if (!window.ShaaritThemeConfig) return; await window.ShaaritThemeConfig.save({ mode }); } catch (e) { // eslint-disable-next-line no-console console.error('[shaarit] Failed to sync mode to bookmark', e); } } // Handle themeChanged event fired by tools.html window.addEventListener('themeChanged', () => { updateTheme(localStorage.getItem('theme') || 'dark'); }); // Init Theme const savedTheme = localStorage.getItem('theme') || (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'); updateTheme(savedTheme); if (themeCheckbox) { themeCheckbox.addEventListener('change', () => { if (checkThemeRestrictions()) return; // Extra safety const next = themeCheckbox.checked ? 'dark' : 'light'; updateTheme(next); // Sync mode to bookmark in background syncModeToBookmark(next); }); } });