diff --git a/packages/shared/data/preferenceTypes.ts b/packages/shared/data/preferenceTypes.ts index 20df0d567e..aac3cee166 100644 --- a/packages/shared/data/preferenceTypes.ts +++ b/packages/shared/data/preferenceTypes.ts @@ -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' diff --git a/packages/shared/data/preferences.ts b/packages/shared/data/preferences.ts index 485618e650..68b3b130b7 100644 --- a/packages/shared/data/preferences.ts +++ b/packages/shared/data/preferences.ts @@ -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 // 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, diff --git a/src/main/data/migrate/dataRefactor/migrators/PreferencesMappings.ts b/src/main/data/migrate/dataRefactor/migrators/PreferencesMappings.ts index 2061b4cc07..778856d858 100644 --- a/src/main/data/migrate/dataRefactor/migrators/PreferencesMappings.ts +++ b/src/main/data/migrate/dataRefactor/migrators/PreferencesMappings.ts @@ -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) diff --git a/src/renderer/src/components/CodeBlockView/view.tsx b/src/renderer/src/components/CodeBlockView/view.tsx index 174327ae68..a9e038869a 100644 --- a/src/renderer/src/components/CodeBlockView/view.tsx +++ b/src/renderer/src/components/CodeBlockView/view.tsx @@ -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 = 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 = memo(({ children, language, onSave const [tools, setTools] = useState([]) const isExecutable = useMemo(() => { - return codeExecution.enabled && language === 'python' - }, [codeExecution.enabled, language]) + return codeExecutionEnabled && language === 'python' + }, [codeExecutionEnabled, language]) const sourceViewRef = useRef(null) const specialViewRef = useRef(null) @@ -153,7 +158,7 @@ export const CodeBlockView: React.FC = 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 = 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 = 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 = memo(({ children, language, onSave // 代码编辑器的保存按钮 useSaveTool({ - enabled: codeEditor.enabled && !isInSpecialView, + enabled: codeEditorEnabled && !isInSpecialView, sourceViewRef, setTools }) @@ -241,7 +246,7 @@ export const CodeBlockView: React.FC = memo(({ children, language, onSave // 源代码视图组件 const sourceView = useMemo( () => - codeEditor.enabled ? ( + codeEditorEnabled ? ( = memo(({ children, language, onSave {children} ), - [children, codeEditor.enabled, handleHeightChange, language, onSave, shouldExpand, shouldWrap] + [children, codeEditorEnabled, handleHeightChange, language, onSave, shouldExpand, shouldWrap] ) // 特殊视图组件映射 diff --git a/src/renderer/src/components/CodeEditor/index.tsx b/src/renderer/src/components/CodeEditor/index.tsx index 7c541cbdb8..ccd2496209 100644 --- a/src/renderer/src/components/CodeEditor/index.tsx +++ b/src/renderer/src/components/CodeEditor/index.tsx @@ -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 的 basicSetup,options 优先 diff --git a/src/renderer/src/components/CodeViewer.tsx b/src/renderer/src/components/CodeViewer.tsx index 440aed9c7c..7c634716b1 100644 --- a/src/renderer/src/components/CodeViewer.tsx +++ b/src/renderer/src/components/CodeViewer.tsx @@ -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(null) const scrollerRef = useRef(null) diff --git a/src/renderer/src/components/Popups/TextEditPopup.tsx b/src/renderer/src/components/Popups/TextEditPopup.tsx index 5fec6f3a18..65b250b865 100644 --- a/src/renderer/src/components/Popups/TextEditPopup.tsx +++ b/src/renderer/src/components/Popups/TextEditPopup.tsx @@ -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 = ({ const [textValue, setTextValue] = useState(text) const [isTranslating, setIsTranslating] = useState(false) const textareaRef = useRef(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(() => { diff --git a/src/renderer/src/components/TranslateButton.tsx b/src/renderer/src/components/TranslateButton.tsx index 6f074a079a..9aec798659 100644 --- a/src/renderer/src/components/TranslateButton.tsx +++ b/src/renderer/src/components/TranslateButton.tsx @@ -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 = ({ 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 = () => { diff --git a/src/renderer/src/hooks/useAppInit.ts b/src/renderer/src/hooks/useAppInit.ts index 7525b87e4f..5150fdc43b 100644 --- a/src/renderer/src/hooks/useAppInit.ts +++ b/src/renderer/src/hooks/useAppInit.ts @@ -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') diff --git a/src/renderer/src/hooks/useSettings.ts b/src/renderer/src/hooks/useSettings.ts index a66969a543..2a12b93f95 100644 --- a/src/renderer/src/hooks/useSettings.ts +++ b/src/renderer/src/hooks/useSettings.ts @@ -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) diff --git a/src/renderer/src/pages/home/Inputbar/Inputbar.tsx b/src/renderer/src/pages/home/Inputbar/Inputbar.tsx index 04f654ad91..b086e205e2 100644 --- a/src/renderer/src/pages/home/Inputbar/Inputbar.tsx +++ b/src/renderer/src/pages/home/Inputbar/Inputbar.tsx @@ -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 = ({ 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 }) diff --git a/src/renderer/src/pages/home/Tabs/SettingsTab.tsx b/src/renderer/src/pages/home/Tabs/SettingsTab.tsx index bbae428542..1c418f6a2c 100644 --- a/src/renderer/src/pages/home/Tabs/SettingsTab.tsx +++ b/src/renderer/src/pages/home/Tabs/SettingsTab.tsx @@ -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' diff --git a/src/renderer/src/store/selectionStore.ts b/src/renderer/src/store/selectionStore.ts index 8ef85d1409..448cb45f0a 100644 --- a/src/renderer/src/store/selectionStore.ts +++ b/src/renderer/src/store/selectionStore.ts @@ -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) => { -// state.selectionEnabled = action.payload -// }, -// setTriggerMode: (state, action: PayloadAction) => { -// state.triggerMode = action.payload -// }, -// setIsCompact: (state, action: PayloadAction) => { -// state.isCompact = action.payload -// }, -// setIsAutoClose: (state, action: PayloadAction) => { -// state.isAutoClose = action.payload -// }, -// setIsAutoPin: (state, action: PayloadAction) => { -// state.isAutoPin = action.payload -// }, -// setIsFollowToolbar: (state, action: PayloadAction) => { -// state.isFollowToolbar = action.payload -// }, -// setIsRemeberWinSize: (state, action: PayloadAction) => { -// state.isRemeberWinSize = action.payload -// }, -// setFilterMode: (state, action: PayloadAction) => { -// state.filterMode = action.payload -// }, -// setFilterList: (state, action: PayloadAction) => { -// state.filterList = action.payload -// }, -// setActionWindowOpacity: (state, action: PayloadAction) => { -// state.actionWindowOpacity = action.payload -// }, -// setActionItems: (state, action: PayloadAction) => { -// 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) => { + state.selectionEnabled = action.payload + }, + setTriggerMode: (state, action: PayloadAction) => { + state.triggerMode = action.payload + }, + setIsCompact: (state, action: PayloadAction) => { + state.isCompact = action.payload + }, + setIsAutoClose: (state, action: PayloadAction) => { + state.isAutoClose = action.payload + }, + setIsAutoPin: (state, action: PayloadAction) => { + state.isAutoPin = action.payload + }, + setIsFollowToolbar: (state, action: PayloadAction) => { + state.isFollowToolbar = action.payload + }, + setIsRemeberWinSize: (state, action: PayloadAction) => { + state.isRemeberWinSize = action.payload + }, + setFilterMode: (state, action: PayloadAction) => { + state.filterMode = action.payload + }, + setFilterList: (state, action: PayloadAction) => { + state.filterList = action.payload + }, + setActionWindowOpacity: (state, action: PayloadAction) => { + state.actionWindowOpacity = action.payload + }, + setActionItems: (state, action: PayloadAction) => { + 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 diff --git a/src/renderer/src/store/settings.ts b/src/renderer/src/store/settings.ts index 1d6a5dac7c..d386577eba 100644 --- a/src/renderer/src/store/settings.ts +++ b/src/renderer/src/store/settings.ts @@ -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 } diff --git a/src/renderer/src/utils/__tests__/input.test.ts b/src/renderer/src/utils/__tests__/input.test.ts index 0eb697d36b..67cf83425c 100644 --- a/src/renderer/src/utils/__tests__/input.test.ts +++ b/src/renderer/src/utils/__tests__/input.test.ts @@ -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' diff --git a/src/renderer/src/utils/input.ts b/src/renderer/src/utils/input.ts index 85eb804255..ae09f7d802 100644 --- a/src/renderer/src/utils/input.ts +++ b/src/renderer/src/utils/input.ts @@ -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')