ChatGPT-Next-Web/app/components/home.tsx
xyj-boop 20aa0ba45c 4.4
2023-04-04 10:05:10 +08:00

194 lines
5.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
require("../polyfill");
import { useState, useEffect } from "react";
import { IconButton } from "./button";
import styles from "./home.module.scss";
import SettingsIcon from "../icons/settings.svg";
import GithubIcon from "../icons/github.svg";
import ChatGptIcon from "../icons/chatgpt.svg";
import BotIcon from "../icons/bot.svg";
import AddIcon from "../icons/add.svg";
import LoadingIcon from "../icons/three-dots.svg";
import CloseIcon from "../icons/close.svg";
import { useChatStore } from "../store";
import { isMobileScreen } from "../utils";
import Locale from "../locales";
import { ChatList } from "./chat-list";
import { Chat } from "./chat";
import dynamic from "next/dynamic";
import { REPO_URL } from "../constant";
import { ErrorBoundary } from "./error";
export function Loading(props: { noLogo?: boolean }) {
return (
<div className={styles["loading-content"]}>
{!props.noLogo && <BotIcon />}
<LoadingIcon />
</div>
);
}
const Settings = dynamic(async () => (await import("./settings")).Settings, {
loading: () => <Loading noLogo />,
});
function useSwitchTheme() {
const config = useChatStore((state) => state.config);
useEffect(() => {
document.body.classList.remove("light");
document.body.classList.remove("dark");
if (config.theme === "dark") {
document.body.classList.add("dark");
} else if (config.theme === "light") {
document.body.classList.add("light");
}
const themeColor = getComputedStyle(document.body)
.getPropertyValue("--theme-color")
.trim();
const metaDescription = document.querySelector('meta[name="theme-color"]');
metaDescription?.setAttribute("content", themeColor);
}, [config.theme]);
}
const useHasHydrated = () => {
const [hasHydrated, setHasHydrated] = useState<boolean>(false);
useEffect(() => {
setHasHydrated(true);
}, []);
return hasHydrated;
};
function _Home() {
const [createNewSession, currentIndex, removeSession] = useChatStore(
(state) => [
state.newSession,
state.currentSessionIndex,
state.removeSession,
],
);
const loading = !useHasHydrated();
const [showSideBar, setShowSideBar] = useState(true);
// setting
const [openSettings, setOpenSettings] = useState(false);
const config = useChatStore((state) => state.config);
useSwitchTheme();
if (loading) {
return <Loading />;
}
return (
<div
className={`${
config.tightBorder && !isMobileScreen()
? styles["tight-container"]
: styles.container
}`}
>
<div
className={styles.sidebar + ` ${showSideBar && styles["sidebar-show"]}`}
>
<div className={styles["sidebar-header"]}>
<div className={styles["sidebar-title"]}>ChatGPTScoPe</div>
<div className={styles["sidebar-sub-title"]}>
ChatGPT ChatGPT ChatGPTScoPe
</div>
<div className={styles["sidebar-logo"]}>
<ChatGptIcon />
</div>
</div>
<div
className={styles["sidebar-body"]}
onClick={() => {
setOpenSettings(false);
setShowSideBar(false);
}}
>
<ChatList />
</div>
<div className={styles["sidebar-tail"]}>
<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"]}>
<IconButton
icon={<SettingsIcon />}
onClick={() => {
setOpenSettings(true);
setShowSideBar(false);
}}
shadow
/>
</div>
<div className={styles["sidebar-action"]}>
<a href={REPO_URL} target="_blank">
<IconButton icon={<GithubIcon />} shadow />
</a>
</div>
</div>
<div>
<IconButton
icon={<AddIcon />}
text={Locale.Home.NewChat}
onClick={() => {
createNewSession();
setShowSideBar(false);
}}
shadow
/>
</div>
</div>
</div>
<div className={styles["window-content"]}>
{openSettings ? (
<Settings
closeSettings={() => {
setOpenSettings(false);
setShowSideBar(true);
}}
/>
) : (
<Chat
key="chat"
showSideBar={() => setShowSideBar(true)}
sideBarShowing={showSideBar}
/>
)}
</div>
</div>
);
}
export function Home() {
return (
<ErrorBoundary>
<_Home></_Home>
</ErrorBoundary>
);
}