diff --git a/eslint.config.mjs b/eslint.config.mjs index 19b4efcd31..546c6d377f 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -48,6 +48,27 @@ export default defineConfig([ '@eslint-react/no-children-to-array': 'off' } }, + { + ignores: [ + 'node_modules/**', + 'build/**', + 'dist/**', + 'out/**', + 'local/**', + '.yarn/**', + '.gitignore', + 'scripts/cloudflare-worker.js', + 'src/main/integration/nutstore/sso/lib/**', + 'src/main/integration/cherryin/index.js', + 'src/main/integration/nutstore/sso/lib/**', + 'src/renderer/src/ui/**', + 'packages/**/dist' + ] + }, + // turn off oxlint supported rules. + ...oxlint.configs['flat/eslint'], + ...oxlint.configs['flat/typescript'], + ...oxlint.configs['flat/unicorn'], { // LoggerService Custom Rules - only apply to src directory files: ['src/**/*.{ts,tsx,js,jsx}'], @@ -121,34 +142,18 @@ export default defineConfig([ { name: 'antd', // TODO: migrate message again - importNames: ['Flex'], + importNames: ['Flex', 'Switch'], message: - '❌ Do not import Flex from antd. Use our custom Layout components instead: import { Flex } from "@cherrystudio/ui"' - } + '❌ Do not import this component from antd. Use our custom components instead: import { ... } from "@cherrystudio/ui"' + }, + // { + // name: '@heroui/react', + // message: + // '❌ Do not import components from heroui directly. Use our wrapped components instead: import { ... } from "@cherrystudio/ui"' + // } ] } ] } - }, - { - ignores: [ - 'node_modules/**', - 'build/**', - 'dist/**', - 'out/**', - 'local/**', - '.yarn/**', - '.gitignore', - 'scripts/cloudflare-worker.js', - 'src/main/integration/nutstore/sso/lib/**', - 'src/main/integration/cherryin/index.js', - 'src/main/integration/nutstore/sso/lib/**', - 'src/renderer/src/ui/**', - 'packages/**/dist' - ] - }, - // turn off oxlint supported rules. - ...oxlint.configs['flat/eslint'], - ...oxlint.configs['flat/typescript'], - ...oxlint.configs['flat/unicorn'] + } ]) diff --git a/packages/ui/src/components/base/Switch/index.tsx b/packages/ui/src/components/base/Switch/index.tsx new file mode 100644 index 0000000000..b3fdf7b989 --- /dev/null +++ b/packages/ui/src/components/base/Switch/index.tsx @@ -0,0 +1,27 @@ +import type { SwitchProps } from '@heroui/react' +import { Spinner, Switch } from '@heroui/react' + +// Enhanced Switch component with loading state support +interface CustomSwitchProps extends SwitchProps { + isLoading?: boolean +} + +/** + * A customized Switch component based on HeroUI Switch + * @see https://www.heroui.com/docs/components/switch#api + * @param isLoading When true, displays a loading spinner in the switch thumb + */ +const CustomizedSwitch = ({ isLoading, children, ref, thumbIcon, ...props }: CustomSwitchProps) => { + const finalThumbIcon = isLoading ? : thumbIcon + + return ( + + {children} + + ) +} + +CustomizedSwitch.displayName = 'Switch' + +export { CustomizedSwitch as Switch } +export type { CustomSwitchProps as SwitchProps } diff --git a/packages/ui/src/components/index.ts b/packages/ui/src/components/index.ts index c5f3727e34..8e83e2ea82 100644 --- a/packages/ui/src/components/index.ts +++ b/packages/ui/src/components/index.ts @@ -10,6 +10,7 @@ export { default as IndicatorLight } from './base/IndicatorLight' export { default as Spinner } from './base/Spinner' export type { StatusTagProps, StatusType } from './base/StatusTag' export { ErrorTag, InfoTag, StatusTag, SuccessTag, WarnTag } from './base/StatusTag' +export { Switch } from './base/Switch' export { default as TextBadge } from './base/TextBadge' // Display Components diff --git a/packages/ui/src/utils/index.ts b/packages/ui/src/utils/index.ts index 9eb12d4de3..6f3e963d06 100644 --- a/packages/ui/src/utils/index.ts +++ b/packages/ui/src/utils/index.ts @@ -1,9 +1 @@ -import { type ClassValue, clsx } from 'clsx' - -/** - * 合并CSS类名的工具函数 - * 基于clsx,支持条件类名和Tailwind CSS - */ -export function cn(...inputs: ClassValue[]) { - return clsx(inputs) -} +export { cn } from '@heroui/react' diff --git a/src/renderer/src/components/Buttons/ActionIconButton.tsx b/src/renderer/src/components/Buttons/ActionIconButton.tsx index 9f5c98abf0..d571f7ff17 100644 --- a/src/renderer/src/components/Buttons/ActionIconButton.tsx +++ b/src/renderer/src/components/Buttons/ActionIconButton.tsx @@ -1,4 +1,4 @@ -import { cn } from '@heroui/react' +import { cn } from '@cherrystudio/ui' import type { ButtonProps } from 'antd' import { Button } from 'antd' import React, { memo } from 'react' diff --git a/src/renderer/src/components/ObsidianExportDialog.tsx b/src/renderer/src/components/ObsidianExportDialog.tsx index 9cad3986e7..5ccac03d3c 100644 --- a/src/renderer/src/components/ObsidianExportDialog.tsx +++ b/src/renderer/src/components/ObsidianExportDialog.tsx @@ -1,3 +1,4 @@ +import { Switch } from '@cherrystudio/ui' import { usePreference } from '@data/hooks/usePreference' import { loggerService } from '@logger' import i18n from '@renderer/i18n' @@ -10,7 +11,7 @@ import { messageToMarkdownWithReasoning, topicToMarkdown } from '@renderer/utils/export' -import { Alert, Empty, Form, Input, Modal, Select, Spin, Switch, TreeSelect } from 'antd' +import { Alert, Empty, Form, Input, Modal, Select, Spin, TreeSelect } from 'antd' import React, { useEffect, useState } from 'react' const logger = loggerService.withContext('ObsidianExportDialog') @@ -410,7 +411,7 @@ const PopupContainer: React.FC = ({ - + diff --git a/src/renderer/src/context/HeroUIProvider.tsx b/src/renderer/src/context/HeroUIProvider.tsx index 1a0f31a89b..d6f9780660 100644 --- a/src/renderer/src/context/HeroUIProvider.tsx +++ b/src/renderer/src/context/HeroUIProvider.tsx @@ -1,6 +1,7 @@ import { HeroUIProvider } from '@heroui/react' import { useSettings } from '@renderer/hooks/useSettings' +// TODO: migrate to ui package const AppHeroUIProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { const { language } = useSettings() return ( diff --git a/src/renderer/src/hero.ts b/src/renderer/src/hero.ts index 93a081c30b..a93a523a01 100644 --- a/src/renderer/src/hero.ts +++ b/src/renderer/src/hero.ts @@ -1,2 +1,5 @@ import { heroui } from '@heroui/react' -export default heroui() + +const hero: ReturnType = heroui() + +export default hero diff --git a/src/renderer/src/pages/home/Tabs/SettingsTab.tsx b/src/renderer/src/pages/home/Tabs/SettingsTab.tsx index 4c61f497fe..e405e79f9d 100644 --- a/src/renderer/src/pages/home/Tabs/SettingsTab.tsx +++ b/src/renderer/src/pages/home/Tabs/SettingsTab.tsx @@ -1,4 +1,5 @@ import { RowFlex } from '@cherrystudio/ui' +import { Switch } from '@cherrystudio/ui' import { useMultiplePreferences, usePreference } from '@data/hooks/usePreference' import EditableNumber from '@renderer/components/EditableNumber' import Scrollbar from '@renderer/components/Scrollbar' @@ -21,7 +22,7 @@ import { modalConfirm } from '@renderer/utils' import { getSendMessageShortcutLabel } from '@renderer/utils/input' import type { SendMessageShortcut } from '@shared/data/preference/preferenceTypes' import { ThemeMode } from '@shared/data/preference/preferenceTypes' -import { Button, Col, InputNumber, Row, Slider, Switch } from 'antd' +import { Button, Col, InputNumber, Row, Slider } from 'antd' import { Settings2 } from 'lucide-react' import type { FC } from 'react' import { useCallback, useEffect, useMemo, useState } from 'react' @@ -188,10 +189,10 @@ const SettingsTab: FC = (props) => { { + size="sm" + className="ml-auto" + isSelected={enableTemperature} + onValueChange={(enabled) => { setEnableTemperature(enabled) onUpdateAssistantSettings({ enableTemperature: enabled }) }} @@ -235,9 +236,9 @@ const SettingsTab: FC = (props) => { {t('models.stream_output')} { + size="sm" + isSelected={streamOutput} + onValueChange={(checked) => { setStreamOutput(checked) onUpdateAssistantSettings({ streamOutput: checked }) }} @@ -252,9 +253,9 @@ const SettingsTab: FC = (props) => { { + size="sm" + isSelected={enableMaxTokens} + onValueChange={async (enabled) => { if (enabled) { const confirmed = await modalConfirm({ title: t('chat.settings.max_tokens.confirm'), @@ -302,15 +303,15 @@ const SettingsTab: FC = (props) => { {t('settings.messages.prompt')} - setShowPrompt(checked)} /> + {t('settings.messages.use_serif_font')} setMessageFont(checked ? 'serif' : 'system')} + size="sm" + isSelected={messageFont === 'serif'} + onValueChange={(checked) => setMessageFont(checked ? 'serif' : 'system')} /> @@ -319,16 +320,12 @@ const SettingsTab: FC = (props) => { {t('chat.settings.thought_auto_collapse.label')} - setThoughtAutoCollapse(checked)} - /> + {t('settings.messages.show_message_outline')} - setShowMessageOutline(checked)} /> + @@ -413,11 +410,7 @@ const SettingsTab: FC = (props) => { {t('settings.math.single_dollar.label')} - setMathEnableSingleDollar(checked)} - /> + @@ -441,7 +434,7 @@ const SettingsTab: FC = (props) => { {t('chat.settings.code_fancy_block.label')} - setCodeFancyBlock(checked)} /> + @@ -450,9 +443,9 @@ const SettingsTab: FC = (props) => { setCodeExecution({ enabled: checked })} + size="sm" + isSelected={codeExecution.enabled} + onValueChange={(checked) => setCodeExecution({ enabled: checked })} /> {codeExecution.enabled && ( @@ -479,9 +472,9 @@ const SettingsTab: FC = (props) => { {t('chat.settings.code_editor.title')} setCodeEditor({ enabled: checked })} + size="sm" + isSelected={codeEditor.enabled} + onValueChange={(checked) => setCodeEditor({ enabled: checked })} /> {codeEditor.enabled && ( @@ -490,36 +483,36 @@ const SettingsTab: FC = (props) => { {t('chat.settings.code_editor.highlight_active_line')} setCodeEditor({ highlightActiveLine: checked })} + size="sm" + isSelected={codeEditor.highlightActiveLine} + onValueChange={(checked) => setCodeEditor({ highlightActiveLine: checked })} /> {t('chat.settings.code_editor.fold_gutter')} setCodeEditor({ foldGutter: checked })} + size="sm" + isSelected={codeEditor.foldGutter} + onValueChange={(checked) => setCodeEditor({ foldGutter: checked })} /> {t('chat.settings.code_editor.autocompletion')} setCodeEditor({ autocompletion: checked })} + size="sm" + isSelected={codeEditor.autocompletion} + onValueChange={(checked) => setCodeEditor({ autocompletion: checked })} /> {t('chat.settings.code_editor.keymap')} setCodeEditor({ keymap: checked })} + size="sm" + isSelected={codeEditor.keymap} + onValueChange={(checked) => setCodeEditor({ keymap: checked })} /> @@ -527,21 +520,17 @@ const SettingsTab: FC = (props) => { {t('chat.settings.show_line_numbers')} - setCodeShowLineNumbers(checked)} - /> + {t('chat.settings.code_collapsible')} - setCodeCollapsible(checked)} /> + {t('chat.settings.code_wrappable')} - setCodeWrappable(checked)} /> + @@ -549,7 +538,7 @@ const SettingsTab: FC = (props) => { {t('chat.settings.code_image_tools.label')} - setCodeImageTools(checked)} /> + @@ -558,20 +547,12 @@ const SettingsTab: FC = (props) => { {t('settings.messages.input.show_estimated_tokens')} - setShowInputEstimatedTokens(checked)} - /> + {t('settings.messages.input.paste_long_text_as_file')} - setPasteLongTextAsFile(checked)} - /> + {pasteLongTextAsFile && ( <> @@ -594,9 +575,9 @@ const SettingsTab: FC = (props) => { {t('settings.messages.markdown_rendering_input_message')} setRenderInputMessageAsMarkdown(checked)} + size="sm" + isSelected={renderInputMessageAsMarkdown} + onValueChange={setRenderInputMessageAsMarkdown} /> @@ -604,49 +585,29 @@ const SettingsTab: FC = (props) => { <> {t('settings.input.auto_translate_with_space')} - setAutoTranslateWithSpace(checked)} - /> + )} {t('settings.input.show_translate_confirm')} - setShowTranslateConfirm(checked)} - /> + {t('settings.messages.input.enable_quick_triggers')} - setEnableQuickPanelTriggers(checked)} - /> + {t('settings.messages.input.confirm_delete_message')} - setConfirmDeleteMessage(checked)} - /> + {t('settings.messages.input.confirm_regenerate_message')} - setConfirmRegenerateMessage(checked)} - /> + diff --git a/src/renderer/src/pages/minapps/MiniappSettings/MiniAppSettings.tsx b/src/renderer/src/pages/minapps/MiniappSettings/MiniAppSettings.tsx index da1e6e61ff..7b3925d5b8 100644 --- a/src/renderer/src/pages/minapps/MiniappSettings/MiniAppSettings.tsx +++ b/src/renderer/src/pages/minapps/MiniappSettings/MiniAppSettings.tsx @@ -1,9 +1,10 @@ import { UndoOutlined } from '@ant-design/icons' // 导入重置图标 +import { Switch } from '@cherrystudio/ui' import { usePreference } from '@data/hooks/usePreference' import { DEFAULT_MIN_APPS } from '@renderer/config/minapps' import { useMinapps } from '@renderer/hooks/useMinapps' import { SettingDescription, SettingDivider, SettingRowTitle, SettingTitle } from '@renderer/pages/settings' -import { Button, message, Slider, Switch, Tooltip } from 'antd' +import { Button, message, Slider, Tooltip } from 'antd' import type { FC } from 'react' import { useCallback, useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' @@ -97,7 +98,7 @@ const MiniAppSettings: FC = () => { {t('settings.miniapps.open_link_external.title')} - setMinappsOpenLinkExternal(checked)} /> + setMinappsOpenLinkExternal(checked)} /> {/* 缓存小程序数量设置 */} @@ -134,7 +135,10 @@ const MiniAppSettings: FC = () => { {t('settings.miniapps.sidebar_title')} {t('settings.miniapps.sidebar_description')} - setShowOpenedMinappsInSidebar(checked)} /> + setShowOpenedMinappsInSidebar(checked)} + /> ) diff --git a/src/renderer/src/pages/paintings/AihubmixPage.tsx b/src/renderer/src/pages/paintings/AihubmixPage.tsx index e5f06b8e52..38d9045ee4 100644 --- a/src/renderer/src/pages/paintings/AihubmixPage.tsx +++ b/src/renderer/src/pages/paintings/AihubmixPage.tsx @@ -1,5 +1,6 @@ import { PlusOutlined, RedoOutlined } from '@ant-design/icons' import { RowFlex } from '@cherrystudio/ui' +import { Switch } from '@cherrystudio/ui' import { useCache } from '@data/hooks/useCache' import { usePreference } from '@data/hooks/usePreference' import { loggerService } from '@logger' @@ -20,7 +21,7 @@ import { translateText } from '@renderer/services/TranslateService' import type { FileMetadata } from '@renderer/types' import type { PaintingAction, PaintingsState } from '@renderer/types' import { getErrorMessage, uuid } from '@renderer/utils' -import { Avatar, Button, Input, InputNumber, Radio, Segmented, Select, Slider, Switch, Tooltip, Upload } from 'antd' +import { Avatar, Button, Input, InputNumber, Radio, Segmented, Select, Slider, Tooltip, Upload } from 'antd' import TextArea from 'antd/es/input/TextArea' import { Info } from 'lucide-react' import type { FC } from 'react' @@ -747,8 +748,8 @@ const AihubmixPage: FC<{ Options: string[] }> = ({ Options }) => { return ( updatePaintingState({ [item.key!]: checked })} + isSelected={(painting[item.key!] || item.initialValue) as boolean} + onValueChange={(checked) => updatePaintingState({ [item.key!]: checked })} /> ) diff --git a/src/renderer/src/pages/paintings/DmxapiPage.tsx b/src/renderer/src/pages/paintings/DmxapiPage.tsx index df2c833d56..0d47a9263f 100644 --- a/src/renderer/src/pages/paintings/DmxapiPage.tsx +++ b/src/renderer/src/pages/paintings/DmxapiPage.tsx @@ -1,5 +1,6 @@ import { PlusOutlined, RedoOutlined } from '@ant-design/icons' import { RowFlex } from '@cherrystudio/ui' +import { Switch } from '@cherrystudio/ui' import { useCache } from '@data/hooks/useCache' import DMXAPIToImg from '@renderer/assets/images/providers/DMXAPI-to-img.webp' import { Navbar, NavbarCenter, NavbarRight } from '@renderer/components/app/Navbar' @@ -13,7 +14,7 @@ import FileManager from '@renderer/services/FileManager' import type { FileMetadata } from '@renderer/types' import { convertToBase64, uuid } from '@renderer/utils' import type { DmxapiPainting } from '@types' -import { Avatar, Button, Input, InputNumber, Segmented, Select, Switch, Tooltip } from 'antd' +import { Avatar, Button, Input, InputNumber, Segmented, Select, Tooltip } from 'antd' import TextArea from 'antd/es/input/TextArea' import { Info } from 'lucide-react' import type { FC } from 'react' @@ -960,7 +961,7 @@ const DmxapiPage: FC<{ Options: string[] }> = ({ Options }) => { - onChangeAutoCreate(checked)} /> + onChangeAutoCreate(checked)} /> diff --git a/src/renderer/src/pages/paintings/SiliconPage.tsx b/src/renderer/src/pages/paintings/SiliconPage.tsx index 173c8ab5b6..0b54f4e2db 100644 --- a/src/renderer/src/pages/paintings/SiliconPage.tsx +++ b/src/renderer/src/pages/paintings/SiliconPage.tsx @@ -1,5 +1,6 @@ import { PlusOutlined, RedoOutlined } from '@ant-design/icons' import { ColFlex, RowFlex } from '@cherrystudio/ui' +import { Switch } from '@cherrystudio/ui' import { useCache } from '@data/hooks/useCache' import { usePreference } from '@data/hooks/usePreference' import { loggerService } from '@logger' @@ -24,7 +25,7 @@ import FileManager from '@renderer/services/FileManager' import { translateText } from '@renderer/services/TranslateService' import type { FileMetadata, Painting } from '@renderer/types' import { getErrorMessage, uuid } from '@renderer/utils' -import { Button, Input, InputNumber, Radio, Select, Slider, Switch, Tooltip } from 'antd' +import { Button, Input, InputNumber, Radio, Select, Slider, Tooltip } from 'antd' import TextArea from 'antd/es/input/TextArea' import { Info } from 'lucide-react' import type { FC } from 'react' @@ -485,8 +486,8 @@ const SiliconPage: FC<{ Options: string[] }> = ({ Options }) => { updatePaintingState({ promptEnhancement: checked })} + isSelected={painting.promptEnhancement} + onValueChange={(checked) => updatePaintingState({ promptEnhancement: checked })} /> diff --git a/src/renderer/src/pages/paintings/components/DynamicFormRender.tsx b/src/renderer/src/pages/paintings/components/DynamicFormRender.tsx index 7495ad1a59..dab3e27b6d 100644 --- a/src/renderer/src/pages/paintings/components/DynamicFormRender.tsx +++ b/src/renderer/src/pages/paintings/components/DynamicFormRender.tsx @@ -1,7 +1,8 @@ import { CloseOutlined, LinkOutlined, RedoOutlined, UploadOutlined } from '@ant-design/icons' +import { Switch } from '@cherrystudio/ui' import { loggerService } from '@logger' import { convertToBase64 } from '@renderer/utils' -import { Button, Input, InputNumber, Select, Switch, Upload } from 'antd' +import { Button, Input, InputNumber, Select, Upload } from 'antd' import TextArea from 'antd/es/input/TextArea' import { useCallback } from 'react' @@ -205,8 +206,8 @@ export const DynamicFormRender: React.FC = ({ if (type === 'boolean') { return ( onChange(propertyName, checked)} + isSelected={value !== undefined ? value : defaultValue} + onValueChange={(checked) => onChange(propertyName, checked)} style={{ width: '2px' }} /> ) diff --git a/src/renderer/src/pages/settings/AboutSettings.tsx b/src/renderer/src/pages/settings/AboutSettings.tsx index 1751c5d949..2dfb7ddeb0 100644 --- a/src/renderer/src/pages/settings/AboutSettings.tsx +++ b/src/renderer/src/pages/settings/AboutSettings.tsx @@ -1,5 +1,6 @@ import { GithubOutlined } from '@ant-design/icons' import { RowFlex } from '@cherrystudio/ui' +import { Switch } from '@cherrystudio/ui' import { usePreference } from '@data/hooks/usePreference' import IndicatorLight from '@renderer/components/IndicatorLight' import { APP_NAME, AppLogo } from '@renderer/config/env' @@ -13,7 +14,7 @@ import { handleSaveData } from '@renderer/store' import { runAsyncFunction } from '@renderer/utils' import { UpgradeChannel } from '@shared/data/preference/preferenceTypes' import { ThemeMode } from '@shared/data/preference/preferenceTypes' -import { Avatar, Button, Progress, Radio, Row, Switch, Tag, Tooltip } from 'antd' +import { Avatar, Button, Progress, Radio, Row, Tag, Tooltip } from 'antd' import { debounce } from 'lodash' import { Bug, FileCheck, Github, Globe, Mail, Rss } from 'lucide-react' import { BadgeQuestionMark } from 'lucide-react' @@ -237,13 +238,13 @@ const AboutSettings: FC = () => { {t('settings.general.auto_check_update.title')} - setAutoCheckUpdate(v)} /> + setAutoCheckUpdate(v)} /> {t('settings.general.test_plan.title')} - handleSetTestPlan(v)} /> + handleSetTestPlan(v)} /> {testPlan && ( diff --git a/src/renderer/src/pages/settings/AssistantSettings/AssistantMCPSettings.tsx b/src/renderer/src/pages/settings/AssistantSettings/AssistantMCPSettings.tsx index 13c4974e45..addff65dd3 100644 --- a/src/renderer/src/pages/settings/AssistantSettings/AssistantMCPSettings.tsx +++ b/src/renderer/src/pages/settings/AssistantSettings/AssistantMCPSettings.tsx @@ -1,8 +1,9 @@ import { InfoCircleOutlined } from '@ant-design/icons' import { Box } from '@cherrystudio/ui' +import { Switch } from '@cherrystudio/ui' import { useMCPServers } from '@renderer/hooks/useMCPServers' import type { Assistant, AssistantSettings } from '@renderer/types' -import { Empty, Switch, Tooltip } from 'antd' +import { Empty, Tooltip } from 'antd' import { useTranslation } from 'react-i18next' import styled from 'styled-components' @@ -84,10 +85,10 @@ const AssistantMCPSettings: React.FC = ({ assistant, updateAssistant }) = : undefined }> handleServerToggle(server.id)} - size="small" + onValueChange={() => handleServerToggle(server.id)} + size="sm" /> diff --git a/src/renderer/src/pages/settings/AssistantSettings/AssistantMemorySettings.tsx b/src/renderer/src/pages/settings/AssistantSettings/AssistantMemorySettings.tsx index d414108d3b..8c5ec1538f 100644 --- a/src/renderer/src/pages/settings/AssistantSettings/AssistantMemorySettings.tsx +++ b/src/renderer/src/pages/settings/AssistantSettings/AssistantMemorySettings.tsx @@ -1,11 +1,12 @@ import { InfoCircleOutlined } from '@ant-design/icons' import { Box } from '@cherrystudio/ui' +import { Switch } from '@cherrystudio/ui' import { loggerService } from '@logger' import MemoriesSettingsModal from '@renderer/pages/memory/settings-modal' import MemoryService from '@renderer/services/MemoryService' import { selectGlobalMemoryEnabled, selectMemoryConfig } from '@renderer/store/memory' import type { Assistant, AssistantSettings } from '@renderer/types' -import { Alert, Button, Card, Space, Switch, Tooltip, Typography } from 'antd' +import { Alert, Button, Card, Space, Tooltip, Typography } from 'antd' import { useForm } from 'antd/es/form/Form' import { Settings2 } from 'lucide-react' import { useCallback, useEffect, useState } from 'react' @@ -91,8 +92,8 @@ const AssistantMemorySettings: React.FC = ({ assistant, updateAssistant, : '' }> diff --git a/src/renderer/src/pages/settings/AssistantSettings/AssistantModelSettings.tsx b/src/renderer/src/pages/settings/AssistantSettings/AssistantModelSettings.tsx index c797e4d600..af6e89c316 100644 --- a/src/renderer/src/pages/settings/AssistantSettings/AssistantModelSettings.tsx +++ b/src/renderer/src/pages/settings/AssistantSettings/AssistantModelSettings.tsx @@ -1,5 +1,6 @@ import { QuestionCircleOutlined } from '@ant-design/icons' import { RowFlex } from '@cherrystudio/ui' +import { Switch } from '@cherrystudio/ui' import ModelAvatar from '@renderer/components/Avatar/ModelAvatar' import EditableNumber from '@renderer/components/EditableNumber' import { DeleteIcon, ResetIcon } from '@renderer/components/Icons' @@ -11,7 +12,7 @@ import { useTimer } from '@renderer/hooks/useTimer' import { SettingRow } from '@renderer/pages/settings' import type { Assistant, AssistantSettingCustomParameters, AssistantSettings, Model } from '@renderer/types' import { modalConfirm } from '@renderer/utils' -import { Button, Col, Divider, Input, InputNumber, Row, Select, Slider, Switch, Tooltip } from 'antd' +import { Button, Col, Divider, Input, InputNumber, Row, Select, Slider, Tooltip } from 'antd' import { isNull } from 'lodash' import { PlusIcon } from 'lucide-react' import type { FC } from 'react' @@ -250,8 +251,8 @@ const AssistantModelSettings: FC = ({ assistant, updateAssistant, updateA { + isSelected={enableTemperature} + onValueChange={(enabled) => { setEnableTemperature(enabled) updateAssistantSettings({ enableTemperature: enabled }) }} @@ -298,8 +299,8 @@ const AssistantModelSettings: FC = ({ assistant, updateAssistant, updateA { + isSelected={enableTopP} + onValueChange={(enabled) => { setEnableTopP(enabled) updateAssistantSettings({ enableTopP: enabled }) }} @@ -387,8 +388,8 @@ const AssistantModelSettings: FC = ({ assistant, updateAssistant, updateA { + isSelected={enableMaxTokens} + onValueChange={async (enabled) => { if (enabled) { const confirmed = await modalConfirm({ title: t('chat.settings.max_tokens.confirm'), @@ -430,8 +431,8 @@ const AssistantModelSettings: FC = ({ assistant, updateAssistant, updateA { + isSelected={streamOutput} + onValueChange={(checked) => { setStreamOutput(checked) updateAssistantSettings({ streamOutput: checked }) }} diff --git a/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx b/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx index 253675a1e1..508c67952b 100644 --- a/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx +++ b/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx @@ -6,6 +6,7 @@ import { YuqueOutlined } from '@ant-design/icons' import { RowFlex } from '@cherrystudio/ui' +import { Switch } from '@cherrystudio/ui' import { usePreference } from '@data/hooks/usePreference' import DividerWithText from '@renderer/components/DividerWithText' import { NutstoreIcon } from '@renderer/components/Icons/NutstoreIcons' @@ -19,7 +20,7 @@ import { reset } from '@renderer/services/BackupService' import type { AppInfo } from '@renderer/types' import { formatFileSize } from '@renderer/utils' import { occupiedDirs } from '@shared/config/constant' -import { Button, Progress, Switch, Typography } from 'antd' +import { Button, Progress, Typography } from 'antd' import { FileText, FolderCog, FolderInput, FolderOpen, SaveIcon, Sparkle } from 'lucide-react' import type { FC } from 'react' import { useEffect, useState } from 'react' @@ -287,11 +288,11 @@ const DataSettings: FC = () => {
{ + defaultSelected={shouldCopyData} + onValueChange={(checked) => { shouldCopyData = checked }} - style={{ marginRight: '8px' }} + className="mr-2" /> {t('settings.data.app_data.copy_data_option')} @@ -612,7 +613,7 @@ const DataSettings: FC = () => { {t('settings.data.backup.skip_file_data_title')} - + {t('settings.data.backup.skip_file_data_help')} diff --git a/src/renderer/src/pages/settings/DataSettings/ExportMenuSettings.tsx b/src/renderer/src/pages/settings/DataSettings/ExportMenuSettings.tsx index 4276b55ee0..974f760239 100644 --- a/src/renderer/src/pages/settings/DataSettings/ExportMenuSettings.tsx +++ b/src/renderer/src/pages/settings/DataSettings/ExportMenuSettings.tsx @@ -1,6 +1,6 @@ +import { Switch } from '@cherrystudio/ui' import { useMultiplePreferences } from '@data/hooks/usePreference' import { useTheme } from '@renderer/context/ThemeProvider' -import { Switch } from 'antd' import type { FC } from 'react' import { useTranslation } from 'react-i18next' @@ -35,66 +35,87 @@ const ExportMenuOptions: FC = () => { {t('settings.data.export_menu.image')} - handleToggleOption('image', checked)} /> + handleToggleOption('image', checked)} + /> {t('settings.data.export_menu.markdown')} - handleToggleOption('markdown', checked)} /> + handleToggleOption('markdown', checked)} + /> {t('settings.data.export_menu.markdown_reason')} handleToggleOption('markdown_reason', checked)} + isSelected={exportMenuOptions.markdown_reason} + onValueChange={(checked) => handleToggleOption('markdown_reason', checked)} /> {t('settings.data.export_menu.notion')} - handleToggleOption('notion', checked)} /> + handleToggleOption('notion', checked)} + /> {t('settings.data.export_menu.yuque')} - handleToggleOption('yuque', checked)} /> + handleToggleOption('yuque', checked)} + /> {t('settings.data.export_menu.joplin')} - handleToggleOption('joplin', checked)} /> + handleToggleOption('joplin', checked)} + /> {t('settings.data.export_menu.obsidian')} - handleToggleOption('obsidian', checked)} /> + handleToggleOption('obsidian', checked)} + /> {t('settings.data.export_menu.siyuan')} - handleToggleOption('siyuan', checked)} /> + handleToggleOption('siyuan', checked)} + /> {t('settings.data.export_menu.docx')} - handleToggleOption('docx', checked)} /> + handleToggleOption('docx', checked)} /> {t('settings.data.export_menu.plain_text')} handleToggleOption('plain_text', checked)} + isSelected={exportMenuOptions.plain_text} + onValueChange={(checked) => handleToggleOption('plain_text', checked)} /> diff --git a/src/renderer/src/pages/settings/DataSettings/JoplinSettings.tsx b/src/renderer/src/pages/settings/DataSettings/JoplinSettings.tsx index 2aaf86e249..c3379514cf 100644 --- a/src/renderer/src/pages/settings/DataSettings/JoplinSettings.tsx +++ b/src/renderer/src/pages/settings/DataSettings/JoplinSettings.tsx @@ -1,9 +1,10 @@ import { InfoCircleOutlined } from '@ant-design/icons' import { RowFlex } from '@cherrystudio/ui' +import { Switch } from '@cherrystudio/ui' import { usePreference } from '@data/hooks/usePreference' import { useTheme } from '@renderer/context/ThemeProvider' import { useMinappPopup } from '@renderer/hooks/useMinappPopup' -import { Button, Space, Switch, Tooltip } from 'antd' +import { Button, Space, Tooltip } from 'antd' import { Input } from 'antd' import type { FC } from 'react' import { useTranslation } from 'react-i18next' @@ -118,7 +119,7 @@ const JoplinSettings: FC = () => { {t('settings.data.joplin.export_reasoning.title')} - + {t('settings.data.joplin.export_reasoning.help')} diff --git a/src/renderer/src/pages/settings/DataSettings/LocalBackupSettings.tsx b/src/renderer/src/pages/settings/DataSettings/LocalBackupSettings.tsx index 1b369e2dc2..c67a453b59 100644 --- a/src/renderer/src/pages/settings/DataSettings/LocalBackupSettings.tsx +++ b/src/renderer/src/pages/settings/DataSettings/LocalBackupSettings.tsx @@ -1,5 +1,6 @@ import { DeleteOutlined, FolderOpenOutlined, SaveOutlined, SyncOutlined, WarningOutlined } from '@ant-design/icons' import { RowFlex } from '@cherrystudio/ui' +import { Switch } from '@cherrystudio/ui' import { usePreference } from '@data/hooks/usePreference' import { loggerService } from '@logger' import { LocalBackupManager } from '@renderer/components/LocalBackupManager' @@ -9,7 +10,7 @@ import { useTheme } from '@renderer/context/ThemeProvider' import { startAutoSync, stopAutoSync } from '@renderer/services/BackupService' import { useAppSelector } from '@renderer/store' import type { AppInfo } from '@renderer/types' -import { Button, Input, Switch, Tooltip } from 'antd' +import { Button, Input, Tooltip } from 'antd' import dayjs from 'dayjs' import { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' @@ -256,7 +257,7 @@ const LocalBackupSettings: React.FC = () => { {t('settings.data.backup.skip_file_data_title')} - + {t('settings.data.backup.skip_file_data_help')} diff --git a/src/renderer/src/pages/settings/DataSettings/MarkdownExportSettings.tsx b/src/renderer/src/pages/settings/DataSettings/MarkdownExportSettings.tsx index ed1dff4f1b..f7a23b8867 100644 --- a/src/renderer/src/pages/settings/DataSettings/MarkdownExportSettings.tsx +++ b/src/renderer/src/pages/settings/DataSettings/MarkdownExportSettings.tsx @@ -1,8 +1,9 @@ import { DeleteOutlined, FolderOpenOutlined } from '@ant-design/icons' import { RowFlex } from '@cherrystudio/ui' +import { Switch } from '@cherrystudio/ui' import { usePreference } from '@data/hooks/usePreference' import { useTheme } from '@renderer/context/ThemeProvider' -import { Button, Switch } from 'antd' +import { Button } from 'antd' import Input from 'antd/es/input/Input' import type { FC } from 'react' import { useTranslation } from 'react-i18next' @@ -96,7 +97,7 @@ const MarkdownExportSettings: FC = () => { {t('settings.data.markdown_export.force_dollar_math.title')} - + {t('settings.data.markdown_export.force_dollar_math.help')} @@ -104,7 +105,7 @@ const MarkdownExportSettings: FC = () => { {t('settings.data.message_title.use_topic_naming.title')} - + {t('settings.data.message_title.use_topic_naming.help')} @@ -112,7 +113,7 @@ const MarkdownExportSettings: FC = () => { {t('settings.data.markdown_export.show_model_name.title')} - + {t('settings.data.markdown_export.show_model_name.help')} @@ -120,7 +121,7 @@ const MarkdownExportSettings: FC = () => { {t('settings.data.markdown_export.show_model_provider.title')} - + {t('settings.data.markdown_export.show_model_provider.help')} @@ -128,7 +129,7 @@ const MarkdownExportSettings: FC = () => { {t('settings.data.markdown_export.exclude_citations.title')} - + {t('settings.data.markdown_export.exclude_citations.help')} @@ -136,7 +137,7 @@ const MarkdownExportSettings: FC = () => { {t('settings.data.markdown_export.standardize_citations.title')} - + {t('settings.data.markdown_export.standardize_citations.help')} diff --git a/src/renderer/src/pages/settings/DataSettings/NotionSettings.tsx b/src/renderer/src/pages/settings/DataSettings/NotionSettings.tsx index 6139372eb1..d8b3c78be9 100644 --- a/src/renderer/src/pages/settings/DataSettings/NotionSettings.tsx +++ b/src/renderer/src/pages/settings/DataSettings/NotionSettings.tsx @@ -1,10 +1,11 @@ import { InfoCircleOutlined } from '@ant-design/icons' import { RowFlex } from '@cherrystudio/ui' +import { Switch } from '@cherrystudio/ui' import { usePreference } from '@data/hooks/usePreference' import { Client } from '@notionhq/client' import { useTheme } from '@renderer/context/ThemeProvider' import { useMinappPopup } from '@renderer/hooks/useMinappPopup' -import { Button, Space, Switch, Tooltip } from 'antd' +import { Button, Space, Tooltip } from 'antd' import { Input } from 'antd' import type { FC } from 'react' import { useTranslation } from 'react-i18next' @@ -126,7 +127,7 @@ const NotionSettings: FC = () => { {t('settings.data.notion.export_reasoning.title')} - + {t('settings.data.notion.export_reasoning.help')} diff --git a/src/renderer/src/pages/settings/DataSettings/NutstoreSettings.tsx b/src/renderer/src/pages/settings/DataSettings/NutstoreSettings.tsx index 99891f728f..3b169a7592 100644 --- a/src/renderer/src/pages/settings/DataSettings/NutstoreSettings.tsx +++ b/src/renderer/src/pages/settings/DataSettings/NutstoreSettings.tsx @@ -1,5 +1,6 @@ import { CheckOutlined, FolderOutlined, LoadingOutlined, SyncOutlined, WarningOutlined } from '@ant-design/icons' import { RowFlex } from '@cherrystudio/ui' +import { Switch } from '@cherrystudio/ui' import { usePreference } from '@data/hooks/usePreference' import NutstorePathPopup from '@renderer/components/Popups/NutsorePathPopup' import Selector from '@renderer/components/Selector' @@ -19,7 +20,7 @@ import { import { useAppSelector } from '@renderer/store' import { modalConfirm } from '@renderer/utils' import { NUTSTORE_HOST } from '@shared/config/nutstore' -import { Button, Input, Switch, Tooltip, Typography } from 'antd' +import { Button, Input, Tooltip, Typography } from 'antd' import dayjs from 'dayjs' import type { FC } from 'react' import { useCallback, useEffect, useState } from 'react' @@ -319,7 +320,7 @@ const NutstoreSettings: FC = () => { {t('settings.data.backup.skip_file_data_title')} - + {t('settings.data.backup.skip_file_data_help')} diff --git a/src/renderer/src/pages/settings/DataSettings/S3Settings.tsx b/src/renderer/src/pages/settings/DataSettings/S3Settings.tsx index ba314751c1..f5f74b4429 100644 --- a/src/renderer/src/pages/settings/DataSettings/S3Settings.tsx +++ b/src/renderer/src/pages/settings/DataSettings/S3Settings.tsx @@ -1,5 +1,6 @@ import { FolderOpenOutlined, InfoCircleOutlined, SaveOutlined, SyncOutlined, WarningOutlined } from '@ant-design/icons' import { RowFlex } from '@cherrystudio/ui' +import { Switch } from '@cherrystudio/ui' import { usePreference } from '@data/hooks/usePreference' import { S3BackupManager } from '@renderer/components/S3BackupManager' import { S3BackupModal, useS3BackupModal } from '@renderer/components/S3Modals' @@ -8,7 +9,7 @@ import { useTheme } from '@renderer/context/ThemeProvider' import { useMinappPopup } from '@renderer/hooks/useMinappPopup' import { startAutoSync, stopAutoSync } from '@renderer/services/BackupService' import { useAppSelector } from '@renderer/store' -import { Button, Input, Switch, Tooltip } from 'antd' +import { Button, Input, Tooltip } from 'antd' import dayjs from 'dayjs' import type { FC } from 'react' import { useState } from 'react' @@ -237,7 +238,7 @@ const S3Settings: FC = () => { {t('settings.data.s3.skipBackupFile.label')} - + {t('settings.data.s3.skipBackupFile.help')} diff --git a/src/renderer/src/pages/settings/DataSettings/WebDavSettings.tsx b/src/renderer/src/pages/settings/DataSettings/WebDavSettings.tsx index c9db62dac6..d3cf5963fe 100644 --- a/src/renderer/src/pages/settings/DataSettings/WebDavSettings.tsx +++ b/src/renderer/src/pages/settings/DataSettings/WebDavSettings.tsx @@ -1,5 +1,6 @@ import { FolderOpenOutlined, SaveOutlined, SyncOutlined, WarningOutlined } from '@ant-design/icons' import { RowFlex } from '@cherrystudio/ui' +import { Switch } from '@cherrystudio/ui' import { usePreference } from '@data/hooks/usePreference' import Selector from '@renderer/components/Selector' import { WebdavBackupManager } from '@renderer/components/WebdavBackupManager' @@ -7,7 +8,7 @@ import { useWebdavBackupModal, WebdavBackupModal } from '@renderer/components/We import { useTheme } from '@renderer/context/ThemeProvider' import { startAutoSync, stopAutoSync } from '@renderer/services/BackupService' import { useAppSelector } from '@renderer/store' -import { Button, Input, Switch, Tooltip } from 'antd' +import { Button, Input, Tooltip } from 'antd' import dayjs from 'dayjs' import type { FC } from 'react' import { useState } from 'react' @@ -198,7 +199,7 @@ const WebDavSettings: FC = () => { {t('settings.data.backup.skip_file_data_title')} - + {t('settings.data.backup.skip_file_data_help')} @@ -206,7 +207,7 @@ const WebDavSettings: FC = () => { {t('settings.data.webdav.disableStream.title')} - + {t('settings.data.webdav.disableStream.help')} diff --git a/src/renderer/src/pages/settings/DisplaySettings/DisplaySettings.tsx b/src/renderer/src/pages/settings/DisplaySettings/DisplaySettings.tsx index 24abdcc8a2..98e0f6e922 100644 --- a/src/renderer/src/pages/settings/DisplaySettings/DisplaySettings.tsx +++ b/src/renderer/src/pages/settings/DisplaySettings/DisplaySettings.tsx @@ -1,5 +1,6 @@ import { RowFlex } from '@cherrystudio/ui' import { CodeEditor } from '@cherrystudio/ui' +import { Switch } from '@cherrystudio/ui' import { usePreference } from '@data/hooks/usePreference' import { ResetIcon } from '@renderer/components/Icons' import TextBadge from '@renderer/components/TextBadge' @@ -11,7 +12,7 @@ import useUserTheme from '@renderer/hooks/useUserTheme' import { DefaultPreferences } from '@shared/data/preference/preferenceSchemas' import type { AssistantIconType } from '@shared/data/preference/preferenceTypes' import { ThemeMode } from '@shared/data/preference/preferenceTypes' -import { Button, ColorPicker, Segmented, Select, Switch } from 'antd' +import { Button, ColorPicker, Segmented, Select } from 'antd' import { Minus, Monitor, Moon, Plus, Sun } from 'lucide-react' import type { FC } from 'react' import { useCallback, useEffect, useMemo, useState } from 'react' @@ -229,7 +230,7 @@ const DisplaySettings: FC = () => { {t('settings.theme.window.style.transparent')} - + )} @@ -361,8 +362,8 @@ const DisplaySettings: FC = () => { {t('settings.advanced.auto_switch_to_topics')} setClickAssistantToShowTopic(checked)} + isSelected={clickAssistantToShowTopic} + onValueChange={(checked) => setClickAssistantToShowTopic(checked)} /> @@ -370,12 +371,12 @@ const DisplaySettings: FC = () => { )} {t('settings.topic.show.time')} - setShowTopicTime(checked)} /> + setShowTopicTime(checked)} /> {t('settings.topic.pin_to_top')} - setPinTopicsToTop(checked)} /> + setPinTopicsToTop(checked)} /> diff --git a/src/renderer/src/pages/settings/GeneralSettings.tsx b/src/renderer/src/pages/settings/GeneralSettings.tsx index 20abd11b4b..fab07d15c8 100644 --- a/src/renderer/src/pages/settings/GeneralSettings.tsx +++ b/src/renderer/src/pages/settings/GeneralSettings.tsx @@ -1,6 +1,7 @@ import { InfoCircleOutlined } from '@ant-design/icons' import { RowFlex } from '@cherrystudio/ui' import { Flex } from '@cherrystudio/ui' +import { Switch } from '@cherrystudio/ui' import { useMultiplePreferences, usePreference } from '@data/hooks/usePreference' import Selector from '@renderer/components/Selector' import { InfoTooltip } from '@renderer/components/TooltipIcons' @@ -12,7 +13,7 @@ import { isValidProxyUrl } from '@renderer/utils' import { formatErrorMessage } from '@renderer/utils/error' import { defaultByPassRules, defaultLanguage } from '@shared/config/constant' import type { LanguageVarious } from '@shared/data/preference/preferenceTypes' -import { Input, Switch, Tooltip } from 'antd' +import { Input, Tooltip } from 'antd' import type { FC } from 'react' import { useState } from 'react' import { useTranslation } from 'react-i18next' @@ -260,12 +261,12 @@ const GeneralSettings: FC = () => { /> )} - + {t('settings.hardware_acceleration.title')} - + @@ -278,17 +279,26 @@ const GeneralSettings: FC = () => { - handleNotificationChange('assistant', v)} /> + handleNotificationChange('assistant', v)} + /> {t('settings.notification.backup')} - handleNotificationChange('backup', v)} /> + handleNotificationChange('backup', v)} + /> {t('settings.notification.knowledge_embed')} - handleNotificationChange('knowledge', v)} /> + handleNotificationChange('knowledge', v)} + /> @@ -296,12 +306,12 @@ const GeneralSettings: FC = () => { {t('settings.launch.onboot')} - updateLaunchOnBoot(checked)} /> + updateLaunchOnBoot(checked)} /> {t('settings.launch.totray')} - updateLaunchToTray(checked)} /> + updateLaunchToTray(checked)} /> @@ -309,12 +319,12 @@ const GeneralSettings: FC = () => { {t('settings.tray.show')} - updateTray(checked)} /> + updateTray(checked)} /> {t('settings.tray.onclose')} - updateTrayOnClose(checked)} /> + updateTrayOnClose(checked)} /> @@ -323,8 +333,8 @@ const GeneralSettings: FC = () => { {t('settings.privacy.enable_privacy_mode')} { + isSelected={enableDataCollection} + onValueChange={(v) => { setEnableDataCollection(v) window.api.config.set('enableDataCollection', v) }} @@ -339,7 +349,7 @@ const GeneralSettings: FC = () => { {t('settings.developer.enable_developer_mode')} - + diff --git a/src/renderer/src/pages/settings/MCPSettings/McpServerCard.tsx b/src/renderer/src/pages/settings/MCPSettings/McpServerCard.tsx index f7bc4fae2e..046a830d34 100644 --- a/src/renderer/src/pages/settings/MCPSettings/McpServerCard.tsx +++ b/src/renderer/src/pages/settings/MCPSettings/McpServerCard.tsx @@ -1,3 +1,4 @@ +import { Switch } from '@cherrystudio/ui' import { ErrorBoundary } from '@renderer/components/ErrorBoundary' import { DeleteIcon } from '@renderer/components/Icons' import GeneralPopup from '@renderer/components/Popups/GeneralPopup' @@ -5,7 +6,7 @@ import Scrollbar from '@renderer/components/Scrollbar' import { getMcpTypeLabel } from '@renderer/i18n/label' import type { MCPServer } from '@renderer/types' import { formatErrorMessage } from '@renderer/utils/error' -import { Alert, Button, Space, Switch, Tag, Tooltip, Typography } from 'antd' +import { Alert, Button, Space, Tag, Tooltip, Typography } from 'antd' import { CircleXIcon, Settings2, SquareArrowOutUpRight } from 'lucide-react' import type { FC } from 'react' import { useCallback } from 'react' @@ -132,11 +133,11 @@ const McpServerCard: FC = ({ e.stopPropagation()}>