Skip to content

Commit d52ce48

Browse files
authored
feat: the search input box supports multi-line input (#501)
* feat: the search input box supports multi-line input * docs: update notes
1 parent 573e1cf commit d52ce48

3 files changed

Lines changed: 33 additions & 58 deletions

File tree

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Information about release notes of Coco Server is provided here.
2121
- feat: the chat input box supports multi-line input #490
2222
- feat: add `~/Applications` to the search path #493
2323
- feat: the chat content has added a button to return to the bottom #495
24+
- feat: the search input box supports multi-line input #501
2425

2526
### 🐛 Bug fix
2627

src/components/Search/DropdownList.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ function DropdownList({
205205
<CircleAlert className="text-[#FF0000] size-3" />
206206
{t("search.list.failures")}
207207

208-
<Tooltip content={IsError} position="left">
208+
<Tooltip content={IsError} position="bottom">
209209
<Ellipsis className="dark:text-white size-3 cursor-pointer" />
210210
</Tooltip>
211211

@@ -221,6 +221,7 @@ function DropdownList({
221221
/>
222222
</div>
223223
)}
224+
224225
{Object.entries(SearchData).map(([sourceName, items]) => {
225226
const showHeader = Object.entries(SearchData).length < 5;
226227

src/components/Search/InputBox.tsx

Lines changed: 30 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { ArrowBigLeft, Search, Send, Brain } from "lucide-react";
22
import { useCallback, useEffect, useRef, useState } from "react";
33
import { useTranslation } from "react-i18next";
44
import clsx from "clsx";
5-
import { useBoolean, useKeyPress } from "ahooks";
5+
import { useKeyPress } from "ahooks";
66

77
import ChatSwitch from "@/components/Common/ChatSwitch";
88
import AutoResizeTextarea from "./AutoResizeTextarea";
@@ -108,7 +108,6 @@ export default function ChatInput({
108108
const modeSwitch = useShortcutsStore((state) => state.modeSwitch);
109109
const returnToInput = useShortcutsStore((state) => state.returnToInput);
110110
const deepThinking = useShortcutsStore((state) => state.deepThinking);
111-
const [isComposition, { setTrue, setFalse }] = useBoolean();
112111

113112
useEffect(() => {
114113
return () => {
@@ -119,7 +118,6 @@ export default function ChatInput({
119118
};
120119
}, []);
121120

122-
const inputRef = useRef<HTMLInputElement>(null);
123121
const textareaRef = useRef<{ reset: () => void; focus: () => void }>(null);
124122

125123
const { curChatEnd, connected } = useChatStore();
@@ -160,12 +158,8 @@ export default function ChatInput({
160158
}, []);
161159

162160
const handleToggleFocus = useCallback(() => {
163-
if (isChatMode) {
164-
textareaRef.current?.focus();
165-
} else {
166-
inputRef.current?.focus();
167-
}
168-
}, [isChatMode, textareaRef, inputRef]);
161+
textareaRef.current?.focus();
162+
}, [isChatMode, textareaRef]);
169163

170164
const handleSubmit = useCallback(() => {
171165
const trimmedValue = inputValue.trim();
@@ -258,11 +252,7 @@ export default function ChatInput({
258252
let unlisten: (() => void) | undefined;
259253

260254
setupWindowFocusListener(() => {
261-
if (isChatMode) {
262-
textareaRef.current?.focus();
263-
} else {
264-
inputRef.current?.focus();
265-
}
255+
textareaRef.current?.focus();
266256
}).then((unlistener) => {
267257
unlisten = unlistener;
268258
});
@@ -293,53 +283,36 @@ export default function ChatInput({
293283
/>
294284
) : null}
295285

296-
{isChatMode ? (
297-
<AutoResizeTextarea
298-
ref={textareaRef}
299-
input={inputValue}
300-
setInput={(value: string) => {
301-
changeInput(value);
302-
}}
303-
connected={connected}
304-
handleKeyDown={(e: React.KeyboardEvent<HTMLTextAreaElement>) => {
305-
const { key, shiftKey } = e;
286+
<AutoResizeTextarea
287+
ref={textareaRef}
288+
input={inputValue}
289+
setInput={(value: string) => {
290+
changeInput(value);
306291

307-
if (key !== "Enter" || shiftKey) return;
292+
if (!isChatMode) {
293+
onSend(value);
294+
}
295+
}}
296+
connected={connected}
297+
handleKeyDown={(e: React.KeyboardEvent<HTMLTextAreaElement>) => {
298+
const { key, shiftKey } = e;
308299

309-
e.preventDefault();
310-
handleSubmit();
311-
}}
312-
chatPlaceholder={chatPlaceholder}
313-
/>
314-
) : (
315-
<input
316-
ref={inputRef}
317-
type="text"
318-
autoFocus
319-
autoComplete="off"
320-
autoCapitalize="none"
321-
spellCheck="false"
322-
className="text-base font-normal flex-1 outline-none min-w-[200px] text-[#333] dark:text-[#d8d8d8] placeholder-text-xs placeholder-[#999] dark:placeholder-gray-500 bg-transparent"
323-
placeholder={
324-
searchPlaceholder || t("search.input.searchPlaceholder")
300+
if (key !== "Enter" || shiftKey) return;
301+
302+
e.preventDefault();
303+
handleSubmit();
304+
305+
if (!isChatMode) {
306+
onSend(inputValue);
325307
}
326-
value={inputValue}
327-
onCompositionStart={setTrue}
328-
onCompositionEnd={() => {
329-
setTimeout(setFalse, 0);
330-
}}
331-
onKeyDown={(event) => {
332-
if (event.key !== "Enter") return;
308+
}}
309+
chatPlaceholder={
310+
isChatMode
311+
? chatPlaceholder
312+
: searchPlaceholder || t("search.input.searchPlaceholder")
313+
}
314+
/>
333315

334-
if (isComposition) {
335-
event.stopPropagation();
336-
}
337-
}}
338-
onChange={(e) => {
339-
onSend(e.target.value);
340-
}}
341-
/>
342-
)}
343316
{showTooltip && !isChatMode && sourceData && (
344317
<div className="absolute -top-[5px] left-2">
345318
<VisibleKey shortcut="←" />

0 commit comments

Comments
 (0)