feat(chat): 优化聊天面板交互体验 — 推理折叠/智能滚动/工具中文名/代码块按钮
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
import type { UIMessage } from "ai";
|
||||
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
|
||||
const NEAR_BOTTOM_THRESHOLD = 80;
|
||||
|
||||
interface UseChatScrollOptions {
|
||||
messages: UIMessage[];
|
||||
scrollRef: React.RefObject<HTMLDivElement | null>;
|
||||
status: string;
|
||||
}
|
||||
|
||||
export function useChatScroll({ messages, scrollRef, status }: UseChatScrollOptions) {
|
||||
const [isAtBottom, setIsAtBottom] = useState(true);
|
||||
const isStreaming = status === "streaming";
|
||||
|
||||
const checkNearBottom = useCallback(() => {
|
||||
const el = scrollRef.current;
|
||||
if (!el) return true;
|
||||
return el.scrollHeight - el.scrollTop - el.clientHeight < NEAR_BOTTOM_THRESHOLD;
|
||||
}, [scrollRef]);
|
||||
|
||||
useEffect(() => {
|
||||
const el = scrollRef.current;
|
||||
if (!el) return;
|
||||
|
||||
setIsAtBottom(checkNearBottom());
|
||||
|
||||
const handleScroll = () => {
|
||||
setIsAtBottom(checkNearBottom());
|
||||
};
|
||||
|
||||
el.addEventListener("scroll", handleScroll, { passive: true });
|
||||
return () => el.removeEventListener("scroll", handleScroll);
|
||||
}, [scrollRef, checkNearBottom]);
|
||||
|
||||
useEffect(() => {
|
||||
const el = scrollRef.current;
|
||||
if (!el || !isAtBottom) return;
|
||||
|
||||
el.scrollTo({
|
||||
behavior: isStreaming ? "instant" : "smooth",
|
||||
top: el.scrollHeight,
|
||||
});
|
||||
}, [messages, isStreaming, isAtBottom, scrollRef]);
|
||||
|
||||
const scrollToBottom = useCallback(() => {
|
||||
const el = scrollRef.current;
|
||||
if (!el) return;
|
||||
el.scrollTo({ behavior: "smooth", top: el.scrollHeight });
|
||||
setIsAtBottom(true);
|
||||
}, [scrollRef]);
|
||||
|
||||
return { isAtBottom, scrollToBottom };
|
||||
}
|
||||
Reference in New Issue
Block a user