- Rename directory keep-notes -> memento-note with all code references - Prisma: SQLite -> PostgreSQL (both app and MCP server schemas) - Sync MCP schema with main app (add missing fields, relations, indexes) - Delete 17 SQLite migrations (clean slate for PostgreSQL) - Remove SQLite dependencies (@libsql/client, better-sqlite3, etc.) - Fix MCP server: hardcoded Windows DB paths -> DATABASE_URL env var - Fix MCP server: .dockerignore excluded index-sse.js (SSE mode broken) - MCP Dockerfile: node:20 -> node:22 - Docker Compose: add postgres service, remove SQLite volume - Generate favicon.ico, icon-192.png, icon-512.png, apple-icon.png - Update layout.tsx icons and manifest.json for PNG icons - Update all .env files for PostgreSQL - Rewrite README.md with updated sections - Remove mcp-server/node_modules and prisma/client-generated from git tracking Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
84 lines
2.6 KiB
TypeScript
84 lines
2.6 KiB
TypeScript
'use client'
|
|
|
|
import { useEffect } from 'react'
|
|
|
|
interface ThemeInitializerProps {
|
|
theme?: string
|
|
fontSize?: string
|
|
}
|
|
|
|
export function ThemeInitializer({ theme, fontSize }: ThemeInitializerProps) {
|
|
useEffect(() => {
|
|
|
|
// Helper to apply theme
|
|
const applyTheme = (t?: string) => {
|
|
|
|
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
|
|
|
|
|
|
|
|
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
|
|
}
|