refactor: update preference keys and enhance preference management

- Updated preference keys from 'app.theme.*' to 'ui.*' for better organization and clarity.
- Introduced new preferences for assistant tab sorting and visibility.
- Refactored components to utilize the updated preference keys, improving consistency across the codebase.
- Cleaned up unused code and comments related to previous settings for maintainability.
- Updated auto-generated preference mappings to reflect the new structure.
This commit is contained in:
fullex 2025-09-02 15:37:30 +08:00
parent 0a67ab4103
commit 820d6a6e96
24 changed files with 135 additions and 115 deletions

View File

@ -40,3 +40,5 @@ export type LanguageVarious = 'zh-CN' | 'zh-TW' | 'el-GR' | 'en-US' | 'es-ES' |
export type WindowStyle = 'transparent' | 'opaque'
export type SendMessageShortcut = 'Enter' | 'Shift+Enter' | 'Ctrl+Enter' | 'Command+Enter' | 'Alt+Enter'
export type AssistantTabSortType = 'tags' | 'list'

View File

@ -1,6 +1,6 @@
/**
* Auto-generated preferences configuration
* Generated at: 2025-09-02T04:48:55.916Z
* Generated at: 2025-09-02T06:55:00.341Z
*
* This file is automatically generated from classification.json
* To update this file, modify classification.json and run:
@ -11,6 +11,7 @@
import { TRANSLATE_PROMPT } from '@shared/config/prompts'
import type {
AssistantTabSortType,
SelectionActionItem,
SelectionFilterMode,
SelectionTriggerMode,
@ -58,12 +59,6 @@ export interface PreferencesType {
'app.spell_check.enabled': boolean
// redux/settings/spellCheckLanguages
'app.spell_check.languages': unknown[]
// redux/settings/theme
'app.theme.mode': ThemeMode
// redux/settings/userTheme.colorPrimary
'app.theme.user.color_primary': string
// redux/settings/windowStyle
'app.theme.window_style': WindowStyle
// redux/settings/tray
'app.tray.enabled': boolean
// redux/settings/trayOnClose
@ -76,6 +71,14 @@ export interface PreferencesType {
'app.user.name': string
// electronStore/ZoomFactor/ZoomFactor
'app.zoom_factor': number
// redux/settings/clickAssistantToShowTopic
'assistant.click_to_show_topic': boolean
// redux/settings/assistantIconType
'assistant.icon_type': string
// redux/settings/showAssistants
'assistant.tab.show': boolean
// redux/settings/assistantsTabSortType
'assistant.tab.sort_type': AssistantTabSortType
// redux/settings/codeCollapsible
'chat.code.collapsible': boolean
// redux/settings/codeEditor.autocompletion
@ -290,6 +293,8 @@ export interface PreferencesType {
'feature.minapp.open_link_external': boolean
// redux/settings/showOpenedMinappsInSidebar
'feature.minapp.show_opened_in_sidebar': boolean
// redux/settings/showWorkspace
'feature.notes.show_workspace': boolean
// redux/settings/clickTrayToShowQuickAssistant
'feature.quick_assistant.click_tray_to_show': boolean
// redux/settings/enableQuickAssistant
@ -358,20 +363,24 @@ export interface PreferencesType {
'topic.naming.enabled': boolean
// redux/settings/topicNamingPrompt
'topic.naming.prompt': string
// redux/settings/pinTopicsToTop
'topic.pin_to_top': boolean
// redux/settings/topicPosition
'topic.position': string
// redux/settings/pinTopicsToTop
'topic.tab.pin_to_top': boolean
// redux/settings/showTopics
'topic.tab.show': boolean
// redux/settings/showTopicTime
'topic.show_time': boolean
// redux/settings/assistantIconType
'ui.assistant_icon_type': string
// redux/settings/clickAssistantToShowTopic
'ui.click_assistant_to_show_topic': boolean
'topic.tab.show_time': boolean
// redux/settings/customCss
'ui.custom_css': string
// redux/settings/navbarPosition
'ui.navbar.position': 'left' | 'top'
// redux/settings/theme
'ui.theme_mode': ThemeMode
// redux/settings/userTheme.colorPrimary
'ui.theme_user.color_primary': string
// redux/settings/windowStyle
'ui.window_style': WindowStyle
}
}
@ -394,15 +403,16 @@ export const DefaultPreferences: PreferencesType = {
'app.proxy.url': null,
'app.spell_check.enabled': false,
'app.spell_check.languages': [],
'app.theme.mode': ThemeMode.system,
'app.theme.user.color_primary': '#00b96b',
'app.theme.window_style': 'opaque',
'app.tray.enabled': true,
'app.tray.on_close': true,
'app.tray.on_launch': false,
'app.user.id': 'uuid()',
'app.user.name': '',
'app.zoom_factor': 1,
'assistant.click_to_show_topic': true,
'assistant.icon_type': 'emoji',
'assistant.tab.show': true,
'assistant.tab.sort_type': 'list',
'chat.code.collapsible': false,
'chat.code.editor.autocompletion': true,
'chat.code.editor.enabled': false,
@ -510,6 +520,7 @@ export const DefaultPreferences: PreferencesType = {
'feature.minapp.max_keep_alive': 3,
'feature.minapp.open_link_external': false,
'feature.minapp.show_opened_in_sidebar': true,
'feature.notes.show_workspace': true,
'feature.quick_assistant.click_tray_to_show': false,
'feature.quick_assistant.enabled': false,
'feature.quick_assistant.read_clipboard_at_startup': true,
@ -591,13 +602,15 @@ export const DefaultPreferences: PreferencesType = {
'shortcut.topic.new': { editable: true, enabled: true, key: ['CommandOrControl', 'N'], system: false },
'topic.naming.enabled': true,
'topic.naming.prompt': '',
'topic.pin_to_top': false,
'topic.position': 'left',
'topic.show_time': false,
'ui.assistant_icon_type': 'emoji',
'ui.click_assistant_to_show_topic': true,
'topic.tab.pin_to_top': false,
'topic.tab.show': true,
'topic.tab.show_time': false,
'ui.custom_css': '',
'ui.navbar.position': 'top'
'ui.navbar.position': 'top',
'ui.theme_mode': ThemeMode.system,
'ui.theme_user.color_primary': '#00b96b',
'ui.window_style': 'opaque'
}
}
@ -605,8 +618,8 @@ export const DefaultPreferences: PreferencesType = {
/**
* :
* - 总配置项: 173
* - 总配置项: 177
* - electronStore项: 1
* - redux项: 172
* - redux项: 176
* - localStorage项: 0
*/

