mirror of
https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web.git
synced 2025-11-13 04:33:42 +08:00
Merge remote-tracking branch 'upstream/main'
This commit is contained in:
@@ -648,39 +648,6 @@
|
||||
bottom: 32px;
|
||||
}
|
||||
|
||||
.chat-input-image {
|
||||
background-color: var(--primary);
|
||||
color: white;
|
||||
|
||||
position: absolute;
|
||||
right: 28px;
|
||||
bottom: 78px;
|
||||
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.chat-input-image-close {
|
||||
background-color: white;
|
||||
fill: black;
|
||||
border: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
width: 22px;
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
.chat-input-image-close:hover {
|
||||
background-color: #f3f3f3;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 600px) {
|
||||
.chat-input {
|
||||
font-size: 16px;
|
||||
@@ -689,4 +656,4 @@
|
||||
.chat-input-send {
|
||||
bottom: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,7 +90,6 @@ import {
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import {
|
||||
CHAT_PAGE_SIZE,
|
||||
LAST_INPUT_IMAGE_KEY,
|
||||
LAST_INPUT_KEY,
|
||||
ModelProvider,
|
||||
Path,
|
||||
@@ -105,7 +104,6 @@ import { prettyObject } from "../utils/format";
|
||||
import { ExportMessageModal } from "./exporter";
|
||||
import { getClientConfig } from "../config/client";
|
||||
import { useAllModels } from "../utils/hooks";
|
||||
import Image from "next/image";
|
||||
import { ClientApi } from "../client/api";
|
||||
import { createTTSPlayer } from "../utils/audio";
|
||||
import { MultimodalContent } from "../client/api";
|
||||
@@ -455,7 +453,6 @@ export function ChatActions(props: {
|
||||
showPromptModal: () => void;
|
||||
scrollToBottom: () => void;
|
||||
showPromptHints: () => void;
|
||||
imageSelected: (img: any) => void;
|
||||
hitBottom: boolean;
|
||||
uploading: boolean;
|
||||
}) {
|
||||
@@ -717,7 +714,6 @@ function _Chat() {
|
||||
|
||||
const inputRef = useRef<HTMLTextAreaElement>(null);
|
||||
const [userInput, setUserInput] = useState("");
|
||||
const [userImage, setUserImage] = useState<any>();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const { submitKey, shouldSubmit } = useSubmitHandler();
|
||||
const scrollRef = useRef<HTMLDivElement>(null);
|
||||
@@ -803,7 +799,7 @@ function _Chat() {
|
||||
}
|
||||
};
|
||||
|
||||
const doSubmit = (userInput: string, userImage?: any) => {
|
||||
const doSubmit = (userInput: string) => {
|
||||
if (userInput.trim() === "") return;
|
||||
const matchCommand = chatCommands.match(userInput);
|
||||
if (matchCommand.matched) {
|
||||
@@ -818,10 +814,8 @@ function _Chat() {
|
||||
.then(() => setIsLoading(false));
|
||||
setAttachImages([]);
|
||||
localStorage.setItem(LAST_INPUT_KEY, userInput);
|
||||
localStorage.setItem(LAST_INPUT_IMAGE_KEY, userImage);
|
||||
setUserInput("");
|
||||
setPromptHints([]);
|
||||
setUserImage(null);
|
||||
if (!isMobileScreen) inputRef.current?.focus();
|
||||
setAutoScroll(true);
|
||||
};
|
||||
@@ -886,12 +880,11 @@ function _Chat() {
|
||||
!(e.metaKey || e.altKey || e.ctrlKey)
|
||||
) {
|
||||
setUserInput(localStorage.getItem(LAST_INPUT_KEY) ?? "");
|
||||
setUserImage(localStorage.getItem(LAST_INPUT_IMAGE_KEY));
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
if (shouldSubmit(e) && promptHints.length === 0) {
|
||||
doSubmit(userInput, userImage);
|
||||
doSubmit(userInput);
|
||||
e.preventDefault();
|
||||
}
|
||||
};
|
||||
@@ -1069,7 +1062,6 @@ function _Chat() {
|
||||
isLoading,
|
||||
session.messages,
|
||||
userInput,
|
||||
userImage?.fileUrl,
|
||||
]);
|
||||
|
||||
const [msgRenderIndex, _setMsgRenderIndex] = useState(
|
||||
@@ -1283,8 +1275,6 @@ function _Chat() {
|
||||
setAttachImages(images);
|
||||
}
|
||||
|
||||
const textareaMinHeight = userImage ? 121 : 68;
|
||||
|
||||
return (
|
||||
<div className={styles.chat} key={session.id}>
|
||||
<div className="window-header" data-tauri-drag-region>
|
||||
@@ -1574,19 +1564,6 @@ function _Chat() {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{!isUser && message.model?.includes("vision") && (
|
||||
<div
|
||||
className={[
|
||||
styles["chat-message-actions"],
|
||||
styles["column-flex"],
|
||||
].join(" ")}
|
||||
>
|
||||
<div
|
||||
style={{ marginTop: "6px" }}
|
||||
className={styles["chat-input-actions"]}
|
||||
></div>
|
||||
</div>
|
||||
)}
|
||||
<div className={styles["chat-message-action-date"]}>
|
||||
{isContext
|
||||
? Locale.Chat.IsContext
|
||||
@@ -1622,9 +1599,6 @@ function _Chat() {
|
||||
setUserInput("/");
|
||||
onSearch("");
|
||||
}}
|
||||
imageSelected={(img: any) => {
|
||||
setUserImage(img);
|
||||
}}
|
||||
/>
|
||||
<label
|
||||
className={`${styles["chat-input-panel-inner"]} ${
|
||||
@@ -1649,7 +1623,6 @@ function _Chat() {
|
||||
autoFocus={autoFocus}
|
||||
style={{
|
||||
fontSize: config.fontSize,
|
||||
minHeight: textareaMinHeight,
|
||||
}}
|
||||
/>
|
||||
{attachImages.length != 0 && (
|
||||
@@ -1680,7 +1653,7 @@ function _Chat() {
|
||||
text={Locale.Chat.Send}
|
||||
className={styles["chat-input-send"]}
|
||||
type="primary"
|
||||
onClick={() => doSubmit(userInput, userImage)}
|
||||
onClick={() => doSubmit(userInput)}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@@ -116,41 +116,38 @@ function escapeDollarNumber(text: string) {
|
||||
return escapedText;
|
||||
}
|
||||
|
||||
function _MarkDownContent(props: { content: string; imageBase64?: string }) {
|
||||
function _MarkDownContent(props: { content: string }) {
|
||||
const escapedContent = useMemo(
|
||||
() => escapeDollarNumber(props.content),
|
||||
[props.content],
|
||||
);
|
||||
|
||||
return (
|
||||
<div style={{ fontSize: "inherit" }}>
|
||||
{props.imageBase64 && <img src={props.imageBase64} alt="" />}
|
||||
<ReactMarkdown
|
||||
remarkPlugins={[RemarkMath, RemarkGfm, RemarkBreaks]}
|
||||
rehypePlugins={[
|
||||
RehypeKatex,
|
||||
[
|
||||
RehypeHighlight,
|
||||
{
|
||||
detect: false,
|
||||
ignoreMissing: true,
|
||||
},
|
||||
],
|
||||
]}
|
||||
components={{
|
||||
pre: PreCode,
|
||||
p: (pProps) => <p {...pProps} dir="auto" />,
|
||||
a: (aProps) => {
|
||||
const href = aProps.href || "";
|
||||
const isInternal = /^\/#/i.test(href);
|
||||
const target = isInternal ? "_self" : aProps.target ?? "_blank";
|
||||
return <a {...aProps} target={target} />;
|
||||
<ReactMarkdown
|
||||
remarkPlugins={[RemarkMath, RemarkGfm, RemarkBreaks]}
|
||||
rehypePlugins={[
|
||||
RehypeKatex,
|
||||
[
|
||||
RehypeHighlight,
|
||||
{
|
||||
detect: false,
|
||||
ignoreMissing: true,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{escapedContent}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
],
|
||||
]}
|
||||
components={{
|
||||
pre: PreCode,
|
||||
p: (pProps) => <p {...pProps} dir="auto" />,
|
||||
a: (aProps) => {
|
||||
const href = aProps.href || "";
|
||||
const isInternal = /^\/#/i.test(href);
|
||||
const target = isInternal ? "_self" : aProps.target ?? "_blank";
|
||||
return <a {...aProps} target={target} />;
|
||||
},
|
||||
}}
|
||||
>
|
||||
{escapedContent}
|
||||
</ReactMarkdown>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -163,10 +160,10 @@ export function Markdown(
|
||||
fontSize?: number;
|
||||
parentRef?: RefObject<HTMLDivElement>;
|
||||
defaultShow?: boolean;
|
||||
imageBase64?: string;
|
||||
} & React.DOMAttributes<HTMLDivElement>,
|
||||
) {
|
||||
const mdRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
return (
|
||||
<div
|
||||
className="markdown-body"
|
||||
@@ -181,10 +178,7 @@ export function Markdown(
|
||||
{props.loading ? (
|
||||
<LoadingIcon />
|
||||
) : (
|
||||
<MarkdownContent
|
||||
content={props.content}
|
||||
imageBase64={props.imageBase64}
|
||||
/>
|
||||
<MarkdownContent content={props.content} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user