From 01933546a70768781f1ab7c56b2878294f7cb80e Mon Sep 17 00:00:00 2001 From: Panfilov Konstantin Date: Wed, 21 Oct 2026 22:05:02 +0300 Subject: [PATCH] fix(theme): mirror bounded cookie propagation reconciliation --- components/theme-client.php | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/components/theme-client.php b/components/theme-client.php index 715ea10..dffe4db 100644 --- a/components/theme-client.php +++ b/components/theme-client.php @@ -44,6 +44,24 @@ $themeSurface = isset($themeSurface) && in_array($themeSurface, ['public', 'priv return hex.slice(0, 8) + '-' + hex.slice(8, 12) + '-' + hex.slice(12, 16) + '-' + hex.slice(16, 20) + '-' + hex.slice(20); } function refresh() { const value = read(); apply(value ? themeOf(value) : shown); } + const storageTimers = {soon: null, settled: null, trailing: null}; + function refreshAfterStorage() { + refresh(); + // Между процессами storage notification может прийти раньше cookie. + // Только повторно читаем authority: event.newValue не задаёт порядок выбора. + const schedule = (slot, delay) => { + storageTimers[slot] = window.setTimeout(() => { + storageTimers[slot] = null; + refresh(); + }, delay); + }; + if (storageTimers.soon === null) schedule('soon', 0); + if (storageTimers.settled === null) schedule('settled', 50); + // Новое notification получает собственное trailing окно; ранние passes + // не перезапускаются. Максимум три timers, после тишины повторов нет. + if (storageTimers.trailing !== null) window.clearTimeout(storageTimers.trailing); + schedule('trailing', 250); + } function choose(theme) { if (theme !== 'light' && theme !== 'dark') return; const from = shown; @@ -66,7 +84,7 @@ $themeSurface = isset($themeSurface) && in_array($themeSurface, ['public', 'priv const button = event.target instanceof Element ? event.target.closest('[data-theme-choice]') : null; if (button && !button.disabled) choose(button.dataset.themeChoice); }); - window.addEventListener('storage', event => { if (event.key === key || event.key === null) refresh(); }); + window.addEventListener('storage', event => { if (event.key === key || event.key === null) refreshAfterStorage(); }); window.addEventListener('pageshow', refresh); document.addEventListener('DOMContentLoaded', refresh); document.addEventListener('pjax:end', refresh);