fix(desktop): session persistence — refresh/login/context/empty-content 4-bug fix
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
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)
This commit is contained in:
56
admin-v2/src/stores/themeStore.ts
Normal file
56
admin-v2/src/stores/themeStore.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
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 })
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user