mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-25 15:25:50 +00:00
支持系统深浅自适应同步
This commit is contained in:
25
src/App.tsx
25
src/App.tsx
@@ -25,7 +25,7 @@ import NotificationWindow from './pages/NotificationWindow'
|
|||||||
import AIChatPage from './pages/AIChatPage'
|
import AIChatPage from './pages/AIChatPage'
|
||||||
|
|
||||||
import { useAppStore } from './stores/appStore'
|
import { useAppStore } from './stores/appStore'
|
||||||
import { themes, useThemeStore, type ThemeId } from './stores/themeStore'
|
import { themes, useThemeStore, type ThemeId, type ThemeMode } from './stores/themeStore'
|
||||||
import * as configService from './services/config'
|
import * as configService from './services/config'
|
||||||
import { Download, X, Shield } from 'lucide-react'
|
import { Download, X, Shield } from 'lucide-react'
|
||||||
import './App.scss'
|
import './App.scss'
|
||||||
@@ -101,14 +101,27 @@ function App() {
|
|||||||
|
|
||||||
// 应用主题
|
// 应用主题
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
const mq = window.matchMedia('(prefers-color-scheme: dark)')
|
||||||
|
const applyMode = (mode: ThemeMode, systemDark?: boolean) => {
|
||||||
|
const effectiveMode = mode === 'system' ? (systemDark ?? mq.matches ? 'dark' : 'light') : mode
|
||||||
document.documentElement.setAttribute('data-theme', currentTheme)
|
document.documentElement.setAttribute('data-theme', currentTheme)
|
||||||
document.documentElement.setAttribute('data-mode', themeMode)
|
document.documentElement.setAttribute('data-mode', effectiveMode)
|
||||||
|
const symbolColor = effectiveMode === 'dark' ? '#ffffff' : '#1a1a1a'
|
||||||
// 更新窗口控件颜色以适配主题
|
|
||||||
const symbolColor = themeMode === 'dark' ? '#ffffff' : '#1a1a1a'
|
|
||||||
if (!isOnboardingWindow && !isNotificationWindow) {
|
if (!isOnboardingWindow && !isNotificationWindow) {
|
||||||
window.electronAPI.window.setTitleBarOverlay({ symbolColor })
|
window.electronAPI.window.setTitleBarOverlay({ symbolColor })
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
applyMode(themeMode)
|
||||||
|
|
||||||
|
// 监听系统主题变化
|
||||||
|
const handler = (e: MediaQueryListEvent) => {
|
||||||
|
if (useThemeStore.getState().themeMode === 'system') {
|
||||||
|
applyMode('system', e.matches)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mq.addEventListener('change', handler)
|
||||||
|
return () => mq.removeEventListener('change', handler)
|
||||||
}, [currentTheme, themeMode, isOnboardingWindow, isNotificationWindow])
|
}, [currentTheme, themeMode, isOnboardingWindow, isNotificationWindow])
|
||||||
|
|
||||||
// 读取已保存的主题设置
|
// 读取已保存的主题设置
|
||||||
@@ -122,7 +135,7 @@ function App() {
|
|||||||
if (savedThemeId && themes.some((theme) => theme.id === savedThemeId)) {
|
if (savedThemeId && themes.some((theme) => theme.id === savedThemeId)) {
|
||||||
setTheme(savedThemeId as ThemeId)
|
setTheme(savedThemeId as ThemeId)
|
||||||
}
|
}
|
||||||
if (savedThemeMode === 'light' || savedThemeMode === 'dark') {
|
if (savedThemeMode === 'light' || savedThemeMode === 'dark' || savedThemeMode === 'system') {
|
||||||
setThemeMode(savedThemeMode)
|
setThemeMode(savedThemeMode)
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { dialog } from '../services/ipc'
|
|||||||
import * as configService from '../services/config'
|
import * as configService from '../services/config'
|
||||||
import {
|
import {
|
||||||
Eye, EyeOff, FolderSearch, FolderOpen, Search, Copy,
|
Eye, EyeOff, FolderSearch, FolderOpen, Search, Copy,
|
||||||
RotateCcw, Trash2, Plug, Check, Sun, Moon,
|
RotateCcw, Trash2, Plug, Check, Sun, Moon, Monitor,
|
||||||
Palette, Database, Download, HardDrive, Info, RefreshCw, ChevronDown, Mic,
|
Palette, Database, Download, HardDrive, Info, RefreshCw, ChevronDown, Mic,
|
||||||
ShieldCheck, Fingerprint, Lock, KeyRound, Bell, Globe, BarChart2
|
ShieldCheck, Fingerprint, Lock, KeyRound, Bell, Globe, BarChart2
|
||||||
} from 'lucide-react'
|
} from 'lucide-react'
|
||||||
@@ -55,6 +55,14 @@ function SettingsPage() {
|
|||||||
|
|
||||||
const resetChatStore = useChatStore((state) => state.reset)
|
const resetChatStore = useChatStore((state) => state.reset)
|
||||||
const { currentTheme, themeMode, setTheme, setThemeMode } = useThemeStore()
|
const { currentTheme, themeMode, setTheme, setThemeMode } = useThemeStore()
|
||||||
|
const [systemDark, setSystemDark] = useState(() => window.matchMedia('(prefers-color-scheme: dark)').matches)
|
||||||
|
useEffect(() => {
|
||||||
|
const mq = window.matchMedia('(prefers-color-scheme: dark)')
|
||||||
|
const handler = (e: MediaQueryListEvent) => setSystemDark(e.matches)
|
||||||
|
mq.addEventListener('change', handler)
|
||||||
|
return () => mq.removeEventListener('change', handler)
|
||||||
|
}, [])
|
||||||
|
const effectiveMode = themeMode === 'system' ? (systemDark ? 'dark' : 'light') : themeMode
|
||||||
const clearAnalyticsStoreCache = useAnalyticsStore((state) => state.clearCache)
|
const clearAnalyticsStoreCache = useAnalyticsStore((state) => state.clearCache)
|
||||||
|
|
||||||
const [activeTab, setActiveTab] = useState<SettingsTab>('appearance')
|
const [activeTab, setActiveTab] = useState<SettingsTab>('appearance')
|
||||||
@@ -993,11 +1001,14 @@ function SettingsPage() {
|
|||||||
<button className={`mode-btn ${themeMode === 'dark' ? 'active' : ''}`} onClick={() => setThemeMode('dark')}>
|
<button className={`mode-btn ${themeMode === 'dark' ? 'active' : ''}`} onClick={() => setThemeMode('dark')}>
|
||||||
<Moon size={16} /> 深色
|
<Moon size={16} /> 深色
|
||||||
</button>
|
</button>
|
||||||
|
<button className={`mode-btn ${themeMode === 'system' ? 'active' : ''}`} onClick={() => setThemeMode('system')}>
|
||||||
|
<Monitor size={16} /> 跟随系统
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="theme-grid">
|
<div className="theme-grid">
|
||||||
{themes.map((theme) => (
|
{themes.map((theme) => (
|
||||||
<div key={theme.id} className={`theme-card ${currentTheme === theme.id ? 'active' : ''}`} onClick={() => setTheme(theme.id)}>
|
<div key={theme.id} className={`theme-card ${currentTheme === theme.id ? 'active' : ''}`} onClick={() => setTheme(theme.id)}>
|
||||||
<div className="theme-preview" style={{ background: themeMode === 'dark' ? 'linear-gradient(135deg, #1a1a1a 0%, #2a2a2a 100%)' : `linear-gradient(135deg, ${theme.bgColor} 0%, ${theme.bgColor}dd 100%)` }}>
|
<div className="theme-preview" style={{ background: effectiveMode === 'dark' ? 'linear-gradient(135deg, #1a1a1a 0%, #2a2a2a 100%)' : `linear-gradient(135deg, ${theme.bgColor} 0%, ${theme.bgColor}dd 100%)` }}>
|
||||||
<div className="theme-accent" style={{ background: theme.primaryColor }} />
|
<div className="theme-accent" style={{ background: theme.primaryColor }} />
|
||||||
</div>
|
</div>
|
||||||
<div className="theme-info">
|
<div className="theme-info">
|
||||||
|
|||||||
@@ -118,13 +118,13 @@ export async function setWxidConfig(wxid: string, configValue: WxidConfig): Prom
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取主题
|
// 获取主题
|
||||||
export async function getTheme(): Promise<'light' | 'dark'> {
|
export async function getTheme(): Promise<'light' | 'dark' | 'system'> {
|
||||||
const value = await config.get(CONFIG_KEYS.THEME)
|
const value = await config.get(CONFIG_KEYS.THEME)
|
||||||
return (value as 'light' | 'dark') || 'light'
|
return (value as 'light' | 'dark' | 'system') || 'light'
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置主题
|
// 设置主题
|
||||||
export async function setTheme(theme: 'light' | 'dark'): Promise<void> {
|
export async function setTheme(theme: 'light' | 'dark' | 'system'): Promise<void> {
|
||||||
await config.set(CONFIG_KEYS.THEME, theme)
|
await config.set(CONFIG_KEYS.THEME, theme)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { create } from 'zustand'
|
|||||||
import { persist } from 'zustand/middleware'
|
import { persist } from 'zustand/middleware'
|
||||||
|
|
||||||
export type ThemeId = 'cloud-dancer' | 'corundum-blue' | 'kiwi-green' | 'spicy-red' | 'teal-water'
|
export type ThemeId = 'cloud-dancer' | 'corundum-blue' | 'kiwi-green' | 'spicy-red' | 'teal-water'
|
||||||
export type ThemeMode = 'light' | 'dark'
|
export type ThemeMode = 'light' | 'dark' | 'system'
|
||||||
|
|
||||||
export interface ThemeInfo {
|
export interface ThemeInfo {
|
||||||
id: ThemeId
|
id: ThemeId
|
||||||
|
|||||||
Reference in New Issue
Block a user