mirror of
https://github.com/Mintplex-Labs/anything-llm.git
synced 2024-11-16 11:20:10 +01:00
Autoscroll to end of chat fix (#201)
bug fix for autoscrolling on message send/recieve
This commit is contained in:
parent
4a67cf2198
commit
b01e49bb3c
@ -1,23 +1,12 @@
|
|||||||
import { useEffect, useRef, memo } from "react";
|
import { memo, forwardRef } from "react";
|
||||||
import { AlertTriangle } from "react-feather";
|
import { AlertTriangle } from "react-feather";
|
||||||
import Jazzicon from "../../../../UserIcon";
|
import Jazzicon from "../../../../UserIcon";
|
||||||
import renderMarkdown from "../../../../../utils/chat/markdown";
|
import renderMarkdown from "../../../../../utils/chat/markdown";
|
||||||
import { userFromStorage } from "../../../../../utils/request";
|
import { userFromStorage } from "../../../../../utils/request";
|
||||||
import Citations from "../Citation";
|
import Citations from "../Citation";
|
||||||
|
|
||||||
function HistoricalMessage({
|
const HistoricalMessage = forwardRef(
|
||||||
message,
|
({ message, role, workspace, sources = [], error = false }, ref) => {
|
||||||
role,
|
|
||||||
workspace,
|
|
||||||
sources = [],
|
|
||||||
error = false,
|
|
||||||
}) {
|
|
||||||
const replyRef = useRef(null);
|
|
||||||
useEffect(() => {
|
|
||||||
if (replyRef.current)
|
|
||||||
replyRef.current.scrollIntoView({ behavior: "smooth", block: "end" });
|
|
||||||
}, [replyRef.current]);
|
|
||||||
|
|
||||||
if (role === "user") {
|
if (role === "user") {
|
||||||
return (
|
return (
|
||||||
<div className="flex justify-end mb-4 items-start">
|
<div className="flex justify-end mb-4 items-start">
|
||||||
@ -50,7 +39,7 @@ function HistoricalMessage({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={replyRef} className="flex justify-start items-end mb-4">
|
<div ref={ref} className="flex justify-start items-end mb-4">
|
||||||
<Jazzicon size={30} user={{ uid: workspace.slug }} />
|
<Jazzicon size={30} user={{ uid: workspace.slug }} />
|
||||||
<div className="ml-2 py-3 px-4 overflow-x-scroll w-fit md:max-w-[75%] bg-orange-100 dark:bg-stone-700 rounded-t-2xl rounded-br-2xl rounded-bl-sm">
|
<div className="ml-2 py-3 px-4 overflow-x-scroll w-fit md:max-w-[75%] bg-orange-100 dark:bg-stone-700 rounded-t-2xl rounded-br-2xl rounded-bl-sm">
|
||||||
<span
|
<span
|
||||||
@ -62,5 +51,6 @@ function HistoricalMessage({
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
|
||||||
export default memo(HistoricalMessage);
|
export default memo(HistoricalMessage);
|
||||||
|
@ -1,28 +1,21 @@
|
|||||||
import { memo, useEffect, useRef } from "react";
|
import { forwardRef, memo } from "react";
|
||||||
import { AlertTriangle } from "react-feather";
|
import { AlertTriangle } from "react-feather";
|
||||||
import Jazzicon from "../../../../UserIcon";
|
import Jazzicon from "../../../../UserIcon";
|
||||||
import renderMarkdown from "../../../../../utils/chat/markdown";
|
import renderMarkdown from "../../../../../utils/chat/markdown";
|
||||||
import Citations from "../Citation";
|
import Citations from "../Citation";
|
||||||
|
|
||||||
function PromptReply({
|
const PromptReply = forwardRef(
|
||||||
uuid,
|
(
|
||||||
reply,
|
{ uuid, reply, pending, error, workspace, sources = [], closed = true },
|
||||||
pending,
|
ref
|
||||||
error,
|
) => {
|
||||||
workspace,
|
|
||||||
sources = [],
|
|
||||||
closed = true,
|
|
||||||
}) {
|
|
||||||
const replyRef = useRef(null);
|
|
||||||
useEffect(() => {
|
|
||||||
if (replyRef.current)
|
|
||||||
replyRef.current.scrollIntoView({ behavior: "smooth", block: "end" });
|
|
||||||
}, [replyRef.current]);
|
|
||||||
|
|
||||||
if (!reply && !sources.length === 0 && !pending && !error) return null;
|
if (!reply && !sources.length === 0 && !pending && !error) return null;
|
||||||
if (pending) {
|
if (pending) {
|
||||||
return (
|
return (
|
||||||
<div className="chat__message flex justify-start mb-4 items-end">
|
<div
|
||||||
|
ref={ref}
|
||||||
|
className="chat__message flex justify-start mb-4 items-end"
|
||||||
|
>
|
||||||
<Jazzicon size={30} user={{ uid: workspace.slug }} />
|
<Jazzicon size={30} user={{ uid: workspace.slug }} />
|
||||||
<div className="ml-2 pt-2 px-6 w-fit md:max-w-[75%] bg-orange-100 dark:bg-stone-700 rounded-t-2xl rounded-br-2xl rounded-bl-sm">
|
<div className="ml-2 pt-2 px-6 w-fit md:max-w-[75%] bg-orange-100 dark:bg-stone-700 rounded-t-2xl rounded-br-2xl rounded-bl-sm">
|
||||||
<span className={`inline-block p-2`}>
|
<span className={`inline-block p-2`}>
|
||||||
@ -40,8 +33,8 @@ function PromptReply({
|
|||||||
<div className="ml-2 py-3 px-4 rounded-br-3xl rounded-tr-3xl rounded-tl-xl text-slate-100 ">
|
<div className="ml-2 py-3 px-4 rounded-br-3xl rounded-tr-3xl rounded-tl-xl text-slate-100 ">
|
||||||
<div className="bg-red-50 text-red-500 rounded-lg w-fit flex flex-col p-2">
|
<div className="bg-red-50 text-red-500 rounded-lg w-fit flex flex-col p-2">
|
||||||
<span className={`inline-block`}>
|
<span className={`inline-block`}>
|
||||||
<AlertTriangle className="h-4 w-4 mb-1 inline-block" /> Could not
|
<AlertTriangle className="h-4 w-4 mb-1 inline-block" /> Could
|
||||||
respond to message.
|
not respond to message.
|
||||||
</span>
|
</span>
|
||||||
<span className="text-xs">Reason: {error || "unknown"}</span>
|
<span className="text-xs">Reason: {error || "unknown"}</span>
|
||||||
</div>
|
</div>
|
||||||
@ -51,11 +44,7 @@ function PromptReply({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div key={uuid} ref={ref} className="mb-4 flex justify-start items-end">
|
||||||
key={uuid}
|
|
||||||
ref={replyRef}
|
|
||||||
className="mb-4 flex justify-start items-end"
|
|
||||||
>
|
|
||||||
<Jazzicon size={30} user={{ uid: workspace.slug }} />
|
<Jazzicon size={30} user={{ uid: workspace.slug }} />
|
||||||
<div className="ml-2 py-3 px-4 overflow-x-scroll w-fit md:max-w-[75%] bg-orange-100 dark:bg-stone-700 rounded-t-2xl rounded-br-2xl rounded-bl-sm">
|
<div className="ml-2 py-3 px-4 overflow-x-scroll w-fit md:max-w-[75%] bg-orange-100 dark:bg-stone-700 rounded-t-2xl rounded-br-2xl rounded-bl-sm">
|
||||||
<span
|
<span
|
||||||
@ -67,5 +56,6 @@ function PromptReply({
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
|
||||||
export default memo(PromptReply);
|
export default memo(PromptReply);
|
||||||
|
@ -1,8 +1,19 @@
|
|||||||
import { Frown } from "react-feather";
|
import { Frown } from "react-feather";
|
||||||
import HistoricalMessage from "./HistoricalMessage";
|
import HistoricalMessage from "./HistoricalMessage";
|
||||||
import PromptReply from "./PromptReply";
|
import PromptReply from "./PromptReply";
|
||||||
|
import { useEffect, useRef } from "react";
|
||||||
|
|
||||||
export default function ChatHistory({ history = [], workspace }) {
|
export default function ChatHistory({ history = [], workspace }) {
|
||||||
|
const replyRef = useRef(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (replyRef.current) {
|
||||||
|
setTimeout(() => {
|
||||||
|
replyRef.current.scrollIntoView({ behavior: "smooth", block: "end" });
|
||||||
|
}, 700);
|
||||||
|
}
|
||||||
|
}, [history]);
|
||||||
|
|
||||||
if (history.length === 0) {
|
if (history.length === 0) {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col h-[89%] md:mt-0 pb-5 w-full justify-center items-center">
|
<div className="flex flex-col h-[89%] md:mt-0 pb-5 w-full justify-center items-center">
|
||||||
@ -22,48 +33,37 @@ export default function ChatHistory({ history = [], workspace }) {
|
|||||||
className="h-[89%] pb-[100px] md:pt-[50px] md:pt-0 md:pb-5 mx-2 md:mx-0 overflow-y-scroll flex flex-col justify-start no-scroll"
|
className="h-[89%] pb-[100px] md:pt-[50px] md:pt-0 md:pb-5 mx-2 md:mx-0 overflow-y-scroll flex flex-col justify-start no-scroll"
|
||||||
id="chat-history"
|
id="chat-history"
|
||||||
>
|
>
|
||||||
{history.map(
|
{history.map((props, index) => {
|
||||||
(
|
const isLastMessage = index === history.length - 1;
|
||||||
{
|
|
||||||
uuid = null,
|
if (props.role === "assistant" && props.animate) {
|
||||||
content,
|
|
||||||
sources = [],
|
|
||||||
role,
|
|
||||||
closed = true,
|
|
||||||
pending = false,
|
|
||||||
error = false,
|
|
||||||
animate = false,
|
|
||||||
},
|
|
||||||
index
|
|
||||||
) => {
|
|
||||||
const isLastBotReply =
|
|
||||||
index === history.length - 1 && role === "assistant";
|
|
||||||
if (isLastBotReply && animate) {
|
|
||||||
return (
|
return (
|
||||||
<PromptReply
|
<PromptReply
|
||||||
key={uuid}
|
key={props.uuid}
|
||||||
uuid={uuid}
|
ref={isLastMessage ? replyRef : null}
|
||||||
reply={content}
|
uuid={props.uuid}
|
||||||
pending={pending}
|
reply={props.content}
|
||||||
sources={sources}
|
pending={props.pending}
|
||||||
error={error}
|
sources={props.sources}
|
||||||
|
error={props.error}
|
||||||
workspace={workspace}
|
workspace={workspace}
|
||||||
closed={closed}
|
closed={props.closed}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HistoricalMessage
|
<HistoricalMessage
|
||||||
key={index}
|
key={index}
|
||||||
message={content}
|
ref={isLastMessage ? replyRef : null}
|
||||||
role={role}
|
message={props.content}
|
||||||
|
role={props.role}
|
||||||
workspace={workspace}
|
workspace={workspace}
|
||||||
sources={sources}
|
sources={props.sources}
|
||||||
error={error}
|
error={props.error}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
})}
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user