View File

@ -1,6 +1,6 @@
/**
* Auto-generated preference mappings from classification.json
* Generated at: 2025-09-02T05:21:08.374Z
* Generated at: 2025-09-02T06:27:50.213Z
*
* This file contains pure mapping relationships without default values.
* Default values are managed in packages/shared/data/preferences.ts
@ -72,7 +72,7 @@ export const REDUX_STORE_MAPPINGS = {
},
{
originalKey: 'theme',
targetKey: 'app.theme.mode'
targetKey: 'ui.theme_mode'
},
{
originalKey: 'tray',
@ -82,6 +82,18 @@ export const REDUX_STORE_MAPPINGS = {
originalKey: 'trayOnClose',
targetKey: 'app.tray.on_close'
},
{
originalKey: 'showAssistants',
targetKey: 'assistant.tab.show'
},
{
originalKey: 'showTopics',
targetKey: 'topic.tab.show'
},
{
originalKey: 'assistantsTabSortType',
targetKey: 'assistant.tab.sort_type'
},
{
originalKey: 'sendMessageShortcut',
targetKey: 'chat.input.send_message_shortcut'
@ -132,11 +144,11 @@ export const REDUX_STORE_MAPPINGS = {
},
{
originalKey: 'userTheme.colorPrimary',
targetKey: 'app.theme.user.color_primary'
targetKey: 'ui.theme_user.color_primary'
},
{
originalKey: 'windowStyle',
targetKey: 'app.theme.window_style'
targetKey: 'ui.window_style'
},
{
originalKey: 'fontSize',
@ -148,15 +160,15 @@ export const REDUX_STORE_MAPPINGS = {
},
{
originalKey: 'showTopicTime',
targetKey: 'topic.show_time'
targetKey: 'topic.tab.show_time'
},
{
originalKey: 'pinTopicsToTop',
targetKey: 'topic.pin_to_top'
targetKey: 'topic.tab.pin_to_top'
},
{
originalKey: 'assistantIconType',
targetKey: 'ui.assistant_icon_type'
targetKey: 'assistant.icon_type'
},
{
originalKey: 'pasteLongTextAsFile',
@ -168,7 +180,7 @@ export const REDUX_STORE_MAPPINGS = {
},
{
originalKey: 'clickAssistantToShowTopic',
targetKey: 'ui.click_assistant_to_show_topic'
targetKey: 'assistant.click_to_show_topic'
},
{
originalKey: 'codeExecution.enabled',
@ -732,9 +744,9 @@ export const REDUX_STORE_MAPPINGS = {
/**
* :
* - ElectronStore项: 1
* - Redux Store项: 172
* - Redux Store项: 175
* - Redux分类: settings, selectionStore, nutstore, shortcuts
* - 总配置项: 173
* - 总配置项: 176
*
* 使:
* 1. ElectronStore读取: configManager.get(mapping.originalKey)

View File

@ -8,18 +8,18 @@ import { titleBarOverlayDark, titleBarOverlayLight } from '../config'
class ThemeService {
private theme: ThemeMode = ThemeMode.system
constructor() {
this.theme = preferenceService.get('app.theme.mode')
this.theme = preferenceService.get('ui.theme_mode')
if (this.theme === ThemeMode.dark || this.theme === ThemeMode.light || this.theme === ThemeMode.system) {
nativeTheme.themeSource = this.theme
} else {
// 兼容旧版本
preferenceService.set('app.theme.mode', ThemeMode.system)
preferenceService.set('ui.theme_mode', ThemeMode.system)
nativeTheme.themeSource = ThemeMode.system
}
nativeTheme.on('updated', this.themeUpdatadHandler.bind(this))
preferenceService.subscribeChange('app.theme.mode', (newTheme) => {
preferenceService.subscribeChange('ui.theme_mode', (newTheme) => {
this.theme = newTheme
nativeTheme.themeSource = newTheme
})

View File

@ -17,7 +17,7 @@ import { useTheme } from './ThemeProvider'
const AntdProvider: FC<PropsWithChildren> = ({ children }) => {
const [language] = usePreference('app.language')
const [colorPrimary] = usePreference('app.theme.user.color_primary')
const [colorPrimary] = usePreference('ui.theme_user.color_primary')
const { theme: _theme } = useTheme()
return (

View File

@ -27,7 +27,7 @@ export const ThemeProvider: React.FC<ThemeProviderProps> = ({ children }) => {
// 用户设置的主题
// const { theme: settedTheme, setTheme: setSettedTheme } = useSettings()
const [settedTheme, setSettedTheme] = usePreference('app.theme.mode')
const [settedTheme, setSettedTheme] = usePreference('ui.theme_mode')
const [actualTheme, setActualTheme] = useState<ThemeMode>(
window.matchMedia('(prefers-color-scheme: dark)').matches ? ThemeMode.dark : ThemeMode.light

View File

@ -38,7 +38,7 @@ export function useAppInit() {
enableDataCollection
} = useSettings()
const [language] = usePreference('app.language')
const [windowStyle] = usePreference('app.theme.window_style')
const [windowStyle] = usePreference('ui.window_style')
const [customCss] = usePreference('ui.custom_css')
const { minappShow } = useRuntime()

View File

@ -2,7 +2,7 @@ import { usePreference } from '@data/hooks/usePreference'
import { isMac } from '@renderer/config/constant'
function useNavBackgroundColor() {
const [windowStyle] = usePreference('app.theme.window_style')
const [windowStyle] = usePreference('ui.window_style')
const macTransparentWindow = isMac && windowStyle === 'transparent'

View File

@ -1,54 +1,42 @@
import { useAppDispatch, useAppSelector } from '@renderer/store'
import {
setAssistantsTabSortType,
setShowAssistants,
setShowTopics,
setShowWorkspace,
toggleShowAssistants,
toggleShowTopics,
toggleShowWorkspace
} from '@renderer/store/settings'
import { AssistantsSortType } from '@renderer/types'
//FIXME 这个文件有必要存在吗? fullex@data refactor
import { usePreference } from '@data/hooks/usePreference'
export function useShowAssistants() {
const showAssistants = useAppSelector((state) => state.settings.showAssistants)
const dispatch = useAppDispatch()
const [showAssistants, setShowAssistants] = usePreference('assistant.tab.show')
return {
showAssistants,
setShowAssistants: (show: boolean) => dispatch(setShowAssistants(show)),
toggleShowAssistants: () => dispatch(toggleShowAssistants())
setShowAssistants,
toggleShowAssistants: () => setShowAssistants(!showAssistants)
}
}
export function useShowTopics() {
const showTopics = useAppSelector((state) => state.settings.showTopics)
const dispatch = useAppDispatch()
const [showTopics, setShowTopics] = usePreference('topic.tab.show')
return {
showTopics,
setShowTopics: (show: boolean) => dispatch(setShowTopics(show)),
toggleShowTopics: () => dispatch(toggleShowTopics())
setShowTopics,
toggleShowTopics: () => setShowTopics(!showTopics)
}
}
export function useAssistantsTabSortType() {
const assistantsTabSortType = useAppSelector((state) => state.settings.assistantsTabSortType)
const dispatch = useAppDispatch()
const [assistantsTabSortType, setAssistantsTabSortType] = usePreference('assistant.tab.sort_type')
return {
assistantsTabSortType,
setAssistantsTabSortType: (sortType: AssistantsSortType) => dispatch(setAssistantsTabSortType(sortType))
setAssistantsTabSortType
}
}
export function useShowWorkspace() {
const showWorkspace = useAppSelector((state) => state.settings.showWorkspace)
const dispatch = useAppDispatch()
const [showWorkspace, setShowWorkspace] = usePreference('feature.notes.show_workspace')
return {
showWorkspace,
setShowWorkspace: (show: boolean) => dispatch(setShowWorkspace(show)),
toggleShowWorkspace: () => dispatch(toggleShowWorkspace())
setShowWorkspace,
toggleShowWorkspace: () => setShowWorkspace(!showWorkspace)
}
}

View File

@ -5,7 +5,7 @@ import { usePreference } from '@data/hooks/usePreference'
import Color from 'color'
export default function useUserTheme() {
const [colorPrimary, setColorPrimary] = usePreference('app.theme.user.color_primary')
const [colorPrimary, setColorPrimary] = usePreference('ui.theme_user.color_primary')
const initUserTheme = (theme: { colorPrimary: string } = { colorPrimary }) => {
const colorPrimary = Color(theme.colorPrimary)

View File

@ -1,9 +1,9 @@
import { usePreference } from '@data/hooks/usePreference'
import { NavbarHeader } from '@renderer/components/app/Navbar'
import { HStack } from '@renderer/components/Layout'
import SearchPopup from '@renderer/components/Popups/SearchPopup'
import { useAssistant } from '@renderer/hooks/useAssistant'
import { modelGenerating } from '@renderer/hooks/useRuntime'
import { useSettings } from '@renderer/hooks/useSettings'
import { useShortcut } from '@renderer/hooks/useShortcuts'
import { useShowAssistants, useShowTopics } from '@renderer/hooks/useStore'
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
@ -32,7 +32,10 @@ interface Props {
const HeaderNavbar: FC<Props> = ({ activeAssistant, setActiveAssistant, activeTopic, setActiveTopic }) => {
const { assistant } = useAssistant(activeAssistant.id)
const { showAssistants, toggleShowAssistants } = useShowAssistants()
const { topicPosition, narrowMode } = useSettings()
const [topicPosition] = usePreference('topic.position')
const [narrowMode] = usePreference('chat.narrow_mode')
const { showTopics, toggleShowTopics } = useShowTopics()
const dispatch = useAppDispatch()

View File

@ -5,7 +5,8 @@ import { useAgents } from '@renderer/hooks/useAgents'
import { useAssistants } from '@renderer/hooks/useAssistant'
import { useAssistantsTabSortType } from '@renderer/hooks/useStore'
import { useTags } from '@renderer/hooks/useTags'
import { Assistant, AssistantsSortType } from '@renderer/types'
import { Assistant } from '@renderer/types'
import type { AssistantTabSortType } from '@shared/data/preferenceTypes'
import { Tooltip, Typography } from 'antd'
import { Plus } from 'lucide-react'
import { FC, useCallback, useMemo, useRef, useState } from 'react'
@ -47,7 +48,7 @@ const Assistants: FC<AssistantsTabProps> = ({
)
const handleSortByChange = useCallback(
(sortType: AssistantsSortType) => {
(sortType: AssistantTabSortType) => {
setAssistantsTabSortType(sortType)
},
[setAssistantsTabSortType]

View File

@ -8,9 +8,10 @@ import { useTags } from '@renderer/hooks/useTags'
import AssistantSettingsPopup from '@renderer/pages/settings/AssistantSettings'
import { getDefaultModel } from '@renderer/services/AssistantService'
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
import { Assistant, AssistantsSortType } from '@renderer/types'
import { Assistant } from '@renderer/types'
import { getLeadingEmoji, uuid } from '@renderer/utils'
import { hasTopicPendingRequests } from '@renderer/utils/queue'
import type { AssistantTabSortType } from '@shared/data/preferenceTypes'
import { Dropdown, MenuProps } from 'antd'
import { omit } from 'lodash'
import {
@ -36,14 +37,14 @@ import AssistantTagsPopup from './AssistantTagsPopup'
interface AssistantItemProps {
assistant: Assistant
isActive: boolean
sortBy: AssistantsSortType
sortBy: AssistantTabSortType
onSwitch: (assistant: Assistant) => void
onDelete: (assistant: Assistant) => void
onCreateDefaultAssistant: () => void
addAgent: (agent: any) => void
copyAssistant: (assistant: Assistant) => void
onTagClick?: (tag: string) => void
handleSortByChange?: (sortType: AssistantsSortType) => void
handleSortByChange?: (sortType: AssistantTabSortType) => void
}
const AssistantItem: FC<AssistantItemProps> = ({

View File

@ -68,7 +68,7 @@ const DisplaySettings: FC = () => {
sidebarIcons,
assistantIconType
} = useSettings()
const [windowStyle, setWindowStyle] = usePreference('app.theme.window_style')
const [windowStyle, setWindowStyle] = usePreference('ui.window_style')
const [customCss, setCustomCss] = usePreference('ui.custom_css')
const { navbarPosition, setNavbarPosition } = useNavbarPosition()

View File

@ -3,7 +3,6 @@ import { isMac } from '@renderer/config/constant'
import { DEFAULT_SIDEBAR_ICONS } from '@renderer/config/sidebar'
import {
ApiServerConfig,
AssistantsSortType,
CodeStyleVarious,
MathEngine,
OpenAIServiceTier,
@ -17,6 +16,7 @@ import { uuid } from '@renderer/utils'
import { UpgradeChannel } from '@shared/config/constant'
import { TRANSLATE_PROMPT } from '@shared/config/prompts'
import type { SendMessageShortcut } from '@shared/data/preferenceTypes'
import type { AssistantTabSortType } from '@shared/data/preferenceTypes'
import { LanguageVarious, ThemeMode } from '@shared/data/preferenceTypes'
import { OpenAIVerbosity } from '@types'
@ -38,7 +38,7 @@ export type UserTheme = {
export interface SettingsState {
showAssistants: boolean
showTopics: boolean
assistantsTabSortType: AssistantsSortType
assistantsTabSortType: AssistantTabSortType
sendMessageShortcut: SendMessageShortcut
language: LanguageVarious
targetLanguage: TranslateLanguageCode
@ -432,7 +432,7 @@ const settingsSlice = createSlice({
toggleShowTopics: (state) => {
state.showTopics = !state.showTopics
},
setAssistantsTabSortType: (state, action: PayloadAction<AssistantsSortType>) => {
setAssistantsTabSortType: (state, action: PayloadAction<AssistantTabSortType>) => {
state.assistantsTabSortType = action.payload
},
setSendMessageShortcut: (state, action: PayloadAction<SendMessageShortcut>) => {
@ -861,10 +861,10 @@ const settingsSlice = createSlice({
export const {
setShowModelNameInMarkdown,
setShowModelProviderInMarkdown,
setShowAssistants,
toggleShowAssistants,
setShowTopics,
toggleShowTopics,
// setShowAssistants,
// toggleShowAssistants,
// setShowTopics,
// toggleShowTopics,
setAssistantsTabSortType,
setSendMessageShortcut,
setLanguage,

View File

@ -53,7 +53,7 @@ export const isTranslateAssistant = (assistant: Assistant): assistant is Transla
return (assistant.model && assistant.targetLanguage && typeof assistant.content === 'string') !== undefined
}
export type AssistantsSortType = 'tags' | 'list'
// export type AssistantsSortType = 'tags' | 'list'
export type AssistantMessage = {
role: 'user' | 'assistant'

View File

@ -49,7 +49,7 @@ const TestApp: React.FC = () => {
const windowNumber = getWindowNumber()
// Add theme preference monitoring for UI changes
const [theme, setTheme] = usePreference('app.theme.mode')
const [theme, setTheme] = usePreference('ui.theme_mode')
const [language] = usePreference('app.language')
const [zoomFactor] = usePreference('app.zoom_factor')

View File

@ -12,7 +12,7 @@ const { Option } = Select
* Tests single preference management with React hooks
*/
const PreferenceBasicTests: React.FC = () => {
const [selectedKey, setSelectedKey] = useState<PreferenceKeyType>('app.theme.mode')
const [selectedKey, setSelectedKey] = useState<PreferenceKeyType>('ui.theme_mode')
// Use the hook with the selected key
const [value, setValue] = usePreference(selectedKey)
@ -20,7 +20,7 @@ const PreferenceBasicTests: React.FC = () => {
const [inputValue, setInputValue] = useState<string>('')
// Add theme monitoring for visual changes
const [currentTheme] = usePreference('app.theme.mode')
const [currentTheme] = usePreference('ui.theme_mode')
const isDarkTheme = currentTheme === ThemeMode.dark
const handleSetValue = async () => {
@ -51,7 +51,7 @@ const PreferenceBasicTests: React.FC = () => {
}
const testCases = [
{ key: 'app.theme.mode', label: 'App Theme Mode', sampleValue: 'ThemeMode.dark', type: 'enum' },
{ key: 'ui.theme_mode', label: 'App Theme Mode', sampleValue: 'ThemeMode.dark', type: 'enum' },
{ key: 'app.language', label: 'App Language', sampleValue: 'zh-CN', type: 'enum' },
{ key: 'app.spell_check.enabled', label: 'Spell Check', sampleValue: 'true', type: 'boolean' },
{ key: 'app.zoom_factor', label: 'Zoom Factor', sampleValue: '1.2', type: 'number', min: 0.5, max: 2.0, step: 0.1 },
@ -132,7 +132,7 @@ const PreferenceBasicTests: React.FC = () => {
<Text strong>:</Text>
<Space wrap style={{ marginTop: 8 }}>
{/* Theme Toggle with Visual Feedback */}
{selectedKey === 'app.theme.mode' && (
{selectedKey === 'ui.theme_mode' && (
<Button
size="small"
type={isDarkTheme ? 'default' : 'primary'}

View File

@ -18,13 +18,13 @@ const PreferenceHookTests: React.FC = () => {
const [subscriptionCount, setSubscriptionCount] = useState(0)
// Test multiple hooks with same key
const [theme1] = usePreference('app.theme.mode')
const [theme2] = usePreference('app.theme.mode')
const [theme1] = usePreference('ui.theme_mode')
const [theme2] = usePreference('ui.theme_mode')
const [language] = usePreference('app.language')
// Manual preload implementation using useEffect
React.useEffect(() => {
const preloadKeys: PreferenceKeyType[] = ['app.theme.mode', 'app.language', 'app.zoom_factor']
const preloadKeys: PreferenceKeyType[] = ['ui.theme_mode', 'app.language', 'app.zoom_factor']
preferenceService.preload(preloadKeys).catch((error) => {
logger.error('Failed to preload preferences:', error as Error)
})
@ -36,7 +36,7 @@ const PreferenceHookTests: React.FC = () => {
const testSubscriptions = () => {
// Test subscription behavior
const unsubscribe = preferenceService.subscribeChange('app.theme.mode')(() => {
const unsubscribe = preferenceService.subscribeChange('ui.theme_mode')(() => {
setSubscriptionCount((prev) => prev + 1)
})
@ -51,7 +51,7 @@ const PreferenceHookTests: React.FC = () => {
const testCacheWarming = async () => {
try {
const keys: PreferenceKeyType[] = ['app.theme.mode', 'app.language', 'app.zoom_factor', 'app.spell_check.enabled']
const keys: PreferenceKeyType[] = ['ui.theme_mode', 'app.language', 'app.zoom_factor', 'app.spell_check.enabled']
await preferenceService.preload(keys)
const cachedStates = keys.map((key) => ({
@ -69,7 +69,7 @@ const PreferenceHookTests: React.FC = () => {
const testBatchOperations = async () => {
try {
const keys: PreferenceKeyType[] = ['app.theme.mode', 'app.language']
const keys: PreferenceKeyType[] = ['ui.theme_mode', 'app.language']
const result = await preferenceService.getMultiple(keys)
message.success(`批量获取成功: ${Object.keys(result).length}`)
@ -77,7 +77,7 @@ const PreferenceHookTests: React.FC = () => {
// Test batch set
await preferenceService.setMultiple({
'app.theme.mode': theme1 === ThemeMode.dark ? ThemeMode.light : ThemeMode.dark,
'ui.theme_mode': theme1 === ThemeMode.dark ? ThemeMode.light : ThemeMode.dark,
'app.language': language === 'zh-CN' ? 'en-US' : 'zh-CN'
})
@ -94,7 +94,7 @@ const PreferenceHookTests: React.FC = () => {
try {
// Test rapid reads
for (let i = 0; i < iterations; i++) {
preferenceService.getCachedValue('app.theme.mode')
preferenceService.getCachedValue('ui.theme_mode')
}
const readTime = performance.now() - start
@ -103,7 +103,7 @@ const PreferenceHookTests: React.FC = () => {
const writeStart = performance.now()
for (let i = 0; i < 10; i++) {
await preferenceService.set(
'app.theme.mode',
'ui.theme_mode',
i % 3 === 0 ? ThemeMode.light : i % 3 === 1 ? ThemeMode.dark : ThemeMode.system
)
}
@ -158,7 +158,7 @@ const PreferenceHookTests: React.FC = () => {
<Text>
Service实例: <Text code>{preferenceService ? '已连接' : '未连接'}</Text>
</Text>
<Text>预加载Keys: app.theme.mode, app.language, app.zoom_factor</Text>
<Text>预加载Keys: ui.theme_mode, app.language, app.zoom_factor</Text>
<Text type="secondary" style={{ fontSize: '12px' }}>
usePreferenceService()
</Text>
@ -169,7 +169,7 @@ const PreferenceHookTests: React.FC = () => {
<Card size="small" title="Hook 行为测试">
<Space direction="vertical" size="small" style={{ width: '100%' }}>
<Text strong>:</Text>
<Text type="secondary">1. app.theme.mode app.language</Text>
<Text type="secondary">1. ui.theme_mode app.language</Text>
<Text type="secondary">2. </Text>
<Text type="secondary">3. </Text>
</Space>

View File

@ -17,12 +17,12 @@ const PreferenceMultipleTests: React.FC = () => {
const scenarios = {
basic: {
theme: 'app.theme.mode',
theme: 'ui.theme_mode',
language: 'app.language',
zoom: 'app.zoom_factor'
},
ui: {
theme: 'app.theme.mode',
theme: 'ui.theme_mode',
zoom: 'app.zoom_factor',
spell: 'app.spell_check.enabled'
},
@ -37,7 +37,7 @@ const PreferenceMultipleTests: React.FC = () => {
opacity: 'feature.selection.action_window_opacity'
},
custom: {
key1: 'app.theme.mode',
key1: 'ui.theme_mode',
key2: 'app.language',
key3: 'app.zoom_factor',
key4: 'app.spell_check.enabled'
@ -79,7 +79,7 @@ const PreferenceMultipleTests: React.FC = () => {
const prefKey = currentKeys[localKey as keyof typeof currentKeys]
switch (prefKey) {
case 'app.theme.mode':
case 'ui.theme_mode':
sampleUpdates[localKey] = values[localKey] === 'ThemeMode.dark' ? 'ThemeMode.light' : 'ThemeMode.dark'
break
case 'app.language':
@ -150,7 +150,7 @@ const PreferenceMultipleTests: React.FC = () => {
width: 150,
render: (_, record) => (
<Space size="small">
{record.prefKey === 'app.theme.mode' && (
{record.prefKey === 'ui.theme_mode' && (
<Button
size="small"
onClick={() =>
@ -339,7 +339,7 @@ const PreferenceMultipleTests: React.FC = () => {
onClick={async () => {
const toggles: Record<string, any> = {}
Object.entries(currentKeys).forEach(([localKey, prefKey]) => {
if (prefKey === 'app.theme.mode') {
if (prefKey === 'ui.theme_mode') {
toggles[localKey] = values[localKey] === 'ThemeMode.dark' ? 'ThemeMode.light' : 'ThemeMode.dark'
} else if (prefKey === 'app.spell_check.enabled') {
toggles[localKey] = !values[localKey]

View File

@ -12,13 +12,13 @@ const { Text } = Typography
* Tests the service layer functionality without React hooks
*/
const PreferenceServiceTests: React.FC = () => {
const [testKey, setTestKey] = useState<string>('app.theme.mode')
const [testKey, setTestKey] = useState<string>('ui.theme_mode')
const [testValue, setTestValue] = useState<string>(ThemeMode.dark)
const [getResult, setGetResult] = useState<any>(null)
const [loading, setLoading] = useState(false)
// Theme monitoring for visual changes
const [currentTheme] = usePreference('app.theme.mode')
const [currentTheme] = usePreference('ui.theme_mode')
const isDarkTheme = currentTheme === ThemeMode.dark
const handleGet = async () => {
@ -173,10 +173,10 @@ const PreferenceServiceTests: React.FC = () => {
<Button
size="small"
onClick={() => {
setTestKey('app.theme.mode')
setTestKey('ui.theme_mode')
setTestValue(ThemeMode.dark)
}}>
Test: app.theme.mode
Test: ui.theme_mode
</Button>
<Button
size="small"

View File

@ -40,7 +40,7 @@ const logger = loggerService.withContext('HomeWindow')
const HomeWindow: FC<{ draggable?: boolean }> = ({ draggable = true }) => {
const [readClipboardAtStartup] = usePreference('feature.quick_assistant.read_clipboard_at_startup')
const [language] = usePreference('app.language')
const [windowStyle] = usePreference('app.theme.window_style')
const [windowStyle] = usePreference('ui.window_style')
const { theme } = useTheme()
const { t } = useTranslation()

View File

@ -22,8 +22,8 @@ loggerService.initWindowSource('SelectionActionWindow')
await preferenceService.preload([
'app.language',
'ui.custom_css',
'app.theme.mode',
'app.theme.user.color_primary',
'ui.theme_mode',
'ui.theme_user.color_primary',
'feature.selection.auto_close',
'feature.selection.auto_pin',
'feature.selection.action_window_opacity'

View File

@ -12,8 +12,8 @@ loggerService.initWindowSource('SelectionToolbar')
await preferenceService.preload([
'app.language',
'ui.custom_css',
'app.theme.mode',
'app.theme.user.color_primary',
'ui.theme_mode',
'ui.theme_user.color_primary',
'feature.selection.compact',
'feature.selection.action_items'
])