diff --git a/bun.lock b/bun.lock index 45b159c..4f617f5 100644 --- a/bun.lock +++ b/bun.lock @@ -19,6 +19,8 @@ "antd": "^6.4.3", "drizzle-orm": "^0.45.2", "es-toolkit": "^1.47.0", + "overlayscrollbars": "^2.16.0", + "overlayscrollbars-react": "^0.5.6", "pino": "^10.3.1", "pino-pretty": "^13.1.3", "pino-roll": "^4.0.0", @@ -1259,6 +1261,10 @@ "optionator": ["optionator@0.9.4", "https://registry.npmmirror.com/optionator/-/optionator-0.9.4.tgz", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], + "overlayscrollbars": ["overlayscrollbars@2.16.0", "", {}, "sha512-N03oje/q7j93D0aLZtoCdsDSYLmhheSsv8H7oSLE7HhdV9P/bmCURtLV/KbPye7P/bpfyt/obSfDpGUYoJ0OWg=="], + + "overlayscrollbars-react": ["overlayscrollbars-react@0.5.6", "", { "peerDependencies": { "overlayscrollbars": "^2.0.0", "react": ">=16.8.0" } }, "sha512-E5To04bL5brn9GVCZ36SnfGanxa2I2MDkWoa4Cjo5wol7l+diAgi4DBc983V7l2nOk/OLJ6Feg4kySspQEGDBw=="], + "own-keys": ["own-keys@1.0.1", "https://registry.npmmirror.com/own-keys/-/own-keys-1.0.1.tgz", { "dependencies": { "get-intrinsic": "^1.2.6", "object-keys": "^1.1.1", "safe-push-apply": "^1.0.0" } }, "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg=="], "p-limit": ["p-limit@3.1.0", "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], diff --git a/package.json b/package.json index 4e1d231..385aee4 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,8 @@ "antd": "^6.4.3", "drizzle-orm": "^0.45.2", "es-toolkit": "^1.47.0", + "overlayscrollbars": "^2.16.0", + "overlayscrollbars-react": "^0.5.6", "pino": "^10.3.1", "pino-pretty": "^13.1.3", "pino-roll": "^4.0.0", diff --git a/src/web/consoles/workbench/components/chat/ChatPanel.tsx b/src/web/consoles/workbench/components/chat/ChatPanel.tsx index bdba0f5..79a4ee7 100644 --- a/src/web/consoles/workbench/components/chat/ChatPanel.tsx +++ b/src/web/consoles/workbench/components/chat/ChatPanel.tsx @@ -1,5 +1,5 @@ import { useChat } from "@ai-sdk/react"; -import { ArrowDownOutlined, CopyOutlined, EditOutlined, RedoOutlined, RobotOutlined } from "@ant-design/icons"; +import { CopyOutlined, EditOutlined, RedoOutlined, RobotOutlined } from "@ant-design/icons"; import { Sender } from "@ant-design/x"; import { useQueryClient } from "@tanstack/react-query"; import { DefaultChatTransport, type UIMessage } from "ai"; @@ -14,10 +14,10 @@ import { } from "../../../../hooks/use-conversations"; import { useLogger } from "../../../../hooks/use-logger"; import { useModelList } from "../../../../hooks/use-models"; +import { ChatScrollArea } from "./ChatScrollArea"; import { ReasoningPart } from "./parts/ReasoningPart"; import { TextPart } from "./parts/TextPart"; import { ToolPart } from "./parts/ToolPart"; -import { useChatScroll } from "./use-chat-scroll"; interface ChatPanelProps { conversationId: null | string; @@ -35,7 +35,6 @@ export function ChatPanel({ conversationId, onConversationCreated, projectId }: const [loadingHistory, setLoadingHistory] = useState(false); const [selectedModelId, setSelectedModelId] = useState(null); const fetchRef = useRef(fetchMessages); - const scrollRef = useRef(null); const skipHistoryLoadRef = useRef(null); const { data: modelsData } = useModelList({ pageSize: 200 }); @@ -56,8 +55,6 @@ export function ChatPanel({ conversationId, onConversationCreated, projectId }: const isLoading = status === "submitted" || status === "streaming"; - const { isAtBottom, scrollToBottom } = useChatScroll({ messages, scrollRef, status }); - useEffect(() => { if (!conversationId) { setMessages([]); @@ -348,7 +345,7 @@ export function ChatPanel({ conversationId, onConversationCreated, projectId }: ) : ( -
+ {messages.map((msg, idx) => ( )} -
- )} - {!isAtBottom && ( -