fix(chat): keep sent messages in view
This commit is contained in:
@@ -47,6 +47,7 @@ const ReplyingAnimation = lazy(() =>
|
||||
export interface ChatAreaProps {
|
||||
messages: readonly UiMessage[];
|
||||
isReplyingAI: boolean;
|
||||
scrollToBottomSignal?: number;
|
||||
initialScrollReady?: boolean;
|
||||
canLoadMoreHistory?: boolean;
|
||||
isLoadingMoreHistory?: boolean;
|
||||
@@ -62,6 +63,7 @@ export interface ChatAreaProps {
|
||||
export function ChatArea({
|
||||
messages,
|
||||
isReplyingAI,
|
||||
scrollToBottomSignal = 0,
|
||||
initialScrollReady = true,
|
||||
canLoadMoreHistory = false,
|
||||
isLoadingMoreHistory = false,
|
||||
@@ -77,6 +79,7 @@ export function ChatArea({
|
||||
const contentRef = useRef<HTMLDivElement>(null);
|
||||
const initialScrollSettledRef = useRef(false);
|
||||
const shouldStickToBottomRef = useRef(true);
|
||||
const previousScrollToBottomSignalRef = useRef(scrollToBottomSignal);
|
||||
const loadMoreAnchorRef = useRef<{
|
||||
scrollHeight: number;
|
||||
scrollTop: number;
|
||||
@@ -115,12 +118,33 @@ export function ChatArea({
|
||||
useLayoutEffect(() => {
|
||||
if (!initialScrollReady) {
|
||||
initialScrollSettledRef.current = false;
|
||||
previousScrollToBottomSignalRef.current = scrollToBottomSignal;
|
||||
return;
|
||||
}
|
||||
|
||||
const scrollNode = scrollRef.current;
|
||||
if (!scrollNode) return;
|
||||
|
||||
const shouldForceScrollToBottom =
|
||||
previousScrollToBottomSignalRef.current !== scrollToBottomSignal;
|
||||
previousScrollToBottomSignalRef.current = scrollToBottomSignal;
|
||||
|
||||
if (shouldForceScrollToBottom) {
|
||||
loadMoreAnchorRef.current = null;
|
||||
initialScrollSettledRef.current = true;
|
||||
shouldStickToBottomRef.current = true;
|
||||
scrollToBottom(scrollNode);
|
||||
const frameId = requestAnimationFrame(() => {
|
||||
if (
|
||||
scrollRef.current === scrollNode &&
|
||||
shouldStickToBottomRef.current
|
||||
) {
|
||||
scrollToBottom(scrollNode);
|
||||
}
|
||||
});
|
||||
return () => cancelAnimationFrame(frameId);
|
||||
}
|
||||
|
||||
if (loadMoreAnchorRef.current && !isLoadingMoreHistory) {
|
||||
const anchor = loadMoreAnchorRef.current;
|
||||
loadMoreAnchorRef.current = null;
|
||||
@@ -149,7 +173,13 @@ export function ChatArea({
|
||||
});
|
||||
|
||||
return () => cancelAnimationFrame(frameId);
|
||||
}, [initialScrollReady, isLoadingMoreHistory, isReplyingAI, messages]);
|
||||
}, [
|
||||
initialScrollReady,
|
||||
isLoadingMoreHistory,
|
||||
isReplyingAI,
|
||||
messages,
|
||||
scrollToBottomSignal,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
const scrollNode = scrollRef.current;
|
||||
|
||||
Reference in New Issue
Block a user