forked from XiaoMo/ChatGPT-Next-Web
refactor: #121 trigger auto-cmp with / prefix
This commit is contained in:
parent
73b2ede53a
commit
e606810581
@ -102,7 +102,7 @@ export function ChatList() {
|
||||
state.currentSessionIndex,
|
||||
state.selectSession,
|
||||
state.removeSession,
|
||||
]
|
||||
],
|
||||
);
|
||||
|
||||
return (
|
||||
@ -128,7 +128,7 @@ function useSubmitHandler() {
|
||||
|
||||
const shouldSubmit = (e: KeyboardEvent) => {
|
||||
if (e.key !== "Enter") return false;
|
||||
|
||||
|
||||
return (
|
||||
(config.submitKey === SubmitKey.AltEnter && e.altKey) ||
|
||||
(config.submitKey === SubmitKey.CtrlEnter && e.ctrlKey) ||
|
||||
@ -170,7 +170,10 @@ export function PromptHints(props: {
|
||||
);
|
||||
}
|
||||
|
||||
export function Chat(props: { showSideBar?: () => void, sideBarShowing?: boolean }) {
|
||||
export function Chat(props: {
|
||||
showSideBar?: () => void;
|
||||
sideBarShowing?: boolean;
|
||||
}) {
|
||||
type RenderMessage = Message & { preview?: boolean };
|
||||
|
||||
const chatStore = useChatStore();
|
||||
@ -190,11 +193,10 @@ export function Chat(props: { showSideBar?: () => void, sideBarShowing?: boolean
|
||||
const [promptHints, setPromptHints] = useState<Prompt[]>([]);
|
||||
const onSearch = useDebouncedCallback(
|
||||
(text: string) => {
|
||||
if (chatStore.config.disablePromptHint) return;
|
||||
setPromptHints(promptStore.search(text));
|
||||
},
|
||||
100,
|
||||
{ leading: true, trailing: true }
|
||||
{ leading: true, trailing: true },
|
||||
);
|
||||
|
||||
const onPromptSelect = (prompt: Prompt) => {
|
||||
@ -203,20 +205,31 @@ export function Chat(props: { showSideBar?: () => void, sideBarShowing?: boolean
|
||||
inputRef.current?.focus();
|
||||
};
|
||||
|
||||
const scrollInput = () => {
|
||||
const dom = inputRef.current;
|
||||
if (!dom) return;
|
||||
const paddingBottomNum: number = parseInt(
|
||||
window.getComputedStyle(dom).paddingBottom,
|
||||
10,
|
||||
);
|
||||
dom.scrollTop = dom.scrollHeight - dom.offsetHeight + paddingBottomNum;
|
||||
};
|
||||
|
||||
// only search prompts when user input is short
|
||||
const SEARCH_TEXT_LIMIT = 30;
|
||||
const onInput = (text: string) => {
|
||||
const textareaDom = inputRef.current
|
||||
if (textareaDom) {
|
||||
const paddingBottomNum: number = parseInt(window.getComputedStyle(textareaDom).paddingBottom, 10);
|
||||
textareaDom.scrollTop = textareaDom.scrollHeight - textareaDom.offsetHeight + paddingBottomNum;
|
||||
}
|
||||
scrollInput();
|
||||
setUserInput(text);
|
||||
const n = text.trim().length;
|
||||
if (n === 0 || n > SEARCH_TEXT_LIMIT) {
|
||||
|
||||
// clear search results
|
||||
if (n === 0) {
|
||||
setPromptHints([]);
|
||||
} else {
|
||||
onSearch(text);
|
||||
} else if (!chatStore.config.disablePromptHint && n < SEARCH_TEXT_LIMIT) {
|
||||
// check if need to trigger auto completion
|
||||
if (text.startsWith("/") && text.length > 1) {
|
||||
onSearch(text.slice(1));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -285,7 +298,7 @@ export function Chat(props: { showSideBar?: () => void, sideBarShowing?: boolean
|
||||
preview: true,
|
||||
},
|
||||
]
|
||||
: []
|
||||
: [],
|
||||
)
|
||||
.concat(
|
||||
userInput.length > 0
|
||||
@ -297,7 +310,7 @@ export function Chat(props: { showSideBar?: () => void, sideBarShowing?: boolean
|
||||
preview: true,
|
||||
},
|
||||
]
|
||||
: []
|
||||
: [],
|
||||
);
|
||||
|
||||
// auto scroll
|
||||
@ -380,32 +393,33 @@ export function Chat(props: { showSideBar?: () => void, sideBarShowing?: boolean
|
||||
</div>
|
||||
)}
|
||||
<div className={styles["chat-message-item"]}>
|
||||
{(!isUser && !(message.preview || message.content.length === 0)) && (
|
||||
<div className={styles["chat-message-top-actions"]}>
|
||||
{message.streaming ? (
|
||||
<div
|
||||
className={styles["chat-message-top-action"]}
|
||||
onClick={() => onUserStop(i)}
|
||||
>
|
||||
{Locale.Chat.Actions.Stop}
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
className={styles["chat-message-top-action"]}
|
||||
onClick={() => onResend(i)}
|
||||
>
|
||||
{Locale.Chat.Actions.Retry}
|
||||
</div>
|
||||
)}
|
||||
{!isUser &&
|
||||
!(message.preview || message.content.length === 0) && (
|
||||
<div className={styles["chat-message-top-actions"]}>
|
||||
{message.streaming ? (
|
||||
<div
|
||||
className={styles["chat-message-top-action"]}
|
||||
onClick={() => onUserStop(i)}
|
||||
>
|
||||
{Locale.Chat.Actions.Stop}
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
className={styles["chat-message-top-action"]}
|
||||
onClick={() => onResend(i)}
|
||||
>
|
||||
{Locale.Chat.Actions.Retry}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div
|
||||
className={styles["chat-message-top-action"]}
|
||||
onClick={() => copyToClipboard(message.content)}
|
||||
>
|
||||
{Locale.Chat.Actions.Copy}
|
||||
<div
|
||||
className={styles["chat-message-top-action"]}
|
||||
onClick={() => copyToClipboard(message.content)}
|
||||
>
|
||||
{Locale.Chat.Actions.Copy}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
)}
|
||||
{(message.preview || message.content.length === 0) &&
|
||||
!isUser ? (
|
||||
<LoadingIcon />
|
||||
@ -560,7 +574,7 @@ export function Home() {
|
||||
state.newSession,
|
||||
state.currentSessionIndex,
|
||||
state.removeSession,
|
||||
]
|
||||
],
|
||||
);
|
||||
const loading = !useHasHydrated();
|
||||
const [showSideBar, setShowSideBar] = useState(true);
|
||||
@ -653,7 +667,11 @@ export function Home() {
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<Chat key="chat" showSideBar={() => setShowSideBar(true)} sideBarShowing={showSideBar} />
|
||||
<Chat
|
||||
key="chat"
|
||||
showSideBar={() => setShowSideBar(true)}
|
||||
sideBarShowing={showSideBar}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -77,7 +77,7 @@ const cn = {
|
||||
Prompt: {
|
||||
Disable: {
|
||||
Title: "禁用提示词自动补全",
|
||||
SubTitle: "禁用后将无法自动根据输入补全",
|
||||
SubTitle: "在输入框开头输入 / 即可触发自动补全",
|
||||
},
|
||||
List: "自定义提示词列表",
|
||||
ListCount: (builtin: number, custom: number) =>
|
||||
|
@ -79,7 +79,7 @@ const en: LocaleType = {
|
||||
Prompt: {
|
||||
Disable: {
|
||||
Title: "Disable auto-completion",
|
||||
SubTitle: "After disabling, auto-completion will not be available",
|
||||
SubTitle: "Input / to trigger auto-completion",
|
||||
},
|
||||
List: "Prompt List",
|
||||
ListCount: (builtin: number, custom: number) =>
|
||||
|
@ -20,7 +20,7 @@ const tw: LocaleType = {
|
||||
Retry: "重試",
|
||||
},
|
||||
Typing: "正在輸入…",
|
||||
Input: (submitKey: string) => {
|
||||
Input: (submitKey: string) => {
|
||||
var inputHints = `輸入訊息後,按下 ${submitKey} 鍵即可發送`;
|
||||
if (submitKey === String(SubmitKey.Enter)) {
|
||||
inputHints += ",Shift + Enter 鍵換行";
|
||||
@ -78,7 +78,7 @@ const tw: LocaleType = {
|
||||
Prompt: {
|
||||
Disable: {
|
||||
Title: "停用提示詞自動補全",
|
||||
SubTitle: "若停用後,將無法自動根據輸入進行補全",
|
||||
SubTitle: "在輸入框開頭輸入 / 即可觸發自動補全",
|
||||
},
|
||||
List: "自定義提示詞列表",
|
||||
ListCount: (builtin: number, custom: number) =>
|
||||
@ -124,8 +124,7 @@ const tw: LocaleType = {
|
||||
Prompt: {
|
||||
History: (content: string) =>
|
||||
"這是 AI 與用戶的歷史聊天總結,作為前情提要:" + content,
|
||||
Topic:
|
||||
"直接返回這句話的簡要主題,無須解釋,若無主題,請直接返回「閒聊」",
|
||||
Topic: "直接返回這句話的簡要主題,無須解釋,若無主題,請直接返回「閒聊」",
|
||||
Summarize:
|
||||
"簡要總結一下你和用戶的對話,作為後續的上下文提示 prompt,且字數控制在 50 字以內",
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user