|
|
|
@ -1,15 +1,14 @@
|
|
|
|
|
import { forwardRef, useState } from 'react';
|
|
|
|
|
import Avatar from '../components/Avatar';
|
|
|
|
|
import CoppyButton from '../components/CopyButton';
|
|
|
|
|
import remarkGfm from 'remark-gfm';
|
|
|
|
|
import { FEEDBACK, MESSAGE_TYPE } from './conversationModels';
|
|
|
|
|
import classes from './ConversationBubble.module.css';
|
|
|
|
|
import Alert from './../assets/alert.svg';
|
|
|
|
|
import Like from './../assets/like.svg?react';
|
|
|
|
|
import Dislike from './../assets/dislike.svg?react';
|
|
|
|
|
import Copy from './../assets/copy.svg?react';
|
|
|
|
|
import CheckMark from './../assets/checkmark.svg?react';
|
|
|
|
|
|
|
|
|
|
import ReactMarkdown from 'react-markdown';
|
|
|
|
|
import copy from 'copy-to-clipboard';
|
|
|
|
|
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
|
|
|
|
import { vscDarkPlus } from 'react-syntax-highlighter/dist/cjs/styles/prism';
|
|
|
|
|
import DocsGPT3 from '../assets/cute_docsgpt3.svg';
|
|
|
|
@ -30,17 +29,7 @@ const ConversationBubble = forwardRef<
|
|
|
|
|
ref,
|
|
|
|
|
) {
|
|
|
|
|
const [openSource, setOpenSource] = useState<number | null>(null);
|
|
|
|
|
const [copied, setCopied] = useState(false);
|
|
|
|
|
|
|
|
|
|
const handleCopyClick = (text: string) => {
|
|
|
|
|
copy(text);
|
|
|
|
|
setCopied(true);
|
|
|
|
|
// Reset copied to false after a few seconds
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
setCopied(false);
|
|
|
|
|
}, 3000);
|
|
|
|
|
};
|
|
|
|
|
const [isCopyHovered, setIsCopyHovered] = useState(false);
|
|
|
|
|
const [isLikeHovered, setIsLikeHovered] = useState(false);
|
|
|
|
|
const [isDislikeHovered, setIsDislikeHovered] = useState(false);
|
|
|
|
|
const [isLikeClicked, setIsLikeClicked] = useState(false);
|
|
|
|
@ -52,7 +41,7 @@ const ConversationBubble = forwardRef<
|
|
|
|
|
bubble = (
|
|
|
|
|
<div ref={ref} className={`flex flex-row-reverse self-end ${className}`}>
|
|
|
|
|
<Avatar className="mt-2 text-2xl" avatar="🧑💻"></Avatar>
|
|
|
|
|
<div className="mr-2 ml-10 flex items-center rounded-3xl bg-purple-30 p-3.5 text-white">
|
|
|
|
|
<div className="ml-10 mr-2 flex items-center rounded-3xl bg-purple-30 p-3.5 text-white">
|
|
|
|
|
<ReactMarkdown className="whitespace-pre-wrap break-normal leading-normal">
|
|
|
|
|
{message}
|
|
|
|
|
</ReactMarkdown>
|
|
|
|
@ -94,19 +83,28 @@ const ConversationBubble = forwardRef<
|
|
|
|
|
code({ node, inline, className, children, ...props }) {
|
|
|
|
|
const match = /language-(\w+)/.exec(className || '');
|
|
|
|
|
|
|
|
|
|
return !inline && match ? (
|
|
|
|
|
<SyntaxHighlighter
|
|
|
|
|
PreTag="div"
|
|
|
|
|
language={match[1]}
|
|
|
|
|
{...props}
|
|
|
|
|
style={vscDarkPlus}
|
|
|
|
|
>
|
|
|
|
|
{String(children).replace(/\n$/, '')}
|
|
|
|
|
</SyntaxHighlighter>
|
|
|
|
|
) : (
|
|
|
|
|
<code className={className ? className : ''} {...props}>
|
|
|
|
|
{children}
|
|
|
|
|
</code>
|
|
|
|
|
return (
|
|
|
|
|
<div className="relative">
|
|
|
|
|
{!inline && match ? (
|
|
|
|
|
<SyntaxHighlighter
|
|
|
|
|
PreTag="div"
|
|
|
|
|
language={match[1]}
|
|
|
|
|
{...props}
|
|
|
|
|
style={vscDarkPlus}
|
|
|
|
|
>
|
|
|
|
|
{String(children).replace(/\n$/, '')}
|
|
|
|
|
</SyntaxHighlighter>
|
|
|
|
|
) : (
|
|
|
|
|
<code className={className ? className : ''} {...props}>
|
|
|
|
|
{children}
|
|
|
|
|
</code>
|
|
|
|
|
)}
|
|
|
|
|
<div className="absolute right-3 top-3">
|
|
|
|
|
<CoppyButton
|
|
|
|
|
text={String(children).replace(/\n$/, '')}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
ul({ children }) {
|
|
|
|
@ -172,7 +170,7 @@ const ConversationBubble = forwardRef<
|
|
|
|
|
{sources?.map((source, index) => (
|
|
|
|
|
<div
|
|
|
|
|
key={index}
|
|
|
|
|
className={`max-w-xs sm:max-w-sm md:max-w-md cursor-pointer rounded-[28px] py-1 px-4 ${
|
|
|
|
|
className={`max-w-xs cursor-pointer rounded-[28px] px-4 py-1 sm:max-w-sm md:max-w-md ${
|
|
|
|
|
openSource === index
|
|
|
|
|
? 'bg-[#007DFF]'
|
|
|
|
|
: 'bg-[#D7EBFD] hover:bg-[#BFE1FF]'
|
|
|
|
@ -203,31 +201,7 @@ const ConversationBubble = forwardRef<
|
|
|
|
|
${type !== 'ERROR' ? 'group-hover:lg:visible' : ''}`}
|
|
|
|
|
>
|
|
|
|
|
<div className="absolute left-2 top-4">
|
|
|
|
|
<div
|
|
|
|
|
className={`flex items-center justify-center rounded-full p-2
|
|
|
|
|
${
|
|
|
|
|
isCopyHovered
|
|
|
|
|
? 'bg-[#EEEEEE] dark:bg-purple-taupe'
|
|
|
|
|
: 'bg-[#ffffff] dark:bg-transparent'
|
|
|
|
|
}`}
|
|
|
|
|
>
|
|
|
|
|
{copied ? (
|
|
|
|
|
<CheckMark
|
|
|
|
|
className="cursor-pointer stroke-green-2000"
|
|
|
|
|
onMouseEnter={() => setIsCopyHovered(true)}
|
|
|
|
|
onMouseLeave={() => setIsCopyHovered(false)}
|
|
|
|
|
/>
|
|
|
|
|
) : (
|
|
|
|
|
<Copy
|
|
|
|
|
className={`cursor-pointer fill-none`}
|
|
|
|
|
onClick={() => {
|
|
|
|
|
handleCopyClick(message);
|
|
|
|
|
}}
|
|
|
|
|
onMouseEnter={() => setIsCopyHovered(true)}
|
|
|
|
|
onMouseLeave={() => setIsCopyHovered(false)}
|
|
|
|
|
></Copy>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
<CoppyButton text={message} />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|