From 4dde49a9f0f116cbb9cbbd4cb144ec2f86eecc7c Mon Sep 17 00:00:00 2001 From: kangfenmao Date: Wed, 4 Sep 2024 21:29:16 +0800 Subject: [PATCH] feat: new chat style --- .../src/assets/fonts/icon-fonts/iconfont.css | 30 +++-- .../assets/fonts/icon-fonts/iconfont.woff2 | Bin 2836 -> 2916 bytes src/renderer/src/assets/styles/index.scss | 8 +- src/renderer/src/config/minapp.ts | 79 ++++++++++++ src/renderer/src/hooks/useStore.ts | 19 ++- src/renderer/src/pages/apps/AppsPage.tsx | 71 +--------- src/renderer/src/pages/home/Assistants.tsx | 25 ++-- src/renderer/src/pages/home/Chat.tsx | 11 +- src/renderer/src/pages/home/HomePage.tsx | 7 +- .../src/pages/home/Inputbar/Inputbar.tsx | 25 ++-- .../src/pages/home/Messages/Message.tsx | 9 +- .../src/pages/home/Messages/Messages.tsx | 12 +- src/renderer/src/pages/home/Navbar.tsx | 122 ++++++++++++------ src/renderer/src/pages/home/Settings.tsx | 12 +- src/renderer/src/pages/home/Topics.tsx | 5 +- .../home/components/SelectModelButton.tsx | 2 +- .../src/pages/settings/GeneralSettings.tsx | 12 +- src/renderer/src/store/index.ts | 2 +- src/renderer/src/store/migrate.ts | 10 ++ src/renderer/src/store/settings.ts | 16 ++- src/renderer/src/types/index.ts | 1 + 21 files changed, 313 insertions(+), 165 deletions(-) create mode 100644 src/renderer/src/config/minapp.ts diff --git a/src/renderer/src/assets/fonts/icon-fonts/iconfont.css b/src/renderer/src/assets/fonts/icon-fonts/iconfont.css index 6319f34107..949dafd5d1 100644 --- a/src/renderer/src/assets/fonts/icon-fonts/iconfont.css +++ b/src/renderer/src/assets/fonts/icon-fonts/iconfont.css @@ -1,6 +1,6 @@ @font-face { font-family: 'iconfont'; /* Project id 4563475 */ - src: url('iconfont.woff2?t=1725424338696') format('woff2'); + src: url('iconfont.woff2?t=1725450669049') format('woff2'); } .iconfont { @@ -11,6 +11,26 @@ -moz-osx-font-smoothing: grayscale; } +.icon-gridlines:before { + content: '\e942'; +} + +.icon-grid-frame:before { + content: '\e680'; +} + +.icon-grid-row-2copy:before { + content: '\e681'; +} + +.icon-sidebar-left:before { + content: '\e6ab'; +} + +.icon-sidebar-right:before { + content: '\e6ac'; +} + .icon-inbox:before { content: '\e869'; } @@ -43,14 +63,6 @@ content: '\e758'; } -.icon-hidesidebarhoriz:before { - content: '\e8eb'; -} - -.icon-showsidebarhoriz:before { - content: '\e944'; -} - .icon-a-addchat:before { content: '\e658'; } diff --git a/src/renderer/src/assets/fonts/icon-fonts/iconfont.woff2 b/src/renderer/src/assets/fonts/icon-fonts/iconfont.woff2 index ca971eb62fdec20d687fc5f86737b6c8806c1be5..07fda21bb786e9a58e8e0ca0b2d50752515a27d8 100644 GIT binary patch literal 2916 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 O0;^0DGW%eAJpcg9omG1P literal 2836 zcmV+v3+wcEPew8T0RR9101FfV3jhEB02Ral01C$d0RR9100000000000000000000 z0000SR0d!Gg$@dvD3)LWHUcCAJPRNI1Rw>3X9s~=8<-L!Qn4b*{yKrq;oz|aeL#rD z4gyowcCk!m_v&XT!!eJRtd01rvzhK{_lFLS8A{2+*I0Xh_XPKlEEI-x(`j6&NTd;x zX(&v;3MFVFF~nV@1VEr$+kJ090S5~G{I_X;hKb&Z;SnVSjT&*<2=S4q)SY41q4i;i zR4fKHk-+W~)4wide!lOTzmFg%Bh1m{>?e>4NWQBM>co`O{8PN zD*%_yua7^-i~uA#ldrYyj6-m*V1KH@SuczH32b%K;MNJ6kYTlBrSXyNyu&?Qb;LpO zK7Lp+cKLIig8g2~?|ZIJ>kk+AxBvMc7yt3^PgUN3$eOP_*6=>ZIlW*h~-Y$=GfVO+suqyt#)A0qUMSy>E@V}V;Dani;UzC!2>;>ZELdp*sFricp1($olGD zwZW2*SR!Iyo#;wROdV~r2yL_usUILp%Aiw)jdF*-ryR1@z9?yWPYvFeDp-cikw9h9 z*yfNv>6q_@ES)vrb4eK^&NhZmyVqs{j&|&S_ zMYye7=}AlEiv12UnWsg@PfN%i%4XqnR~GK*t~szPyH$JX6m{P7)vJ2;?&(&U z;x@?o^gOTc*Y!IbrdRLaqxSPWs{x4<4R4z^xyq zjJZ)#LM|tyQMpE)Zg@R+puOhdgZG<8|G6>b>zL%?!h#xxrpUqbNBiaS{-fojg?L|9 z(|$@pvf^Zj{c>Yy2$XSl*zx9b#L=b;D z8>U~@nQnqkM+?6ZA}XzVh3>e*Fa5hWF_Z4uZpTFeAs>|ZRDUT#;e}L()p_P zu-Dua1GAS>4Jt1prB9if7=Pq>$8@yfxK80p)E!g&%&Uo0Cm>!?g8<5nR$8f;v&OP>F9q6f`s};=55Og z*Jhqvn>rE|v+bI!LS9v~g?{rLr7L=}J2G>q-1bF9%9Uy6$W@C|?sR4TgowN&2okD6 zki*7AT>YFo5(?gjl;@cWP3zrZ`1I)iXT`B`)HBQlhX_}M(JG)H`^TiAxCk@$T-3lF7QkEx$2N1qkb zR_vL|P0eL$O8>vVEB;T#cYB0=+{x+MaMtjr?gWc}Z5fmEEw&cwGyKVLwmYo<1Sjn6 zxoh}iSG-038xcI1-jtf!)JKro=M9Se0lLb|1q1UBAltlN9^6U)=ro>!&ggO)(*J26 z9)=Gfc5(Y#7jb=&c-Pr%7|sfGQ@S1`!&eLb1$eheY+2_$PP}@Lc`GRWdb6T8wD^Ak z#INWnzy5Tf#R*koLcre8&-U*h%`TtL?kVhL1B8-Gg8quCLgDOxe_wMV3a0H4YeevK zA&c38U9v0=vIXD|QHWEC3iN?QUA8X}kcobfXvjvO2jk-j5W_0K0rLq202O==*%*Yu zT($s0;5y=v_!NC0@w;qakij3&4-!9RBcQS1XCpv`dCVIVDp}}{5KT^wiaOW(O@2Ee zr?vbOOGFcNbsO*cqC{NAePriXstz3I89q<1N7Iy{a308L9aPJ@X&iN*+T?lh#)N9+ zx6mJpMw63UU8BF>H~H;^%#8iFSPnjM{m|7dBlb&7tXVt4%g(Py2PEnJreE-Qje(JzgLD5WA_*hh@K& zm`J3O8Cfe7iK3YF(&TcyiDn~|?3G0xy9W(4Q#C~&^jR5`Oe3gorlR^yD8OevzJ_Q? mFiMXcGRM=aXvIGEfIF config.app) + .map(([key, config]) => ({ id: key, ...config.app })) + .concat(_apps) + return list +} + +export function startMinAppById(id: string) { + const app = getAllMinApps().find((app) => app?.id === id) + app && MinApp.start(app) +} diff --git a/src/renderer/src/hooks/useStore.ts b/src/renderer/src/hooks/useStore.ts index 51e0981b8f..c1f24fccbf 100644 --- a/src/renderer/src/hooks/useStore.ts +++ b/src/renderer/src/hooks/useStore.ts @@ -1,5 +1,11 @@ import { useAppDispatch, useAppSelector } from '@renderer/store' -import { setShowRightSidebar, toggleRightSidebar, toggleShowAssistants } from '@renderer/store/settings' +import { + setShowRightSidebar, + setShowTopics, + toggleRightSidebar, + toggleShowAssistants, + toggleShowTopics +} from '@renderer/store/settings' export function useShowRightSidebar() { const showRightSidebar = useAppSelector((state) => state.settings.showRightSidebar) @@ -23,6 +29,17 @@ export function useShowAssistants() { } } +export function useShowTopics() { + const showTopics = useAppSelector((state) => state.settings.showTopics) + const dispatch = useAppDispatch() + + return { + showTopics, + setShowTopics: (show: boolean) => dispatch(setShowTopics(show)), + toggleShowTopics: () => dispatch(toggleShowTopics()) + } +} + export function useRuntime() { return useAppSelector((state) => state.runtime) } diff --git a/src/renderer/src/pages/apps/AppsPage.tsx b/src/renderer/src/pages/apps/AppsPage.tsx index 0d6b5f884e..7b6baf13cd 100644 --- a/src/renderer/src/pages/apps/AppsPage.tsx +++ b/src/renderer/src/pages/apps/AppsPage.tsx @@ -1,18 +1,7 @@ import { SearchOutlined } from '@ant-design/icons' -import AiAssistantAppLogo from '@renderer/assets/images/apps/360-ai.png' -import AiSearchAppLogo from '@renderer/assets/images/apps/ai-search.png' -import BaiduAiAppLogo from '@renderer/assets/images/apps/baidu-ai.png' -import DevvAppLogo from '@renderer/assets/images/apps/devv.png' -import MetasoAppLogo from '@renderer/assets/images/apps/metaso.webp' -import PerplexityAppLogo from '@renderer/assets/images/apps/perplexity.webp' -import SensetimeAppLogo from '@renderer/assets/images/apps/sensetime.png' -import SparkDeskAppLogo from '@renderer/assets/images/apps/sparkdesk.png' -import TiangongAiLogo from '@renderer/assets/images/apps/tiangong.png' -import TencentYuanbaoAppLogo from '@renderer/assets/images/apps/yuanbao.png' import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar' import { Center } from '@renderer/components/Layout' -import { PROVIDER_CONFIG } from '@renderer/config/provider' -import { MinAppType } from '@renderer/types' +import { getAllMinApps } from '@renderer/config/minapp' import { Empty, Input } from 'antd' import { isEmpty } from 'lodash' import { FC, useState } from 'react' @@ -21,68 +10,12 @@ import styled from 'styled-components' import App from './App' -const _apps: MinAppType[] = [ - { - name: 'AI 助手', - logo: AiAssistantAppLogo, - url: 'https://bot.360.com/' - }, - { - name: '文心一言', - logo: BaiduAiAppLogo, - url: 'https://yiyan.baidu.com/' - }, - { - name: 'SparkDesk', - logo: SparkDeskAppLogo, - url: 'https://xinghuo.xfyun.cn/desk' - }, - { - name: '腾讯元宝', - logo: TencentYuanbaoAppLogo, - url: 'https://yuanbao.tencent.com/chat' - }, - { - name: '商量', - logo: SensetimeAppLogo, - url: 'https://chat.sensetime.com/wb/chat' - }, - { - name: '360AI搜索', - logo: AiSearchAppLogo, - url: 'https://so.360.com/' - }, - { - name: '秘塔AI搜索', - logo: MetasoAppLogo, - url: 'https://metaso.cn/' - }, - { - name: '天工AI', - logo: TiangongAiLogo, - url: 'https://www.tiangong.cn/' - }, - { - name: 'DEVV_', - logo: DevvAppLogo, - url: 'https://devv.ai/' - }, - { - name: 'perplexity', - logo: PerplexityAppLogo, - url: 'https://www.perplexity.ai/' - } -] +const list = getAllMinApps() const AppsPage: FC = () => { const { t } = useTranslation() const [search, setSearch] = useState('') - const list: MinAppType[] = (Object.entries(PROVIDER_CONFIG) as any[]) - .filter(([, config]) => config.app) - .map(([key, config]) => ({ id: key, ...config.app })) - .concat(_apps) - const apps = search ? list.filter( (app) => app.name.toLowerCase().includes(search.toLowerCase()) || app.url.includes(search.toLowerCase()) diff --git a/src/renderer/src/pages/home/Assistants.tsx b/src/renderer/src/pages/home/Assistants.tsx index 8e4f290207..9866a01356 100644 --- a/src/renderer/src/pages/home/Assistants.tsx +++ b/src/renderer/src/pages/home/Assistants.tsx @@ -1,7 +1,8 @@ -import { ArrowRightOutlined, CopyOutlined, DeleteOutlined, EditOutlined } from '@ant-design/icons' +import { CopyOutlined, DeleteOutlined, EditOutlined } from '@ant-design/icons' import DragableList from '@renderer/components/DragableList' import AssistantSettingPopup from '@renderer/components/Popups/AssistantSettingPopup' import { useAssistant, useAssistants } from '@renderer/hooks/useAssistant' +import { useShowTopics } from '@renderer/hooks/useStore' import { getDefaultTopic, syncAsistantToAgent } from '@renderer/services/assistant' import { EVENT_NAMES, EventEmitter } from '@renderer/services/event' import { useAppSelector } from '@renderer/store' @@ -24,6 +25,7 @@ const Assistants: FC = ({ activeAssistant, setActiveAssistant, onCreateAs const { assistants, removeAssistant, addAssistant, updateAssistants } = useAssistants() const generating = useAppSelector((state) => state.runtime.generating) const { updateAssistant } = useAssistant(activeAssistant.id) + const { toggleShowTopics } = useShowTopics() const { t } = useTranslation() const onDelete = useCallback( @@ -84,10 +86,14 @@ const Assistants: FC = ({ activeAssistant, setActiveAssistant, onCreateAs }) } + if (assistant.id === activeAssistant?.id) { + toggleShowTopics() + } + EventEmitter.emit(EVENT_NAMES.SWITCH_TOPIC_SIDEBAR) setActiveAssistant(assistant) }, - [generating, setActiveAssistant, t] + [activeAssistant?.id, generating, setActiveAssistant, t, toggleShowTopics] ) return ( @@ -99,8 +105,8 @@ const Assistants: FC = ({ activeAssistant, setActiveAssistant, onCreateAs onClick={() => onSwitchAssistant(assistant)} className={assistant.id === activeAssistant?.id ? 'active' : ''}> {assistant.name || t('chat.default.name')} - onEditAssistant(assistant)}> - + + {false && {assistant.topics.length}} @@ -120,7 +126,7 @@ const Container = styled.div` height: calc(100vh - var(--navbar-height)); overflow-y: auto; padding-top: 10px; - padding-bottom: 0; + padding-bottom: 10px; ` const AssistantItem = styled.div` @@ -134,7 +140,7 @@ const AssistantItem = styled.div` padding-right: 35px; cursor: pointer; font-family: Ubuntu; - .anticon { + .iconfont { opacity: 0; color: var(--color-text-3); } @@ -143,7 +149,7 @@ const AssistantItem = styled.div` .topics-count { display: none; } - .anticon { + .iconfont { opacity: 1; } } @@ -152,7 +158,7 @@ const AssistantItem = styled.div` .topics-count { display: none; } - .anticon { + .iconfont { opacity: 1; color: var(--color-text-2); } @@ -182,6 +188,9 @@ const ArrowRightButton = styled.div` position: absolute; right: 10px; top: 5px; + .anticon { + font-size: 14px; + } &:hover { background-color: var(--color-background); } diff --git a/src/renderer/src/pages/home/Chat.tsx b/src/renderer/src/pages/home/Chat.tsx index 17d02c7eb7..88fc937f52 100644 --- a/src/renderer/src/pages/home/Chat.tsx +++ b/src/renderer/src/pages/home/Chat.tsx @@ -1,5 +1,5 @@ import { useAssistant } from '@renderer/hooks/useAssistant' -import { useShowRightSidebar } from '@renderer/hooks/useStore' +import { useShowRightSidebar, useShowTopics } from '@renderer/hooks/useStore' import { Assistant, Topic } from '@renderer/types' import { Flex } from 'antd' import { FC, useEffect, useState } from 'react' @@ -7,7 +7,7 @@ import styled from 'styled-components' import Inputbar from './Inputbar/Inputbar' import Messages from './Messages/Messages' -import RightSidebar from './RightSidebar' +import Topics from './Topics' interface Props { assistant: Assistant @@ -19,6 +19,7 @@ const Chat: FC = (props) => { const { assistant } = useAssistant(props.assistant.id) const [showSetting, setShowSetting] = useState(false) const { rightSidebarShown } = useShowRightSidebar() + const { showTopics } = useShowTopics() useEffect(() => { !rightSidebarShown && showSetting && setShowSetting(false) @@ -26,11 +27,13 @@ const Chat: FC = (props) => { return ( + {showTopics && ( + + )}
- +
-
) } diff --git a/src/renderer/src/pages/home/HomePage.tsx b/src/renderer/src/pages/home/HomePage.tsx index e5a5226cb4..bcd1885dfa 100644 --- a/src/renderer/src/pages/home/HomePage.tsx +++ b/src/renderer/src/pages/home/HomePage.tsx @@ -34,7 +34,12 @@ const HomePage: FC = () => { return ( - + {showAssistants && ( = ({ assistant, setActiveTopic }) => { const [files, setFiles] = useState([]) const { t } = useTranslation() const containerRef = useRef(null) + const { toggleShowTopics } = useShowTopics() _text = text @@ -204,7 +208,7 @@ const Inputbar: FC = ({ assistant, setActiveTopic }) => { - + @@ -221,15 +225,17 @@ const Inputbar: FC = ({ assistant, setActiveTopic }) => { - EventEmitter.emit(EVENT_NAMES.SHOW_TOPIC_SIDEBAR)}> + - - EventEmitter.emit(EVENT_NAMES.SHOW_CHAT_SETTINGS)}> - - - + } trigger="click" placement="topRight"> + + + + + + {/* */} @@ -250,6 +256,7 @@ const Inputbar: FC = ({ assistant, setActiveTopic }) => { )} + {generating && ( diff --git a/src/renderer/src/pages/home/Messages/Message.tsx b/src/renderer/src/pages/home/Messages/Message.tsx index 22fa3e574c..7d4eb39531 100644 --- a/src/renderer/src/pages/home/Messages/Message.tsx +++ b/src/renderer/src/pages/home/Messages/Message.tsx @@ -9,6 +9,7 @@ import { } from '@ant-design/icons' import UserPopup from '@renderer/components/Popups/UserPopup' import { FONT_FAMILY } from '@renderer/config/constant' +import { startMinAppById } from '@renderer/config/minapp' import { getModelLogo } from '@renderer/config/provider' import { useAssistant } from '@renderer/hooks/useAssistant' import useAvatar from '@renderer/hooks/useAvatar' @@ -127,12 +128,18 @@ const MessageItem: FC = ({ message, index, showMenu, onDeleteMessage }) = ) }, [message, t]) + const showMiniApp = () => model?.provider && startMinAppById(model?.provider) + return ( {isAssistantMessage ? ( - + {avatarName} ) : ( diff --git a/src/renderer/src/pages/home/Messages/Messages.tsx b/src/renderer/src/pages/home/Messages/Messages.tsx index f608e1923a..fcda339a4a 100644 --- a/src/renderer/src/pages/home/Messages/Messages.tsx +++ b/src/renderer/src/pages/home/Messages/Messages.tsx @@ -20,9 +20,10 @@ import Prompt from './Prompt' interface Props { assistant: Assistant topic: Topic + setActiveTopic: (topic: Topic) => void } -const Messages: FC = ({ assistant, topic }) => { +const Messages: FC = ({ assistant, topic, setActiveTopic }) => { const [messages, setMessages] = useState([]) const [lastMessage, setLastMessage] = useState(null) const provider = useProviderByAssistant(assistant) @@ -42,9 +43,13 @@ const Messages: FC = ({ assistant, topic }) => { const _topic = getTopic(assistant, topic.id) if (_topic && _topic.name === t('chat.default.topic.name') && messages.length >= 2) { const summaryText = await fetchMessagesSummary({ messages, assistant }) - summaryText && updateTopic({ ..._topic, name: summaryText }) + if (summaryText) { + const data = { ..._topic, name: summaryText } + setActiveTopic(data) + updateTopic(data) + } } - }, [assistant, messages, topic, updateTopic]) + }, [assistant, messages, setActiveTopic, topic.id, updateTopic]) const onDeleteMessage = useCallback( (message: Message) => { @@ -117,6 +122,7 @@ const Messages: FC = ({ assistant, topic }) => { } const Container = styled.div` + position: relative; display: flex; flex-direction: column; overflow-y: auto; diff --git a/src/renderer/src/pages/home/Navbar.tsx b/src/renderer/src/pages/home/Navbar.tsx index e2bf45575f..ead9027668 100644 --- a/src/renderer/src/pages/home/Navbar.tsx +++ b/src/renderer/src/pages/home/Navbar.tsx @@ -1,28 +1,30 @@ +import { FormOutlined } from '@ant-design/icons' import { Navbar, NavbarCenter, NavbarLeft, NavbarRight } from '@renderer/components/app/Navbar' +import { HStack } from '@renderer/components/Layout' import AddAssistantPopup from '@renderer/components/Popups/AddAssistantPopup' import { isMac, isWindows } from '@renderer/config/constant' import { useTheme } from '@renderer/context/ThemeProvider' import { useAssistant } from '@renderer/hooks/useAssistant' -import { useShowAssistants, useShowRightSidebar } from '@renderer/hooks/useStore' -import { Assistant } from '@renderer/types' -import { removeLeadingEmoji } from '@renderer/utils' +import { useShowAssistants, useShowTopics } from '@renderer/hooks/useStore' +import { getDefaultTopic } from '@renderer/services/assistant' +import { Assistant, Topic } from '@renderer/types' import { Switch } from 'antd' -import { FC } from 'react' +import { FC, useCallback } from 'react' import { useTranslation } from 'react-i18next' import styled from 'styled-components' -import SelectModelButton from './components/SelectModelButton' - interface Props { activeAssistant: Assistant + activeTopic: Topic setActiveAssistant: (assistant: Assistant) => void + setActiveTopic: (topic: Topic) => void } -const HeaderNavbar: FC = ({ activeAssistant, setActiveAssistant }) => { - const { assistant } = useAssistant(activeAssistant.id) +const HeaderNavbar: FC = ({ activeAssistant, activeTopic, setActiveAssistant, setActiveTopic }) => { + const { assistant, addTopic } = useAssistant(activeAssistant.id) const { t } = useTranslation() const { showAssistants, toggleShowAssistants } = useShowAssistants() - const { rightSidebarShown, toggleRightSidebar } = useShowRightSidebar() + const { showTopics, toggleShowTopics } = useShowTopics() const { theme, toggleTheme } = useTheme() const onCreateAssistant = async () => { @@ -30,37 +32,68 @@ const HeaderNavbar: FC = ({ activeAssistant, setActiveAssistant }) => { assistant && setActiveAssistant(assistant) } + const addNewTopic = useCallback(() => { + const topic = getDefaultTopic() + addTopic(topic) + setActiveTopic(topic) + }, [addTopic, setActiveTopic]) + return ( {showAssistants && ( - + - - + + )} - - {!showAssistants && ( - - + {showTopics && ( + + + {!showAssistants && ( + + + + )} + {showAssistants && ( + + {t('chat.topics.title')} ({assistant.topics.length}) + + )} + + + - )} - {removeLeadingEmoji(assistant?.name) || t('chat.default.name')} - - - - } - unCheckedChildren={} - checked={theme === 'dark'} - onChange={toggleTheme} - /> - - - + + )} + + + {!showAssistants && !showTopics && ( + toggleShowAssistants()} style={{ marginRight: isMac ? 8 : 25 }}> + + + )} + + {assistant.name} {!showTopics && toggleShowTopics()}>#{activeTopic.name}#} + + + + } + unCheckedChildren={} + checked={theme === 'dark'} + onChange={toggleTheme} + /> + ) @@ -69,23 +102,23 @@ const HeaderNavbar: FC = ({ activeAssistant, setActiveAssistant }) => { export const NewButton = styled.div` -webkit-app-region: none; border-radius: 4px; - width: 30px; height: 30px; + padding: 0 8px; display: flex; flex-direction: row; justify-content: center; align-items: center; transition: all 0.2s ease-in-out; - color: var(--color-icon); cursor: pointer; + .iconfont { + font-size: 18px; + color: var(--color-icon); + } .icon-a-addchat { font-size: 20px; } .anticon { - font-size: 19px; - } - .icon-showsidebarhoriz, - .icon-hidesidebarhoriz { + color: var(--color-icon); font-size: 17px; } &:hover { @@ -94,18 +127,29 @@ export const NewButton = styled.div` } ` -const AssistantName = styled.span` +const TitleText = styled.span` margin-left: 5px; - margin-right: 10px; font-family: Ubuntu; + font-size: 13px; ` const ThemeSwitch = styled(Switch)` - -webkit-app-region: none; + -webkit-app-region: no-drag; margin-right: 10px; .icon-theme { font-size: 14px; } ` +const HashTag = styled.span` + -webkit-app-region: no-drag; + color: var(--color-primary); + margin-left: 5px; + user-select: none; + cursor: pointer; + &:hover { + text-decoration: underline; + } +` + export default HeaderNavbar diff --git a/src/renderer/src/pages/home/Settings.tsx b/src/renderer/src/pages/home/Settings.tsx index 5338b6758b..2c331ce410 100644 --- a/src/renderer/src/pages/home/Settings.tsx +++ b/src/renderer/src/pages/home/Settings.tsx @@ -87,7 +87,7 @@ const SettingsTab: FC = (props) => { return ( - + {t('settings.messages.model.title')}{' '} @@ -234,13 +234,9 @@ 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; + overflow: hidden; + min-width: 300px; + padding-bottom: 10px; ` const Label = styled.p` diff --git a/src/renderer/src/pages/home/Topics.tsx b/src/renderer/src/pages/home/Topics.tsx index 47ad7e93cd..65e430d3e3 100644 --- a/src/renderer/src/pages/home/Topics.tsx +++ b/src/renderer/src/pages/home/Topics.tsx @@ -127,7 +127,7 @@ const Container = styled.div` padding-top: 10px; min-width: var(--topic-list-width); max-width: var(--topic-list-width); - border-left: 0.5px solid var(--color-border); + border-right: 0.5px solid var(--color-border); overflow-y: scroll; height: calc(100vh - var(--navbar-height)); ` @@ -146,7 +146,8 @@ const TopicListItem = styled.div` background-color: var(--color-background-soft); } &.active { - background-color: var(--color-background-mute); + background-color: var(--color-primary); + color: white; } ` diff --git a/src/renderer/src/pages/home/components/SelectModelButton.tsx b/src/renderer/src/pages/home/components/SelectModelButton.tsx index 3b50570bc7..e8db8e854b 100644 --- a/src/renderer/src/pages/home/components/SelectModelButton.tsx +++ b/src/renderer/src/pages/home/components/SelectModelButton.tsx @@ -23,7 +23,7 @@ const SelectModelButton: FC = ({ assistant }) => { } return ( - + {model ? upperFirst(model.name) : t('button.select_model')} diff --git a/src/renderer/src/pages/settings/GeneralSettings.tsx b/src/renderer/src/pages/settings/GeneralSettings.tsx index 7a58db38da..7b57fb9999 100644 --- a/src/renderer/src/pages/settings/GeneralSettings.tsx +++ b/src/renderer/src/pages/settings/GeneralSettings.tsx @@ -43,7 +43,7 @@ const GeneralSettings: FC = () => { {t('common.language')} { {t('settings.theme.window.style.title')}