"use client"; import { useState, useRef, useEffect } from "react"; import ReactMarkdown from "react-markdown"; import "katex/dist/katex.min.css"; import RemarkMath from "remark-math"; import RehypeKatex from "rehype-katex"; import EmojiPicker, { Emoji, EmojiClickData } from "emoji-picker-react"; import { IconButton } from "./button"; import styles from "./home.module.css"; import SettingsIcon from "../icons/settings.svg"; import GithubIcon from "../icons/github.svg"; import ChatGptIcon from "../icons/chatgpt.svg"; import SendWhiteIcon from "../icons/send-white.svg"; import BrainIcon from "../icons/brain.svg"; import ExportIcon from "../icons/export.svg"; import BotIcon from "../icons/bot.svg"; import AddIcon from "../icons/add.svg"; import DeleteIcon from "../icons/delete.svg"; import LoadingIcon from "../icons/three-dots.svg"; import { Message, SubmitKey, useChatStore } from "../store"; import { Card, List, ListItem, Popover } from "./ui-lib"; export function Markdown(props: { content: string }) { return ( {props.content} ); } export function Avatar(props: { role: Message["role"] }) { const config = useChatStore((state) => state.config); if (props.role === "assistant") { return ; } return (
); } export function ChatItem(props: { onClick?: () => void; onDelete?: () => void; title: string; count: number; time: string; selected: boolean; }) { return (
{props.title}
{props.count} 条对话
{props.time}
); } export function ChatList() { const [sessions, selectedIndex, selectSession, removeSession] = useChatStore( (state) => [ state.sessions, state.currentSessionIndex, state.selectSession, state.removeSession, ] ); return (
{sessions.map((item, i) => ( selectSession(i)} onDelete={() => removeSession(i)} /> ))}
); } export function Chat() { type RenderMessage = Message & { preview?: boolean }; const session = useChatStore((state) => state.currentSession()); const [userInput, setUserInput] = useState(""); const [isLoading, setIsLoading] = useState(false); const onUserInput = useChatStore((state) => state.onUserInput); const onUserSubmit = () => { if (userInput.length <= 0) return; setIsLoading(true); onUserInput(userInput).then(() => setIsLoading(false)); setUserInput(""); }; const onInputKeyDown = (e: KeyboardEvent) => { if (e.key === "Enter" && (e.shiftKey || e.ctrlKey || e.metaKey)) { onUserSubmit(); e.preventDefault(); } }; const latestMessageRef = useRef(null); const messages = (session.messages as RenderMessage[]) .concat( isLoading ? [ { role: "assistant", content: "……", date: new Date().toLocaleString(), preview: true, }, ] : [] ) .concat( userInput.length > 0 ? [ { role: "user", content: userInput, date: new Date().toLocaleString(), preview: true, }, ] : [] ); useEffect(() => { latestMessageRef.current?.scrollIntoView({ behavior: "smooth", block: "end", }); }); return (
{session.topic}
与 ChatGPT 的 {session.messages.length} 条对话
} bordered />
} bordered />
{messages.map((message, i) => { const isUser = message.role === "user"; return (
{(message.preview || message.streaming) && (
正在输入…
)}
{(message.preview || message.content.length === 0) && !isUser ? ( ) : (
)}
{!isUser && !message.preview && (
{message.date.toLocaleString()}
)}
); })} -