"use client";
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 DeleteIcon from "../icons/delete.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 LeftIcon from "../icons/left.svg";
import RightIcon from "../icons/right.svg";
import { Message, SubmitKey, 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 type { Prompt } from "../store/prompt";
export function Loading(props: { noLogo?: boolean }) {
return (
{!props.noLogo && }
);
}
const Settings = dynamic(async () => (await import("./settings")).Settings, {
loading: () => ,
});
const Emoji = dynamic(async () => (await import("emoji-picker-react")).Emoji, {
loading: () => ,
});
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;
}) {
const [sidebarCollapse] = useChatStore((state) => [state.sidebarCollapse]);
return sidebarCollapse ? (
{Locale.ChatItem.ChatItemCount(props.count).replace(/[^0-9]/g, "")
.length <= 3
? Locale.ChatItem.ChatItemCount(props.count).replace(/[^0-9]/g, "")
: ":)"}
) : (
{props.title}
{Locale.ChatItem.ChatItemCount(props.count)}
{props.time}
);
}
function useSubmitHandler() {
const config = useChatStore((state) => state.config);
const submitKey = config.submitKey;
const shouldSubmit = (e: React.KeyboardEvent) => {
if (e.key !== "Enter") return false;
if (e.key === "Enter" && e.nativeEvent.isComposing) return false;
return (
(config.submitKey === SubmitKey.AltEnter && e.altKey) ||
(config.submitKey === SubmitKey.CtrlEnter && e.ctrlKey) ||
(config.submitKey === SubmitKey.ShiftEnter && e.shiftKey) ||
(config.submitKey === SubmitKey.MetaEnter && e.metaKey) ||
(config.submitKey === SubmitKey.Enter &&
!e.altKey &&
!e.ctrlKey &&
!e.shiftKey &&
!e.metaKey)
);
};
return {
submitKey,
shouldSubmit,
};
}
export function PromptHints(props: {
prompts: Prompt[];
onPromptSelect: (prompt: Prompt) => void;
}) {
if (props.prompts.length === 0) return null;
return (
{props.prompts.map((prompt, i) => (
props.onPromptSelect(prompt)}
>
{prompt.title}
{prompt.content}
))}
);
}
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(false);
useEffect(() => {
setHasHydrated(true);
}, []);
return hasHydrated;
};
export function Home() {
const [createNewSession, currentIndex, removeSession] = useChatStore(
(state) => [
state.newSession,
state.currentSessionIndex,
state.removeSession,
],
);
const loading = !useHasHydrated();
const [sidebarCollapse, setSideBarCollapse] = useChatStore((state) => [
state.sidebarCollapse,
state.setSidebarCollapse,
]);
// setting
const [openSettings, setOpenSettings] = useState(false);
const config = useChatStore((state) => state.config);
useSwitchTheme();
if (loading) {
return ;
}
return (
{sidebarCollapse ? null : (
<>
ChatGPT Next
Build your own AI assistant.
>
)}
{sidebarCollapse ? (
) : (
)}
{
setOpenSettings(false);
if (window.innerWidth < 768) {
setSideBarCollapse(true);
}
}}
>
{sidebarCollapse ? (
}
onClick={() => {
setSideBarCollapse(false);
}}
/>
) : (
}
onClick={() => {
setSideBarCollapse(true);
}}
/>
)}
}
onClick={() => {
if (confirm(Locale.Home.DeleteChat)) {
removeSession(currentIndex);
}
}}
/>
}
onClick={() => {
setOpenSettings(true);
setSideBarCollapse(true);
}}
shadow
/>
}
text={sidebarCollapse ? undefined : Locale.Home.NewChat}
onClick={() => {
createNewSession();
setSideBarCollapse(true);
}}
shadow
/>
{openSettings ? (
{
setOpenSettings(false);
setSideBarCollapse(false);
}}
/>
) : (
)}
);
}