import React, { useEffect, useRef, useMemo, useState, Fragment } from "react"; import styles from "./home.module.scss"; import { IconButton } from "./button"; import SettingsIcon from "../icons/settings.svg"; import GithubIcon from "../icons/github.svg"; import ChatGptIcon from "../icons/chatgpt.svg"; import AddIcon from "../icons/add.svg"; import CloseIcon from "../icons/close.svg"; import DeleteIcon from "../icons/delete.svg"; import MaskIcon from "../icons/mask.svg"; import DragIcon from "../icons/drag.svg"; import DiscoveryIcon from "../icons/discovery.svg"; import Locale from "../locales"; import { useAppConfig, useChatStore } from "../store"; import { DEFAULT_SIDEBAR_WIDTH, MAX_SIDEBAR_WIDTH, MIN_SIDEBAR_WIDTH, NARROW_SIDEBAR_WIDTH, Path, PLUGINS, REPO_URL, } from "../constant"; import { signOut } from "next-auth/react"; import dynamic from "next/dynamic"; import { Link, useNavigate } from "react-router-dom"; import { isIOS, useMobileScreen } from "../utils"; import dynamic from "next/dynamic"; import { showConfirm, Selector } from "./ui-lib"; const ChatList = dynamic(async () => (await import("./chat-list")).ChatList, { loading: () => null, }); export function useHotKey() { const chatStore = useChatStore(); useEffect(() => { const onKeyDown = (e: KeyboardEvent) => { if (e.altKey || e.ctrlKey) { if (e.key === "ArrowUp") { chatStore.nextSession(-1); } else if (e.key === "ArrowDown") { chatStore.nextSession(1); } } }; window.addEventListener("keydown", onKeyDown); return () => window.removeEventListener("keydown", onKeyDown); }); } export function useDragSideBar() { const limit = (x: number) => Math.min(MAX_SIDEBAR_WIDTH, x); const config = useAppConfig(); const startX = useRef(0); const startDragWidth = useRef(config.sidebarWidth ?? DEFAULT_SIDEBAR_WIDTH); const lastUpdateTime = useRef(Date.now()); const toggleSideBar = () => { config.update((config) => { if (config.sidebarWidth < MIN_SIDEBAR_WIDTH) { config.sidebarWidth = DEFAULT_SIDEBAR_WIDTH; } else { config.sidebarWidth = NARROW_SIDEBAR_WIDTH; } }); }; return (
{title}
{subTitle}
{logo}
{children}
); } export function SideBarBody(props: { children: React.ReactNode; onClick?: (e: React.MouseEvent) => void; }) { const { onClick, children } = props; return (
{children}
); } export function SideBarTail(props: { primaryAction?: React.ReactNode; secondaryAction?: React.ReactNode; }) { const { primaryAction, secondaryAction } = props; return (
{primaryAction}
{secondaryAction}
); } export function SideBar(props: { className?: string }) { useHotKey(); const { onDragStart, shouldNarrow } = useDragSideBar(); const [showPluginSelector, setShowPluginSelector] = useState(false); const navigate = useNavigate(); const config = useAppConfig(); const chatStore = useChatStore(); return ( } >
} text={shouldNarrow ? undefined : Locale.Mask.Name} className={styles["sidebar-bar-button"]} onClick={() => { if (config.dontShowMaskSplashScreen !== true) { navigate(Path.NewChat, { state: { fromHome: true } }); } else { navigate(Path.Masks, { state: { fromHome: true } }); } }} shadow /> } text={shouldNarrow ? undefined : Locale.Discovery.Name} className={styles["sidebar-bar-button"]} onClick={() => setShowPluginSelector(true)} shadow />
{showPluginSelector && ( { return { title: item.name, value: item.path, }; }), ]} onClose={() => setShowPluginSelector(false)} onSelection={(s) => { navigate(s[0], { state: { fromHome: true } }); }} /> )}
{ if (e.target === e.currentTarget) { navigate(Path.Home); } }} >
} onClick={async () => { if (await showConfirm(Locale.Home.DeleteChat)) { chatStore.deleteSession(chatStore.currentSessionIndex); } }} />
} shadow />
} shadow />
} secondaryAction={ } text={shouldNarrow ? undefined : Locale.Home.NewChat} onClick={() => { if (config.dontShowMaskSplashScreen) { chatStore.newSession(); navigate(Path.Chat); } else { navigate(Path.NewChat); } }} shadow /> } />
); }