optimize mobile experience

This commit is contained in:
cyhhao 2023-04-02 02:26:42 +08:00
parent 44145f11db
commit a9523f036b
2 changed files with 31 additions and 29 deletions

View File

@ -144,8 +144,10 @@
} }
} }
.chat-item:hover { @media only screen and (min-width: 600px) {
background-color: var(--hover-color); .chat-item:hover {
background-color: var(--hover-color);
}
} }
.chat-item-selected { .chat-item-selected {
@ -170,6 +172,13 @@
opacity: 0; opacity: 0;
} }
@media only screen and (max-width: 600px) {
.chat-item-delete {
right: 10px;
opacity: 0.5;
}
}
.chat-item:hover > .chat-item-delete { .chat-item:hover > .chat-item-delete {
opacity: 0.5; opacity: 0.5;
right: 10px; right: 10px;
@ -422,6 +431,7 @@
@media only screen and (max-width: 600px) { @media only screen and (max-width: 600px) {
.chat-input { .chat-input {
font-size: 16px; font-size: 16px;
padding: 10px 5px;
} }
} }

View File

@ -108,7 +108,7 @@ export function ChatList() {
state.currentSessionIndex, state.currentSessionIndex,
state.selectSession, state.selectSession,
state.removeSession, state.removeSession,
] ],
); );
return ( return (
@ -202,7 +202,7 @@ export function Chat(props: {
setPromptHints(promptStore.search(text)); setPromptHints(promptStore.search(text));
}, },
100, 100,
{ leading: true, trailing: true } { leading: true, trailing: true },
); );
const onPromptSelect = (prompt: Prompt) => { const onPromptSelect = (prompt: Prompt) => {
@ -216,7 +216,7 @@ export function Chat(props: {
if (!dom) return; if (!dom) return;
const paddingBottomNum: number = parseInt( const paddingBottomNum: number = parseInt(
window.getComputedStyle(dom).paddingBottom, window.getComputedStyle(dom).paddingBottom,
10 10,
); );
dom.scrollTop = dom.scrollHeight - dom.offsetHeight + paddingBottomNum; dom.scrollTop = dom.scrollHeight - dom.offsetHeight + paddingBottomNum;
}; };
@ -246,7 +246,7 @@ export function Chat(props: {
chatStore.onUserInput(userInput).then(() => setIsLoading(false)); chatStore.onUserInput(userInput).then(() => setIsLoading(false));
setUserInput(""); setUserInput("");
setPromptHints([]); setPromptHints([]);
inputRef.current?.focus(); if (!isMobileScreen()) inputRef.current?.focus();
}; };
// stop response // stop response
@ -290,6 +290,7 @@ export function Chat(props: {
// for auto-scroll // for auto-scroll
const latestMessageRef = useRef<HTMLDivElement>(null); const latestMessageRef = useRef<HTMLDivElement>(null);
const dialogBoxRef = useRef<HTMLDivElement>(null);
const [autoScroll, setAutoScroll] = useState(true); const [autoScroll, setAutoScroll] = useState(true);
// preview messages // preview messages
@ -304,7 +305,7 @@ export function Chat(props: {
preview: true, preview: true,
}, },
] ]
: [] : [],
) )
.concat( .concat(
userInput.length > 0 userInput.length > 0
@ -316,7 +317,7 @@ export function Chat(props: {
preview: true, preview: true,
}, },
] ]
: [] : [],
); );
// auto scroll // auto scroll
@ -324,6 +325,7 @@ export function Chat(props: {
setTimeout(() => { setTimeout(() => {
const dom = latestMessageRef.current; const dom = latestMessageRef.current;
const inputDom = inputRef.current; const inputDom = inputRef.current;
const dialogBox = dialogBoxRef.current!;
// only scroll when input overlaped message body // only scroll when input overlaped message body
let shouldScroll = true; let shouldScroll = true;
@ -334,8 +336,9 @@ export function Chat(props: {
} }
if (dom && autoScroll && shouldScroll) { if (dom && autoScroll && shouldScroll) {
dom.scrollIntoView({ console.log(dialogBox.scrollHeight, dialogBox.clientHeight);
block: "end", dialogBox.scrollTo({
top: dialogBox.scrollHeight - dialogBox.clientHeight,
}); });
} }
}, 500); }, 500);
@ -354,7 +357,7 @@ export function Chat(props: {
const newTopic = prompt(Locale.Chat.Rename, session.topic); const newTopic = prompt(Locale.Chat.Rename, session.topic);
if (newTopic && newTopic !== session.topic) { if (newTopic && newTopic !== session.topic) {
chatStore.updateCurrentSession( chatStore.updateCurrentSession(
(session) => (session.topic = newTopic!) (session) => (session.topic = newTopic!),
); );
} }
}} }}
@ -397,7 +400,7 @@ export function Chat(props: {
</div> </div>
</div> </div>
<div className={styles["chat-body"]}> <div className={styles["chat-body"]} ref={dialogBoxRef}>
{messages.map((message, i) => { {messages.map((message, i) => {
const isUser = message.role === "user"; const isUser = message.role === "user";
@ -445,8 +448,7 @@ export function Chat(props: {
</div> </div>
</div> </div>
)} )}
{(message.preview || message.content.length === 0) && {message.preview || message.content.length === 0 ? (
!isUser ? (
<LoadingIcon /> <LoadingIcon />
) : ( ) : (
<div <div
@ -484,21 +486,21 @@ export function Chat(props: {
<textarea <textarea
ref={inputRef} ref={inputRef}
className={styles["chat-input"]} className={styles["chat-input"]}
placeholder={Locale.Chat.Input(submitKey)} placeholder={isMobileScreen() ? "" : Locale.Chat.Input(submitKey)}
rows={4} rows={isMobileScreen() ? 2 : 4}
onInput={(e) => onInput(e.currentTarget.value)} onInput={(e) => onInput(e.currentTarget.value)}
value={userInput} value={userInput}
onKeyDown={(e) => onInputKeyDown(e as any)} onKeyDown={(e) => onInputKeyDown(e as any)}
onFocus={() => setAutoScroll(true)} onFocus={() => setAutoScroll(true)}
onBlur={() => { onBlur={() => {
setAutoScroll(false); if (!isMobileScreen()) setAutoScroll(false);
setTimeout(() => setPromptHints([]), 500); setTimeout(() => setPromptHints([]), 500);
}} }}
autoFocus={!props?.sideBarShowing} autoFocus={!props?.sideBarShowing}
/> />
<IconButton <IconButton
icon={<SendWhiteIcon />} icon={<SendWhiteIcon />}
text={Locale.Chat.Send} text={isMobileScreen() ? "" : Locale.Chat.Send}
className={styles["chat-input-send"] + " no-dark"} className={styles["chat-input-send"] + " no-dark"}
onClick={onUserSubmit} onClick={onUserSubmit}
/> />
@ -603,7 +605,7 @@ export function Home() {
state.newSession, state.newSession,
state.currentSessionIndex, state.currentSessionIndex,
state.removeSession, state.removeSession,
] ],
); );
const loading = !useHasHydrated(); const loading = !useHasHydrated();
const [showSideBar, setShowSideBar] = useState(true); const [showSideBar, setShowSideBar] = useState(true);
@ -651,16 +653,6 @@ export function Home() {
<div className={styles["sidebar-tail"]}> <div className={styles["sidebar-tail"]}>
<div className={styles["sidebar-actions"]}> <div className={styles["sidebar-actions"]}>
<div className={styles["sidebar-action"] + " " + styles.mobile}>
<IconButton
icon={<CloseIcon />}
onClick={() => {
if (confirm(Locale.Home.DeleteChat)) {
removeSession(currentIndex);
}
}}
/>
</div>
<div className={styles["sidebar-action"]}> <div className={styles["sidebar-action"]}>
<IconButton <IconButton
icon={<SettingsIcon />} icon={<SettingsIcon />}