feat: add data settings
This commit is contained in:
parent
303a0e20a0
commit
90fec317e5
@ -188,6 +188,7 @@
|
|||||||
"settings": {
|
"settings": {
|
||||||
"title": "Settings",
|
"title": "Settings",
|
||||||
"general": "General Settings",
|
"general": "General Settings",
|
||||||
|
"data": "Data Settings",
|
||||||
"provider": "Model Provider",
|
"provider": "Model Provider",
|
||||||
"model": "Default Model",
|
"model": "Default Model",
|
||||||
"assistant": "Default Assistant",
|
"assistant": "Default Assistant",
|
||||||
@ -208,15 +209,15 @@
|
|||||||
"general.backup.button": "Backup",
|
"general.backup.button": "Backup",
|
||||||
"general.restore.button": "Restore",
|
"general.restore.button": "Restore",
|
||||||
"general.view_webdav_settings": "View WebDAV settings",
|
"general.view_webdav_settings": "View WebDAV settings",
|
||||||
"general.webdav.title": "WebDAV",
|
"data.webdav.title": "WebDAV",
|
||||||
"general.webdav.host": "WebDAV Host",
|
"data.webdav.host": "WebDAV Host",
|
||||||
"general.webdav.host.placeholder": "http://localhost:8080",
|
"data.webdav.host.placeholder": "http://localhost:8080",
|
||||||
"general.webdav.user": "WebDAV User",
|
"data.webdav.user": "WebDAV User",
|
||||||
"general.webdav.password": "WebDAV Password",
|
"data.webdav.password": "WebDAV Password",
|
||||||
"general.webdav.path": "WebDAV Path",
|
"data.webdav.path": "WebDAV Path",
|
||||||
"general.webdav.path.placeholder": "/backup",
|
"data.webdav.path.placeholder": "/backup",
|
||||||
"general.webdav.backup.button": "Backup to WebDAV",
|
"data.webdav.backup.button": "Backup to WebDAV",
|
||||||
"general.webdav.restore.button": "Restore from WebDAV",
|
"data.webdav.restore.button": "Restore from WebDAV",
|
||||||
"general.reset.title": "Data Reset",
|
"general.reset.title": "Data Reset",
|
||||||
"general.reset.button": "Reset",
|
"general.reset.button": "Reset",
|
||||||
"general.check_update_setting": "Check for updates",
|
"general.check_update_setting": "Check for updates",
|
||||||
|
|||||||
@ -188,6 +188,7 @@
|
|||||||
"settings": {
|
"settings": {
|
||||||
"title": "设置",
|
"title": "设置",
|
||||||
"general": "常规设置",
|
"general": "常规设置",
|
||||||
|
"data": "数据设置",
|
||||||
"provider": "模型服务",
|
"provider": "模型服务",
|
||||||
"model": "默认模型",
|
"model": "默认模型",
|
||||||
"assistant": "默认助手",
|
"assistant": "默认助手",
|
||||||
@ -210,15 +211,15 @@
|
|||||||
"general.reset.title": "重置数据",
|
"general.reset.title": "重置数据",
|
||||||
"general.reset.button": "重置",
|
"general.reset.button": "重置",
|
||||||
"general.view_webdav_settings": "查看 WebDAV 设置",
|
"general.view_webdav_settings": "查看 WebDAV 设置",
|
||||||
"general.webdav.title": "WebDAV",
|
"data.webdav.title": "WebDAV",
|
||||||
"general.webdav.host": "WebDAV 地址",
|
"data.webdav.host": "WebDAV 地址",
|
||||||
"general.webdav.host.placeholder": "http://localhost:8080",
|
"data.webdav.host.placeholder": "http://localhost:8080",
|
||||||
"general.webdav.user": "WebDAV 用户名",
|
"data.webdav.user": "WebDAV 用户名",
|
||||||
"general.webdav.password": "WebDAV 密码",
|
"data.webdav.password": "WebDAV 密码",
|
||||||
"general.webdav.path": "WebDAV 路径",
|
"data.webdav.path": "WebDAV 路径",
|
||||||
"general.webdav.path.placeholder": "/backup",
|
"data.webdav.path.placeholder": "/backup",
|
||||||
"general.webdav.backup.button": "备份到 WebDAV",
|
"data.webdav.backup.button": "备份到 WebDAV",
|
||||||
"general.webdav.restore.button": "从 WebDAV 恢复",
|
"data.webdav.restore.button": "从 WebDAV 恢复",
|
||||||
"general.check_update_setting": "更新设置",
|
"general.check_update_setting": "更新设置",
|
||||||
"general.manual_update_check": "手动检查更新",
|
"general.manual_update_check": "手动检查更新",
|
||||||
"general.auto_update_check": "自动检查更新",
|
"general.auto_update_check": "自动检查更新",
|
||||||
|
|||||||
@ -188,6 +188,7 @@
|
|||||||
"settings": {
|
"settings": {
|
||||||
"title": "設定",
|
"title": "設定",
|
||||||
"general": "一般設定",
|
"general": "一般設定",
|
||||||
|
"data": "數據設定",
|
||||||
"provider": "模型提供者",
|
"provider": "模型提供者",
|
||||||
"model": "預設模型",
|
"model": "預設模型",
|
||||||
"assistant": "預設助手",
|
"assistant": "預設助手",
|
||||||
@ -208,15 +209,15 @@
|
|||||||
"general.backup.button": "備份",
|
"general.backup.button": "備份",
|
||||||
"general.restore.button": "復原",
|
"general.restore.button": "復原",
|
||||||
"general.view_webdav_settings": "查看 WebDAV 設定",
|
"general.view_webdav_settings": "查看 WebDAV 設定",
|
||||||
"general.webdav.title": "WebDAV",
|
"data.webdav.title": "WebDAV",
|
||||||
"general.webdav.host": "WebDAV 主機位址",
|
"data.webdav.host": "WebDAV 主機位址",
|
||||||
"general.webdav.host.placeholder": "http://localhost:8080",
|
"data.webdav.host.placeholder": "http://localhost:8080",
|
||||||
"general.webdav.user": "WebDAV 使用者名稱",
|
"data.webdav.user": "WebDAV 使用者名稱",
|
||||||
"general.webdav.password": "WebDAV 密碼",
|
"data.webdav.password": "WebDAV 密碼",
|
||||||
"general.webdav.path": "WebDAV Path",
|
"data.webdav.path": "WebDAV Path",
|
||||||
"general.webdav.path.placeholder": "/backup",
|
"data.webdav.path.placeholder": "/backup",
|
||||||
"general.webdav.backup.button": "從 WebDAV 備份",
|
"data.webdav.backup.button": "從 WebDAV 備份",
|
||||||
"general.webdav.restore.button": "從 WebDAV 恢復",
|
"data.webdav.restore.button": "從 WebDAV 恢復",
|
||||||
"general.reset.title": "資料重置",
|
"general.reset.title": "資料重置",
|
||||||
"general.reset.button": "重置",
|
"general.reset.button": "重置",
|
||||||
"general.check_update_setting": "更新設定",
|
"general.check_update_setting": "更新設定",
|
||||||
|
|||||||
@ -0,0 +1,61 @@
|
|||||||
|
import { FolderOpenOutlined, SaveOutlined } from '@ant-design/icons'
|
||||||
|
import { HStack, VStack } from '@renderer/components/Layout'
|
||||||
|
import { backup, reset, restore } from '@renderer/services/backup'
|
||||||
|
import { Button } from 'antd'
|
||||||
|
import { FC } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { Link, Route, Routes } from 'react-router-dom'
|
||||||
|
|
||||||
|
import { SettingContainer, SettingDivider, SettingRow, SettingRowTitle, SettingTitle } from '..'
|
||||||
|
import WebDavSettings from './WebDavSettings'
|
||||||
|
|
||||||
|
const DataSettings: FC = () => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Routes>
|
||||||
|
<Route
|
||||||
|
path="/"
|
||||||
|
element={
|
||||||
|
<SettingContainer>
|
||||||
|
<SettingTitle>{t('settings.data')}</SettingTitle>
|
||||||
|
<SettingDivider />
|
||||||
|
<SettingRow style={{ minHeight: 32 }}>
|
||||||
|
<SettingRowTitle>{t('settings.data.webdav.title')}</SettingRowTitle>
|
||||||
|
<VStack gap="5px">
|
||||||
|
<Link to="/settings/data/webdav" style={{ color: 'var(--color-text-2)' }}>
|
||||||
|
{t('settings.general.view_webdav_settings')}
|
||||||
|
</Link>
|
||||||
|
</VStack>
|
||||||
|
</SettingRow>
|
||||||
|
<SettingDivider />
|
||||||
|
<SettingRow>
|
||||||
|
<SettingRowTitle>{t('settings.general.backup.title')}</SettingRowTitle>
|
||||||
|
<HStack gap="5px" justifyContent="space-between">
|
||||||
|
<Button onClick={backup} icon={<SaveOutlined />}>
|
||||||
|
{t('settings.general.backup.button')}
|
||||||
|
</Button>
|
||||||
|
<Button onClick={restore} icon={<FolderOpenOutlined />}>
|
||||||
|
{t('settings.general.restore.button')}
|
||||||
|
</Button>
|
||||||
|
</HStack>
|
||||||
|
</SettingRow>
|
||||||
|
<SettingDivider />
|
||||||
|
<SettingRow>
|
||||||
|
<SettingRowTitle>{t('settings.general.reset.title')}</SettingRowTitle>
|
||||||
|
<HStack gap="5px">
|
||||||
|
<Button onClick={reset} danger>
|
||||||
|
{t('settings.general.reset.button')}
|
||||||
|
</Button>
|
||||||
|
</HStack>
|
||||||
|
</SettingRow>
|
||||||
|
<SettingDivider />
|
||||||
|
</SettingContainer>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Route path="webdav" element={<WebDavSettings />} />
|
||||||
|
</Routes>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DataSettings
|
||||||
@ -62,20 +62,20 @@ const WebDavSettings: FC = () => {
|
|||||||
<Breadcrumb
|
<Breadcrumb
|
||||||
items={[
|
items={[
|
||||||
{
|
{
|
||||||
title: t('settings.general.title'),
|
title: t('settings.data'),
|
||||||
href: '#/settings/general'
|
href: '#/settings/data'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('settings.general.webdav.title')
|
title: t('settings.data.webdav.title')
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
<SettingTitle style={{ marginTop: 20 }}>{t('settings.general.webdav.title')}</SettingTitle>
|
<SettingTitle style={{ marginTop: 20 }}>{t('settings.data.webdav.title')}</SettingTitle>
|
||||||
<SettingDivider />
|
<SettingDivider />
|
||||||
<SettingRow>
|
<SettingRow>
|
||||||
<SettingRowTitle>{t('settings.general.webdav.host')}</SettingRowTitle>
|
<SettingRowTitle>{t('settings.data.webdav.host')}</SettingRowTitle>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t('settings.general.webdav.host.placeholder')}
|
placeholder={t('settings.data.webdav.host.placeholder')}
|
||||||
value={webdavHost}
|
value={webdavHost}
|
||||||
onChange={(e) => setWebdavHost(e.target.value)}
|
onChange={(e) => setWebdavHost(e.target.value)}
|
||||||
style={{ width: 250 }}
|
style={{ width: 250 }}
|
||||||
@ -85,9 +85,9 @@ const WebDavSettings: FC = () => {
|
|||||||
</SettingRow>
|
</SettingRow>
|
||||||
<SettingDivider />
|
<SettingDivider />
|
||||||
<SettingRow>
|
<SettingRow>
|
||||||
<SettingRowTitle>{t('settings.general.webdav.user')}</SettingRowTitle>
|
<SettingRowTitle>{t('settings.data.webdav.user')}</SettingRowTitle>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t('settings.general.webdav.user')}
|
placeholder={t('settings.data.webdav.user')}
|
||||||
value={webdavUser}
|
value={webdavUser}
|
||||||
onChange={(e) => setWebdavUser(e.target.value)}
|
onChange={(e) => setWebdavUser(e.target.value)}
|
||||||
style={{ width: 250 }}
|
style={{ width: 250 }}
|
||||||
@ -96,9 +96,9 @@ const WebDavSettings: FC = () => {
|
|||||||
</SettingRow>
|
</SettingRow>
|
||||||
<SettingDivider />
|
<SettingDivider />
|
||||||
<SettingRow>
|
<SettingRow>
|
||||||
<SettingRowTitle>{t('settings.general.webdav.password')}</SettingRowTitle>
|
<SettingRowTitle>{t('settings.data.webdav.password')}</SettingRowTitle>
|
||||||
<Input.Password
|
<Input.Password
|
||||||
placeholder={t('settings.general.webdav.password')}
|
placeholder={t('settings.data.webdav.password')}
|
||||||
value={webdavPass}
|
value={webdavPass}
|
||||||
onChange={(e) => setWebdavPass(e.target.value)}
|
onChange={(e) => setWebdavPass(e.target.value)}
|
||||||
style={{ width: 250 }}
|
style={{ width: 250 }}
|
||||||
@ -107,9 +107,9 @@ const WebDavSettings: FC = () => {
|
|||||||
</SettingRow>
|
</SettingRow>
|
||||||
<SettingDivider />
|
<SettingDivider />
|
||||||
<SettingRow>
|
<SettingRow>
|
||||||
<SettingRowTitle>{t('settings.general.webdav.path')}</SettingRowTitle>
|
<SettingRowTitle>{t('settings.data.webdav.path')}</SettingRowTitle>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t('settings.general.webdav.path.placeholder')}
|
placeholder={t('settings.data.webdav.path.placeholder')}
|
||||||
value={webdavPath}
|
value={webdavPath}
|
||||||
onChange={(e) => setWebdavPath(e.target.value)}
|
onChange={(e) => setWebdavPath(e.target.value)}
|
||||||
style={{ width: 250 }}
|
style={{ width: 250 }}
|
||||||
@ -122,10 +122,10 @@ const WebDavSettings: FC = () => {
|
|||||||
<HStack gap="5px" justifyContent="space-between">
|
<HStack gap="5px" justifyContent="space-between">
|
||||||
{/* 添加 在线备份 在线还原 按钮 */}
|
{/* 添加 在线备份 在线还原 按钮 */}
|
||||||
<Button onClick={onBackup} icon={<SaveOutlined />} loading={backuping}>
|
<Button onClick={onBackup} icon={<SaveOutlined />} loading={backuping}>
|
||||||
{t('settings.general.webdav.backup.button')}
|
{t('settings.data.webdav.backup.button')}
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={onRestore} icon={<FolderOpenOutlined />} loading={restoring}>
|
<Button onClick={onRestore} icon={<FolderOpenOutlined />} loading={restoring}>
|
||||||
{t('settings.general.webdav.restore.button')}
|
{t('settings.data.webdav.restore.button')}
|
||||||
</Button>
|
</Button>
|
||||||
</HStack>
|
</HStack>
|
||||||
</SettingRow>
|
</SettingRow>
|
||||||
152
src/renderer/src/pages/settings/GeneralSettings.tsx
Normal file
152
src/renderer/src/pages/settings/GeneralSettings.tsx
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
import { isMac } from '@renderer/config/constant'
|
||||||
|
import { useSettings } from '@renderer/hooks/useSettings'
|
||||||
|
import i18n from '@renderer/i18n'
|
||||||
|
import { useAppDispatch } from '@renderer/store'
|
||||||
|
import { setClickAssistantToShowTopic, setLanguage, setManualUpdateCheck } from '@renderer/store/settings'
|
||||||
|
import { setProxyUrl as _setProxyUrl } from '@renderer/store/settings'
|
||||||
|
import { ThemeMode } from '@renderer/types'
|
||||||
|
import { isValidProxyUrl } from '@renderer/utils'
|
||||||
|
import { Input, Select, Switch } from 'antd'
|
||||||
|
import { FC, useState } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
|
import { SettingContainer, SettingDivider, SettingRow, SettingRowTitle, SettingTitle } from '.'
|
||||||
|
|
||||||
|
const GeneralSettings: FC = () => {
|
||||||
|
const {
|
||||||
|
language,
|
||||||
|
proxyUrl: storeProxyUrl,
|
||||||
|
theme,
|
||||||
|
windowStyle,
|
||||||
|
topicPosition,
|
||||||
|
clickAssistantToShowTopic,
|
||||||
|
manualUpdateCheck,
|
||||||
|
setTheme,
|
||||||
|
setWindowStyle,
|
||||||
|
setTopicPosition
|
||||||
|
} = useSettings()
|
||||||
|
const [proxyUrl, setProxyUrl] = useState<string | undefined>(storeProxyUrl)
|
||||||
|
|
||||||
|
const dispatch = useAppDispatch()
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
|
const onSelectLanguage = (value: string) => {
|
||||||
|
dispatch(setLanguage(value))
|
||||||
|
localStorage.setItem('language', value)
|
||||||
|
i18n.changeLanguage(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
const onSetProxyUrl = () => {
|
||||||
|
if (proxyUrl && !isValidProxyUrl(proxyUrl)) {
|
||||||
|
window.message.error({ content: t('message.error.invalid.proxy.url'), key: 'proxy-error' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(_setProxyUrl(proxyUrl))
|
||||||
|
window.api.setProxy(proxyUrl)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SettingContainer>
|
||||||
|
<SettingTitle>{t('settings.general.title')}</SettingTitle>
|
||||||
|
<SettingDivider />
|
||||||
|
<SettingRow>
|
||||||
|
<SettingRowTitle>{t('common.language')}</SettingRowTitle>
|
||||||
|
<Select
|
||||||
|
defaultValue={language || 'en-US'}
|
||||||
|
style={{ width: 180 }}
|
||||||
|
onChange={onSelectLanguage}
|
||||||
|
options={[
|
||||||
|
{ value: 'zh-CN', label: '中文' },
|
||||||
|
{ value: 'zh-TW', label: '中文(繁体)' },
|
||||||
|
{ value: 'en-US', label: 'English' }
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</SettingRow>
|
||||||
|
<SettingDivider />
|
||||||
|
<SettingRow>
|
||||||
|
<SettingRowTitle>{t('settings.theme.title')}</SettingRowTitle>
|
||||||
|
<Select
|
||||||
|
defaultValue={theme}
|
||||||
|
style={{ width: 180 }}
|
||||||
|
onChange={setTheme}
|
||||||
|
options={[
|
||||||
|
{ value: ThemeMode.light, label: t('settings.theme.light') },
|
||||||
|
{ value: ThemeMode.dark, label: t('settings.theme.dark') },
|
||||||
|
{ value: ThemeMode.auto, label: t('settings.theme.auto') }
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</SettingRow>
|
||||||
|
{isMac && (
|
||||||
|
<>
|
||||||
|
<SettingDivider />
|
||||||
|
<SettingRow>
|
||||||
|
<SettingRowTitle>{t('settings.theme.window.style.title')}</SettingRowTitle>
|
||||||
|
<Select
|
||||||
|
defaultValue={windowStyle || 'opaque'}
|
||||||
|
style={{ width: 180 }}
|
||||||
|
onChange={setWindowStyle}
|
||||||
|
options={[
|
||||||
|
{ value: 'transparent', label: t('settings.theme.window.style.transparent') },
|
||||||
|
{ value: 'opaque', label: t('settings.theme.window.style.opaque') }
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</SettingRow>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<SettingDivider />
|
||||||
|
<SettingRow>
|
||||||
|
<SettingRowTitle>{t('settings.general.check_update_setting')}</SettingRowTitle>
|
||||||
|
<Select
|
||||||
|
defaultValue={manualUpdateCheck ?? false}
|
||||||
|
style={{ width: 180 }}
|
||||||
|
onChange={(v) => dispatch(setManualUpdateCheck(v))}
|
||||||
|
options={[
|
||||||
|
{ value: false, label: t('settings.general.auto_update_check') },
|
||||||
|
{ value: true, label: t('settings.general.manual_update_check') }
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</SettingRow>
|
||||||
|
<SettingDivider />
|
||||||
|
<SettingRow>
|
||||||
|
<SettingRowTitle>{t('settings.proxy.title')}</SettingRowTitle>
|
||||||
|
<Input
|
||||||
|
placeholder="socks5://127.0.0.1:6153"
|
||||||
|
value={proxyUrl}
|
||||||
|
onChange={(e) => setProxyUrl(e.target.value)}
|
||||||
|
style={{ width: 180 }}
|
||||||
|
onBlur={() => onSetProxyUrl()}
|
||||||
|
type="url"
|
||||||
|
/>
|
||||||
|
</SettingRow>
|
||||||
|
<SettingDivider />
|
||||||
|
<SettingRow>
|
||||||
|
<SettingRowTitle>{t('settings.topic.position')}</SettingRowTitle>
|
||||||
|
<Select
|
||||||
|
defaultValue={topicPosition || 'right'}
|
||||||
|
style={{ width: 180 }}
|
||||||
|
onChange={setTopicPosition}
|
||||||
|
options={[
|
||||||
|
{ value: 'left', label: t('settings.topic.position.left') },
|
||||||
|
{ value: 'right', label: t('settings.topic.position.right') }
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</SettingRow>
|
||||||
|
<SettingDivider />
|
||||||
|
{topicPosition === 'left' && (
|
||||||
|
<>
|
||||||
|
<SettingRow style={{ minHeight: 32 }}>
|
||||||
|
<SettingRowTitle>{t('settings.advanced.click_assistant_switch_to_topics')}</SettingRowTitle>
|
||||||
|
<Switch
|
||||||
|
checked={clickAssistantToShowTopic}
|
||||||
|
onChange={(checked) => dispatch(setClickAssistantToShowTopic(checked))}
|
||||||
|
/>
|
||||||
|
</SettingRow>
|
||||||
|
<SettingDivider />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</SettingContainer>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GeneralSettings
|
||||||
@ -1,195 +0,0 @@
|
|||||||
import { FolderOpenOutlined, SaveOutlined } from '@ant-design/icons'
|
|
||||||
import { HStack, VStack } from '@renderer/components/Layout'
|
|
||||||
import { isMac } from '@renderer/config/constant'
|
|
||||||
import { useSettings } from '@renderer/hooks/useSettings'
|
|
||||||
import i18n from '@renderer/i18n'
|
|
||||||
import { backup, reset, restore } from '@renderer/services/backup'
|
|
||||||
import { useAppDispatch } from '@renderer/store'
|
|
||||||
import { setClickAssistantToShowTopic, setLanguage, setManualUpdateCheck } from '@renderer/store/settings'
|
|
||||||
import { setProxyUrl as _setProxyUrl } from '@renderer/store/settings'
|
|
||||||
import { ThemeMode } from '@renderer/types'
|
|
||||||
import { isValidProxyUrl } from '@renderer/utils'
|
|
||||||
import { Button, Input, Select, Switch } from 'antd'
|
|
||||||
import { FC, useState } from 'react'
|
|
||||||
import { useTranslation } from 'react-i18next'
|
|
||||||
import { Link, Route, Routes } from 'react-router-dom'
|
|
||||||
|
|
||||||
import { SettingContainer, SettingDivider, SettingRow, SettingRowTitle, SettingTitle } from '..'
|
|
||||||
import WebDavSettings from './WebDavSettings'
|
|
||||||
|
|
||||||
const GeneralSettings: FC = () => {
|
|
||||||
const {
|
|
||||||
language,
|
|
||||||
proxyUrl: storeProxyUrl,
|
|
||||||
theme,
|
|
||||||
windowStyle,
|
|
||||||
topicPosition,
|
|
||||||
clickAssistantToShowTopic,
|
|
||||||
manualUpdateCheck,
|
|
||||||
setTheme,
|
|
||||||
setWindowStyle,
|
|
||||||
setTopicPosition
|
|
||||||
} = useSettings()
|
|
||||||
const [proxyUrl, setProxyUrl] = useState<string | undefined>(storeProxyUrl)
|
|
||||||
|
|
||||||
const dispatch = useAppDispatch()
|
|
||||||
const { t } = useTranslation()
|
|
||||||
|
|
||||||
const onSelectLanguage = (value: string) => {
|
|
||||||
dispatch(setLanguage(value))
|
|
||||||
localStorage.setItem('language', value)
|
|
||||||
i18n.changeLanguage(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
const onSetProxyUrl = () => {
|
|
||||||
if (proxyUrl && !isValidProxyUrl(proxyUrl)) {
|
|
||||||
window.message.error({ content: t('message.error.invalid.proxy.url'), key: 'proxy-error' })
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatch(_setProxyUrl(proxyUrl))
|
|
||||||
window.api.setProxy(proxyUrl)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Routes>
|
|
||||||
<Route
|
|
||||||
path="/"
|
|
||||||
element={
|
|
||||||
<SettingContainer>
|
|
||||||
<SettingTitle>{t('settings.general.title')}</SettingTitle>
|
|
||||||
<SettingDivider />
|
|
||||||
<SettingRow>
|
|
||||||
<SettingRowTitle>{t('common.language')}</SettingRowTitle>
|
|
||||||
<Select
|
|
||||||
defaultValue={language || 'en-US'}
|
|
||||||
style={{ width: 180 }}
|
|
||||||
onChange={onSelectLanguage}
|
|
||||||
options={[
|
|
||||||
{ value: 'zh-CN', label: '中文' },
|
|
||||||
{ value: 'zh-TW', label: '中文(繁体)' },
|
|
||||||
{ value: 'en-US', label: 'English' }
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</SettingRow>
|
|
||||||
<SettingDivider />
|
|
||||||
<SettingRow>
|
|
||||||
<SettingRowTitle>{t('settings.theme.title')}</SettingRowTitle>
|
|
||||||
<Select
|
|
||||||
defaultValue={theme}
|
|
||||||
style={{ width: 180 }}
|
|
||||||
onChange={setTheme}
|
|
||||||
options={[
|
|
||||||
{ value: ThemeMode.light, label: t('settings.theme.light') },
|
|
||||||
{ value: ThemeMode.dark, label: t('settings.theme.dark') },
|
|
||||||
{ value: ThemeMode.auto, label: t('settings.theme.auto') }
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</SettingRow>
|
|
||||||
{isMac && (
|
|
||||||
<>
|
|
||||||
<SettingDivider />
|
|
||||||
<SettingRow>
|
|
||||||
<SettingRowTitle>{t('settings.theme.window.style.title')}</SettingRowTitle>
|
|
||||||
<Select
|
|
||||||
defaultValue={windowStyle || 'opaque'}
|
|
||||||
style={{ width: 180 }}
|
|
||||||
onChange={setWindowStyle}
|
|
||||||
options={[
|
|
||||||
{ value: 'transparent', label: t('settings.theme.window.style.transparent') },
|
|
||||||
{ value: 'opaque', label: t('settings.theme.window.style.opaque') }
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</SettingRow>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
<SettingDivider />
|
|
||||||
<SettingRow>
|
|
||||||
<SettingRowTitle>{t('settings.topic.position')}</SettingRowTitle>
|
|
||||||
<Select
|
|
||||||
defaultValue={topicPosition || 'right'}
|
|
||||||
style={{ width: 180 }}
|
|
||||||
onChange={setTopicPosition}
|
|
||||||
options={[
|
|
||||||
{ value: 'left', label: t('settings.topic.position.left') },
|
|
||||||
{ value: 'right', label: t('settings.topic.position.right') }
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</SettingRow>
|
|
||||||
<SettingDivider />
|
|
||||||
{topicPosition === 'left' && (
|
|
||||||
<>
|
|
||||||
<SettingRow style={{ minHeight: 32 }}>
|
|
||||||
<SettingRowTitle>{t('settings.advanced.click_assistant_switch_to_topics')}</SettingRowTitle>
|
|
||||||
<Switch
|
|
||||||
checked={clickAssistantToShowTopic}
|
|
||||||
onChange={(checked) => dispatch(setClickAssistantToShowTopic(checked))}
|
|
||||||
/>
|
|
||||||
</SettingRow>
|
|
||||||
<SettingDivider />
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
<SettingRow>
|
|
||||||
<SettingRowTitle>{t('settings.general.check_update_setting')}</SettingRowTitle>
|
|
||||||
<Select
|
|
||||||
defaultValue={manualUpdateCheck ?? false}
|
|
||||||
style={{ width: 180 }}
|
|
||||||
onChange={(v) => dispatch(setManualUpdateCheck(v))}
|
|
||||||
options={[
|
|
||||||
{ value: false, label: t('settings.general.auto_update_check') },
|
|
||||||
{ value: true, label: t('settings.general.manual_update_check') }
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</SettingRow>
|
|
||||||
<SettingDivider />
|
|
||||||
<SettingRow>
|
|
||||||
<SettingRowTitle>{t('settings.proxy.title')}</SettingRowTitle>
|
|
||||||
<Input
|
|
||||||
placeholder="socks5://127.0.0.1:6153"
|
|
||||||
value={proxyUrl}
|
|
||||||
onChange={(e) => setProxyUrl(e.target.value)}
|
|
||||||
style={{ width: 180 }}
|
|
||||||
onBlur={() => onSetProxyUrl()}
|
|
||||||
type="url"
|
|
||||||
/>
|
|
||||||
</SettingRow>
|
|
||||||
<SettingDivider />
|
|
||||||
<SettingRow style={{ minHeight: 32 }}>
|
|
||||||
<SettingRowTitle>{t('settings.general.webdav.title')}</SettingRowTitle>
|
|
||||||
<VStack gap="5px">
|
|
||||||
<Link to="/settings/general/webdav" style={{ color: 'var(--color-text-2)' }}>
|
|
||||||
{t('settings.general.view_webdav_settings')}
|
|
||||||
</Link>
|
|
||||||
</VStack>
|
|
||||||
</SettingRow>
|
|
||||||
<SettingDivider />
|
|
||||||
<SettingRow>
|
|
||||||
<SettingRowTitle>{t('settings.general.backup.title')}</SettingRowTitle>
|
|
||||||
<HStack gap="5px" justifyContent="space-between">
|
|
||||||
<Button onClick={backup} icon={<SaveOutlined />}>
|
|
||||||
{t('settings.general.backup.button')}
|
|
||||||
</Button>
|
|
||||||
<Button onClick={restore} icon={<FolderOpenOutlined />}>
|
|
||||||
{t('settings.general.restore.button')}
|
|
||||||
</Button>
|
|
||||||
</HStack>
|
|
||||||
</SettingRow>
|
|
||||||
<SettingDivider />
|
|
||||||
<SettingRow>
|
|
||||||
<SettingRowTitle>{t('settings.general.reset.title')}</SettingRowTitle>
|
|
||||||
<HStack gap="5px">
|
|
||||||
<Button onClick={reset} danger>
|
|
||||||
{t('settings.general.reset.button')}
|
|
||||||
</Button>
|
|
||||||
</HStack>
|
|
||||||
</SettingRow>
|
|
||||||
<SettingDivider />
|
|
||||||
</SettingContainer>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<Route path="webdav" element={<WebDavSettings />} />
|
|
||||||
</Routes>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default GeneralSettings
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
import { CloudOutlined, InfoCircleOutlined, MessageOutlined, SettingOutlined } from '@ant-design/icons'
|
import { CloudOutlined, InfoCircleOutlined, MessageOutlined, SaveOutlined, SettingOutlined } from '@ant-design/icons'
|
||||||
import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar'
|
import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar'
|
||||||
import { isLocalAi } from '@renderer/config/env'
|
import { isLocalAi } from '@renderer/config/env'
|
||||||
import { FC } from 'react'
|
import { FC } from 'react'
|
||||||
@ -8,7 +8,8 @@ import styled from 'styled-components'
|
|||||||
|
|
||||||
import AboutSettings from './AboutSettings'
|
import AboutSettings from './AboutSettings'
|
||||||
import AssistantSettings from './AssistantSettings'
|
import AssistantSettings from './AssistantSettings'
|
||||||
import GeneralSettings from './GeneralSettings/GeneralSettings'
|
import DataSettings from './DataSettings/DataSettings'
|
||||||
|
import GeneralSettings from './GeneralSettings'
|
||||||
import ModelSettings from './ModelSettings'
|
import ModelSettings from './ModelSettings'
|
||||||
import ProvidersList from './ProviderSettings'
|
import ProvidersList from './ProviderSettings'
|
||||||
|
|
||||||
@ -53,6 +54,12 @@ const SettingsPage: FC = () => {
|
|||||||
{t('settings.general')}
|
{t('settings.general')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</MenuItemLink>
|
</MenuItemLink>
|
||||||
|
<MenuItemLink to="/settings/data">
|
||||||
|
<MenuItem className={isRoute('/settings/data')}>
|
||||||
|
<SaveOutlined />
|
||||||
|
{t('settings.data')}
|
||||||
|
</MenuItem>
|
||||||
|
</MenuItemLink>
|
||||||
<MenuItemLink to="/settings/about">
|
<MenuItemLink to="/settings/about">
|
||||||
<MenuItem className={isRoute('/settings/about')}>
|
<MenuItem className={isRoute('/settings/about')}>
|
||||||
<InfoCircleOutlined />
|
<InfoCircleOutlined />
|
||||||
@ -66,6 +73,7 @@ const SettingsPage: FC = () => {
|
|||||||
<Route path="model" element={<ModelSettings />} />
|
<Route path="model" element={<ModelSettings />} />
|
||||||
<Route path="assistant" element={<AssistantSettings />} />
|
<Route path="assistant" element={<AssistantSettings />} />
|
||||||
<Route path="general/*" element={<GeneralSettings />} />
|
<Route path="general/*" element={<GeneralSettings />} />
|
||||||
|
<Route path="data/*" element={<DataSettings />} />
|
||||||
<Route path="about" element={<AboutSettings />} />
|
<Route path="about" element={<AboutSettings />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</SettingContent>
|
</SettingContent>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user