mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-19 14:41:24 +08:00
feature: add option to change font (#10133)
* feature: add option to change font 1. set app global font 2. set code block font Signed-off-by: Albert Abdilim <albert.abdilim@foxmail.com> * formatted code with Prettier * fix ci errors 1.add migration in `migrate.ts` 2.add to-be-translated strings by running `yarn sync:i18n` * chore: update yarn.lock to include font-list package version 2.0.0 * fix migration issue --------- Signed-off-by: Albert Abdilim <albert.abdilim@foxmail.com> Co-authored-by: suyao <sy20010504@gmail.com>
This commit is contained in:
parent
80afb3a86e
commit
993d497aad
@ -78,6 +78,7 @@
|
|||||||
"@strongtz/win32-arm64-msvc": "^0.4.7",
|
"@strongtz/win32-arm64-msvc": "^0.4.7",
|
||||||
"express": "^5.1.0",
|
"express": "^5.1.0",
|
||||||
"faiss-node": "^0.5.1",
|
"faiss-node": "^0.5.1",
|
||||||
|
"font-list": "^2.0.0",
|
||||||
"graceful-fs": "^4.2.11",
|
"graceful-fs": "^4.2.11",
|
||||||
"jsdom": "26.1.0",
|
"jsdom": "26.1.0",
|
||||||
"node-stream-zip": "^1.15.0",
|
"node-stream-zip": "^1.15.0",
|
||||||
|
|||||||
@ -38,6 +38,7 @@ export enum IpcChannel {
|
|||||||
App_GetDiskInfo = 'app:get-disk-info',
|
App_GetDiskInfo = 'app:get-disk-info',
|
||||||
App_SetFullScreen = 'app:set-full-screen',
|
App_SetFullScreen = 'app:set-full-screen',
|
||||||
App_IsFullScreen = 'app:is-full-screen',
|
App_IsFullScreen = 'app:is-full-screen',
|
||||||
|
App_GetSystemFonts = 'app:get-system-fonts',
|
||||||
|
|
||||||
App_MacIsProcessTrusted = 'app:mac-is-process-trusted',
|
App_MacIsProcessTrusted = 'app:mac-is-process-trusted',
|
||||||
App_MacRequestProcessTrust = 'app:mac-request-process-trust',
|
App_MacRequestProcessTrust = 'app:mac-request-process-trust',
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import { IpcChannel } from '@shared/IpcChannel'
|
|||||||
import { FileMetadata, Provider, Shortcut, ThemeMode } from '@types'
|
import { FileMetadata, Provider, Shortcut, ThemeMode } from '@types'
|
||||||
import checkDiskSpace from 'check-disk-space'
|
import checkDiskSpace from 'check-disk-space'
|
||||||
import { BrowserWindow, dialog, ipcMain, ProxyConfig, session, shell, systemPreferences, webContents } from 'electron'
|
import { BrowserWindow, dialog, ipcMain, ProxyConfig, session, shell, systemPreferences, webContents } from 'electron'
|
||||||
|
import fontList from 'font-list'
|
||||||
import { Notification } from 'src/renderer/src/types/notification'
|
import { Notification } from 'src/renderer/src/types/notification'
|
||||||
|
|
||||||
import { apiServerService } from './services/ApiServerService'
|
import { apiServerService } from './services/ApiServerService'
|
||||||
@ -219,6 +220,17 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) {
|
|||||||
return mainWindow.isFullScreen()
|
return mainWindow.isFullScreen()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Get System Fonts
|
||||||
|
ipcMain.handle(IpcChannel.App_GetSystemFonts, async () => {
|
||||||
|
try {
|
||||||
|
const fonts = await fontList.getFonts()
|
||||||
|
return fonts.map((font: string) => font.replace(/^"(.*)"$/, '$1')).filter((font: string) => font.length > 0)
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Failed to get system fonts:', error as Error)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
ipcMain.handle(IpcChannel.Config_Set, (_, key: string, value: any, isNotify: boolean = false) => {
|
ipcMain.handle(IpcChannel.Config_Set, (_, key: string, value: any, isNotify: boolean = false) => {
|
||||||
configManager.set(key, value, isNotify)
|
configManager.set(key, value, isNotify)
|
||||||
})
|
})
|
||||||
|
|||||||
@ -84,6 +84,7 @@ const api = {
|
|||||||
ipcRenderer.invoke(IpcChannel.App_LogToMain, source, level, message, data),
|
ipcRenderer.invoke(IpcChannel.App_LogToMain, source, level, message, data),
|
||||||
setFullScreen: (value: boolean): Promise<void> => ipcRenderer.invoke(IpcChannel.App_SetFullScreen, value),
|
setFullScreen: (value: boolean): Promise<void> => ipcRenderer.invoke(IpcChannel.App_SetFullScreen, value),
|
||||||
isFullScreen: (): Promise<boolean> => ipcRenderer.invoke(IpcChannel.App_IsFullScreen),
|
isFullScreen: (): Promise<boolean> => ipcRenderer.invoke(IpcChannel.App_IsFullScreen),
|
||||||
|
getSystemFonts: (): Promise<string[]> => ipcRenderer.invoke(IpcChannel.App_GetSystemFonts),
|
||||||
mac: {
|
mac: {
|
||||||
isProcessTrusted: (): Promise<boolean> => ipcRenderer.invoke(IpcChannel.App_MacIsProcessTrusted),
|
isProcessTrusted: (): Promise<boolean> => ipcRenderer.invoke(IpcChannel.App_MacIsProcessTrusted),
|
||||||
requestProcessTrust: (): Promise<boolean> => ipcRenderer.invoke(IpcChannel.App_MacRequestProcessTrust)
|
requestProcessTrust: (): Promise<boolean> => ipcRenderer.invoke(IpcChannel.App_MacRequestProcessTrust)
|
||||||
|
|||||||
@ -1,23 +1,24 @@
|
|||||||
:root {
|
:root {
|
||||||
--font-family:
|
--font-family:
|
||||||
Ubuntu, -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, Roboto, Oxygen, Cantarell, 'Open Sans',
|
var(--user-font-family), Ubuntu, -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, Roboto, Oxygen,
|
||||||
'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
|
Cantarell, 'Open Sans', 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
|
||||||
'Noto Color Emoji';
|
'Segoe UI Symbol', 'Noto Color Emoji';
|
||||||
|
|
||||||
--font-family-serif:
|
--font-family-serif:
|
||||||
serif, -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, Ubuntu, Roboto, Oxygen, Cantarell, 'Open Sans',
|
serif, -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, Ubuntu, Roboto, Oxygen, Cantarell, 'Open Sans',
|
||||||
'Helvetica Neue', Arial, 'Noto Sans', 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
'Helvetica Neue', Arial, 'Noto Sans', 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
||||||
|
|
||||||
--code-font-family: 'Cascadia Code', 'Fira Code', 'Consolas', Menlo, Courier, monospace;
|
--code-font-family: var(--user-code-font-family), 'Cascadia Code', 'Fira Code', 'Consolas', Menlo, Courier, monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Windows系统专用字体配置 */
|
/* Windows系统专用字体配置 */
|
||||||
body[os='windows'] {
|
body[os='windows'] {
|
||||||
--font-family:
|
--font-family:
|
||||||
'Twemoji Country Flags', Ubuntu, -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, Roboto, Oxygen,
|
var(--user-font-family), 'Twemoji Country Flags', Ubuntu, -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui,
|
||||||
Cantarell, 'Open Sans', 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
|
Roboto, Oxygen, Cantarell, 'Open Sans', 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji',
|
||||||
'Segoe UI Symbol', 'Noto Color Emoji';
|
'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
||||||
|
|
||||||
--code-font-family:
|
--code-font-family:
|
||||||
'Cascadia Code', 'Fira Code', 'Consolas', 'Sarasa Mono SC', 'Microsoft YaHei UI', Courier, monospace;
|
var(--user-code-font-family), 'Cascadia Code', 'Fira Code', 'Consolas', 'Sarasa Mono SC', 'Microsoft YaHei UI',
|
||||||
|
Courier, monospace;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,6 +15,10 @@ export default function useUserTheme() {
|
|||||||
document.body.style.setProperty('--primary', colorPrimary.toString())
|
document.body.style.setProperty('--primary', colorPrimary.toString())
|
||||||
document.body.style.setProperty('--color-primary-soft', colorPrimary.alpha(0.6).toString())
|
document.body.style.setProperty('--color-primary-soft', colorPrimary.alpha(0.6).toString())
|
||||||
document.body.style.setProperty('--color-primary-mute', colorPrimary.alpha(0.3).toString())
|
document.body.style.setProperty('--color-primary-mute', colorPrimary.alpha(0.3).toString())
|
||||||
|
|
||||||
|
// Set font family CSS variables
|
||||||
|
document.documentElement.style.setProperty('--user-font-family', `'${theme.userFontFamily}'`)
|
||||||
|
document.documentElement.style.setProperty('--user-code-font-family', `'${theme.userCodeFontFamily}'`)
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -3116,6 +3116,13 @@
|
|||||||
"placeholder": "/* Put custom CSS here */"
|
"placeholder": "/* Put custom CSS here */"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"font": {
|
||||||
|
"code": "Code Font",
|
||||||
|
"default": "Default",
|
||||||
|
"global": "Global Font",
|
||||||
|
"select": "Select Font",
|
||||||
|
"title": "Font Settings"
|
||||||
|
},
|
||||||
"navbar": {
|
"navbar": {
|
||||||
"position": {
|
"position": {
|
||||||
"label": "Navbar Position",
|
"label": "Navbar Position",
|
||||||
|
|||||||
@ -3117,6 +3117,13 @@
|
|||||||
"placeholder": "/* 这里写自定义 CSS */"
|
"placeholder": "/* 这里写自定义 CSS */"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"font": {
|
||||||
|
"code": "代码字体",
|
||||||
|
"default": "默认",
|
||||||
|
"global": "全局字体",
|
||||||
|
"select": "选择字体",
|
||||||
|
"title": "字体设置"
|
||||||
|
},
|
||||||
"navbar": {
|
"navbar": {
|
||||||
"position": {
|
"position": {
|
||||||
"label": "导航栏位置",
|
"label": "导航栏位置",
|
||||||
|
|||||||
@ -3116,6 +3116,13 @@
|
|||||||
"placeholder": "/* 這裡寫自訂 CSS */"
|
"placeholder": "/* 這裡寫自訂 CSS */"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"font": {
|
||||||
|
"code": "[to be translated]:代码字体",
|
||||||
|
"default": "[to be translated]:默认",
|
||||||
|
"global": "[to be translated]:全局字体",
|
||||||
|
"select": "[to be translated]:选择字体",
|
||||||
|
"title": "[to be translated]:字体设置"
|
||||||
|
},
|
||||||
"navbar": {
|
"navbar": {
|
||||||
"position": {
|
"position": {
|
||||||
"label": "導航欄位置",
|
"label": "導航欄位置",
|
||||||
|
|||||||
@ -3116,6 +3116,13 @@
|
|||||||
"placeholder": "/* Γράψτε εδώ την προσαρμοστική CSS */"
|
"placeholder": "/* Γράψτε εδώ την προσαρμοστική CSS */"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"font": {
|
||||||
|
"code": "[to be translated]:代码字体",
|
||||||
|
"default": "[to be translated]:默认",
|
||||||
|
"global": "[to be translated]:全局字体",
|
||||||
|
"select": "[to be translated]:选择字体",
|
||||||
|
"title": "[to be translated]:字体设置"
|
||||||
|
},
|
||||||
"navbar": {
|
"navbar": {
|
||||||
"position": {
|
"position": {
|
||||||
"label": "Θέση Γραμμής Πλοήγησης",
|
"label": "Θέση Γραμμής Πλοήγησης",
|
||||||
|
|||||||
@ -3116,6 +3116,13 @@
|
|||||||
"placeholder": "/* Escribe tu CSS personalizado aquí */"
|
"placeholder": "/* Escribe tu CSS personalizado aquí */"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"font": {
|
||||||
|
"code": "[to be translated]:代码字体",
|
||||||
|
"default": "[to be translated]:默认",
|
||||||
|
"global": "[to be translated]:全局字体",
|
||||||
|
"select": "[to be translated]:选择字体",
|
||||||
|
"title": "[to be translated]:字体设置"
|
||||||
|
},
|
||||||
"navbar": {
|
"navbar": {
|
||||||
"position": {
|
"position": {
|
||||||
"label": "Posición de la barra de navegación",
|
"label": "Posición de la barra de navegación",
|
||||||
|
|||||||
@ -3116,6 +3116,13 @@
|
|||||||
"placeholder": "/* Écrire votre CSS personnalisé ici */"
|
"placeholder": "/* Écrire votre CSS personnalisé ici */"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"font": {
|
||||||
|
"code": "[to be translated]:代码字体",
|
||||||
|
"default": "[to be translated]:默认",
|
||||||
|
"global": "[to be translated]:全局字体",
|
||||||
|
"select": "[to be translated]:选择字体",
|
||||||
|
"title": "[to be translated]:字体设置"
|
||||||
|
},
|
||||||
"navbar": {
|
"navbar": {
|
||||||
"position": {
|
"position": {
|
||||||
"label": "Position de la barre de navigation",
|
"label": "Position de la barre de navigation",
|
||||||
|
|||||||
@ -3116,6 +3116,13 @@
|
|||||||
"placeholder": "/* ここにカスタムCSSを入力 */"
|
"placeholder": "/* ここにカスタムCSSを入力 */"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"font": {
|
||||||
|
"code": "[to be translated]:代码字体",
|
||||||
|
"default": "[to be translated]:默认",
|
||||||
|
"global": "[to be translated]:全局字体",
|
||||||
|
"select": "[to be translated]:选择字体",
|
||||||
|
"title": "[to be translated]:字体设置"
|
||||||
|
},
|
||||||
"navbar": {
|
"navbar": {
|
||||||
"position": {
|
"position": {
|
||||||
"label": "ナビゲーションバー位置",
|
"label": "ナビゲーションバー位置",
|
||||||
|
|||||||
@ -3116,6 +3116,13 @@
|
|||||||
"placeholder": "/* Escreva seu CSS personalizado aqui */"
|
"placeholder": "/* Escreva seu CSS personalizado aqui */"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"font": {
|
||||||
|
"code": "[to be translated]:代码字体",
|
||||||
|
"default": "[to be translated]:默认",
|
||||||
|
"global": "[to be translated]:全局字体",
|
||||||
|
"select": "[to be translated]:选择字体",
|
||||||
|
"title": "[to be translated]:字体设置"
|
||||||
|
},
|
||||||
"navbar": {
|
"navbar": {
|
||||||
"position": {
|
"position": {
|
||||||
"label": "Posição da Barra de Navegação",
|
"label": "Posição da Barra de Navegação",
|
||||||
|
|||||||
@ -3116,6 +3116,13 @@
|
|||||||
"placeholder": "/* Здесь введите пользовательский CSS */"
|
"placeholder": "/* Здесь введите пользовательский CSS */"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"font": {
|
||||||
|
"code": "[to be translated]:代码字体",
|
||||||
|
"default": "[to be translated]:默认",
|
||||||
|
"global": "[to be translated]:全局字体",
|
||||||
|
"select": "[to be translated]:选择字体",
|
||||||
|
"title": "[to be translated]:字体设置"
|
||||||
|
},
|
||||||
"navbar": {
|
"navbar": {
|
||||||
"position": {
|
"position": {
|
||||||
"label": "Положение навигации",
|
"label": "Положение навигации",
|
||||||
|
|||||||
@ -18,7 +18,7 @@ import {
|
|||||||
setSidebarIcons
|
setSidebarIcons
|
||||||
} from '@renderer/store/settings'
|
} from '@renderer/store/settings'
|
||||||
import { ThemeMode } from '@renderer/types'
|
import { ThemeMode } from '@renderer/types'
|
||||||
import { Button, ColorPicker, Segmented, Switch } from 'antd'
|
import { Button, ColorPicker, Segmented, Select, Switch } from 'antd'
|
||||||
import { Minus, Monitor, Moon, Plus, Sun } from 'lucide-react'
|
import { Minus, Monitor, Moon, Plus, Sun } from 'lucide-react'
|
||||||
import { FC, useCallback, useEffect, useMemo, useState } from 'react'
|
import { FC, useCallback, useEffect, useMemo, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
@ -78,6 +78,7 @@ const DisplaySettings: FC = () => {
|
|||||||
|
|
||||||
const [visibleIcons, setVisibleIcons] = useState(sidebarIcons?.visible || DEFAULT_SIDEBAR_ICONS)
|
const [visibleIcons, setVisibleIcons] = useState(sidebarIcons?.visible || DEFAULT_SIDEBAR_ICONS)
|
||||||
const [disabledIcons, setDisabledIcons] = useState(sidebarIcons?.disabled || [])
|
const [disabledIcons, setDisabledIcons] = useState(sidebarIcons?.disabled || [])
|
||||||
|
const [fontList, setFontList] = useState<string[]>([])
|
||||||
|
|
||||||
const handleWindowStyleChange = useCallback(
|
const handleWindowStyleChange = useCallback(
|
||||||
(checked: boolean) => {
|
(checked: boolean) => {
|
||||||
@ -136,6 +137,11 @@ const DisplaySettings: FC = () => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
// 初始化获取所有系统字体
|
||||||
|
window.api.getSystemFonts().then((fonts: string[]) => {
|
||||||
|
setFontList(fonts)
|
||||||
|
})
|
||||||
|
|
||||||
// 初始化获取当前缩放值
|
// 初始化获取当前缩放值
|
||||||
window.api.handleZoomFactor(0).then((factor) => {
|
window.api.handleZoomFactor(0).then((factor) => {
|
||||||
setCurrentZoom(factor)
|
setCurrentZoom(factor)
|
||||||
@ -160,6 +166,26 @@ const DisplaySettings: FC = () => {
|
|||||||
setCurrentZoom(zoomFactor)
|
setCurrentZoom(zoomFactor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleUserFontChange = useCallback(
|
||||||
|
(value: string) => {
|
||||||
|
setUserTheme({
|
||||||
|
...userTheme,
|
||||||
|
userFontFamily: value
|
||||||
|
})
|
||||||
|
},
|
||||||
|
[setUserTheme, userTheme]
|
||||||
|
)
|
||||||
|
|
||||||
|
const handleUserCodeFontChange = useCallback(
|
||||||
|
(value: string) => {
|
||||||
|
setUserTheme({
|
||||||
|
...userTheme,
|
||||||
|
userCodeFontFamily: value
|
||||||
|
})
|
||||||
|
},
|
||||||
|
[setUserTheme, userTheme]
|
||||||
|
)
|
||||||
|
|
||||||
const assistantIconTypeOptions = useMemo(
|
const assistantIconTypeOptions = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{ value: 'model', label: t('settings.assistant.icon.type.model') },
|
{ value: 'model', label: t('settings.assistant.icon.type.model') },
|
||||||
@ -194,6 +220,7 @@ const DisplaySettings: FC = () => {
|
|||||||
))}
|
))}
|
||||||
</HStack>
|
</HStack>
|
||||||
<ColorPicker
|
<ColorPicker
|
||||||
|
style={{ fontFamily: 'inherit' }}
|
||||||
className="color-picker"
|
className="color-picker"
|
||||||
value={userTheme.colorPrimary}
|
value={userTheme.colorPrimary}
|
||||||
onChange={(color) => handleColorPrimaryChange(color.toHexString())}
|
onChange={(color) => handleColorPrimaryChange(color.toHexString())}
|
||||||
@ -255,6 +282,75 @@ const DisplaySettings: FC = () => {
|
|||||||
</ZoomButtonGroup>
|
</ZoomButtonGroup>
|
||||||
</SettingRow>
|
</SettingRow>
|
||||||
</SettingGroup>
|
</SettingGroup>
|
||||||
|
<SettingGroup theme={theme}>
|
||||||
|
<SettingTitle style={{ justifyContent: 'flex-start', gap: 5 }}>
|
||||||
|
{t('settings.display.font.title')} <TextBadge text="New" />
|
||||||
|
</SettingTitle>
|
||||||
|
<SettingDivider />
|
||||||
|
<SettingRow>
|
||||||
|
<SettingRowTitle>{t('settings.display.font.global')}</SettingRowTitle>
|
||||||
|
<SelectRow>
|
||||||
|
<Select
|
||||||
|
style={{ width: 200 }}
|
||||||
|
placeholder={t('settings.display.font.select')}
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
label: (
|
||||||
|
<span style={{ fontFamily: 'Ubuntu, -apple-system, system-ui, Arial, sans-serif' }}>
|
||||||
|
{t('settings.display.font.default')}
|
||||||
|
</span>
|
||||||
|
),
|
||||||
|
value: ''
|
||||||
|
},
|
||||||
|
...fontList.map((font) => ({ label: <span style={{ fontFamily: font }}>{font}</span>, value: font }))
|
||||||
|
]}
|
||||||
|
value={userTheme.userFontFamily || ''}
|
||||||
|
onChange={(font) => handleUserFontChange(font)}
|
||||||
|
showSearch
|
||||||
|
getPopupContainer={(triggerNode) => triggerNode.parentElement || document.body}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
onClick={() => handleUserFontChange('')}
|
||||||
|
style={{ marginLeft: 8 }}
|
||||||
|
icon={<ResetIcon size="14" />}
|
||||||
|
color="default"
|
||||||
|
variant="text"
|
||||||
|
/>
|
||||||
|
</SelectRow>
|
||||||
|
</SettingRow>
|
||||||
|
<SettingDivider />
|
||||||
|
<SettingRow>
|
||||||
|
<SettingRowTitle>{t('settings.display.font.code')}</SettingRowTitle>
|
||||||
|
<SelectRow>
|
||||||
|
<Select
|
||||||
|
style={{ width: 200 }}
|
||||||
|
placeholder={t('settings.display.font.select')}
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
label: (
|
||||||
|
<span style={{ fontFamily: 'Ubuntu, -apple-system, system-ui, Arial, sans-serif' }}>
|
||||||
|
{t('settings.display.font.default')}
|
||||||
|
</span>
|
||||||
|
),
|
||||||
|
value: ''
|
||||||
|
},
|
||||||
|
...fontList.map((font) => ({ label: <span style={{ fontFamily: font }}>{font}</span>, value: font }))
|
||||||
|
]}
|
||||||
|
value={userTheme.userCodeFontFamily || ''}
|
||||||
|
onChange={(font) => handleUserCodeFontChange(font)}
|
||||||
|
showSearch
|
||||||
|
getPopupContainer={(triggerNode) => triggerNode.parentElement || document.body}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
onClick={() => handleUserCodeFontChange('')}
|
||||||
|
style={{ marginLeft: 8 }}
|
||||||
|
icon={<ResetIcon size="14" />}
|
||||||
|
color="default"
|
||||||
|
variant="text"
|
||||||
|
/>
|
||||||
|
</SelectRow>
|
||||||
|
</SettingRow>
|
||||||
|
</SettingGroup>
|
||||||
<SettingGroup theme={theme}>
|
<SettingGroup theme={theme}>
|
||||||
<SettingTitle>{t('settings.display.topic.title')}</SettingTitle>
|
<SettingTitle>{t('settings.display.topic.title')}</SettingTitle>
|
||||||
<SettingDivider />
|
<SettingDivider />
|
||||||
@ -379,4 +475,11 @@ const ZoomValue = styled.span`
|
|||||||
margin: 0 5px;
|
margin: 0 5px;
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const SelectRow = styled.div`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
width: 300px;
|
||||||
|
`
|
||||||
|
|
||||||
export default DisplaySettings
|
export default DisplaySettings
|
||||||
|
|||||||
@ -2451,6 +2451,18 @@ const migrateConfig = {
|
|||||||
logger.error('migrate 153 error', error as Error)
|
logger.error('migrate 153 error', error as Error)
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
'154': (state: RootState) => {
|
||||||
|
try {
|
||||||
|
if (state.settings.userTheme) {
|
||||||
|
state.settings.userTheme.userFontFamily = settingsInitialState.userTheme.userFontFamily
|
||||||
|
state.settings.userTheme.userCodeFontFamily = settingsInitialState.userTheme.userCodeFontFamily
|
||||||
|
}
|
||||||
|
return state
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('migrate 154 error', error as Error)
|
||||||
|
return state
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -33,6 +33,8 @@ export type AssistantIconType = 'model' | 'emoji' | 'none'
|
|||||||
|
|
||||||
export type UserTheme = {
|
export type UserTheme = {
|
||||||
colorPrimary: string
|
colorPrimary: string
|
||||||
|
userFontFamily: string
|
||||||
|
userCodeFontFamily: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SettingsState {
|
export interface SettingsState {
|
||||||
@ -242,7 +244,9 @@ export const initialState: SettingsState = {
|
|||||||
tray: true,
|
tray: true,
|
||||||
theme: ThemeMode.system,
|
theme: ThemeMode.system,
|
||||||
userTheme: {
|
userTheme: {
|
||||||
colorPrimary: '#00b96b'
|
colorPrimary: '#00b96b',
|
||||||
|
userFontFamily: '',
|
||||||
|
userCodeFontFamily: ''
|
||||||
},
|
},
|
||||||
windowStyle: isMac ? 'transparent' : 'opaque',
|
windowStyle: isMac ? 'transparent' : 'opaque',
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
|
|||||||
@ -13198,6 +13198,7 @@ __metadata:
|
|||||||
fast-diff: "npm:^1.3.0"
|
fast-diff: "npm:^1.3.0"
|
||||||
fast-xml-parser: "npm:^5.2.0"
|
fast-xml-parser: "npm:^5.2.0"
|
||||||
fetch-socks: "npm:1.3.2"
|
fetch-socks: "npm:1.3.2"
|
||||||
|
font-list: "npm:^2.0.0"
|
||||||
framer-motion: "npm:^12.23.12"
|
framer-motion: "npm:^12.23.12"
|
||||||
franc-min: "npm:^6.2.0"
|
franc-min: "npm:^6.2.0"
|
||||||
fs-extra: "npm:^11.2.0"
|
fs-extra: "npm:^11.2.0"
|
||||||
@ -18043,6 +18044,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"font-list@npm:^2.0.0":
|
||||||
|
version: 2.0.0
|
||||||
|
resolution: "font-list@npm:2.0.0"
|
||||||
|
checksum: 10c0/9fc8600fa40a5d079982505ea101e49b21260a36f33167ac993fd7b26cec8372a16017c00d6fb404e259600ce8d588830167c9141c2df7dedb0fedd5953905f6
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"foreground-child@npm:^3.1.0":
|
"foreground-child@npm:^3.1.0":
|
||||||
version: 3.3.1
|
version: 3.3.1
|
||||||
resolution: "foreground-child@npm:3.3.1"
|
resolution: "foreground-child@npm:3.3.1"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user