feat(Settings): implement assistant icon type selection and localization updates
This commit is contained in:
parent
97ef7016d3
commit
41981acd77
@ -1,10 +1,11 @@
|
||||
import store, { useAppDispatch, useAppSelector } from '@renderer/store'
|
||||
import {
|
||||
AssistantIconType,
|
||||
SendMessageShortcut,
|
||||
setAssistantIconType,
|
||||
setLaunchOnBoot,
|
||||
setLaunchToTray,
|
||||
setSendMessageShortcut as _setSendMessageShortcut,
|
||||
setShowAssistantIcon,
|
||||
setSidebarIcons,
|
||||
setTargetLanguage,
|
||||
setTheme,
|
||||
@ -70,8 +71,8 @@ export function useSettings() {
|
||||
updateSidebarDisabledIcons(icons: SidebarIcon[]) {
|
||||
dispatch(setSidebarIcons({ disabled: icons }))
|
||||
},
|
||||
setShowAssistantIcon(showAssistantIcon: boolean) {
|
||||
dispatch(setShowAssistantIcon(showAssistantIcon))
|
||||
setAssistantIconType(assistantIconType: AssistantIconType) {
|
||||
dispatch(setAssistantIconType(assistantIconType))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,6 +43,7 @@
|
||||
"edit.title": "Edit Assistant",
|
||||
"save.success": "Saved successfully",
|
||||
"save.title": "Save to agent",
|
||||
"icon.type": "Assistant Icon",
|
||||
"search": "Search assistants...",
|
||||
"settings.default_model": "Default Model",
|
||||
"settings.knowledge_base": "Knowledge Base Settings",
|
||||
@ -787,7 +788,10 @@
|
||||
"advanced.title": "Advanced Settings",
|
||||
"assistant": "Default Assistant",
|
||||
"assistant.model_params": "Model Parameters",
|
||||
"assistant.show.icon": "Show model icon",
|
||||
"assistant.icon.type": "Model Icon Type",
|
||||
"assistant.icon.type.model": "Model Icon",
|
||||
"assistant.icon.type.emoji": "Emoji Icon",
|
||||
"assistant.icon.type.none": "Hide",
|
||||
"assistant.title": "Default Assistant",
|
||||
"data": {
|
||||
"app_data": "App Data",
|
||||
|
||||
@ -43,6 +43,7 @@
|
||||
"edit.title": "アシスタントを編集",
|
||||
"save.success": "保存に成功しました",
|
||||
"save.title": "エージェントに保存",
|
||||
"icon.type": "アシスタントアイコン",
|
||||
"search": "アシスタントを検索...",
|
||||
"settings.mcp": "MCP サーバー",
|
||||
"settings.mcp.enableFirst": "まず MCP 設定でこのサーバーを有効にしてください",
|
||||
@ -787,7 +788,10 @@
|
||||
"advanced.title": "詳細設定",
|
||||
"assistant": "デフォルトアシスタント",
|
||||
"assistant.model_params": "モデルパラメータ",
|
||||
"assistant.show.icon": "モデルアイコンを表示",
|
||||
"assistant.icon.type": "モデルアイコンタイプ",
|
||||
"assistant.icon.type.model": "モデルアイコン",
|
||||
"assistant.icon.type.emoji": "Emoji アイコン",
|
||||
"assistant.icon.type.none": "表示しない",
|
||||
"assistant.title": "デフォルトアシスタント",
|
||||
"data": {
|
||||
"app_data": "アプリデータ",
|
||||
|
||||
@ -43,6 +43,7 @@
|
||||
"edit.title": "Редактировать ассистента",
|
||||
"save.success": "Успешно сохранено",
|
||||
"save.title": "Сохранить в агента",
|
||||
"icon.type": "Иконка ассистента",
|
||||
"search": "Поиск ассистентов...",
|
||||
"settings.mcp": "Серверы MCP",
|
||||
"settings.mcp.enableFirst": "Сначала включите этот сервер в настройках MCP",
|
||||
@ -787,7 +788,10 @@
|
||||
"advanced.title": "Расширенные настройки",
|
||||
"assistant": "Ассистент по умолчанию",
|
||||
"assistant.model_params": "Параметры модели",
|
||||
"assistant.show.icon": "Показывать модельный иконки",
|
||||
"assistant.icon.type": "Тип модели иконки",
|
||||
"assistant.icon.type.model": "Модель иконки",
|
||||
"assistant.icon.type.emoji": "Emoji иконка",
|
||||
"assistant.icon.type.none": "Не отображать",
|
||||
"assistant.title": "Ассистент по умолчанию",
|
||||
"data": {
|
||||
"app_data": "Данные приложения",
|
||||
|
||||
@ -43,6 +43,7 @@
|
||||
"edit.title": "编辑助手",
|
||||
"save.success": "保存成功",
|
||||
"save.title": "保存到智能体",
|
||||
"icon.type": "助手图标",
|
||||
"search": "搜索助手",
|
||||
"settings.mcp": "MCP 服务器",
|
||||
"settings.mcp.enableFirst": "请先在 MCP 设置中启用此服务器",
|
||||
@ -787,7 +788,10 @@
|
||||
"advanced.title": "高级设置",
|
||||
"assistant": "默认助手",
|
||||
"assistant.model_params": "模型参数",
|
||||
"assistant.show.icon": "显示模型图标",
|
||||
"assistant.icon.type": "模型图标类型",
|
||||
"assistant.icon.type.model": "模型图标",
|
||||
"assistant.icon.type.emoji": "Emoji 表情",
|
||||
"assistant.icon.type.none": "不显示",
|
||||
"assistant.title": "默认助手",
|
||||
"data": {
|
||||
"app_data": "应用数据",
|
||||
|
||||
@ -43,6 +43,7 @@
|
||||
"edit.title": "編輯助手",
|
||||
"save.success": "儲存成功",
|
||||
"save.title": "儲存到智慧代理人",
|
||||
"icon.type": "助手圖示",
|
||||
"search": "搜尋助手...",
|
||||
"settings.mcp": "MCP 伺服器",
|
||||
"settings.mcp.enableFirst": "請先在 MCP 設定中啟用此伺服器",
|
||||
@ -787,7 +788,10 @@
|
||||
"advanced.title": "進階設定",
|
||||
"assistant": "預設助手",
|
||||
"assistant.model_params": "模型參數",
|
||||
"assistant.show.icon": "顯示模型圖示",
|
||||
"assistant.icon.type": "模型圖示類型",
|
||||
"assistant.icon.type.model": "模型圖示",
|
||||
"assistant.icon.type.emoji": "Emoji 表情",
|
||||
"assistant.icon.type.none": "不顯示",
|
||||
"assistant.title": "預設助手",
|
||||
"data": {
|
||||
"app_data": "應用程式資料",
|
||||
|
||||
@ -3,6 +3,7 @@ import {
|
||||
EditOutlined,
|
||||
MinusCircleOutlined,
|
||||
SaveOutlined,
|
||||
SmileOutlined,
|
||||
SortAscendingOutlined,
|
||||
SortDescendingOutlined
|
||||
} from '@ant-design/icons'
|
||||
@ -39,7 +40,7 @@ interface AssistantItemProps {
|
||||
const AssistantItem: FC<AssistantItemProps> = ({ assistant, isActive, onSwitch, onDelete, addAgent, addAssistant }) => {
|
||||
const { t } = useTranslation()
|
||||
const { removeAllTopics } = useAssistant(assistant.id) // 使用当前助手的ID
|
||||
const { clickAssistantToShowTopic, topicPosition, showAssistantIcon } = useSettings()
|
||||
const { clickAssistantToShowTopic, topicPosition, assistantIconType, setAssistantIconType } = useSettings()
|
||||
const defaultModel = getDefaultModel()
|
||||
const { assistants, updateAssistants } = useAssistants()
|
||||
|
||||
@ -119,6 +120,28 @@ const AssistantItem: FC<AssistantItemProps> = ({ assistant, isActive, onSwitch,
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
label: t('assistants.icon.type'),
|
||||
key: 'icon-type',
|
||||
icon: <SmileOutlined />,
|
||||
children: [
|
||||
{
|
||||
label: t('settings.assistant.icon.type.model'),
|
||||
key: 'model',
|
||||
onClick: () => setAssistantIconType('model')
|
||||
},
|
||||
{
|
||||
label: t('settings.assistant.icon.type.emoji'),
|
||||
key: 'emoji',
|
||||
onClick: () => setAssistantIconType('emoji')
|
||||
},
|
||||
{
|
||||
label: t('settings.assistant.icon.type.none'),
|
||||
key: 'none',
|
||||
onClick: () => setAssistantIconType('none')
|
||||
}
|
||||
]
|
||||
},
|
||||
{ type: 'divider' },
|
||||
{
|
||||
label: t('common.sort.pinyin.asc'),
|
||||
@ -174,18 +197,20 @@ const AssistantItem: FC<AssistantItemProps> = ({ assistant, isActive, onSwitch,
|
||||
<Dropdown menu={{ items: getMenuItems(assistant) }} trigger={['contextMenu']}>
|
||||
<Container onClick={handleSwitch} className={isActive ? 'active' : ''}>
|
||||
<AssistantNameRow className="name" title={fullAssistantName}>
|
||||
{showAssistantIcon ? (
|
||||
{assistantIconType === 'model' ? (
|
||||
<ModelAvatar
|
||||
model={assistant.model || defaultModel}
|
||||
size={22}
|
||||
size={24}
|
||||
className={isPending && !isActive ? 'animation-pulse' : ''}
|
||||
/>
|
||||
) : (
|
||||
<AssistantEmoji
|
||||
$emoji={assistant.emoji || assistantName.slice(0, 1)}
|
||||
className={isPending && !isActive ? 'animation-pulse' : ''}>
|
||||
{assistant.emoji || assistantName.slice(0, 1)}
|
||||
</AssistantEmoji>
|
||||
assistantIconType === 'emoji' && (
|
||||
<AssistantEmoji
|
||||
$emoji={assistant.emoji || assistantName.slice(0, 1)}
|
||||
className={isPending && !isActive ? 'animation-pulse' : ''}>
|
||||
{assistant.emoji || assistantName.slice(0, 1)}
|
||||
</AssistantEmoji>
|
||||
)
|
||||
)}
|
||||
<AssistantName className="text-nowrap">{assistantName}</AssistantName>
|
||||
</AssistantNameRow>
|
||||
@ -203,7 +228,8 @@ const Container = styled.div`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
padding: 7px 10px;
|
||||
padding: 0 10px;
|
||||
height: 37px;
|
||||
position: relative;
|
||||
font-family: Ubuntu;
|
||||
border-radius: var(--list-item-border-radius);
|
||||
@ -231,20 +257,21 @@ const AssistantNameRow = styled.div`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
gap: 8px;
|
||||
`
|
||||
|
||||
const AssistantEmoji = styled.div<{ $emoji: string }>`
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
border-radius: 11px;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
border-radius: 13px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
font-size: 12px;
|
||||
font-size: 15px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
margin-right: 3px;
|
||||
&:before {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@ -261,7 +288,9 @@ const AssistantEmoji = styled.div<{ $emoji: string }>`
|
||||
}
|
||||
`
|
||||
|
||||
const AssistantName = styled.div``
|
||||
const AssistantName = styled.div`
|
||||
font-size: 13px;
|
||||
`
|
||||
|
||||
const MenuButton = styled.div`
|
||||
display: flex;
|
||||
|
||||
@ -4,7 +4,9 @@ import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { useAppDispatch } from '@renderer/store'
|
||||
import {
|
||||
AssistantIconType,
|
||||
DEFAULT_SIDEBAR_ICONS,
|
||||
setAssistantIconType,
|
||||
setClickAssistantToShowTopic,
|
||||
setCustomCss,
|
||||
setShowTopicTime,
|
||||
@ -31,8 +33,7 @@ const DisplaySettings: FC = () => {
|
||||
showTopicTime,
|
||||
customCss,
|
||||
sidebarIcons,
|
||||
showAssistantIcon,
|
||||
setShowAssistantIcon
|
||||
assistantIconType
|
||||
} = useSettings()
|
||||
const { theme: themeMode } = useTheme()
|
||||
const { t } = useTranslation()
|
||||
@ -87,6 +88,15 @@ const DisplaySettings: FC = () => {
|
||||
[t]
|
||||
)
|
||||
|
||||
const assistantIconTypeOptions = useMemo(
|
||||
() => [
|
||||
{ value: 'model', label: t('settings.assistant.icon.type.model') },
|
||||
{ value: 'emoji', label: t('settings.assistant.icon.type.emoji') },
|
||||
{ value: 'none', label: t('settings.assistant.icon.type.none') }
|
||||
],
|
||||
[t]
|
||||
)
|
||||
|
||||
return (
|
||||
<SettingContainer theme={themeMode}>
|
||||
<SettingGroup theme={theme}>
|
||||
@ -143,8 +153,13 @@ const DisplaySettings: FC = () => {
|
||||
<SettingTitle>{t('settings.display.assistant.title')}</SettingTitle>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitle>{t('settings.assistant.show.icon')}</SettingRowTitle>
|
||||
<Switch checked={showAssistantIcon} onChange={(checked) => setShowAssistantIcon(checked)} />
|
||||
<SettingRowTitle>{t('settings.assistant.icon.type')}</SettingRowTitle>
|
||||
<Segmented
|
||||
value={assistantIconType}
|
||||
shape="round"
|
||||
onChange={(value) => dispatch(setAssistantIconType(value as AssistantIconType))}
|
||||
options={assistantIconTypeOptions}
|
||||
/>
|
||||
</SettingRow>
|
||||
</SettingGroup>
|
||||
<SettingGroup theme={theme}>
|
||||
|
||||
@ -42,7 +42,7 @@ const persistedReducer = persistReducer(
|
||||
{
|
||||
key: 'cherry-studio',
|
||||
storage,
|
||||
version: 95,
|
||||
version: 96,
|
||||
blacklist: ['runtime', 'messages'],
|
||||
migrate
|
||||
},
|
||||
|
||||
@ -1213,6 +1213,17 @@ const migrateConfig = {
|
||||
} catch (error) {
|
||||
return state
|
||||
}
|
||||
},
|
||||
'96': (state: RootState) => {
|
||||
try {
|
||||
// @ts-ignore eslint-disable-next-line
|
||||
state.settings.assistantIconType = state.settings?.showAssistantIcon ? 'model' : 'emoji'
|
||||
// @ts-ignore eslint-disable-next-line
|
||||
delete state.settings.showAssistantIcon
|
||||
return state
|
||||
} catch (error) {
|
||||
return state
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -21,6 +21,8 @@ export const DEFAULT_SIDEBAR_ICONS: SidebarIcon[] = [
|
||||
|
||||
export interface NutstoreSyncRuntime extends WebDAVSyncState {}
|
||||
|
||||
export type AssistantIconType = 'model' | 'emoji' | 'none'
|
||||
|
||||
export interface SettingsState {
|
||||
showAssistants: boolean
|
||||
showTopics: boolean
|
||||
@ -42,7 +44,7 @@ export interface SettingsState {
|
||||
fontSize: number
|
||||
topicPosition: 'left' | 'right'
|
||||
showTopicTime: boolean
|
||||
showAssistantIcon: boolean
|
||||
assistantIconType: AssistantIconType
|
||||
pasteLongTextAsFile: boolean
|
||||
pasteLongTextThreshold: number
|
||||
clickAssistantToShowTopic: boolean
|
||||
@ -147,7 +149,7 @@ export const initialState: SettingsState = {
|
||||
fontSize: 14,
|
||||
topicPosition: 'left',
|
||||
showTopicTime: false,
|
||||
showAssistantIcon: false,
|
||||
assistantIconType: 'emoji',
|
||||
pasteLongTextAsFile: false,
|
||||
pasteLongTextThreshold: 1500,
|
||||
clickAssistantToShowTopic: true,
|
||||
@ -294,8 +296,8 @@ const settingsSlice = createSlice({
|
||||
setShowTopicTime: (state, action: PayloadAction<boolean>) => {
|
||||
state.showTopicTime = action.payload
|
||||
},
|
||||
setShowAssistantIcon: (state, action: PayloadAction<boolean>) => {
|
||||
state.showAssistantIcon = action.payload
|
||||
setAssistantIconType: (state, action: PayloadAction<AssistantIconType>) => {
|
||||
state.assistantIconType = action.payload
|
||||
},
|
||||
setPasteLongTextAsFile: (state, action: PayloadAction<boolean>) => {
|
||||
state.pasteLongTextAsFile = action.payload
|
||||
@ -508,7 +510,7 @@ export const {
|
||||
setWindowStyle,
|
||||
setTopicPosition,
|
||||
setShowTopicTime,
|
||||
setShowAssistantIcon,
|
||||
setAssistantIconType,
|
||||
setPasteLongTextAsFile,
|
||||
setAutoCheckUpdate,
|
||||
setRenderInputMessageAsMarkdown,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user