mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-19 14:41:24 +08:00
refactor(ui): improve settings tab and assistant item UI (#11819)
* refactor(ui): improve settings tab and assistant item UI - Remove SettingsTab from HomeTabs, open settings via navbar drawer instead - Add menu icon to assistant/agent items for quick access to settings popup - Remove SessionSettingsTab component (consolidated into settings popup) - Restore avatar display in bubble message style - Update topic/session item styles for consistency 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor(ui): simplify MessageHeader component logic - Removed unnecessary header visibility check in MessageHeader. - Updated justifyContent logic for UserWrap to account for multi-select mode. This change enhances the clarity and maintainability of the MessageHeader component. * refactor(ui): streamline ChatNavbar and SettingsTab components - Removed unused chat state from ChatNavbar. - Updated SettingsTab to conditionally render settings based on active topic or session. - Enhanced clarity and maintainability by reducing unnecessary checks and improving component logic. This change improves the overall user experience and code readability. * refactor(ui): enhance AgentItem and ChatNavbar components for improved UI - Updated AgentItem to conditionally hide the assistant icon based on settings. - Enhanced ChatNavbar to display the assistant's emoji and name with a new layout. - Introduced memoization for assistant name to optimize rendering. These changes improve the user interface and maintainability of the components. * refactor(ui): update HtmlArtifactsPopup to start in fullscreen mode - Changed initial state of isFullscreen in HtmlArtifactsPopup from false to true. This adjustment enhances the user experience by providing a more immersive view upon opening the popup. * refactor(types): remove 'settings' tab from Tab type - Updated the Tab type in chat.ts to remove the 'settings' option, simplifying the available tabs for the chat interface. This change streamlines the chat functionality and improves code clarity. * refactor(ui): enhance UserWrap styling in MessageHeader component - Added flex property to UserWrap to improve layout flexibility. This change enhances the responsiveness and layout management of the MessageHeader component. * refactor(ui): update HtmlArtifactsPopup to prevent drag on ViewControls - Added "nodrag" class to ViewControls to prevent drag events on double click. This change improves the user interaction by ensuring that double-clicking on the ViewControls does not trigger drag actions. * refactor(ui): adjust spacing in AgentLabel component - Updated the gap between items in the AgentLabel component from 1 to 2 for improved layout consistency. This change enhances the visual spacing and overall user interface of the AgentSettings page. * refactor(ui): remove unused useSessions hook from AgentItem component - Eliminated the useSessions hook from the AgentItem component to streamline the code and improve performance. This change enhances the maintainability of the AgentItem component by removing unnecessary dependencies. * refactor(ui): optimize MessageHeader component layout and logic - Introduced a memoized userNameJustifyContent calculation to streamline the justifyContent logic for UserWrap. - Simplified the HStack component by replacing inline logic with the new memoized value. These changes enhance the maintainability and clarity of the MessageHeader component. --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
5f3af646f4
commit
367c4fe6b6
@ -25,7 +25,7 @@ type ViewMode = 'split' | 'code' | 'preview'
|
||||
const HtmlArtifactsPopup: React.FC<HtmlArtifactsPopupProps> = ({ open, title, html, onSave, onClose }) => {
|
||||
const { t } = useTranslation()
|
||||
const [viewMode, setViewMode] = useState<ViewMode>('split')
|
||||
const [isFullscreen, setIsFullscreen] = useState(false)
|
||||
const [isFullscreen, setIsFullscreen] = useState(true)
|
||||
const [saved, setSaved] = useTemporaryValue(false, 2000)
|
||||
const codeEditorRef = useRef<CodeEditorHandles>(null)
|
||||
const previewFrameRef = useRef<HTMLIFrameElement>(null)
|
||||
@ -78,7 +78,7 @@ const HtmlArtifactsPopup: React.FC<HtmlArtifactsPopupProps> = ({ open, title, ht
|
||||
</HeaderLeft>
|
||||
|
||||
<HeaderCenter>
|
||||
<ViewControls onDoubleClick={(e) => e.stopPropagation()}>
|
||||
<ViewControls onDoubleClick={(e) => e.stopPropagation()} className="nodrag">
|
||||
<ViewButton
|
||||
size="small"
|
||||
type={viewMode === 'split' ? 'primary' : 'default'}
|
||||
|
||||
@ -89,10 +89,7 @@ const Sidebar: FC = () => {
|
||||
)}
|
||||
</MainMenusContainer>
|
||||
<Menus>
|
||||
<Tooltip
|
||||
title={t('settings.theme.title') + ': ' + getThemeModeLabel(settedTheme)}
|
||||
mouseEnterDelay={0.8}
|
||||
placement="right">
|
||||
<Tooltip title={t('settings.theme.title') + ': ' + getThemeModeLabel(settedTheme)} placement="right">
|
||||
<Icon theme={theme} onClick={toggleTheme}>
|
||||
{settedTheme === ThemeMode.dark ? (
|
||||
<Moon size={20} className="icon" />
|
||||
|
||||
@ -19,6 +19,7 @@ import styled from 'styled-components'
|
||||
|
||||
import AssistantsDrawer from './components/AssistantsDrawer'
|
||||
import ChatNavbarContent from './components/ChatNavbarContent'
|
||||
import SettingsButton from './components/SettingsButton'
|
||||
import UpdateAppButton from './components/UpdateAppButton'
|
||||
|
||||
interface Props {
|
||||
@ -65,14 +66,6 @@ const HeaderNavbar: FC<Props> = ({ activeAssistant, setActiveAssistant, activeTo
|
||||
})
|
||||
}
|
||||
|
||||
// const handleUpdateModel = useCallback(
|
||||
// async (model: ApiModel) => {
|
||||
// if (!activeSession || !activeAgent) return
|
||||
// return updateModel(activeSession.id, model.id, { showSuccessToast: false })
|
||||
// },
|
||||
// [activeAgent, activeSession, updateModel]
|
||||
// )
|
||||
|
||||
return (
|
||||
<NavbarHeader className="home-navbar" style={{ height: 'var(--navbar-height)' }}>
|
||||
<div className="flex h-full min-w-0 flex-1 shrink items-center overflow-auto">
|
||||
@ -107,6 +100,7 @@ const HeaderNavbar: FC<Props> = ({ activeAssistant, setActiveAssistant, activeTo
|
||||
</div>
|
||||
<HStack alignItems="center" gap={8}>
|
||||
{isTopNavbar && <UpdateAppButton />}
|
||||
<SettingsButton assistant={assistant} />
|
||||
{isTopNavbar && (
|
||||
<Tooltip title={t('navbar.expand')} mouseEnterDelay={0.8}>
|
||||
<NarrowIcon onClick={handleNarrowModeToggle}>
|
||||
|
||||
@ -429,7 +429,7 @@ const FileBlocksContainer = styled.div`
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
padding: 0 15px;
|
||||
padding: 0;
|
||||
margin: 8px 0;
|
||||
background: transparent;
|
||||
border-radius: 4px;
|
||||
|
||||
@ -83,11 +83,11 @@ const MessageHeader: FC<Props> = memo(({ assistant, model, message, topic, isGro
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [model?.provider, showMinappIcon])
|
||||
|
||||
const hideHeader = isBubbleStyle ? isUserMessage && !isMultiSelectMode : false
|
||||
|
||||
if (hideHeader) {
|
||||
return null
|
||||
}
|
||||
const userNameJustifyContent = useMemo(() => {
|
||||
if (!isBubbleStyle) return 'flex-start'
|
||||
if (isUserMessage && !isMultiSelectMode) return 'flex-end'
|
||||
return 'flex-start'
|
||||
}, [isBubbleStyle, isUserMessage, isMultiSelectMode])
|
||||
|
||||
return (
|
||||
<Container className="message-header">
|
||||
@ -121,7 +121,7 @@ const MessageHeader: FC<Props> = memo(({ assistant, model, message, topic, isGro
|
||||
</>
|
||||
)}
|
||||
<UserWrap>
|
||||
<HStack alignItems="center">
|
||||
<HStack alignItems="center" justifyContent={userNameJustifyContent}>
|
||||
<UserName isBubbleStyle={isBubbleStyle} theme={theme}>
|
||||
{username}
|
||||
</UserName>
|
||||
|
||||
@ -63,7 +63,10 @@ const Prompt: FC<Props> = ({ assistant, topic }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Container className="system-prompt" onClick={() => AssistantSettingsPopup.show({ assistant })} $isDark={isDark}>
|
||||
<Container
|
||||
className="system-prompt"
|
||||
onClick={() => AssistantSettingsPopup.show({ assistant, tab: 'prompt' })}
|
||||
$isDark={isDark}>
|
||||
<Text $isVisible={isVisible}>{displayText}</Text>
|
||||
</Container>
|
||||
)
|
||||
|
||||
@ -1,45 +0,0 @@
|
||||
import type { useUpdateSession } from '@renderer/hooks/agents/useUpdateSession'
|
||||
import { SettingDivider } from '@renderer/pages/settings'
|
||||
import { SessionSettingsPopup } from '@renderer/pages/settings/AgentSettings'
|
||||
import AdvancedSettings from '@renderer/pages/settings/AgentSettings/AdvancedSettings'
|
||||
import EssentialSettings from '@renderer/pages/settings/AgentSettings/EssentialSettings'
|
||||
import type { GetAgentSessionResponse } from '@renderer/types'
|
||||
import { Button } from 'antd'
|
||||
import type { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
interface Props {
|
||||
session: GetAgentSessionResponse | undefined | null
|
||||
update: ReturnType<typeof useUpdateSession>['updateSession']
|
||||
}
|
||||
|
||||
const SessionSettingsTab: FC<Props> = ({ session, update }) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const onMoreSetting = () => {
|
||||
if (session?.id) {
|
||||
SessionSettingsPopup.show({
|
||||
agentId: session.agent_id,
|
||||
sessionId: session.id
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (!session) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-[var(--assistants-width)] p-2 px-3 pt-4">
|
||||
<EssentialSettings agentBase={session} update={update} showModelSetting={false} />
|
||||
<SettingDivider />
|
||||
<AdvancedSettings agentBase={session} update={update} />
|
||||
<SettingDivider />
|
||||
<Button size="small" block onClick={onMoreSetting}>
|
||||
{t('settings.moresetting.label')}
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default SessionSettingsTab
|
||||
@ -1,24 +1,17 @@
|
||||
import EditableNumber from '@renderer/components/EditableNumber'
|
||||
import { HStack } from '@renderer/components/Layout'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
import Selector from '@renderer/components/Selector'
|
||||
import { HelpTooltip } from '@renderer/components/TooltipIcons'
|
||||
import {
|
||||
DEFAULT_CONTEXTCOUNT,
|
||||
DEFAULT_MAX_TOKENS,
|
||||
DEFAULT_TEMPERATURE,
|
||||
MAX_CONTEXT_COUNT
|
||||
} from '@renderer/config/constant'
|
||||
import { isOpenAIModel, isSupportVerbosityModel } from '@renderer/config/models'
|
||||
import { UNKNOWN } from '@renderer/config/translate'
|
||||
import { useCodeStyle } from '@renderer/context/CodeStyleProvider'
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { useAssistant } from '@renderer/hooks/useAssistant'
|
||||
import { useProvider } from '@renderer/hooks/useProvider'
|
||||
import { useRuntime } from '@renderer/hooks/useRuntime'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import useTranslate from '@renderer/hooks/useTranslate'
|
||||
import { SettingDivider, SettingRow, SettingRowTitle } from '@renderer/pages/settings'
|
||||
import AssistantSettingsPopup from '@renderer/pages/settings/AssistantSettings'
|
||||
import { CollapsibleSettingGroup } from '@renderer/pages/settings/SettingGroup'
|
||||
import { getDefaultModel } from '@renderer/services/AssistantService'
|
||||
import { useAppDispatch } from '@renderer/store'
|
||||
@ -52,19 +45,17 @@ import {
|
||||
setShowTranslateConfirm,
|
||||
setThoughtAutoCollapse
|
||||
} from '@renderer/store/settings'
|
||||
import type { Assistant, AssistantSettings, CodeStyleVarious, MathEngine } from '@renderer/types'
|
||||
import type { Assistant, CodeStyleVarious, MathEngine } from '@renderer/types'
|
||||
import { isGroqSystemProvider, ThemeMode } from '@renderer/types'
|
||||
import { modalConfirm } from '@renderer/utils'
|
||||
import { getSendMessageShortcutLabel } from '@renderer/utils/input'
|
||||
import {
|
||||
isOpenAICompatibleProvider,
|
||||
isSupportServiceTierProvider,
|
||||
isSupportVerbosityProvider
|
||||
} from '@renderer/utils/provider'
|
||||
import { Button, Col, InputNumber, Row, Slider, Switch } from 'antd'
|
||||
import { Settings2 } from 'lucide-react'
|
||||
import { Col, Row, Slider, Switch } from 'antd'
|
||||
import type { FC } from 'react'
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
|
||||
@ -76,20 +67,15 @@ interface Props {
|
||||
}
|
||||
|
||||
const SettingsTab: FC<Props> = (props) => {
|
||||
const { assistant, updateAssistantSettings } = useAssistant(props.assistant.id)
|
||||
const { chat } = useRuntime()
|
||||
const { assistant } = useAssistant(props.assistant.id)
|
||||
const { provider } = useProvider(assistant.model.provider)
|
||||
|
||||
const { messageStyle, fontSize, language } = useSettings()
|
||||
const { theme } = useTheme()
|
||||
const { themeNames } = useCodeStyle()
|
||||
|
||||
const [temperature, setTemperature] = useState(assistant?.settings?.temperature ?? DEFAULT_TEMPERATURE)
|
||||
const [enableTemperature, setEnableTemperature] = useState(assistant?.settings?.enableTemperature ?? true)
|
||||
const [contextCount, setContextCount] = useState(assistant?.settings?.contextCount ?? DEFAULT_CONTEXTCOUNT)
|
||||
const [enableMaxTokens, setEnableMaxTokens] = useState(assistant?.settings?.enableMaxTokens ?? false)
|
||||
const [maxTokens, setMaxTokens] = useState(assistant?.settings?.maxTokens ?? 0)
|
||||
const [fontSizeValue, setFontSizeValue] = useState(fontSize)
|
||||
const [streamOutput, setStreamOutput] = useState(assistant?.settings?.streamOutput)
|
||||
const { translateLanguages } = useTranslate()
|
||||
|
||||
const { t } = useTranslation()
|
||||
@ -128,28 +114,6 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
confirmRegenerateMessage
|
||||
} = useSettings()
|
||||
|
||||
const onUpdateAssistantSettings = (settings: Partial<AssistantSettings>) => {
|
||||
updateAssistantSettings(settings)
|
||||
}
|
||||
|
||||
const onTemperatureChange = (value) => {
|
||||
if (!isNaN(value as number)) {
|
||||
onUpdateAssistantSettings({ temperature: value })
|
||||
}
|
||||
}
|
||||
|
||||
const onContextCountChange = (value) => {
|
||||
if (!isNaN(value as number)) {
|
||||
onUpdateAssistantSettings({ contextCount: value })
|
||||
}
|
||||
}
|
||||
|
||||
const onMaxTokensChange = (value) => {
|
||||
if (!isNaN(value as number)) {
|
||||
onUpdateAssistantSettings({ maxTokens: value })
|
||||
}
|
||||
}
|
||||
|
||||
const codeStyle = useMemo(() => {
|
||||
return codeEditor.enabled
|
||||
? theme === ThemeMode.light
|
||||
@ -176,15 +140,6 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
[dispatch, theme, codeEditor.enabled]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
setTemperature(assistant?.settings?.temperature ?? DEFAULT_TEMPERATURE)
|
||||
setEnableTemperature(assistant?.settings?.enableTemperature ?? true)
|
||||
setContextCount(assistant?.settings?.contextCount ?? DEFAULT_CONTEXTCOUNT)
|
||||
setEnableMaxTokens(assistant?.settings?.enableMaxTokens ?? false)
|
||||
setMaxTokens(assistant?.settings?.maxTokens ?? DEFAULT_MAX_TOKENS)
|
||||
setStreamOutput(assistant?.settings?.streamOutput ?? true)
|
||||
}, [assistant])
|
||||
|
||||
const model = assistant.model || getDefaultModel()
|
||||
|
||||
const showOpenAiSettings =
|
||||
@ -193,173 +148,36 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
isSupportServiceTierProvider(provider) ||
|
||||
(isSupportVerbosityModel(model) && isSupportVerbosityProvider(provider))
|
||||
|
||||
const isTopicSettings = chat.activeTopicOrSession === 'topic'
|
||||
|
||||
return (
|
||||
<Container className="settings-tab">
|
||||
{props.assistant.id !== 'fake' && (
|
||||
<CollapsibleSettingGroup
|
||||
title={t('assistants.settings.title')}
|
||||
defaultExpanded={true}
|
||||
extra={
|
||||
<HStack alignItems="center" gap={2}>
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
icon={<Settings2 size={16} />}
|
||||
onClick={() => AssistantSettingsPopup.show({ assistant, tab: 'model' })}
|
||||
/>
|
||||
</HStack>
|
||||
}>
|
||||
<SettingGroup style={{ marginTop: 5 }}>
|
||||
<Row align="middle">
|
||||
<SettingRowTitleSmall>
|
||||
{t('chat.settings.temperature.label')}
|
||||
<HelpTooltip title={t('chat.settings.temperature.tip')} />
|
||||
</SettingRowTitleSmall>
|
||||
<Switch
|
||||
size="small"
|
||||
style={{ marginLeft: 'auto' }}
|
||||
checked={enableTemperature}
|
||||
onChange={(enabled) => {
|
||||
setEnableTemperature(enabled)
|
||||
onUpdateAssistantSettings({ enableTemperature: enabled })
|
||||
}}
|
||||
/>
|
||||
</Row>
|
||||
{enableTemperature ? (
|
||||
<Row align="middle" gutter={10}>
|
||||
<Col span={23}>
|
||||
<Slider
|
||||
min={0}
|
||||
max={2}
|
||||
onChange={setTemperature}
|
||||
onChangeComplete={onTemperatureChange}
|
||||
value={typeof temperature === 'number' ? temperature : 0}
|
||||
step={0.1}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
) : (
|
||||
<SettingDivider />
|
||||
)}
|
||||
<Row align="middle" gutter={10} justify="space-between">
|
||||
<SettingRowTitleSmall>
|
||||
{t('chat.settings.context_count.label')}
|
||||
<HelpTooltip title={t('chat.settings.context_count.tip')} />
|
||||
</SettingRowTitleSmall>
|
||||
<Col span={8}>
|
||||
<EditableNumber
|
||||
min={0}
|
||||
max={20}
|
||||
step={1}
|
||||
value={contextCount}
|
||||
changeOnBlur
|
||||
onChange={(value) => {
|
||||
if (value !== null && value >= 0 && value <= 20) {
|
||||
setContextCount(value)
|
||||
onContextCountChange(value)
|
||||
}
|
||||
}}
|
||||
formatter={(value) => (value === MAX_CONTEXT_COUNT ? t('chat.settings.max') : (value ?? ''))}
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row align="middle" gutter={10}>
|
||||
<Col span={24}>
|
||||
<Slider
|
||||
min={0}
|
||||
max={20}
|
||||
onChange={setContextCount}
|
||||
onChangeComplete={onContextCountChange}
|
||||
value={Math.min(contextCount, 20)}
|
||||
tooltip={{ open: false }}
|
||||
step={1}
|
||||
marks={{
|
||||
0: '0',
|
||||
10: '10',
|
||||
20: '20'
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('models.stream_output')}</SettingRowTitleSmall>
|
||||
<Switch
|
||||
size="small"
|
||||
checked={streamOutput}
|
||||
onChange={(checked) => {
|
||||
setStreamOutput(checked)
|
||||
onUpdateAssistantSettings({ streamOutput: checked })
|
||||
}}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<Row align="middle">
|
||||
<SettingRowTitleSmall>
|
||||
{t('chat.settings.max_tokens.label')}
|
||||
<HelpTooltip title={t('chat.settings.max_tokens.tip')} />
|
||||
</SettingRowTitleSmall>
|
||||
</Row>
|
||||
<Switch
|
||||
size="small"
|
||||
checked={enableMaxTokens}
|
||||
onChange={async (enabled) => {
|
||||
if (enabled) {
|
||||
const confirmed = await modalConfirm({
|
||||
title: t('chat.settings.max_tokens.confirm'),
|
||||
content: t('chat.settings.max_tokens.confirm_content'),
|
||||
okButtonProps: {
|
||||
danger: true
|
||||
}
|
||||
})
|
||||
if (!confirmed) return
|
||||
}
|
||||
setEnableMaxTokens(enabled)
|
||||
onUpdateAssistantSettings({ enableMaxTokens: enabled })
|
||||
}}
|
||||
/>
|
||||
</SettingRow>
|
||||
{enableMaxTokens && (
|
||||
<Row align="middle" gutter={10} style={{ marginTop: 10 }}>
|
||||
<Col span={24}>
|
||||
<InputNumber
|
||||
disabled={!enableMaxTokens}
|
||||
min={0}
|
||||
max={10000000}
|
||||
step={100}
|
||||
value={typeof maxTokens === 'number' ? maxTokens : 0}
|
||||
changeOnBlur
|
||||
onChange={(value) => value && setMaxTokens(value)}
|
||||
onBlur={() => onMaxTokensChange(maxTokens)}
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
)}
|
||||
<SettingDivider />
|
||||
</SettingGroup>
|
||||
</CollapsibleSettingGroup>
|
||||
)}
|
||||
{showOpenAiSettings && (
|
||||
<OpenAISettingsGroup
|
||||
model={model}
|
||||
providerId={provider.id}
|
||||
SettingGroup={SettingGroup}
|
||||
SettingRowTitleSmall={SettingRowTitleSmall}
|
||||
/>
|
||||
)}
|
||||
{isGroqSystemProvider(provider) && (
|
||||
<GroqSettingsGroup SettingGroup={SettingGroup} SettingRowTitleSmall={SettingRowTitleSmall} />
|
||||
{isTopicSettings && (
|
||||
<>
|
||||
{showOpenAiSettings && (
|
||||
<OpenAISettingsGroup
|
||||
model={model}
|
||||
providerId={provider.id}
|
||||
SettingGroup={SettingGroup}
|
||||
SettingRowTitleSmall={SettingRowTitleSmall}
|
||||
/>
|
||||
)}
|
||||
{isGroqSystemProvider(provider) && (
|
||||
<GroqSettingsGroup SettingGroup={SettingGroup} SettingRowTitleSmall={SettingRowTitleSmall} />
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
<CollapsibleSettingGroup title={t('settings.messages.title')} defaultExpanded={true}>
|
||||
<SettingGroup>
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('settings.messages.prompt')}</SettingRowTitleSmall>
|
||||
<Switch size="small" checked={showPrompt} onChange={(checked) => dispatch(setShowPrompt(checked))} />
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
{isTopicSettings && (
|
||||
<>
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('settings.messages.prompt')}</SettingRowTitleSmall>
|
||||
<Switch size="small" checked={showPrompt} onChange={(checked) => dispatch(setShowPrompt(checked))} />
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
</>
|
||||
)}
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('settings.messages.use_serif_font')}</SettingRowTitleSmall>
|
||||
<Switch
|
||||
@ -381,15 +199,19 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('settings.messages.show_message_outline')}</SettingRowTitleSmall>
|
||||
<Switch
|
||||
size="small"
|
||||
checked={showMessageOutline}
|
||||
onChange={(checked) => dispatch(setShowMessageOutline(checked))}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
{isTopicSettings && (
|
||||
<>
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('settings.messages.show_message_outline')}</SettingRowTitleSmall>
|
||||
<Switch
|
||||
size="small"
|
||||
checked={showMessageOutline}
|
||||
onChange={(checked) => dispatch(setShowMessageOutline(checked))}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
</>
|
||||
)}
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('message.message.style.label')}</SettingRowTitleSmall>
|
||||
<Selector
|
||||
@ -402,20 +224,24 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('message.message.multi_model_style.label')}</SettingRowTitleSmall>
|
||||
<Selector
|
||||
value={multiModelMessageStyle}
|
||||
onChange={(value) => dispatch(setMultiModelMessageStyle(value))}
|
||||
options={[
|
||||
{ value: 'fold', label: t('message.message.multi_model_style.fold.label') },
|
||||
{ value: 'vertical', label: t('message.message.multi_model_style.vertical') },
|
||||
{ value: 'horizontal', label: t('message.message.multi_model_style.horizontal') },
|
||||
{ value: 'grid', label: t('message.message.multi_model_style.grid') }
|
||||
]}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
{isTopicSettings && (
|
||||
<>
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('message.message.multi_model_style.label')}</SettingRowTitleSmall>
|
||||
<Selector
|
||||
value={multiModelMessageStyle}
|
||||
onChange={(value) => dispatch(setMultiModelMessageStyle(value))}
|
||||
options={[
|
||||
{ value: 'fold', label: t('message.message.multi_model_style.fold.label') },
|
||||
{ value: 'vertical', label: t('message.message.multi_model_style.vertical') },
|
||||
{ value: 'horizontal', label: t('message.message.multi_model_style.horizontal') },
|
||||
{ value: 'grid', label: t('message.message.multi_model_style.grid') }
|
||||
]}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
</>
|
||||
)}
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('settings.messages.navigation.label')}</SettingRowTitleSmall>
|
||||
<Selector
|
||||
@ -627,15 +453,19 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
</CollapsibleSettingGroup>
|
||||
<CollapsibleSettingGroup title={t('settings.messages.input.title')} defaultExpanded={false}>
|
||||
<SettingGroup>
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('settings.messages.input.show_estimated_tokens')}</SettingRowTitleSmall>
|
||||
<Switch
|
||||
size="small"
|
||||
checked={showInputEstimatedTokens}
|
||||
onChange={(checked) => dispatch(setShowInputEstimatedTokens(checked))}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
{isTopicSettings && (
|
||||
<>
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('settings.messages.input.show_estimated_tokens')}</SettingRowTitleSmall>
|
||||
<Switch
|
||||
size="small"
|
||||
checked={showInputEstimatedTokens}
|
||||
onChange={(checked) => dispatch(setShowInputEstimatedTokens(checked))}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
</>
|
||||
)}
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('settings.messages.input.paste_long_text_as_file')}</SettingRowTitleSmall>
|
||||
<Switch
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { DeleteIcon, EditIcon } from '@renderer/components/Icons'
|
||||
import { useSessions } from '@renderer/hooks/agents/useSessions'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import AgentSettingsPopup from '@renderer/pages/settings/AgentSettings/AgentSettingsPopup'
|
||||
import { AgentLabel } from '@renderer/pages/settings/AgentSettings/shared'
|
||||
@ -8,7 +7,7 @@ import type { AgentEntity } from '@renderer/types'
|
||||
import { cn } from '@renderer/utils'
|
||||
import type { MenuProps } from 'antd'
|
||||
import { Dropdown, Tooltip } from 'antd'
|
||||
import { Bot } from 'lucide-react'
|
||||
import { Bot, MoreVertical } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { memo, useCallback, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -24,8 +23,7 @@ interface AgentItemProps {
|
||||
|
||||
const AgentItem: FC<AgentItemProps> = ({ agent, isActive, onDelete, onPress }) => {
|
||||
const { t } = useTranslation()
|
||||
const { sessions } = useSessions(agent.id)
|
||||
const { clickAssistantToShowTopic, topicPosition } = useSettings()
|
||||
const { clickAssistantToShowTopic, topicPosition, assistantIconType } = useSettings()
|
||||
|
||||
const handlePress = useCallback(() => {
|
||||
// Show session sidebar if setting is enabled (reusing the assistant setting for consistency)
|
||||
@ -37,6 +35,14 @@ const AgentItem: FC<AgentItemProps> = ({ agent, isActive, onDelete, onPress }) =
|
||||
onPress()
|
||||
}, [clickAssistantToShowTopic, topicPosition, onPress])
|
||||
|
||||
const handleMoreClick = useCallback(
|
||||
(e: React.MouseEvent) => {
|
||||
e.stopPropagation()
|
||||
agent.id && AgentSettingsPopup.show({ agentId: agent.id })
|
||||
},
|
||||
[agent.id]
|
||||
)
|
||||
|
||||
const menuItems: MenuProps['items'] = useMemo(
|
||||
() => [
|
||||
{
|
||||
@ -72,14 +78,14 @@ const AgentItem: FC<AgentItemProps> = ({ agent, isActive, onDelete, onPress }) =
|
||||
<Container onClick={handlePress} isActive={isActive}>
|
||||
<AssistantNameRow className="name" title={agent.name ?? agent.id}>
|
||||
<AgentNameWrapper>
|
||||
<AgentLabel agent={agent} />
|
||||
<AgentLabel agent={agent} hideIcon={assistantIconType === 'none'} />
|
||||
</AgentNameWrapper>
|
||||
{isActive && (
|
||||
<MenuButton>
|
||||
<SessionCount>{sessions.length}</SessionCount>
|
||||
<MenuButton onClick={handleMoreClick}>
|
||||
<MoreVertical size={14} className="text-[var(--color-text-secondary)]" />
|
||||
</MenuButton>
|
||||
)}
|
||||
{!isActive && <BotIcon />}
|
||||
{!isActive && assistantIconType !== 'none' && <BotIcon />}
|
||||
</AssistantNameRow>
|
||||
</Container>
|
||||
</Dropdown>
|
||||
@ -116,7 +122,7 @@ export const AgentNameWrapper: React.FC<React.HTMLAttributes<HTMLDivElement>> =
|
||||
export const MenuButton: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({ className, ...props }) => (
|
||||
<div
|
||||
className={cn(
|
||||
'flex h-5 min-h-5 w-5 flex-row items-center justify-center rounded-full border border-[var(--color-border)] bg-[var(--color-background)]',
|
||||
'flex h-[22px] min-h-[22px] min-w-[22px] flex-row items-center justify-center rounded-[11px] border-[0.5px] border-[var(--color-border)] bg-[var(--color-background)] px-[5px]',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@ -22,6 +22,7 @@ import {
|
||||
ArrowUpAZ,
|
||||
BrushCleaning,
|
||||
Check,
|
||||
MoreVertical,
|
||||
Plus,
|
||||
Save,
|
||||
Settings2,
|
||||
@ -150,6 +151,14 @@ const AssistantItem: FC<AssistantItemProps> = ({
|
||||
[assistant.emoji, assistantName]
|
||||
)
|
||||
|
||||
const handleMoreClick = useCallback(
|
||||
(e: React.MouseEvent) => {
|
||||
e.stopPropagation()
|
||||
AssistantSettingsPopup.show({ assistant })
|
||||
},
|
||||
[assistant]
|
||||
)
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
menu={{ items: menuItems }}
|
||||
@ -174,8 +183,8 @@ const AssistantItem: FC<AssistantItemProps> = ({
|
||||
<AssistantName className="text-nowrap">{assistantName}</AssistantName>
|
||||
</AssistantNameRow>
|
||||
{isActive && (
|
||||
<MenuButton onClick={() => EventEmitter.emit(EVENT_NAMES.SWITCH_TOPIC_SIDEBAR)}>
|
||||
<TopicCount className="topics-count">{assistant.topics.length}</TopicCount>
|
||||
<MenuButton onClick={handleMoreClick}>
|
||||
<MoreVertical size={14} className="text-[var(--color-text-secondary)]" />
|
||||
</MenuButton>
|
||||
)}
|
||||
</Container>
|
||||
@ -447,19 +456,4 @@ const MenuButton = ({
|
||||
</div>
|
||||
)
|
||||
|
||||
const TopicCount = ({
|
||||
children,
|
||||
className,
|
||||
...props
|
||||
}: PropsWithChildren<{} & React.HTMLAttributes<HTMLDivElement>>) => (
|
||||
<div
|
||||
{...props}
|
||||
className={cn(
|
||||
'flex flex-row items-center justify-center rounded-[10px] text-[10px] text-[var(--color-text)]',
|
||||
className
|
||||
)}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
|
||||
export default memo(AssistantItem)
|
||||
|
||||
@ -232,12 +232,11 @@ const SessionListItem = styled.div`
|
||||
}
|
||||
|
||||
&.singlealone {
|
||||
border-radius: 0 !important;
|
||||
&:hover {
|
||||
background-color: var(--color-background-soft);
|
||||
}
|
||||
&.active {
|
||||
border-left: 2px solid var(--color-primary);
|
||||
background-color: var(--color-background-mute);
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,8 +19,6 @@ import styled from 'styled-components'
|
||||
import AddButton from './AddButton'
|
||||
import SessionItem from './SessionItem'
|
||||
|
||||
// const logger = loggerService.withContext('SessionsTab')
|
||||
|
||||
interface SessionsProps {
|
||||
agentId: string
|
||||
}
|
||||
|
||||
@ -499,7 +499,7 @@ export const Topics: React.FC<Props> = ({ assistant: _assistant, activeTopic, se
|
||||
className="topics-tab"
|
||||
list={sortedTopics}
|
||||
onUpdate={updateTopics}
|
||||
style={{ height: '100%', padding: '11px 0 10px 10px' }}
|
||||
style={{ height: '100%', padding: '9px 0 10px 10px' }}
|
||||
itemContainerStyle={{ paddingBottom: '8px' }}
|
||||
header={
|
||||
<>
|
||||
@ -632,12 +632,11 @@ const TopicListItem = styled.div`
|
||||
}
|
||||
}
|
||||
&.singlealone {
|
||||
border-radius: 0 !important;
|
||||
&:hover {
|
||||
background-color: var(--color-background-soft);
|
||||
}
|
||||
&.active {
|
||||
border-left: 2px solid var(--color-primary);
|
||||
background-color: var(--color-background-mute);
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,5 @@
|
||||
import AddAssistantPopup from '@renderer/components/Popups/AddAssistantPopup'
|
||||
import { useActiveSession } from '@renderer/hooks/agents/useActiveSession'
|
||||
import { useUpdateSession } from '@renderer/hooks/agents/useUpdateSession'
|
||||
import { useAssistants, useDefaultAssistant } from '@renderer/hooks/useAssistant'
|
||||
import { useRuntime } from '@renderer/hooks/useRuntime'
|
||||
import { useNavbarPosition, useSettings } from '@renderer/hooks/useSettings'
|
||||
import { useShowTopics } from '@renderer/hooks/useStore'
|
||||
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
|
||||
@ -10,16 +7,13 @@ import { useAppDispatch } from '@renderer/store'
|
||||
import { setActiveAgentId, setActiveTopicOrSessionAction } from '@renderer/store/runtime'
|
||||
import type { Assistant, Topic } from '@renderer/types'
|
||||
import type { Tab } from '@renderer/types/chat'
|
||||
import { classNames, getErrorMessage, uuid } from '@renderer/utils'
|
||||
import { Alert, Skeleton } from 'antd'
|
||||
import { classNames, uuid } from '@renderer/utils'
|
||||
import type { FC } from 'react'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
|
||||
import Assistants from './AssistantsTab'
|
||||
import SessionSettingsTab from './SessionSettingsTab'
|
||||
import Settings from './SettingsTab'
|
||||
import Topics from './TopicsTab'
|
||||
|
||||
interface Props {
|
||||
@ -49,15 +43,8 @@ const HomeTabs: FC<Props> = ({
|
||||
const { toggleShowTopics } = useShowTopics()
|
||||
const { isLeftNavbar } = useNavbarPosition()
|
||||
const { t } = useTranslation()
|
||||
const { chat } = useRuntime()
|
||||
const { activeTopicOrSession, activeAgentId } = chat
|
||||
const { session, isLoading: isSessionLoading, error: sessionError } = useActiveSession()
|
||||
const { updateSession } = useUpdateSession(activeAgentId)
|
||||
const dispatch = useAppDispatch()
|
||||
|
||||
const isSessionView = activeTopicOrSession === 'session'
|
||||
const isTopicView = activeTopicOrSession === 'topic'
|
||||
|
||||
const [tab, setTab] = useState<Tab>(position === 'left' ? _tab || 'assistants' : 'topic')
|
||||
const borderStyle = '0.5px solid var(--color-border)'
|
||||
const border =
|
||||
@ -96,9 +83,6 @@ const HomeTabs: FC<Props> = ({
|
||||
EventEmitter.on(EVENT_NAMES.SHOW_TOPIC_SIDEBAR, (): any => {
|
||||
showTab && setTab('topic')
|
||||
}),
|
||||
EventEmitter.on(EVENT_NAMES.SHOW_CHAT_SETTINGS, (): any => {
|
||||
showTab && setTab('settings')
|
||||
}),
|
||||
EventEmitter.on(EVENT_NAMES.SWITCH_TOPIC_SIDEBAR, () => {
|
||||
showTab && setTab('topic')
|
||||
if (position === 'left' && topicPosition === 'right') {
|
||||
@ -113,7 +97,7 @@ const HomeTabs: FC<Props> = ({
|
||||
if (position === 'right' && topicPosition === 'right' && tab === 'assistants') {
|
||||
setTab('topic')
|
||||
}
|
||||
if (position === 'left' && topicPosition === 'right' && (tab === 'topic' || tab === 'settings')) {
|
||||
if (position === 'left' && topicPosition === 'right' && tab === 'topic') {
|
||||
setTab('assistants')
|
||||
}
|
||||
}, [position, tab, topicPosition, forceToSeeAllTab])
|
||||
@ -130,20 +114,6 @@ const HomeTabs: FC<Props> = ({
|
||||
<TabItem active={tab === 'topic'} onClick={() => setTab('topic')}>
|
||||
{t('common.topics')}
|
||||
</TabItem>
|
||||
<TabItem active={tab === 'settings'} onClick={() => setTab('settings')}>
|
||||
{t('settings.title')}
|
||||
</TabItem>
|
||||
</CustomTabs>
|
||||
)}
|
||||
|
||||
{position === 'right' && topicPosition === 'right' && (
|
||||
<CustomTabs>
|
||||
<TabItem active={tab === 'topic'} onClick={() => setTab('topic')}>
|
||||
{t('common.topics')}
|
||||
</TabItem>
|
||||
<TabItem active={tab === 'settings'} onClick={() => setTab('settings')}>
|
||||
{t('settings.title')}
|
||||
</TabItem>
|
||||
</CustomTabs>
|
||||
)}
|
||||
|
||||
@ -164,22 +134,6 @@ const HomeTabs: FC<Props> = ({
|
||||
position={position}
|
||||
/>
|
||||
)}
|
||||
{tab === 'settings' && isTopicView && <Settings assistant={activeAssistant} />}
|
||||
{tab === 'settings' && isSessionView && !sessionError && (
|
||||
<Skeleton loading={isSessionLoading} active style={{ height: '100%', padding: '16px' }}>
|
||||
<SessionSettingsTab session={session} update={updateSession} />
|
||||
</Skeleton>
|
||||
)}
|
||||
{tab === 'settings' && isSessionView && sessionError && (
|
||||
<div className="w-[var(--assistants-width)] p-2 px-3 pt-4">
|
||||
<Alert
|
||||
type="error"
|
||||
message={t('agent.session.get.error.failed')}
|
||||
description={getErrorMessage(sessionError)}
|
||||
style={{ padding: '10px 15px' }}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</TabContent>
|
||||
</Container>
|
||||
)
|
||||
|
||||
@ -1,14 +1,17 @@
|
||||
import EmojiIcon from '@renderer/components/EmojiIcon'
|
||||
import HorizontalScrollContainer from '@renderer/components/HorizontalScrollContainer'
|
||||
import { useActiveAgent } from '@renderer/hooks/agents/useActiveAgent'
|
||||
import { useActiveSession } from '@renderer/hooks/agents/useActiveSession'
|
||||
import { useUpdateSession } from '@renderer/hooks/agents/useUpdateSession'
|
||||
import { useRuntime } from '@renderer/hooks/useRuntime'
|
||||
import AssistantSettingsPopup from '@renderer/pages/settings/AssistantSettings'
|
||||
import type { AgentEntity, AgentSessionEntity, ApiModel, Assistant } from '@renderer/types'
|
||||
import { getLeadingEmoji } from '@renderer/utils'
|
||||
import { formatErrorMessageWithPrefix } from '@renderer/utils/error'
|
||||
import { t } from 'i18next'
|
||||
import { ChevronRight, Folder } from 'lucide-react'
|
||||
import type { FC, ReactNode } from 'react'
|
||||
import { useCallback } from 'react'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
|
||||
import { AgentSettingsPopup, SessionSettingsPopup } from '../../settings/AgentSettings'
|
||||
@ -29,6 +32,8 @@ const ChatNavbarContent: FC<Props> = ({ assistant }) => {
|
||||
const { session: activeSession } = useActiveSession()
|
||||
const { updateModel } = useUpdateSession(activeAgent?.id ?? null)
|
||||
|
||||
const assistantName = useMemo(() => assistant.name || t('chat.default.name'), [assistant.name])
|
||||
|
||||
const handleUpdateModel = useCallback(
|
||||
async (model: ApiModel) => {
|
||||
if (!activeAgent || !activeSession) return
|
||||
@ -39,7 +44,25 @@ const ChatNavbarContent: FC<Props> = ({ assistant }) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
{activeTopicOrSession === 'topic' && <SelectModelButton assistant={assistant} />}
|
||||
{activeTopicOrSession === 'topic' && (
|
||||
<HorizontalScrollContainer className="ml-2 flex-initial">
|
||||
<div className="flex flex-nowrap items-center gap-2">
|
||||
{/* Assistant Label */}
|
||||
<div
|
||||
className="flex h-full cursor-pointer items-center gap-1.5"
|
||||
onClick={() => AssistantSettingsPopup.show({ assistant })}>
|
||||
<EmojiIcon emoji={assistant.emoji || getLeadingEmoji(assistantName)} size={24} />
|
||||
<span className="max-w-40 truncate text-xs">{assistantName}</span>
|
||||
</div>
|
||||
|
||||
{/* Separator */}
|
||||
<ChevronRight className="h-4 w-4 text-gray-400" />
|
||||
|
||||
{/* Model Button */}
|
||||
<SelectModelButton assistant={assistant} />
|
||||
</div>
|
||||
</HorizontalScrollContainer>
|
||||
)}
|
||||
{activeTopicOrSession === 'session' && activeAgent && (
|
||||
<HorizontalScrollContainer className="ml-2 flex-initial">
|
||||
<div className="flex flex-nowrap items-center gap-2">
|
||||
|
||||
38
src/renderer/src/pages/home/components/SettingsButton.tsx
Normal file
38
src/renderer/src/pages/home/components/SettingsButton.tsx
Normal file
@ -0,0 +1,38 @@
|
||||
import type { Assistant } from '@renderer/types'
|
||||
import { Drawer, Tooltip } from 'antd'
|
||||
import { t } from 'i18next'
|
||||
import { Settings2 } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { useState } from 'react'
|
||||
|
||||
import { NavbarIcon } from '../ChatNavbar'
|
||||
import HomeSettings from '../Tabs/SettingsTab'
|
||||
|
||||
interface Props {
|
||||
assistant: Assistant
|
||||
}
|
||||
|
||||
const SettingsButton: FC<Props> = ({ assistant }) => {
|
||||
const [settingsOpen, setSettingsOpen] = useState(false)
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tooltip title={t('settings.title')} mouseEnterDelay={0.8}>
|
||||
<NavbarIcon onClick={() => setSettingsOpen(true)}>
|
||||
<Settings2 size={18} />
|
||||
</NavbarIcon>
|
||||
</Tooltip>
|
||||
<Drawer
|
||||
placement="right"
|
||||
open={settingsOpen}
|
||||
onClose={() => setSettingsOpen(false)}
|
||||
width="var(--assistants-width)"
|
||||
closable={false}
|
||||
styles={{ body: { padding: 0, paddingTop: 'var(--navbar-height)' } }}>
|
||||
<HomeSettings assistant={assistant} />
|
||||
</Drawer>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default SettingsButton
|
||||
@ -119,7 +119,7 @@ const AgentSettingPopupContainer: React.FC<AgentSettingPopupParams> = ({ tab, ag
|
||||
onOk={onOk}
|
||||
onCancel={onCancel}
|
||||
afterClose={afterClose}
|
||||
maskClosable={false}
|
||||
maskClosable={menu !== 'prompt'}
|
||||
footer={null}
|
||||
title={<AgentLabel agent={agent} />}
|
||||
transitionName="animation-move-down"
|
||||
|
||||
@ -29,14 +29,15 @@ export type AgentLabelProps = {
|
||||
avatar?: string
|
||||
name?: string
|
||||
}
|
||||
hideIcon?: boolean
|
||||
}
|
||||
|
||||
export const AgentLabel: React.FC<AgentLabelProps> = ({ agent, classNames }) => {
|
||||
export const AgentLabel: React.FC<AgentLabelProps> = ({ agent, classNames, hideIcon }) => {
|
||||
const emoji = agent?.configuration?.avatar
|
||||
|
||||
return (
|
||||
<div className={cn('flex w-full items-center gap-2 truncate', classNames?.container)}>
|
||||
<EmojiIcon emoji={emoji || '⭐️'} className={classNames?.avatar} />
|
||||
{!hideIcon && <EmojiIcon emoji={emoji || '⭐️'} className={classNames?.avatar} size={24} />}
|
||||
<span className={cn('truncate', 'text-[var(--color-text)]', classNames?.name)}>
|
||||
{agent?.name ?? (agent?.type ? getAgentTypeLabel(agent.type) : '')}
|
||||
</span>
|
||||
|
||||
@ -37,7 +37,7 @@ interface Props extends AssistantSettingPopupShowParams {
|
||||
const AssistantSettingPopupContainer: React.FC<Props> = ({ resolve, tab, ...props }) => {
|
||||
const [open, setOpen] = useState(true)
|
||||
const { t } = useTranslation()
|
||||
const [menu, setMenu] = useState<AssistantSettingPopupTab>(tab || 'prompt')
|
||||
const [menu, setMenu] = useState<AssistantSettingPopupTab>(tab || 'model')
|
||||
|
||||
const _useAssistant = useAssistant(props.assistant.id)
|
||||
const _useAgent = useAssistantPreset(props.assistant.id)
|
||||
@ -64,14 +64,14 @@ const AssistantSettingPopupContainer: React.FC<Props> = ({ resolve, tab, ...prop
|
||||
}
|
||||
|
||||
const items = [
|
||||
{
|
||||
key: 'prompt',
|
||||
label: t('assistants.settings.prompt')
|
||||
},
|
||||
{
|
||||
key: 'model',
|
||||
label: t('assistants.settings.model')
|
||||
},
|
||||
{
|
||||
key: 'prompt',
|
||||
label: t('assistants.settings.prompt')
|
||||
},
|
||||
showKnowledgeIcon && {
|
||||
key: 'knowledge_base',
|
||||
label: t('assistants.settings.knowledge_base.label')
|
||||
@ -96,7 +96,7 @@ const AssistantSettingPopupContainer: React.FC<Props> = ({ resolve, tab, ...prop
|
||||
onOk={onOk}
|
||||
onCancel={onCancel}
|
||||
afterClose={afterClose}
|
||||
maskClosable={false}
|
||||
maskClosable={menu !== 'prompt'}
|
||||
footer={null}
|
||||
title={assistant.name}
|
||||
transitionName="animation-move-down"
|
||||
@ -116,22 +116,22 @@ const AssistantSettingPopupContainer: React.FC<Props> = ({ resolve, tab, ...prop
|
||||
<HStack>
|
||||
<LeftMenu>
|
||||
<StyledMenu
|
||||
defaultSelectedKeys={[tab || 'prompt']}
|
||||
defaultSelectedKeys={[tab || 'model']}
|
||||
mode="vertical"
|
||||
items={items}
|
||||
onSelect={({ key }) => setMenu(key as AssistantSettingPopupTab)}
|
||||
/>
|
||||
</LeftMenu>
|
||||
<Settings>
|
||||
{menu === 'prompt' && (
|
||||
<AssistantPromptSettings
|
||||
{menu === 'model' && (
|
||||
<AssistantModelSettings
|
||||
assistant={assistant}
|
||||
updateAssistant={updateAssistant}
|
||||
updateAssistantSettings={updateAssistantSettings}
|
||||
/>
|
||||
)}
|
||||
{menu === 'model' && (
|
||||
<AssistantModelSettings
|
||||
{menu === 'prompt' && (
|
||||
<AssistantPromptSettings
|
||||
assistant={assistant}
|
||||
updateAssistant={updateAssistant}
|
||||
updateAssistantSettings={updateAssistantSettings}
|
||||
|
||||
@ -4,8 +4,6 @@ export const EventEmitter = new Emittery()
|
||||
|
||||
export const EVENT_NAMES = {
|
||||
SEND_MESSAGE: 'SEND_MESSAGE',
|
||||
// APPEND_MESSAGE: 'APPEND_MESSAGE',
|
||||
// RECEIVE_MESSAGE: 'RECEIVE_MESSAGE',
|
||||
MESSAGE_COMPLETE: 'MESSAGE_COMPLETE',
|
||||
AI_AUTO_RENAME: 'AI_AUTO_RENAME',
|
||||
CLEAR_MESSAGES: 'CLEAR_MESSAGES',
|
||||
@ -15,7 +13,6 @@ export const EVENT_NAMES = {
|
||||
CHAT_COMPLETION_PAUSED: 'CHAT_COMPLETION_PAUSED',
|
||||
ESTIMATED_TOKEN_COUNT: 'ESTIMATED_TOKEN_COUNT',
|
||||
SHOW_ASSISTANTS: 'SHOW_ASSISTANTS',
|
||||
SHOW_CHAT_SETTINGS: 'SHOW_CHAT_SETTINGS',
|
||||
SHOW_TOPIC_SIDEBAR: 'SHOW_TOPIC_SIDEBAR',
|
||||
SWITCH_TOPIC_SIDEBAR: 'SWITCH_TOPIC_SIDEBAR',
|
||||
NEW_CONTEXT: 'NEW_CONTEXT',
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
export type Tab = 'assistants' | 'topic' | 'settings'
|
||||
export type Tab = 'assistants' | 'topic'
|
||||
|
||||
export type InputBarToolType =
|
||||
| 'new_topic'
|
||||
|
||||
Loading…
Reference in New Issue
Block a user