parent
744a1fedba
commit
f7151bd066
@ -16,6 +16,8 @@ export default defineConfig({
|
||||
}
|
||||
},
|
||||
plugins: [react()],
|
||||
assetsInclude: ['**/*.md']
|
||||
server: {
|
||||
hmr: false
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@ -107,6 +107,7 @@ body {
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
color: var(--color-text);
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
overflow: hidden;
|
||||
background: transparent !important;
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
.markdown {
|
||||
color: var(--color-text);
|
||||
font-size: 15px;
|
||||
line-height: 1.6;
|
||||
user-select: text;
|
||||
word-break: break-word;
|
||||
|
||||
@ -39,7 +39,6 @@ const NavbarLeftContainer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
color: var(--color-text-1);
|
||||
`
|
||||
@ -49,7 +48,6 @@ const NavbarCenterContainer = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 ${isMac ? '20px' : '15px'};
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
color: var(--color-text-1);
|
||||
`
|
||||
|
||||
@ -27,7 +27,8 @@ const resources = {
|
||||
save: 'Save',
|
||||
footnotes: 'References',
|
||||
select: 'Select',
|
||||
search: 'Search'
|
||||
search: 'Search',
|
||||
default: 'Default'
|
||||
},
|
||||
button: {
|
||||
add: 'Add',
|
||||
@ -183,7 +184,8 @@ const resources = {
|
||||
'theme.title': 'Theme',
|
||||
'theme.dark': 'Dark',
|
||||
'theme.light': 'Light',
|
||||
'theme.auto': 'Auto'
|
||||
'theme.auto': 'Auto',
|
||||
'font_size.title': 'Message Font Size'
|
||||
},
|
||||
translate: {
|
||||
title: 'Translation',
|
||||
@ -241,7 +243,8 @@ const resources = {
|
||||
you: '用户',
|
||||
footnote: '引用内容',
|
||||
select: '选择',
|
||||
search: '搜索'
|
||||
search: '搜索',
|
||||
default: '默认'
|
||||
},
|
||||
button: {
|
||||
add: '添加',
|
||||
@ -336,7 +339,7 @@ const resources = {
|
||||
settings: {
|
||||
title: '设置',
|
||||
general: '常规设置',
|
||||
provider: '模型提供商',
|
||||
provider: '模型服务',
|
||||
model: '默认模型',
|
||||
assistant: '默认助手',
|
||||
about: '关于我们',
|
||||
@ -398,7 +401,8 @@ const resources = {
|
||||
'theme.title': '主题',
|
||||
'theme.dark': '深色主题',
|
||||
'theme.light': '浅色主题',
|
||||
'theme.auto': '跟随系统'
|
||||
'theme.auto': '跟随系统',
|
||||
'font_size.title': '消息字体大小'
|
||||
},
|
||||
translate: {
|
||||
title: '翻译',
|
||||
|
||||
@ -168,7 +168,6 @@ const AssistantItem = styled.div`
|
||||
`
|
||||
|
||||
const AssistantName = styled.div`
|
||||
font-size: 14px;
|
||||
color: var(--color-text);
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 1;
|
||||
|
||||
@ -39,7 +39,7 @@ const Inputbar: FC<Props> = ({ assistant, setActiveTopic }) => {
|
||||
const [text, setText] = useState(_text)
|
||||
const [inputFocus, setInputFocus] = useState(false)
|
||||
const { addTopic } = useAssistant(assistant.id)
|
||||
const { sendMessageShortcut, showInputEstimatedTokens } = useSettings()
|
||||
const { sendMessageShortcut, showInputEstimatedTokens, fontSize } = useSettings()
|
||||
const [expended, setExpend] = useState(false)
|
||||
const [estimateTokenCount, setEstimateTokenCount] = useState(0)
|
||||
const generating = useAppSelector((state) => state.runtime.generating)
|
||||
@ -230,6 +230,7 @@ const Inputbar: FC<Props> = ({ assistant, setActiveTopic }) => {
|
||||
styles={{ textarea: { paddingLeft: 0 } }}
|
||||
onFocus={() => setInputFocus(true)}
|
||||
onBlur={() => setInputFocus(false)}
|
||||
style={{ fontSize }}
|
||||
/>
|
||||
</Container>
|
||||
)
|
||||
|
||||
@ -38,7 +38,7 @@ const MessageItem: FC<Props> = ({ message, index, showMenu, onDeleteMessage }) =
|
||||
const avatar = useAvatar()
|
||||
const { t } = useTranslation()
|
||||
const { assistant, model, setModel } = useAssistant(message.assistantId)
|
||||
const { userName, showMessageDivider, messageFont } = useSettings()
|
||||
const { userName, showMessageDivider, messageFont, fontSize } = useSettings()
|
||||
const { generating } = useRuntime()
|
||||
const [copied, setCopied] = useState(false)
|
||||
|
||||
@ -135,7 +135,7 @@ const MessageItem: FC<Props> = ({ message, index, showMenu, onDeleteMessage }) =
|
||||
</UserWrap>
|
||||
</AvatarWrapper>
|
||||
</MessageHeader>
|
||||
<MessageContent style={{ fontFamily }}>
|
||||
<MessageContent style={{ fontFamily, fontSize }}>
|
||||
<MessageItem />
|
||||
<MessageFooter style={{ border: messageBorder }}>
|
||||
{showMenu && (
|
||||
|
||||
@ -143,7 +143,6 @@ const TopicListItem = styled.div`
|
||||
padding: 7px 10px;
|
||||
cursor: pointer;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
@ -4,10 +4,10 @@ import i18n from '@renderer/i18n'
|
||||
import LocalStorage from '@renderer/services/storage'
|
||||
import { useAppDispatch } from '@renderer/store'
|
||||
import { setAvatar } from '@renderer/store/runtime'
|
||||
import { setLanguage, setUserName, ThemeMode } from '@renderer/store/settings'
|
||||
import { setFontSize, setLanguage, setUserName, ThemeMode } from '@renderer/store/settings'
|
||||
import { setProxyUrl as _setProxyUrl } from '@renderer/store/settings'
|
||||
import { compressImage, isValidProxyUrl } from '@renderer/utils'
|
||||
import { Avatar, Input, Select, Upload } from 'antd'
|
||||
import { Avatar, Input, Select, Slider, Upload } from 'antd'
|
||||
import { FC, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -16,7 +16,8 @@ import { SettingContainer, SettingDivider, SettingRow, SettingRowTitle, SettingT
|
||||
|
||||
const GeneralSettings: FC = () => {
|
||||
const avatar = useAvatar()
|
||||
const { language, proxyUrl: storeProxyUrl, userName, theme, setTheme } = useSettings()
|
||||
const { language, proxyUrl: storeProxyUrl, userName, theme, setTheme, fontSize } = useSettings()
|
||||
const [fontSizeValue, setFontSizeValue] = useState(fontSize)
|
||||
const [proxyUrl, setProxyUrl] = useState<string | undefined>(storeProxyUrl)
|
||||
const dispatch = useAppDispatch()
|
||||
const { t } = useTranslation()
|
||||
@ -100,6 +101,27 @@ const GeneralSettings: FC = () => {
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitle>{t('settings.font_size.title')}</SettingRowTitle>
|
||||
<Slider
|
||||
style={{ width: 290 }}
|
||||
value={fontSizeValue}
|
||||
onChange={(value) => setFontSizeValue(value)}
|
||||
onChangeComplete={(value) => {
|
||||
dispatch(setFontSize(value))
|
||||
console.debug('set font size', value)
|
||||
}}
|
||||
min={12}
|
||||
max={18}
|
||||
step={1}
|
||||
marks={{
|
||||
12: <span style={{ fontSize: '12px' }}>A</span>,
|
||||
14: <span style={{ fontSize: '14px' }}>{t('common.default')}</span>,
|
||||
18: <span style={{ fontSize: '18px' }}>A</span>
|
||||
}}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitle>{t('settings.proxy.title')}</SettingRowTitle>
|
||||
<Input
|
||||
|
||||
@ -1,3 +1,10 @@
|
||||
import {
|
||||
CloudOutlined,
|
||||
CodeSandboxOutlined,
|
||||
InfoCircleOutlined,
|
||||
MessageOutlined,
|
||||
SettingOutlined
|
||||
} from '@ant-design/icons'
|
||||
import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar'
|
||||
import { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -24,19 +31,34 @@ const SettingsPage: FC = () => {
|
||||
<ContentContainer>
|
||||
<SettingMenus>
|
||||
<MenuItemLink to="/settings/provider">
|
||||
<MenuItem className={isRoute('/settings/provider')}>{t('settings.provider')}</MenuItem>
|
||||
<MenuItem className={isRoute('/settings/provider')}>
|
||||
<CloudOutlined />
|
||||
{t('settings.provider')}
|
||||
</MenuItem>
|
||||
</MenuItemLink>
|
||||
<MenuItemLink to="/settings/model">
|
||||
<MenuItem className={isRoute('/settings/model')}>{t('settings.model')}</MenuItem>
|
||||
<MenuItem className={isRoute('/settings/model')}>
|
||||
<CodeSandboxOutlined />
|
||||
{t('settings.model')}
|
||||
</MenuItem>
|
||||
</MenuItemLink>
|
||||
<MenuItemLink to="/settings/assistant">
|
||||
<MenuItem className={isRoute('/settings/assistant')}>{t('settings.assistant')}</MenuItem>
|
||||
<MenuItem className={isRoute('/settings/assistant')}>
|
||||
<MessageOutlined />
|
||||
{t('settings.assistant')}
|
||||
</MenuItem>
|
||||
</MenuItemLink>
|
||||
<MenuItemLink to="/settings/general">
|
||||
<MenuItem className={isRoute('/settings/general')}>{t('settings.general')}</MenuItem>
|
||||
<MenuItem className={isRoute('/settings/general')}>
|
||||
<SettingOutlined />
|
||||
{t('settings.general')}
|
||||
</MenuItem>
|
||||
</MenuItemLink>
|
||||
<MenuItemLink to="/settings/about">
|
||||
<MenuItem className={isRoute('/settings/about')}>{t('settings.about')}</MenuItem>
|
||||
<MenuItem className={isRoute('/settings/about')}>
|
||||
<InfoCircleOutlined />
|
||||
{t('settings.about')}
|
||||
</MenuItem>
|
||||
</MenuItemLink>
|
||||
</SettingMenus>
|
||||
<SettingContent>
|
||||
@ -81,13 +103,20 @@ const MenuItemLink = styled(Link)`
|
||||
`
|
||||
|
||||
const MenuItem = styled.li`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 6px 10px;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
border-radius: 5px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
transition: all 0.2s ease-in-out;
|
||||
.anticon {
|
||||
font-size: 16px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
&:hover {
|
||||
background: var(--color-primary-soft);
|
||||
}
|
||||
|
||||
@ -22,7 +22,7 @@ const persistedReducer = persistReducer(
|
||||
{
|
||||
key: 'cherry-studio',
|
||||
storage,
|
||||
version: 19,
|
||||
version: 20,
|
||||
blacklist: ['runtime'],
|
||||
migrate
|
||||
},
|
||||
|
||||
@ -287,6 +287,15 @@ const migrateConfig = {
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'20': (state: RootState) => {
|
||||
return {
|
||||
...state,
|
||||
settings: {
|
||||
...state.settings,
|
||||
fontSize: 14
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@ export interface SettingsState {
|
||||
messageFont: 'system' | 'serif'
|
||||
showInputEstimatedTokens: boolean
|
||||
theme: ThemeMode
|
||||
fontSize: number
|
||||
}
|
||||
|
||||
const initialState: SettingsState = {
|
||||
@ -31,7 +32,8 @@ const initialState: SettingsState = {
|
||||
showMessageDivider: false,
|
||||
messageFont: 'system',
|
||||
showInputEstimatedTokens: false,
|
||||
theme: ThemeMode.light
|
||||
theme: ThemeMode.light,
|
||||
fontSize: 14
|
||||
}
|
||||
|
||||
const settingsSlice = createSlice({
|
||||
@ -70,6 +72,9 @@ const settingsSlice = createSlice({
|
||||
},
|
||||
setTheme: (state, action: PayloadAction<ThemeMode>) => {
|
||||
state.theme = action.payload
|
||||
},
|
||||
setFontSize: (state, action: PayloadAction<number>) => {
|
||||
state.fontSize = action.payload
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -85,7 +90,8 @@ export const {
|
||||
setShowMessageDivider,
|
||||
setMessageFont,
|
||||
setShowInputEstimatedTokens,
|
||||
setTheme
|
||||
setTheme,
|
||||
setFontSize
|
||||
} = settingsSlice.actions
|
||||
|
||||
export default settingsSlice.reducer
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user