Merge pull request #1220 from Yidadaa/bugfix-0503

feat: #782 select prompt with arrow down / up
This commit is contained in:
Yifei Zhang 2023-05-03 16:26:27 +08:00 committed by GitHub
commit e0053d57f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 62 additions and 22 deletions

View File

@ -54,7 +54,7 @@ import styles from "./home.module.scss";
import chatStyle from "./chat.module.scss";
import { ListItem, Modal, showModal } from "./ui-lib";
import { useNavigate } from "react-router-dom";
import { useLocation, useNavigate } from "react-router-dom";
import { Path } from "../constant";
import { Avatar } from "./emoji";
import { MaskAvatar, MaskConfig } from "./mask";
@ -224,15 +224,63 @@ export function PromptHints(props: {
prompts: Prompt[];
onPromptSelect: (prompt: Prompt) => void;
}) {
if (props.prompts.length === 0) return null;
const noPrompts = props.prompts.length === 0;
const [selectIndex, setSelectIndex] = useState(0);
const selectedRef = useRef<HTMLDivElement>(null);
useEffect(() => {
setSelectIndex(0);
}, [props.prompts.length]);
useEffect(() => {
const onKeyDown = (e: KeyboardEvent) => {
if (noPrompts) return;
// arrow up / down to select prompt
const changeIndex = (delta: number) => {
e.stopPropagation();
e.preventDefault();
const nextIndex = Math.max(
0,
Math.min(props.prompts.length - 1, selectIndex + delta),
);
setSelectIndex(nextIndex);
selectedRef.current?.scrollIntoView({
block: "center",
});
};
if (e.key === "ArrowUp") {
changeIndex(1);
} else if (e.key === "ArrowDown") {
changeIndex(-1);
} else if (e.key === "Enter") {
const selectedPrompt = props.prompts.at(selectIndex);
if (selectedPrompt) {
props.onPromptSelect(selectedPrompt);
}
}
};
window.addEventListener("keydown", onKeyDown);
return () => window.removeEventListener("keydown", onKeyDown);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [noPrompts, selectIndex]);
if (noPrompts) return null;
return (
<div className={styles["prompt-hints"]}>
{props.prompts.map((prompt, i) => (
<div
className={styles["prompt-hint"]}
ref={i === selectIndex ? selectedRef : null}
className={
styles["prompt-hint"] +
` ${i === selectIndex ? styles["prompt-hint-selected"] : ""}`
}
key={prompt.title + i.toString()}
onClick={() => props.onPromptSelect(prompt)}
onMouseEnter={() => setSelectIndex(i)}
>
<div className={styles["hint-title"]}>{prompt.title}</div>
<div className={styles["hint-content"]}>{prompt.content}</div>
@ -370,7 +418,7 @@ export function Chat() {
const navigate = useNavigate();
const onChatBodyScroll = (e: HTMLElement) => {
const isTouchBottom = e.scrollTop + e.clientHeight >= e.scrollHeight - 20;
const isTouchBottom = e.scrollTop + e.clientHeight >= e.scrollHeight - 100;
setHitBottom(isTouchBottom);
};
@ -397,7 +445,7 @@ export function Chat() {
() => {
const rows = inputRef.current ? autoGrowTextArea(inputRef.current) : 1;
const inputRows = Math.min(
5,
20,
Math.max(2 + Number(!isMobileScreen), rows),
);
setInputRows(inputRows);
@ -566,12 +614,9 @@ export function Chat() {
}
};
// Auto focus
useEffect(() => {
if (isMobileScreen) return;
inputRef.current?.focus();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const location = useLocation();
const isChat = location.pathname === Path.Chat;
const autoFocus = !isMobileScreen || isChat; // only focus in chat page
return (
<div className={styles.chat} key={session.id}>
@ -762,16 +807,9 @@ export function Chat() {
value={userInput}
onKeyDown={onInputKeyDown}
onFocus={() => setAutoScroll(true)}
onBlur={() => {
setTimeout(() => {
if (document.activeElement !== inputRef.current) {
setAutoScroll(false);
setPromptHints([]);
}
}, 100);
}}
autoFocus
onBlur={() => setAutoScroll(false)}
rows={inputRows}
autoFocus={autoFocus}
/>
<IconButton
icon={<SendWhiteIcon />}

View File

@ -22,6 +22,7 @@ export const AllLangs = [
export type Lang = (typeof AllLangs)[number];
const LANG_KEY = "lang";
const DEFAULT_LANG = "en";
function getItem(key: string) {
try {
@ -41,7 +42,8 @@ function getLanguage() {
try {
return navigator.language.toLowerCase();
} catch {
return "cn";
console.log("[Lang] failed to detect user lang.");
return DEFAULT_LANG;
}
}
@ -60,7 +62,7 @@ export function getLang(): Lang {
}
}
return "en";
return DEFAULT_LANG;
}
export function changeLang(lang: Lang) {