2024-10-01 15:46:24 +02:00
|
|
|
import React, { ForwardedRef, useState, useEffect, useRef } from 'react';
|
2024-09-18 10:03:36 +02:00
|
|
|
|
2024-09-20 09:17:28 +02:00
|
|
|
type Message = {
|
|
|
|
role: string
|
|
|
|
content: string
|
|
|
|
}
|
|
|
|
|
2024-09-18 10:03:36 +02:00
|
|
|
interface ConversationProps {
|
2024-09-20 09:17:28 +02:00
|
|
|
messages: Message[];
|
2024-10-01 14:29:15 +02:00
|
|
|
onStopClick: () => void;
|
2024-09-18 11:17:34 +02:00
|
|
|
onResendClick: () => void;
|
|
|
|
onEditClick: () => void;
|
|
|
|
onCopyClick: () => void;
|
2024-10-01 09:22:33 +02:00
|
|
|
isClicked: boolean
|
2024-09-18 10:03:36 +02:00
|
|
|
}
|
|
|
|
|
2024-09-18 14:52:04 +02:00
|
|
|
const ConversationFrontend = React.forwardRef<HTMLDivElement, ConversationProps>(
|
2024-10-01 15:46:24 +02:00
|
|
|
({ messages, onStopClick, onResendClick, onEditClick, onCopyClick, isClicked }, ref: ForwardedRef<HTMLDivElement>) => {
|
|
|
|
const [isScrolling, setIsScrolling] = useState(true);
|
|
|
|
const messagesEndRef = useRef<HTMLDivElement | null>(null);
|
2024-10-01 11:37:53 +02:00
|
|
|
|
2024-10-01 14:29:15 +02:00
|
|
|
useEffect(() => {
|
2024-10-01 15:46:24 +02:00
|
|
|
const observer = new IntersectionObserver(
|
|
|
|
(entries) => {
|
|
|
|
if (entries[0].isIntersecting) {
|
|
|
|
console.log('End of messages reached');
|
|
|
|
setIsScrolling(true);
|
|
|
|
} else {
|
|
|
|
console.log('End of messages not reached');
|
|
|
|
setIsScrolling(false);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
root: document.querySelector('.output'),
|
|
|
|
threshold: 1.0, // Ensure the whole element is visible
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
const endOfMessages = messagesEndRef.current;
|
|
|
|
if (endOfMessages) {
|
|
|
|
observer.observe(endOfMessages);
|
|
|
|
}
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
if (endOfMessages) {
|
|
|
|
observer.unobserve(endOfMessages);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}, [messages]);
|
2024-10-01 14:29:15 +02:00
|
|
|
|
2024-10-01 15:46:24 +02:00
|
|
|
// Scroll to bottom when new messages arrive
|
2024-10-01 11:57:38 +02:00
|
|
|
useEffect(() => {
|
2024-10-01 15:46:24 +02:00
|
|
|
if (isScrolling) {
|
|
|
|
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
|
|
|
|
}
|
|
|
|
}, [messages, isScrolling]);
|
2024-10-01 10:39:21 +02:00
|
|
|
|
2024-09-18 11:17:34 +02:00
|
|
|
return (
|
2024-10-01 10:39:21 +02:00
|
|
|
<div className="output" ref={ref}>
|
|
|
|
<div className="conversation resize" id="conversation">
|
2024-09-18 11:17:34 +02:00
|
|
|
{messages.map((message, index) => {
|
2024-10-01 11:57:38 +02:00
|
|
|
if (index >= 1) {
|
2024-09-27 16:51:44 +02:00
|
|
|
|
|
|
|
return (
|
|
|
|
<div
|
|
|
|
key={index}
|
2024-10-01 10:39:21 +02:00
|
|
|
className={message.role === "user" ? 'user-message' : 'ai-message'}
|
2024-10-01 11:57:38 +02:00
|
|
|
>
|
2024-09-27 16:51:44 +02:00
|
|
|
<p> {message.content}</p>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
2024-09-18 11:17:34 +02:00
|
|
|
})}
|
2024-10-01 10:39:21 +02:00
|
|
|
|
2024-09-18 11:17:34 +02:00
|
|
|
<div className="button-container">
|
2024-10-01 14:29:15 +02:00
|
|
|
<div className="tooltip">
|
|
|
|
<button type="button" onClick={onStopClick}>
|
|
|
|
<img src="/img/resend.svg" alt="stop" />
|
|
|
|
</button>
|
|
|
|
<span className="tooltiptext">Stop</span>
|
|
|
|
</div>
|
|
|
|
<div className="tooltip">
|
|
|
|
<button type="button" onClick={onResendClick}>
|
|
|
|
<img src="/img/resend.svg" alt="resend" />
|
|
|
|
</button>
|
|
|
|
<span className="tooltiptext">Resend</span>
|
|
|
|
</div>
|
|
|
|
<div className="tooltip">
|
|
|
|
<button type="button" onClick={onEditClick}>
|
|
|
|
<img src="/img/edit.svg" alt="edit" />
|
|
|
|
</button>
|
|
|
|
<span className="tooltiptext">Edit</span>
|
|
|
|
</div>
|
|
|
|
<div className="tooltip">
|
|
|
|
<button type="button" onClick={onCopyClick}>
|
|
|
|
<img src="/img/copy.svg" alt="copy" />
|
|
|
|
</button>
|
|
|
|
<span className="tooltiptext">{isClicked?"Copied!": "Copy" }</span>
|
|
|
|
</div>
|
2024-09-18 11:17:34 +02:00
|
|
|
</div>
|
2024-10-01 16:54:56 +02:00
|
|
|
<div className={"endOfMessages"} ref={messagesEndRef} style={{ height: "3px"}}/>
|
2024-10-01 11:57:38 +02:00
|
|
|
</div>
|
2024-10-01 15:46:24 +02:00
|
|
|
<button id="scrollToBottom" disabled={isScrolling?true:false} style={{visibility: isScrolling?"hidden":"visible"}} onClick={()=> setIsScrolling(true)}>Down</button>
|
2024-09-18 10:03:36 +02:00
|
|
|
</div>
|
2024-09-18 11:17:34 +02:00
|
|
|
);
|
2024-10-01 15:46:24 +02:00
|
|
|
}
|
2024-09-18 11:17:34 +02:00
|
|
|
);
|
2024-09-18 10:03:36 +02:00
|
|
|
|
2024-09-18 14:52:04 +02:00
|
|
|
export default ConversationFrontend;
|