diff --git a/app/components/home.tsx b/app/components/home.tsx
index 576112715..19ecb730f 100644
--- a/app/components/home.tsx
+++ b/app/components/home.tsx
@@ -59,7 +59,7 @@ const Sd = dynamic(async () => (await import("./sd")).Sd, {
loading: () => ,
});
-const SdPanel = dynamic(async () => (await import("./sd")).SdPanel, {
+const SdNew = dynamic(async () => (await import("./sd")).SdNew, {
loading: () => ,
});
@@ -144,7 +144,7 @@ function Screen() {
const isHome = location.pathname === Path.Home;
const isAuth = location.pathname === Path.Auth;
const isSd = location.pathname === Path.Sd;
- const isSdPanel = location.pathname === Path.SdPanel;
+ const isSdNew = location.pathname === Path.SdNew;
const isMobileScreen = useMobileScreen();
const shouldTightBorder =
@@ -157,7 +157,7 @@ function Screen() {
const renderContent = () => {
if (isAuth) return ;
if (isSd) return ;
- if (isSdPanel) return ;
+ if (isSdNew) return ;
return (
<>
@@ -167,8 +167,6 @@ function Screen() {
} />
} />
} />
- } />
- } />
} />
diff --git a/app/components/sd/index.tsx b/app/components/sd/index.tsx
index d442c22bc..f2808bd3e 100644
--- a/app/components/sd/index.tsx
+++ b/app/components/sd/index.tsx
@@ -1,2 +1,3 @@
export * from "./sd";
export * from "./sd-panel";
+export * from "./sd-new";
diff --git a/app/components/sd/sd-new.tsx b/app/components/sd/sd-new.tsx
new file mode 100644
index 000000000..77e70d64f
--- /dev/null
+++ b/app/components/sd/sd-new.tsx
@@ -0,0 +1,85 @@
+import homeStyles from "@/app/components/home.module.scss";
+
+import { IconButton } from "@/app/components/button";
+import GithubIcon from "@/app/icons/github.svg";
+import ReturnIcon from "@/app/icons/return.svg";
+import Locale from "@/app/locales";
+import HistoryIcon from "@/app/icons/history.svg";
+
+import { Path, REPO_URL } from "@/app/constant";
+
+import { useNavigate } from "react-router-dom";
+import dynamic from "next/dynamic";
+import {
+ SideBarContainer,
+ SideBarBody,
+ SideBarTail,
+ useDragSideBar,
+ useHotKey,
+} from "@/app/components/sidebar";
+
+const SdPanel = dynamic(
+ async () => (await import("@/app/components/sd")).SdPanel,
+ {
+ loading: () => null,
+ },
+);
+
+export function SdNew() {
+ useHotKey();
+ const { onDragStart, shouldNarrow } = useDragSideBar();
+ const navigate = useNavigate();
+ return (
+
+
+ {
+
+
+ }
+ bordered
+ title={Locale.Sd.Actions.ReturnHome}
+ onClick={() => navigate(Path.Home)}
+ />
+
+
+ }
+
+
+
+
+ }
+ bordered
+ title={Locale.Sd.Actions.History}
+ onClick={() => navigate(Path.Sd)}
+ />
+
+
+
+
+
+
+
+ } shadow />
+
+ }
+ />
+
+ );
+}
diff --git a/app/components/sd/sd-sidebar.tsx b/app/components/sd/sd-sidebar.tsx
index 9d85846d7..93909218f 100644
--- a/app/components/sd/sd-sidebar.tsx
+++ b/app/components/sd/sd-sidebar.tsx
@@ -1,5 +1,3 @@
-import styles from "@/app/components/home.module.scss";
-
import { IconButton } from "@/app/components/button";
import GithubIcon from "@/app/icons/github.svg";
import SDIcon from "@/app/icons/sd.svg";
@@ -13,12 +11,14 @@ import dynamic from "next/dynamic";
import {
SideBarContainer,
SideBarBody,
+ SideBarHeader,
+ SideBarTail,
useDragSideBar,
useHotKey,
} from "@/app/components/sidebar";
const SdPanel = dynamic(
- async () => (await import("@/app/components/sd/sd-panel")).SdPanel,
+ async () => (await import("@/app/components/sd")).SdPanel,
{
loading: () => null,
},
@@ -35,31 +35,27 @@ export function SideBar(props: { className?: string }) {
shouldNarrow={shouldNarrow}
{...props}
>
-
-
+ }
bordered
- title={Locale.Chat.Actions.ChatList}
- onClick={() => navigate(Path.Chat)}
+ title={Locale.Sd.Actions.ReturnHome}
+ onClick={() => navigate(Path.Home)}
/>
-
-
-
-
-
+ }
+ logo={}
+ >
-
+
+ } shadow />
+
+ }
+ />
);
}
diff --git a/app/components/sd/sd.tsx b/app/components/sd/sd.tsx
index 547a877ee..83326e5eb 100644
--- a/app/components/sd/sd.tsx
+++ b/app/components/sd/sd.tsx
@@ -111,7 +111,7 @@ export function Sd() {
icon={}
bordered
title={Locale.Chat.Actions.ChatList}
- onClick={() => navigate(Path.SdPanel)}
+ onClick={() => navigate(Path.SdNew)}
/>
diff --git a/app/components/sidebar.tsx b/app/components/sidebar.tsx
index 79af7e121..5db77170e 100644
--- a/app/components/sidebar.tsx
+++ b/app/components/sidebar.tsx
@@ -1,4 +1,4 @@
-import { useEffect, useRef, useMemo, useState } from "react";
+import React, { useEffect, useRef, useMemo, useState, Fragment } from "react";
import styles from "./home.module.scss";
@@ -161,70 +161,24 @@ export function SideBarContainer(props: {
);
}
-export function SideBarHeader(props: { shouldNarrow: boolean }) {
- const navigate = useNavigate();
- const config = useAppConfig();
- const { shouldNarrow } = props;
- const [showPluginSelector, setShowPluginSelector] = useState(false);
-
+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 (
- <>
+
- NextChat
-
-
- Build your own AI assistant.
-
-
-
+ {title}
+
{subTitle}
+
{logo}
-
-
- }
- 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.Plugin.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 } });
- }}
- />
- )}
- >
+ {children}
+
);
}
@@ -240,50 +194,16 @@ export function SideBarBody(props: {
);
}
-export function SideBarTail(props: { shouldNarrow: boolean }) {
- const { shouldNarrow } = props;
- const chatStore = useChatStore();
- const navigate = useNavigate();
- const config = useAppConfig();
+export function SideBarTail(props: {
+ primaryAction?: React.ReactNode;
+ secondaryAction?: React.ReactNode;
+}) {
+ const { primaryAction, secondaryAction } = props;
+
return (
-
-
- }
- onClick={async () => {
- if (await showConfirm(Locale.Home.DeleteChat)) {
- chatStore.deleteSession(chatStore.currentSessionIndex);
- }
- }}
- />
-
-
-
- } shadow />
-
-
-
-
-
- }
- text={shouldNarrow ? undefined : Locale.Home.NewChat}
- onClick={() => {
- if (config.dontShowMaskSplashScreen) {
- chatStore.newSession();
- navigate(Path.Chat);
- } else {
- navigate(Path.NewChat);
- }
- }}
- shadow
- />
-
+
{primaryAction}
+
{secondaryAction}
);
}
@@ -291,7 +211,10 @@ export function SideBarTail(props: { shouldNarrow: boolean }) {
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.Plugin.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) {
@@ -309,7 +280,47 @@ export function SideBar(props: { className?: string }) {
>
-
+
+
+ }
+ onClick={async () => {
+ if (await showConfirm(Locale.Home.DeleteChat)) {
+ chatStore.deleteSession(chatStore.currentSessionIndex);
+ }
+ }}
+ />
+
+
+
+ } shadow />
+
+
+
+ >
+ }
+ secondaryAction={
+ }
+ text={shouldNarrow ? undefined : Locale.Home.NewChat}
+ onClick={() => {
+ if (config.dontShowMaskSplashScreen) {
+ chatStore.newSession();
+ navigate(Path.Chat);
+ } else {
+ navigate(Path.NewChat);
+ }
+ }}
+ shadow
+ />
+ }
+ />
);
}
diff --git a/app/constant.ts b/app/constant.ts
index 8f13d6103..1065aa14a 100644
--- a/app/constant.ts
+++ b/app/constant.ts
@@ -34,7 +34,7 @@ export enum Path {
Masks = "/masks",
Auth = "/auth",
Sd = "/sd",
- SdPanel = "/sd-panel",
+ SdNew = "/sd-new",
}
export enum ApiPath {
diff --git a/app/icons/history.svg b/app/icons/history.svg
new file mode 100644
index 000000000..e7b47c022
--- /dev/null
+++ b/app/icons/history.svg
@@ -0,0 +1,10 @@
+
+
\ No newline at end of file
diff --git a/app/locales/cn.ts b/app/locales/cn.ts
index a6391913d..6370cf76f 100644
--- a/app/locales/cn.ts
+++ b/app/locales/cn.ts
@@ -564,6 +564,8 @@ const cn = {
Copy: "ๅคๅถๆ็คบ่ฏ",
Delete: "ๅ ้ค",
Retry: "้่ฏ",
+ ReturnHome: "่ฟๅ้ฆ้กต",
+ History: "ๆฅ็ๅๅฒ",
},
EmptyRecord: "ๆๆ ็ป็ป่ฎฐๅฝ",
Status: {
diff --git a/app/locales/en.ts b/app/locales/en.ts
index 0bbea0c16..24784946c 100644
--- a/app/locales/en.ts
+++ b/app/locales/en.ts
@@ -570,6 +570,8 @@ const en: LocaleType = {
Copy: "Copy Prompt",
Delete: "Delete",
Retry: "Retry",
+ ReturnHome: "Return Home",
+ History: "History",
},
EmptyRecord: "No images yet",
Status: {