Skip to content

Commit 3cfb03d

Browse files
authored
feat: the chat input box supports multi-line input (#490)
* chore: chat input * feat: the chat input box supports multi-line input * docs: update notes * chore: remove env record * chore: remove debug
1 parent 386b9cc commit 3cfb03d

File tree

9 files changed

+73
-68
lines changed

9 files changed

+73
-68
lines changed

docs/content.en/docs/release-notes/_index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Information about release notes of Coco Server is provided here.
1818
- feat: supports Shift + Enter input box line feeds #472
1919
- feat: support for snapshot version updates #480
2020
- feat: history list add put away button #482
21+
- feat: the chat input box supports multi-line input #490
2122

2223
### 🐛 Bug fix
2324

src/components/Assistant/Chat.tsx

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,7 @@ const ChatAI = memo(
190190
setActiveChat(undefined);
191191
setCurChatEnd(true);
192192
clearChatPage && clearChatPage();
193-
}, [
194-
activeChat,
195-
chatClose,
196-
]);
193+
}, [activeChat, chatClose]);
197194

198195
const init = useCallback(
199196
async (value: string) => {
@@ -242,13 +239,7 @@ const ChatAI = memo(
242239
chatHistory(response);
243240
}
244241
},
245-
[
246-
cancelChat,
247-
activeChat,
248-
chatClose,
249-
openSessionChat,
250-
chatHistory,
251-
]
242+
[cancelChat, activeChat, chatClose, openSessionChat, chatHistory]
252243
);
253244

