forked from XiaoMo/ChatGPT-Next-Web
feat: close #1055 cmd/alt/ctrl + arrow up/down to switch window
This commit is contained in:
parent
9b1f25140e
commit
2b7f72deec
@ -53,7 +53,7 @@ import chatStyle from "./chat.module.scss";
|
|||||||
|
|
||||||
import { ListItem, Modal, showModal } from "./ui-lib";
|
import { ListItem, Modal, showModal } from "./ui-lib";
|
||||||
import { useLocation, useNavigate } from "react-router-dom";
|
import { useLocation, useNavigate } from "react-router-dom";
|
||||||
import { Path } from "../constant";
|
import { LAST_INPUT_KEY, Path } from "../constant";
|
||||||
import { Avatar } from "./emoji";
|
import { Avatar } from "./emoji";
|
||||||
import { MaskAvatar, MaskConfig } from "./mask";
|
import { MaskAvatar, MaskConfig } from "./mask";
|
||||||
import { useMaskStore } from "../store/mask";
|
import { useMaskStore } from "../store/mask";
|
||||||
@ -404,7 +404,6 @@ export function Chat() {
|
|||||||
|
|
||||||
const inputRef = useRef<HTMLTextAreaElement>(null);
|
const inputRef = useRef<HTMLTextAreaElement>(null);
|
||||||
const [userInput, setUserInput] = useState("");
|
const [userInput, setUserInput] = useState("");
|
||||||
const [beforeInput, setBeforeInput] = useState("");
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const { submitKey, shouldSubmit } = useSubmitHandler();
|
const { submitKey, shouldSubmit } = useSubmitHandler();
|
||||||
const { scrollRef, setAutoScroll, scrollToBottom } = useScrollToBottom();
|
const { scrollRef, setAutoScroll, scrollToBottom } = useScrollToBottom();
|
||||||
@ -477,7 +476,7 @@ export function Chat() {
|
|||||||
if (userInput.trim() === "") return;
|
if (userInput.trim() === "") return;
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
chatStore.onUserInput(userInput).then(() => setIsLoading(false));
|
chatStore.onUserInput(userInput).then(() => setIsLoading(false));
|
||||||
setBeforeInput(userInput);
|
localStorage.setItem(LAST_INPUT_KEY, userInput);
|
||||||
setUserInput("");
|
setUserInput("");
|
||||||
setPromptHints([]);
|
setPromptHints([]);
|
||||||
if (!isMobileScreen) inputRef.current?.focus();
|
if (!isMobileScreen) inputRef.current?.focus();
|
||||||
@ -491,9 +490,9 @@ export function Chat() {
|
|||||||
|
|
||||||
// check if should send message
|
// check if should send message
|
||||||
const onInputKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
const onInputKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
||||||
// if ArrowUp and no userInput
|
// if ArrowUp and no userInput, fill with last input
|
||||||
if (e.key === "ArrowUp" && userInput.length <= 0) {
|
if (e.key === "ArrowUp" && userInput.length <= 0) {
|
||||||
setUserInput(beforeInput);
|
setUserInput(localStorage.getItem(LAST_INPUT_KEY) ?? "");
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -503,11 +502,6 @@ export function Chat() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
const onRightClick = (e: any, message: Message) => {
|
const onRightClick = (e: any, message: Message) => {
|
||||||
// auto fill user input
|
|
||||||
if (message.role === "user") {
|
|
||||||
setUserInput(message.content);
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy to clipboard
|
// copy to clipboard
|
||||||
if (selectOrCopy(e.currentTarget, message.content)) {
|
if (selectOrCopy(e.currentTarget, message.content)) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
@ -32,6 +32,28 @@ const ChatList = dynamic(async () => (await import("./chat-list")).ChatList, {
|
|||||||
loading: () => null,
|
loading: () => null,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function useHotKey() {
|
||||||
|
const chatStore = useChatStore();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const onKeyDown = (e: KeyboardEvent) => {
|
||||||
|
if (e.metaKey || e.altKey || e.ctrlKey) {
|
||||||
|
const n = chatStore.sessions.length;
|
||||||
|
const limit = (x: number) => (x + n) % n;
|
||||||
|
const i = chatStore.currentSessionIndex;
|
||||||
|
if (e.key === "ArrowUp") {
|
||||||
|
chatStore.selectSession(limit(i - 1));
|
||||||
|
} else if (e.key === "ArrowDown") {
|
||||||
|
chatStore.selectSession(limit(i + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener("keydown", onKeyDown);
|
||||||
|
return () => window.removeEventListener("keydown", onKeyDown);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function useDragSideBar() {
|
function useDragSideBar() {
|
||||||
const limit = (x: number) => Math.min(MAX_SIDEBAR_WIDTH, x);
|
const limit = (x: number) => Math.min(MAX_SIDEBAR_WIDTH, x);
|
||||||
|
|
||||||
@ -86,9 +108,10 @@ export function SideBar(props: { className?: string }) {
|
|||||||
// drag side bar
|
// drag side bar
|
||||||
const { onDragMouseDown, shouldNarrow } = useDragSideBar();
|
const { onDragMouseDown, shouldNarrow } = useDragSideBar();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const config = useAppConfig();
|
const config = useAppConfig();
|
||||||
|
|
||||||
|
useHotKey();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`${styles.sidebar} ${props.className} ${
|
className={`${styles.sidebar} ${props.className} ${
|
||||||
|
@ -38,3 +38,5 @@ export const MIN_SIDEBAR_WIDTH = 230;
|
|||||||
export const NARROW_SIDEBAR_WIDTH = 100;
|
export const NARROW_SIDEBAR_WIDTH = 100;
|
||||||
|
|
||||||
export const ACCESS_CODE_PREFIX = "ak-";
|
export const ACCESS_CODE_PREFIX = "ak-";
|
||||||
|
|
||||||
|
export const LAST_INPUT_KEY = "last-input";
|
||||||
|
Loading…
Reference in New Issue
Block a user