feat: edit user message

This commit is contained in:
kangfenmao 2024-07-09 16:11:45 +08:00
parent 232892b71c
commit 0bce853157
5 changed files with 38 additions and 29 deletions

View File

@ -1,4 +1,3 @@
import 'highlight.js/styles/github-dark.css'
import React from 'react' import React from 'react'
import ReactDOM from 'react-dom/client' import ReactDOM from 'react-dom/client'
import App from './App' import App from './App'

View File

@ -8,7 +8,7 @@ import { Button, Popconfirm, Tooltip } from 'antd'
import { useShowRightSidebar } from '@renderer/hooks/useStore' import { useShowRightSidebar } from '@renderer/hooks/useStore'
import { useAssistant } from '@renderer/hooks/useAssistant' import { useAssistant } from '@renderer/hooks/useAssistant'
import { ClearOutlined, HistoryOutlined, PlusCircleOutlined } from '@ant-design/icons' import { ClearOutlined, HistoryOutlined, PlusCircleOutlined } from '@ant-design/icons'
import { TextAreaRef } from 'antd/es/input/TextArea' import TextArea, { TextAreaRef } from 'antd/es/input/TextArea'
import { isEmpty } from 'lodash' import { isEmpty } from 'lodash'
import SendMessageSetting from './SendMessageSetting' import SendMessageSetting from './SendMessageSetting'
import { useSettings } from '@renderer/hooks/useSettings' import { useSettings } from '@renderer/hooks/useSettings'
@ -24,7 +24,7 @@ const Inputbar: FC<Props> = ({ assistant, setActiveTopic }) => {
const { setShowRightSidebar } = useShowRightSidebar() const { setShowRightSidebar } = useShowRightSidebar()
const { addTopic } = useAssistant(assistant.id) const { addTopic } = useAssistant(assistant.id)
const { sendMessageShortcut } = useSettings() const { sendMessageShortcut } = useSettings()
const inputRef = useRef<TextAreaRef>() const inputRef = useRef<TextAreaRef>(null)
const sendMessage = () => { const sendMessage = () => {
if (isEmpty(text.trim())) { if (isEmpty(text.trim())) {
@ -85,6 +85,16 @@ const Inputbar: FC<Props> = ({ assistant, setActiveTopic }) => {
return () => document.removeEventListener('keydown', onKeydown) return () => document.removeEventListener('keydown', onKeydown)
}, [addNewTopic]) }, [addNewTopic])
useEffect(() => {
const unsubscribes = [
EventEmitter.on(EVENT_NAMES.EDIT_MESSAGE, (message: Message) => {
setText(message.content)
inputRef.current?.focus()
})
]
return () => unsubscribes.forEach((unsub) => unsub())
}, [])
useEffect(() => { useEffect(() => {
inputRef.current?.focus() inputRef.current?.focus()
}, [assistant]) }, [assistant])
@ -133,6 +143,9 @@ const Inputbar: FC<Props> = ({ assistant, setActiveTopic }) => {
placeholder="Type your message here..." placeholder="Type your message here..."
autoFocus autoFocus
contextMenu="true" contextMenu="true"
variant="borderless"
styles={{ textarea: { resize: 'none', paddingLeft: 0 } }}
allowClear
ref={inputRef} ref={inputRef}
/> />
</Container> </Container>
@ -148,16 +161,11 @@ const Container = styled.div`
padding: 5px 15px; padding: 5px 15px;
` `
const Textarea = styled.textarea` const Textarea = styled(TextArea)`
padding: 0;
border-radius: 0;
display: flex; display: flex;
flex: 1; flex: 1;
border: none;
outline: none;
resize: none;
font-size: 13px;
line-height: 18px;
color: var(--color-text);
background-color: transparent;
` `
const Toolbar = styled.div` const Toolbar = styled.div`

View File

@ -1,12 +1,13 @@
import { Message } from '@renderer/types' import { Message } from '@renderer/types'
import { Avatar } from 'antd' import { Avatar, Tooltip } from 'antd'
import { FC } from 'react' import { FC } from 'react'
import styled from 'styled-components' import styled from 'styled-components'
import Logo from '@renderer/assets/images/logo.png' import Logo from '@renderer/assets/images/logo.png'
import useAvatar from '@renderer/hooks/useAvatar' import useAvatar from '@renderer/hooks/useAvatar'
import { CopyOutlined, DeleteOutlined } from '@ant-design/icons' import { CopyOutlined, DeleteOutlined, EditOutlined } from '@ant-design/icons'
import Markdown from 'react-markdown' import Markdown from 'react-markdown'
import CodeBlock from './CodeBlock' import CodeBlock from './CodeBlock'
import { EVENT_NAMES, EventEmitter } from '@renderer/services/event'
interface Props { interface Props {
message: Message message: Message
@ -33,6 +34,10 @@ const MessageItem: FC<Props> = ({ message, showMenu, onDeleteMessage }) => {
confirmed && onDeleteMessage?.(message) confirmed && onDeleteMessage?.(message)
} }
const onEdit = () => {
EventEmitter.emit(EVENT_NAMES.EDIT_MESSAGE, message)
}
return ( return (
<MessageContainer key={message.id}> <MessageContainer key={message.id}>
<AvatarWrapper>{message.role === 'assistant' ? <Avatar src={Logo} /> : <Avatar src={avatar} />}</AvatarWrapper> <AvatarWrapper>{message.role === 'assistant' ? <Avatar src={Logo} /> : <Avatar src={avatar} />}</AvatarWrapper>
@ -40,11 +45,19 @@ const MessageItem: FC<Props> = ({ message, showMenu, onDeleteMessage }) => {
<Markdown className="markdown" components={{ code: CodeBlock as any }}> <Markdown className="markdown" components={{ code: CodeBlock as any }}>
{message.content} {message.content}
</Markdown> </Markdown>
{/* <Markdown className="markdown" dangerouslySetInnerHTML={{ __html: marked(message.content) }} /> */}
{showMenu && ( {showMenu && (
<MenusBar className="menubar"> <MenusBar className="menubar">
<CopyOutlined onClick={onCopy} /> {message.role === 'user' && (
<DeleteOutlined onClick={onDelete} /> <Tooltip title="Edit" mouseEnterDelay={1}>
<EditOutlined onClick={onEdit} />
</Tooltip>
)}
<Tooltip title="Copy" mouseEnterDelay={1}>
<CopyOutlined onClick={onCopy} />
</Tooltip>
<Tooltip title="Delete" mouseEnterDelay={1}>
<DeleteOutlined onClick={onDelete} />
</Tooltip>
<ModelName>{message.modelId}</ModelName> <ModelName>{message.modelId}</ModelName>
</MenusBar> </MenusBar>
)} )}
@ -64,8 +77,6 @@ const AvatarWrapper = styled.div`
margin-right: 10px; margin-right: 10px;
` `
// const Markdown = styled.div``
const MessageContent = styled.div` const MessageContent = styled.div`
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View File

@ -3,9 +3,6 @@ import { FC, useEffect, useState } from 'react'
import styled from 'styled-components' import styled from 'styled-components'
import Logo from '@renderer/assets/images/logo.png' import Logo from '@renderer/assets/images/logo.png'
import { runAsyncFunction } from '@renderer/utils' import { runAsyncFunction } from '@renderer/utils'
import { marked } from 'marked'
const changeLog = ``
const AboutSettings: FC = () => { const AboutSettings: FC = () => {
const [version, setVersion] = useState('') const [version, setVersion] = useState('')
@ -24,13 +21,6 @@ const AboutSettings: FC = () => {
Cherry Studio <Version>(v{version})</Version> Cherry Studio <Version>(v{version})</Version>
</Title> </Title>
<Description>A powerful AI assistant for producer.</Description> <Description>A powerful AI assistant for producer.</Description>
<div
className="markdown"
style={{ width: '80%' }}
dangerouslySetInnerHTML={{
__html: marked(changeLog)
}}
/>
</Container> </Container>
) )
} }

View File

@ -7,5 +7,6 @@ export const EVENT_NAMES = {
AI_CHAT_COMPLETION: 'AI_CHAT_COMPLETION', AI_CHAT_COMPLETION: 'AI_CHAT_COMPLETION',
AI_AUTO_RENAME: 'AI_AUTO_RENAME', AI_AUTO_RENAME: 'AI_AUTO_RENAME',
CLEAR_MESSAGES: 'CLEAR_MESSAGES', CLEAR_MESSAGES: 'CLEAR_MESSAGES',
ADD_ASSISTANT: 'ADD_ASSISTANT' ADD_ASSISTANT: 'ADD_ASSISTANT',
EDIT_MESSAGE: 'EDIT_MESSAGE'
} }