feat(DisplaySettings): add theme color presets and zoom settings

- Introduced a new color selection feature in DisplaySettings, allowing users to choose from predefined theme color presets.
- Added a dedicated section for zoom settings in the DisplaySettings component, enhancing user customization options.
- Updated localization files to include new zoom settings titles in multiple languages.
This commit is contained in:
kangfenmao 2025-05-29 15:28:28 +08:00
parent a78db10798
commit a6bb58bb45
13 changed files with 103 additions and 33 deletions

View File

@ -15,3 +15,18 @@ export const TOKENFLUX_HOST = 'https://tokenflux.ai'
// Messages loading configuration // Messages loading configuration
export const INITIAL_MESSAGES_COUNT = 20 export const INITIAL_MESSAGES_COUNT = 20
export const LOAD_MORE_COUNT = 20 export const LOAD_MORE_COUNT = 20
export const DEFAULT_COLOR_PRIMARY = '#00b96b'
export const THEME_COLOR_PRESETS = [
DEFAULT_COLOR_PRIMARY,
'#FF5470', // Coral Pink
'#14B8A6', // Teal
'#6366F1', // Indigo
'#8B5CF6', // Purple
'#EC4899', // Pink
'#3B82F6', // Blue
'#F59E0B', // Amber
'#6D28D9', // Violet
'#0EA5E9', // Sky Blue
'#0284C7' // Light Blue
]

View File

