mirror of
				https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web.git
				synced 2025-11-04 16:23:41 +08:00 
			
		
		
		
	feat: close #1055 cmd/alt/ctrl + arrow up/down to switch window
This commit is contained in:
		@@ -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";
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user