revert: fold topics
This commit is contained in:
parent
563472f3a9
commit
ce830b692b
@ -36,8 +36,8 @@
|
|||||||
--color-error: #f44336;
|
--color-error: #f44336;
|
||||||
--color-link: #1677ff;
|
--color-link: #1677ff;
|
||||||
--color-code-background: #323232;
|
--color-code-background: #323232;
|
||||||
--color-scrollbar-thumb: rgba(255, 255, 255, 0.15);
|
--color-scrollbar-thumb: rgba(255, 255, 255, 0.08);
|
||||||
--color-scrollbar-thumb-hover: rgba(255, 255, 255, 0.3);
|
--color-scrollbar-thumb-hover: rgba(255, 255, 255, 0.15);
|
||||||
|
|
||||||
--navbar-background-mac: rgba(30, 30, 30, 0.8);
|
--navbar-background-mac: rgba(30, 30, 30, 0.8);
|
||||||
--navbar-background: rgba(30, 30, 30);
|
--navbar-background: rgba(30, 30, 30);
|
||||||
@ -48,8 +48,8 @@
|
|||||||
--status-bar-height: 40px;
|
--status-bar-height: 40px;
|
||||||
--input-bar-height: 85px;
|
--input-bar-height: 85px;
|
||||||
|
|
||||||
--assistants-width: 280px;
|
--assistants-width: 250px;
|
||||||
--topic-list-width: 280px;
|
--topic-list-width: 250px;
|
||||||
--settings-width: var(--assistants-width);
|
--settings-width: var(--assistants-width);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,8 +86,8 @@ body[theme-mode='light'] {
|
|||||||
--color-error: #f44336;
|
--color-error: #f44336;
|
||||||
--color-link: #1677ff;
|
--color-link: #1677ff;
|
||||||
--color-code-background: #e3e3e3;
|
--color-code-background: #e3e3e3;
|
||||||
--color-scrollbar-thumb: rgba(0, 0, 0, 0.15);
|
--color-scrollbar-thumb: rgba(0, 0, 0, 0.08);
|
||||||
--color-scrollbar-thumb-hover: rgba(0, 0, 0, 0.3);
|
--color-scrollbar-thumb-hover: rgba(0, 0, 0, 0.15);
|
||||||
|
|
||||||
--navbar-background-mac: rgba(255, 255, 255, 0.75);
|
--navbar-background-mac: rgba(255, 255, 255, 0.75);
|
||||||
--navbar-background: rgba(255, 255, 255);
|
--navbar-background: rgba(255, 255, 255);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/* 全局初始化滚动条样式 */
|
/* 全局初始化滚动条样式 */
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 3px;
|
width: 2px;
|
||||||
height: 3px;
|
height: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-track {
|
::-webkit-scrollbar-track {
|
||||||
@ -10,7 +10,6 @@
|
|||||||
|
|
||||||
::-webkit-scrollbar-thumb {
|
::-webkit-scrollbar-thumb {
|
||||||
background: var(--color-scrollbar-thumb);
|
background: var(--color-scrollbar-thumb);
|
||||||
border-radius: 5px;
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: var(--color-scrollbar-thumb-hover);
|
background: var(--color-scrollbar-thumb-hover);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,13 +4,14 @@ import { FC } from 'react'
|
|||||||
|
|
||||||
interface Props<T> {
|
interface Props<T> {
|
||||||
list: T[]
|
list: T[]
|
||||||
|
style?: React.CSSProperties
|
||||||
children: (item: T, index: number) => React.ReactNode
|
children: (item: T, index: number) => React.ReactNode
|
||||||
onUpdate: (list: T[]) => void
|
onUpdate: (list: T[]) => void
|
||||||
onDragStart?: () => void
|
onDragStart?: () => void
|
||||||
onDragEnd?: () => 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) => {
|
const _onDragEnd = (result: DropResult) => {
|
||||||
onDragEnd?.()
|
onDragEnd?.()
|
||||||
if (result.destination) {
|
if (result.destination) {
|
||||||
@ -33,7 +34,7 @@ const DragableList: FC<Props<any>> = ({ children, list, onDragStart, onUpdate, o
|
|||||||
ref={provided.innerRef}
|
ref={provided.innerRef}
|
||||||
{...provided.draggableProps}
|
{...provided.draggableProps}
|
||||||
{...provided.dragHandleProps}
|
{...provided.dragHandleProps}
|
||||||
style={{ ...provided.draggableProps.style, marginBottom: 8 }}>
|
style={{ ...provided.draggableProps.style, marginBottom: 8, ...style }}>
|
||||||
{children(item, index)}
|
{children(item, index)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -34,7 +34,14 @@ const AssistantSettingPopupContainer: React.FC<Props> = ({ assistant, resolve })
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
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>
|
<Box mb={8}>{t('common.name')}</Box>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t('common.assistant') + t('common.name')}
|
placeholder={t('common.assistant') + t('common.name')}
|
||||||
|
|||||||
@ -1,5 +1,17 @@
|
|||||||
import { useAppDispatch, useAppSelector } from '@renderer/store'
|
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() {
|
export function useShowAssistants() {
|
||||||
const showAssistants = useAppSelector((state) => state.settings.showAssistants)
|
const showAssistants = useAppSelector((state) => state.settings.showAssistants)
|
||||||
|
|||||||
@ -70,6 +70,7 @@ const resources = {
|
|||||||
'topics.delete.all.content': 'Are you sure you want to delete all topics?',
|
'topics.delete.all.content': 'Are you sure you want to delete all topics?',
|
||||||
'topics.list': 'Topic List',
|
'topics.list': 'Topic List',
|
||||||
'input.new_topic': 'New Topic',
|
'input.new_topic': 'New Topic',
|
||||||
|
'input.topics': ' Topics ',
|
||||||
'input.clear': 'Clear',
|
'input.clear': 'Clear',
|
||||||
'input.expand': 'Expand',
|
'input.expand': 'Expand',
|
||||||
'input.collapse': 'Collapse',
|
'input.collapse': 'Collapse',
|
||||||
@ -315,6 +316,7 @@ const resources = {
|
|||||||
'topics.delete.all.content': '确定要删除所有话题吗?',
|
'topics.delete.all.content': '确定要删除所有话题吗?',
|
||||||
'topics.list': '话题列表',
|
'topics.list': '话题列表',
|
||||||
'input.new_topic': '新话题',
|
'input.new_topic': '新话题',
|
||||||
|
'input.topics': ' 话题 ',
|
||||||
'input.clear': '清除',
|
'input.clear': '清除',
|
||||||
'input.expand': '展开',
|
'input.expand': '展开',
|
||||||
'input.collapse': '收起',
|
'input.collapse': '收起',
|
||||||
|
|||||||
@ -5,36 +5,22 @@ import { useAssistant, useAssistants } from '@renderer/hooks/useAssistant'
|
|||||||
import { getDefaultTopic, syncAsistantToAgent } from '@renderer/services/assistant'
|
import { getDefaultTopic, syncAsistantToAgent } from '@renderer/services/assistant'
|
||||||
import { EVENT_NAMES, EventEmitter } from '@renderer/services/event'
|
import { EVENT_NAMES, EventEmitter } from '@renderer/services/event'
|
||||||
import { useAppSelector } from '@renderer/store'
|
import { useAppSelector } from '@renderer/store'
|
||||||
import { Assistant, Topic } from '@renderer/types'
|
import { Assistant } from '@renderer/types'
|
||||||
import { uuid } from '@renderer/utils'
|
import { uuid } from '@renderer/utils'
|
||||||
import { Dropdown, Tooltip } from 'antd'
|
import { Dropdown } from 'antd'
|
||||||
import { ItemType } from 'antd/es/menu/interface'
|
import { ItemType } from 'antd/es/menu/interface'
|
||||||
import { last } from 'lodash'
|
import { last } from 'lodash'
|
||||||
import { FC, useCallback } from 'react'
|
import { FC, useCallback } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
|
||||||
import Topics from './Topics'
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
activeAssistant: Assistant
|
activeAssistant: Assistant
|
||||||
setActiveAssistant: (assistant: Assistant) => void
|
setActiveAssistant: (assistant: Assistant) => void
|
||||||
activeTopic: Topic
|
|
||||||
setActiveTopic: (topic: Topic) => void
|
|
||||||
showTopics: boolean
|
|
||||||
setShowTopics: (showTopics: boolean) => void
|
|
||||||
onCreateAssistant: () => void
|
onCreateAssistant: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const Assistants: FC<Props> = ({
|
const Assistants: FC<Props> = ({ activeAssistant, setActiveAssistant, onCreateAssistant }) => {
|
||||||
activeAssistant,
|
|
||||||
setActiveAssistant,
|
|
||||||
activeTopic,
|
|
||||||
setActiveTopic,
|
|
||||||
showTopics,
|
|
||||||
setShowTopics,
|
|
||||||
onCreateAssistant
|
|
||||||
}) => {
|
|
||||||
const { assistants, removeAssistant, addAssistant, updateAssistants } = useAssistants()
|
const { assistants, removeAssistant, addAssistant, updateAssistants } = useAssistants()
|
||||||
const generating = useAppSelector((state) => state.runtime.generating)
|
const generating = useAppSelector((state) => state.runtime.generating)
|
||||||
const { updateAssistant } = useAssistant(activeAssistant.id)
|
const { updateAssistant } = useAssistant(activeAssistant.id)
|
||||||
@ -49,6 +35,15 @@ const Assistants: FC<Props> = ({
|
|||||||
[assistants, onCreateAssistant, removeAssistant, setActiveAssistant]
|
[assistants, onCreateAssistant, removeAssistant, setActiveAssistant]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const onEditAssistant = useCallback(
|
||||||
|
async (assistant: Assistant) => {
|
||||||
|
const _assistant = await AssistantSettingPopup.show({ assistant })
|
||||||
|
updateAssistant(_assistant)
|
||||||
|
syncAsistantToAgent(_assistant)
|
||||||
|
},
|
||||||
|
[updateAssistant]
|
||||||
|
)
|
||||||
|
|
||||||
const getMenuItems = useCallback(
|
const getMenuItems = useCallback(
|
||||||
(assistant: Assistant) =>
|
(assistant: Assistant) =>
|
||||||
[
|
[
|
||||||
@ -56,11 +51,7 @@ const Assistants: FC<Props> = ({
|
|||||||
label: t('common.edit'),
|
label: t('common.edit'),
|
||||||
key: 'edit',
|
key: 'edit',
|
||||||
icon: <EditOutlined />,
|
icon: <EditOutlined />,
|
||||||
async onClick() {
|
onClick: () => onEditAssistant(assistant)
|
||||||
const _assistant = await AssistantSettingPopup.show({ assistant })
|
|
||||||
updateAssistant(_assistant)
|
|
||||||
syncAsistantToAgent(_assistant)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('common.duplicate'),
|
label: t('common.duplicate'),
|
||||||
@ -81,7 +72,7 @@ const Assistants: FC<Props> = ({
|
|||||||
onClick: () => onDelete(assistant)
|
onClick: () => onDelete(assistant)
|
||||||
}
|
}
|
||||||
] as ItemType[],
|
] as ItemType[],
|
||||||
[addAssistant, onDelete, setActiveAssistant, t, updateAssistant]
|
[addAssistant, onDelete, onEditAssistant, setActiveAssistant, t]
|
||||||
)
|
)
|
||||||
|
|
||||||
const onSwitchAssistant = useCallback(
|
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)
|
EventEmitter.emit(EVENT_NAMES.SWITCH_TOPIC_SIDEBAR)
|
||||||
setActiveAssistant(assistant)
|
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 (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<DragableList list={assistants} onUpdate={updateAssistants}>
|
<DragableList list={assistants} onUpdate={updateAssistants}>
|
||||||
@ -121,11 +99,9 @@ const Assistants: FC<Props> = ({
|
|||||||
onClick={() => onSwitchAssistant(assistant)}
|
onClick={() => onSwitchAssistant(assistant)}
|
||||||
className={assistant.id === activeAssistant?.id ? 'active' : ''}>
|
className={assistant.id === activeAssistant?.id ? 'active' : ''}>
|
||||||
<AssistantName className="name">{assistant.name || t('chat.default.name')}</AssistantName>
|
<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={() => onEditAssistant(assistant)}>
|
||||||
<ArrowRightButton className="arrow-button" onClick={() => setShowTopics(true)}>
|
|
||||||
<ArrowRightOutlined />
|
<ArrowRightOutlined />
|
||||||
</ArrowRightButton>
|
</ArrowRightButton>
|
||||||
</Tooltip>
|
|
||||||
{false && <TopicCount className="topics-count">{assistant.topics.length}</TopicCount>}
|
{false && <TopicCount className="topics-count">{assistant.topics.length}</TopicCount>}
|
||||||
</AssistantItem>
|
</AssistantItem>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
@ -205,6 +181,7 @@ const ArrowRightButton = styled.div`
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 10px;
|
right: 10px;
|
||||||
|
top: 5px;
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: var(--color-background);
|
background-color: var(--color-background);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,12 +1,13 @@
|
|||||||
import { useAssistant } from '@renderer/hooks/useAssistant'
|
import { useAssistant } from '@renderer/hooks/useAssistant'
|
||||||
|
import { useShowRightSidebar } from '@renderer/hooks/useStore'
|
||||||
import { Assistant, Topic } from '@renderer/types'
|
import { Assistant, Topic } from '@renderer/types'
|
||||||
import { Flex } from 'antd'
|
import { Flex } from 'antd'
|
||||||
import { FC, useState } from 'react'
|
import { FC, useEffect, useState } from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
|
||||||
import Inputbar from './Inputbar/Inputbar'
|
import Inputbar from './Inputbar/Inputbar'
|
||||||
import Messages from './Messages/Messages'
|
import Messages from './Messages/Messages'
|
||||||
import Settings from './Settings'
|
import RightSidebar from './RightSidebar'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
assistant: Assistant
|
assistant: Assistant
|
||||||
@ -17,19 +18,19 @@ interface Props {
|
|||||||
const Chat: FC<Props> = (props) => {
|
const Chat: FC<Props> = (props) => {
|
||||||
const { assistant } = useAssistant(props.assistant.id)
|
const { assistant } = useAssistant(props.assistant.id)
|
||||||
const [showSetting, setShowSetting] = useState(false)
|
const [showSetting, setShowSetting] = useState(false)
|
||||||
|
const { rightSidebarShown } = useShowRightSidebar()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
!rightSidebarShown && showSetting && setShowSetting(false)
|
||||||
|
}, [rightSidebarShown, showSetting])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container id="chat">
|
<Container id="chat">
|
||||||
<Main vertical flex={1} justify="space-between">
|
<Main vertical flex={1} justify="space-between">
|
||||||
<Messages assistant={assistant} topic={props.activeTopic} />
|
<Messages assistant={assistant} topic={props.activeTopic} />
|
||||||
<Inputbar
|
<Inputbar assistant={assistant} setActiveTopic={props.setActiveTopic} />
|
||||||
assistant={assistant}
|
|
||||||
setActiveTopic={props.setActiveTopic}
|
|
||||||
showSetting={showSetting}
|
|
||||||
setShowSetting={setShowSetting}
|
|
||||||
/>
|
|
||||||
</Main>
|
</Main>
|
||||||
{showSetting && <Settings assistant={assistant} onClose={() => setShowSetting(false)} />}
|
<RightSidebar assistant={assistant} activeTopic={props.activeTopic} setActiveTopic={props.setActiveTopic} />
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,41 +1,26 @@
|
|||||||
import { ArrowLeftOutlined, UnorderedListOutlined } from '@ant-design/icons'
|
import { useAssistants, useDefaultAssistant } from '@renderer/hooks/useAssistant'
|
||||||
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 { useShowAssistants } from '@renderer/hooks/useStore'
|
import { useShowAssistants } from '@renderer/hooks/useStore'
|
||||||
import { useActiveTopic } from '@renderer/hooks/useTopic'
|
import { useActiveTopic } from '@renderer/hooks/useTopic'
|
||||||
import { getDefaultTopic } from '@renderer/services/assistant'
|
|
||||||
import { Assistant, Topic } from '@renderer/types'
|
import { Assistant, Topic } from '@renderer/types'
|
||||||
import { uuid } from '@renderer/utils'
|
import { uuid } from '@renderer/utils'
|
||||||
import { Switch } from 'antd'
|
|
||||||
import { FC, useState } from 'react'
|
import { FC, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
|
||||||
import AddAssistantPopup from '../../components/Popups/AddAssistantPopup'
|
|
||||||
import Assistants from './Assistants'
|
import Assistants from './Assistants'
|
||||||
import Chat from './Chat'
|
import Chat from './Chat'
|
||||||
import SelectModelButton from './components/SelectModelButton'
|
import Navbar from './Navbar'
|
||||||
|
|
||||||
let _activeAssistant: Assistant
|
let _activeAssistant: Assistant
|
||||||
let _showTopics = false
|
|
||||||
|
|
||||||
const HomePage: FC = () => {
|
const HomePage: FC = () => {
|
||||||
const { assistants, addAssistant } = useAssistants()
|
const { assistants, addAssistant } = useAssistants()
|
||||||
const [activeAssistant, setActiveAssistant] = useState(_activeAssistant || assistants[0])
|
const [activeAssistant, setActiveAssistant] = useState(_activeAssistant || assistants[0])
|
||||||
const { showAssistants } = useShowAssistants()
|
const { showAssistants } = useShowAssistants()
|
||||||
const { defaultAssistant } = useDefaultAssistant()
|
const { defaultAssistant } = useDefaultAssistant()
|
||||||
const { theme, toggleTheme } = useTheme()
|
|
||||||
const [showTopics, setShowTopics] = useState(_showTopics)
|
|
||||||
const { t } = useTranslation()
|
|
||||||
|
|
||||||
const { activeTopic, setActiveTopic } = useActiveTopic(activeAssistant)
|
const { activeTopic, setActiveTopic } = useActiveTopic(activeAssistant)
|
||||||
const { addTopic } = useAssistant(activeAssistant.id)
|
|
||||||
|
|
||||||
_activeAssistant = activeAssistant
|
_activeAssistant = activeAssistant
|
||||||
_showTopics = showTopics
|
|
||||||
|
|
||||||
const onCreateDefaultAssistant = () => {
|
const onCreateDefaultAssistant = () => {
|
||||||
const assistant = { ...defaultAssistant, id: uuid() }
|
const assistant = { ...defaultAssistant, id: uuid() }
|
||||||
@ -43,59 +28,18 @@ const HomePage: FC = () => {
|
|||||||
setActiveAssistant(assistant)
|
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) => {
|
const onSetActiveTopic = (topic: Topic) => {
|
||||||
setActiveTopic(topic)
|
setActiveTopic(topic)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<Navbar>
|
<Navbar activeAssistant={activeAssistant} setActiveAssistant={setActiveAssistant} />
|
||||||
{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>
|
|
||||||
<ContentContainer>
|
<ContentContainer>
|
||||||
{showAssistants && (
|
{showAssistants && (
|
||||||
<Assistants
|
<Assistants
|
||||||
activeAssistant={activeAssistant}
|
activeAssistant={activeAssistant}
|
||||||
setActiveAssistant={setActiveAssistant}
|
setActiveAssistant={setActiveAssistant}
|
||||||
activeTopic={activeTopic}
|
|
||||||
setActiveTopic={setActiveTopic}
|
|
||||||
showTopics={showTopics}
|
|
||||||
setShowTopics={setShowTopics}
|
|
||||||
onCreateAssistant={onCreateDefaultAssistant}
|
onCreateAssistant={onCreateDefaultAssistant}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@ -118,67 +62,4 @@ const ContentContainer = styled.div`
|
|||||||
background-color: var(--color-background);
|
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
|
export default HomePage
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import {
|
|||||||
ControlOutlined,
|
ControlOutlined,
|
||||||
FullscreenExitOutlined,
|
FullscreenExitOutlined,
|
||||||
FullscreenOutlined,
|
FullscreenOutlined,
|
||||||
|
HistoryOutlined,
|
||||||
PauseCircleOutlined,
|
PauseCircleOutlined,
|
||||||
PlusCircleOutlined,
|
PlusCircleOutlined,
|
||||||
QuestionCircleOutlined
|
QuestionCircleOutlined
|
||||||
@ -30,13 +31,11 @@ import SendMessageButton from './SendMessageButton'
|
|||||||
interface Props {
|
interface Props {
|
||||||
assistant: Assistant
|
assistant: Assistant
|
||||||
setActiveTopic: (topic: Topic) => void
|
setActiveTopic: (topic: Topic) => void
|
||||||
showSetting: boolean
|
|
||||||
setShowSetting: (show: boolean) => void
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let _text = ''
|
let _text = ''
|
||||||
|
|
||||||
const Inputbar: FC<Props> = ({ assistant, setActiveTopic, showSetting, setShowSetting }) => {
|
const Inputbar: FC<Props> = ({ assistant, setActiveTopic }) => {
|
||||||
const [text, setText] = useState(_text)
|
const [text, setText] = useState(_text)
|
||||||
const [inputFocus, setInputFocus] = useState(false)
|
const [inputFocus, setInputFocus] = useState(false)
|
||||||
const { addTopic } = useAssistant(assistant.id)
|
const { addTopic } = useAssistant(assistant.id)
|
||||||
@ -221,8 +220,13 @@ const Inputbar: FC<Props> = ({ assistant, setActiveTopic, showSetting, setShowSe
|
|||||||
</ToolbarButton>
|
</ToolbarButton>
|
||||||
</Popconfirm>
|
</Popconfirm>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip placement="top" title={t('chat.input.settings')} arrow className={showSetting ? 'active' : ''}>
|
<Tooltip placement="top" title={t('chat.input.topics')} arrow>
|
||||||
<ToolbarButton type="text" onClick={() => setShowSetting(!showSetting)}>
|
<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 />
|
<ControlOutlined />
|
||||||
</ToolbarButton>
|
</ToolbarButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
@ -236,7 +240,6 @@ const Inputbar: FC<Props> = ({ assistant, setActiveTopic, showSetting, setShowSe
|
|||||||
<TextCount>
|
<TextCount>
|
||||||
<Tooltip title={t('chat.input.context_count.tip') + ' | ' + t('chat.input.estimated_tokens.tip')}>
|
<Tooltip title={t('chat.input.context_count.tip') + ' | ' + t('chat.input.estimated_tokens.tip')}>
|
||||||
<StyledTag>
|
<StyledTag>
|
||||||
<i className="iconfont icon-history" style={{ marginRight: '3px' }} />
|
|
||||||
{assistant?.settings?.contextCount ?? DEFAULT_CONEXTCOUNT}
|
{assistant?.settings?.contextCount ?? DEFAULT_CONEXTCOUNT}
|
||||||
<Divider type="vertical" style={{ marginTop: 2, marginLeft: 5, marginRight: 5 }} />↑{inputTokenCount}
|
<Divider type="vertical" style={{ marginTop: 2, marginLeft: 5, marginRight: 5 }} />↑{inputTokenCount}
|
||||||
<span style={{ margin: '0 2px' }}>/</span>
|
<span style={{ margin: '0 2px' }}>/</span>
|
||||||
@ -342,11 +345,12 @@ const TextCount = styled.div`
|
|||||||
|
|
||||||
const StyledTag = styled(Tag)`
|
const StyledTag = styled(Tag)`
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border-radius: 6px;
|
border-radius: 20px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 2px 8px;
|
padding: 2px 8px;
|
||||||
border-width: 0.5;
|
border-width: 0.5;
|
||||||
|
margin: 0;
|
||||||
`
|
`
|
||||||
|
|
||||||
export default Inputbar
|
export default Inputbar
|
||||||
|
|||||||
111
src/renderer/src/pages/home/Navbar.tsx
Normal file
111
src/renderer/src/pages/home/Navbar.tsx
Normal 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
|
||||||
96
src/renderer/src/pages/home/RightSidebar.tsx
Normal file
96
src/renderer/src/pages/home/RightSidebar.tsx
Normal 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
|
||||||
@ -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 { HStack } from '@renderer/components/Layout'
|
||||||
import { DEFAULT_CONEXTCOUNT, DEFAULT_MAX_TOKENS, DEFAULT_TEMPERATURE } from '@renderer/config/constant'
|
import { DEFAULT_CONEXTCOUNT, DEFAULT_MAX_TOKENS, DEFAULT_TEMPERATURE } from '@renderer/config/constant'
|
||||||
import { useAssistant } from '@renderer/hooks/useAssistant'
|
import { useAssistant } from '@renderer/hooks/useAssistant'
|
||||||
@ -19,7 +19,6 @@ import styled from 'styled-components'
|
|||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
assistant: Assistant
|
assistant: Assistant
|
||||||
onClose: () => void
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const SettingsTab: FC<Props> = (props) => {
|
const SettingsTab: FC<Props> = (props) => {
|
||||||
@ -88,10 +87,6 @@ const SettingsTab: FC<Props> = (props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<SettingsHeader>
|
|
||||||
{t('settings.title')}
|
|
||||||
<CloseIcon onClick={props.onClose} />
|
|
||||||
</SettingsHeader>
|
|
||||||
<SettingSubtitle>
|
<SettingSubtitle>
|
||||||
{t('settings.messages.model.title')}{' '}
|
{t('settings.messages.model.title')}{' '}
|
||||||
<Tooltip title={t('chat.settings.reset')}>
|
<Tooltip title={t('chat.settings.reset')}>
|
||||||
@ -264,21 +259,4 @@ const SettingRowTitleSmall = styled(SettingRowTitle)`
|
|||||||
font-size: 13px;
|
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
|
export default SettingsTab
|
||||||
|
|||||||
@ -125,10 +125,15 @@ const Container = styled.div`
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding-top: 10px;
|
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`
|
const TopicListItem = styled.div`
|
||||||
padding: 5px 10px;
|
padding: 7px 10px;
|
||||||
margin: 0 10px;
|
margin: 0 10px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
|||||||
@ -9,6 +9,7 @@ export enum ThemeMode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface SettingsState {
|
export interface SettingsState {
|
||||||
|
showRightSidebar: boolean
|
||||||
showAssistants: boolean
|
showAssistants: boolean
|
||||||
sendMessageShortcut: SendMessageShortcut
|
sendMessageShortcut: SendMessageShortcut
|
||||||
language: string
|
language: string
|
||||||
@ -23,6 +24,7 @@ export interface SettingsState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const initialState: SettingsState = {
|
const initialState: SettingsState = {
|
||||||
|
showRightSidebar: true,
|
||||||
showAssistants: true,
|
showAssistants: true,
|
||||||
sendMessageShortcut: 'Enter',
|
sendMessageShortcut: 'Enter',
|
||||||
language: navigator.language,
|
language: navigator.language,
|
||||||
@ -32,7 +34,7 @@ const initialState: SettingsState = {
|
|||||||
messageFont: 'system',
|
messageFont: 'system',
|
||||||
showInputEstimatedTokens: false,
|
showInputEstimatedTokens: false,
|
||||||
theme: ThemeMode.light,
|
theme: ThemeMode.light,
|
||||||
windowStyle: 'opaque',
|
windowStyle: 'transparent',
|
||||||
fontSize: 14
|
fontSize: 14
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,6 +42,12 @@ const settingsSlice = createSlice({
|
|||||||
name: 'settings',
|
name: 'settings',
|
||||||
initialState,
|
initialState,
|
||||||
reducers: {
|
reducers: {
|
||||||
|
toggleRightSidebar: (state) => {
|
||||||
|
state.showRightSidebar = !state.showRightSidebar
|
||||||
|
},
|
||||||
|
setShowRightSidebar: (state, action: PayloadAction<boolean>) => {
|
||||||
|
state.showRightSidebar = action.payload
|
||||||
|
},
|
||||||
toggleShowAssistants: (state) => {
|
toggleShowAssistants: (state) => {
|
||||||
state.showAssistants = !state.showAssistants
|
state.showAssistants = !state.showAssistants
|
||||||
},
|
},
|
||||||
@ -78,6 +86,8 @@ const settingsSlice = createSlice({
|
|||||||
})
|
})
|
||||||
|
|
||||||
export const {
|
export const {
|
||||||
|
setShowRightSidebar,
|
||||||
|
toggleRightSidebar,
|
||||||
toggleShowAssistants,
|
toggleShowAssistants,
|
||||||
setSendMessageShortcut,
|
setSendMessageShortcut,
|
||||||
setLanguage,
|
setLanguage,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user