refactor: enhance preference management and update mappings

- Updated preferences to utilize the new SendMessageShortcut type for better type safety.
- Refactored components to use the usePreference hook instead of useSettings for improved preference handling.
- Added new preferences for target language and send message shortcut in various components.
- Cleaned up unused code and comments related to settings for better maintainability.
- Updated auto-generated preference mappings to reflect recent changes in preference structure.
This commit is contained in:
fullex 2025-09-02 13:24:41 +08:00
parent 5cc7390bb6
commit 0a67ab4103
16 changed files with 184 additions and 139 deletions

View File

@ -38,3 +38,5 @@ export enum ThemeMode {
export type LanguageVarious = 'zh-CN' | 'zh-TW' | 'el-GR' | 'en-US' | 'es-ES' | 'fr-FR' | 'ja-JP' | 'pt-PT' | 'ru-RU'
export type WindowStyle = 'transparent' | 'opaque'
export type SendMessageShortcut = 'Enter' | 'Shift+Enter' | 'Ctrl+Enter' | 'Command+Enter' | 'Alt+Enter'

View File

@ -1,6 +1,6 @@
/**
* Auto-generated preferences configuration
* Generated at: 2025-09-02T02:45:09.198Z
* Generated at: 2025-09-02T04:48:55.916Z
*
* This file is automatically generated from classification.json
* To update this file, modify classification.json and run:
@ -14,6 +14,7 @@ import type {
SelectionActionItem,
SelectionFilterMode,
SelectionTriggerMode,
SendMessageShortcut,
WindowStyle
} from '@shared/data/preferenceTypes'
import { LanguageVarious, ThemeMode } from '@shared/data/preferenceTypes'
@ -116,7 +117,7 @@ export interface PreferencesType {
// redux/settings/enableQuickPanelTriggers
'chat.input.quick_panel.triggers_enabled': boolean
// redux/settings/sendMessageShortcut
'chat.input.send_message_shortcut': string
'chat.input.send_message_shortcut': SendMessageShortcut
// redux/settings/showInputEstimatedTokens
'chat.input.show_estimated_tokens': boolean
// redux/settings/autoTranslateWithSpace
@ -143,8 +144,6 @@ export interface PreferencesType {
'chat.message.show_divider': boolean
// redux/settings/showPrompt
'chat.message.show_prompt': boolean
// redux/settings/showTokens
'chat.message.show_tokens': boolean
// redux/settings/messageStyle
'chat.message.style': string
// redux/settings/thoughtAutoCollapse
@ -321,6 +320,8 @@ export interface PreferencesType {
'feature.selection.trigger_mode': SelectionTriggerMode
// redux/settings/translateModelPrompt
'feature.translate.model_prompt': string
// redux/settings/targetLanguage
'feature.translate.target_language': string
// redux/shortcuts/shortcuts.exit_fullscreen
'shortcut.app.exit_fullscreen': Record<string, unknown>
// redux/shortcuts/shortcuts.search_message
@ -436,7 +437,6 @@ export const DefaultPreferences: PreferencesType = {
'chat.message.navigation_mode': 'none',
'chat.message.show_divider': true,
'chat.message.show_prompt': true,
'chat.message.show_tokens': true,
'chat.message.style': 'plain',
'chat.message.thought.auto_collapse': true,
'chat.narrow_mode': false,
@ -552,6 +552,7 @@ export const DefaultPreferences: PreferencesType = {
'feature.selection.remember_win_size': false,
'feature.selection.trigger_mode': 'selected',
'feature.translate.model_prompt': TRANSLATE_PROMPT,
'feature.translate.target_language': 'en-us',
'shortcut.app.exit_fullscreen': { editable: false, enabled: true, key: ['Escape'], system: true },
'shortcut.app.search_message': {
editable: true,

View File

@ -1,6 +1,6 @@
/**
* Auto-generated preference mappings from classification.json
* Generated at: 2025-09-01T14:38:08.063Z
* Generated at: 2025-09-02T05:21:08.374Z
*
* This file contains pure mapping relationships without default values.
* Default values are managed in packages/shared/data/preferences.ts
@ -14,10 +14,6 @@
* ElectronStore没有嵌套originalKey直接对应configManager.get(key)
*/
export const ELECTRON_STORE_MAPPINGS = [
{
originalKey: 'Language',
targetKey: 'app.language'
},
{
originalKey: 'ZoomFactor',
targetKey: 'app.zoom_factor'
@ -58,6 +54,10 @@ export const REDUX_STORE_MAPPINGS = {
originalKey: 'enableQuickAssistant',
targetKey: 'feature.quick_assistant.enabled'
},
{
originalKey: 'language',
targetKey: 'app.language'
},
{
originalKey: 'launchToTray',
targetKey: 'app.tray.on_launch'
@ -86,6 +86,10 @@ export const REDUX_STORE_MAPPINGS = {
originalKey: 'sendMessageShortcut',
targetKey: 'chat.input.send_message_shortcut'
},
{
originalKey: 'targetLanguage',
targetKey: 'feature.translate.target_language'
},
{
originalKey: 'proxyMode',
targetKey: 'app.proxy.mode'
@ -110,10 +114,6 @@ export const REDUX_STORE_MAPPINGS = {
originalKey: 'showPrompt',
targetKey: 'chat.message.show_prompt'
},
{
originalKey: 'showTokens',
targetKey: 'chat.message.show_tokens'
},
{
originalKey: 'showMessageDivider',
targetKey: 'chat.message.show_divider'
@ -180,7 +180,7 @@ export const REDUX_STORE_MAPPINGS = {
},
{
originalKey: 'codeEditor.enabled',
targetKey: 'chat.code.editor.highlight_active_line'
targetKey: 'chat.code.editor.enabled'
},
{
originalKey: 'codeEditor.themeLight',
@ -190,6 +190,10 @@ export const REDUX_STORE_MAPPINGS = {
originalKey: 'codeEditor.themeDark',
targetKey: 'chat.code.editor.theme_dark'
},
{
originalKey: 'codeEditor.highlightActiveLine',
targetKey: 'chat.code.editor.highlight_active_line'
},
{
originalKey: 'codeEditor.foldGutter',
targetKey: 'chat.code.editor.fold_gutter'
@ -298,6 +302,10 @@ export const REDUX_STORE_MAPPINGS = {
originalKey: 'webdavDisableStream',
targetKey: 'data.backup.webdav.disable_stream'
},
{
originalKey: 'translateModelPrompt',
targetKey: 'feature.translate.model_prompt'
},
{
originalKey: 'autoTranslateWithSpace',
targetKey: 'chat.input.translate.auto_translate_with_space'
@ -723,10 +731,10 @@ export const REDUX_STORE_MAPPINGS = {
/**
* :
* - ElectronStore项: 2
* - Redux Store项: 169
* - ElectronStore项: 1
* - Redux Store项: 172
* - Redux分类: settings, selectionStore, nutstore, shortcuts
* - 总配置项: 171
* - 总配置项: 173
*
* 使:
* 1. ElectronStore读取: configManager.get(mapping.originalKey)

View File

@ -1,3 +1,4 @@
import { usePreference } from '@data/hooks/usePreference'
import { loggerService } from '@logger'
import { ActionTool } from '@renderer/components/ActionTools'
import CodeEditor, { CodeEditorHandles } from '@renderer/components/CodeEditor'
@ -16,7 +17,6 @@ import CodeViewer from '@renderer/components/CodeViewer'
import ImageViewer from '@renderer/components/ImageViewer'
import { BasicPreviewHandles } from '@renderer/components/Preview'
import { MAX_COLLAPSED_CODE_HEIGHT } from '@renderer/config/constant'
import { useSettings } from '@renderer/hooks/useSettings'
import { pyodideService } from '@renderer/services/PyodideService'
import { getExtensionByLanguage } from '@renderer/utils/code-language'
import { extractHtmlTitle } from '@renderer/utils/formats'
@ -28,7 +28,6 @@ import styled, { css } from 'styled-components'
import { SPECIAL_VIEW_COMPONENTS, SPECIAL_VIEWS } from './constants'
import StatusBar from './StatusBar'
import { ViewMode } from './types'
const logger = loggerService.withContext('CodeBlockView')
interface Props {
@ -55,7 +54,13 @@ interface Props {
*/
export const CodeBlockView: React.FC<Props> = memo(({ children, language, onSave }) => {
const { t } = useTranslation()
const { codeEditor, codeExecution, codeImageTools, codeCollapsible, codeWrappable } = useSettings()
const [codeEditorEnabled] = usePreference('chat.code.editor.enabled')
const [codeExecutionEnabled] = usePreference('chat.code.execution.enabled')
const [codeExecutionTimeoutMinutes] = usePreference('chat.code.execution.timeout_minutes')
const [codeCollapsible] = usePreference('chat.code.collapsible')
const [codeWrappable] = usePreference('chat.code.wrappable')
const [codeImageTools] = usePreference('chat.code.image_tools')
const [viewState, setViewState] = useState({
mode: 'special' as ViewMode,
@ -87,8 +92,8 @@ export const CodeBlockView: React.FC<Props> = memo(({ children, language, onSave
const [tools, setTools] = useState<ActionTool[]>([])
const isExecutable = useMemo(() => {
return codeExecution.enabled && language === 'python'
}, [codeExecution.enabled, language])
return codeExecutionEnabled && language === 'python'
}, [codeExecutionEnabled, language])
const sourceViewRef = useRef<CodeEditorHandles>(null)
const specialViewRef = useRef<BasicPreviewHandles>(null)
@ -153,7 +158,7 @@ export const CodeBlockView: React.FC<Props> = memo(({ children, language, onSave
setExecutionResult(null)
pyodideService
.runScript(children, {}, codeExecution.timeoutMinutes * 60000)
.runScript(children, {}, codeExecutionTimeoutMinutes * 60000)
.then((result) => {
setExecutionResult(result)
})
@ -166,7 +171,7 @@ export const CodeBlockView: React.FC<Props> = memo(({ children, language, onSave
.finally(() => {
setIsRunning(false)
})
}, [children, codeExecution.timeoutMinutes])
}, [children, codeExecutionTimeoutMinutes])
const showPreviewTools = useMemo(() => {
return viewMode !== 'source' && hasSpecialView
@ -191,7 +196,7 @@ export const CodeBlockView: React.FC<Props> = memo(({ children, language, onSave
// 特殊视图的编辑/查看源码按钮,在分屏模式下不可用
useViewSourceTool({
enabled: hasSpecialView,
editable: codeEditor.enabled,
editable: codeEditorEnabled,
viewMode,
onViewModeChange: setViewMode,
setTools
@ -233,7 +238,7 @@ export const CodeBlockView: React.FC<Props> = memo(({ children, language, onSave
// 代码编辑器的保存按钮
useSaveTool({
enabled: codeEditor.enabled && !isInSpecialView,
enabled: codeEditorEnabled && !isInSpecialView,
sourceViewRef,
setTools
})
@ -241,7 +246,7 @@ export const CodeBlockView: React.FC<Props> = memo(({ children, language, onSave
// 源代码视图组件
const sourceView = useMemo(
() =>
codeEditor.enabled ? (
codeEditorEnabled ? (
<CodeEditor
className="source-view"
ref={sourceViewRef}
@ -264,7 +269,7 @@ export const CodeBlockView: React.FC<Props> = memo(({ children, language, onSave
{children}
</CodeViewer>
),
[children, codeEditor.enabled, handleHeightChange, language, onSave, shouldExpand, shouldWrap]
[children, codeEditorEnabled, handleHeightChange, language, onSave, shouldExpand, shouldWrap]
)
// 特殊视图组件映射

View File

@ -1,5 +1,5 @@
import { useMultiplePreferences, usePreference } from '@data/hooks/usePreference'
import { useCodeStyle } from '@renderer/context/CodeStyleProvider'
import { useSettings } from '@renderer/hooks/useSettings'
import CodeMirror, { Annotation, BasicSetupOptions, EditorView, Extension } from '@uiw/react-codemirror'
import diff from 'fast-diff'
import { useCallback, useEffect, useImperativeHandle, useMemo, useRef } from 'react'
@ -117,7 +117,17 @@ const CodeEditor = ({
expanded = true,
wrapped = true
}: CodeEditorProps) => {
const { fontSize: _fontSize, codeShowLineNumbers: _lineNumbers, codeEditor } = useSettings()
const [_fontSize] = usePreference('chat.message.font_size')
const [_lineNumbers] = usePreference('chat.code.show_line_numbers')
const [codeEditor] = useMultiplePreferences({
autocompletion: 'chat.code.editor.autocompletion',
foldGutter: 'chat.code.editor.fold_gutter',
highlightActiveLine: 'chat.code.editor.highlight_active_line',
keymap: 'chat.code.editor.keymap',
themeLight: 'chat.code.editor.theme_light',
themeDark: 'chat.code.editor.theme_dark'
})
const enableKeymap = useMemo(() => options?.keymap ?? codeEditor.keymap, [options?.keymap, codeEditor.keymap])
// 合并 codeEditor 和 options 的 basicSetupoptions 优先

View File

@ -1,7 +1,7 @@
import { usePreference } from '@data/hooks/usePreference'
import { MAX_COLLAPSED_CODE_HEIGHT } from '@renderer/config/constant'
import { useCodeStyle } from '@renderer/context/CodeStyleProvider'
import { useCodeHighlight } from '@renderer/hooks/useCodeHighlight'
import { useSettings } from '@renderer/hooks/useSettings'
import { uuid } from '@renderer/utils'
import { getReactStyleFromToken } from '@renderer/utils/shiki'
import { useVirtualizer } from '@tanstack/react-virtual'
@ -27,7 +27,8 @@ interface CodeViewerProps {
* -
*/
const CodeViewer = ({ children, language, expanded, wrapped, onHeightChange, className, height }: CodeViewerProps) => {
const { codeShowLineNumbers, fontSize } = useSettings()
const [codeShowLineNumbers] = usePreference('chat.code.show_line_numbers')
const [fontSize] = usePreference('chat.message.font_size')
const { getShikiPreProperties, isShikiThemeDark } = useCodeStyle()
const shikiThemeRef = useRef<HTMLDivElement>(null)
const scrollerRef = useRef<HTMLDivElement>(null)

View File

@ -1,6 +1,6 @@
import { LoadingOutlined } from '@ant-design/icons'
import { usePreference } from '@data/hooks/usePreference'
import { loggerService } from '@logger'
import { useSettings } from '@renderer/hooks/useSettings'
import useTranslate from '@renderer/hooks/useTranslate'
import { translateText } from '@renderer/services/TranslateService'
import { Modal, ModalProps } from 'antd'
@ -42,7 +42,8 @@ const PopupContainer: React.FC<Props> = ({
const [textValue, setTextValue] = useState(text)
const [isTranslating, setIsTranslating] = useState(false)
const textareaRef = useRef<TextAreaRef>(null)
const { targetLanguage, showTranslateConfirm } = useSettings()
const [targetLanguage] = usePreference('feature.translate.target_language')
const [showTranslateConfirm] = usePreference('chat.input.translate.show_confirm')
const isMounted = useRef(true)
useEffect(() => {

View File

@ -1,6 +1,6 @@
import { LoadingOutlined } from '@ant-design/icons'
import { usePreference } from '@data/hooks/usePreference'
import { loggerService } from '@logger'
import { useSettings } from '@renderer/hooks/useSettings'
import useTranslate from '@renderer/hooks/useTranslate'
import { translateText } from '@renderer/services/TranslateService'
import { Button, Tooltip } from 'antd'
@ -22,7 +22,8 @@ const logger = loggerService.withContext('TranslateButton')
const TranslateButton: FC<Props> = ({ text, onTranslated, disabled, style, isLoading }) => {
const { t } = useTranslation()
const [isTranslating, setIsTranslating] = useState(false)
const { targetLanguage, showTranslateConfirm } = useSettings()
const [targetLanguage] = usePreference('feature.translate.target_language')
const [showTranslateConfirm] = usePreference('chat.input.translate.show_confirm')
const { getLanguageByLangcode } = useTranslate()
const translateConfirm = () => {

View File

@ -30,13 +30,14 @@ export function useAppInit() {
const {
proxyUrl,
proxyBypassRules,
language,
// language,
// windowStyle,
autoCheckUpdate,
proxyMode,
// customCss,
enableDataCollection
} = useSettings()
const [language] = usePreference('app.language')
const [windowStyle] = usePreference('app.theme.window_style')
const [customCss] = usePreference('ui.custom_css')

View File

@ -1,7 +1,6 @@
import store, { useAppDispatch, useAppSelector } from '@renderer/store'
import {
AssistantIconType,
SendMessageShortcut,
setAssistantIconType,
setAutoCheckUpdate as _setAutoCheckUpdate,
// setDisableHardwareAcceleration,
@ -22,6 +21,7 @@ import {
} from '@renderer/store/settings'
import { SidebarIcon, TranslateLanguageCode } from '@renderer/types'
import { UpgradeChannel } from '@shared/config/constant'
import type { SendMessageShortcut } from '@shared/data/preferenceTypes'
export function useSettings() {
const settings = useAppSelector((state) => state.settings)

View File

@ -1,4 +1,5 @@
import { HolderOutlined } from '@ant-design/icons'
import { usePreference } from '@data/hooks/usePreference'
import { loggerService } from '@logger'
import { QuickPanelView, useQuickPanel } from '@renderer/components/QuickPanel'
import TranslateButton from '@renderer/components/TranslateButton'
@ -18,7 +19,6 @@ import { useAssistant } from '@renderer/hooks/useAssistant'
import { useKnowledgeBases } from '@renderer/hooks/useKnowledge'
import { useMessageOperations, useTopicLoading } from '@renderer/hooks/useMessageOperations'
import { modelGenerating, useRuntime } from '@renderer/hooks/useRuntime'
import { useSettings } from '@renderer/hooks/useSettings'
import { useShortcut, useShortcutDisplay } from '@renderer/hooks/useShortcuts'
import { useSidebarIconShow } from '@renderer/hooks/useSidebarIcon'
import { useTimer } from '@renderer/hooks/useTimer'
@ -75,20 +75,20 @@ let _text = ''
let _files: FileType[] = []
const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) => {
const [targetLanguage] = usePreference('feature.translate.target_language')
const [sendMessageShortcut] = usePreference('chat.input.send_message_shortcut')
const [pasteLongTextAsFile] = usePreference('chat.input.paste_long_text_as_file')
const [pasteLongTextThreshold] = usePreference('chat.input.paste_long_text_threshold')
const [showInputEstimatedTokens] = usePreference('chat.input.show_estimated_tokens')
const [autoTranslateWithSpace] = usePreference('chat.input.translate.auto_translate_with_space')
const [enableQuickPanelTriggers] = usePreference('chat.input.quick_panel.triggers_enabled')
const [enableSpellCheck] = usePreference('app.spell_check.enabled')
const [fontSize] = usePreference('chat.message.font_size')
const [text, setText] = useState(_text)
const [inputFocus, setInputFocus] = useState(false)
const { assistant, addTopic, model, setModel, updateAssistant } = useAssistant(_assistant.id)
const {
targetLanguage,
sendMessageShortcut,
fontSize,
pasteLongTextAsFile,
pasteLongTextThreshold,
showInputEstimatedTokens,
autoTranslateWithSpace,
enableQuickPanelTriggers,
enableSpellCheck
} = useSettings()
const [expanded, setExpand] = useState(false)
const [estimateTokenCount, setEstimateTokenCount] = useState(0)
const [contextCount, setContextCount] = useState({ current: 0, max: 0 })

View File

@ -17,7 +17,6 @@ import { CollapsibleSettingGroup } from '@renderer/pages/settings/SettingGroup'
import { getDefaultModel } from '@renderer/services/AssistantService'
import { useAppDispatch } from '@renderer/store'
import {
SendMessageShortcut,
setAutoTranslateWithSpace,
setCodeCollapsible,
setCodeEditor,
@ -48,6 +47,7 @@ import {
import { Assistant, AssistantSettings, CodeStyleVarious, MathEngine } from '@renderer/types'
import { modalConfirm } from '@renderer/utils'
import { getSendMessageShortcutLabel } from '@renderer/utils/input'
import type { SendMessageShortcut } from '@shared/data/preferenceTypes'
import { ThemeMode } from '@shared/data/preferenceTypes'
import { Button, Col, InputNumber, Row, Slider, Switch, Tooltip } from 'antd'
import { CircleHelp, Settings2 } from 'lucide-react'

View File

@ -1,89 +1,103 @@
// import { createSlice, PayloadAction } from '@reduxjs/toolkit'
// import { SelectionActionItem, FilterMode, SelectionState, TriggerMode } from '@shared/data/preferenceTypes'
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import type { SelectionActionItem, SelectionFilterMode, SelectionTriggerMode } from '@shared/data/preferenceTypes'
// export const defaultActionItems: ActionItem[] = [
// { id: 'translate', name: 'selection.action.builtin.translate', enabled: true, isBuiltIn: true, icon: 'languages' },
// { id: 'explain', name: 'selection.action.builtin.explain', enabled: true, isBuiltIn: true, icon: 'file-question' },
// { id: 'summary', name: 'selection.action.builtin.summary', enabled: true, isBuiltIn: true, icon: 'scan-text' },
// {
// id: 'search',
// name: 'selection.action.builtin.search',
// enabled: true,
// isBuiltIn: true,
// icon: 'search',
// searchEngine: 'Google|https://www.google.com/search?q={{queryString}}'
// },
// { id: 'copy', name: 'selection.action.builtin.copy', enabled: true, isBuiltIn: true, icon: 'clipboard-copy' },
// { id: 'refine', name: 'selection.action.builtin.refine', enabled: false, isBuiltIn: true, icon: 'wand-sparkles' },
// { id: 'quote', name: 'selection.action.builtin.quote', enabled: false, isBuiltIn: true, icon: 'quote' }
// ]
interface SelectionState {
selectionEnabled: boolean
triggerMode: SelectionTriggerMode
isCompact: boolean
isAutoClose: boolean
isAutoPin: boolean
isFollowToolbar: boolean
isRemeberWinSize: boolean
filterMode: SelectionFilterMode
filterList: string[]
actionWindowOpacity: number
actionItems: SelectionActionItem[]
}
// export const initialState: SelectionState = {
// selectionEnabled: false,
// triggerMode: 'selected',
// isCompact: false,
// isAutoClose: false,
// isAutoPin: false,
// isFollowToolbar: true,
// isRemeberWinSize: false,
// filterMode: 'default',
// filterList: [],
// actionWindowOpacity: 100,
// actionItems: defaultActionItems
// }
export const defaultActionItems: SelectionActionItem[] = [
{ id: 'translate', name: 'selection.action.builtin.translate', enabled: true, isBuiltIn: true, icon: 'languages' },
{ id: 'explain', name: 'selection.action.builtin.explain', enabled: true, isBuiltIn: true, icon: 'file-question' },
{ id: 'summary', name: 'selection.action.builtin.summary', enabled: true, isBuiltIn: true, icon: 'scan-text' },
{
id: 'search',
name: 'selection.action.builtin.search',
enabled: true,
isBuiltIn: true,
icon: 'search',
searchEngine: 'Google|https://www.google.com/search?q={{queryString}}'
},
{ id: 'copy', name: 'selection.action.builtin.copy', enabled: true, isBuiltIn: true, icon: 'clipboard-copy' },
{ id: 'refine', name: 'selection.action.builtin.refine', enabled: false, isBuiltIn: true, icon: 'wand-sparkles' },
{ id: 'quote', name: 'selection.action.builtin.quote', enabled: false, isBuiltIn: true, icon: 'quote' }
]
// const selectionSlice = createSlice({
// name: 'selectionStore',
// initialState,
// reducers: {
// setSelectionEnabled: (state, action: PayloadAction<boolean>) => {
// state.selectionEnabled = action.payload
// },
// setTriggerMode: (state, action: PayloadAction<TriggerMode>) => {
// state.triggerMode = action.payload
// },
// setIsCompact: (state, action: PayloadAction<boolean>) => {
// state.isCompact = action.payload
// },
// setIsAutoClose: (state, action: PayloadAction<boolean>) => {
// state.isAutoClose = action.payload
// },
// setIsAutoPin: (state, action: PayloadAction<boolean>) => {
// state.isAutoPin = action.payload
// },
// setIsFollowToolbar: (state, action: PayloadAction<boolean>) => {
// state.isFollowToolbar = action.payload
// },
// setIsRemeberWinSize: (state, action: PayloadAction<boolean>) => {
// state.isRemeberWinSize = action.payload
// },
// setFilterMode: (state, action: PayloadAction<FilterMode>) => {
// state.filterMode = action.payload
// },
// setFilterList: (state, action: PayloadAction<string[]>) => {
// state.filterList = action.payload
// },
// setActionWindowOpacity: (state, action: PayloadAction<number>) => {
// state.actionWindowOpacity = action.payload
// },
// setActionItems: (state, action: PayloadAction<ActionItem[]>) => {
// state.actionItems = action.payload
// }
// }
// })
export const initialState: SelectionState = {
selectionEnabled: false,
triggerMode: 'selected',
isCompact: false,
isAutoClose: false,
isAutoPin: false,
isFollowToolbar: true,
isRemeberWinSize: false,
filterMode: 'default',
filterList: [],
actionWindowOpacity: 100,
actionItems: defaultActionItems
}
// export const {
// setSelectionEnabled,
// setTriggerMode,
// setIsCompact,
// setIsAutoClose,
// setIsAutoPin,
// setIsFollowToolbar,
// setIsRemeberWinSize,
// setFilterMode,
// setFilterList,
// setActionWindowOpacity,
// setActionItems
// } = selectionSlice.actions
const selectionSlice = createSlice({
name: 'selectionStore',
initialState,
reducers: {
setSelectionEnabled: (state, action: PayloadAction<boolean>) => {
state.selectionEnabled = action.payload
},
setTriggerMode: (state, action: PayloadAction<SelectionTriggerMode>) => {
state.triggerMode = action.payload
},
setIsCompact: (state, action: PayloadAction<boolean>) => {
state.isCompact = action.payload
},
setIsAutoClose: (state, action: PayloadAction<boolean>) => {
state.isAutoClose = action.payload
},
setIsAutoPin: (state, action: PayloadAction<boolean>) => {
state.isAutoPin = action.payload
},
setIsFollowToolbar: (state, action: PayloadAction<boolean>) => {
state.isFollowToolbar = action.payload
},
setIsRemeberWinSize: (state, action: PayloadAction<boolean>) => {
state.isRemeberWinSize = action.payload
},
setFilterMode: (state, action: PayloadAction<SelectionFilterMode>) => {
state.filterMode = action.payload
},
setFilterList: (state, action: PayloadAction<string[]>) => {
state.filterList = action.payload
},
setActionWindowOpacity: (state, action: PayloadAction<number>) => {
state.actionWindowOpacity = action.payload
},
setActionItems: (state, action: PayloadAction<SelectionActionItem[]>) => {
state.actionItems = action.payload
}
}
})
// export default selectionSlice.reducer
export const {
setSelectionEnabled,
setTriggerMode,
setIsCompact,
setIsAutoClose,
setIsAutoPin,
setIsFollowToolbar,
setIsRemeberWinSize,
setFilterMode,
setFilterList,
setActionWindowOpacity,
setActionItems
} = selectionSlice.actions
export default selectionSlice.reducer

View File

@ -16,12 +16,13 @@ import {
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 { LanguageVarious, ThemeMode } from '@shared/data/preferenceTypes'
import { OpenAIVerbosity } from '@types'
import { RemoteSyncState } from './backup'
export type SendMessageShortcut = 'Enter' | 'Shift+Enter' | 'Ctrl+Enter' | 'Command+Enter' | 'Alt+Enter'
// export type SendMessageShortcut = 'Enter' | 'Shift+Enter' | 'Ctrl+Enter' | 'Command+Enter' | 'Alt+Enter'
// Re-export for backward compatibility
export { DEFAULT_SIDEBAR_ICONS }

View File

@ -1,4 +1,4 @@
import type { SendMessageShortcut } from '@renderer/store/settings'
import type { SendMessageShortcut } from '@shared/data/preferenceTypes'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { getFilesFromDropEvent, getSendMessageShortcutLabel, isSendMessageKeyPressed } from '../input'

View File

@ -1,7 +1,7 @@
import { loggerService } from '@logger'
import { isMac, isWin } from '@renderer/config/constant'
import type { SendMessageShortcut } from '@renderer/store/settings'
import { FileMetadata } from '@renderer/types'
import type { SendMessageShortcut } from '@shared/data/preferenceTypes'
const logger = loggerService.withContext('Utils:Input')