From 0bc61881c4abfd35dd6008dee582c31f66ad08dc Mon Sep 17 00:00:00 2001
From: BiggerRain <15911122312@163.COM>
Date: Tue, 4 Mar 2025 15:49:04 +0800
Subject: [PATCH] chore: Coco chat window input and message (#237)
---
src/components/Assistant/Chat.tsx | 52 ++++++++++---------
src/components/Assistant/ChatHeader.tsx | 20 +++++---
src/components/Assistant/Greetings.tsx | 20 ++++++++
src/components/ChatMessage/QueryIntent.tsx | 2 +-
src/components/Search/InputBox.tsx | 60 +++++++++++++---------
src/locales/zh/translation.json | 2 +-
src/pages/chat/index.tsx | 40 +++++++--------
src/pages/main/index.tsx | 6 +--
src/stores/chatStore.ts | 8 +--
9 files changed, 126 insertions(+), 84 deletions(-)
create mode 100644 src/components/Assistant/Greetings.tsx
diff --git a/src/components/Assistant/Chat.tsx b/src/components/Assistant/Chat.tsx
index a335e9b3..43f6f90b 100644
--- a/src/components/Assistant/Chat.tsx
+++ b/src/components/Assistant/Chat.tsx
@@ -22,7 +22,8 @@ import { Sidebar } from "@/components/Assistant/Sidebar";
import { useConnectStore } from "@/stores/connectStore";
import { useSearchStore } from "@/stores/searchStore";
import { IServer } from "@/stores/appStore";
-import FileList from "../Search/FileList";
+import FileList from "@/components/Search/FileList";
+import { Greetings } from "./Greetings";
interface ChatAIProps {
isTransitioned: boolean;
@@ -33,6 +34,7 @@ interface ChatAIProps {
setIsSidebarOpen?: (value: boolean) => void;
isSidebarOpen?: boolean;
clearChatPage?: () => void;
+ isChatPage?: boolean;
}
export interface ChatAIRef {
@@ -56,6 +58,7 @@ const ChatAI = memo(
setIsSidebarOpen,
isSidebarOpen = false,
clearChatPage,
+ isChatPage = false,
},
ref
) => {
@@ -174,6 +177,7 @@ const ChatAI = memo(
});
}, []);
+ // send、new、history
const clearCurrentChat = useCallback(() => {
setQuery_intent(undefined);
setFetch_source(undefined);
@@ -258,11 +262,12 @@ const ChatAI = memo(
useEffect(() => {
let unlisten_message = null;
+ console.log("connected:", connected);
if (connected) {
setErrorShow(false);
unlisten_message = listen("ws-message", (event) => {
dealMsg(String(event.payload));
- console.log("message:", event.payload);
+ // console.log("message:", event.payload);
});
}
@@ -415,7 +420,6 @@ const ChatAI = memo(
);
const init = (value: string) => {
- console.log("init", value, curChatEnd, activeChat);
if (!curChatEnd) return;
if (!activeChat?._id) {
createNewChat(value);
@@ -424,16 +428,10 @@ const ChatAI = memo(
}
};
- const handleSendMessage = useCallback(
- async (content: string, newChat?: Chat) => {
- newChat = newChat || activeChat;
+ const sendMessage = useCallback(
+ async (content: string, newChat: Chat) => {
if (!newChat?._id || !content) return;
- setQuestion(content);
- await chatHistory(newChat);
- setTimedoutShow(false);
- setErrorShow(false);
- clearCurrentChat();
try {
// console.log("sourceDataIds", sourceDataIds);
let response: any = await invoke("send_message", {
@@ -464,7 +462,21 @@ const ChatAI = memo(
console.error("Failed to fetch user data:", error);
}
},
- [activeChat, isSearchActive, isDeepThinkActive]
+ [JSON.stringify(activeChat?.messages), isSearchActive, isDeepThinkActive]
+ );
+
+ const handleSendMessage = useCallback(
+ async (content: string, newChat?: Chat) => {
+ newChat = newChat || activeChat;
+ if (!newChat?._id || !content) return;
+ setQuestion(content);
+ await chatHistory(newChat, (chat) => sendMessage(content, chat));
+
+ setTimedoutShow(false);
+ setErrorShow(false);
+ clearCurrentChat();
+ },
+ [activeChat, sendMessage]
);
const chatClose = async () => {
@@ -527,7 +539,7 @@ const ChatAI = memo(
};
}, []);
- const chatHistory = async (chat: Chat) => {
+ const chatHistory = async (chat: Chat, callback?: (chat: Chat) => void) => {
try {
let response: any = await invoke("session_chat_history", {
serverId: currentService?.id,
@@ -543,6 +555,7 @@ const ChatAI = memo(
messages: hits,
};
setActiveChat(updatedChat);
+ callback && callback(updatedChat)
} catch (error) {
console.error("Failed to fetch user data:", error);
}
@@ -550,6 +563,7 @@ const ChatAI = memo(
const onSelectChat = async (chat: any) => {
chatClose();
+ clearCurrentChat();
try {
let response: any = await invoke("open_session_chat", {
serverId: currentService?.id,
@@ -655,20 +669,12 @@ const ChatAI = memo(
isSidebarOpen={isSidebarOpenChat}
activeChat={activeChat}
reconnect={reconnect}
+ isChatPage={isChatPage}
/>
{/* Chat messages */}
-
+
{activeChat?.messages?.map((message, index) => (
void;
+ isChatPage?: boolean;
}
export function ChatHeader({
@@ -47,6 +48,7 @@ export function ChatHeader({
setIsSidebarOpen,
activeChat,
reconnect,
+ isChatPage = false,
}: ChatHeaderProps) {
const { t } = useTranslation();
@@ -77,7 +79,7 @@ export function ChatHeader({
);
if (currentServiceExists) {
- switchServer(currentService);
+ switchServer(currentService, true);
} else {
switchServer(enabledServers[enabledServers.length - 1]);
}
@@ -108,7 +110,7 @@ export function ChatHeader({
}
};
- const switchServer = async (server: IServer) => {
+ const switchServer = async (server: IServer, isCurrent: boolean = false) => {
if (!server) return;
try {
// Switch UI first, then switch server connection
@@ -117,8 +119,10 @@ export function ChatHeader({
setMessages(""); // Clear previous messages
onCreateNewChat();
//
- await disconnect();
- reconnect && reconnect(server);
+ if (!(isCurrent && connected)) {
+ await disconnect();
+ reconnect && reconnect(server);
+ }
} catch (error) {
console.error("switchServer:", error);
}
@@ -306,9 +310,11 @@ export function ChatHeader({
-
+ {isChatPage ? null : (
+
+ )}
);
diff --git a/src/components/Assistant/Greetings.tsx b/src/components/Assistant/Greetings.tsx
new file mode 100644
index 00000000..e948ccf3
--- /dev/null
+++ b/src/components/Assistant/Greetings.tsx
@@ -0,0 +1,20 @@
+import { useTranslation } from "react-i18next";
+
+import { ChatMessage } from "@/components/ChatMessage";
+
+export const Greetings = () => {
+ const { t } = useTranslation();
+
+ return (
+
+ );
+};
diff --git a/src/components/ChatMessage/QueryIntent.tsx b/src/components/ChatMessage/QueryIntent.tsx
index edf440d6..27519dea 100644
--- a/src/components/ChatMessage/QueryIntent.tsx
+++ b/src/components/ChatMessage/QueryIntent.tsx
@@ -37,7 +37,7 @@ export const QueryIntent = ({ ChunkData, getSuggestion }: QueryIntentProps) => {
const lastMatch = allMatches[allMatches.length - 1];
const jsonString = lastMatch.replace(/
|<\/JSON>/g, "");
const data = JSON.parse(jsonString);
- console.log("QueryIntent", data);
+ // console.log("QueryIntent", data);
if (data?.suggestion && getSuggestion) {
getSuggestion(data?.suggestion)
}
diff --git a/src/components/Search/InputBox.tsx b/src/components/Search/InputBox.tsx
index bae0dded..a4ce7e73 100644
--- a/src/components/Search/InputBox.tsx
+++ b/src/components/Search/InputBox.tsx
@@ -21,6 +21,7 @@ import {
} from "@headlessui/react";
import clsx from "clsx";
import { useReactive, useRequest } from "ahooks";
+import { isArray } from "lodash-es";
import ChatSwitch from "@/components/Common/ChatSwitch";
import AutoResizeTextarea from "./AutoResizeTextarea";
@@ -31,14 +32,13 @@ import { useSearchStore } from "@/stores/searchStore";
import { metaOrCtrlKey } from "@/utils/keyboardUtils";
import { useConnectStore } from "@/stores/connectStore";
import TypeIcon from "@/components/Common/Icons/TypeIcon";
-import { isArray } from "lodash-es";
import InputExtra from "./InputExtra";
interface ChatInputProps {
onSend: (message: string) => void;
disabled: boolean;
disabledChange: () => void;
- changeMode: (isChatMode: boolean) => void;
+ changeMode?: (isChatMode: boolean) => void;
isChatMode: boolean;
inputValue: string;
changeInput: (val: string) => void;
@@ -47,6 +47,7 @@ interface ChatInputProps {
setIsSearchActive: () => void;
isDeepThinkActive: boolean;
setIsDeepThinkActive: () => void;
+ isChatPage?: boolean;
}
export default function ChatInput({
@@ -62,6 +63,7 @@ export default function ChatInput({
setIsSearchActive,
isDeepThinkActive,
setIsDeepThinkActive,
+ isChatPage = false,
}: ChatInputProps) {
const { t } = useTranslation();
@@ -266,7 +268,7 @@ export default function ChatInput({
if (!isChatMode) return;
if (connected) return;
if (countdown <= 0) {
- console.log("ReconnectClick", 111111);
+ console.log("ReconnectClick");
ReconnectClick();
return;
}
@@ -310,8 +312,16 @@ export default function ChatInput({
};
return (
-
-
+
+
{!isChatMode && !sourceData ? (
@@ -326,7 +336,9 @@ export default function ChatInput({
{
+ changeInput(value);
+ }}
connected={connected}
handleKeyDown={(e) => {
if (e.key === "Enter") {
@@ -657,23 +669,25 @@ export default function ChatInput({
)}
-
- {showTooltip && isCommandPressed ? (
-
- T
-
- ) : null}
-
{
- value && disabledChange();
- changeMode(value);
- setSourceData(undefined);
- }}
- />
-
+ {isChatPage ? null : (
+
+ {showTooltip && isCommandPressed ? (
+
+ T
+
+ ) : null}
+
{
+ value && disabledChange();
+ changeMode && changeMode(value);
+ setSourceData(undefined);
+ }}
+ />
+
+ )}
);
diff --git a/src/locales/zh/translation.json b/src/locales/zh/translation.json
index dab3a735..2f2144e8 100644
--- a/src/locales/zh/translation.json
+++ b/src/locales/zh/translation.json
@@ -138,7 +138,7 @@
"fetch_source": "检索 {{count}} 份文档",
"pick_source": "智能预选 {{count}} 个结果",
"pick_source_start": "正在智能预选",
- "deep_read": "深度阅读,",
+ "deep_read": "深度阅读",
"think": "AI 正在思考...",
"thoughtTime": "思考了数秒",
"keywords": "关键词",
diff --git a/src/pages/chat/index.tsx b/src/pages/chat/index.tsx
index 4d7675ad..c9c6363a 100644
--- a/src/pages/chat/index.tsx
+++ b/src/pages/chat/index.tsx
@@ -2,10 +2,10 @@ import { useState, useRef, useEffect } from "react";
import { invoke } from "@tauri-apps/api/core";
import ChatAI, { ChatAIRef } from "@/components/Assistant/Chat";
-import { ChatInput } from "@/components/Assistant/ChatInput";
import { Sidebar } from "@/components/Assistant/Sidebar";
import type { Chat } from "@/components/Assistant/types";
import { useConnectStore } from "@/stores/connectStore";
+import InputBox from "@/components/Search/InputBox";
interface ChatProps {}
@@ -17,13 +17,15 @@ export default function Chat({}: ChatProps) {
const [chats, setChats] = useState
([]);
const [activeChat, setActiveChat] = useState();
const [isSidebarOpen, setIsSidebarOpen] = useState(true);
- const [isTyping, setIsTyping] = useState(false);
+ const isTyping = false;
- const [curChatEnd, setCurChatEnd] = useState(true);
+ const [input, setInput] = useState("");
const [isSearchActive, setIsSearchActive] = useState(false);
const [isDeepThinkActive, setIsDeepThinkActive] = useState(false);
+ const isChatPage = true
+
useEffect(() => {
getChatHistory();
}, []);
@@ -62,6 +64,7 @@ export default function Chat({}: ChatProps) {
};
const handleSendMessage = async (content: string) => {
+ setInput(content);
chatAIRef.current?.init(content);
};
@@ -116,17 +119,7 @@ export default function Chat({}: ChatProps) {
};
const cancelChat = async () => {
- if (!activeChat?._id) return;
- try {
- let response: any = await invoke("cancel_session_chat", {
- serverId: currentService?.id,
- sessionId: activeChat?._id,
- });
- response = JSON.parse(response || "");
- console.log("_cancel", response);
- } catch (error) {
- console.error("Failed to fetch user data:", error);
- }
+ chatAIRef.current?.cancelChat();
};
const clearChat = () => {
@@ -134,6 +127,10 @@ export default function Chat({}: ChatProps) {
setActiveChat(undefined);
};
+ const reconnect = () => {
+ chatAIRef.current?.reconnect();
+ };
+
return (
@@ -169,23 +166,24 @@ export default function Chat({}: ChatProps) {
setIsSidebarOpen={setIsSidebarOpen}
isSidebarOpen={isSidebarOpen}
clearChatPage={clearChat}
+ isChatPage={isChatPage}
/>
{/* Input area */}
- {
- cancelChat();
- setCurChatEnd(true);
- setIsTyping(false);
- }}
+ disabledChange={cancelChat}
+ reconnect={reconnect}
isSearchActive={isSearchActive}
setIsSearchActive={() => setIsSearchActive((prev) => !prev)}
isDeepThinkActive={isDeepThinkActive}
setIsDeepThinkActive={() => setIsDeepThinkActive((prev) => !prev)}
+ isChatPage={isChatPage}
/>
diff --git a/src/pages/main/index.tsx b/src/pages/main/index.tsx
index f9b1ab2d..8ffd852b 100644
--- a/src/pages/main/index.tsx
+++ b/src/pages/main/index.tsx
@@ -64,7 +64,7 @@ export default function DesktopApp() {
setIsTransitioned(value);
}
- async function changeInput(value: string) {
+ function changeInput(value: string) {
setInput(value);
}
@@ -114,9 +114,7 @@ export default function DesktopApp() {
inputValue={input}
onSend={handleSendMessage}
disabled={isTyping}
- disabledChange={() => {
- cancelChat();
- }}
+ disabledChange={cancelChat}
changeMode={changeMode}
changeInput={changeInput}
reconnect={reconnect}
diff --git a/src/stores/chatStore.ts b/src/stores/chatStore.ts
index 9b05a4b1..280af7c0 100644
--- a/src/stores/chatStore.ts
+++ b/src/stores/chatStore.ts
@@ -46,10 +46,10 @@ export const useChatStore = create
()(
{
name: "chat-state",
// storage: createJSONStorage(() => sessionStorage),
- partialize: (state) =>
- Object.fromEntries(
- Object.entries(state).filter(([key]) => key === "curChatEnd")
- ),
+ partialize: (state) => ({
+ curChatEnd: state.curChatEnd,
+ connected: state.connected,
+ }),
}
)
);