diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 00000000000..fc885b29354
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,37 @@
+name: Run Tests
+
+on:
+ push:
+ branches:
+ - main
+ tags:
+ - "!*"
+ pull_request:
+
+jobs:
+ test:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Set up Node.js
+ uses: actions/setup-node@v3
+ with:
+ node-version: 18
+ cache: "yarn"
+
+ - name: Cache node_modules
+ uses: actions/cache@v4
+ with:
+ path: node_modules
+ key: ${{ runner.os }}-node_modules-${{ hashFiles('**/yarn.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-node_modules-
+
+ - name: Install dependencies
+ run: yarn install
+
+ - name: Run Jest tests
+ run: yarn test:ci
diff --git a/app/components/auth.tsx b/app/components/auth.tsx
index e19512d8741..539a52eecc9 100644
--- a/app/components/auth.tsx
+++ b/app/components/auth.tsx
@@ -11,6 +11,7 @@ import Logo from "../icons/logo.svg";
import { useMobileScreen } from "@/app/utils";
import BotIcon from "../icons/bot.svg";
import { getClientConfig } from "../config/client";
+import { PasswordInput } from "./ui-lib";
import LeftIcon from "@/app/icons/left.svg";
import { safeLocalStorage } from "@/app/utils";
import {
@@ -60,36 +61,43 @@ export function AuthPage() {
{Locale.Auth.Title}
{Locale.Auth.Tips}
- {
accessStore.update(
(access) => (access.accessCode = e.currentTarget.value),
);
}}
/>
+
{!accessStore.hideUserApiKey ? (
<>
{Locale.Auth.SubTips}
- {
accessStore.update(
(access) => (access.openaiApiKey = e.currentTarget.value),
);
}}
/>
- {
accessStore.update(
(access) => (access.googleApiKey = e.currentTarget.value),
diff --git a/app/components/home.module.scss b/app/components/home.module.scss
index b31334568dd..381b6a9b951 100644
--- a/app/components/home.module.scss
+++ b/app/components/home.module.scss
@@ -140,6 +140,9 @@
display: flex;
justify-content: space-between;
align-items: center;
+ &-narrow {
+ justify-content: center;
+ }
}
.sidebar-logo {
diff --git a/app/components/markdown.tsx b/app/components/markdown.tsx
index a25b8537bc1..9841a196d27 100644
--- a/app/components/markdown.tsx
+++ b/app/components/markdown.tsx
@@ -169,6 +169,12 @@ export function PreCode(props: { children: any }) {
}
function CustomCode(props: { children: any; className?: string }) {
+ const chatStore = useChatStore();
+ const session = chatStore.currentSession();
+ const config = useAppConfig();
+ const enableCodeFold =
+ session.mask?.enableCodeFold !== false && config.enableCodeFold;
+
const ref = useRef(null);
const [collapsed, setCollapsed] = useState(true);
const [showToggle, setShowToggle] = useState(false);
@@ -184,25 +190,30 @@ function CustomCode(props: { children: any; className?: string }) {
const toggleCollapsed = () => {
setCollapsed((collapsed) => !collapsed);
};
+ const renderShowMoreButton = () => {
+ if (showToggle && enableCodeFold && collapsed) {
+ return (
+
+
+
+ );
+ }
+ return null;
+ };
return (
<>
{props.children}
- {showToggle && collapsed && (
-
-
-
- )}
+
+ {renderShowMoreButton()}
>
);
}
diff --git a/app/components/mask.tsx b/app/components/mask.tsx
index c60e7a528fe..12b19e33514 100644
--- a/app/components/mask.tsx
+++ b/app/components/mask.tsx
@@ -183,6 +183,23 @@ export function MaskConfig(props: {
>
)}
+ {globalConfig.enableCodeFold && (
+
+ {
+ props.updateMask((mask) => {
+ mask.enableCodeFold = e.currentTarget.checked;
+ });
+ }}
+ >
+
+ )}
{!props.shouldSyncFromGlobal ? (
+
+
+ updateConfig(
+ (config) => (config.enableCodeFold = e.currentTarget.checked),
+ )
+ }
+ >
+
diff --git a/app/components/sidebar.tsx b/app/components/sidebar.tsx
index 493b1103beb..2a5c308b78c 100644
--- a/app/components/sidebar.tsx
+++ b/app/components/sidebar.tsx
@@ -165,11 +165,17 @@ export function SideBarHeader(props: {
subTitle?: string | React.ReactNode;
logo?: React.ReactNode;
children?: React.ReactNode;
+ shouldNarrow?: boolean;
}) {
- const { title, subTitle, logo, children } = props;
+ const { title, subTitle, logo, children, shouldNarrow } = props;
return (
-
+
{title}
@@ -227,6 +233,7 @@ export function SideBar(props: { className?: string }) {
title="NextChat"
subTitle="Build your own AI assistant."
logo={
}
+ shouldNarrow={shouldNarrow}
>