From 367c4fe6b64d07fb104facb1c159afff7075cc57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=A2=E5=A5=8B=E7=8C=AB?= Date: Thu, 11 Dec 2025 16:11:21 +0800 Subject: [PATCH] refactor(ui): improve settings tab and assistant item UI (#11819) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 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 * 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 --- .../CodeBlockView/HtmlArtifactsPopup.tsx | 4 +- src/renderer/src/components/app/Sidebar.tsx | 5 +- src/renderer/src/pages/home/ChatNavbar.tsx | 10 +- .../src/pages/home/Messages/MessageEditor.tsx | 2 +- .../src/pages/home/Messages/MessageHeader.tsx | 12 +- .../src/pages/home/Messages/Prompt.tsx | 5 +- .../pages/home/Tabs/SessionSettingsTab.tsx | 45 --- .../src/pages/home/Tabs/SettingsTab.tsx | 320 ++++-------------- .../pages/home/Tabs/components/AgentItem.tsx | 24 +- .../home/Tabs/components/AssistantItem.tsx | 28 +- .../home/Tabs/components/SessionItem.tsx | 3 +- .../pages/home/Tabs/components/Sessions.tsx | 2 - .../src/pages/home/Tabs/components/Topics.tsx | 5 +- src/renderer/src/pages/home/Tabs/index.tsx | 50 +-- .../home/components/ChatNavbarContent.tsx | 27 +- .../pages/home/components/SettingsButton.tsx | 38 +++ .../AgentSettings/AgentSettingsPopup.tsx | 2 +- .../pages/settings/AgentSettings/shared.tsx | 5 +- .../settings/AssistantSettings/index.tsx | 22 +- src/renderer/src/services/EventService.ts | 3 - src/renderer/src/types/chat.ts | 2 +- 21 files changed, 201 insertions(+), 413 deletions(-) delete mode 100644 src/renderer/src/pages/home/Tabs/SessionSettingsTab.tsx create mode 100644 src/renderer/src/pages/home/components/SettingsButton.tsx diff --git a/src/renderer/src/components/CodeBlockView/HtmlArtifactsPopup.tsx b/src/renderer/src/components/CodeBlockView/HtmlArtifactsPopup.tsx index 2cd8171d0..8346eee12 100644 --- a/src/renderer/src/components/CodeBlockView/HtmlArtifactsPopup.tsx +++ b/src/renderer/src/components/CodeBlockView/HtmlArtifactsPopup.tsx @@ -25,7 +25,7 @@ type ViewMode = 'split' | 'code' | 'preview' const HtmlArtifactsPopup: React.FC = ({ open, title, html, onSave, onClose }) => { const { t } = useTranslation() const [viewMode, setViewMode] = useState('split') - const [isFullscreen, setIsFullscreen] = useState(false) + const [isFullscreen, setIsFullscreen] = useState(true) const [saved, setSaved] = useTemporaryValue(false, 2000) const codeEditorRef = useRef(null) const previewFrameRef = useRef(null) @@ -78,7 +78,7 @@ const HtmlArtifactsPopup: React.FC = ({ open, title, ht - e.stopPropagation()}> + e.stopPropagation()} className="nodrag"> { )} - + {settedTheme === ThemeMode.dark ? ( diff --git a/src/renderer/src/pages/home/ChatNavbar.tsx b/src/renderer/src/pages/home/ChatNavbar.tsx index 17b45ad18..1685c7d23 100644 --- a/src/renderer/src/pages/home/ChatNavbar.tsx +++ b/src/renderer/src/pages/home/ChatNavbar.tsx @@ -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 = ({ 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 (
@@ -107,6 +100,7 @@ const HeaderNavbar: FC = ({ activeAssistant, setActiveAssistant, activeTo
{isTopNavbar && } + {isTopNavbar && ( diff --git a/src/renderer/src/pages/home/Messages/MessageEditor.tsx b/src/renderer/src/pages/home/Messages/MessageEditor.tsx index e136be1d3..f9546b531 100644 --- a/src/renderer/src/pages/home/Messages/MessageEditor.tsx +++ b/src/renderer/src/pages/home/Messages/MessageEditor.tsx @@ -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; diff --git a/src/renderer/src/pages/home/Messages/MessageHeader.tsx b/src/renderer/src/pages/home/Messages/MessageHeader.tsx index 5f6a69663..bc1b2ab62 100644 --- a/src/renderer/src/pages/home/Messages/MessageHeader.tsx +++ b/src/renderer/src/pages/home/Messages/MessageHeader.tsx @@ -83,11 +83,11 @@ const MessageHeader: FC = 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 ( @@ -121,7 +121,7 @@ const MessageHeader: FC = memo(({ assistant, model, message, topic, isGro )} - + {username} diff --git a/src/renderer/src/pages/home/Messages/Prompt.tsx b/src/renderer/src/pages/home/Messages/Prompt.tsx index 1be977059..0f48d03c2 100644 --- a/src/renderer/src/pages/home/Messages/Prompt.tsx +++ b/src/renderer/src/pages/home/Messages/Prompt.tsx @@ -63,7 +63,10 @@ const Prompt: FC = ({ assistant, topic }) => { } return ( - AssistantSettingsPopup.show({ assistant })} $isDark={isDark}> + AssistantSettingsPopup.show({ assistant, tab: 'prompt' })} + $isDark={isDark}> {displayText} ) diff --git a/src/renderer/src/pages/home/Tabs/SessionSettingsTab.tsx b/src/renderer/src/pages/home/Tabs/SessionSettingsTab.tsx deleted file mode 100644 index b138caaf8..000000000 --- a/src/renderer/src/pages/home/Tabs/SessionSettingsTab.tsx +++ /dev/null @@ -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['updateSession'] -} - -const SessionSettingsTab: FC = ({ session, update }) => { - const { t } = useTranslation() - - const onMoreSetting = () => { - if (session?.id) { - SessionSettingsPopup.show({ - agentId: session.agent_id, - sessionId: session.id - }) - } - } - - if (!session) { - return null - } - - return ( -
- - - - - -
- ) -} - -export default SessionSettingsTab diff --git a/src/renderer/src/pages/home/Tabs/SettingsTab.tsx b/src/renderer/src/pages/home/Tabs/SettingsTab.tsx index 014897ce9..f76971e99 100644 --- a/src/renderer/src/pages/home/Tabs/SettingsTab.tsx +++ b/src/renderer/src/pages/home/Tabs/SettingsTab.tsx @@ -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) => { - 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) => { confirmRegenerateMessage } = useSettings() - const onUpdateAssistantSettings = (settings: Partial) => { - 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) => { [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) => { isSupportServiceTierProvider(provider) || (isSupportVerbosityModel(model) && isSupportVerbosityProvider(provider)) + const isTopicSettings = chat.activeTopicOrSession === 'topic' + return ( - {props.assistant.id !== 'fake' && ( - -