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