From 6b0ef4f65de1b4ec2eb6fc752904722675d3a7e5 Mon Sep 17 00:00:00 2001 From: DirkSchlossmacher <62424946+DirkSchlossmacher@users.noreply.github.com> Date: Sat, 27 Jul 2024 14:09:34 +0200 Subject: [PATCH] copy sidebar --- app/components/sidebar - Copy.tsx | 492 ++++++++++++++++++++++++++++++ 1 file changed, 492 insertions(+) create mode 100644 app/components/sidebar - Copy.tsx diff --git a/app/components/sidebar - Copy.tsx b/app/components/sidebar - Copy.tsx new file mode 100644 index 000000000..00c4f2ea3 --- /dev/null +++ b/app/components/sidebar - Copy.tsx @@ -0,0 +1,492 @@ +<<<<<<< HEAD +import { useEffect, useRef, useMemo, useCallback, useState } from "react"; +//import Image from 'next/image'; // Import the Image component from Next.js +======= +import React, { useEffect, useRef, useMemo, useState, Fragment } from "react"; +>>>>>>> upstream/main + +import styles from "./home.module.scss"; + +import AddIcon from "../icons/add.svg"; +import CloseIcon from "../icons/close.svg"; +import DragIcon from "../icons/drag.svg"; +import GithubIcon from "../icons/github.svg"; +import MaskIcon from "../icons/mask.svg"; +<<<<<<< HEAD +import PluginIcon from "../icons/plugin.svg"; +import SettingsIcon from "../icons/settings.svg"; +import SignoutIcon from "../icons/signout.svg"; +import { IconButton } from "./button"; +======= +import DragIcon from "../icons/drag.svg"; +import DiscoveryIcon from "../icons/discovery.svg"; +>>>>>>> upstream/main + +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"; +<<<<<<< HEAD +import { showConfirm, showToast } from "./ui-lib"; +======= +import dynamic from "next/dynamic"; +import { showConfirm, Selector } from "./ui-lib"; +>>>>>>> upstream/main + +import UsageStats from './usage-stats/UsageStats'; + + +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; + } + }); + }; + + const onDragStart = (e: MouseEvent) => { + // Remembers the initial width each time the mouse is pressed + startX.current = e.clientX; + startDragWidth.current = config.sidebarWidth; + const dragStartTime = Date.now(); + + const handleDragMove = (e: MouseEvent) => { + if (Date.now() < lastUpdateTime.current + 20) { + return; + } + lastUpdateTime.current = Date.now(); + const d = e.clientX - startX.current; + const nextWidth = limit(startDragWidth.current + d); + config.update((config) => { + if (nextWidth < MIN_SIDEBAR_WIDTH) { + config.sidebarWidth = NARROW_SIDEBAR_WIDTH; + } else { + config.sidebarWidth = nextWidth; + } + }); + }; + + const handleDragEnd = () => { + // In useRef the data is non-responsive, so `config.sidebarWidth` can't get the dynamic sidebarWidth + window.removeEventListener("pointermove", handleDragMove); + window.removeEventListener("pointerup", handleDragEnd); + + // if user click the drag icon, should toggle the sidebar + const shouldFireClick = Date.now() - dragStartTime < 300; + if (shouldFireClick) { + toggleSideBar(); + } + }; + + window.addEventListener("pointermove", handleDragMove); + window.addEventListener("pointerup", handleDragEnd); + }; + + const isMobileScreen = useMobileScreen(); + const shouldNarrow = + !isMobileScreen && config.sidebarWidth < MIN_SIDEBAR_WIDTH; + + useEffect(() => { + const barWidth = shouldNarrow + ? NARROW_SIDEBAR_WIDTH + : limit(config.sidebarWidth ?? DEFAULT_SIDEBAR_WIDTH); + const sideBarWidth = isMobileScreen ? "100vw" : `${barWidth}px`; + document.documentElement.style.setProperty("--sidebar-width", sideBarWidth); + }, [config.sidebarWidth, isMobileScreen, shouldNarrow]); + + return { + onDragStart, + shouldNarrow, + }; +} +<<<<<<< HEAD + +export function SideBar(props: { className?: string }) { + const chatStore = useChatStore(); + + const [showUsageStats, setShowUsageStats] = useState(false); // State to control the visibility of the usage stats + const toggleUsageStats = () => setShowUsageStats(!showUsageStats); // Function to toggle the usage stats UI + + + // drag side bar + const { onDragStart, shouldNarrow } = useDragSideBar(); + const navigate = useNavigate(); + const config = useAppConfig(); +======= +export function SideBarContainer(props: { + children: React.ReactNode; + onDragStart: (e: MouseEvent) => void; + shouldNarrow: boolean; + className?: string; +}) { +>>>>>>> upstream/main + const isMobileScreen = useMobileScreen(); + const isIOSMobile = useMemo( + () => isIOS() && isMobileScreen, + [isMobileScreen], + ); +<<<<<<< HEAD + + const usageStatsComponent = showUsageStats && setShowUsageStats(false)} />; + + useHotKey(); + + return ( + <> + {usageStatsComponent} {/* This is where the UsageStats component gets rendered */} +
+
+
+ AdExGPT - via API +
+
+ secure local UI for  + + OpenAI API + +
+ + FAQ & Support + +
+
+ {/* Replace img with Image component and add an alt attribute */} + AdEx Logo +
+
+ +
+======= + const { children, className, onDragStart, shouldNarrow } = props; + return ( +
+ {children} +
onDragStart(e as any)} + > + +
+
+ ); +} + +export function SideBarHeader(props: { + title?: string | React.ReactNode; + subTitle?: string | React.ReactNode; + logo?: React.ReactNode; + children?: React.ReactNode; +}) { + const { title, subTitle, logo, children } = props; + 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 /> + +
+ + + } + secondaryAction={ +>>>>>>> upstream/main + } + 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 + /> +<<<<<<< HEAD + } + text={shouldNarrow ? undefined : Locale.Plugin.Name} + className={styles["sidebar-bar-button"]} + onClick={() => showToast(Locale.WIP)} + shadow + /> +
+ +
{ + if (e.target === e.currentTarget) { + navigate(Path.Home); + } + }} + > + +
+ +
+
+
+ } + onClick={async () => { + if (await showConfirm(Locale.Home.DeleteChat)) { + chatStore.deleteSession(chatStore.currentSessionIndex); + } + }} + /> +
+ +
+ + } shadow /> + +
+ +
+ + } shadow /> + +
+ +
+ } + shadow + onClick={() => signOut()} + /> +
+
+
+ } + text={shouldNarrow ? undefined : Locale.Home.NewChat} + onClick={() => { + if (config.dontShowMaskSplashScreen) { + chatStore.newSession(); + navigate(Path.Chat); + } else { + navigate(Path.NewChat); + } + }} + shadow + /> +
+
+ +
onDragStart(e as any)} + > + +
+
+ + +======= + } + /> + +>>>>>>> upstream/main + ); +}