The restricted page's early script now honors the URL theme parameter before the cached profile theme, so a fresh server-provided override wins and the host color scheme applies without a flash. After session load, an empty profile theme clears the cache but keeps the URL parameter in effect instead of reverting to the system default.
58 lines
2.4 KiB
JavaScript
58 lines
2.4 KiB
JavaScript
// Theme override utilities - shared across apps
|
|
// User preference or URL hash can force light/dark mode
|
|
|
|
const TRANSITION_ID = 'theme-transition'
|
|
const STORAGE_KEY = 'paskia-theme'
|
|
|
|
/** Apply theme by setting class on documentElement */
|
|
export function applyTheme(theme, element = document.documentElement, animate = false) {
|
|
// Add temporary transition for smooth theme change
|
|
if (animate) {
|
|
let transitionStyle = document.getElementById(TRANSITION_ID)
|
|
if (!transitionStyle) {
|
|
transitionStyle = document.createElement('style')
|
|
transitionStyle.id = TRANSITION_ID
|
|
transitionStyle.textContent = '*, *::before, *::after { transition: background-color 0.3s, color 0.3s, border-color 0.3s, box-shadow 0.3s !important; }'
|
|
document.head.appendChild(transitionStyle)
|
|
}
|
|
setTimeout(() => document.getElementById(TRANSITION_ID)?.remove(), 350)
|
|
}
|
|
// If no explicit theme, check system preference
|
|
const isDark = theme === 'dark' || (theme !== 'light' && matchMedia('(prefers-color-scheme:dark)').matches)
|
|
element.classList.toggle('dark', isDark)
|
|
}
|
|
|
|
/** Get theme from localStorage cache */
|
|
export function getCachedTheme() {
|
|
return localStorage.getItem(STORAGE_KEY) || ''
|
|
}
|
|
|
|
/** Cache theme in localStorage */
|
|
export function setCachedTheme(theme) {
|
|
if (theme) localStorage.setItem(STORAGE_KEY, theme)
|
|
else localStorage.removeItem(STORAGE_KEY)
|
|
}
|
|
|
|
/** Initialize theme from user preference (with localStorage cache for fast load) */
|
|
export function initThemeFromCache() {
|
|
applyTheme(getCachedTheme())
|
|
}
|
|
|
|
/** Theme default from the URL hash (restricted iframe/forward pages only) */
|
|
function getHashTheme() {
|
|
const theme = new URLSearchParams(window.location.hash.slice(1)).get('theme')
|
|
return theme === 'light' || theme === 'dark' ? theme : ''
|
|
}
|
|
|
|
/** Update theme from session context (call after login/session load) */
|
|
export function updateThemeFromSession(ctx, animate = false) {
|
|
const theme = ctx?.user?.theme || ''
|
|
// Always keep the cache in sync with the profile: empty override clears it
|
|
// so stale values never mask future server-provided themes.
|
|
setCachedTheme(theme)
|
|
// Without a profile override, stay consistent with the initial paint: a
|
|
// theme parameter on the URL (e.g. host page color scheme injected by
|
|
// paskia-js) remains in effect before the browser/desktop default.
|
|
applyTheme(theme || getHashTheme(), document.documentElement, animate)
|
|
}
|