|
@@ -23,7 +23,13 @@ import DownloadIcon from "../icons/download.svg";
|
|
|
|
|
|
import { Message, SubmitKey, useChatStore, ChatSession } from "../store";
|
|
|
import { showModal, showToast } from "./ui-lib";
|
|
|
-import { copyToClipboard, downloadAs, isIOS, selectOrCopy } from "../utils";
|
|
|
+import {
|
|
|
+ copyToClipboard,
|
|
|
+ downloadAs,
|
|
|
+ isIOS,
|
|
|
+ isMobileScreen,
|
|
|
+ selectOrCopy,
|
|
|
+} from "../utils";
|
|
|
import Locale from "../locales";
|
|
|
|
|
|
import dynamic from "next/dynamic";
|
|
@@ -102,7 +108,7 @@ export function ChatList() {
|
|
|
state.currentSessionIndex,
|
|
|
state.selectSession,
|
|
|
state.removeSession,
|
|
|
- ]
|
|
|
+ ],
|
|
|
);
|
|
|
|
|
|
return (
|
|
@@ -196,7 +202,7 @@ export function Chat(props: {
|
|
|
setPromptHints(promptStore.search(text));
|
|
|
},
|
|
|
100,
|
|
|
- { leading: true, trailing: true }
|
|
|
+ { leading: true, trailing: true },
|
|
|
);
|
|
|
|
|
|
const onPromptSelect = (prompt: Prompt) => {
|
|
@@ -210,7 +216,7 @@ export function Chat(props: {
|
|
|
if (!dom) return;
|
|
|
const paddingBottomNum: number = parseInt(
|
|
|
window.getComputedStyle(dom).paddingBottom,
|
|
|
- 10
|
|
|
+ 10,
|
|
|
);
|
|
|
dom.scrollTop = dom.scrollHeight - dom.offsetHeight + paddingBottomNum;
|
|
|
};
|
|
@@ -284,9 +290,7 @@ export function Chat(props: {
|
|
|
|
|
|
// for auto-scroll
|
|
|
const latestMessageRef = useRef<HTMLDivElement>(null);
|
|
|
-
|
|
|
- // wont scroll while hovering messages
|
|
|
- const [autoScroll, setAutoScroll] = useState(false);
|
|
|
+ const [autoScroll, setAutoScroll] = useState(true);
|
|
|
|
|
|
// preview messages
|
|
|
const messages = (session.messages as RenderMessage[])
|
|
@@ -300,7 +304,7 @@ export function Chat(props: {
|
|
|
preview: true,
|
|
|
},
|
|
|
]
|
|
|
- : []
|
|
|
+ : [],
|
|
|
)
|
|
|
.concat(
|
|
|
userInput.length > 0
|
|
@@ -312,14 +316,24 @@ export function Chat(props: {
|
|
|
preview: true,
|
|
|
},
|
|
|
]
|
|
|
- : []
|
|
|
+ : [],
|
|
|
);
|
|
|
|
|
|
// auto scroll
|
|
|
useLayoutEffect(() => {
|
|
|
setTimeout(() => {
|
|
|
const dom = latestMessageRef.current;
|
|
|
- if (dom && !isIOS() && autoScroll) {
|
|
|
+ const inputDom = inputRef.current;
|
|
|
+
|
|
|
+ // only scroll when input overlaped message body
|
|
|
+ let shouldScroll = true;
|
|
|
+ if (dom && inputDom) {
|
|
|
+ const domRect = dom.getBoundingClientRect();
|
|
|
+ const inputRect = inputDom.getBoundingClientRect();
|
|
|
+ shouldScroll = domRect.top > inputRect.top;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (dom && autoScroll && shouldScroll) {
|
|
|
dom.scrollIntoView({
|
|
|
block: "end",
|
|
|
});
|
|
@@ -340,7 +354,7 @@ export function Chat(props: {
|
|
|
const newTopic = prompt(Locale.Chat.Rename, session.topic);
|
|
|
if (newTopic && newTopic !== session.topic) {
|
|
|
chatStore.updateCurrentSession(
|
|
|
- (session) => (session.topic = newTopic!)
|
|
|
+ (session) => (session.topic = newTopic!),
|
|
|
);
|
|
|
}
|
|
|
}}
|
|
@@ -475,7 +489,7 @@ export function Chat(props: {
|
|
|
onFocus={() => setAutoScroll(true)}
|
|
|
onBlur={() => {
|
|
|
setAutoScroll(false);
|
|
|
- setTimeout(() => setPromptHints([]), 100);
|
|
|
+ setTimeout(() => setPromptHints([]), 500);
|
|
|
}}
|
|
|
autoFocus={!props?.sideBarShowing}
|
|
|
/>
|
|
@@ -586,7 +600,7 @@ export function Home() {
|
|
|
state.newSession,
|
|
|
state.currentSessionIndex,
|
|
|
state.removeSession,
|
|
|
- ]
|
|
|
+ ],
|
|
|
);
|
|
|
const loading = !useHasHydrated();
|
|
|
const [showSideBar, setShowSideBar] = useState(true);
|
|
@@ -604,7 +618,9 @@ export function Home() {
|
|
|
return (
|
|
|
<div
|
|
|
className={`${
|
|
|
- config.tightBorder ? styles["tight-container"] : styles.container
|
|
|
+ config.tightBorder && !isMobileScreen()
|
|
|
+ ? styles["tight-container"]
|
|
|
+ : styles.container
|
|
|
}`}
|
|
|
>
|
|
|
<div
|