import { create } from 'zustand' import { isThemeMode, THEME_MODES, type ThemeMode } from '../types/settings' const THEME_STORAGE_KEY = 'cc-haha-theme' function getStoredTheme(): ThemeMode { try { const stored = localStorage.getItem(THEME_STORAGE_KEY) if (isThemeMode(stored)) return stored } catch { /* localStorage unavailable */ } return 'light' } export function applyTheme(theme: ThemeMode) { if (typeof document === 'undefined') return document.documentElement.setAttribute('data-theme', theme) document.documentElement.style.colorScheme = theme === 'dark' ? 'dark' : 'light' } export function initializeTheme() { applyTheme(getStoredTheme()) } export type Toast = { id: string type: 'success' | 'error' | 'warning' | 'info' message: string duration?: number } export type SettingsTab = | 'providers' | 'permissions' | 'activity' | 'general' | 'h5Access' | 'adapters' | 'terminal' | 'mcp' | 'agents' | 'skills' | 'memory' | 'plugins' | 'computerUse' | 'diagnostics' | 'about' type ActiveView = 'code' | 'scheduled' | 'terminal' | 'history' | 'settings' type UIStore = { theme: ThemeMode sidebarOpen: boolean activeView: ActiveView pendingSettingsTab: SettingsTab | null pendingMemoryPath: string | null activeModal: string | null toasts: Toast[] setTheme: (theme: ThemeMode) => void toggleTheme: () => void toggleSidebar: () => void setSidebarOpen: (open: boolean) => void setActiveView: (view: ActiveView) => void setPendingSettingsTab: (tab: SettingsTab | null) => void setPendingMemoryPath: (path: string | null) => void openModal: (id: string) => void closeModal: () => void addToast: (toast: Omit) => void removeToast: (id: string) => void } let toastCounter = 0 export const useUIStore = create((set) => ({ theme: getStoredTheme(), sidebarOpen: true, activeView: 'code', pendingSettingsTab: null, pendingMemoryPath: null, activeModal: null, toasts: [], setTheme: (theme) => { applyTheme(theme) try { localStorage.setItem(THEME_STORAGE_KEY, theme) } catch { /* noop */ } set({ theme }) }, toggleTheme: () => { set((state) => { const currentIndex = THEME_MODES.indexOf(state.theme) const next = THEME_MODES[(currentIndex + 1) % THEME_MODES.length] ?? 'light' applyTheme(next) try { localStorage.setItem(THEME_STORAGE_KEY, next) } catch { /* noop */ } return { theme: next } }) }, toggleSidebar: () => set((s) => ({ sidebarOpen: !s.sidebarOpen })), setSidebarOpen: (open) => set({ sidebarOpen: open }), setActiveView: (view) => set({ activeView: view }), setPendingSettingsTab: (tab) => set({ pendingSettingsTab: tab }), setPendingMemoryPath: (path) => set({ pendingMemoryPath: path }), openModal: (id) => set({ activeModal: id }), closeModal: () => set({ activeModal: null }), addToast: (toast) => { const id = `toast-${++toastCounter}` set((s) => ({ toasts: [...s.toasts, { ...toast, id }] })) // Auto-remove after duration const duration = toast.duration ?? 4000 if (duration > 0) { setTimeout(() => { set((s) => ({ toasts: s.toasts.filter((t) => t.id !== id) })) }, duration) } }, removeToast: (id) => set((s) => ({ toasts: s.toasts.filter((t) => t.id !== id) })), }))