From d319f5ebc7acfe95395fdbfc85b168a1f8101378 Mon Sep 17 00:00:00 2001 From: BiggerRain <15911122312@163.COM> Date: Wed, 12 Mar 2025 16:50:35 +0800 Subject: [PATCH] fix: the chat scrolling and chat rendering (#282) * fix: the chat scrolling and chat rendering * docs: update release notes --- docs/content.en/docs/release-notes/_index.md | 2 + src-tauri/src/server/servers.rs | 1 + src-tauri/src/server/websocket.rs | 2 +- src/components/Assistant/ChatContent.tsx | 1 + src/components/ChatMessage/PickSource.tsx | 2 +- src/components/ChatMessage/QueryIntent.tsx | 2 +- src/components/Cloud/Cloud.tsx | 32 +++++++----- src/hooks/useChatActions.ts | 3 +- src/hooks/useChatScroll.ts | 52 ++++++++++---------- 9 files changed, 53 insertions(+), 44 deletions(-) diff --git a/docs/content.en/docs/release-notes/_index.md b/docs/content.en/docs/release-notes/_index.md index 24d52e1d..631fbb95 100644 --- a/docs/content.en/docs/release-notes/_index.md +++ b/docs/content.en/docs/release-notes/_index.md @@ -17,10 +17,12 @@ Information about release notes of Coco Server is provided here. - Fix the issue that the fusion search include disabled servers - Fix incorrect version type: should be string instead of u32 - Fix the chat end judgment type #280 +- Fix the chat scrolling and chat rendering #282 ### Improvements - Refactor: chat components #273 +- Feat:add endpoint display #282 ## 0.2.0 (2025-03-07) diff --git a/src-tauri/src/server/servers.rs b/src-tauri/src/server/servers.rs index df1d6911..c2a56c91 100644 --- a/src-tauri/src/server/servers.rs +++ b/src-tauri/src/server/servers.rs @@ -589,6 +589,7 @@ fn test_trim_endpoint_last_forward_slash() { version: Version { number: "".to_string(), }, + minimal_client_version: None, updated: "".to_string(), public: false, available: false, diff --git a/src-tauri/src/server/websocket.rs b/src-tauri/src/server/websocket.rs index a736c4a7..75aa81d5 100644 --- a/src-tauri/src/server/websocket.rs +++ b/src-tauri/src/server/websocket.rs @@ -128,7 +128,7 @@ pub async fn connect_to_server( msg = ws.next() => { match msg { Some(Ok(Message::Text(text))) => { - println!("Received message: {}", text); + //println!("Received message: {}", text); let _ = app_handle_clone.emit("ws-message", text); }, Some(Err(WsError::ConnectionClosed)) => { diff --git a/src/components/Assistant/ChatContent.tsx b/src/components/Assistant/ChatContent.tsx index e254cc0e..88b8ee6d 100644 --- a/src/components/Assistant/ChatContent.tsx +++ b/src/components/Assistant/ChatContent.tsx @@ -57,6 +57,7 @@ export const ChatContent = ({ deep_read?.message_chunk, think?.message_chunk, response?.message_chunk, + curChatEnd, ]); useEffect(() => { diff --git a/src/components/ChatMessage/PickSource.tsx b/src/components/ChatMessage/PickSource.tsx index aa544c4e..d3183e28 100644 --- a/src/components/ChatMessage/PickSource.tsx +++ b/src/components/ChatMessage/PickSource.tsx @@ -36,7 +36,7 @@ export const PickSource = ({ useEffect(() => { if (!ChunkData?.message_chunk) return; - if (loading) { + if (!loading) { try { const cleanContent = ChunkData.message_chunk.replace(/^"|"$/g, ""); const allMatches = cleanContent.match(/([\s\S]*?)<\/JSON>/g); diff --git a/src/components/ChatMessage/QueryIntent.tsx b/src/components/ChatMessage/QueryIntent.tsx index d6900aac..313b2025 100644 --- a/src/components/ChatMessage/QueryIntent.tsx +++ b/src/components/ChatMessage/QueryIntent.tsx @@ -42,7 +42,7 @@ export const QueryIntent = ({ useEffect(() => { if (!ChunkData?.message_chunk) return; - if (loading) { + if (!loading) { const cleanContent = ChunkData.message_chunk.replace(/^"|"$/g, ""); const allMatches = cleanContent.match(/([\s\S]*?)<\/JSON>/g); if (allMatches) { diff --git a/src/components/Cloud/Cloud.tsx b/src/components/Cloud/Cloud.tsx index e49d8c91..3665687b 100644 --- a/src/components/Cloud/Cloud.tsx +++ b/src/components/Cloud/Cloud.tsx @@ -28,6 +28,7 @@ import { useAppStore } from "@/stores/appStore"; import { useConnectStore } from "@/stores/connectStore"; import bannerImg from "@/assets/images/coco-cloud-banner.jpeg"; import SettingsToggle from "@/components/Settings/SettingsToggle"; +import Tooltip from "@/components/Common/Tooltip"; export default function Cloud() { const { t } = useTranslation(); @@ -312,19 +313,22 @@ export default function Cloud() { }); }; - const enable_coco_server = useCallback(async (enabled: boolean) => { - try { - const command = enabled ? "enable_server" : "disable_server"; + const enable_coco_server = useCallback( + async (enabled: boolean) => { + try { + const command = enabled ? "enable_server" : "disable_server"; - await invoke(command, { id: currentService?.id }); + await invoke(command, { id: currentService?.id }); - setCurrentService({ ...currentService, enabled }); + setCurrentService({ ...currentService, enabled }); - await fetchServers(false); - } catch (error) { - setError(error); - } - }, [currentService?.id]); + await fetchServers(false); + } catch (error) { + setError(error); + } + }, + [currentService?.id] + ); return (
@@ -346,9 +350,11 @@ export default function Cloud() {
-
- {currentService?.name} -
+ +
+ {currentService?.name} +
+
{ if (!newChat?._id || !content) return; - + clearAllChunkData(); try { let response: any = await invoke("send_message", { serverId: currentServiceId, @@ -154,7 +154,6 @@ export function useChatActions( setTimedoutShow(false); setErrorShow(false); - clearAllChunkData(); await chatHistory(activeChat, (chat) => sendMessage(content, chat)); }, diff --git a/src/hooks/useChatScroll.ts b/src/hooks/useChatScroll.ts index d0c913c9..9fd0c6ed 100644 --- a/src/hooks/useChatScroll.ts +++ b/src/hooks/useChatScroll.ts @@ -5,18 +5,28 @@ export function useChatScroll(messagesEndRef: React.RefObject) { const [userScrolling, setUserScrolling] = useState(false); const scrollTimeoutRef = useRef(); + const lastScrollHeightRef = useRef(0); + + const isNearBottom = (container: HTMLElement) => { + const { scrollTop, scrollHeight, clientHeight } = container; + return Math.abs(scrollHeight - scrollTop - clientHeight) < 150; + }; + const scrollToBottom = useCallback( debounce(() => { - if (!userScrolling) { - const container = messagesEndRef.current?.parentElement; - if (container) { - container.scrollTo({ - top: container.scrollHeight, - behavior: "smooth", - }); - } + const container = messagesEndRef.current?.parentElement; + if (!container) return; + + const contentChanged = lastScrollHeightRef.current !== container.scrollHeight; + lastScrollHeightRef.current = container.scrollHeight; + + if (!userScrolling || (contentChanged && isNearBottom(container))) { + container.scrollTo({ + top: container.scrollHeight, + behavior: "smooth", + }); } - }, 100), + }, 50), [userScrolling, messagesEndRef] ); @@ -24,33 +34,23 @@ export function useChatScroll(messagesEndRef: React.RefObject) { const container = messagesEndRef.current?.parentElement; if (!container) return; + lastScrollHeightRef.current = container.scrollHeight; + const handleScroll = () => { if (scrollTimeoutRef.current) { clearTimeout(scrollTimeoutRef.current); } - const { scrollTop, scrollHeight, clientHeight } = container; - const isAtBottom = - Math.abs(scrollHeight - scrollTop - clientHeight) < 10; - - setUserScrolling(!isAtBottom); - - if (isAtBottom) { - setUserScrolling(false); + const near = isNearBottom(container); + if (!near) { + setUserScrolling(true); } scrollTimeoutRef.current = setTimeout(() => { - const { - scrollTop: newScrollTop, - scrollHeight: newScrollHeight, - clientHeight: newClientHeight, - } = container; - const nowAtBottom = - Math.abs(newScrollHeight - newScrollTop - newClientHeight) < 10; - if (nowAtBottom) { + if (isNearBottom(container)) { setUserScrolling(false); } - }, 500); + }, 300); }; container.addEventListener("scroll", handleScroll);