mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-27 04:31:27 +08:00
feat(chat): add session messages view and active state tracking
Implement agent session messages display component and track active topic/session state Add AgentSessionMessages component and integrate with chat view Update topic and session selection to set active state in store
This commit is contained in:
parent
64e3de9ada
commit
5ddf9683b4
@ -6,6 +6,7 @@ import PromptPopup from '@renderer/components/Popups/PromptPopup'
|
||||
import { QuickPanelProvider } from '@renderer/components/QuickPanel'
|
||||
import { useAssistant } from '@renderer/hooks/useAssistant'
|
||||
import { useChatContext } from '@renderer/hooks/useChatContext'
|
||||
import { useRuntime } from '@renderer/hooks/useRuntime'
|
||||
import { useNavbarPosition, useSettings } from '@renderer/hooks/useSettings'
|
||||
import { useShortcut } from '@renderer/hooks/useShortcuts'
|
||||
import { useShowAssistants, useShowTopics } from '@renderer/hooks/useStore'
|
||||
@ -23,6 +24,7 @@ import styled from 'styled-components'
|
||||
|
||||
import ChatNavbar from './ChatNavbar'
|
||||
import Inputbar from './Inputbar/Inputbar'
|
||||
import AgentSessionMessages from './Messages/AgentSessionMessages'
|
||||
import ChatNavigation from './Messages/ChatNavigation'
|
||||
import Messages from './Messages/Messages'
|
||||
import Tabs from './Tabs'
|
||||
@ -44,6 +46,8 @@ const Chat: FC<Props> = (props) => {
|
||||
const { isMultiSelectMode } = useChatContext(props.activeTopic)
|
||||
const { isTopNavbar } = useNavbarPosition()
|
||||
const chatMaxWidth = useChatMaxWidth()
|
||||
const { chat } = useRuntime()
|
||||
const { activeTopicOrSession, activeAgentId, activeSessionId } = chat
|
||||
|
||||
const mainRef = React.useRef<HTMLDivElement>(null)
|
||||
const contentSearchRef = React.useRef<ContentSearchRef>(null)
|
||||
@ -136,6 +140,17 @@ const Chat: FC<Props> = (props) => {
|
||||
? 'calc(100vh - var(--navbar-height) - var(--navbar-height) - 12px)'
|
||||
: 'calc(100vh - var(--navbar-height))'
|
||||
|
||||
const SessionMessages = () => {
|
||||
if (activeAgentId === null) {
|
||||
return <div> Active Agent ID is invalid.</div>
|
||||
}
|
||||
const sessionId = activeSessionId[activeAgentId]
|
||||
if (!sessionId) {
|
||||
return <div> Active Session ID is invalid.</div>
|
||||
}
|
||||
return <AgentSessionMessages agentId={activeAgentId} sessionId={sessionId} />
|
||||
}
|
||||
|
||||
return (
|
||||
<Container id="chat" className={classNames([messageStyle, { 'multi-select-mode': isMultiSelectMode }])}>
|
||||
{isTopNavbar && (
|
||||
@ -156,23 +171,28 @@ const Chat: FC<Props> = (props) => {
|
||||
justify="space-between"
|
||||
style={{ maxWidth: chatMaxWidth, height: mainHeight }}>
|
||||
<QuickPanelProvider>
|
||||
<Messages
|
||||
key={props.activeTopic.id}
|
||||
assistant={assistant}
|
||||
topic={props.activeTopic}
|
||||
setActiveTopic={props.setActiveTopic}
|
||||
onComponentUpdate={messagesComponentUpdateHandler}
|
||||
onFirstUpdate={messagesComponentFirstUpdateHandler}
|
||||
/>
|
||||
<ContentSearch
|
||||
ref={contentSearchRef}
|
||||
searchTarget={mainRef as React.RefObject<HTMLElement>}
|
||||
filter={contentSearchFilter}
|
||||
includeUser={filterIncludeUser}
|
||||
onIncludeUserChange={userOutlinedItemClickHandler}
|
||||
/>
|
||||
{messageNavigation === 'buttons' && <ChatNavigation containerId="messages" />}
|
||||
<Inputbar assistant={assistant} setActiveTopic={props.setActiveTopic} topic={props.activeTopic} />
|
||||
{activeTopicOrSession === 'topic' && (
|
||||
<>
|
||||
<Messages
|
||||
key={props.activeTopic.id}
|
||||
assistant={assistant}
|
||||
topic={props.activeTopic}
|
||||
setActiveTopic={props.setActiveTopic}
|
||||
onComponentUpdate={messagesComponentUpdateHandler}
|
||||
onFirstUpdate={messagesComponentFirstUpdateHandler}
|
||||
/>
|
||||
<ContentSearch
|
||||
ref={contentSearchRef}
|
||||
searchTarget={mainRef as React.RefObject<HTMLElement>}
|
||||
filter={contentSearchFilter}
|
||||
includeUser={filterIncludeUser}
|
||||
onIncludeUserChange={userOutlinedItemClickHandler}
|
||||
/>
|
||||
{messageNavigation === 'buttons' && <ChatNavigation containerId="messages" />}
|
||||
<Inputbar assistant={assistant} setActiveTopic={props.setActiveTopic} topic={props.activeTopic} />
|
||||
</>
|
||||
)}
|
||||
{activeTopicOrSession === 'session' && <SessionMessages />}
|
||||
{isMultiSelectMode && <MultiSelectActionPopup topic={props.activeTopic} />}
|
||||
</QuickPanelProvider>
|
||||
</Main>
|
||||
|
||||
@ -5,6 +5,7 @@ import { useActiveTopic } from '@renderer/hooks/useTopic'
|
||||
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
|
||||
import NavigationService from '@renderer/services/NavigationService'
|
||||
import { newMessagesActions } from '@renderer/store/newMessage'
|
||||
import { setActiveTopicOrSessionAction } from '@renderer/store/runtime'
|
||||
import { Assistant, Topic } from '@renderer/types'
|
||||
import { MIN_WINDOW_HEIGHT, MIN_WINDOW_WIDTH, SECOND_MIN_WINDOW_WIDTH } from '@shared/config/constant'
|
||||
import { AnimatePresence, motion } from 'motion/react'
|
||||
@ -52,6 +53,7 @@ const HomePage: FC = () => {
|
||||
startTransition(() => {
|
||||
_setActiveTopic((prev) => (newTopic?.id === prev.id ? prev : newTopic))
|
||||
dispatch(newMessagesActions.setTopicFulfilled({ topicId: newTopic.id, fulfilled: false }))
|
||||
dispatch(setActiveTopicOrSessionAction('topic'))
|
||||
})
|
||||
},
|
||||
[_setActiveTopic, dispatch]
|
||||
|
||||
@ -0,0 +1,58 @@
|
||||
import ContextMenu from '@renderer/components/ContextMenu'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
import { useSession } from '@renderer/hooks/agents/useSession'
|
||||
import { memo } from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
import NarrowLayout from './NarrowLayout'
|
||||
|
||||
type Props = {
|
||||
agentId: string
|
||||
sessionId: string
|
||||
}
|
||||
|
||||
const AgentSessionMessages: React.FC<Props> = ({ agentId, sessionId }) => {
|
||||
const { messages } = useSession(agentId, sessionId)
|
||||
|
||||
return (
|
||||
<MessagesContainer id="messages" className="messages-container">
|
||||
<NarrowLayout style={{ display: 'flex', flexDirection: 'column-reverse' }}>
|
||||
<ContextMenu>
|
||||
<ScrollContainer>
|
||||
{messages.map((message) => {
|
||||
const content = message.content.content
|
||||
if (typeof content === 'string') {
|
||||
return <div key={message.id}>{content}</div>
|
||||
} else {
|
||||
return 'Not string content'
|
||||
}
|
||||
})}
|
||||
</ScrollContainer>
|
||||
</ContextMenu>
|
||||
</NarrowLayout>
|
||||
</MessagesContainer>
|
||||
)
|
||||
}
|
||||
|
||||
const ScrollContainer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
padding: 10px 10px 20px;
|
||||
.multi-select-mode & {
|
||||
padding-bottom: 60px;
|
||||
}
|
||||
`
|
||||
|
||||
interface ContainerProps {
|
||||
$right?: boolean
|
||||
}
|
||||
|
||||
const MessagesContainer = styled(Scrollbar)<ContainerProps>`
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
overflow-x: hidden;
|
||||
z-index: 1;
|
||||
position: relative;
|
||||
`
|
||||
|
||||
export default memo(AgentSessionMessages)
|
||||
@ -2,7 +2,7 @@ import { Button, Spinner } from '@heroui/react'
|
||||
import { SessionModal } from '@renderer/components/Popups/agent/SessionModal'
|
||||
import { useSessions } from '@renderer/hooks/agents/useSessions'
|
||||
import { useAppDispatch } from '@renderer/store'
|
||||
import { setActiveSessionIdAction } from '@renderer/store/runtime'
|
||||
import { setActiveSessionIdAction, setActiveTopicOrSessionAction } from '@renderer/store/runtime'
|
||||
import { Plus } from 'lucide-react'
|
||||
import { memo, useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -23,6 +23,7 @@ const Sessions: React.FC<SessionsProps> = ({ agentId }) => {
|
||||
const setActiveSessionId = useCallback(
|
||||
(agentId: string, sessionId: string | null) => {
|
||||
dispatch(setActiveSessionIdAction({ agentId, sessionId }))
|
||||
dispatch(setActiveTopicOrSessionAction('session'))
|
||||
},
|
||||
[dispatch]
|
||||
)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user