RSS Git Download  Clone
Raw Blame History 2kB 77 lines
import { create } from 'zustand'
import { isDarkTheme } from '../themes'

const STORAGE_KEY = 'p3xr-theme'
const AUTO = 'auto'

function getSystemDark(): boolean {
    return typeof window !== 'undefined' && window.matchMedia?.('(prefers-color-scheme: dark)').matches
}

function readStored(): string {
    try { return localStorage.getItem(STORAGE_KEY) || AUTO } catch { return AUTO }
}

function applyBodyClasses(resolved: string): void {
    if (typeof document === 'undefined') return
    const dark = isDarkTheme(resolved)
    document.documentElement.setAttribute('data-color-scheme', dark ? 'dark' : 'light')
    document.body.classList.toggle('p3xr-theme-dark', dark)
    document.body.classList.toggle('p3xr-theme-light', !dark)
}

// Same logic as Angular ThemeService
function resolveThemeKey(stored: string): string {
    if (stored === AUTO) return getSystemDark() ? 'dark' : 'enterprise'
    return stored
}

interface ThemeState {
    isAuto: boolean
    themeKey: string     // resolved key: 'dark', 'enterprise', 'light', etc.
    storedValue: string  // raw stored: 'auto' or theme key
    setTheme: (choice: string) => void  // 'auto' or any theme key
}

export const useThemeStore = create<ThemeState>((set) => {
    const stored = readStored()
    const isAuto = stored === AUTO
    const themeKey = resolveThemeKey(stored)

    // Apply on initial load
    applyBodyClasses(themeKey)

    return {
        isAuto,
        themeKey,
        storedValue: stored,

        setTheme: (choice: string) => {
            const auto = choice === AUTO
            const resolved = auto ? resolveThemeKey(AUTO) : choice
            try { localStorage.setItem(STORAGE_KEY, choice) } catch {}

            applyBodyClasses(resolved)

            // Notify Electron parent
            try {
                window.parent?.postMessage({ type: 'p3x-theme-change', dark: isDarkTheme(resolved) }, '*')
            } catch {}

            set({ isAuto: auto, themeKey: resolved, storedValue: choice })
        },
    }
})

// Listen for system theme changes (auto mode)
if (typeof window !== 'undefined' && window.matchMedia) {
    window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
        const { isAuto } = useThemeStore.getState()
        if (isAuto) {
            const resolved = getSystemDark() ? 'dark' : 'enterprise'
            applyBodyClasses(resolved)
            useThemeStore.setState({ themeKey: resolved })
        }
    })
}