interstellar_ai/app/components/ConversationFrontend.tsx
2024-10-01 15:46:24 +02:00

109 lines
3.5 KiB
TypeScript

import React, { ForwardedRef, useState, useEffect, useRef } from 'react';
type Message = {
role: string
content: string
}
interface ConversationProps {
messages: Message[];
onStopClick: () => void;
onResendClick: () => void;
onEditClick: () => void;
onCopyClick: () => void;
isClicked: boolean
}
const ConversationFrontend = React.forwardRef<HTMLDivElement, ConversationProps>(
({ messages, onStopClick, onResendClick, onEditClick, onCopyClick, isClicked }, ref: ForwardedRef<HTMLDivElement>) => {
const [isScrolling, setIsScrolling] = useState(true);
const messagesEndRef = useRef<HTMLDivElement | null>(null);
useEffect(() => {
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]);
// Scroll to bottom when new messages arrive
useEffect(() => {
if (isScrolling) {
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
}
}, [messages, isScrolling]);
return (
<div className="output" ref={ref}>
<div className="conversation resize" id="conversation">
{messages.map((message, index) => {
if (index >= 1) {
return (
<div
key={index}
className={message.role === "user" ? 'user-message' : 'ai-message'}
>
<p> {message.content}</p>
</div>
);
}
})}
<div className="button-container">
<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>
</div>
<div className={"endOfMessages"} ref={messagesEndRef} style={{height:"10px"}}/>
</div>
<button id="scrollToBottom" disabled={isScrolling?true:false} style={{visibility: isScrolling?"hidden":"visible"}} onClick={()=> setIsScrolling(true)}>Down</button>
</div>
);
}
);
export default ConversationFrontend;