- Unified localStorage key to 'theme-preference' across all components
- Fixed header.tsx using wrong localStorage key ('theme' instead of 'theme-preference')
- Added localStorage hybrid persistence for instant theme changes
- Removed router.refresh() which was causing stale data revert
- Replaced Blue theme with Sepia
- Consolidated auth() calls to prevent race conditions
- Updated UserSettingsData types to include all themes
84 lines
2.8 KiB
TypeScript
84 lines
2.8 KiB
TypeScript
'use client'
|
|
|
|
import { useEffect } from 'react'
|
|
|
|
interface ThemeInitializerProps {
|
|
theme?: string
|
|
fontSize?: string
|
|
}
|
|
|
|
export function ThemeInitializer({ theme, fontSize }: ThemeInitializerProps) {
|
|
useEffect(() => {
|
|
console.log('[ThemeInitializer] Received theme:', theme)
|
|
// Helper to apply theme
|
|
const applyTheme = (t?: string) => {
|
|
console.log('[ThemeInitializer] Applying theme:', t)
|
|
if (!t) return
|
|
|
|
const root = document.documentElement
|
|
|
|
// Reset
|
|
root.removeAttribute('data-theme')
|
|
root.classList.remove('dark')
|
|
|
|
if (t === 'auto') {
|
|
const systemDark = window.matchMedia('(prefers-color-scheme: dark)').matches
|
|
if (systemDark) root.classList.add('dark')
|
|
} else if (t === 'dark') {
|
|
root.classList.add('dark')
|
|
} else if (t === 'light') {
|
|
// Default, nothing needed usually if light is default, but ensuring no 'dark' class
|
|
} else {
|
|
// Named theme
|
|
root.setAttribute('data-theme', t)
|
|
// Check if theme implies dark mode (e.g. midnight)
|
|
if (['midnight'].includes(t)) {
|
|
root.classList.add('dark')
|
|
}
|
|
}
|
|
}
|
|
|
|
// Helper to apply font size
|
|
const applyFontSize = (s?: string) => {
|
|
const size = s || 'medium'
|
|
|
|
const fontSizeMap: Record<string, string> = {
|
|
'small': '14px',
|
|
'medium': '16px',
|
|
'large': '18px',
|
|
'extra-large': '20px'
|
|
}
|
|
|
|
const fontSizeFactorMap: Record<string, number> = {
|
|
'small': 0.95,
|
|
'medium': 1.0,
|
|
'large': 1.1,
|
|
'extra-large': 1.25
|
|
}
|
|
|
|
const root = document.documentElement
|
|
root.style.setProperty('--user-font-size', fontSizeMap[size] || '16px')
|
|
root.style.setProperty('--user-font-size-factor', (fontSizeFactorMap[size] || 1).toString())
|
|
}
|
|
|
|
// CRITICAL: Use localStorage as the source of truth (it's always fresh)
|
|
// Server prop may be stale due to caching.
|
|
const localTheme = localStorage.getItem('theme-preference')
|
|
const effectiveTheme = localTheme || theme
|
|
|
|
console.log('[ThemeInitializer] Local theme:', localTheme, '| Server theme:', theme, '| Using:', effectiveTheme)
|
|
|
|
applyTheme(effectiveTheme)
|
|
|
|
// Only sync to localStorage if it was empty (first visit after login)
|
|
// NEVER overwrite with server value if localStorage already has a value
|
|
if (!localTheme && theme) {
|
|
localStorage.setItem('theme-preference', theme)
|
|
}
|
|
|
|
applyFontSize(fontSize)
|
|
}, [theme, fontSize])
|
|
|
|
return null
|
|
}
|