mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-10 23:59:45 +08:00
feat: new settings ui
This commit is contained in:
parent
335ce4963b
commit
0ec61e1c47
@ -51,42 +51,42 @@ const Sidebar: FC = () => {
|
|||||||
<AvatarImg src={avatar || UserAvatar} draggable={false} className="nodrag" onClick={onEditUser} />
|
<AvatarImg src={avatar || UserAvatar} draggable={false} className="nodrag" onClick={onEditUser} />
|
||||||
<MainMenus>
|
<MainMenus>
|
||||||
<Menus onClick={MinApp.onClose}>
|
<Menus onClick={MinApp.onClose}>
|
||||||
<Tooltip title={t('assistants.title')} mouseEnterDelay={0.5} placement="right">
|
<Tooltip title={t('assistants.title')} mouseEnterDelay={0.8} placement="right">
|
||||||
<StyledLink onClick={() => to('/')}>
|
<StyledLink onClick={() => to('/')}>
|
||||||
<Icon className={isRoute('/')}>
|
<Icon className={isRoute('/')}>
|
||||||
<i className="iconfont icon-chat" />
|
<i className="iconfont icon-chat" />
|
||||||
</Icon>
|
</Icon>
|
||||||
</StyledLink>
|
</StyledLink>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip title={t('agents.title')} mouseEnterDelay={0.5} placement="right">
|
<Tooltip title={t('agents.title')} mouseEnterDelay={0.8} placement="right">
|
||||||
<StyledLink onClick={() => to('/agents')}>
|
<StyledLink onClick={() => to('/agents')}>
|
||||||
<Icon className={isRoutes('/agents')}>
|
<Icon className={isRoutes('/agents')}>
|
||||||
<i className="iconfont icon-business-smart-assistant" />
|
<i className="iconfont icon-business-smart-assistant" />
|
||||||
</Icon>
|
</Icon>
|
||||||
</StyledLink>
|
</StyledLink>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip title={t('paintings.title')} mouseEnterDelay={0.5} placement="right">
|
<Tooltip title={t('paintings.title')} mouseEnterDelay={0.8} placement="right">
|
||||||
<StyledLink onClick={() => to('/paintings')}>
|
<StyledLink onClick={() => to('/paintings')}>
|
||||||
<Icon className={isRoute('/paintings')}>
|
<Icon className={isRoute('/paintings')}>
|
||||||
<PictureOutlined style={{ fontSize: 16 }} />
|
<PictureOutlined style={{ fontSize: 16 }} />
|
||||||
</Icon>
|
</Icon>
|
||||||
</StyledLink>
|
</StyledLink>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip title={t('translate.title')} mouseEnterDelay={0.5} placement="right">
|
<Tooltip title={t('translate.title')} mouseEnterDelay={0.8} placement="right">
|
||||||
<StyledLink onClick={() => to('/translate')}>
|
<StyledLink onClick={() => to('/translate')}>
|
||||||
<Icon className={isRoute('/translate')}>
|
<Icon className={isRoute('/translate')}>
|
||||||
<TranslationOutlined />
|
<TranslationOutlined />
|
||||||
</Icon>
|
</Icon>
|
||||||
</StyledLink>
|
</StyledLink>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip title={t('minapp.title')} mouseEnterDelay={0.5} placement="right">
|
<Tooltip title={t('minapp.title')} mouseEnterDelay={0.8} placement="right">
|
||||||
<StyledLink onClick={() => to('/apps')}>
|
<StyledLink onClick={() => to('/apps')}>
|
||||||
<Icon className={isRoute('/apps')}>
|
<Icon className={isRoute('/apps')}>
|
||||||
<i className="iconfont icon-appstore" />
|
<i className="iconfont icon-appstore" />
|
||||||
</Icon>
|
</Icon>
|
||||||
</StyledLink>
|
</StyledLink>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip title={t('files.title')} mouseEnterDelay={0.5} placement="right">
|
<Tooltip title={t('files.title')} mouseEnterDelay={0.8} placement="right">
|
||||||
<StyledLink onClick={() => to('/files')}>
|
<StyledLink onClick={() => to('/files')}>
|
||||||
<Icon className={isRoute('/files')}>
|
<Icon className={isRoute('/files')}>
|
||||||
<FolderOutlined />
|
<FolderOutlined />
|
||||||
@ -96,7 +96,7 @@ const Sidebar: FC = () => {
|
|||||||
</Menus>
|
</Menus>
|
||||||
</MainMenus>
|
</MainMenus>
|
||||||
<Menus onClick={MinApp.onClose}>
|
<Menus onClick={MinApp.onClose}>
|
||||||
<Tooltip title={t('settings.theme.title')} mouseEnterDelay={0.5} placement="right">
|
<Tooltip title={t('settings.theme.title')} mouseEnterDelay={0.8} placement="right">
|
||||||
<Icon onClick={() => toggleTheme()}>
|
<Icon onClick={() => toggleTheme()}>
|
||||||
{theme === 'dark' ? (
|
{theme === 'dark' ? (
|
||||||
<i className="iconfont icon-theme icon-dark1" />
|
<i className="iconfont icon-theme icon-dark1" />
|
||||||
@ -105,7 +105,7 @@ const Sidebar: FC = () => {
|
|||||||
)}
|
)}
|
||||||
</Icon>
|
</Icon>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip title={t('settings.title')} mouseEnterDelay={0.5} placement="right">
|
<Tooltip title={t('settings.title')} mouseEnterDelay={0.8} placement="right">
|
||||||
<StyledLink onClick={() => to(isLocalAi ? '/settings/assistant' : '/settings/provider')}>
|
<StyledLink onClick={() => to(isLocalAi ? '/settings/assistant' : '/settings/provider')}>
|
||||||
<Icon className={pathname.startsWith('/settings') ? 'active' : ''}>
|
<Icon className={pathname.startsWith('/settings') ? 'active' : ''}>
|
||||||
<i className="iconfont icon-setting" />
|
<i className="iconfont icon-setting" />
|
||||||
@ -183,7 +183,8 @@ const Icon = styled.div`
|
|||||||
background-color: var(--color-active);
|
background-color: var(--color-active);
|
||||||
.iconfont,
|
.iconfont,
|
||||||
.anticon {
|
.anticon {
|
||||||
color: var(--color-icon-white);
|
color: var(--color-primary);
|
||||||
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|||||||
@ -302,8 +302,11 @@
|
|||||||
"provider.api.url.preview": "Preview: {{url}}",
|
"provider.api.url.preview": "Preview: {{url}}",
|
||||||
"provider.api.url.tip": "Ending with / ignores v1, ending with # forces use of input address",
|
"provider.api.url.tip": "Ending with / ignores v1, ending with # forces use of input address",
|
||||||
"models.default_assistant_model": "Default Assistant Model",
|
"models.default_assistant_model": "Default Assistant Model",
|
||||||
|
"models.default_assistant_model_description": "Model used when creating a new assistant, if the assistant is not set, this model will be used",
|
||||||
"models.topic_naming_model": "Topic Naming Model",
|
"models.topic_naming_model": "Topic Naming Model",
|
||||||
|
"models.topic_naming_model_description": "Model used when automatically naming a new topic",
|
||||||
"models.translate_model": "Translate Model",
|
"models.translate_model": "Translate Model",
|
||||||
|
"models.translate_model_description": "Model used for translation service",
|
||||||
"models.add.add_model": "Add Model",
|
"models.add.add_model": "Add Model",
|
||||||
"models.add.model_id.placeholder": "Required e.g. gpt-3.5-turbo",
|
"models.add.model_id.placeholder": "Required e.g. gpt-3.5-turbo",
|
||||||
"models.add.model_id": "Model ID",
|
"models.add.model_id": "Model ID",
|
||||||
|
|||||||
@ -302,8 +302,11 @@
|
|||||||
"provider.api.url.preview": "Предпросмотр: {{url}}",
|
"provider.api.url.preview": "Предпросмотр: {{url}}",
|
||||||
"provider.api.url.tip": "Заканчивая на / игнорирует v1, заканчивая на # принудительно использует введенный адрес",
|
"provider.api.url.tip": "Заканчивая на / игнорирует v1, заканчивая на # принудительно использует введенный адрес",
|
||||||
"models.default_assistant_model": "Модель ассистента по умолчанию",
|
"models.default_assistant_model": "Модель ассистента по умолчанию",
|
||||||
|
"models.default_assistant_model_description": "Модель, используемая при создании нового ассистента, если ассистент не имеет настроенной модели, будет использоваться эта модель",
|
||||||
"models.topic_naming_model": "Модель именования топика",
|
"models.topic_naming_model": "Модель именования топика",
|
||||||
|
"models.topic_naming_model_description": "Модель, используемая при автоматическом именовании нового топика",
|
||||||
"models.translate_model": "Модель перевода",
|
"models.translate_model": "Модель перевода",
|
||||||
|
"models.translate_model_description": "Модель, используемая для сервиса перевода",
|
||||||
"models.add.add_model": "Добавить модель",
|
"models.add.add_model": "Добавить модель",
|
||||||
"models.add.model_id.placeholder": "Обязательно, например, gpt-3.5-turbo",
|
"models.add.model_id.placeholder": "Обязательно, например, gpt-3.5-turbo",
|
||||||
"models.add.model_id": "ID модели",
|
"models.add.model_id": "ID модели",
|
||||||
|
|||||||
@ -290,8 +290,11 @@
|
|||||||
"advanced.title": "高级设置",
|
"advanced.title": "高级设置",
|
||||||
"advanced.auto_switch_to_topics": "自动切换到话题",
|
"advanced.auto_switch_to_topics": "自动切换到话题",
|
||||||
"models.default_assistant_model": "默认助手模型",
|
"models.default_assistant_model": "默认助手模型",
|
||||||
|
"models.default_assistant_model_description": "创建新助手时使用的模型,如果助手未设置模型,则使用此模型",
|
||||||
"models.topic_naming_model": "话题命名模型",
|
"models.topic_naming_model": "话题命名模型",
|
||||||
|
"models.topic_naming_model_description": "自动命名新话题时使用的模型",
|
||||||
"models.translate_model": "翻译模型",
|
"models.translate_model": "翻译模型",
|
||||||
|
"models.translate_model_description": "翻译服务使用的模型",
|
||||||
"models.add.add_model": "添加模型",
|
"models.add.add_model": "添加模型",
|
||||||
"models.add.model_id.placeholder": "必填 例如 gpt-3.5-turbo",
|
"models.add.model_id.placeholder": "必填 例如 gpt-3.5-turbo",
|
||||||
"models.add.model_id": "模型 ID",
|
"models.add.model_id": "模型 ID",
|
||||||
|
|||||||
@ -290,8 +290,11 @@
|
|||||||
"advanced.title": "進階設定",
|
"advanced.title": "進階設定",
|
||||||
"advanced.auto_switch_to_topics": "自動切換到話題",
|
"advanced.auto_switch_to_topics": "自動切換到話題",
|
||||||
"models.default_assistant_model": "預設助手模型",
|
"models.default_assistant_model": "預設助手模型",
|
||||||
|
"models.default_assistant_model_description": "創建新助手時使用的模型,如果助手未設置模型,則使用此模型",
|
||||||
"models.topic_naming_model": "話題命名模型",
|
"models.topic_naming_model": "話題命名模型",
|
||||||
|
"models.topic_naming_model_description": "自動命名新話題時使用的模型",
|
||||||
"models.translate_model": "翻譯模型",
|
"models.translate_model": "翻譯模型",
|
||||||
|
"models.translate_model_description": "翻譯服務使用的模型",
|
||||||
"models.add.add_model": "添加模型",
|
"models.add.add_model": "添加模型",
|
||||||
"models.add.model_id.placeholder": "必填,例如 gpt-3.5-turbo",
|
"models.add.model_id.placeholder": "必填,例如 gpt-3.5-turbo",
|
||||||
"models.add.model_id": "模型 ID",
|
"models.add.model_id": "模型 ID",
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import { FileProtectOutlined, GlobalOutlined, MailOutlined, SoundOutlined } from
|
|||||||
import { HStack } from '@renderer/components/Layout'
|
import { HStack } from '@renderer/components/Layout'
|
||||||
import MinApp from '@renderer/components/MinApp'
|
import MinApp from '@renderer/components/MinApp'
|
||||||
import { APP_NAME, AppLogo } from '@renderer/config/env'
|
import { APP_NAME, AppLogo } from '@renderer/config/env'
|
||||||
|
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||||
import { useSettings } from '@renderer/hooks/useSettings'
|
import { useSettings } from '@renderer/hooks/useSettings'
|
||||||
import { useAppDispatch } from '@renderer/store'
|
import { useAppDispatch } from '@renderer/store'
|
||||||
import { setManualUpdateCheck } from '@renderer/store/settings'
|
import { setManualUpdateCheck } from '@renderer/store/settings'
|
||||||
@ -15,7 +16,7 @@ import { useTranslation } from 'react-i18next'
|
|||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
|
||||||
import { SettingContainer, SettingDivider, SettingRow, SettingTitle } from '.'
|
import { SettingContainer, SettingDivider, SettingGroup, SettingRow, SettingTitle } from '.'
|
||||||
|
|
||||||
const AboutSettings: FC = () => {
|
const AboutSettings: FC = () => {
|
||||||
const [version, setVersion] = useState('')
|
const [version, setVersion] = useState('')
|
||||||
@ -24,6 +25,7 @@ const AboutSettings: FC = () => {
|
|||||||
const [checkUpdateLoading, setCheckUpdateLoading] = useState(false)
|
const [checkUpdateLoading, setCheckUpdateLoading] = useState(false)
|
||||||
const [downloading, setDownloading] = useState(false)
|
const [downloading, setDownloading] = useState(false)
|
||||||
const { manualUpdateCheck } = useSettings()
|
const { manualUpdateCheck } = useSettings()
|
||||||
|
const { theme } = useTheme()
|
||||||
const dispatch = useAppDispatch()
|
const dispatch = useAppDispatch()
|
||||||
|
|
||||||
const onCheckUpdate = debounce(
|
const onCheckUpdate = debounce(
|
||||||
@ -104,102 +106,104 @@ const AboutSettings: FC = () => {
|
|||||||
}, [t])
|
}, [t])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SettingContainer>
|
<SettingContainer theme={theme}>
|
||||||
<SettingTitle>
|
<SettingGroup theme={theme}>
|
||||||
{t('settings.about.title')}
|
<SettingTitle>
|
||||||
<HStack alignItems="center">
|
{t('settings.about.title')}
|
||||||
<Link to="https://github.com/kangfenmao/cherry-studio">
|
<HStack alignItems="center">
|
||||||
<GithubOutlined style={{ marginRight: 4, color: 'var(--color-text)', fontSize: 20 }} />
|
<Link to="https://github.com/kangfenmao/cherry-studio">
|
||||||
</Link>
|
<GithubOutlined style={{ marginRight: 4, color: 'var(--color-text)', fontSize: 20 }} />
|
||||||
</HStack>
|
</Link>
|
||||||
</SettingTitle>
|
</HStack>
|
||||||
<SettingDivider />
|
</SettingTitle>
|
||||||
<AboutHeader>
|
<SettingDivider />
|
||||||
<Row align="middle">
|
<AboutHeader>
|
||||||
<AvatarWrapper onClick={() => onOpenWebsite('https://github.com/kangfenmao/cherry-studio')}>
|
<Row align="middle">
|
||||||
{percent > 0 && (
|
<AvatarWrapper onClick={() => onOpenWebsite('https://github.com/kangfenmao/cherry-studio')}>
|
||||||
<ProgressCircle
|
{percent > 0 && (
|
||||||
type="circle"
|
<ProgressCircle
|
||||||
size={84}
|
type="circle"
|
||||||
percent={percent}
|
size={84}
|
||||||
showInfo={false}
|
percent={percent}
|
||||||
strokeLinecap="butt"
|
showInfo={false}
|
||||||
strokeColor="#67ad5b"
|
strokeLinecap="butt"
|
||||||
/>
|
strokeColor="#67ad5b"
|
||||||
)}
|
/>
|
||||||
<Avatar src={AppLogo} size={80} style={{ minHeight: 80 }} />
|
)}
|
||||||
</AvatarWrapper>
|
<Avatar src={AppLogo} size={80} style={{ minHeight: 80 }} />
|
||||||
<VersionWrapper>
|
</AvatarWrapper>
|
||||||
<Title>{APP_NAME}</Title>
|
<VersionWrapper>
|
||||||
<Description>{t('settings.about.description')}</Description>
|
<Title>{APP_NAME}</Title>
|
||||||
<Tag
|
<Description>{t('settings.about.description')}</Description>
|
||||||
onClick={() => onOpenWebsite('https://github.com/kangfenmao/cherry-studio/releases')}
|
<Tag
|
||||||
color="cyan"
|
onClick={() => onOpenWebsite('https://github.com/kangfenmao/cherry-studio/releases')}
|
||||||
style={{ marginTop: 8, cursor: 'pointer' }}>
|
color="cyan"
|
||||||
v{version}
|
style={{ marginTop: 8, cursor: 'pointer' }}>
|
||||||
</Tag>
|
v{version}
|
||||||
</VersionWrapper>
|
</Tag>
|
||||||
</Row>
|
</VersionWrapper>
|
||||||
<CheckUpdateButton onClick={onCheckUpdate} loading={checkUpdateLoading}>
|
</Row>
|
||||||
{downloading ? t('settings.about.downloading') : t('settings.about.checkUpdate')}
|
<CheckUpdateButton onClick={onCheckUpdate} loading={checkUpdateLoading}>
|
||||||
</CheckUpdateButton>
|
{downloading ? t('settings.about.downloading') : t('settings.about.checkUpdate')}
|
||||||
</AboutHeader>
|
</CheckUpdateButton>
|
||||||
<SettingDivider />
|
</AboutHeader>
|
||||||
<SettingRow>
|
<SettingDivider />
|
||||||
<SettingRowTitle>{t('settings.general.manually_check_update.title')}</SettingRowTitle>
|
<SettingRow>
|
||||||
<Switch value={manualUpdateCheck} onChange={(v) => dispatch(setManualUpdateCheck(v))} />
|
<SettingRowTitle>{t('settings.general.manually_check_update.title')}</SettingRowTitle>
|
||||||
</SettingRow>
|
<Switch value={manualUpdateCheck} onChange={(v) => dispatch(setManualUpdateCheck(v))} />
|
||||||
<SettingDivider />
|
</SettingRow>
|
||||||
<SettingRow>
|
</SettingGroup>
|
||||||
<SettingRowTitle>
|
<SettingGroup theme={theme}>
|
||||||
<SoundOutlined />
|
<SettingRow>
|
||||||
{t('settings.about.releases.title')}
|
<SettingRowTitle>
|
||||||
</SettingRowTitle>
|
<SoundOutlined />
|
||||||
<Button
|
{t('settings.about.releases.title')}
|
||||||
onClick={() =>
|
</SettingRowTitle>
|
||||||
MinApp.start({
|
<Button
|
||||||
name: t('settings.about.releases.title'),
|
onClick={() =>
|
||||||
url: 'https://github.com/kangfenmao/cherry-studio/releases',
|
MinApp.start({
|
||||||
logo: AppLogo
|
name: t('settings.about.releases.title'),
|
||||||
})
|
url: 'https://github.com/kangfenmao/cherry-studio/releases',
|
||||||
}>
|
logo: AppLogo
|
||||||
{t('settings.about.releases.button')}
|
})
|
||||||
</Button>
|
}>
|
||||||
</SettingRow>
|
{t('settings.about.releases.button')}
|
||||||
<SettingDivider />
|
</Button>
|
||||||
<SettingRow>
|
</SettingRow>
|
||||||
<SettingRowTitle>
|
<SettingDivider />
|
||||||
<GlobalOutlined />
|
<SettingRow>
|
||||||
{t('settings.about.website.title')}
|
<SettingRowTitle>
|
||||||
</SettingRowTitle>
|
<GlobalOutlined />
|
||||||
<Button onClick={() => onOpenWebsite('https://cherry-ai.com')}>{t('settings.about.website.button')}</Button>
|
{t('settings.about.website.title')}
|
||||||
</SettingRow>
|
</SettingRowTitle>
|
||||||
<SettingDivider />
|
<Button onClick={() => onOpenWebsite('https://cherry-ai.com')}>{t('settings.about.website.button')}</Button>
|
||||||
<SettingRow>
|
</SettingRow>
|
||||||
<SettingRowTitle>
|
<SettingDivider />
|
||||||
<GithubOutlined />
|
<SettingRow>
|
||||||
{t('settings.about.feedback.title')}
|
<SettingRowTitle>
|
||||||
</SettingRowTitle>
|
<GithubOutlined />
|
||||||
<Button onClick={() => onOpenWebsite('https://github.com/kangfenmao/cherry-studio/issues/new')}>
|
{t('settings.about.feedback.title')}
|
||||||
{t('settings.about.feedback.button')}
|
</SettingRowTitle>
|
||||||
</Button>
|
<Button onClick={() => onOpenWebsite('https://github.com/kangfenmao/cherry-studio/issues/new')}>
|
||||||
</SettingRow>
|
{t('settings.about.feedback.button')}
|
||||||
<SettingDivider />
|
</Button>
|
||||||
<SettingRow>
|
</SettingRow>
|
||||||
<SettingRowTitle>
|
<SettingDivider />
|
||||||
<FileProtectOutlined />
|
<SettingRow>
|
||||||
{t('settings.about.license.title')}
|
<SettingRowTitle>
|
||||||
</SettingRowTitle>
|
<FileProtectOutlined />
|
||||||
<Button onClick={showLicense}>{t('settings.about.license.button')}</Button>
|
{t('settings.about.license.title')}
|
||||||
</SettingRow>
|
</SettingRowTitle>
|
||||||
<SettingDivider />
|
<Button onClick={showLicense}>{t('settings.about.license.button')}</Button>
|
||||||
<SettingRow>
|
</SettingRow>
|
||||||
<SettingRowTitle>
|
<SettingDivider />
|
||||||
<MailOutlined /> {t('settings.about.contact.title')}
|
<SettingRow>
|
||||||
</SettingRowTitle>
|
<SettingRowTitle>
|
||||||
<Button onClick={mailto}>{t('settings.about.contact.button')}</Button>
|
<MailOutlined /> {t('settings.about.contact.title')}
|
||||||
</SettingRow>
|
</SettingRowTitle>
|
||||||
<SettingDivider />
|
<Button onClick={mailto}>{t('settings.about.contact.button')}</Button>
|
||||||
|
</SettingRow>
|
||||||
|
</SettingGroup>
|
||||||
</SettingContainer>
|
</SettingContainer>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { QuestionCircleOutlined } from '@ant-design/icons'
|
|||||||
import { HStack } from '@renderer/components/Layout'
|
import { HStack } from '@renderer/components/Layout'
|
||||||
import { TopView } from '@renderer/components/TopView'
|
import { TopView } from '@renderer/components/TopView'
|
||||||
import { DEFAULT_CONTEXTCOUNT, DEFAULT_MAX_TOKENS, DEFAULT_TEMPERATURE } from '@renderer/config/constant'
|
import { DEFAULT_CONTEXTCOUNT, DEFAULT_MAX_TOKENS, DEFAULT_TEMPERATURE } from '@renderer/config/constant'
|
||||||
|
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||||
import { useDefaultAssistant } from '@renderer/hooks/useAssistant'
|
import { useDefaultAssistant } from '@renderer/hooks/useAssistant'
|
||||||
import { AssistantSettings as AssistantSettingsType } from '@renderer/types'
|
import { AssistantSettings as AssistantSettingsType } from '@renderer/types'
|
||||||
import { Button, Col, Input, InputNumber, Modal, Row, Slider, Switch, Tooltip } from 'antd'
|
import { Button, Col, Input, InputNumber, Modal, Row, Slider, Switch, Tooltip } from 'antd'
|
||||||
@ -18,6 +19,7 @@ const AssistantSettings: FC = () => {
|
|||||||
const [contextCount, setContextCount] = useState(defaultAssistant.settings?.contextCount ?? DEFAULT_CONTEXTCOUNT)
|
const [contextCount, setContextCount] = useState(defaultAssistant.settings?.contextCount ?? DEFAULT_CONTEXTCOUNT)
|
||||||
const [enableMaxTokens, setEnableMaxTokens] = useState(defaultAssistant?.settings?.enableMaxTokens ?? false)
|
const [enableMaxTokens, setEnableMaxTokens] = useState(defaultAssistant?.settings?.enableMaxTokens ?? false)
|
||||||
const [maxTokens, setMaxTokens] = useState(defaultAssistant?.settings?.maxTokens ?? 0)
|
const [maxTokens, setMaxTokens] = useState(defaultAssistant?.settings?.maxTokens ?? 0)
|
||||||
|
const { theme } = useTheme()
|
||||||
|
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
@ -67,7 +69,7 @@ const AssistantSettings: FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SettingContainer style={{ height: 'auto' }}>
|
<SettingContainer style={{ height: 'auto', background: 'transparent', padding: 0 }} theme={theme}>
|
||||||
<SettingSubtitle style={{ marginTop: 0 }}>{t('common.name')}</SettingSubtitle>
|
<SettingSubtitle style={{ marginTop: 0 }}>{t('common.name')}</SettingSubtitle>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t('common.assistant') + t('common.name')}
|
placeholder={t('common.assistant') + t('common.name')}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { FileSearchOutlined, FolderOpenOutlined, SaveOutlined } from '@ant-design/icons'
|
import { FileSearchOutlined, FolderOpenOutlined, SaveOutlined } from '@ant-design/icons'
|
||||||
import { HStack, VStack } from '@renderer/components/Layout'
|
import { HStack, VStack } from '@renderer/components/Layout'
|
||||||
|
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||||
import { backup, reset, restore } from '@renderer/services/BackupService'
|
import { backup, reset, restore } from '@renderer/services/BackupService'
|
||||||
import { AppInfo } from '@renderer/types'
|
import { AppInfo } from '@renderer/types'
|
||||||
import { Button, Typography } from 'antd'
|
import { Button, Typography } from 'antd'
|
||||||
@ -14,12 +15,14 @@ import WebDavSettings from './WebDavSettings'
|
|||||||
const DataSettings: FC = () => {
|
const DataSettings: FC = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const [appInfo, setAppInfo] = useState<AppInfo>()
|
const [appInfo, setAppInfo] = useState<AppInfo>()
|
||||||
|
const { theme } = useTheme()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.api.getAppInfo().then(setAppInfo)
|
window.api.getAppInfo().then(setAppInfo)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const handleOpenPath = (path: string) => {
|
const handleOpenPath = (path?: string) => {
|
||||||
|
if (!path) return
|
||||||
if (path?.endsWith('log')) {
|
if (path?.endsWith('log')) {
|
||||||
const dirPath = path.split(/[/\\]/).slice(0, -1).join('/')
|
const dirPath = path.split(/[/\\]/).slice(0, -1).join('/')
|
||||||
window.api.openPath(dirPath)
|
window.api.openPath(dirPath)
|
||||||
@ -29,8 +32,8 @@ const DataSettings: FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SettingContainer>
|
<SettingContainer theme={theme}>
|
||||||
<SettingGroup>
|
<SettingGroup theme={theme}>
|
||||||
<SettingTitle>{t('settings.data')}</SettingTitle>
|
<SettingTitle>{t('settings.data')}</SettingTitle>
|
||||||
<SettingDivider />
|
<SettingDivider />
|
||||||
<SettingRow>
|
<SettingRow>
|
||||||
@ -63,10 +66,10 @@ const DataSettings: FC = () => {
|
|||||||
</HStack>
|
</HStack>
|
||||||
</SettingRow>
|
</SettingRow>
|
||||||
</SettingGroup>
|
</SettingGroup>
|
||||||
<SettingGroup>
|
<SettingGroup theme={theme}>
|
||||||
<WebDavSettings />
|
<WebDavSettings />
|
||||||
</SettingGroup>
|
</SettingGroup>
|
||||||
<SettingGroup>
|
<SettingGroup theme={theme}>
|
||||||
<SettingTitle>{t('settings.data.title')}</SettingTitle>
|
<SettingTitle>{t('settings.data.title')}</SettingTitle>
|
||||||
<SettingDivider />
|
<SettingDivider />
|
||||||
<SettingRow>
|
<SettingRow>
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { isMac } from '@renderer/config/constant'
|
import { isMac } from '@renderer/config/constant'
|
||||||
|
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||||
import { useSettings } from '@renderer/hooks/useSettings'
|
import { useSettings } from '@renderer/hooks/useSettings'
|
||||||
import i18n from '@renderer/i18n'
|
import i18n from '@renderer/i18n'
|
||||||
import { useAppDispatch } from '@renderer/store'
|
import { useAppDispatch } from '@renderer/store'
|
||||||
@ -10,7 +11,7 @@ import { Input, Select, Space, Switch } from 'antd'
|
|||||||
import { FC, useState } from 'react'
|
import { FC, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
import { SettingContainer, SettingDivider, SettingRow, SettingRowTitle, SettingTitle } from '.'
|
import { SettingContainer, SettingDivider, SettingGroup, SettingRow, SettingRowTitle, SettingTitle } from '.'
|
||||||
|
|
||||||
const GeneralSettings: FC = () => {
|
const GeneralSettings: FC = () => {
|
||||||
const {
|
const {
|
||||||
@ -25,6 +26,7 @@ const GeneralSettings: FC = () => {
|
|||||||
proxyMode: storeProxyMode
|
proxyMode: storeProxyMode
|
||||||
} = useSettings()
|
} = useSettings()
|
||||||
const [proxyUrl, setProxyUrl] = useState<string | undefined>(storeProxyUrl)
|
const [proxyUrl, setProxyUrl] = useState<string | undefined>(storeProxyUrl)
|
||||||
|
const { theme: themeMode } = useTheme()
|
||||||
|
|
||||||
const updateTray = (value: boolean) => {
|
const updateTray = (value: boolean) => {
|
||||||
setTray(value)
|
setTray(value)
|
||||||
@ -76,82 +78,88 @@ const GeneralSettings: FC = () => {
|
|||||||
]
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SettingContainer>
|
<SettingContainer theme={themeMode}>
|
||||||
<SettingTitle>{t('settings.general.title')}</SettingTitle>
|
<SettingGroup theme={theme}>
|
||||||
<SettingDivider />
|
<SettingTitle>{t('settings.general.title')}</SettingTitle>
|
||||||
<SettingRow>
|
<SettingDivider />
|
||||||
<SettingRowTitle>{t('common.language')}</SettingRowTitle>
|
<SettingRow>
|
||||||
<Select defaultValue={language || 'en-US'} style={{ width: 180 }} onChange={onSelectLanguage}>
|
<SettingRowTitle>{t('common.language')}</SettingRowTitle>
|
||||||
{languagesOptions.map((lang) => (
|
<Select defaultValue={language || 'en-US'} style={{ width: 180 }} onChange={onSelectLanguage}>
|
||||||
<Select.Option key={lang.value} value={lang.value}>
|
{languagesOptions.map((lang) => (
|
||||||
<Space.Compact direction="horizontal" block>
|
<Select.Option key={lang.value} value={lang.value}>
|
||||||
<Space.Compact block>{lang.label}</Space.Compact>
|
<Space.Compact direction="horizontal" block>
|
||||||
<span role="img" aria-label={lang.flag}>
|
<Space.Compact block>{lang.label}</Space.Compact>
|
||||||
{lang.flag}
|
<span role="img" aria-label={lang.flag}>
|
||||||
</span>
|
{lang.flag}
|
||||||
</Space.Compact>
|
</span>
|
||||||
</Select.Option>
|
</Space.Compact>
|
||||||
))}
|
</Select.Option>
|
||||||
</Select>
|
))}
|
||||||
</SettingRow>
|
</Select>
|
||||||
<SettingDivider />
|
</SettingRow>
|
||||||
<SettingRow>
|
<SettingDivider />
|
||||||
<SettingRowTitle>{t('settings.theme.title')}</SettingRowTitle>
|
<SettingRow>
|
||||||
<Select
|
<SettingRowTitle>{t('settings.theme.title')}</SettingRowTitle>
|
||||||
defaultValue={theme}
|
<Select
|
||||||
style={{ width: 180 }}
|
defaultValue={theme}
|
||||||
onChange={setTheme}
|
style={{ width: 180 }}
|
||||||
options={[
|
onChange={setTheme}
|
||||||
{ value: ThemeMode.light, label: t('settings.theme.light') },
|
options={[
|
||||||
{ value: ThemeMode.dark, label: t('settings.theme.dark') },
|
{ value: ThemeMode.light, label: t('settings.theme.light') },
|
||||||
{ value: ThemeMode.auto, label: t('settings.theme.auto') }
|
{ value: ThemeMode.dark, label: t('settings.theme.dark') },
|
||||||
]}
|
{ value: ThemeMode.auto, label: t('settings.theme.auto') }
|
||||||
/>
|
]}
|
||||||
</SettingRow>
|
/>
|
||||||
{isMac && (
|
</SettingRow>
|
||||||
<>
|
{isMac && (
|
||||||
<SettingDivider />
|
<>
|
||||||
<SettingRow>
|
<SettingDivider />
|
||||||
<SettingRowTitle>{t('settings.theme.window.style.title')}</SettingRowTitle>
|
<SettingRow>
|
||||||
<Select
|
<SettingRowTitle>{t('settings.theme.window.style.title')}</SettingRowTitle>
|
||||||
defaultValue={windowStyle || 'opaque'}
|
<Select
|
||||||
style={{ width: 180 }}
|
defaultValue={windowStyle || 'opaque'}
|
||||||
onChange={setWindowStyle}
|
style={{ width: 180 }}
|
||||||
options={[
|
onChange={setWindowStyle}
|
||||||
{ value: 'transparent', label: t('settings.theme.window.style.transparent') },
|
options={[
|
||||||
{ value: 'opaque', label: t('settings.theme.window.style.opaque') }
|
{ value: 'transparent', label: t('settings.theme.window.style.transparent') },
|
||||||
]}
|
{ value: 'opaque', label: t('settings.theme.window.style.opaque') }
|
||||||
/>
|
]}
|
||||||
</SettingRow>
|
/>
|
||||||
</>
|
</SettingRow>
|
||||||
)}
|
</>
|
||||||
<SettingDivider />
|
)}
|
||||||
<SettingRow>
|
<SettingDivider />
|
||||||
<SettingRowTitle>{t('settings.proxy.mode.title')}</SettingRowTitle>
|
<SettingRow>
|
||||||
<Select value={storeProxyMode} style={{ width: 180 }} onChange={onProxyModeChange} options={proxyModeOptions} />
|
<SettingRowTitle>{t('settings.proxy.mode.title')}</SettingRowTitle>
|
||||||
</SettingRow>
|
<Select
|
||||||
{storeProxyMode === 'custom' && (
|
value={storeProxyMode}
|
||||||
<>
|
style={{ width: 180 }}
|
||||||
<SettingDivider />
|
onChange={onProxyModeChange}
|
||||||
<SettingRow>
|
options={proxyModeOptions}
|
||||||
<SettingRowTitle>{t('settings.proxy.title')}</SettingRowTitle>
|
/>
|
||||||
<Input
|
</SettingRow>
|
||||||
placeholder="socks5://127.0.0.1:6153"
|
{storeProxyMode === 'custom' && (
|
||||||
value={proxyUrl}
|
<>
|
||||||
onChange={(e) => setProxyUrl(e.target.value)}
|
<SettingDivider />
|
||||||
style={{ width: 180 }}
|
<SettingRow>
|
||||||
onBlur={() => onSetProxyUrl()}
|
<SettingRowTitle>{t('settings.proxy.title')}</SettingRowTitle>
|
||||||
type="url"
|
<Input
|
||||||
/>
|
placeholder="socks5://127.0.0.1:6153"
|
||||||
</SettingRow>
|
value={proxyUrl}
|
||||||
</>
|
onChange={(e) => setProxyUrl(e.target.value)}
|
||||||
)}
|
style={{ width: 180 }}
|
||||||
<SettingDivider />
|
onBlur={() => onSetProxyUrl()}
|
||||||
<SettingRow>
|
type="url"
|
||||||
<SettingRowTitle>{t('settings.tray.title')}</SettingRowTitle>
|
/>
|
||||||
<Switch checked={tray} onChange={(checked) => updateTray(checked)} />
|
</SettingRow>
|
||||||
</SettingRow>
|
</>
|
||||||
<SettingDivider />
|
)}
|
||||||
|
<SettingDivider />
|
||||||
|
<SettingRow>
|
||||||
|
<SettingRowTitle>{t('settings.tray.title')}</SettingRowTitle>
|
||||||
|
<Switch checked={tray} onChange={(checked) => updateTray(checked)} />
|
||||||
|
</SettingRow>
|
||||||
|
</SettingGroup>
|
||||||
</SettingContainer>
|
</SettingContainer>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { EditOutlined, MessageOutlined, SettingOutlined, TranslationOutlined } from '@ant-design/icons'
|
import { EditOutlined, MessageOutlined, SettingOutlined, TranslationOutlined } from '@ant-design/icons'
|
||||||
import { HStack } from '@renderer/components/Layout'
|
import { HStack } from '@renderer/components/Layout'
|
||||||
|
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||||
import { useDefaultModel } from '@renderer/hooks/useAssistant'
|
import { useDefaultModel } from '@renderer/hooks/useAssistant'
|
||||||
import { useProviders } from '@renderer/hooks/useProvider'
|
import { useProviders } from '@renderer/hooks/useProvider'
|
||||||
import { getModelUniqId, hasModel } from '@renderer/services/ModelService'
|
import { getModelUniqId, hasModel } from '@renderer/services/ModelService'
|
||||||
@ -9,7 +10,7 @@ import { find, sortBy } from 'lodash'
|
|||||||
import { FC, useMemo } from 'react'
|
import { FC, useMemo } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
import { SettingContainer, SettingDivider, SettingTitle } from '.'
|
import { SettingContainer, SettingDescription, SettingDivider, SettingGroup, SettingTitle } from '.'
|
||||||
import AssistantSettingsPopup from './AssistantSettings'
|
import AssistantSettingsPopup from './AssistantSettings'
|
||||||
|
|
||||||
const ModelSettings: FC = () => {
|
const ModelSettings: FC = () => {
|
||||||
@ -17,6 +18,7 @@ const ModelSettings: FC = () => {
|
|||||||
useDefaultModel()
|
useDefaultModel()
|
||||||
const { providers } = useProviders()
|
const { providers } = useProviders()
|
||||||
const allModels = providers.map((p) => p.models).flat()
|
const allModels = providers.map((p) => p.models).flat()
|
||||||
|
const { theme } = useTheme()
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
const selectOptions = providers
|
const selectOptions = providers
|
||||||
@ -46,57 +48,64 @@ const ModelSettings: FC = () => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SettingContainer>
|
<SettingContainer theme={theme}>
|
||||||
<SettingTitle>
|
<SettingGroup theme={theme}>
|
||||||
<div>
|
<SettingTitle>
|
||||||
<MessageOutlined style={iconStyle} />
|
<div>
|
||||||
{t('settings.models.default_assistant_model')}
|
<MessageOutlined style={iconStyle} />
|
||||||
</div>
|
{t('settings.models.default_assistant_model')}
|
||||||
</SettingTitle>
|
</div>
|
||||||
<SettingDivider />
|
</SettingTitle>
|
||||||
<HStack alignItems="center">
|
<SettingDivider />
|
||||||
|
<HStack alignItems="center">
|
||||||
|
<Select
|
||||||
|
value={defaultModelValue}
|
||||||
|
defaultValue={defaultModelValue}
|
||||||
|
style={{ width: 360 }}
|
||||||
|
onChange={(value) => setDefaultModel(find(allModels, JSON.parse(value)) as Model)}
|
||||||
|
options={selectOptions}
|
||||||
|
placeholder={t('settings.models.empty')}
|
||||||
|
/>
|
||||||
|
<Button icon={<SettingOutlined />} style={{ marginLeft: 8 }} onClick={() => AssistantSettingsPopup.show()} />
|
||||||
|
</HStack>
|
||||||
|
<SettingDescription>{t('settings.models.default_assistant_model_description')}</SettingDescription>
|
||||||
|
</SettingGroup>
|
||||||
|
<SettingGroup theme={theme}>
|
||||||
|
<SettingTitle>
|
||||||
|
<div>
|
||||||
|
<EditOutlined style={iconStyle} />
|
||||||
|
{t('settings.models.topic_naming_model')}
|
||||||
|
</div>
|
||||||
|
</SettingTitle>
|
||||||
|
<SettingDivider />
|
||||||
<Select
|
<Select
|
||||||
value={defaultModelValue}
|
value={defaultTopicNamingModel}
|
||||||
defaultValue={defaultModelValue}
|
defaultValue={defaultTopicNamingModel}
|
||||||
style={{ width: 360 }}
|
style={{ width: 360 }}
|
||||||
onChange={(value) => setDefaultModel(find(allModels, JSON.parse(value)) as Model)}
|
onChange={(value) => setTopicNamingModel(find(allModels, JSON.parse(value)) as Model)}
|
||||||
options={selectOptions}
|
options={selectOptions}
|
||||||
placeholder={t('settings.models.empty')}
|
placeholder={t('settings.models.empty')}
|
||||||
/>
|
/>
|
||||||
<Button icon={<SettingOutlined />} style={{ marginLeft: 8 }} onClick={() => AssistantSettingsPopup.show()} />
|
<SettingDescription>{t('settings.models.topic_naming_model_description')}</SettingDescription>
|
||||||
</HStack>
|
</SettingGroup>
|
||||||
<div style={{ height: 30 }} />
|
<SettingGroup theme={theme}>
|
||||||
<SettingTitle>
|
<SettingTitle>
|
||||||
<div>
|
<div>
|
||||||
<EditOutlined style={iconStyle} />
|
<TranslationOutlined style={iconStyle} />
|
||||||
{t('settings.models.topic_naming_model')}
|
{t('settings.models.translate_model')}
|
||||||
</div>
|
</div>
|
||||||
</SettingTitle>
|
</SettingTitle>
|
||||||
<SettingDivider />
|
<SettingDivider />
|
||||||
<Select
|
<Select
|
||||||
value={defaultTopicNamingModel}
|
value={defaultTranslateModel}
|
||||||
defaultValue={defaultTopicNamingModel}
|
defaultValue={defaultTranslateModel}
|
||||||
style={{ width: 360 }}
|
style={{ width: 360 }}
|
||||||
onChange={(value) => setTopicNamingModel(find(allModels, JSON.parse(value)) as Model)}
|
onChange={(value) => setTranslateModel(find(allModels, JSON.parse(value)) as Model)}
|
||||||
options={selectOptions}
|
options={selectOptions}
|
||||||
placeholder={t('settings.models.empty')}
|
placeholder={t('settings.models.empty')}
|
||||||
/>
|
/>
|
||||||
<div style={{ height: 30 }} />
|
<SettingDescription>{t('settings.models.translate_model_description')}</SettingDescription>
|
||||||
<SettingTitle>
|
</SettingGroup>
|
||||||
<div>
|
|
||||||
<TranslationOutlined style={iconStyle} />
|
|
||||||
{t('settings.models.translate_model')}
|
|
||||||
</div>
|
|
||||||
</SettingTitle>
|
|
||||||
<SettingDivider />
|
|
||||||
<Select
|
|
||||||
value={defaultTranslateModel}
|
|
||||||
defaultValue={defaultTranslateModel}
|
|
||||||
style={{ width: 360 }}
|
|
||||||
onChange={(value) => setTranslateModel(find(allModels, JSON.parse(value)) as Model)}
|
|
||||||
options={selectOptions}
|
|
||||||
placeholder={t('settings.models.empty')}
|
|
||||||
/>
|
|
||||||
</SettingContainer>
|
</SettingContainer>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -126,12 +126,7 @@ const ProviderSetting: FC<Props> = ({ provider: _provider }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SettingContainer
|
<SettingContainer theme={theme}>
|
||||||
style={
|
|
||||||
theme === 'dark'
|
|
||||||
? { backgroundColor: 'var(--color-background)' }
|
|
||||||
: { backgroundColor: 'var(--color-background-mute)' }
|
|
||||||
}>
|
|
||||||
<SettingTitle>
|
<SettingTitle>
|
||||||
<Flex align="center">
|
<Flex align="center">
|
||||||
<span>{provider.isSystem ? t(`provider.${provider.id}`) : provider.name}</span>
|
<span>{provider.isSystem ? t(`provider.${provider.id}`) : provider.name}</span>
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
import { isMac } from '@renderer/config/constant'
|
import { isMac } from '@renderer/config/constant'
|
||||||
|
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||||
import { Switch, Table as AntTable, Tag } from 'antd'
|
import { Switch, Table as AntTable, Tag } from 'antd'
|
||||||
import type { ColumnsType } from 'antd/es/table'
|
import type { ColumnsType } from 'antd/es/table'
|
||||||
import { FC } from 'react'
|
import { FC } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
|
||||||
import { SettingContainer, SettingDivider, SettingTitle } from '.'
|
import { SettingContainer, SettingDivider, SettingGroup, SettingTitle } from '.'
|
||||||
|
|
||||||
interface ShortcutItem {
|
interface ShortcutItem {
|
||||||
key: string
|
key: string
|
||||||
@ -16,6 +17,7 @@ interface ShortcutItem {
|
|||||||
|
|
||||||
const ShortcutSettings: FC = () => {
|
const ShortcutSettings: FC = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
const { theme } = useTheme()
|
||||||
|
|
||||||
const commandKey = isMac ? '⌘' : 'Ctrl'
|
const commandKey = isMac ? '⌘' : 'Ctrl'
|
||||||
|
|
||||||
@ -81,16 +83,18 @@ const ShortcutSettings: FC = () => {
|
|||||||
]
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SettingContainer>
|
<SettingContainer theme={theme}>
|
||||||
<SettingTitle>{t('settings.shortcuts.title')}</SettingTitle>
|
<SettingGroup theme={theme}>
|
||||||
<SettingDivider style={{ marginBottom: 0 }} />
|
<SettingTitle>{t('settings.shortcuts.title')}</SettingTitle>
|
||||||
<Table
|
<SettingDivider style={{ marginBottom: 0 }} />
|
||||||
columns={columns as ColumnsType<unknown>}
|
<Table
|
||||||
dataSource={shortcuts}
|
columns={columns as ColumnsType<unknown>}
|
||||||
pagination={false}
|
dataSource={shortcuts}
|
||||||
size="middle"
|
pagination={false}
|
||||||
showHeader={false}
|
size="middle"
|
||||||
/>
|
showHeader={false}
|
||||||
|
/>
|
||||||
|
</SettingGroup>
|
||||||
</SettingContainer>
|
</SettingContainer>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,15 +1,17 @@
|
|||||||
|
import { ThemeMode } from '@renderer/types'
|
||||||
import { Divider } from 'antd'
|
import { Divider } from 'antd'
|
||||||
import Link from 'antd/es/typography/Link'
|
import Link from 'antd/es/typography/Link'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
|
||||||
export const SettingContainer = styled.div`
|
export const SettingContainer = styled.div<{ theme?: ThemeMode }>`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
height: calc(100vh - var(--navbar-height));
|
height: calc(100vh - var(--navbar-height));
|
||||||
padding: 15px;
|
padding: 20px;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
font-family: Ubuntu;
|
font-family: Ubuntu;
|
||||||
|
background: ${(props) => (props.theme === 'dark' ? 'transparent' : 'var(--color-background-soft)')};
|
||||||
|
|
||||||
&::-webkit-scrollbar {
|
&::-webkit-scrollbar {
|
||||||
display: none;
|
display: none;
|
||||||
@ -22,7 +24,7 @@ export const SettingTitle = styled.div`
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
font-size: 16px;
|
font-size: 14px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
`
|
`
|
||||||
|
|
||||||
@ -34,6 +36,12 @@ export const SettingSubtitle = styled.div`
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
`
|
`
|
||||||
|
|
||||||
|
export const SettingDescription = styled.div`
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--color-text-3);
|
||||||
|
margin-top: 10px;
|
||||||
|
`
|
||||||
|
|
||||||
export const SettingDivider = styled(Divider)`
|
export const SettingDivider = styled(Divider)`
|
||||||
margin: 10px 0;
|
margin: 10px 0;
|
||||||
`
|
`
|
||||||
@ -70,9 +78,10 @@ export const SettingHelpLink = styled(Link)`
|
|||||||
padding: 0 5px;
|
padding: 0 5px;
|
||||||
`
|
`
|
||||||
|
|
||||||
export const SettingGroup = styled.div`
|
export const SettingGroup = styled.div<{ theme?: ThemeMode }>`
|
||||||
margin-bottom: 16px;
|
margin-bottom: 20px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
border: 0.5px solid var(--color-border);
|
border: 0.5px solid var(--color-border);
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
|
background: ${(props) => (props.theme === 'dark' ? 'var(--color-background-soft)' : 'var(--color-background)')};
|
||||||
`
|
`
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user