254245
const deleteChat = useCallback(
@@ -331,7 +322,7 @@ const ChatAI = memo(
331322
return (
332323
<div
333324
data-tauri-drag-region
334-
className={`h-full flex flex-col rounded-md relative`}
325+
className={`flex flex-col rounded-md relative h-full overflow-hidden`}
335326
>
336327
{showChatHistory && !setIsSidebarOpen && (
337328
<ChatSidebar
@@ -360,6 +351,7 @@ const ChatAI = memo(
360351
showChatHistory={showChatHistory}
361352
assistantIDs={assistantIDs}
362353
/>
354+
363355
{isLogin ? (
364356
<ChatContent
365357
activeChat={activeChat}

src/components/Assistant/ChatContent.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ export const ChatContent = ({
8484
const allMessages = activeChat?.messages || [];
8585

8686
return (
87-
<div className="relative flex flex-col h-full justify-between overflow-hidden">
87+
<div className="flex-1 overflow-hidden flex flex-col justify-between relative">
8888
<div className="flex-1 w-full overflow-x-hidden overflow-y-auto border-t border-[rgba(0,0,0,0.1)] dark:border-[rgba(255,255,255,0.15)] custom-scrollbar relative">
8989
<Greetings />
9090

@@ -112,7 +112,8 @@ export const ChatContent = ({
112112
_id: "current",
113113
_source: {
114114
type: "assistant",
115-
assistant_id: allMessages[allMessages.length-1]?._source?.assistant_id,
115+
assistant_id:
116+
allMessages[allMessages.length - 1]?._source?.assistant_id,
116117
message: "",
117118
question: Question,
118119
},
@@ -129,6 +130,7 @@ export const ChatContent = ({
129130
loadingStep={loadingStep}
130131
/>
131132
) : null}
133+
132134
{timedoutShow ? (
133135
<ChatMessage
134136
key={"timedout"}

src/components/Assistant/ChatSidebar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export const ChatSidebar: React.FC<ChatSidebarProps> = ({
3232
<div
3333
data-sidebar
3434
className={`
35-
h-[calc(100%+90px)] absolute top-0 left-0 z-10 w-64
35+
h-screen absolute top-0 left-0 z-10 w-64
3636
transform transition-all duration-300 ease-in-out
3737
${isSidebarOpen ? "translate-x-0" : "-translate-x-full"}
3838
bg-gray-100 dark:bg-gray-800

src/components/Assistant/Splash.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ const Splash = () => {
9696

9797
return (
9898
visibleStartPage && (
99-
<div className="absolute inset-0 flex flex-col items-center px-6 pt-6 text-[#333] dark:text-white select-none">
99+
<div className="absolute inset-0 flex flex-col items-center px-6 pt-6 text-[#333] dark:text-white select-none overflow-y-auto custom-scrollbar">
100100
<CircleX
101101
className="absolute top-3 right-3 size-4 text-[#999] cursor-pointer"
102102
onClick={() => {

src/components/Search/AutoResizeTextarea.tsx

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import { useBoolean } from "ahooks";
2-
import { useRef, useImperativeHandle, forwardRef, KeyboardEvent } from "react";
2+
import {
3+
useRef,
4+
useImperativeHandle,
5+
forwardRef,
6+
KeyboardEvent,
7+
useEffect,
8+
} from "react";
39
import { useTranslation } from "react-i18next";
410

511
interface AutoResizeTextareaProps {
@@ -35,14 +41,22 @@ const AutoResizeTextarea = forwardRef<
3541
handleKeyDown?.(event);
3642
};
3743

44+
useEffect(() => {
45+
if (textareaRef.current) {
46+
textareaRef.current.style.height = "auto";
47+
const newHeight = Math.min(textareaRef.current.scrollHeight, 15 * 16); // 15rem ≈ 15 * 16px
48+
textareaRef.current.style.height = `${newHeight}px`;
49+
}
50+
}, [input]);
51+
3852
return (
3953
<textarea
4054
ref={textareaRef}
4155
autoFocus
4256
autoComplete="off"
4357
autoCapitalize="none"
4458
spellCheck="false"
45-
className="text-base flex-1 outline-none min-w-[200px] text-[#333] dark:text-[#d8d8d8] placeholder-text-xs placeholder-[#999] dark:placeholder-gray-500 bg-transparent"
59+
className="text-base flex-1 outline-none min-w-[200px] text-[#333] dark:text-[#d8d8d8] placeholder-text-xs placeholder-[#999] dark:placeholder-gray-500 bg-transparent custom-scrollbar"
4660
placeholder={
4761
connected ? chatPlaceholder || t("search.textarea.placeholder") : ""
4862
}
@@ -58,7 +72,7 @@ const AutoResizeTextarea = forwardRef<
5872
style={{
5973
resize: "none", // Prevent manual resize
6074
overflow: "auto", // Enable scrollbars when needed
61-
maxHeight: "4.5rem", // Limit height to 3 rows (3 * 1.5 line-height)
75+
maxHeight: "15rem", // Limit height to 10 rows (10 * 1.5 line-height)
6276
lineHeight: "1.5rem", // Line height to match row height
6377
}}
6478
/>

src/components/Search/InputBox.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ export default function ChatInput({
434434

435435
<div
436436
data-tauri-drag-region
437-
className="flex justify-between items-center py-2"
437+
className="flex justify-between items-center pt-2"
438438
>
439439
{isChatMode ? (
440440
<div className="flex gap-2 text-[12px] leading-3 text-[#333] dark:text-[#d8d8d8]">

src/components/SearchChat/index.tsx

Lines changed: 43 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ function SearchChat({
337337
<div
338338
data-tauri-drag-region={isTauri}
339339
className={clsx(
340-
"m-auto overflow-hidden relative bg-no-repeat bg-cover bg-center bg-white dark:bg-black",
340+
"m-auto overflow-hidden relative bg-no-repeat bg-cover bg-center bg-white dark:bg-black flex flex-col",
341341
[
342342
isTransitioned
343343
? "bg-chat_bg_light dark:bg-chat_bg_dark"
@@ -353,12 +353,31 @@ function SearchChat({
353353
)}
354354
style={{ opacity: blurred ? opacity / 100 : 1 }}
355355
>
356+
{isTransitioned && (
357+
<div
358+
data-tauri-drag-region={isTauri}
359+
className="flex-1 w-full overflow-hidden"
360+
>
361+
<Suspense fallback={<LoadingFallback />}>
362+
<ChatAI
363+
ref={chatAIRef}
364+
key="ChatAI"
365+
changeInput={setInput}
366+
isSearchActive={isSearchActive}
367+
isDeepThinkActive={isDeepThinkActive}
368+
isMCPActive={isMCPActive}
369+
getFileUrl={getFileUrl}
370+
showChatHistory={showChatHistory}
371+
assistantIDs={assistantIDs}
372+
/>
373+
</Suspense>
374+
</div>
375+
)}
376+
356377
<div
357378
data-tauri-drag-region={isTauri}
358-
className={`p-2 absolute w-full flex justify-center transition-all duration-500 ${
359-
isTransitioned
360-
? "top-[calc(100%-82px)] h-[82px] border-t"
361-
: "top-0 h-[82px] border-b"
379+
className={`p-2 w-full flex justify-center transition-all duration-500 min-h-[82px] ${
380+
isTransitioned ? "border-t" : "border-b"
362381
} border-[#E6E6E6] dark:border-[#272626]`}
363382
>
364383
<InputBox
@@ -395,48 +414,25 @@ function SearchChat({
395414
/>
396415
</div>
397416

398-
<div
399-
data-tauri-drag-region={isTauri}
400-
className={`absolute w-full transition-opacity duration-500 ${
401-
isTransitioned ? "opacity-0 pointer-events-none" : "opacity-100"
402-
} bottom-0 h-[calc(100%-82px)] `}
403-
>
404-
<Suspense fallback={<LoadingFallback />}>
405-
<Search
406-
key="Search"
407-
isTauri={isTauri}
408-
input={input}
409-
isChatMode={isChatMode}
410-
changeInput={setInput}
411-
hideCoco={hideCoco}
412-
openSetting={openSetting}
413-
setWindowAlwaysOnTop={setWindowAlwaysOnTop}
414-
/>
415-
</Suspense>
416-
</div>
417-
418-
<div
419-
data-tauri-drag-region={isTauri}
420-
className={`absolute w-full transition-all duration-500 select-auto ${
421-
isTransitioned
422-
? "top-0 opacity-100 pointer-events-auto"
423-
: "-top-[506px] opacity-0 pointer-events-none"
424-
} h-[calc(100%-90px)]`}
425-
>
426-
<Suspense fallback={<LoadingFallback />}>
427-
<ChatAI
428-
ref={chatAIRef}
429-
key="ChatAI"
430-
changeInput={setInput}
431-
isSearchActive={isSearchActive}
432-
isDeepThinkActive={isDeepThinkActive}
433-
isMCPActive={isMCPActive}
434-
getFileUrl={getFileUrl}
435-
showChatHistory={showChatHistory}
436-
assistantIDs={assistantIDs}
437-
/>
438-
</Suspense>
439-
</div>
417+
{!isTransitioned && (
418+
<div
419+
data-tauri-drag-region={isTauri}
420+
className="flex-1 overflow-auto w-full"
421+
>
422+
<Suspense fallback={<LoadingFallback />}>
423+
<Search
424+
key="Search"
425+
isTauri={isTauri}
426+
input={input}
427+
isChatMode={isChatMode}
428+
changeInput={setInput}
429+
hideCoco={hideCoco}
430+
openSetting={openSetting}
431+
setWindowAlwaysOnTop={setWindowAlwaysOnTop}
432+
/>
433+
</Suspense>
434+
</div>
435+
)}
440436

441437
<UpdateApp checkUpdate={checkUpdate} relaunchApp={relaunchApp} />
442438
</div>

src/hooks/useWebSocket.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export default function useWebSocket({
3838

3939
// web
4040
const { readyState, connect, disconnect } = useWebSocketAHook(
41-
// "wss://coco.infini.cloud/ws",
41+
//"wss://coco.infini.cloud/ws",
4242
//"ws://localhost:9000/ws",
4343
isTauri ? "" : endpoint_websocket,
4444
{

0 commit comments

Comments
 (0)