From 5ce380c37ac63eb342e86f761c35ec931069d8ce Mon Sep 17 00:00:00 2001 From: kangfenmao Date: Tue, 3 Sep 2024 10:21:48 +0800 Subject: [PATCH] feat: merge assistant and topics --- .../src/assets/images/models/chatglm.jpeg | Bin 9288 -> 0 bytes .../src/assets/images/models/chatglm.png | Bin 0 -> 21604 bytes src/renderer/src/components/app/Sidebar.tsx | 32 ++++-- src/renderer/src/config/models.ts | 44 +++++--- src/renderer/src/config/provider.ts | 2 +- src/renderer/src/hooks/useStore.ts | 14 +-- src/renderer/src/hooks/useTopic.ts | 5 +- src/renderer/src/i18n/index.ts | 8 +- src/renderer/src/pages/home/Assistants.tsx | 64 ++++++++++-- src/renderer/src/pages/home/Chat.tsx | 22 ++-- src/renderer/src/pages/home/Header.tsx | 42 -------- src/renderer/src/pages/home/HomePage.tsx | 49 ++++++--- .../src/pages/home/Inputbar/Inputbar.tsx | 15 ++- .../src/pages/home/Messages/Message.tsx | 2 +- .../src/pages/home/RightSidebar/index.tsx | 96 ------------------ .../SettingsTab.tsx => Settings.tsx} | 6 ++ .../TopicsTab.tsx => Topics.tsx} | 7 +- .../pages/settings/ProviderSettings/index.tsx | 3 +- src/renderer/src/pages/settings/index.tsx | 4 - src/renderer/src/services/ProviderSDK.ts | 21 ++-- src/renderer/src/store/settings.ts | 10 -- 21 files changed, 200 insertions(+), 246 deletions(-) delete mode 100644 src/renderer/src/assets/images/models/chatglm.jpeg create mode 100644 src/renderer/src/assets/images/models/chatglm.png delete mode 100644 src/renderer/src/pages/home/Header.tsx delete mode 100644 src/renderer/src/pages/home/RightSidebar/index.tsx rename src/renderer/src/pages/home/{RightSidebar/SettingsTab.tsx => Settings.tsx} (97%) rename src/renderer/src/pages/home/{RightSidebar/TopicsTab.tsx => Topics.tsx} (97%) diff --git a/src/renderer/src/assets/images/models/chatglm.jpeg b/src/renderer/src/assets/images/models/chatglm.jpeg deleted file mode 100644 index ec40bf962e6f944ff726a70b41d1328d8b2a5249..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9288 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 Kb6kuE1^@s67{VYS00009a7bBm000XU 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 literal 0 HcmV?d00001 diff --git a/src/renderer/src/components/app/Sidebar.tsx b/src/renderer/src/components/app/Sidebar.tsx index c7ee672014..ead585a2da 100644 --- a/src/renderer/src/components/app/Sidebar.tsx +++ b/src/renderer/src/components/app/Sidebar.tsx @@ -2,9 +2,10 @@ import { TranslationOutlined } from '@ant-design/icons' import { isMac } from '@renderer/config/constant' import { AppLogo, isLocalAi } from '@renderer/config/env' import useAvatar from '@renderer/hooks/useAvatar' -import { useRuntime } from '@renderer/hooks/useStore' +import { useRuntime, useShowAssistants } from '@renderer/hooks/useStore' import { Avatar } from 'antd' import { FC } from 'react' +import { useTranslation } from 'react-i18next' import { Link, useLocation } from 'react-router-dom' import styled from 'styled-components' @@ -16,11 +17,26 @@ const Sidebar: FC = () => { const { pathname } = useLocation() const avatar = useAvatar() const { minappShow } = useRuntime() + const { toggleShowAssistants } = useShowAssistants() + const { generating } = useRuntime() + const { t } = useTranslation() const isRoute = (path: string): string => (pathname === path ? 'active' : '') - const onEditUser = () => { - UserPopup.show() + const onEditUser = () => UserPopup.show() + + const to = (path: string) => { + if (generating) { + window.message.warning({ content: t('message.switch.disabled'), key: 'switch-assistant' }) + return '/' + } + return path + } + + const onToggleShowAssistants = () => { + if (pathname === '/') { + toggleShowAssistants() + } } return ( @@ -28,22 +44,22 @@ const Sidebar: FC = () => { - + - + - + - + @@ -51,7 +67,7 @@ const Sidebar: FC = () => { - + diff --git a/src/renderer/src/config/models.ts b/src/renderer/src/config/models.ts index 3e8bc5dbad..e519152bdf 100644 --- a/src/renderer/src/config/models.ts +++ b/src/renderer/src/config/models.ts @@ -255,46 +255,60 @@ export const SYSTEM_MODELS: Record = { } ], zhipu: [ - { - id: 'glm-4-0520', - provider: 'zhipu', - name: 'GLM-4-0520', - group: 'GLM', - enabled: true - }, { id: 'glm-4', provider: 'zhipu', name: 'GLM-4', - group: 'GLM', + group: 'GLM-4', enabled: false }, { - id: 'glm-4-airx', + id: 'glm-4-plus', provider: 'zhipu', - name: 'GLM-4-AirX', - group: 'GLM', + name: 'GLM-4-Plus', + group: 'GLM-4', enabled: false }, { id: 'glm-4-air', provider: 'zhipu', name: 'GLM-4-Air', - group: 'GLM', + group: 'GLM-4', enabled: true }, + { + id: 'glm-4-airx', + provider: 'zhipu', + name: 'GLM-4-AirX', + group: 'GLM-4', + enabled: false + }, + { + id: 'glm-4-flash', + provider: 'zhipu', + name: 'GLM-4-Flash', + group: 'GLM-4', + enabled: false + }, { id: 'glm-4v', provider: 'zhipu', - name: 'GLM-4V', - group: 'GLM', + name: 'GLM 4V', + group: 'GLM-4v', + enabled: false + }, + { + id: 'glm-4v-plus', + provider: 'zhipu', + name: 'GLM-4V-Plus', + group: 'GLM-4v', enabled: false }, { id: 'glm-4-alltools', provider: 'zhipu', name: 'GLM-4-AllTools', - group: 'GLM', + group: 'GLM-4-AllTools', enabled: false } ], diff --git a/src/renderer/src/config/provider.ts b/src/renderer/src/config/provider.ts index 3f89ea870a..171b23da7a 100644 --- a/src/renderer/src/config/provider.ts +++ b/src/renderer/src/config/provider.ts @@ -2,7 +2,7 @@ import BaicuanAppLogo from '@renderer/assets/images/apps/baixiaoying.webp' import KimiAppLogo from '@renderer/assets/images/apps/kimi.jpg' import YuewenAppLogo from '@renderer/assets/images/apps/yuewen.png' import BaichuanModelLogo from '@renderer/assets/images/models/baichuan.png' -import ChatGLMModelLogo from '@renderer/assets/images/models/chatglm.jpeg' +import ChatGLMModelLogo from '@renderer/assets/images/models/chatglm.png' import ChatGPTModelLogo from '@renderer/assets/images/models/chatgpt.jpeg' import ClaudeModelLogo from '@renderer/assets/images/models/claude.png' import DeepSeekModelLogo from '@renderer/assets/images/models/deepseek.png' diff --git a/src/renderer/src/hooks/useStore.ts b/src/renderer/src/hooks/useStore.ts index 51e0981b8f..1b21048e90 100644 --- a/src/renderer/src/hooks/useStore.ts +++ b/src/renderer/src/hooks/useStore.ts @@ -1,17 +1,5 @@ import { useAppDispatch, useAppSelector } from '@renderer/store' -import { setShowRightSidebar, toggleRightSidebar, toggleShowAssistants } from '@renderer/store/settings' - -export function useShowRightSidebar() { - const showRightSidebar = useAppSelector((state) => state.settings.showRightSidebar) - const dispatch = useAppDispatch() - - return { - rightSidebarShown: showRightSidebar, - toggleRightSidebar: () => dispatch(toggleRightSidebar()), - showRightSidebar: () => dispatch(setShowRightSidebar(true)), - hideRightSidebar: () => dispatch(setShowRightSidebar(false)) - } -} +import { toggleShowAssistants } from '@renderer/store/settings' export function useShowAssistants() { const showAssistants = useAppSelector((state) => state.settings.showAssistants) diff --git a/src/renderer/src/hooks/useTopic.ts b/src/renderer/src/hooks/useTopic.ts index 7704aa56aa..6fa9767b7f 100644 --- a/src/renderer/src/hooks/useTopic.ts +++ b/src/renderer/src/hooks/useTopic.ts @@ -2,9 +2,12 @@ import { Assistant, Topic } from '@renderer/types' import { find } from 'lodash' import { useEffect, useState } from 'react' +import { useAssistant } from './useAssistant' + let _activeTopic: Topic -export function useActiveTopic(assistant: Assistant) { +export function useActiveTopic(_assistant: Assistant) { + const { assistant } = useAssistant(_assistant.id) const [activeTopic, setActiveTopic] = useState(_activeTopic || assistant?.topics[0]) useEffect(() => { diff --git a/src/renderer/src/i18n/index.ts b/src/renderer/src/i18n/index.ts index ead15a5b04..ae5868bc00 100644 --- a/src/renderer/src/i18n/index.ts +++ b/src/renderer/src/i18n/index.ts @@ -29,7 +29,8 @@ const resources = { select: 'Select', search: 'Search', default: 'Default', - warning: 'Warning' + warning: 'Warning', + back: 'Back' }, button: { add: 'Add', @@ -67,7 +68,6 @@ const resources = { 'topics.delete.all.title': 'Delete all topics', 'topics.delete.all.content': 'Are you sure you want to delete all topics?', 'input.new_topic': 'New Topic', - 'input.topics': ' Topics ', 'input.clear': 'Clear', 'input.expand': 'Expand', 'input.collapse': 'Collapse', @@ -267,7 +267,8 @@ const resources = { select: '选择', search: '搜索', default: '默认', - warning: '警告' + warning: '警告', + back: '返回' }, button: { add: '添加', @@ -305,7 +306,6 @@ const resources = { 'topics.delete.all.title': '删除所有话题', 'topics.delete.all.content': '确定要删除所有话题吗?', 'input.new_topic': '新话题', - 'input.topics': ' 话题 ', 'input.clear': '清除', 'input.expand': '展开', 'input.collapse': '收起', diff --git a/src/renderer/src/pages/home/Assistants.tsx b/src/renderer/src/pages/home/Assistants.tsx index 0a2204ba20..b238d81986 100644 --- a/src/renderer/src/pages/home/Assistants.tsx +++ b/src/renderer/src/pages/home/Assistants.tsx @@ -1,11 +1,13 @@ -import { CopyOutlined, DeleteOutlined, EditOutlined } from '@ant-design/icons' +import { ArrowRightOutlined, CopyOutlined, DeleteOutlined, EditOutlined } from '@ant-design/icons' +import { ArrowLeftOutlined } from '@ant-design/icons' import DragableList from '@renderer/components/DragableList' +import { HStack } from '@renderer/components/Layout' import AssistantSettingPopup from '@renderer/components/Popups/AssistantSettingPopup' import { useAssistant, useAssistants } from '@renderer/hooks/useAssistant' import { getDefaultTopic, syncAsistantToAgent } from '@renderer/services/assistant' import { EVENT_NAMES, EventEmitter } from '@renderer/services/event' import { useAppSelector } from '@renderer/store' -import { Assistant } from '@renderer/types' +import { Assistant, Topic } from '@renderer/types' import { uuid } from '@renderer/utils' import { Dropdown } from 'antd' import { ItemType } from 'antd/es/menu/interface' @@ -14,13 +16,27 @@ import { FC, useCallback } from 'react' import { useTranslation } from 'react-i18next' import styled from 'styled-components' +import Topics from './Topics' + interface Props { activeAssistant: Assistant setActiveAssistant: (assistant: Assistant) => void + activeTopic: Topic + setActiveTopic: (topic: Topic) => void + showTopics: boolean + setShowTopics: (showTopics: boolean) => void onCreateAssistant: () => void } -const Assistants: FC = ({ activeAssistant, setActiveAssistant, onCreateAssistant }) => { +const Assistants: FC = ({ + activeAssistant, + setActiveAssistant, + activeTopic, + setActiveTopic, + showTopics, + setShowTopics, + onCreateAssistant +}) => { const { assistants, removeAssistant, addAssistant, updateAssistants } = useAssistants() const generating = useAppSelector((state) => state.runtime.generating) const { updateAssistant } = useAssistant(activeAssistant.id) @@ -80,10 +96,23 @@ const Assistants: FC = ({ activeAssistant, setActiveAssistant, onCreateAs } EventEmitter.emit(EVENT_NAMES.SWITCH_TOPIC_SIDEBAR) setActiveAssistant(assistant) + setShowTopics(true) }, - [generating, setActiveAssistant, t] + [generating, setActiveAssistant, setShowTopics, t] ) + if (showTopics) { + return ( + + setShowTopics(false)}> + + {t('common.back')} + + + + ) + } + return ( @@ -93,6 +122,9 @@ const Assistants: FC = ({ activeAssistant, setActiveAssistant, onCreateAs onClick={() => onSwitchAssistant(assistant)} className={assistant.id === activeAssistant?.id ? 'active' : ''}> {assistant.name || t('chat.default.name')} + + + )} @@ -108,26 +140,31 @@ const Container = styled.div` max-width: var(--assistants-width); border-right: 0.5px solid var(--color-border); height: calc(100vh - var(--navbar-height)); - padding: 10px; overflow-y: auto; + padding: 10px 0; ` const AssistantItem = styled.div` display: flex; - flex-direction: column; + flex-direction: row; + justify-content: space-between; padding: 7px 10px; position: relative; border-radius: 4px; + margin: 0 10px; cursor: pointer; font-family: Ubuntu; .anticon { display: none; + color: var(--color-text-3); } &:hover { background-color: var(--color-background-soft); + .count { + display: none; + } .anticon { display: block; - color: var(--color-text-1); } } &.active { @@ -139,6 +176,19 @@ const AssistantItem = styled.div` } ` +const NavigtaionHeader = styled.div` + display: flex; + flex-direction: row; + align-items: center; + justify-content: flex-start; + gap: 10px; + padding: 0 5px; + cursor: pointer; + color: var(--color-text-3); + margin: 10px; + margin-top: 0; +` + const AssistantName = styled.div` color: var(--color-text); display: -webkit-box; diff --git a/src/renderer/src/pages/home/Chat.tsx b/src/renderer/src/pages/home/Chat.tsx index 70e576b16e..b2d5f76188 100644 --- a/src/renderer/src/pages/home/Chat.tsx +++ b/src/renderer/src/pages/home/Chat.tsx @@ -1,29 +1,35 @@ import { useAssistant } from '@renderer/hooks/useAssistant' -import { useActiveTopic } from '@renderer/hooks/useTopic' -import { Assistant } from '@renderer/types' +import { Assistant, Topic } from '@renderer/types' import { Flex } from 'antd' -import { FC } from 'react' +import { FC, useState } from 'react' import styled from 'styled-components' import Inputbar from './Inputbar/Inputbar' import Messages from './Messages/Messages' -import RightSidebar from './RightSidebar' +import Settings from './Settings' interface Props { assistant: Assistant + activeTopic: Topic + setActiveTopic: (topic: Topic) => void } const Chat: FC = (props) => { const { assistant } = useAssistant(props.assistant.id) - const { activeTopic, setActiveTopic } = useActiveTopic(assistant) + const [showSetting, setShowSetting] = useState(false) return (

- - + +
- + {showSetting && } ) } diff --git a/src/renderer/src/pages/home/Header.tsx b/src/renderer/src/pages/home/Header.tsx deleted file mode 100644 index f7bea8e3bc..0000000000 --- a/src/renderer/src/pages/home/Header.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { NavbarCenter } from '@renderer/components/app/Navbar' -import { isMac } from '@renderer/config/constant' -import { useAssistant } from '@renderer/hooks/useAssistant' -import { useShowAssistants } from '@renderer/hooks/useStore' -import { Assistant } from '@renderer/types' -import { removeLeadingEmoji } from '@renderer/utils' -import { FC } from 'react' -import { useTranslation } from 'react-i18next' -import styled from 'styled-components' - -import SelectModelButton from './components/SelectModelButton' -import { NewButton } from './HomePage' - -interface Props { - activeAssistant: Assistant -} - -const HomeHeader: FC = ({ activeAssistant }) => { - const { assistant } = useAssistant(activeAssistant.id) - const { t } = useTranslation() - const { showAssistants, toggleShowAssistants } = useShowAssistants() - - return ( - - {!showAssistants && ( - - - - )} - {removeLeadingEmoji(assistant?.name) || t('chat.default.name')} - - - ) -} - -const AssistantName = styled.span` - margin-left: 5px; - margin-right: 10px; - font-family: Ubuntu; -` - -export default HomeHeader diff --git a/src/renderer/src/pages/home/HomePage.tsx b/src/renderer/src/pages/home/HomePage.tsx index 0bcab92da9..f7ffb8cf03 100644 --- a/src/renderer/src/pages/home/HomePage.tsx +++ b/src/renderer/src/pages/home/HomePage.tsx @@ -1,30 +1,37 @@ -import { Navbar, NavbarLeft, NavbarRight } from '@renderer/components/app/Navbar' +import { Navbar, NavbarCenter, NavbarLeft, NavbarRight } from '@renderer/components/app/Navbar' import { isMac, isWindows } from '@renderer/config/constant' import { useAssistants, useDefaultAssistant } from '@renderer/hooks/useAssistant' -import { useShowAssistants, useShowRightSidebar } from '@renderer/hooks/useStore' +import { useShowAssistants } from '@renderer/hooks/useStore' +import { useActiveTopic } from '@renderer/hooks/useTopic' import { useTheme } from '@renderer/providers/ThemeProvider' -import { Assistant } from '@renderer/types' +import { Assistant, Topic } from '@renderer/types' import { uuid } from '@renderer/utils' import { Switch } from 'antd' import { FC, useState } from 'react' +import { useTranslation } from 'react-i18next' import styled from 'styled-components' import AddAssistantPopup from '../../components/Popups/AddAssistantPopup' import Assistants from './Assistants' import Chat from './Chat' -import Navigation from './Header' +import SelectModelButton from './components/SelectModelButton' let _activeAssistant: Assistant +let _showTopics = false const HomePage: FC = () => { const { assistants, addAssistant } = useAssistants() const [activeAssistant, setActiveAssistant] = useState(_activeAssistant || assistants[0]) - const { rightSidebarShown, toggleRightSidebar } = useShowRightSidebar() - const { showAssistants, toggleShowAssistants } = useShowAssistants() + const { showAssistants } = useShowAssistants() const { defaultAssistant } = useDefaultAssistant() const { theme, toggleTheme } = useTheme() + const [showTopics, setShowTopics] = useState(_showTopics) + const { t } = useTranslation() + + const { activeTopic, setActiveTopic } = useActiveTopic(activeAssistant) _activeAssistant = activeAssistant + _showTopics = showTopics const onCreateDefaultAssistant = () => { const assistant = { ...defaultAssistant, id: uuid() } @@ -37,20 +44,25 @@ const HomePage: FC = () => { assistant && setActiveAssistant(assistant) } + const onSetActiveTopic = (topic: Topic) => { + setActiveTopic(topic) + setShowTopics(true) + } + return ( {showAssistants && ( - - - - + )} - + + {activeAssistant?.name || t('chat.default.name')} + + } @@ -58,9 +70,6 @@ const HomePage: FC = () => { checked={theme === 'dark'} onChange={toggleTheme} /> - - - @@ -68,10 +77,14 @@ const HomePage: FC = () => { )} - + ) @@ -90,6 +103,12 @@ const ContentContainer = styled.div` background-color: var(--color-background); ` +const AssistantName = styled.span` + margin-left: 5px; + margin-right: 10px; + font-family: Ubuntu; +` + export const NewButton = styled.div` -webkit-app-region: none; border-radius: 4px; diff --git a/src/renderer/src/pages/home/Inputbar/Inputbar.tsx b/src/renderer/src/pages/home/Inputbar/Inputbar.tsx index dc5e8143ea..103f68993d 100644 --- a/src/renderer/src/pages/home/Inputbar/Inputbar.tsx +++ b/src/renderer/src/pages/home/Inputbar/Inputbar.tsx @@ -3,7 +3,6 @@ import { ControlOutlined, FullscreenExitOutlined, FullscreenOutlined, - HistoryOutlined, PauseCircleOutlined, PlusCircleOutlined, QuestionCircleOutlined @@ -32,11 +31,13 @@ import SendMessageButton from './SendMessageButton' interface Props { assistant: Assistant setActiveTopic: (topic: Topic) => void + showSetting: boolean + setShowSetting: (show: boolean) => void } let _text = '' -const Inputbar: FC = ({ assistant, setActiveTopic }) => { +const Inputbar: FC = ({ assistant, setActiveTopic, showSetting, setShowSetting }) => { const [text, setText] = useState(_text) const [inputFocus, setInputFocus] = useState(false) const { addTopic } = useAssistant(assistant.id) @@ -194,6 +195,7 @@ const Inputbar: FC = ({ assistant, setActiveTopic }) => { variant="borderless" rows={1} ref={textareaRef} + style={{ fontSize }} styles={{ textarea: TextareaStyle }} onFocus={() => setInputFocus(true)} onBlur={() => setInputFocus(false)} @@ -219,13 +221,8 @@ const Inputbar: FC = ({ assistant, setActiveTopic }) => { - - EventEmitter.emit(EVENT_NAMES.SHOW_TOPIC_SIDEBAR)}> - - - - - EventEmitter.emit(EVENT_NAMES.SHOW_CHAT_SETTINGS)}> + + setShowSetting(!showSetting)}> diff --git a/src/renderer/src/pages/home/Messages/Message.tsx b/src/renderer/src/pages/home/Messages/Message.tsx index 1d9a7c55e4..915855cc65 100644 --- a/src/renderer/src/pages/home/Messages/Message.tsx +++ b/src/renderer/src/pages/home/Messages/Message.tsx @@ -162,7 +162,7 @@ const MessageItem: FC = ({ message, index, showMenu, onDeleteMessage }) = {canRegenerate && ( - + diff --git a/src/renderer/src/pages/home/RightSidebar/index.tsx b/src/renderer/src/pages/home/RightSidebar/index.tsx deleted file mode 100644 index d01e9f0ce3..0000000000 --- a/src/renderer/src/pages/home/RightSidebar/index.tsx +++ /dev/null @@ -1,96 +0,0 @@ -import { BarsOutlined, SettingOutlined } from '@ant-design/icons' -import { useShowRightSidebar } from '@renderer/hooks/useStore' -import { EVENT_NAMES, EventEmitter } from '@renderer/services/event' -import { Assistant, Topic } from '@renderer/types' -import { Segmented } from 'antd' -import { FC, useEffect, useState } from 'react' -import { useTranslation } from 'react-i18next' -import styled from 'styled-components' - -import SettingsTab from './SettingsTab' -import TopicsTab from './TopicsTab' - -interface Props { - assistant: Assistant - activeTopic: Topic - setActiveTopic: (topic: Topic) => void -} - -const RightSidebar: FC = (props) => { - const [tab, setTab] = useState<'topic' | 'settings'>('topic') - const { rightSidebarShown, showRightSidebar, hideRightSidebar } = useShowRightSidebar() - const { t } = useTranslation() - const isTopicTab = tab === 'topic' - const isSettingsTab = tab === 'settings' - - useEffect(() => { - const unsubscribes = [ - EventEmitter.on(EVENT_NAMES.SHOW_TOPIC_SIDEBAR, (): any => { - if (rightSidebarShown && isTopicTab) { - return hideRightSidebar() - } - if (rightSidebarShown) { - return setTab('topic') - } - showRightSidebar() - setTab('topic') - }), - EventEmitter.on(EVENT_NAMES.SHOW_CHAT_SETTINGS, (): any => { - if (rightSidebarShown && isSettingsTab) { - return hideRightSidebar() - } - if (rightSidebarShown) { - return setTab('settings') - } - showRightSidebar() - setTab('settings') - }), - EventEmitter.on(EVENT_NAMES.SWITCH_TOPIC_SIDEBAR, () => setTab('topic')) - ] - return () => unsubscribes.forEach((unsub) => unsub()) - }, [hideRightSidebar, isSettingsTab, isTopicTab, rightSidebarShown, showRightSidebar]) - - if (!rightSidebarShown) { - return null - } - - return ( - - }, - { label: t('settings.title'), value: 'settings', icon: } - ]} - block - onChange={(value) => setTab(value as 'topic' | 'settings')} - /> - - {tab === 'topic' && } - {tab === 'settings' && } - - - ) -} - -const Container = styled.div` - display: flex; - flex-direction: column; - width: var(--topic-list-width); - height: calc(100vh - var(--navbar-height)); - border-left: 0.5px solid var(--color-border); - .collapsed { - width: 0; - border-left: none; - } -` - -const TabContent = styled.div` - display: flex; - flex: 1; - flex-direction: column; - overflow-y: auto; -` - -export default RightSidebar diff --git a/src/renderer/src/pages/home/RightSidebar/SettingsTab.tsx b/src/renderer/src/pages/home/Settings.tsx similarity index 97% rename from src/renderer/src/pages/home/RightSidebar/SettingsTab.tsx rename to src/renderer/src/pages/home/Settings.tsx index cd803b5cb5..5338b6758b 100644 --- a/src/renderer/src/pages/home/RightSidebar/SettingsTab.tsx +++ b/src/renderer/src/pages/home/Settings.tsx @@ -234,7 +234,13 @@ const Container = styled.div` display: flex; flex: 1; flex-direction: column; + width: var(--topic-list-width); + max-width: var(--topic-list-width); + height: calc(100vh - var(--navbar-height)); + border-left: 0.5px solid var(--color-border); padding: 0 15px; + padding-bottom: 20px; + overflow-y: auto; ` const Label = styled.p` diff --git a/src/renderer/src/pages/home/RightSidebar/TopicsTab.tsx b/src/renderer/src/pages/home/Topics.tsx similarity index 97% rename from src/renderer/src/pages/home/RightSidebar/TopicsTab.tsx rename to src/renderer/src/pages/home/Topics.tsx index a506137a65..e540cc015b 100644 --- a/src/renderer/src/pages/home/RightSidebar/TopicsTab.tsx +++ b/src/renderer/src/pages/home/Topics.tsx @@ -18,7 +18,7 @@ interface Props { setActiveTopic: (topic: Topic) => void } -const TopicsTab: FC = ({ assistant: _assistant, activeTopic, setActiveTopic }) => { +const Topics: FC = ({ assistant: _assistant, activeTopic, setActiveTopic }) => { const { assistant, removeTopic, updateTopic, updateTopics } = useAssistant(_assistant.id) const { t } = useTranslation() const generating = useAppSelector((state) => state.runtime.generating) @@ -136,11 +136,12 @@ const Container = styled.div` display: flex; flex: 1; flex-direction: column; - padding: 10px 10px; + overflow-y: scroll; ` const TopicListItem = styled.div` padding: 7px 10px; + margin: 0 10px; cursor: pointer; border-radius: 4px; white-space: nowrap; @@ -155,4 +156,4 @@ const TopicListItem = styled.div` } ` -export default TopicsTab +export default Topics diff --git a/src/renderer/src/pages/settings/ProviderSettings/index.tsx b/src/renderer/src/pages/settings/ProviderSettings/index.tsx index ab7a9d724e..eb30968f95 100644 --- a/src/renderer/src/pages/settings/ProviderSettings/index.tsx +++ b/src/renderer/src/pages/settings/ProviderSettings/index.tsx @@ -1,5 +1,4 @@ -import { PlusOutlined } from '@ant-design/icons' -import { DeleteOutlined, EditOutlined } from '@ant-design/icons' +import { DeleteOutlined, EditOutlined, PlusOutlined } from '@ant-design/icons' import { DragDropContext, Draggable, Droppable, DropResult } from '@hello-pangea/dnd' import { getProviderLogo } from '@renderer/config/provider' import { useAllProviders, useProviders } from '@renderer/hooks/useProvider' diff --git a/src/renderer/src/pages/settings/index.tsx b/src/renderer/src/pages/settings/index.tsx index 7e82a726da..fe0bc75409 100644 --- a/src/renderer/src/pages/settings/index.tsx +++ b/src/renderer/src/pages/settings/index.tsx @@ -2,8 +2,6 @@ import { Divider } from 'antd' import Link from 'antd/es/typography/Link' import styled from 'styled-components' -import SettingsPage from './SettingsPage' - export const SettingContainer = styled.div` display: flex; flex-direction: column; @@ -69,5 +67,3 @@ export const SettingHelpLink = styled(Link)` font-size: 11px; padding: 0 5px; ` - -export default SettingsPage diff --git a/src/renderer/src/services/ProviderSDK.ts b/src/renderer/src/services/ProviderSDK.ts index 1622d4f01f..1916ac722f 100644 --- a/src/renderer/src/services/ProviderSDK.ts +++ b/src/renderer/src/services/ProviderSDK.ts @@ -54,12 +54,7 @@ export default class ProviderSDK { const userMessages = takeRight(messages, contextCount + 1).map((message) => { return { role: message.role, - content: message.images - ? [ - { type: 'text', text: message.content }, - ...message.images!.map((image) => ({ type: 'image_url', image_url: image })) - ] - : message.content + content: message.content } }) @@ -132,10 +127,22 @@ export default class ProviderSDK { return } + const _userMessages = takeRight(messages, contextCount + 1).map((message) => { + return { + role: message.role, + content: message.images + ? [ + { type: 'text', text: message.content }, + ...message.images!.map((image) => ({ type: 'image_url', image_url: image })) + ] + : message.content + } + }) + // @ts-ignore key is not typed const stream = await this.openaiSdk.chat.completions.create({ model: model.id, - messages: [systemMessage, ...userMessages].filter(Boolean) as ChatCompletionMessageParam[], + messages: [systemMessage, ..._userMessages].filter(Boolean) as ChatCompletionMessageParam[], stream: true, temperature: assistant?.settings?.temperature, max_tokens: maxTokens, diff --git a/src/renderer/src/store/settings.ts b/src/renderer/src/store/settings.ts index 94e2265d6d..7a979bc08a 100644 --- a/src/renderer/src/store/settings.ts +++ b/src/renderer/src/store/settings.ts @@ -9,7 +9,6 @@ export enum ThemeMode { } export interface SettingsState { - showRightSidebar: boolean showAssistants: boolean sendMessageShortcut: SendMessageShortcut language: string @@ -23,7 +22,6 @@ export interface SettingsState { } const initialState: SettingsState = { - showRightSidebar: true, showAssistants: true, sendMessageShortcut: 'Enter', language: navigator.language, @@ -40,12 +38,6 @@ const settingsSlice = createSlice({ name: 'settings', initialState, reducers: { - toggleRightSidebar: (state) => { - state.showRightSidebar = !state.showRightSidebar - }, - setShowRightSidebar: (state, action: PayloadAction) => { - state.showRightSidebar = action.payload - }, toggleShowAssistants: (state) => { state.showAssistants = !state.showAssistants }, @@ -80,8 +72,6 @@ const settingsSlice = createSlice({ }) export const { - setShowRightSidebar, - toggleRightSidebar, toggleShowAssistants, setSendMessageShortcut, setLanguage,