2023-06-04 04:28:07 +02:00
|
|
|
import HistoricalMessage from "./HistoricalMessage";
|
|
|
|
import PromptReply from "./PromptReply";
|
2023-12-04 22:27:07 +01:00
|
|
|
import { useEffect, useRef, useState } from "react";
|
2023-10-23 22:10:34 +02:00
|
|
|
import { useManageWorkspaceModal } from "../../../Modals/MangeWorkspace";
|
|
|
|
import ManageWorkspace from "../../../Modals/MangeWorkspace";
|
2023-12-04 22:27:07 +01:00
|
|
|
import { ArrowDown } from "@phosphor-icons/react";
|
|
|
|
import debounce from "lodash.debounce";
|
2023-06-04 04:28:07 +02:00
|
|
|
|
2024-02-06 20:24:33 +01:00
|
|
|
export default function ChatHistory({ history = [], workspace, sendCommand }) {
|
2023-10-23 22:10:34 +02:00
|
|
|
const { showing, showModal, hideModal } = useManageWorkspaceModal();
|
2023-12-04 22:27:07 +01:00
|
|
|
const [isAtBottom, setIsAtBottom] = useState(true);
|
|
|
|
const chatHistoryRef = useRef(null);
|
2023-08-22 00:46:31 +02:00
|
|
|
|
|
|
|
useEffect(() => {
|
2023-12-04 22:27:07 +01:00
|
|
|
scrollToBottom();
|
2023-08-22 00:46:31 +02:00
|
|
|
}, [history]);
|
|
|
|
|
2023-12-04 22:27:07 +01:00
|
|
|
const handleScroll = () => {
|
2024-01-18 01:22:06 +01:00
|
|
|
const diff =
|
|
|
|
chatHistoryRef.current.scrollHeight -
|
|
|
|
chatHistoryRef.current.scrollTop -
|
2023-12-04 22:27:07 +01:00
|
|
|
chatHistoryRef.current.clientHeight;
|
2024-01-18 01:22:06 +01:00
|
|
|
// Fuzzy margin for what qualifies as "bottom". Stronger than straight comparison since that may change over time.
|
|
|
|
const isBottom = diff <= 10;
|
2023-12-04 22:27:07 +01:00
|
|
|
setIsAtBottom(isBottom);
|
|
|
|
};
|
|
|
|
|
|
|
|
const debouncedScroll = debounce(handleScroll, 100);
|
|
|
|
useEffect(() => {
|
2024-01-09 22:07:09 +01:00
|
|
|
function watchScrollEvent() {
|
|
|
|
if (!chatHistoryRef.current) return null;
|
|
|
|
const chatHistoryElement = chatHistoryRef.current;
|
|
|
|
if (!chatHistoryElement) return null;
|
|
|
|
chatHistoryElement.addEventListener("scroll", debouncedScroll);
|
|
|
|
}
|
|
|
|
watchScrollEvent();
|
2023-12-04 22:27:07 +01:00
|
|
|
}, []);
|
|
|
|
|
|
|
|
const scrollToBottom = () => {
|
|
|
|
if (chatHistoryRef.current) {
|
|
|
|
chatHistoryRef.current.scrollTo({
|
|
|
|
top: chatHistoryRef.current.scrollHeight,
|
|
|
|
behavior: "smooth",
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-02-06 20:24:33 +01:00
|
|
|
const handleSendSuggestedMessage = (heading, message) => {
|
|
|
|
sendCommand(`${heading} ${message}`, true);
|
|
|
|
};
|
|
|
|
|
2023-06-04 04:28:07 +02:00
|
|
|
if (history.length === 0) {
|
|
|
|
return (
|
2024-02-06 20:24:33 +01:00
|
|
|
<div className="flex flex-col h-full md:mt-0 pb-44 md:pb-40 w-full justify-end items-center">
|
|
|
|
<div className="flex flex-col items-center md:items-start md:max-w-[600px] w-full px-4">
|
2024-01-09 22:07:09 +01:00
|
|
|
<p className="text-white/60 text-lg font-base py-4">
|
2023-10-23 22:10:34 +02:00
|
|
|
Welcome to your new workspace.
|
|
|
|
</p>
|
2024-02-06 20:24:33 +01:00
|
|
|
<p className="w-full items-center text-white/60 text-lg font-base flex flex-col md:flex-row gap-x-1">
|
|
|
|
To get started either{" "}
|
|
|
|
<span
|
|
|
|
className="underline font-medium cursor-pointer"
|
|
|
|
onClick={showModal}
|
|
|
|
>
|
|
|
|
upload a document
|
|
|
|
</span>
|
|
|
|
or <b className="font-medium italic">send a chat.</b>
|
|
|
|
</p>
|
|
|
|
<WorkspaceChatSuggestions
|
|
|
|
suggestions={workspace?.suggestedMessages ?? []}
|
|
|
|
sendSuggestion={handleSendSuggestedMessage}
|
|
|
|
/>
|
2023-06-04 04:28:07 +02:00
|
|
|
</div>
|
2023-10-23 22:10:34 +02:00
|
|
|
{showing && (
|
|
|
|
<ManageWorkspace
|
|
|
|
hideModal={hideModal}
|
|
|
|
providedSlug={workspace.slug}
|
|
|
|
/>
|
|
|
|
)}
|
2023-06-04 04:28:07 +02:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div
|
2023-10-26 00:23:55 +02:00
|
|
|
className="h-full md:h-[83%] pb-[100px] pt-6 md:pt-0 md:pb-20 md:mx-0 overflow-y-scroll flex flex-col justify-start no-scroll"
|
2023-06-04 04:28:07 +02:00
|
|
|
id="chat-history"
|
2023-12-04 22:27:07 +01:00
|
|
|
ref={chatHistoryRef}
|
2023-06-04 04:28:07 +02:00
|
|
|
>
|
2023-08-22 00:46:31 +02:00
|
|
|
{history.map((props, index) => {
|
2023-11-14 00:07:30 +01:00
|
|
|
const isLastBotReply =
|
|
|
|
index === history.length - 1 && props.role === "assistant";
|
2023-08-22 00:46:31 +02:00
|
|
|
|
2023-11-14 00:07:30 +01:00
|
|
|
if (isLastBotReply && props.animate) {
|
2023-06-04 04:28:07 +02:00
|
|
|
return (
|
2023-08-22 00:46:31 +02:00
|
|
|
<PromptReply
|
|
|
|
key={props.uuid}
|
|
|
|
uuid={props.uuid}
|
|
|
|
reply={props.content}
|
|
|
|
pending={props.pending}
|
|
|
|
sources={props.sources}
|
|
|
|
error={props.error}
|
2023-06-04 04:28:07 +02:00
|
|
|
workspace={workspace}
|
2023-08-22 00:46:31 +02:00
|
|
|
closed={props.closed}
|
2023-06-04 04:28:07 +02:00
|
|
|
/>
|
|
|
|
);
|
|
|
|
}
|
2023-08-22 00:46:31 +02:00
|
|
|
|
|
|
|
return (
|
|
|
|
<HistoricalMessage
|
|
|
|
key={index}
|
|
|
|
message={props.content}
|
|
|
|
role={props.role}
|
|
|
|
workspace={workspace}
|
|
|
|
sources={props.sources}
|
2024-02-13 20:33:05 +01:00
|
|
|
feedbackScore={props.feedbackScore}
|
|
|
|
chatId={props.chatId}
|
2023-08-22 00:46:31 +02:00
|
|
|
error={props.error}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
})}
|
2023-10-23 22:10:34 +02:00
|
|
|
{showing && (
|
|
|
|
<ManageWorkspace hideModal={hideModal} providedSlug={workspace.slug} />
|
|
|
|
)}
|
2023-12-04 22:27:07 +01:00
|
|
|
{!isAtBottom && (
|
|
|
|
<div className="fixed bottom-40 right-10 md:right-20 z-50 cursor-pointer animate-pulse">
|
|
|
|
<div className="flex flex-col items-center">
|
|
|
|
<div className="p-1 rounded-full border border-white/10 bg-white/10 hover:bg-white/20 hover:text-white">
|
|
|
|
<ArrowDown
|
|
|
|
weight="bold"
|
|
|
|
className="text-white/60 w-5 h-5"
|
|
|
|
onClick={scrollToBottom}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
)}
|
2023-06-04 04:28:07 +02:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
2024-02-06 20:24:33 +01:00
|
|
|
|
|
|
|
function WorkspaceChatSuggestions({ suggestions = [], sendSuggestion }) {
|
|
|
|
if (suggestions.length === 0) return null;
|
|
|
|
return (
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-2 text-white/60 text-xs mt-10 w-full justify-center">
|
|
|
|
{suggestions.map((suggestion, index) => (
|
|
|
|
<button
|
|
|
|
key={index}
|
|
|
|
className="text-left p-2.5 border rounded-xl border-white/20 bg-sidebar hover:bg-workspace-item-selected-gradient"
|
|
|
|
onClick={() => sendSuggestion(suggestion.heading, suggestion.message)}
|
|
|
|
>
|
|
|
|
<p className="font-semibold">{suggestion.heading}</p>
|
|
|
|
<p>{suggestion.message}</p>
|
|
|
|
</button>
|
|
|
|
))}
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|