revert: fold topics

This commit is contained in:
kangfenmao 2024-09-04 15:37:39 +08:00
parent 563472f3a9
commit ce830b692b
15 changed files with 302 additions and 218 deletions

View File

@ -36,8 +36,8 @@
--color-error: #f44336;
--color-link: #1677ff;
--color-code-background: #323232;
--color-scrollbar-thumb: rgba(255, 255, 255, 0.15);
--color-scrollbar-thumb-hover: rgba(255, 255, 255, 0.3);
--color-scrollbar-thumb: rgba(255, 255, 255, 0.08);
--color-scrollbar-thumb-hover: rgba(255, 255, 255, 0.15);
--navbar-background-mac: rgba(30, 30, 30, 0.8);
--navbar-background: rgba(30, 30, 30);
@ -48,8 +48,8 @@
--status-bar-height: 40px;
--input-bar-height: 85px;
--assistants-width: 280px;
--topic-list-width: 280px;
--assistants-width: 250px;
--topic-list-width: 250px;
--settings-width: var(--assistants-width);
}
@ -86,8 +86,8 @@ body[theme-mode='light'] {
--color-error: #f44336;
--color-link: #1677ff;
--color-code-background: #e3e3e3;
--color-scrollbar-thumb: rgba(0, 0, 0, 0.15);
--color-scrollbar-thumb-hover: rgba(0, 0, 0, 0.3);
--color-scrollbar-thumb: rgba(0, 0, 0, 0.08);
--color-scrollbar-thumb-hover: rgba(0, 0, 0, 0.15);
--navbar-background-mac: rgba(255, 255, 255, 0.75);
--navbar-background: rgba(255, 255, 255);

View File

@ -1,7 +1,7 @@
/* 全局初始化滚动条样式 */
::-webkit-scrollbar {
width: 3px;
height: 3px;
width: 2px;
height: 2px;
}
::-webkit-scrollbar-track {
@ -10,7 +10,6 @@
::-webkit-scrollbar-thumb {
background: var(--color-scrollbar-thumb);
border-radius: 5px;
&:hover {
background: var(--color-scrollbar-thumb-hover);
}

View File

@ -4,13 +4,14 @@ import { FC } from 'react'
interface Props<T> {
list: T[]
style?: React.CSSProperties
children: (item: T, index: number) => React.ReactNode
onUpdate: (list: T[]) => void
onDragStart?: () => void
onDragEnd?: () => void
}
const DragableList: FC<Props<any>> = ({ children, list, onDragStart, onUpdate, onDragEnd }) => {
const DragableList: FC<Props<any>> = ({ children, list, style, onDragStart, onUpdate, onDragEnd }) => {
const _onDragEnd = (result: DropResult) => {
onDragEnd?.()
if (result.destination) {
@ -33,7 +34,7 @@ const DragableList: FC<Props<any>> = ({ children, list, onDragStart, onUpdate, o
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
style={{ ...provided.draggableProps.style, marginBottom: 8 }}>
style={{ ...provided.draggableProps.style, marginBottom: 8, ...style }}>
{children(item, index)}
</div>
)}

View File

@ -34,7 +34,14 @@ const AssistantSettingPopupContainer: React.FC<Props> = ({ assistant, resolve })
}
return (
<Modal title={assistant.name} open={open} onOk={onOk} onCancel={handleCancel} afterClose={onClose}>
<Modal
title={assistant.name}
open={open}
onOk={onOk}
onCancel={handleCancel}
afterClose={onClose}
transitionName="ant-move-down"
maskTransitionName="ant-fade">
<Box mb={8}>{t('common.name')}</Box>
<Input
placeholder={t('common.assistant') + t('common.name')}

View File

@ -1,5 +1,17 @@
import { useAppDispatch, useAppSelector } from '@renderer/store'
import { toggleShowAssistants } from '@renderer/store/settings'
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))
}
}
export function useShowAssistants() {
const showAssistants = useAppSelector((state) => state.settings.showAssistants)

View File

@ -70,6 +70,7 @@ const resources = {
'topics.delete.all.content': 'Are you sure you want to delete all topics?',
'topics.list': 'Topic List',
'input.new_topic': 'New Topic',
'input.topics': ' Topics ',
'input.clear': 'Clear',
'input.expand': 'Expand',
'input.collapse': 'Collapse',
@ -315,6 +316,7 @@ const resources = {
'topics.delete.all.content': '确定要删除所有话题吗?',
'topics.list': '话题列表',
'input.new_topic': '新话题',
'input.topics': ' 话题 ',
'input.clear': '清除',
'input.expand': '展开',
'input.collapse': '收起',

View File

@ -5,36 +5,22 @@ 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, Topic } from '@renderer/types'
import { Assistant } from '@renderer/types'
import { uuid } from '@renderer/utils'
import { Dropdown, Tooltip } from 'antd'
import { Dropdown } from 'antd'
import { ItemType } from 'antd/es/menu/interface'
import { last } from 'lodash'
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<Props> = ({
activeAssistant,
setActiveAssistant,
activeTopic,
setActiveTopic,
showTopics,
setShowTopics,
onCreateAssistant
}) => {
const Assistants: FC<Props> = ({ activeAssistant, setActiveAssistant, onCreateAssistant }) => {
const { assistants, removeAssistant, addAssistant, updateAssistants } = useAssistants()
const generating = useAppSelector((state) => state.runtime.generating)
const { updateAssistant } = useAssistant(activeAssistant.id)
@ -49,6 +35,15 @@ const Assistants: FC<Props> = ({
[assistants, onCreateAssistant, removeAssistant, setActiveAssistant]
)
const onEditAssistant = useCallback(
async (assistant: Assistant) => {
const _assistant = await AssistantSettingPopup.show({ assistant })
updateAssistant(_assistant)
syncAsistantToAgent(_assistant)
},
[updateAssistant]
)
const getMenuItems = useCallback(
(assistant: Assistant) =>
[
@ -56,11 +51,7 @@ const Assistants: FC<Props> = ({
label: t('common.edit'),
key: 'edit',
icon: <EditOutlined />,
async onClick() {
const _assistant = await AssistantSettingPopup.show({ assistant })
updateAssistant(_assistant)
syncAsistantToAgent(_assistant)
}
onClick: () => onEditAssistant(assistant)
},
{
label: t('common.duplicate'),
@ -81,7 +72,7 @@ const Assistants: FC<Props> = ({
onClick: () => onDelete(assistant)
}
] as ItemType[],
[addAssistant, onDelete, setActiveAssistant, t, updateAssistant]
[addAssistant, onDelete, onEditAssistant, setActiveAssistant, t]
)
const onSwitchAssistant = useCallback(
@ -93,25 +84,12 @@ const Assistants: FC<Props> = ({
})
}
if (assistant.id === activeAssistant?.id) {
setShowTopics(true)
return
}
EventEmitter.emit(EVENT_NAMES.SWITCH_TOPIC_SIDEBAR)
setActiveAssistant(assistant)
},
[activeAssistant?.id, generating, setActiveAssistant, setShowTopics, t]
[generating, setActiveAssistant, t]
)
if (showTopics) {
return (
<Container style={{ padding: 0 }}>
<Topics assistant={activeAssistant} activeTopic={activeTopic} setActiveTopic={setActiveTopic} />
</Container>
)
}
return (
<Container>
<DragableList list={assistants} onUpdate={updateAssistants}>
@ -121,11 +99,9 @@ const Assistants: FC<Props> = ({
onClick={() => onSwitchAssistant(assistant)}
className={assistant.id === activeAssistant?.id ? 'active' : ''}>
<AssistantName className="name">{assistant.name || t('chat.default.name')}</AssistantName>
<Tooltip arrow title={t('chat.topics.list')} placement="bottom" mouseEnterDelay={0.5}>
<ArrowRightButton className="arrow-button" onClick={() => setShowTopics(true)}>
<ArrowRightOutlined />
</ArrowRightButton>
</Tooltip>
<ArrowRightButton className="arrow-button" onClick={() => onEditAssistant(assistant)}>
<ArrowRightOutlined />
</ArrowRightButton>
{false && <TopicCount className="topics-count">{assistant.topics.length}</TopicCount>}
</AssistantItem>
</Dropdown>
@ -205,6 +181,7 @@ const ArrowRightButton = styled.div`
border-radius: 4px;
position: absolute;
right: 10px;
top: 5px;
&:hover {
background-color: var(--color-background);
}

View File

@ -1,12 +1,13 @@
import { useAssistant } from '@renderer/hooks/useAssistant'
import { useShowRightSidebar } from '@renderer/hooks/useStore'
import { Assistant, Topic } from '@renderer/types'
import { Flex } from 'antd'
import { FC, useState } from 'react'
import { FC, useEffect, useState } from 'react'
import styled from 'styled-components'
import Inputbar from './Inputbar/Inputbar'
import Messages from './Messages/Messages'
import Settings from './Settings'
import RightSidebar from './RightSidebar'
interface Props {
assistant: Assistant
@ -17,19 +18,19 @@ interface Props {
const Chat: FC<Props> = (props) => {
const { assistant } = useAssistant(props.assistant.id)
const [showSetting, setShowSetting] = useState(false)
const { rightSidebarShown } = useShowRightSidebar()
useEffect(() => {
!rightSidebarShown && showSetting && setShowSetting(false)
}, [rightSidebarShown, showSetting])
return (
<Container id="chat">
<Main vertical flex={1} justify="space-between">
<Messages assistant={assistant} topic={props.activeTopic} />
<Inputbar
assistant={assistant}
setActiveTopic={props.setActiveTopic}
showSetting={showSetting}
setShowSetting={setShowSetting}
/>
<Inputbar assistant={assistant} setActiveTopic={props.setActiveTopic} />
</Main>
{showSetting && <Settings assistant={assistant} onClose={() => setShowSetting(false)} />}
<RightSidebar assistant={assistant} activeTopic={props.activeTopic} setActiveTopic={props.setActiveTopic} />
</Container>
)
}

View File

@ -1,41 +1,26 @@
import { ArrowLeftOutlined, UnorderedListOutlined } from '@ant-design/icons'
import { Navbar, NavbarCenter, NavbarLeft } from '@renderer/components/app/Navbar'
import { HStack } from '@renderer/components/Layout'
import { isMac, isWindows } from '@renderer/config/constant'
import { useTheme } from '@renderer/context/ThemeProvider'
import { useAssistant, useAssistants, useDefaultAssistant } from '@renderer/hooks/useAssistant'
import { useAssistants, useDefaultAssistant } from '@renderer/hooks/useAssistant'
import { useShowAssistants } from '@renderer/hooks/useStore'
import { useActiveTopic } from '@renderer/hooks/useTopic'
import { getDefaultTopic } from '@renderer/services/assistant'
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 SelectModelButton from './components/SelectModelButton'
import Navbar from './Navbar'
let _activeAssistant: Assistant
let _showTopics = false
const HomePage: FC = () => {
const { assistants, addAssistant } = useAssistants()
const [activeAssistant, setActiveAssistant] = useState(_activeAssistant || assistants[0])
const { showAssistants } = useShowAssistants()
const { defaultAssistant } = useDefaultAssistant()
const { theme, toggleTheme } = useTheme()
const [showTopics, setShowTopics] = useState(_showTopics)
const { t } = useTranslation()
const { activeTopic, setActiveTopic } = useActiveTopic(activeAssistant)
const { addTopic } = useAssistant(activeAssistant.id)
_activeAssistant = activeAssistant
_showTopics = showTopics
const onCreateDefaultAssistant = () => {
const assistant = { ...defaultAssistant, id: uuid() }
@ -43,59 +28,18 @@ const HomePage: FC = () => {
setActiveAssistant(assistant)
}
const onCreate = async () => {
if (showTopics) {
const topic = getDefaultTopic()
addTopic(topic)
setActiveTopic(topic)
} else {
const assistant = await AddAssistantPopup.show()
assistant && setActiveAssistant(assistant)
}
}
const onSetActiveTopic = (topic: Topic) => {
setActiveTopic(topic)
}
return (
<Container>
<Navbar>
{showAssistants && (
<NavbarLeft
style={{ justifyContent: 'space-between', alignItems: 'center', borderRight: 'none', padding: '0 8px' }}>
<NewButton onClick={() => setShowTopics(!showTopics)} className="back-button">
{showTopics ? <ArrowLeftOutlined /> : <UnorderedListOutlined />}
<BackText>{showTopics ? t('common.assistant') : t('chat.topics.title')}</BackText>
</NewButton>
<NewButton onClick={onCreate}>
<i className="iconfont icon-a-addchat"></i>
</NewButton>
</NavbarLeft>
)}
<NavbarCenter
style={{ justifyContent: 'space-between', paddingLeft: isMac ? 16 : 8, paddingRight: isWindows ? 135 : 12 }}>
<HStack alignItems="center">
<AssistantName>{activeAssistant?.name || t('chat.default.name')}</AssistantName>
<SelectModelButton assistant={activeAssistant} />
</HStack>
<ThemeSwitch
checkedChildren={<i className="iconfont icon-theme icon-dark1" />}
unCheckedChildren={<i className="iconfont icon-theme icon-theme-light" />}
checked={theme === 'dark'}
onChange={toggleTheme}
/>
</NavbarCenter>
</Navbar>
<Navbar activeAssistant={activeAssistant} setActiveAssistant={setActiveAssistant} />
<ContentContainer>
{showAssistants && (
<Assistants
activeAssistant={activeAssistant}
setActiveAssistant={setActiveAssistant}
activeTopic={activeTopic}
setActiveTopic={setActiveTopic}
showTopics={showTopics}
setShowTopics={setShowTopics}
onCreateAssistant={onCreateDefaultAssistant}
/>
)}
@ -118,67 +62,4 @@ const ContentContainer = styled.div`
background-color: var(--color-background);
`
const AssistantName = styled.span`
margin-left: 5px;
margin-right: 10px;
font-family: Ubuntu;
font-size: 13px;
font-weight: 500;
`
export const NewButton = styled.div`
-webkit-app-region: none;
border-radius: 4px;
padding: 0 5px;
height: 30px;
gap: 5px;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
transition: all 0.2s ease-in-out;
color: var(--color-icon);
.icon-a-addchat {
font-size: 20px;
}
.anticon {
font-size: 19px;
}
.icon-showsidebarhoriz,
.icon-hidesidebarhoriz {
font-size: 17px;
}
&.back-button {
margin-left: ${isMac ? '8px' : 0};
.anticon {
font-size: 16px;
}
.anticon-arrow-left {
font-size: 14px;
}
&:hover {
background-color: var(--color-background-mute);
color: var(--color-icon-white);
}
}
&:hover {
background-color: var(--color-background-mute);
cursor: pointer;
color: var(--color-icon-white);
}
`
const BackText = styled.span`
font-size: 12px;
font-weight: 400;
`
const ThemeSwitch = styled(Switch)`
-webkit-app-region: none;
margin-right: 10px;
.icon-theme {
font-size: 14px;
}
`
export default HomePage

View File

@ -3,6 +3,7 @@ import {
ControlOutlined,
FullscreenExitOutlined,
FullscreenOutlined,
HistoryOutlined,
PauseCircleOutlined,
PlusCircleOutlined,
QuestionCircleOutlined
@ -30,13 +31,11 @@ import SendMessageButton from './SendMessageButton'
interface Props {
assistant: Assistant
setActiveTopic: (topic: Topic) => void
showSetting: boolean
setShowSetting: (show: boolean) => void
}
let _text = ''
const Inputbar: FC<Props> = ({ assistant, setActiveTopic, showSetting, setShowSetting }) => {
const Inputbar: FC<Props> = ({ assistant, setActiveTopic }) => {
const [text, setText] = useState(_text)
const [inputFocus, setInputFocus] = useState(false)
const { addTopic } = useAssistant(assistant.id)
@ -221,8 +220,13 @@ const Inputbar: FC<Props> = ({ assistant, setActiveTopic, showSetting, setShowSe
</ToolbarButton>
</Popconfirm>
</Tooltip>
<Tooltip placement="top" title={t('chat.input.settings')} arrow className={showSetting ? 'active' : ''}>
<ToolbarButton type="text" onClick={() => setShowSetting(!showSetting)}>
<Tooltip placement="top" title={t('chat.input.topics')} arrow>
<ToolbarButton type="text" onClick={() => EventEmitter.emit(EVENT_NAMES.SHOW_TOPIC_SIDEBAR)}>
<HistoryOutlined />
</ToolbarButton>
</Tooltip>
<Tooltip placement="top" title={t('chat.input.settings')} arrow>
<ToolbarButton type="text" onClick={() => EventEmitter.emit(EVENT_NAMES.SHOW_CHAT_SETTINGS)}>
<ControlOutlined />
</ToolbarButton>
</Tooltip>
@ -236,7 +240,6 @@ const Inputbar: FC<Props> = ({ assistant, setActiveTopic, showSetting, setShowSe
<TextCount>
<Tooltip title={t('chat.input.context_count.tip') + ' | ' + t('chat.input.estimated_tokens.tip')}>
<StyledTag>
<i className="iconfont icon-history" style={{ marginRight: '3px' }} />
{assistant?.settings?.contextCount ?? DEFAULT_CONEXTCOUNT}
<Divider type="vertical" style={{ marginTop: 2, marginLeft: 5, marginRight: 5 }} />{inputTokenCount}
<span style={{ margin: '0 2px' }}>/</span>
@ -342,11 +345,12 @@ const TextCount = styled.div`
const StyledTag = styled(Tag)`
cursor: pointer;
border-radius: 6px;
border-radius: 20px;
display: flex;
align-items: center;
padding: 2px 8px;
border-width: 0.5;
margin: 0;
`
export default Inputbar

View File

@ -0,0 +1,111 @@
import { Navbar, NavbarCenter, NavbarLeft, NavbarRight } from '@renderer/components/app/Navbar'
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 { Switch } from 'antd'
import { FC } from 'react'
import { useTranslation } from 'react-i18next'
import styled from 'styled-components'
import SelectModelButton from './components/SelectModelButton'
interface Props {
activeAssistant: Assistant
setActiveAssistant: (assistant: Assistant) => void
}
const HeaderNavbar: FC<Props> = ({ activeAssistant, setActiveAssistant }) => {
const { assistant } = useAssistant(activeAssistant.id)
const { t } = useTranslation()
const { showAssistants, toggleShowAssistants } = useShowAssistants()
const { rightSidebarShown, toggleRightSidebar } = useShowRightSidebar()
const { theme, toggleTheme } = useTheme()
const onCreateAssistant = async () => {
const assistant = await AddAssistantPopup.show()
assistant && setActiveAssistant(assistant)
}
return (
<Navbar>
{showAssistants && (
<NavbarLeft style={{ justifyContent: 'space-between', borderRight: 'none', padding: '0 8px' }}>
<NewButton onClick={toggleShowAssistants} style={{ marginLeft: isMac ? 8 : 0 }}>
<i className="iconfont icon-hidesidebarhoriz" />
</NewButton>
<NewButton onClick={onCreateAssistant}>
<i className="iconfont icon-a-addchat"></i>
</NewButton>
</NavbarLeft>
)}
<NavbarCenter style={{ paddingLeft: isMac ? 16 : 8 }}>
{!showAssistants && (
<NewButton onClick={toggleShowAssistants} style={{ marginRight: isMac ? 8 : 25 }}>
<i className="iconfont icon-showsidebarhoriz" />
</NewButton>
)}
<AssistantName>{removeLeadingEmoji(assistant?.name) || t('chat.default.name')}</AssistantName>
<SelectModelButton assistant={assistant} />
</NavbarCenter>
<NavbarRight style={{ justifyContent: 'flex-end', paddingRight: isWindows ? 140 : 12 }}>
<ThemeSwitch
checkedChildren={<i className="iconfont icon-theme icon-dark1" />}
unCheckedChildren={<i className="iconfont icon-theme icon-theme-light" />}
checked={theme === 'dark'}
onChange={toggleTheme}
/>
<NewButton onClick={toggleRightSidebar}>
<i className={`iconfont ${rightSidebarShown ? 'icon-showsidebarhoriz' : 'icon-hidesidebarhoriz'}`} />
</NewButton>
</NavbarRight>
</Navbar>
)
}
export const NewButton = styled.div`
-webkit-app-region: none;
border-radius: 4px;
width: 30px;
height: 30px;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
transition: all 0.2s ease-in-out;
color: var(--color-icon);
cursor: pointer;
.icon-a-addchat {
font-size: 20px;
}
.anticon {
font-size: 19px;
}
.icon-showsidebarhoriz,
.icon-hidesidebarhoriz {
font-size: 17px;
}
&:hover {
background-color: var(--color-background-mute);
color: var(--color-icon-white);
}
`
const AssistantName = styled.span`
margin-left: 5px;
margin-right: 10px;
font-family: Ubuntu;
`
const ThemeSwitch = styled(Switch)`
-webkit-app-region: none;
margin-right: 10px;
.icon-theme {
font-size: 14px;
}
`
export default HeaderNavbar

View File

@ -0,0 +1,96 @@
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 Settings from './Settings'
import Topics from './Topics'
interface Props {
assistant: Assistant
activeTopic: Topic
setActiveTopic: (topic: Topic) => void
}
const RightSidebar: FC<Props> = (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 (
<Container>
<Segmented
value={tab}
style={{ borderRadius: 0, padding: '10px', gap: 5, borderBottom: '0.5px solid var(--color-border)' }}
options={[
{ label: t('common.topics'), value: 'topic', icon: <BarsOutlined /> },
{ label: t('settings.title'), value: 'settings', icon: <SettingOutlined /> }
]}
block
onChange={(value) => setTab(value as 'topic' | 'settings')}
/>
<TabContent>
{tab === 'topic' && <Topics {...props} />}
{tab === 'settings' && <Settings assistant={props.assistant} />}
</TabContent>
</Container>
)
}
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

View File

@ -1,4 +1,4 @@
import { CheckOutlined, CloseOutlined, QuestionCircleOutlined, ReloadOutlined } from '@ant-design/icons'
import { CheckOutlined, QuestionCircleOutlined, ReloadOutlined } from '@ant-design/icons'
import { HStack } from '@renderer/components/Layout'
import { DEFAULT_CONEXTCOUNT, DEFAULT_MAX_TOKENS, DEFAULT_TEMPERATURE } from '@renderer/config/constant'
import { useAssistant } from '@renderer/hooks/useAssistant'
@ -19,7 +19,6 @@ import styled from 'styled-components'
interface Props {
assistant: Assistant
onClose: () => void
}
const SettingsTab: FC<Props> = (props) => {
@ -88,10 +87,6 @@ const SettingsTab: FC<Props> = (props) => {
return (
<Container>
<SettingsHeader>
{t('settings.title')}
<CloseIcon onClick={props.onClose} />
</SettingsHeader>
<SettingSubtitle>
{t('settings.messages.model.title')}{' '}
<Tooltip title={t('chat.settings.reset')}>
@ -264,21 +259,4 @@ const SettingRowTitleSmall = styled(SettingRowTitle)`
font-size: 13px;
`
const SettingsHeader = styled.div`
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
padding: 10px 15px;
border-bottom: 0.5px solid var(--color-border);
margin-left: -15px;
margin-right: -15px;
`
const CloseIcon = styled(CloseOutlined)`
font-size: 14px;
cursor: pointer;
color: var(--color-text-3);
`
export default SettingsTab

View File

@ -125,10 +125,15 @@ const Container = styled.div`
flex: 1;
flex-direction: column;
padding-top: 10px;
min-width: var(--topic-list-width);
max-width: var(--topic-list-width);
border-left: 0.5px solid var(--color-border);
overflow-y: scroll;
height: calc(100vh - var(--navbar-height));
`
const TopicListItem = styled.div`
padding: 5px 10px;
padding: 7px 10px;
margin: 0 10px;
cursor: pointer;
border-radius: 4px;

View File

@ -9,6 +9,7 @@ export enum ThemeMode {
}
export interface SettingsState {
showRightSidebar: boolean
showAssistants: boolean
sendMessageShortcut: SendMessageShortcut
language: string
@ -23,6 +24,7 @@ export interface SettingsState {
}
const initialState: SettingsState = {
showRightSidebar: true,
showAssistants: true,
sendMessageShortcut: 'Enter',
language: navigator.language,
@ -32,7 +34,7 @@ const initialState: SettingsState = {
messageFont: 'system',
showInputEstimatedTokens: false,
theme: ThemeMode.light,
windowStyle: 'opaque',
windowStyle: 'transparent',
fontSize: 14
}
@ -40,6 +42,12 @@ const settingsSlice = createSlice({
name: 'settings',
initialState,
reducers: {
toggleRightSidebar: (state) => {
state.showRightSidebar = !state.showRightSidebar
},
setShowRightSidebar: (state, action: PayloadAction<boolean>) => {
state.showRightSidebar = action.payload
},
toggleShowAssistants: (state) => {
state.showAssistants = !state.showAssistants
},
@ -78,6 +86,8 @@ const settingsSlice = createSlice({
})
export const {
setShowRightSidebar,
toggleRightSidebar,
toggleShowAssistants,
setSendMessageShortcut,
setLanguage,