feat(settings): add messageFont setting
This commit is contained in:
parent
3625eefec4
commit
51f4653cde
@ -1,6 +1,5 @@
|
||||
.markdown {
|
||||
color: #f1f1f1;
|
||||
font-family: Georgia, Cambria, 'Times New Roman', Times, serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
user-select: text;
|
||||
|
||||
@ -32,7 +32,7 @@ const Sidebar: FC = () => {
|
||||
</Menus>
|
||||
</MainMenus>
|
||||
<Menus>
|
||||
<StyledLink to="/settings/provider">
|
||||
<StyledLink to="/settings/general">
|
||||
<Icon className={pathname.startsWith('/settings') ? 'active' : ''}>
|
||||
<i className="iconfont icon-setting"></i>
|
||||
</Icon>
|
||||
|
||||
@ -105,7 +105,9 @@ const resources = {
|
||||
assistant: 'Default Assistant',
|
||||
about: 'About & Feedback',
|
||||
'general.title': 'General Settings',
|
||||
'general.message.title': 'Message Settings',
|
||||
'general.message.divider': 'Show divider between messages',
|
||||
'general.message.use_serif_font': 'Use serif font',
|
||||
'general.user_name': 'User Name',
|
||||
'general.user_name.placeholder': 'Enter your name',
|
||||
'provider.api_key': 'API Key',
|
||||
@ -257,7 +259,9 @@ const resources = {
|
||||
'general.title': '常规设置',
|
||||
'general.user_name': '用户名',
|
||||
'general.user_name.placeholder': '请输入用户名',
|
||||
'general.message.title': '消息设置',
|
||||
'general.message.divider': '消息分割线',
|
||||
'general.message.use_serif_font': '使用衬线字体',
|
||||
'provider.api_key': 'API 密钥',
|
||||
'provider.check': '检查',
|
||||
'provider.get_api_key': '点击这里获取密钥',
|
||||
|
||||
@ -1,21 +1,20 @@
|
||||
import { Message } from '@renderer/types'
|
||||
import { Avatar, Tooltip } from 'antd'
|
||||
import { FC } from 'react'
|
||||
import styled from 'styled-components'
|
||||
import useAvatar from '@renderer/hooks/useAvatar'
|
||||
import { CopyOutlined, DeleteOutlined, EditOutlined } from '@ant-design/icons'
|
||||
import Markdown from 'react-markdown'
|
||||
import CodeBlock from './CodeBlock'
|
||||
import { EVENT_NAMES, EventEmitter } from '@renderer/services/event'
|
||||
import { getModelLogo } from '@renderer/config/provider'
|
||||
import { CopyOutlined, DeleteOutlined, EditOutlined, SyncOutlined } from '@ant-design/icons'
|
||||
import Logo from '@renderer/assets/images/logo.png'
|
||||
import { SyncOutlined } from '@ant-design/icons'
|
||||
import { firstLetter } from '@renderer/utils'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { isEmpty, upperFirst } from 'lodash'
|
||||
import dayjs from 'dayjs'
|
||||
import { getModelLogo } from '@renderer/config/provider'
|
||||
import { useAssistant } from '@renderer/hooks/useAssistant'
|
||||
import useAvatar from '@renderer/hooks/useAvatar'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { EVENT_NAMES, EventEmitter } from '@renderer/services/event'
|
||||
import { Message } from '@renderer/types'
|
||||
import { firstLetter } from '@renderer/utils'
|
||||
import { Avatar, Tooltip } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import { isEmpty, upperFirst } from 'lodash'
|
||||
import { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Markdown from 'react-markdown'
|
||||
import styled from 'styled-components'
|
||||
import CodeBlock from './CodeBlock'
|
||||
|
||||
interface Props {
|
||||
message: Message
|
||||
@ -29,7 +28,7 @@ const MessageItem: FC<Props> = ({ message, index, showMenu, onDeleteMessage }) =
|
||||
const avatar = useAvatar()
|
||||
const { t } = useTranslation()
|
||||
const { assistant } = useAssistant(message.assistantId)
|
||||
const { userName, showMessageDivider } = useSettings()
|
||||
const { userName, showMessageDivider, messageFont } = useSettings()
|
||||
|
||||
const isLastMessage = index === 0
|
||||
const isUserMessage = message.role === 'user'
|
||||
@ -79,8 +78,11 @@ const MessageItem: FC<Props> = ({ message, index, showMenu, onDeleteMessage }) =
|
||||
return userName || t('common.you')
|
||||
}
|
||||
|
||||
const fontFamily = messageFont === 'serif' ? "Georgia, Cambria, 'Times New Roman', Times, serif" : undefined
|
||||
const messageBorder = showMessageDivider ? undefined : 'none'
|
||||
|
||||
return (
|
||||
<MessageContainer key={message.id} className="message" style={{ border: showMessageDivider ? undefined : 'none' }}>
|
||||
<MessageContainer key={message.id} className="message" style={{ border: messageBorder }}>
|
||||
<MessageHeader>
|
||||
<AvatarWrapper>
|
||||
{message.role === 'assistant' ? (
|
||||
@ -101,7 +103,7 @@ const MessageItem: FC<Props> = ({ message, index, showMenu, onDeleteMessage }) =
|
||||
</MessageMetadata>
|
||||
)}
|
||||
</MessageHeader>
|
||||
<MessageContent>
|
||||
<MessageContent style={{ fontFamily }}>
|
||||
{message.status === 'sending' && (
|
||||
<MessageContentLoading>
|
||||
<SyncOutlined spin size={24} />
|
||||
|
||||
@ -31,7 +31,7 @@ const NavigationCenter: FC<Props> = ({ activeAssistant }) => {
|
||||
type: 'group',
|
||||
children: p.models.map((m) => ({
|
||||
key: m.id,
|
||||
label: m.name,
|
||||
label: upperFirst(m.name),
|
||||
style: m.id === model?.id ? { color: colorPrimary } : undefined,
|
||||
onClick: () => setModel(m)
|
||||
}))
|
||||
|
||||
@ -8,14 +8,14 @@ import useAvatar from '@renderer/hooks/useAvatar'
|
||||
import { useAppDispatch } from '@renderer/store'
|
||||
import { setAvatar } from '@renderer/store/runtime'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { setLanguage, setShowMessageDivider, setUserName } from '@renderer/store/settings'
|
||||
import { setLanguage, setMessageFont, setShowMessageDivider, setUserName } from '@renderer/store/settings'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { setProxyUrl as _setProxyUrl } from '@renderer/store/settings'
|
||||
import i18n from '@renderer/i18n'
|
||||
|
||||
const GeneralSettings: FC = () => {
|
||||
const avatar = useAvatar()
|
||||
const { language, proxyUrl: storeProxyUrl, userName, showMessageDivider } = useSettings()
|
||||
const { language, proxyUrl: storeProxyUrl, userName, showMessageDivider, messageFont } = useSettings()
|
||||
const [proxyUrl, setProxyUrl] = useState<string | undefined>(storeProxyUrl)
|
||||
const dispatch = useAppDispatch()
|
||||
const { t } = useTranslation()
|
||||
@ -97,11 +97,21 @@ const GeneralSettings: FC = () => {
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingTitle style={{ marginTop: 20 }}>{t('settings.general.message.title')}</SettingTitle>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitle>{t('settings.general.message.divider')}</SettingRowTitle>
|
||||
<Switch checked={showMessageDivider} onChange={(checked) => dispatch(setShowMessageDivider(checked))} />
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitle>{t('settings.general.message.use_serif_font')}</SettingRowTitle>
|
||||
<Switch
|
||||
checked={messageFont === 'serif'}
|
||||
onChange={(checked) => dispatch(setMessageFont(checked ? 'serif' : 'system'))}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
</SettingContainer>
|
||||
)
|
||||
}
|
||||
|
||||
@ -22,6 +22,9 @@ const SettingsPage: FC = () => {
|
||||
</Navbar>
|
||||
<ContentContainer>
|
||||
<SettingMenus>
|
||||
<MenuItemLink to="/settings/general">
|
||||
<MenuItem className={isRoute('/settings/general')}>{t('settings.general')}</MenuItem>
|
||||
</MenuItemLink>
|
||||
<MenuItemLink to="/settings/provider">
|
||||
<MenuItem className={isRoute('/settings/provider')}>{t('settings.provider')}</MenuItem>
|
||||
</MenuItemLink>
|
||||
@ -31,9 +34,6 @@ const SettingsPage: FC = () => {
|
||||
<MenuItemLink to="/settings/assistant">
|
||||
<MenuItem className={isRoute('/settings/assistant')}>{t('settings.assistant')}</MenuItem>
|
||||
</MenuItemLink>
|
||||
<MenuItemLink to="/settings/general">
|
||||
<MenuItem className={isRoute('/settings/general')}>{t('settings.general')}</MenuItem>
|
||||
</MenuItemLink>
|
||||
<MenuItemLink to="/settings/about">
|
||||
<MenuItem className={isRoute('/settings/about')}>{t('settings.about')}</MenuItem>
|
||||
</MenuItemLink>
|
||||
|
||||
@ -19,7 +19,7 @@ const persistedReducer = persistReducer(
|
||||
{
|
||||
key: 'cherry-studio',
|
||||
storage,
|
||||
version: 15,
|
||||
version: 16,
|
||||
blacklist: ['runtime'],
|
||||
migrate
|
||||
},
|
||||
|
||||
@ -5,8 +5,7 @@ import { isEmpty } from 'lodash'
|
||||
import i18n from '@renderer/i18n'
|
||||
import { Assistant } from '@renderer/types'
|
||||
|
||||
const migrate = createMigrate({
|
||||
// @ts-ignore store type is unknown
|
||||
const migrateConfig = {
|
||||
'2': (state: RootState) => {
|
||||
return {
|
||||
...state,
|
||||
@ -26,7 +25,6 @@ const migrate = createMigrate({
|
||||
}
|
||||
}
|
||||
},
|
||||
// @ts-ignore store type is unknown
|
||||
'3': (state: RootState) => {
|
||||
return {
|
||||
...state,
|
||||
@ -46,7 +44,6 @@ const migrate = createMigrate({
|
||||
}
|
||||
}
|
||||
},
|
||||
// @ts-ignore store type is unknown
|
||||
'4': (state: RootState) => {
|
||||
return {
|
||||
...state,
|
||||
@ -66,7 +63,6 @@ const migrate = createMigrate({
|
||||
}
|
||||
}
|
||||
},
|
||||
// @ts-ignore store type is unknown
|
||||
'5': (state: RootState) => {
|
||||
return {
|
||||
...state,
|
||||
@ -86,7 +82,6 @@ const migrate = createMigrate({
|
||||
}
|
||||
}
|
||||
},
|
||||
// @ts-ignore store type is unknown
|
||||
'6': (state: RootState) => {
|
||||
return {
|
||||
...state,
|
||||
@ -106,7 +101,6 @@ const migrate = createMigrate({
|
||||
}
|
||||
}
|
||||
},
|
||||
// @ts-ignore store type is unknown
|
||||
'7': (state: RootState) => {
|
||||
return {
|
||||
...state,
|
||||
@ -116,7 +110,6 @@ const migrate = createMigrate({
|
||||
}
|
||||
}
|
||||
},
|
||||
// @ts-ignore store type is unknown
|
||||
'8': (state: RootState) => {
|
||||
const fixAssistantName = (assistant: Assistant) => {
|
||||
if (isEmpty(assistant.name)) {
|
||||
@ -142,7 +135,6 @@ const migrate = createMigrate({
|
||||
}
|
||||
}
|
||||
},
|
||||
// @ts-ignore store type is unknown
|
||||
'9': (state: RootState) => {
|
||||
return {
|
||||
...state,
|
||||
@ -157,7 +149,6 @@ const migrate = createMigrate({
|
||||
}
|
||||
}
|
||||
},
|
||||
// @ts-ignore store type is unknown
|
||||
'10': (state: RootState) => {
|
||||
return {
|
||||
...state,
|
||||
@ -178,7 +169,6 @@ const migrate = createMigrate({
|
||||
}
|
||||
}
|
||||
},
|
||||
// @ts-ignore store type is unknown
|
||||
'11': (state: RootState) => {
|
||||
return {
|
||||
...state,
|
||||
@ -208,7 +198,6 @@ const migrate = createMigrate({
|
||||
}
|
||||
}
|
||||
},
|
||||
// @ts-ignore store type is unknown
|
||||
'12': (state: RootState) => {
|
||||
return {
|
||||
...state,
|
||||
@ -229,7 +218,6 @@ const migrate = createMigrate({
|
||||
}
|
||||
}
|
||||
},
|
||||
// @ts-ignore store type is unknown
|
||||
'13': (state: RootState) => {
|
||||
return {
|
||||
...state,
|
||||
@ -244,7 +232,6 @@ const migrate = createMigrate({
|
||||
}
|
||||
}
|
||||
},
|
||||
// @ts-ignore store type is unknown
|
||||
'14': (state: RootState) => {
|
||||
return {
|
||||
...state,
|
||||
@ -255,7 +242,6 @@ const migrate = createMigrate({
|
||||
}
|
||||
}
|
||||
},
|
||||
// @ts-ignore store type is unknown
|
||||
'15': (state: RootState) => {
|
||||
return {
|
||||
...state,
|
||||
@ -265,7 +251,18 @@ const migrate = createMigrate({
|
||||
showMessageDivider: true
|
||||
}
|
||||
}
|
||||
},
|
||||
'16': (state: RootState) => {
|
||||
return {
|
||||
...state,
|
||||
settings: {
|
||||
...state.settings,
|
||||
messageFont: 'system'
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const migrate = createMigrate(migrateConfig as any)
|
||||
|
||||
export default migrate
|
||||
|
||||
@ -10,6 +10,7 @@ export interface SettingsState {
|
||||
proxyUrl?: string
|
||||
userName: string
|
||||
showMessageDivider: boolean
|
||||
messageFont: 'system' | 'serif'
|
||||
}
|
||||
|
||||
const initialState: SettingsState = {
|
||||
@ -19,7 +20,8 @@ const initialState: SettingsState = {
|
||||
language: navigator.language,
|
||||
proxyUrl: undefined,
|
||||
userName: '',
|
||||
showMessageDivider: true
|
||||
showMessageDivider: true,
|
||||
messageFont: 'system'
|
||||
}
|
||||
|
||||
const settingsSlice = createSlice({
|
||||
@ -46,6 +48,9 @@ const settingsSlice = createSlice({
|
||||
},
|
||||
setShowMessageDivider: (state, action: PayloadAction<boolean>) => {
|
||||
state.showMessageDivider = action.payload
|
||||
},
|
||||
setMessageFont: (state, action: PayloadAction<'system' | 'serif'>) => {
|
||||
state.messageFont = action.payload
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -57,7 +62,8 @@ export const {
|
||||
setLanguage,
|
||||
setProxyUrl,
|
||||
setUserName,
|
||||
setShowMessageDivider
|
||||
setShowMessageDivider,
|
||||
setMessageFont
|
||||
} = settingsSlice.actions
|
||||
|
||||
export default settingsSlice.reducer
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user