mirror of
https://github.com/Yidadaa/ChatGPT-Next-Web.git
synced 2025-08-07 17:18:21 +08:00
feat: close #680 lazy rendering markdown
This commit is contained in:
@@ -14,6 +14,11 @@ import DeleteIcon from "../icons/delete.svg";
|
||||
import MaxIcon from "../icons/max.svg";
|
||||
import MinIcon from "../icons/min.svg";
|
||||
|
||||
import LightIcon from "../icons/light.svg";
|
||||
import DarkIcon from "../icons/dark.svg";
|
||||
import AutoIcon from "../icons/auto.svg";
|
||||
import BottomIcon from "../icons/bottom.svg";
|
||||
|
||||
import {
|
||||
Message,
|
||||
SubmitKey,
|
||||
@@ -22,6 +27,7 @@ import {
|
||||
ROLES,
|
||||
createMessage,
|
||||
useAccessStore,
|
||||
Theme,
|
||||
} from "../store";
|
||||
|
||||
import {
|
||||
@@ -31,6 +37,7 @@ import {
|
||||
isMobileScreen,
|
||||
selectOrCopy,
|
||||
autoGrowTextArea,
|
||||
getCSSVar,
|
||||
} from "../utils";
|
||||
|
||||
import dynamic from "next/dynamic";
|
||||
@@ -60,7 +67,11 @@ export function Avatar(props: { role: Message["role"] }) {
|
||||
const config = useChatStore((state) => state.config);
|
||||
|
||||
if (props.role !== "user") {
|
||||
return <BotIcon className={styles["user-avtar"]} />;
|
||||
return (
|
||||
<div className="no-dark">
|
||||
<BotIcon className={styles["user-avtar"]} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -316,22 +327,78 @@ function useScrollToBottom() {
|
||||
// for auto-scroll
|
||||
const scrollRef = useRef<HTMLDivElement>(null);
|
||||
const [autoScroll, setAutoScroll] = useState(true);
|
||||
const scrollToBottom = () => {
|
||||
const dom = scrollRef.current;
|
||||
if (dom) {
|
||||
setTimeout(() => (dom.scrollTop = dom.scrollHeight), 1);
|
||||
}
|
||||
};
|
||||
|
||||
// auto scroll
|
||||
useLayoutEffect(() => {
|
||||
const dom = scrollRef.current;
|
||||
if (dom && autoScroll) {
|
||||
setTimeout(() => (dom.scrollTop = dom.scrollHeight), 1);
|
||||
}
|
||||
autoScroll && scrollToBottom();
|
||||
});
|
||||
|
||||
return {
|
||||
scrollRef,
|
||||
autoScroll,
|
||||
setAutoScroll,
|
||||
scrollToBottom,
|
||||
};
|
||||
}
|
||||
|
||||
export function ChatActions(props: {
|
||||
showPromptModal: () => void;
|
||||
scrollToBottom: () => void;
|
||||
hitBottom: boolean;
|
||||
}) {
|
||||
const chatStore = useChatStore();
|
||||
|
||||
const theme = chatStore.config.theme;
|
||||
|
||||
function nextTheme() {
|
||||
const themes = [Theme.Auto, Theme.Light, Theme.Dark];
|
||||
const themeIndex = themes.indexOf(theme);
|
||||
const nextIndex = (themeIndex + 1) % themes.length;
|
||||
const nextTheme = themes[nextIndex];
|
||||
chatStore.updateConfig((config) => (config.theme = nextTheme));
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={chatStyle["chat-input-actions"]}>
|
||||
{!props.hitBottom && (
|
||||
<div
|
||||
className={`${chatStyle["chat-input-action"]} clickable`}
|
||||
onClick={props.scrollToBottom}
|
||||
>
|
||||
<BottomIcon />
|
||||
</div>
|
||||
)}
|
||||
{props.hitBottom && (
|
||||
<div
|
||||
className={`${chatStyle["chat-input-action"]} clickable`}
|
||||
onClick={props.showPromptModal}
|
||||
>
|
||||
<BrainIcon />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div
|
||||
className={`${chatStyle["chat-input-action"]} clickable`}
|
||||
onClick={nextTheme}
|
||||
>
|
||||
{theme === Theme.Auto ? (
|
||||
<AutoIcon />
|
||||
) : theme === Theme.Light ? (
|
||||
<LightIcon />
|
||||
) : theme === Theme.Dark ? (
|
||||
<DarkIcon />
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function Chat(props: {
|
||||
showSideBar?: () => void;
|
||||
sideBarShowing?: boolean;
|
||||
@@ -350,7 +417,7 @@ export function Chat(props: {
|
||||
const [beforeInput, setBeforeInput] = useState("");
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const { submitKey, shouldSubmit } = useSubmitHandler();
|
||||
const { scrollRef, setAutoScroll } = useScrollToBottom();
|
||||
const { scrollRef, setAutoScroll, scrollToBottom } = useScrollToBottom();
|
||||
const [hitBottom, setHitBottom] = useState(false);
|
||||
|
||||
const onChatBodyScroll = (e: HTMLElement) => {
|
||||
@@ -683,6 +750,8 @@ export function Chat(props: {
|
||||
if (!isMobileScreen()) return;
|
||||
setUserInput(message.content);
|
||||
}}
|
||||
fontSize={fontSize}
|
||||
parentRef={scrollRef}
|
||||
/>
|
||||
</div>
|
||||
{!isUser && !message.preview && (
|
||||
@@ -700,6 +769,12 @@ export function Chat(props: {
|
||||
|
||||
<div className={styles["chat-input-panel"]}>
|
||||
<PromptHints prompts={promptHints} onPromptSelect={onPromptSelect} />
|
||||
|
||||
<ChatActions
|
||||
showPromptModal={() => setShowPromptModal(true)}
|
||||
scrollToBottom={scrollToBottom}
|
||||
hitBottom={hitBottom}
|
||||
/>
|
||||
<div className={styles["chat-input-panel-inner"]}>
|
||||
<textarea
|
||||
ref={inputRef}
|
||||
|
Reference in New Issue
Block a user