Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
1. App.tsx: add restoreSession() call on startup to prevent redirect to login page after refresh (isRestoring guard + BootstrapScreen) 2. CloneManager: call syncAgents() after loadClones() to restore currentAgent and conversation history on app load 3. zclaw-memory: add get_or_create_session() so frontend session UUID is persisted directly — kernel no longer creates mismatched IDs 4. openai.rs: assistant message content must be non-empty for Kimi/Qwen APIs — replace empty content with meaningful placeholders Also includes admin-v2 ModelServices unified page (merge providers + models + API keys into expandable row layout)
57 lines
1.6 KiB
TypeScript
57 lines
1.6 KiB
TypeScript
import { create } from 'zustand'
|
|
|
|
type ThemeMode = 'light' | 'dark' | 'system'
|
|
|
|
interface ThemeState {
|
|
mode: ThemeMode
|
|
resolved: 'light' | 'dark'
|
|
}
|
|
|
|
function getSystemTheme(): 'light' | 'dark' {
|
|
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
|
|
}
|
|
|
|
function resolveTheme(mode: ThemeMode): 'light' | 'dark' {
|
|
return mode === 'system' ? getSystemTheme() : mode
|
|
}
|
|
|
|
function applyTheme(resolved: 'light' | 'dark') {
|
|
const html = document.documentElement
|
|
html.classList.toggle('dark', resolved === 'dark')
|
|
html.setAttribute('data-theme', resolved)
|
|
}
|
|
|
|
function getInitialMode(): ThemeMode {
|
|
const stored = localStorage.getItem('zclaw_admin_theme')
|
|
if (stored === 'light' || stored === 'dark' || stored === 'system') return stored
|
|
return 'system'
|
|
}
|
|
|
|
const initialMode = getInitialMode()
|
|
const initialResolved = resolveTheme(initialMode)
|
|
applyTheme(initialResolved)
|
|
|
|
export const useThemeStore = create<ThemeState>(() => ({
|
|
mode: initialMode,
|
|
resolved: initialResolved,
|
|
}))
|
|
|
|
export function setThemeMode(mode: ThemeMode) {
|
|
const resolved = resolveTheme(mode)
|
|
localStorage.setItem('zclaw_admin_theme', mode)
|
|
applyTheme(resolved)
|
|
useThemeStore.setState({ mode, resolved })
|
|
}
|
|
|
|
// Listen for system theme changes
|
|
if (typeof window !== 'undefined') {
|
|
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
|
|
const { mode } = useThemeStore.getState()
|
|
if (mode === 'system') {
|
|
const resolved = getSystemTheme()
|
|
applyTheme(resolved)
|
|
useThemeStore.setState({ resolved })
|
|
}
|
|
})
|
|
}
|