|
|
|
@ -17,17 +17,7 @@ |
|
|
|
|
|
|
|
|
|
|
|
// Initialize theme and preferences from localStorage immediately (before any components render) |
|
|
|
// Initialize theme and preferences from localStorage immediately (before any components render) |
|
|
|
if (browser) { |
|
|
|
if (browser) { |
|
|
|
// Initialize theme |
|
|
|
// Initialize other preferences first (design theme affects theme) |
|
|
|
const storedTheme = localStorage.getItem('theme'); |
|
|
|
|
|
|
|
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; |
|
|
|
|
|
|
|
const shouldBeDark = storedTheme === 'dark' || (!storedTheme && prefersDark); |
|
|
|
|
|
|
|
if (shouldBeDark) { |
|
|
|
|
|
|
|
document.documentElement.classList.add('dark'); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
document.documentElement.classList.remove('dark'); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Initialize other preferences |
|
|
|
|
|
|
|
const textSize = localStorage.getItem('textSize') || 'medium'; |
|
|
|
const textSize = localStorage.getItem('textSize') || 'medium'; |
|
|
|
const lineSpacing = localStorage.getItem('lineSpacing') || 'normal'; |
|
|
|
const lineSpacing = localStorage.getItem('lineSpacing') || 'normal'; |
|
|
|
const contentWidth = localStorage.getItem('contentWidth') || 'medium'; |
|
|
|
const contentWidth = localStorage.getItem('contentWidth') || 'medium'; |
|
|
|
@ -38,6 +28,31 @@ |
|
|
|
document.documentElement.setAttribute('data-content-width', contentWidth); |
|
|
|
document.documentElement.setAttribute('data-content-width', contentWidth); |
|
|
|
document.documentElement.setAttribute('data-design-theme', designTheme); |
|
|
|
document.documentElement.setAttribute('data-design-theme', designTheme); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Initialize theme (terminal theme always uses dark mode) |
|
|
|
|
|
|
|
const storedTheme = localStorage.getItem('theme'); |
|
|
|
|
|
|
|
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; |
|
|
|
|
|
|
|
let shouldBeDark: boolean; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (designTheme === 'terminal') { |
|
|
|
|
|
|
|
// Terminal theme always uses dark mode |
|
|
|
|
|
|
|
shouldBeDark = true; |
|
|
|
|
|
|
|
} else if (storedTheme) { |
|
|
|
|
|
|
|
shouldBeDark = storedTheme === 'dark'; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
shouldBeDark = prefersDark; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (shouldBeDark) { |
|
|
|
|
|
|
|
document.documentElement.classList.add('dark'); |
|
|
|
|
|
|
|
// Ensure localStorage is set correctly |
|
|
|
|
|
|
|
if (designTheme !== 'terminal') { |
|
|
|
|
|
|
|
localStorage.setItem('theme', 'dark'); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
document.documentElement.classList.remove('dark'); |
|
|
|
|
|
|
|
localStorage.setItem('theme', 'light'); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Try to restore session synchronously if possible |
|
|
|
// Try to restore session synchronously if possible |
|
|
|
// This ensures session is restored before any components render |
|
|
|
// This ensures session is restored before any components render |
|
|
|
(async () => { |
|
|
|
(async () => { |
|
|
|
@ -52,15 +67,67 @@ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Also restore in onMount as fallback |
|
|
|
// Also restore in onMount as fallback |
|
|
|
onMount(async () => { |
|
|
|
onMount(() => { |
|
|
|
try { |
|
|
|
// Set up storage listener synchronously |
|
|
|
// Only restore if there's no active session |
|
|
|
let storageCleanup: (() => void) | undefined; |
|
|
|
// This prevents overwriting sessions that were just created during login |
|
|
|
|
|
|
|
if (!sessionManager.isLoggedIn()) { |
|
|
|
if (browser) { |
|
|
|
await sessionManager.restoreSession(); |
|
|
|
// Listen for storage changes to sync settings across tabs |
|
|
|
} |
|
|
|
const handleStorageChange = (e: StorageEvent) => { |
|
|
|
|
|
|
|
if (e.key === 'theme') { |
|
|
|
if (browser) { |
|
|
|
const designTheme = document.documentElement.getAttribute('data-design-theme') || 'fog'; |
|
|
|
|
|
|
|
if (designTheme === 'terminal') { |
|
|
|
|
|
|
|
// Terminal theme always uses dark mode |
|
|
|
|
|
|
|
document.documentElement.classList.add('dark'); |
|
|
|
|
|
|
|
} else if (e.newValue === 'dark') { |
|
|
|
|
|
|
|
document.documentElement.classList.add('dark'); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
document.documentElement.classList.remove('dark'); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else if (e.key === 'designTheme') { |
|
|
|
|
|
|
|
const newDesignTheme = e.newValue || 'fog'; |
|
|
|
|
|
|
|
document.documentElement.setAttribute('data-design-theme', newDesignTheme); |
|
|
|
|
|
|
|
// Terminal theme always uses dark mode |
|
|
|
|
|
|
|
if (newDesignTheme === 'terminal') { |
|
|
|
|
|
|
|
document.documentElement.classList.add('dark'); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
// Re-apply theme from localStorage |
|
|
|
|
|
|
|
const storedTheme = localStorage.getItem('theme'); |
|
|
|
|
|
|
|
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; |
|
|
|
|
|
|
|
const shouldBeDark = storedTheme === 'dark' || (!storedTheme && prefersDark); |
|
|
|
|
|
|
|
if (shouldBeDark) { |
|
|
|
|
|
|
|
document.documentElement.classList.add('dark'); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
document.documentElement.classList.remove('dark'); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else if (e.key === 'textSize') { |
|
|
|
|
|
|
|
document.documentElement.setAttribute('data-text-size', e.newValue || 'medium'); |
|
|
|
|
|
|
|
} else if (e.key === 'lineSpacing') { |
|
|
|
|
|
|
|
document.documentElement.setAttribute('data-line-spacing', e.newValue || 'normal'); |
|
|
|
|
|
|
|
} else if (e.key === 'contentWidth') { |
|
|
|
|
|
|
|
document.documentElement.setAttribute('data-content-width', e.newValue || 'medium'); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
window.addEventListener('storage', handleStorageChange); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Cleanup |
|
|
|
|
|
|
|
storageCleanup = () => { |
|
|
|
|
|
|
|
window.removeEventListener('storage', handleStorageChange); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Async operations |
|
|
|
|
|
|
|
(async () => { |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
// Only restore if there's no active session |
|
|
|
|
|
|
|
// This prevents overwriting sessions that were just created during login |
|
|
|
|
|
|
|
if (!sessionManager.isLoggedIn()) { |
|
|
|
|
|
|
|
await sessionManager.restoreSession(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (browser) { |
|
|
|
// Check for post-update redirect |
|
|
|
// Check for post-update redirect |
|
|
|
const postUpdateRedirect = sessionStorage.getItem('postUpdateRedirect'); |
|
|
|
const postUpdateRedirect = sessionStorage.getItem('postUpdateRedirect'); |
|
|
|
if (postUpdateRedirect) { |
|
|
|
if (postUpdateRedirect) { |
|
|
|
@ -99,9 +166,13 @@ |
|
|
|
preloadGifs().catch(() => { |
|
|
|
preloadGifs().catch(() => { |
|
|
|
// Non-critical, ignore errors |
|
|
|
// Non-critical, ignore errors |
|
|
|
}); |
|
|
|
}); |
|
|
|
} catch (error) { |
|
|
|
} catch (error) { |
|
|
|
console.error('Failed to restore session:', error); |
|
|
|
console.error('Failed to restore session:', error); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
})(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Return cleanup function |
|
|
|
|
|
|
|
return storageCleanup; |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
function handleUpdateComplete() { |
|
|
|
function handleUpdateComplete() { |
|
|
|
|