diff --git a/shaarli-pro/js/script.js b/shaarli-pro/js/script.js index e58c4ab..b42f607 100644 --- a/shaarli-pro/js/script.js +++ b/shaarli-pro/js/script.js @@ -139,7 +139,18 @@ return inflight; } - window.ShaaritThemeConfig = { save, findCandidates }; + // Reads the current persisted config from the bookmark (no write). + // Returns null when no bookmark exists yet or JSON is invalid. + async function load() { + try { + const { existing } = await readEditForm(CONFIG_URL); + return existing || null; + } catch (e) { + return null; + } + } + + window.ShaaritThemeConfig = { save, load, findCandidates }; })(); document.addEventListener('DOMContentLoaded', () => { @@ -3556,54 +3567,53 @@ document.addEventListener('DOMContentLoaded', () => { })(); // ===== Sync Theme from Bookmark in Background ===== - setTimeout(() => { - // Run sync after a slight delay to avoid blocking initial load - if (!window.shaarli || !window.shaarli.basePath) return; - - fetch(window.shaarli.basePath + '/?searchtags=themes') - .then(res => res.text()) - .then(text => { - const parser = new DOMParser(); - const doc = parser.parseFromString(text, 'text/html'); - const linkCard = doc.querySelector('.linklist-item'); - if (linkCard) { - const descEl = linkCard.querySelector('.link-description p'); - if (descEl) { - try { - const config = JSON.parse(descEl.textContent.trim()); - const remoteThemeId = config.default; - const remoteMode = config.mode; - const localThemeId = localStorage.getItem('shaarit_theme_id') || 'DEFAULT'; - const localMode = localStorage.getItem('theme') || (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'); - - // Sync theme if different - if (remoteThemeId && remoteThemeId !== localThemeId) { - localStorage.setItem('shaarit_theme_id', remoteThemeId); - document.documentElement.setAttribute('data-theme-id', remoteThemeId); - console.log('[shaarit] Theme synced from bookmark:', remoteThemeId); - } - - // Sync mode if different - if (remoteMode && remoteMode !== localMode) { - localStorage.setItem('theme', remoteMode); - document.documentElement.setAttribute('data-theme', remoteMode); - console.log('[shaarit] Mode synced from bookmark:', remoteMode); - } - - // Enforce light/dark constraints based on synced theme - const darkOnlyThemes = ['LINEAR', 'SPOTIFY', 'NOTION', 'DISCORD', 'DRACULA', 'ONE_DARK_PRO', 'TOKYO_NIGHT', 'NORD', 'NIGHT_OWL', 'ANTHRACITE', 'CYBERPUNK', 'NAVY_ELEGANCE', 'EARTHY']; - const syncedThemeId = remoteThemeId || localThemeId; - if (darkOnlyThemes.indexOf(syncedThemeId) !== -1) { - localStorage.setItem('theme', 'dark'); - document.documentElement.setAttribute('data-theme', 'dark'); - } - - window.dispatchEvent(new Event('themeChanged')); - } catch(e) {} - } - } - }) - .catch(err => console.log('[shaarit] Background theme sync failed:', err)); - }, 1500); + // On every page load (including hard refresh): fetch the single config + // bookmark and apply {default, mode} if they differ from localStorage. + // This makes the bookmark the source of truth across devices/sessions. + (async function syncFromBookmark() { + try { + if (!window.ShaaritThemeConfig) return; + const config = await window.ShaaritThemeConfig.load(); + if (!config) return; + + const remoteThemeId = config.default; + const remoteMode = config.mode; + const localThemeId = localStorage.getItem('shaarit_theme_id') || 'DEFAULT'; + const localMode = localStorage.getItem('theme') + || (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'); + + let changed = false; + if (remoteThemeId && remoteThemeId !== localThemeId) { + localStorage.setItem('shaarit_theme_id', remoteThemeId); + document.documentElement.setAttribute('data-theme-id', remoteThemeId); + console.log('[shaarit] Theme synced from bookmark:', remoteThemeId); + changed = true; + } + if (remoteMode && remoteMode !== localMode) { + localStorage.setItem('theme', remoteMode); + document.documentElement.setAttribute('data-theme', remoteMode); + console.log('[shaarit] Mode synced from bookmark:', remoteMode); + changed = true; + } + + // Enforce dark-only theme constraints after remote apply + const darkOnlyThemes = ['LINEAR', 'SPOTIFY', 'NOTION', 'DISCORD', 'DRACULA', + 'ONE_DARK_PRO', 'TOKYO_NIGHT', 'NORD', 'NIGHT_OWL', 'ANTHRACITE', + 'CYBERPUNK', 'NAVY_ELEGANCE', 'EARTHY']; + const effectiveThemeId = remoteThemeId || localThemeId; + if (darkOnlyThemes.indexOf(effectiveThemeId) !== -1 + && localStorage.getItem('theme') !== 'dark') { + localStorage.setItem('theme', 'dark'); + document.documentElement.setAttribute('data-theme', 'dark'); + changed = true; + } + + if (changed) { + window.dispatchEvent(new Event('themeChanged')); + } + } catch (err) { + console.log('[shaarit] Background theme sync failed:', err); + } + })(); });