@ -4,6 +4,7 @@ import Color from 'color'
export default function useUserTheme() { export default function useUserTheme() {
const userTheme = useAppSelector((state) => state.settings.userTheme) const userTheme = useAppSelector((state) => state.settings.userTheme)
const dispatch = useAppDispatch() const dispatch = useAppDispatch()
const initUserTheme = (theme: UserTheme = userTheme) => { const initUserTheme = (theme: UserTheme = userTheme) => {

View File

@ -262,7 +262,7 @@
"settings.show_line_numbers": "Show line numbers in code", "settings.show_line_numbers": "Show line numbers in code",
"settings.temperature": "Temperature", "settings.temperature": "Temperature",
"settings.temperature.tip": "Higher values make the model more creative and unpredictable, while lower values make it more deterministic and precise.", "settings.temperature.tip": "Higher values make the model more creative and unpredictable, while lower values make it more deterministic and precise.",
"settings.thought_auto_collapse": "Automatically Collapse Thought Content", "settings.thought_auto_collapse": "Collapse Thought Content",
"settings.thought_auto_collapse.tip": "Automatically collapse thought content after thinking ends", "settings.thought_auto_collapse.tip": "Automatically collapse thought content after thinking ends",
"settings.top_p": "Top-P", "settings.top_p": "Top-P",
"settings.top_p.tip": "Default value is 1, the smaller the value, the less variety in the answers, the easier to understand, the larger the value, the larger the range of the AI's vocabulary, the more diverse", "settings.top_p.tip": "Default value is 1, the smaller the value, the less variety in the answers, the easier to understand, the larger the value, the larger the range of the AI's vocabulary, the more diverse",
@ -657,7 +657,7 @@
"message.code_style": "Code style", "message.code_style": "Code style",
"message.delete.content": "Are you sure you want to delete this message?", "message.delete.content": "Are you sure you want to delete this message?",
"message.delete.title": "Delete Message", "message.delete.title": "Delete Message",
"message.multi_model_style": "Multi-model response style", "message.multi_model_style": "Group style",
"message.multi_model_style.fold": "Fold view", "message.multi_model_style.fold": "Fold view",
"message.multi_model_style.fold.compress": "Switch to compact layout", "message.multi_model_style.fold.compress": "Switch to compact layout",
"message.multi_model_style.fold.expand": "Switch to expanded layout", "message.multi_model_style.fold.expand": "Switch to expanded layout",
@ -1265,6 +1265,7 @@
"display.sidebar.translate.icon": "Show Translate icon", "display.sidebar.translate.icon": "Show Translate icon",
"display.sidebar.visible": "Show icons", "display.sidebar.visible": "Show icons",
"display.title": "Display Settings", "display.title": "Display Settings",
"display.zoom.title": "Zoom Settings",
"display.topic.title": "Topic Settings", "display.topic.title": "Topic Settings",
"miniapps": { "miniapps": {
"title": "Mini Apps Settings", "title": "Mini Apps Settings",
@ -1500,14 +1501,14 @@
"messages.input.send_shortcuts": "Send shortcuts", "messages.input.send_shortcuts": "Send shortcuts",
"messages.input.show_estimated_tokens": "Show estimated tokens", "messages.input.show_estimated_tokens": "Show estimated tokens",
"messages.input.title": "Input Settings", "messages.input.title": "Input Settings",
"messages.input.enable_quick_triggers": "Enable '/' and '@' triggers", "messages.input.enable_quick_triggers": "Enable / and @ triggers",
"messages.input.enable_delete_model": "Enable the backspace key to delete models/attachments.", "messages.input.enable_delete_model": "Enable the backspace key to delete models/attachments.",
"messages.markdown_rendering_input_message": "Markdown render input message", "messages.markdown_rendering_input_message": "Markdown render input message",
"messages.math_engine": "Math engine", "messages.math_engine": "Math engine",
"messages.math_engine.none": "None", "messages.math_engine.none": "None",
"messages.metrics": "{{time_first_token_millsec}}ms to first token | {{token_speed}} tok/sec", "messages.metrics": "{{time_first_token_millsec}}ms to first token | {{token_speed}} tok/sec",
"messages.model.title": "Model Settings", "messages.model.title": "Model Settings",
"messages.navigation": "Message Navigation", "messages.navigation": "Navigation bar",
"messages.navigation.anchor": "Message Anchor", "messages.navigation.anchor": "Message Anchor",
"messages.navigation.buttons": "Navigation Buttons", "messages.navigation.buttons": "Navigation Buttons",
"messages.navigation.none": "None", "messages.navigation.none": "None",

View File

@ -1263,6 +1263,7 @@
"display.sidebar.translate.icon": "翻訳のアイコンを表示", "display.sidebar.translate.icon": "翻訳のアイコンを表示",
"display.sidebar.visible": "アイコンを表示", "display.sidebar.visible": "アイコンを表示",
"display.title": "表示設定", "display.title": "表示設定",
"display.zoom.title": "ズーム設定",
"display.topic.title": "トピック設定", "display.topic.title": "トピック設定",
"miniapps": { "miniapps": {
"title": "ミニアプリ設定", "title": "ミニアプリ設定",

View File

@ -1264,6 +1264,7 @@
"display.sidebar.translate.icon": "Показывать иконку перевода", "display.sidebar.translate.icon": "Показывать иконку перевода",
"display.sidebar.visible": "Показывать иконки", "display.sidebar.visible": "Показывать иконки",
"display.title": "Настройки отображения", "display.title": "Настройки отображения",
"display.zoom.title": "Настройки масштаба",
"display.topic.title": "Настройки топиков", "display.topic.title": "Настройки топиков",
"miniapps": { "miniapps": {
"title": "Настройки мини-приложений", "title": "Настройки мини-приложений",

View File

@ -1265,6 +1265,7 @@
"display.sidebar.translate.icon": "显示翻译图标", "display.sidebar.translate.icon": "显示翻译图标",
"display.sidebar.visible": "显示的图标", "display.sidebar.visible": "显示的图标",
"display.title": "显示设置", "display.title": "显示设置",
"display.zoom.title": "缩放设置",
"display.topic.title": "话题设置", "display.topic.title": "话题设置",
"miniapps": { "miniapps": {
"title": "小程序设置", "title": "小程序设置",

View File

@ -1265,6 +1265,7 @@
"display.sidebar.translate.icon": "顯示翻譯圖示", "display.sidebar.translate.icon": "顯示翻譯圖示",
"display.sidebar.visible": "顯示的圖示", "display.sidebar.visible": "顯示的圖示",
"display.title": "顯示設定", "display.title": "顯示設定",
"display.zoom.title": "縮放設定",
"display.topic.title": "話題設定", "display.topic.title": "話題設定",
"miniapps": { "miniapps": {
"title": "小程式設置", "title": "小程式設置",

View File

@ -1140,6 +1140,7 @@
"display.sidebar.translate.icon": "Εμφάνιση εικονιδίου μετάφρασης", "display.sidebar.translate.icon": "Εμφάνιση εικονιδίου μετάφρασης",
"display.sidebar.visible": "Εμφανιζόμενα εικονίδια", "display.sidebar.visible": "Εμφανιζόμενα εικονίδια",
"display.title": "Ρυθμίσεις εμφάνισης", "display.title": "Ρυθμίσεις εμφάνισης",
"display.zoom.title": "Ρυθμίσεις κλίμακας",
"display.topic.title": "Ρυθμίσεις Θεμάτων", "display.topic.title": "Ρυθμίσεις Θεμάτων",
"font_size.title": "Μέγεθος γραμμάτων των μηνυμάτων", "font_size.title": "Μέγεθος γραμμάτων των μηνυμάτων",
"general": "Γενικές ρυθμίσεις", "general": "Γενικές ρυθμίσεις",

View File

@ -1139,6 +1139,7 @@
"display.sidebar.translate.icon": "Mostrar icono de traducción", "display.sidebar.translate.icon": "Mostrar icono de traducción",
"display.sidebar.visible": "Iconos visibles", "display.sidebar.visible": "Iconos visibles",
"display.title": "Configuración de visualización", "display.title": "Configuración de visualización",
"display.zoom.title": "Configuración de zoom",
"display.topic.title": "Configuración de tema", "display.topic.title": "Configuración de tema",
"font_size.title": "Tamaño de fuente de mensajes", "font_size.title": "Tamaño de fuente de mensajes",
"general": "Configuración general", "general": "Configuración general",

View File

@ -1140,6 +1140,7 @@
"display.sidebar.translate.icon": "Afficher l'icône de traduction", "display.sidebar.translate.icon": "Afficher l'icône de traduction",
"display.sidebar.visible": "Icônes affichées", "display.sidebar.visible": "Icônes affichées",
"display.title": "Paramètres d'affichage", "display.title": "Paramètres d'affichage",
"display.zoom.title": "Paramètres de zoom",
"display.topic.title": "Paramètres de sujet", "display.topic.title": "Paramètres de sujet",
"font_size.title": "Taille de police des messages", "font_size.title": "Taille de police des messages",
"general": "Paramètres généraux", "general": "Paramètres généraux",

View File

@ -1142,6 +1142,7 @@
"display.sidebar.translate.icon": "Mostrar ícone de tradução", "display.sidebar.translate.icon": "Mostrar ícone de tradução",
"display.sidebar.visible": "Ícones visíveis", "display.sidebar.visible": "Ícones visíveis",
"display.title": "Configurações de exibição", "display.title": "Configurações de exibição",
"display.zoom.title": "Configurações de zoom",
"display.topic.title": "Configurações de tópico", "display.topic.title": "Configurações de tópico",
"font_size.title": "Tamanho da fonte da mensagem", "font_size.title": "Tamanho da fonte da mensagem",
"general": "Configurações gerais", "general": "Configurações gerais",

View File

@ -1,5 +1,6 @@
import { SyncOutlined } from '@ant-design/icons' import { SyncOutlined } from '@ant-design/icons'
import { isMac } from '@renderer/config/constant' import { HStack } from '@renderer/components/Layout'
import { isMac, THEME_COLOR_PRESETS } from '@renderer/config/constant'
import { useTheme } from '@renderer/context/ThemeProvider' import { useTheme } from '@renderer/context/ThemeProvider'
import { useSettings } from '@renderer/hooks/useSettings' import { useSettings } from '@renderer/hooks/useSettings'
import useUserTheme from '@renderer/hooks/useUserTheme' import useUserTheme from '@renderer/hooks/useUserTheme'
@ -15,15 +16,42 @@ import {
setSidebarIcons setSidebarIcons
} from '@renderer/store/settings' } from '@renderer/store/settings'
import { ThemeMode } from '@renderer/types' import { ThemeMode } from '@renderer/types'
import { Minus, Plus, RotateCcw } from 'lucide-react'
import { Button, ColorPicker, Input, Segmented, Switch } from 'antd' import { Button, ColorPicker, Input, Segmented, Switch } from 'antd'
import { FC, useCallback, useMemo, useState, useEffect } from 'react' import { Minus, Plus, RotateCcw } from 'lucide-react'
import { FC, useCallback, useEffect, useMemo, useState } 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, SettingGroup, SettingRow, SettingRowTitle, SettingTitle } from '..' import { SettingContainer, SettingDivider, SettingGroup, SettingRow, SettingRowTitle, SettingTitle } from '..'
import SidebarIconsManager from './SidebarIconsManager' import SidebarIconsManager from './SidebarIconsManager'
const ColorCircleWrapper = styled.div`
width: 24px;
height: 24px;
position: relative;
display: flex;
align-items: center;
justify-content: center;
`
const ColorCircle = styled.div<{ color: string; isActive?: boolean }>`
position: absolute;
top: 50%;
left: 50%;
width: 20px;
height: 20px;
border-radius: 50%;
background-color: ${(props) => props.color};
cursor: pointer;
transform: translate(-50%, -50%);
border: 2px solid ${(props) => (props.isActive ? 'var(--color-border)' : 'transparent')};
transition: opacity 0.2s;
&:hover {
opacity: 0.8;
}
`
const DisplaySettings: FC = () => { const DisplaySettings: FC = () => {
const { const {
setTheme, setTheme,
@ -149,6 +177,48 @@ const DisplaySettings: FC = () => {
<Segmented value={theme} shape="round" onChange={setTheme} options={themeOptions} /> <Segmented value={theme} shape="round" onChange={setTheme} options={themeOptions} />
</SettingRow> </SettingRow>
<SettingDivider /> <SettingDivider />
<SettingRow>
<SettingRowTitle>{t('settings.theme.color_primary')}</SettingRowTitle>
<HStack gap="12px" alignItems="center">
<HStack gap="12px">
{THEME_COLOR_PRESETS.map((color) => (
<ColorCircleWrapper key={color}>
<ColorCircle
color={color}
isActive={userTheme.colorPrimary === color}
onClick={() => handleColorPrimaryChange(color)}
/>
</ColorCircleWrapper>
))}
</HStack>
<ColorPicker
className="color-picker"
value={userTheme.colorPrimary}
onChange={(color) => handleColorPrimaryChange(color.toHexString())}
showText
style={{ width: '110px' }}
presets={[
{
label: 'Presets',
colors: THEME_COLOR_PRESETS
}
]}
/>
</HStack>
</SettingRow>
{isMac && (
<>
<SettingDivider />
<SettingRow>
<SettingRowTitle>{t('settings.theme.window.style.transparent')}</SettingRowTitle>
<Switch checked={windowStyle === 'transparent'} onChange={handleWindowStyleChange} />
</SettingRow>
</>
)}
</SettingGroup>
<SettingGroup theme={theme}>
<SettingTitle>{t('settings.display.zoom.title')}</SettingTitle>
<SettingDivider />
<SettingRow> <SettingRow>
<SettingRowTitle>{t('settings.zoom.title')}</SettingRowTitle> <SettingRowTitle>{t('settings.zoom.title')}</SettingRowTitle>
<ZoomButtonGroup> <ZoomButtonGroup>
@ -162,31 +232,6 @@ const DisplaySettings: FC = () => {
/> />
</ZoomButtonGroup> </ZoomButtonGroup>
</SettingRow> </SettingRow>
<SettingDivider />
<SettingRow>
<SettingRowTitle>{t('settings.theme.color_primary')}</SettingRowTitle>
<ColorPicker
className="color-picker"
value={userTheme.colorPrimary}
onChange={(color) => handleColorPrimaryChange(color.toHexString())}
showText
presets={[
{
label: 'Presets',
colors: ['#007BFF', '#F74F9E', '#FF5257', '#F7821B', '#FFC600', '#62BA46', '#000000']
}
]}
/>
</SettingRow>
{isMac && (
<>
<SettingDivider />
<SettingRow>
<SettingRowTitle>{t('settings.theme.window.style.transparent')}</SettingRowTitle>
<Switch checked={windowStyle === 'transparent'} onChange={handleWindowStyleChange} />
</SettingRow>
</>
)}
</SettingGroup> </SettingGroup>
<SettingGroup theme={theme}> <SettingGroup theme={theme}>
<SettingTitle>{t('settings.display.topic.title')}</SettingTitle> <SettingTitle>{t('settings.display.topic.title')}</SettingTitle>

View File

@ -50,7 +50,7 @@ const persistedReducer = persistReducer(
{ {
key: 'cherry-studio', key: 'cherry-studio',
storage, storage,
version: 107, version: 109,
blacklist: ['runtime', 'messages', 'messageBlocks'], blacklist: ['runtime', 'messages', 'messageBlocks'],
migrate migrate
}, },