DeanYao 1 rok pred
rodič
commit
d89a12aa05

+ 12 - 10
app/api/common.ts

@@ -112,16 +112,16 @@ export async function requestOpenai(req: NextRequest) {
   try {
     const res = await fetch(fetchUrl, fetchOptions);
 
-    // Extract the OpenAI-Organization header from the response
-    const openaiOrganizationHeader = res.headers.get("OpenAI-Organization");
-
-    // Check if serverConfig.openaiOrgId is defined and not an empty string
-    if (serverConfig.openaiOrgId && serverConfig.openaiOrgId.trim() !== "") {
-      // If openaiOrganizationHeader is present, log it; otherwise, log that the header is not present
-      console.log("[Org ID]", openaiOrganizationHeader);
-    } else {
-      console.log("[Org ID] is not set up.");
-    }
+  // Extract the OpenAI-Organization header from the response
+  const openaiOrganizationHeader = res.headers.get("OpenAI-Organization");
+
+  // Check if serverConfig.openaiOrgId is defined and not an empty string
+  if (serverConfig.openaiOrgId && serverConfig.openaiOrgId.trim() !== "") {
+    // If openaiOrganizationHeader is present, log it; otherwise, log that the header is not present
+    console.log("[Org ID]", openaiOrganizationHeader);
+  } else {
+    console.log("[Org ID] is not set up.");
+  }
 
     // to prevent browser prompt for credentials
     const newHeaders = new Headers(res.headers);
@@ -129,6 +129,7 @@ export async function requestOpenai(req: NextRequest) {
     // to disable nginx buffering
     newHeaders.set("X-Accel-Buffering", "no");
 
+
     // Conditionally delete the OpenAI-Organization header from the response if [Org ID] is undefined or empty (not setup in ENV)
     // Also, this is to prevent the header from being sent to the client
     if (!serverConfig.openaiOrgId || serverConfig.openaiOrgId.trim() === "") {
@@ -141,6 +142,7 @@ export async function requestOpenai(req: NextRequest) {
     // The browser will try to decode the response with brotli and fail
     newHeaders.delete("content-encoding");
 
+
     return new Response(res.body, {
       status: res.status,
       statusText: res.statusText,

+ 2 - 4
app/client/platforms/google.ts

@@ -120,9 +120,7 @@ export class GeminiProApi implements LLMApi {
 
       if (!baseUrl) {
         baseUrl = isApp
-          ? DEFAULT_API_HOST +
-            "/api/proxy/google/" +
-            Google.ChatPath(modelConfig.model)
+          ? DEFAULT_API_HOST + "/api/proxy/google/" + Google.ChatPath(modelConfig.model)
           : this.path(Google.ChatPath(modelConfig.model));
       }
 
@@ -141,7 +139,7 @@ export class GeminiProApi implements LLMApi {
         () => controller.abort(),
         REQUEST_TIMEOUT_MS,
       );
-
+      
       if (shouldStream) {
         let responseText = "";
         let remainText = "";

+ 27 - 27
app/components/auth.tsx

@@ -50,33 +50,33 @@ export function AuthPage() {
           );
         }}
       />
-      {/*{!accessStore.hideUserApiKey ? (*/}
-      {/*  <>*/}
-      {/*    <div className={styles["auth-tips"]}>{Locale.Auth.SubTips}</div>*/}
-      {/*    <input*/}
-      {/*      className={styles["auth-input"]}*/}
-      {/*      type="password"*/}
-      {/*      placeholder={Locale.Settings.Access.OpenAI.ApiKey.Placeholder}*/}
-      {/*      value={accessStore.openaiApiKey}*/}
-      {/*      onChange={(e) => {*/}
-      {/*        accessStore.update(*/}
-      {/*          (access) => (access.openaiApiKey = e.currentTarget.value),*/}
-      {/*        );*/}
-      {/*      }}*/}
-      {/*    />*/}
-      {/*    <input*/}
-      {/*      className={styles["auth-input"]}*/}
-      {/*      type="password"*/}
-      {/*      placeholder={Locale.Settings.Access.Google.ApiKey.Placeholder}*/}
-      {/*      value={accessStore.googleApiKey}*/}
-      {/*      onChange={(e) => {*/}
-      {/*        accessStore.update(*/}
-      {/*          (access) => (access.googleApiKey = e.currentTarget.value),*/}
-      {/*        );*/}
-      {/*      }}*/}
-      {/*    />*/}
-      {/*  </>*/}
-      {/*) : null}*/}
+      {!accessStore.hideUserApiKey ? (
+        <>
+          <div className={styles["auth-tips"]}>{Locale.Auth.SubTips}</div>
+          <input
+            className={styles["auth-input"]}
+            type="password"
+            placeholder={Locale.Settings.Access.OpenAI.ApiKey.Placeholder}
+            value={accessStore.openaiApiKey}
+            onChange={(e) => {
+              accessStore.update(
+                (access) => (access.openaiApiKey = e.currentTarget.value),
+              );
+            }}
+          />
+          <input
+            className={styles["auth-input"]}
+            type="password"
+            placeholder={Locale.Settings.Access.Google.ApiKey.Placeholder}
+            value={accessStore.googleApiKey}
+            onChange={(e) => {
+              accessStore.update(
+                (access) => (access.googleApiKey = e.currentTarget.value),
+              );
+            }}
+          />
+        </>
+      ) : null}
 
       <div className={styles["auth-actions"]}>
         <IconButton

+ 93 - 92
app/components/chat.tsx

@@ -491,79 +491,79 @@ export function ChatActions(props: {
 
   return (
     <div className={styles["chat-input-actions"]}>
-      {/*{couldStop && (*/}
-      {/*  <ChatAction*/}
-      {/*    onClick={stopAll}*/}
-      {/*    text={Locale.Chat.InputActions.Stop}*/}
-      {/*    icon={<StopIcon />}*/}
-      {/*  />*/}
-      {/*)}*/}
-      {/*{!props.hitBottom && (*/}
-      {/*  <ChatAction*/}
-      {/*    onClick={props.scrollToBottom}*/}
-      {/*    text={Locale.Chat.InputActions.ToBottom}*/}
-      {/*    icon={<BottomIcon />}*/}
-      {/*  />*/}
-      {/*)}*/}
-      {/*{props.hitBottom && (*/}
-      {/*  <ChatAction*/}
-      {/*    onClick={props.showPromptModal}*/}
-      {/*    text={Locale.Chat.InputActions.Settings}*/}
-      {/*    icon={<SettingsIcon />}*/}
-      {/*  />*/}
-      {/*)}*/}
-
-      {/*{showUploadImage && (*/}
-      {/*  <ChatAction*/}
-      {/*    onClick={props.uploadImage}*/}
-      {/*    text={Locale.Chat.InputActions.UploadImage}*/}
-      {/*    icon={props.uploading ? <LoadingButtonIcon /> : <ImageIcon />}*/}
-      {/*  />*/}
-      {/*)}*/}
-      {/*<ChatAction*/}
-      {/*  onClick={nextTheme}*/}
-      {/*  text={Locale.Chat.InputActions.Theme[theme]}*/}
-      {/*  icon={*/}
-      {/*    <>*/}
-      {/*      {theme === Theme.Auto ? (*/}
-      {/*        <AutoIcon />*/}
-      {/*      ) : theme === Theme.Light ? (*/}
-      {/*        <LightIcon />*/}
-      {/*      ) : theme === Theme.Dark ? (*/}
-      {/*        <DarkIcon />*/}
-      {/*      ) : null}*/}
-      {/*    </>*/}
-      {/*  }*/}
-      {/*/>*/}
-
-      {/*<ChatAction*/}
-      {/*  onClick={props.showPromptHints}*/}
-      {/*  text={Locale.Chat.InputActions.Prompt}*/}
-      {/*  icon={<PromptIcon />}*/}
-      {/*/>*/}
-
-      {/*<ChatAction*/}
-      {/*  onClick={() => {*/}
-      {/*    navigate(Path.Masks);*/}
-      {/*  }}*/}
-      {/*  text={Locale.Chat.InputActions.Masks}*/}
-      {/*  icon={<MaskIcon />}*/}
-      {/*/>*/}
-
-      {/*<ChatAction*/}
-      {/*  text={Locale.Chat.InputActions.Clear}*/}
-      {/*  icon={<BreakIcon />}*/}
-      {/*  onClick={() => {*/}
-      {/*    chatStore.updateCurrentSession((session) => {*/}
-      {/*      if (session.clearContextIndex === session.messages.length) {*/}
-      {/*        session.clearContextIndex = undefined;*/}
-      {/*      } else {*/}
-      {/*        session.clearContextIndex = session.messages.length;*/}
-      {/*        session.memoryPrompt = ""; // will clear memory*/}
-      {/*      }*/}
-      {/*    });*/}
-      {/*  }}*/}
-      {/*/>*/}
+      {couldStop && (
+        <ChatAction
+          onClick={stopAll}
+          text={Locale.Chat.InputActions.Stop}
+          icon={<StopIcon />}
+        />
+      )}
+      {!props.hitBottom && (
+        <ChatAction
+          onClick={props.scrollToBottom}
+          text={Locale.Chat.InputActions.ToBottom}
+          icon={<BottomIcon />}
+        />
+      )}
+      {props.hitBottom && (
+        <ChatAction
+          onClick={props.showPromptModal}
+          text={Locale.Chat.InputActions.Settings}
+          icon={<SettingsIcon />}
+        />
+      )}
+
+      {showUploadImage && (
+        <ChatAction
+          onClick={props.uploadImage}
+          text={Locale.Chat.InputActions.UploadImage}
+          icon={props.uploading ? <LoadingButtonIcon /> : <ImageIcon />}
+        />
+      )}
+      <ChatAction
+        onClick={nextTheme}
+        text={Locale.Chat.InputActions.Theme[theme]}
+        icon={
+          <>
+            {theme === Theme.Auto ? (
+              <AutoIcon />
+            ) : theme === Theme.Light ? (
+              <LightIcon />
+            ) : theme === Theme.Dark ? (
+              <DarkIcon />
+            ) : null}
+          </>
+        }
+      />
+
+      <ChatAction
+        onClick={props.showPromptHints}
+        text={Locale.Chat.InputActions.Prompt}
+        icon={<PromptIcon />}
+      />
+
+      <ChatAction
+        onClick={() => {
+          navigate(Path.Masks);
+        }}
+        text={Locale.Chat.InputActions.Masks}
+        icon={<MaskIcon />}
+      />
+
+      <ChatAction
+        text={Locale.Chat.InputActions.Clear}
+        icon={<BreakIcon />}
+        onClick={() => {
+          chatStore.updateCurrentSession((session) => {
+            if (session.clearContextIndex === session.messages.length) {
+              session.clearContextIndex = undefined;
+            } else {
+              session.clearContextIndex = session.messages.length;
+              session.memoryPrompt = ""; // will clear memory
+            }
+          });
+        }}
+      />
 
       <ChatAction
         onClick={() => setShowModelSelector(true)}
@@ -1089,6 +1089,7 @@ function _Chat() {
             if (payload.url) {
               accessStore.update((access) => (access.openaiUrl = payload.url!));
             }
+            accessStore.update((access) => (access.useCustomConfig = true));
           });
         }
       } catch {
@@ -1233,25 +1234,25 @@ function _Chat() {
           </div>
         </div>
         <div className="window-actions">
-          {/*{!isMobileScreen && (*/}
-          {/*  <div className="window-action-button">*/}
-          {/*    <IconButton*/}
-          {/*      icon={<RenameIcon />}*/}
-          {/*      bordered*/}
-          {/*      onClick={() => setIsEditingMessage(true)}*/}
-          {/*    />*/}
-          {/*  </div>*/}
-          {/*)}*/}
-          {/*<div className="window-action-button">*/}
-          {/*  <IconButton*/}
-          {/*    icon={<ExportIcon />}*/}
-          {/*    bordered*/}
-          {/*    title={Locale.Chat.Actions.Export}*/}
-          {/*    onClick={() => {*/}
-          {/*      setShowExport(true);*/}
-          {/*    }}*/}
-          {/*  />*/}
-          {/*</div>*/}
+          {!isMobileScreen && (
+            <div className="window-action-button">
+              <IconButton
+                icon={<RenameIcon />}
+                bordered
+                onClick={() => setIsEditingMessage(true)}
+              />
+            </div>
+          )}
+          <div className="window-action-button">
+            <IconButton
+              icon={<ExportIcon />}
+              bordered
+              title={Locale.Chat.Actions.Export}
+              onClick={() => {
+                setShowExport(true);
+              }}
+            />
+          </div>
           {showMaxIcon && (
             <div className="window-action-button">
               <IconButton

+ 520 - 455
app/components/settings.tsx

@@ -703,80 +703,80 @@ export function Settings() {
             </Popover>
           </ListItem>
 
-          {/*<ListItem*/}
-          {/*  title={Locale.Settings.Update.Version(currentVersion ?? "unknown")}*/}
-          {/*  subTitle={*/}
-          {/*    checkingUpdate*/}
-          {/*      ? Locale.Settings.Update.IsChecking*/}
-          {/*      : hasNewVersion*/}
-          {/*      ? Locale.Settings.Update.FoundUpdate(remoteId ?? "ERROR")*/}
-          {/*      : Locale.Settings.Update.IsLatest*/}
-          {/*  }*/}
-          {/*>*/}
-          {/*  {checkingUpdate ? (*/}
-          {/*    <LoadingIcon />*/}
-          {/*  ) : hasNewVersion ? (*/}
-          {/*    <Link href={updateUrl} target="_blank" className="link">*/}
-          {/*      {Locale.Settings.Update.GoToUpdate}*/}
-          {/*    </Link>*/}
-          {/*  ) : (*/}
-          {/*    <IconButton*/}
-          {/*      icon={<ResetIcon></ResetIcon>}*/}
-          {/*      text={Locale.Settings.Update.CheckUpdate}*/}
-          {/*      onClick={() => checkUpdate(true)}*/}
-          {/*    />*/}
-          {/*  )}*/}
-          {/*</ListItem>*/}
-
-          {/*<ListItem title={Locale.Settings.SendKey}>*/}
-          {/*  <Select*/}
-          {/*    value={config.submitKey}*/}
-          {/*    onChange={(e) => {*/}
-          {/*      updateConfig(*/}
-          {/*        (config) =>*/}
-          {/*          (config.submitKey = e.target.value as any as SubmitKey),*/}
-          {/*      );*/}
-          {/*    }}*/}
-          {/*  >*/}
-          {/*    {Object.values(SubmitKey).map((v) => (*/}
-          {/*      <option value={v} key={v}>*/}
-          {/*        {v}*/}
-          {/*      </option>*/}
-          {/*    ))}*/}
-          {/*  </Select>*/}
-          {/*</ListItem>*/}
-
-          {/*<ListItem title={Locale.Settings.Theme}>*/}
-          {/*  <Select*/}
-          {/*    value={config.theme}*/}
-          {/*    onChange={(e) => {*/}
-          {/*      updateConfig(*/}
-          {/*        (config) => (config.theme = e.target.value as any as Theme),*/}
-          {/*      );*/}
-          {/*    }}*/}
-          {/*  >*/}
-          {/*    {Object.values(Theme).map((v) => (*/}
-          {/*      <option value={v} key={v}>*/}
-          {/*        {v}*/}
-          {/*      </option>*/}
-          {/*    ))}*/}
-          {/*  </Select>*/}
-          {/*</ListItem>*/}
-
-          {/*<ListItem title={Locale.Settings.Lang.Name}>*/}
-          {/*  <Select*/}
-          {/*    value={getLang()}*/}
-          {/*    onChange={(e) => {*/}
-          {/*      changeLang(e.target.value as any);*/}
-          {/*    }}*/}
-          {/*  >*/}
-          {/*    {AllLangs.map((lang) => (*/}
-          {/*      <option value={lang} key={lang}>*/}
-          {/*        {ALL_LANG_OPTIONS[lang]}*/}
-          {/*      </option>*/}
-          {/*    ))}*/}
-          {/*  </Select>*/}
-          {/*</ListItem>*/}
+          <ListItem
+            title={Locale.Settings.Update.Version(currentVersion ?? "unknown")}
+            subTitle={
+              checkingUpdate
+                ? Locale.Settings.Update.IsChecking
+                : hasNewVersion
+                ? Locale.Settings.Update.FoundUpdate(remoteId ?? "ERROR")
+                : Locale.Settings.Update.IsLatest
+            }
+          >
+            {checkingUpdate ? (
+              <LoadingIcon />
+            ) : hasNewVersion ? (
+              <Link href={updateUrl} target="_blank" className="link">
+                {Locale.Settings.Update.GoToUpdate}
+              </Link>
+            ) : (
+              <IconButton
+                icon={<ResetIcon></ResetIcon>}
+                text={Locale.Settings.Update.CheckUpdate}
+                onClick={() => checkUpdate(true)}
+              />
+            )}
+          </ListItem>
+
+          <ListItem title={Locale.Settings.SendKey}>
+            <Select
+              value={config.submitKey}
+              onChange={(e) => {
+                updateConfig(
+                  (config) =>
+                    (config.submitKey = e.target.value as any as SubmitKey),
+                );
+              }}
+            >
+              {Object.values(SubmitKey).map((v) => (
+                <option value={v} key={v}>
+                  {v}
+                </option>
+              ))}
+            </Select>
+          </ListItem>
+
+          <ListItem title={Locale.Settings.Theme}>
+            <Select
+              value={config.theme}
+              onChange={(e) => {
+                updateConfig(
+                  (config) => (config.theme = e.target.value as any as Theme),
+                );
+              }}
+            >
+              {Object.values(Theme).map((v) => (
+                <option value={v} key={v}>
+                  {v}
+                </option>
+              ))}
+            </Select>
+          </ListItem>
+
+          <ListItem title={Locale.Settings.Lang.Name}>
+            <Select
+              value={getLang()}
+              onChange={(e) => {
+                changeLang(e.target.value as any);
+              }}
+            >
+              {AllLangs.map((lang) => (
+                <option value={lang} key={lang}>
+                  {ALL_LANG_OPTIONS[lang]}
+                </option>
+              ))}
+            </Select>
+          </ListItem>
 
           <ListItem
             title={Locale.Settings.FontSize.Title}
@@ -797,389 +797,454 @@ export function Settings() {
             ></InputRange>
           </ListItem>
 
-          {/*<ListItem*/}
-          {/*  title={Locale.Settings.AutoGenerateTitle.Title}*/}
-          {/*  subTitle={Locale.Settings.AutoGenerateTitle.SubTitle}*/}
-          {/*>*/}
-          {/*  <input*/}
-          {/*    type="checkbox"*/}
-          {/*    checked={config.enableAutoGenerateTitle}*/}
-          {/*    onChange={(e) =>*/}
-          {/*      updateConfig(*/}
-          {/*        (config) =>*/}
-          {/*          (config.enableAutoGenerateTitle = e.currentTarget.checked),*/}
-          {/*      )*/}
-          {/*    }*/}
-          {/*  ></input>*/}
-          {/*</ListItem>*/}
-
-          {/*<ListItem*/}
-          {/*  title={Locale.Settings.SendPreviewBubble.Title}*/}
-          {/*  subTitle={Locale.Settings.SendPreviewBubble.SubTitle}*/}
-          {/*>*/}
-          {/*  <input*/}
-          {/*    type="checkbox"*/}
-          {/*    checked={config.sendPreviewBubble}*/}
-          {/*    onChange={(e) =>*/}
-          {/*      updateConfig(*/}
-          {/*        (config) =>*/}
-          {/*          (config.sendPreviewBubble = e.currentTarget.checked),*/}
-          {/*      )*/}
-          {/*    }*/}
-          {/*  ></input>*/}
-          {/*</ListItem>*/}
+          <ListItem
+            title={Locale.Settings.AutoGenerateTitle.Title}
+            subTitle={Locale.Settings.AutoGenerateTitle.SubTitle}
+          >
+            <input
+              type="checkbox"
+              checked={config.enableAutoGenerateTitle}
+              onChange={(e) =>
+                updateConfig(
+                  (config) =>
+                    (config.enableAutoGenerateTitle = e.currentTarget.checked),
+                )
+              }
+            ></input>
+          </ListItem>
+
+          <ListItem
+            title={Locale.Settings.SendPreviewBubble.Title}
+            subTitle={Locale.Settings.SendPreviewBubble.SubTitle}
+          >
+            <input
+              type="checkbox"
+              checked={config.sendPreviewBubble}
+              onChange={(e) =>
+                updateConfig(
+                  (config) =>
+                    (config.sendPreviewBubble = e.currentTarget.checked),
+                )
+              }
+            ></input>
+          </ListItem>
+        </List>
+
+        <SyncItems />
+
+        <List>
+          <ListItem
+            title={Locale.Settings.Mask.Splash.Title}
+            subTitle={Locale.Settings.Mask.Splash.SubTitle}
+          >
+            <input
+              type="checkbox"
+              checked={!config.dontShowMaskSplashScreen}
+              onChange={(e) =>
+                updateConfig(
+                  (config) =>
+                    (config.dontShowMaskSplashScreen =
+                      !e.currentTarget.checked),
+                )
+              }
+            ></input>
+          </ListItem>
+
+          <ListItem
+            title={Locale.Settings.Mask.Builtin.Title}
+            subTitle={Locale.Settings.Mask.Builtin.SubTitle}
+          >
+            <input
+              type="checkbox"
+              checked={config.hideBuiltinMasks}
+              onChange={(e) =>
+                updateConfig(
+                  (config) =>
+                    (config.hideBuiltinMasks = e.currentTarget.checked),
+                )
+              }
+            ></input>
+          </ListItem>
+        </List>
+
+        <List>
+          <ListItem
+            title={Locale.Settings.Prompt.Disable.Title}
+            subTitle={Locale.Settings.Prompt.Disable.SubTitle}
+          >
+            <input
+              type="checkbox"
+              checked={config.disablePromptHint}
+              onChange={(e) =>
+                updateConfig(
+                  (config) =>
+                    (config.disablePromptHint = e.currentTarget.checked),
+                )
+              }
+            ></input>
+          </ListItem>
+
+          <ListItem
+            title={Locale.Settings.Prompt.List}
+            subTitle={Locale.Settings.Prompt.ListCount(
+              builtinCount,
+              customCount,
+            )}
+          >
+            <IconButton
+              icon={<EditIcon />}
+              text={Locale.Settings.Prompt.Edit}
+              onClick={() => setShowPromptModal(true)}
+            />
+          </ListItem>
+        </List>
+
+        <List id={SlotID.CustomModel}>
+          {showAccessCode && (
+            <ListItem
+              title={Locale.Settings.Access.AccessCode.Title}
+              subTitle={Locale.Settings.Access.AccessCode.SubTitle}
+            >
+              <PasswordInput
+                value={accessStore.accessCode}
+                type="text"
+                placeholder={Locale.Settings.Access.AccessCode.Placeholder}
+                onChange={(e) => {
+                  accessStore.update(
+                    (access) => (access.accessCode = e.currentTarget.value),
+                  );
+                }}
+              />
+            </ListItem>
+          )}
+
+          {!accessStore.hideUserApiKey && (
+            <>
+              {
+                // Conditionally render the following ListItem based on clientConfig.isApp
+                !clientConfig?.isApp && ( // only show if isApp is false
+                  <ListItem
+                    title={Locale.Settings.Access.CustomEndpoint.Title}
+                    subTitle={Locale.Settings.Access.CustomEndpoint.SubTitle}
+                  >
+                    <input
+                      type="checkbox"
+                      checked={accessStore.useCustomConfig}
+                      onChange={(e) =>
+                        accessStore.update(
+                          (access) =>
+                            (access.useCustomConfig = e.currentTarget.checked),
+                        )
+                      }
+                    ></input>
+                  </ListItem>
+                )
+              }
+              {accessStore.useCustomConfig && (
+                <>
+                  <ListItem
+                    title={Locale.Settings.Access.Provider.Title}
+                    subTitle={Locale.Settings.Access.Provider.SubTitle}
+                  >
+                    <Select
+                      value={accessStore.provider}
+                      onChange={(e) => {
+                        accessStore.update(
+                          (access) =>
+                            (access.provider = e.target
+                              .value as ServiceProvider),
+                        );
+                      }}
+                    >
+                      {Object.entries(ServiceProvider).map(([k, v]) => (
+                        <option value={v} key={k}>
+                          {k}
+                        </option>
+                      ))}
+                    </Select>
+                  </ListItem>
+
+                  {accessStore.provider === ServiceProvider.OpenAI && (
+                    <>
+                      <ListItem
+                        title={Locale.Settings.Access.OpenAI.Endpoint.Title}
+                        subTitle={
+                          Locale.Settings.Access.OpenAI.Endpoint.SubTitle
+                        }
+                      >
+                        <input
+                          type="text"
+                          value={accessStore.openaiUrl}
+                          placeholder={OPENAI_BASE_URL}
+                          onChange={(e) =>
+                            accessStore.update(
+                              (access) =>
+                                (access.openaiUrl = e.currentTarget.value),
+                            )
+                          }
+                        ></input>
+                      </ListItem>
+                      <ListItem
+                        title={Locale.Settings.Access.OpenAI.ApiKey.Title}
+                        subTitle={Locale.Settings.Access.OpenAI.ApiKey.SubTitle}
+                      >
+                        <PasswordInput
+                          value={accessStore.openaiApiKey}
+                          type="text"
+                          placeholder={
+                            Locale.Settings.Access.OpenAI.ApiKey.Placeholder
+                          }
+                          onChange={(e) => {
+                            accessStore.update(
+                              (access) =>
+                                (access.openaiApiKey = e.currentTarget.value),
+                            );
+                          }}
+                        />
+                      </ListItem>
+                    </>
+                  )}
+                  {accessStore.provider === ServiceProvider.Azure && (
+                    <>
+                      <ListItem
+                        title={Locale.Settings.Access.Azure.Endpoint.Title}
+                        subTitle={
+                          Locale.Settings.Access.Azure.Endpoint.SubTitle +
+                          Azure.ExampleEndpoint
+                        }
+                      >
+                        <input
+                          type="text"
+                          value={accessStore.azureUrl}
+                          placeholder={Azure.ExampleEndpoint}
+                          onChange={(e) =>
+                            accessStore.update(
+                              (access) =>
+                                (access.azureUrl = e.currentTarget.value),
+                            )
+                          }
+                        ></input>
+                      </ListItem>
+                      <ListItem
+                        title={Locale.Settings.Access.Azure.ApiKey.Title}
+                        subTitle={Locale.Settings.Access.Azure.ApiKey.SubTitle}
+                      >
+                        <PasswordInput
+                          value={accessStore.azureApiKey}
+                          type="text"
+                          placeholder={
+                            Locale.Settings.Access.Azure.ApiKey.Placeholder
+                          }
+                          onChange={(e) => {
+                            accessStore.update(
+                              (access) =>
+                                (access.azureApiKey = e.currentTarget.value),
+                            );
+                          }}
+                        />
+                      </ListItem>
+                      <ListItem
+                        title={Locale.Settings.Access.Azure.ApiVerion.Title}
+                        subTitle={
+                          Locale.Settings.Access.Azure.ApiVerion.SubTitle
+                        }
+                      >
+                        <input
+                          type="text"
+                          value={accessStore.azureApiVersion}
+                          placeholder="2023-08-01-preview"
+                          onChange={(e) =>
+                            accessStore.update(
+                              (access) =>
+                                (access.azureApiVersion =
+                                  e.currentTarget.value),
+                            )
+                          }
+                        ></input>
+                      </ListItem>
+                    </>
+                  )}
+                  {accessStore.provider === ServiceProvider.Google && (
+                    <>
+                      <ListItem
+                        title={Locale.Settings.Access.Google.Endpoint.Title}
+                        subTitle={
+                          Locale.Settings.Access.Google.Endpoint.SubTitle +
+                          Google.ExampleEndpoint
+                        }
+                      >
+                        <input
+                          type="text"
+                          value={accessStore.googleUrl}
+                          placeholder={Google.ExampleEndpoint}
+                          onChange={(e) =>
+                            accessStore.update(
+                              (access) =>
+                                (access.googleUrl = e.currentTarget.value),
+                            )
+                          }
+                        ></input>
+                      </ListItem>
+                      <ListItem
+                        title={Locale.Settings.Access.Google.ApiKey.Title}
+                        subTitle={Locale.Settings.Access.Google.ApiKey.SubTitle}
+                      >
+                        <PasswordInput
+                          value={accessStore.googleApiKey}
+                          type="text"
+                          placeholder={
+                            Locale.Settings.Access.Google.ApiKey.Placeholder
+                          }
+                          onChange={(e) => {
+                            accessStore.update(
+                              (access) =>
+                                (access.googleApiKey = e.currentTarget.value),
+                            );
+                          }}
+                        />
+                      </ListItem>
+                      <ListItem
+                        title={Locale.Settings.Access.Google.ApiVersion.Title}
+                        subTitle={
+                          Locale.Settings.Access.Google.ApiVersion.SubTitle
+                        }
+                      >
+                        <input
+                          type="text"
+                          value={accessStore.googleApiVersion}
+                          placeholder="2023-08-01-preview"
+                          onChange={(e) =>
+                            accessStore.update(
+                              (access) =>
+                                (access.googleApiVersion =
+                                  e.currentTarget.value),
+                            )
+                          }
+                        ></input>
+                      </ListItem>
+                    </>
+                  )}
+                  {accessStore.provider === ServiceProvider.Anthropic && (
+                    <>
+                      <ListItem
+                        title={Locale.Settings.Access.Anthropic.Endpoint.Title}
+                        subTitle={
+                          Locale.Settings.Access.Anthropic.Endpoint.SubTitle +
+                          Anthropic.ExampleEndpoint
+                        }
+                      >
+                        <input
+                          type="text"
+                          value={accessStore.anthropicUrl}
+                          placeholder={Anthropic.ExampleEndpoint}
+                          onChange={(e) =>
+                            accessStore.update(
+                              (access) =>
+                                (access.anthropicUrl = e.currentTarget.value),
+                            )
+                          }
+                        ></input>
+                      </ListItem>
+                      <ListItem
+                        title={Locale.Settings.Access.Anthropic.ApiKey.Title}
+                        subTitle={
+                          Locale.Settings.Access.Anthropic.ApiKey.SubTitle
+                        }
+                      >
+                        <PasswordInput
+                          value={accessStore.anthropicApiKey}
+                          type="text"
+                          placeholder={
+                            Locale.Settings.Access.Anthropic.ApiKey.Placeholder
+                          }
+                          onChange={(e) => {
+                            accessStore.update(
+                              (access) =>
+                                (access.anthropicApiKey =
+                                  e.currentTarget.value),
+                            );
+                          }}
+                        />
+                      </ListItem>
+                      <ListItem
+                        title={Locale.Settings.Access.Anthropic.ApiVerion.Title}
+                        subTitle={
+                          Locale.Settings.Access.Anthropic.ApiVerion.SubTitle
+                        }
+                      >
+                        <input
+                          type="text"
+                          value={accessStore.anthropicApiVersion}
+                          placeholder={Anthropic.Vision}
+                          onChange={(e) =>
+                            accessStore.update(
+                              (access) =>
+                                (access.anthropicApiVersion =
+                                  e.currentTarget.value),
+                            )
+                          }
+                        ></input>
+                      </ListItem>
+                    </>
+                  )}
+                </>
+              )}
+            </>
+          )}
+
+          {!shouldHideBalanceQuery && !clientConfig?.isApp ? (
+            <ListItem
+              title={Locale.Settings.Usage.Title}
+              subTitle={
+                showUsage
+                  ? loadingUsage
+                    ? Locale.Settings.Usage.IsChecking
+                    : Locale.Settings.Usage.SubTitle(
+                        usage?.used ?? "[?]",
+                        usage?.subscription ?? "[?]",
+                      )
+                  : Locale.Settings.Usage.NoAccess
+              }
+            >
+              {!showUsage || loadingUsage ? (
+                <div />
+              ) : (
+                <IconButton
+                  icon={<ResetIcon></ResetIcon>}
+                  text={Locale.Settings.Usage.Check}
+                  onClick={() => checkUsage(true)}
+                />
+              )}
+            </ListItem>
+          ) : null}
+
+          <ListItem
+            title={Locale.Settings.Access.CustomModel.Title}
+            subTitle={Locale.Settings.Access.CustomModel.SubTitle}
+          >
+            <input
+              type="text"
+              value={config.customModels}
+              placeholder="model1,model2,model3"
+              onChange={(e) =>
+                config.update(
+                  (config) => (config.customModels = e.currentTarget.value),
+                )
+              }
+            ></input>
+          </ListItem>
         </List>
 
-        {/*<SyncItems />*/}
-
-        {/*<List>*/}
-        {/*  <ListItem*/}
-        {/*    title={Locale.Settings.Mask.Splash.Title}*/}
-        {/*    subTitle={Locale.Settings.Mask.Splash.SubTitle}*/}
-        {/*  >*/}
-        {/*    <input*/}
-        {/*      type="checkbox"*/}
-        {/*      checked={!config.dontShowMaskSplashScreen}*/}
-        {/*      onChange={(e) =>*/}
-        {/*        updateConfig(*/}
-        {/*          (config) =>*/}
-        {/*            (config.dontShowMaskSplashScreen =*/}
-        {/*              !e.currentTarget.checked),*/}
-        {/*        )*/}
-        {/*      }*/}
-        {/*    ></input>*/}
-        {/*  </ListItem>*/}
-
-        {/*  <ListItem*/}
-        {/*    title={Locale.Settings.Mask.Builtin.Title}*/}
-        {/*    subTitle={Locale.Settings.Mask.Builtin.SubTitle}*/}
-        {/*  >*/}
-        {/*    <input*/}
-        {/*      type="checkbox"*/}
-        {/*      checked={config.hideBuiltinMasks}*/}
-        {/*      onChange={(e) =>*/}
-        {/*        updateConfig(*/}
-        {/*          (config) =>*/}
-        {/*            (config.hideBuiltinMasks = e.currentTarget.checked),*/}
-        {/*        )*/}
-        {/*      }*/}
-        {/*    ></input>*/}
-        {/*  </ListItem>*/}
-        {/*</List>*/}
-
-        {/*<List>*/}
-        {/*  <ListItem*/}
-        {/*    title={Locale.Settings.Prompt.Disable.Title}*/}
-        {/*    subTitle={Locale.Settings.Prompt.Disable.SubTitle}*/}
-        {/*  >*/}
-        {/*    <input*/}
-        {/*      type="checkbox"*/}
-        {/*      checked={config.disablePromptHint}*/}
-        {/*      onChange={(e) =>*/}
-        {/*        updateConfig(*/}
-        {/*          (config) =>*/}
-        {/*            (config.disablePromptHint = e.currentTarget.checked),*/}
-        {/*        )*/}
-        {/*      }*/}
-        {/*    ></input>*/}
-        {/*  </ListItem>*/}
-
-        {/*  <ListItem*/}
-        {/*    title={Locale.Settings.Prompt.List}*/}
-        {/*    subTitle={Locale.Settings.Prompt.ListCount(*/}
-        {/*      builtinCount,*/}
-        {/*      customCount,*/}
-        {/*    )}*/}
-        {/*  >*/}
-        {/*    <IconButton*/}
-        {/*      icon={<EditIcon />}*/}
-        {/*      text={Locale.Settings.Prompt.Edit}*/}
-        {/*      onClick={() => setShowPromptModal(true)}*/}
-        {/*    />*/}
-        {/*  </ListItem>*/}
-        {/*</List>*/}
-
-        {/*<List id={SlotID.CustomModel}>*/}
-        {/*  {showAccessCode && (*/}
-        {/*    <ListItem*/}
-        {/*      title={Locale.Settings.Access.AccessCode.Title}*/}
-        {/*      subTitle={Locale.Settings.Access.AccessCode.SubTitle}*/}
-        {/*    >*/}
-        {/*      <PasswordInput*/}
-        {/*        value={accessStore.accessCode}*/}
-        {/*        type="text"*/}
-        {/*        placeholder={Locale.Settings.Access.AccessCode.Placeholder}*/}
-        {/*        onChange={(e) => {*/}
-        {/*          accessStore.update(*/}
-        {/*            (access) => (access.accessCode = e.currentTarget.value),*/}
-        {/*          );*/}
-        {/*        }}*/}
-        {/*      />*/}
-        {/*    </ListItem>*/}
-        {/*  )}*/}
-
-        {/*  {!accessStore.hideUserApiKey && (*/}
-        {/*    <>*/}
-        {/*      {*/}
-        {/*        // Conditionally render the following ListItem based on clientConfig.isApp*/}
-        {/*        !clientConfig?.isApp && ( // only show if isApp is false*/}
-        {/*          <ListItem*/}
-        {/*            title={Locale.Settings.Access.CustomEndpoint.Title}*/}
-        {/*            subTitle={Locale.Settings.Access.CustomEndpoint.SubTitle}*/}
-        {/*          >*/}
-        {/*            <input*/}
-        {/*              type="checkbox"*/}
-        {/*              checked={accessStore.useCustomConfig}*/}
-        {/*              onChange={(e) =>*/}
-        {/*                accessStore.update(*/}
-        {/*                  (access) =>*/}
-        {/*                    (access.useCustomConfig = e.currentTarget.checked),*/}
-        {/*                )*/}
-        {/*              }*/}
-        {/*            ></input>*/}
-        {/*          </ListItem>*/}
-        {/*        )*/}
-        {/*      }*/}
-        {/*      {accessStore.useCustomConfig && (*/}
-        {/*        <>*/}
-        {/*          <ListItem*/}
-        {/*            title={Locale.Settings.Access.Provider.Title}*/}
-        {/*            subTitle={Locale.Settings.Access.Provider.SubTitle}*/}
-        {/*          >*/}
-        {/*            <Select*/}
-        {/*              value={accessStore.provider}*/}
-        {/*              onChange={(e) => {*/}
-        {/*                accessStore.update(*/}
-        {/*                  (access) =>*/}
-        {/*                    (access.provider = e.target*/}
-        {/*                      .value as ServiceProvider),*/}
-        {/*                );*/}
-        {/*              }}*/}
-        {/*            >*/}
-        {/*              {Object.entries(ServiceProvider).map(([k, v]) => (*/}
-        {/*                <option value={v} key={k}>*/}
-        {/*                  {k}*/}
-        {/*                </option>*/}
-        {/*              ))}*/}
-        {/*            </Select>*/}
-        {/*          </ListItem>*/}
-
-        {/*          {accessStore.provider === "OpenAI" ? (*/}
-        {/*            <>*/}
-        {/*              <ListItem*/}
-        {/*                title={Locale.Settings.Access.OpenAI.Endpoint.Title}*/}
-        {/*                subTitle={*/}
-        {/*                  Locale.Settings.Access.OpenAI.Endpoint.SubTitle*/}
-        {/*                }*/}
-        {/*              >*/}
-        {/*                <input*/}
-        {/*                  type="text"*/}
-        {/*                  value={accessStore.openaiUrl}*/}
-        {/*                  placeholder={OPENAI_BASE_URL}*/}
-        {/*                  onChange={(e) =>*/}
-        {/*                    accessStore.update(*/}
-        {/*                      (access) =>*/}
-        {/*                        (access.openaiUrl = e.currentTarget.value),*/}
-        {/*                    )*/}
-        {/*                  }*/}
-        {/*                ></input>*/}
-        {/*              </ListItem>*/}
-        {/*              <ListItem*/}
-        {/*                title={Locale.Settings.Access.OpenAI.ApiKey.Title}*/}
-        {/*                subTitle={Locale.Settings.Access.OpenAI.ApiKey.SubTitle}*/}
-        {/*              >*/}
-        {/*                <PasswordInput*/}
-        {/*                  value={accessStore.openaiApiKey}*/}
-        {/*                  type="text"*/}
-        {/*                  placeholder={*/}
-        {/*                    Locale.Settings.Access.OpenAI.ApiKey.Placeholder*/}
-        {/*                  }*/}
-        {/*                  onChange={(e) => {*/}
-        {/*                    accessStore.update(*/}
-        {/*                      (access) =>*/}
-        {/*                        (access.openaiApiKey = e.currentTarget.value),*/}
-        {/*                    );*/}
-        {/*                  }}*/}
-        {/*                />*/}
-        {/*              </ListItem>*/}
-        {/*            </>*/}
-        {/*          ) : accessStore.provider === "Azure" ? (*/}
-        {/*            <>*/}
-        {/*              <ListItem*/}
-        {/*                title={Locale.Settings.Access.Azure.Endpoint.Title}*/}
-        {/*                subTitle={*/}
-        {/*                  Locale.Settings.Access.Azure.Endpoint.SubTitle +*/}
-        {/*                  Azure.ExampleEndpoint*/}
-        {/*                }*/}
-        {/*              >*/}
-        {/*                <input*/}
-        {/*                  type="text"*/}
-        {/*                  value={accessStore.azureUrl}*/}
-        {/*                  placeholder={Azure.ExampleEndpoint}*/}
-        {/*                  onChange={(e) =>*/}
-        {/*                    accessStore.update(*/}
-        {/*                      (access) =>*/}
-        {/*                        (access.azureUrl = e.currentTarget.value),*/}
-        {/*                    )*/}
-        {/*                  }*/}
-        {/*                ></input>*/}
-        {/*              </ListItem>*/}
-        {/*              <ListItem*/}
-        {/*                title={Locale.Settings.Access.Azure.ApiKey.Title}*/}
-        {/*                subTitle={Locale.Settings.Access.Azure.ApiKey.SubTitle}*/}
-        {/*              >*/}
-        {/*                <PasswordInput*/}
-        {/*                  value={accessStore.azureApiKey}*/}
-        {/*                  type="text"*/}
-        {/*                  placeholder={*/}
-        {/*                    Locale.Settings.Access.Azure.ApiKey.Placeholder*/}
-        {/*                  }*/}
-        {/*                  onChange={(e) => {*/}
-        {/*                    accessStore.update(*/}
-        {/*                      (access) =>*/}
-        {/*                        (access.azureApiKey = e.currentTarget.value),*/}
-        {/*                    );*/}
-        {/*                  }}*/}
-        {/*                />*/}
-        {/*              </ListItem>*/}
-        {/*              <ListItem*/}
-        {/*                title={Locale.Settings.Access.Azure.ApiVerion.Title}*/}
-        {/*                subTitle={*/}
-        {/*                  Locale.Settings.Access.Azure.ApiVerion.SubTitle*/}
-        {/*                }*/}
-        {/*              >*/}
-        {/*                <input*/}
-        {/*                  type="text"*/}
-        {/*                  value={accessStore.azureApiVersion}*/}
-        {/*                  placeholder="2023-08-01-preview"*/}
-        {/*                  onChange={(e) =>*/}
-        {/*                    accessStore.update(*/}
-        {/*                      (access) =>*/}
-        {/*                        (access.azureApiVersion =*/}
-        {/*                          e.currentTarget.value),*/}
-        {/*                    )*/}
-        {/*                  }*/}
-        {/*                ></input>*/}
-        {/*              </ListItem>*/}
-        {/*            </>*/}
-        {/*          ) : accessStore.provider === "Google" ? (*/}
-        {/*            <>*/}
-        {/*              <ListItem*/}
-        {/*                title={Locale.Settings.Access.Google.Endpoint.Title}*/}
-        {/*                subTitle={*/}
-        {/*                  Locale.Settings.Access.Google.Endpoint.SubTitle +*/}
-        {/*                  Google.ExampleEndpoint*/}
-        {/*                }*/}
-        {/*              >*/}
-        {/*                <input*/}
-        {/*                  type="text"*/}
-        {/*                  value={accessStore.googleUrl}*/}
-        {/*                  placeholder={Google.ExampleEndpoint}*/}
-        {/*                  onChange={(e) =>*/}
-        {/*                    accessStore.update(*/}
-        {/*                      (access) =>*/}
-        {/*                        (access.googleUrl = e.currentTarget.value),*/}
-        {/*                    )*/}
-        {/*                  }*/}
-        {/*                ></input>*/}
-        {/*              </ListItem>*/}
-        {/*              <ListItem*/}
-        {/*                title={Locale.Settings.Access.Google.ApiKey.Title}*/}
-        {/*                subTitle={Locale.Settings.Access.Google.ApiKey.SubTitle}*/}
-        {/*              >*/}
-        {/*                <PasswordInput*/}
-        {/*                  value={accessStore.googleApiKey}*/}
-        {/*                  type="text"*/}
-        {/*                  placeholder={*/}
-        {/*                    Locale.Settings.Access.Google.ApiKey.Placeholder*/}
-        {/*                  }*/}
-        {/*                  onChange={(e) => {*/}
-        {/*                    accessStore.update(*/}
-        {/*                      (access) =>*/}
-        {/*                        (access.googleApiKey = e.currentTarget.value),*/}
-        {/*                    );*/}
-        {/*                  }}*/}
-        {/*                />*/}
-        {/*              </ListItem>*/}
-        {/*              <ListItem*/}
-        {/*                title={Locale.Settings.Access.Google.ApiVersion.Title}*/}
-        {/*                subTitle={*/}
-        {/*                  Locale.Settings.Access.Google.ApiVersion.SubTitle*/}
-        {/*                }*/}
-        {/*              >*/}
-        {/*                <input*/}
-        {/*                  type="text"*/}
-        {/*                  value={accessStore.googleApiVersion}*/}
-        {/*                  placeholder="2023-08-01-preview"*/}
-        {/*                  onChange={(e) =>*/}
-        {/*                    accessStore.update(*/}
-        {/*                      (access) =>*/}
-        {/*                        (access.googleApiVersion =*/}
-        {/*                          e.currentTarget.value),*/}
-        {/*                    )*/}
-        {/*                  }*/}
-        {/*                ></input>*/}
-        {/*              </ListItem>*/}
-        {/*            </>*/}
-        {/*          ) : null}*/}
-        {/*        </>*/}
-        {/*      )}*/}
-        {/*    </>*/}
-        {/*  )}*/}
-
-        {/*  {!shouldHideBalanceQuery && !clientConfig?.isApp ? (*/}
-        {/*    <ListItem*/}
-        {/*      title={Locale.Settings.Usage.Title}*/}
-        {/*      subTitle={*/}
-        {/*        showUsage*/}
-        {/*          ? loadingUsage*/}
-        {/*            ? Locale.Settings.Usage.IsChecking*/}
-        {/*            : Locale.Settings.Usage.SubTitle(*/}
-        {/*                usage?.used ?? "[?]",*/}
-        {/*                usage?.subscription ?? "[?]",*/}
-        {/*              )*/}
-        {/*          : Locale.Settings.Usage.NoAccess*/}
-        {/*      }*/}
-        {/*    >*/}
-        {/*      {!showUsage || loadingUsage ? (*/}
-        {/*        <div />*/}
-        {/*      ) : (*/}
-        {/*        <IconButton*/}
-        {/*          icon={<ResetIcon></ResetIcon>}*/}
-        {/*          text={Locale.Settings.Usage.Check}*/}
-        {/*          onClick={() => checkUsage(true)}*/}
-        {/*        />*/}
-        {/*      )}*/}
-        {/*    </ListItem>*/}
-        {/*  ) : null}*/}
-
-        {/*  <ListItem*/}
-        {/*    title={Locale.Settings.Access.CustomModel.Title}*/}
-        {/*    subTitle={Locale.Settings.Access.CustomModel.SubTitle}*/}
-        {/*  >*/}
-        {/*    <input*/}
-        {/*      type="text"*/}
-        {/*      value={config.customModels}*/}
-        {/*      placeholder="model1,model2,model3"*/}
-        {/*      onChange={(e) =>*/}
-        {/*        config.update(*/}
-        {/*          (config) => (config.customModels = e.currentTarget.value),*/}
-        {/*        )*/}
-        {/*      }*/}
-        {/*    ></input>*/}
-        {/*  </ListItem>*/}
-        {/*</List>*/}
-
-        {/*<List>*/}
-        {/*  <ModelConfigList*/}
-        {/*    modelConfig={config.modelConfig}*/}
-        {/*    updateConfig={(updater) => {*/}
-        {/*      const modelConfig = { ...config.modelConfig };*/}
-        {/*      updater(modelConfig);*/}
-        {/*      config.update((config) => (config.modelConfig = modelConfig));*/}
-        {/*    }}*/}
-        {/*  />*/}
-        {/*</List>*/}
+        <List>
+          <ModelConfigList
+            modelConfig={config.modelConfig}
+            updateConfig={(updater) => {
+              const modelConfig = { ...config.modelConfig };
+              updater(modelConfig);
+              config.update((config) => (config.modelConfig = modelConfig));
+            }}
+          />
+        </List>
 
         {shouldShowPromptModal && (
           <UserPromptModal onClose={() => setShowPromptModal(false)} />

+ 32 - 33
app/components/sidebar.tsx

@@ -6,7 +6,6 @@ import { IconButton } from "./button";
 import SettingsIcon from "../icons/settings.svg";
 import GithubIcon from "../icons/github.svg";
 import ChatGptIcon from "../icons/chatgpt.svg";
-import DiitIcon from "../icons/diit.svg";
 import AddIcon from "../icons/add.svg";
 import CloseIcon from "../icons/close.svg";
 import DeleteIcon from "../icons/delete.svg";
@@ -156,38 +155,38 @@ export function SideBar(props: { className?: string }) {
     >
       <div className={styles["sidebar-header"]} data-tauri-drag-region>
         <div className={styles["sidebar-title"]} data-tauri-drag-region>
-          DiitChat
+          NextChat
+        </div>
+        <div className={styles["sidebar-sub-title"]}>
+          Build your own AI assistant.
         </div>
-        {/*<div className={styles["sidebar-sub-title"]}>*/}
-        {/*  Build your own AI assistant.*/}
-        {/*</div>*/}
         <div className={styles["sidebar-logo"] + " no-dark"}>
-          <DiitIcon />
+          <ChatGptIcon />
         </div>
       </div>
 
-      {/*<div className={styles["sidebar-header-bar"]}>*/}
-      {/*  <IconButton*/}
-      {/*    icon={<MaskIcon />}*/}
-      {/*    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*/}
-      {/*  />*/}
-      {/*  <IconButton*/}
-      {/*    icon={<PluginIcon />}*/}
-      {/*    text={shouldNarrow ? undefined : Locale.Plugin.Name}*/}
-      {/*    className={styles["sidebar-bar-button"]}*/}
-      {/*    onClick={() => showToast(Locale.WIP)}*/}
-      {/*    shadow*/}
-      {/*  />*/}
-      {/*</div>*/}
+      <div className={styles["sidebar-header-bar"]}>
+        <IconButton
+          icon={<MaskIcon />}
+          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
+        />
+        <IconButton
+          icon={<PluginIcon />}
+          text={shouldNarrow ? undefined : Locale.Plugin.Name}
+          className={styles["sidebar-bar-button"]}
+          onClick={() => showToast(Locale.WIP)}
+          shadow
+        />
+      </div>
 
       <div
         className={styles["sidebar-body"]}
@@ -217,11 +216,11 @@ export function SideBar(props: { className?: string }) {
               <IconButton icon={<SettingsIcon />} shadow />
             </Link>
           </div>
-          {/*<div className={styles["sidebar-action"]}>*/}
-          {/*  <a href={REPO_URL} target="_blank" rel="noopener noreferrer">*/}
-          {/*    <IconButton icon={<GithubIcon />} shadow />*/}
-          {/*  </a>*/}
-          {/*</div>*/}
+          <div className={styles["sidebar-action"]}>
+            <a href={REPO_URL} target="_blank" rel="noopener noreferrer">
+              <IconButton icon={<GithubIcon />} shadow />
+            </a>
+          </div>
         </div>
         <div>
           <IconButton

+ 1 - 1
app/constant.ts

@@ -149,7 +149,7 @@ const openaiModels = [
   "gpt-4o",
   "gpt-4o-2024-05-13",
   "gpt-4-vision-preview",
-  "gpt-4-turbo-2024-04-09",
+  "gpt-4-turbo-2024-04-09"
 ];
 
 const googleModels = [

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 0
app/icons/diit.svg


+ 2 - 5
app/layout.tsx

@@ -10,7 +10,7 @@ import { GoogleTagManager } from "@next/third-parties/google";
 const serverConfig = getServerSideConfig();
 
 export const metadata: Metadata = {
-  title: "DiitChat",
+  title: "NextChat",
   description: "Your personal ChatGPT Chat Bot.",
   viewport: {
     width: "device-width",
@@ -36,10 +36,7 @@ export default function RootLayout({
     <html lang="en">
       <head>
         <meta name="config" content={JSON.stringify(getClientConfig())} />
-        <meta
-          name="viewport"
-          content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
-        />
+        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
         <link rel="manifest" href="/site.webmanifest"></link>
         <script src="/serviceWorkerRegister.js" defer></script>
       </head>

+ 1 - 1
app/locales/cn.ts

@@ -8,7 +8,7 @@ const cn = {
   Error: {
     Unauthorized: isApp
       ? "检测到无效 API Key,请前往[设置](/#/settings)页检查 API Key 是否配置正确。"
-      : "访问密码不正确或为空,请前往[登录](/#/auth)页输入正确的访问密码。",
+      : "访问密码不正确或为空,请前往[登录](/#/auth)页输入正确的访问密码,或者在[设置](/#/settings)页填入你自己的 OpenAI API Key。",
   },
   Auth: {
     Title: "需要密码",

+ 15 - 15
app/locales/index.ts

@@ -71,9 +71,9 @@ export const ALL_LANG_OPTIONS: Record<Lang, string> = {
 };
 
 const LANG_KEY = "lang";
-const DEFAULT_LANG = "cn";
+const DEFAULT_LANG = "en";
 
-const fallbackLang = cn;
+const fallbackLang = en;
 const targetLang = ALL_LANGS[getLang()] as LocaleType;
 
 // if target lang missing some fields, it will use fallback lang string
@@ -104,19 +104,19 @@ function getLanguage() {
 }
 
 export function getLang(): Lang {
-  // const savedLang = getItem(LANG_KEY);
-  //
-  // if (AllLangs.includes((savedLang ?? "") as Lang)) {
-  //   return savedLang as Lang;
-  // }
-  //
-  // const lang = getLanguage();
-  //
-  // for (const option of AllLangs) {
-  //   if (lang.includes(option)) {
-  //     return option;
-  //   }
-  // }
+  const savedLang = getItem(LANG_KEY);
+
+  if (AllLangs.includes((savedLang ?? "") as Lang)) {
+    return savedLang as Lang;
+  }
+
+  const lang = getLanguage();
+
+  for (const option of AllLangs) {
+    if (lang.includes(option)) {
+      return option;
+    }
+  }
 
   return DEFAULT_LANG;
 }

+ 3 - 5
app/masks/index.ts

@@ -22,8 +22,6 @@ export const BUILTIN_MASK_STORE = {
   },
 };
 
-export const BUILTIN_MASKS: BuiltinMask[] = [
-  ...CN_MASKS,
-  ...TW_MASKS,
-  ...EN_MASKS,
-].map((m) => BUILTIN_MASK_STORE.add(m));
+export const BUILTIN_MASKS: BuiltinMask[] = [...CN_MASKS, ...TW_MASKS, ...EN_MASKS].map(
+  (m) => BUILTIN_MASK_STORE.add(m),
+);

+ 3 - 3
app/store/config.ts

@@ -33,14 +33,14 @@ export const DEFAULT_CONFIG = {
   avatar: "1f603",
   fontSize: 14,
   theme: Theme.Auto as Theme,
-  tightBorder: !!getClientConfig()?.isApp,
-  sendPreviewBubble: false,
+  tightBorder: !!config?.isApp,
+  sendPreviewBubble: true,
   enableAutoGenerateTitle: true,
   sidebarWidth: DEFAULT_SIDEBAR_WIDTH,
 
   disablePromptHint: false,
 
-  dontShowMaskSplashScreen: true, // dont show splash screen when create chat
+  dontShowMaskSplashScreen: false, // dont show splash screen when create chat
   hideBuiltinMasks: false, // dont add builtin masks
 
   customModels: "",

+ 3 - 5
app/store/sync.ts

@@ -100,17 +100,15 @@ export const useSyncStore = createPersistStore(
         const remoteState = await client.get(config.username);
         if (!remoteState || remoteState === "") {
           await client.set(config.username, JSON.stringify(localState));
-          console.log(
-            "[Sync] Remote state is empty, using local state instead.",
-          );
-          return;
+          console.log("[Sync] Remote state is empty, using local state instead.");
+          return
         } else {
           const parsedRemoteState = JSON.parse(
             await client.get(config.username),
           ) as AppState;
           mergeAppState(localState, parsedRemoteState);
           setLocalAppState(localState);
-        }
+       } 
       } catch (e) {
         console.log("[Sync] failed to get remote state", e);
         throw e;

+ 1 - 1
package.json

@@ -65,5 +65,5 @@
   "resolutions": {
     "lint-staged/yaml": "^2.2.2"
   },
-  "version": "0.0.0"
+  "packageManager": "yarn@1.22.19"
 }

BIN
public/android-chrome-192x192.png


BIN
public/android-chrome-512x512.png


BIN
public/apple-touch-icon.png


BIN
public/favicon-16x16.png


BIN
public/favicon-32x32.png


BIN
public/favicon.ico


BIN
public/macos.png


BIN
src-tauri/icons/128x128.png


BIN
src-tauri/icons/128x128@2x.png


BIN
src-tauri/icons/32x32.png


BIN
src-tauri/icons/Square107x107Logo.png


BIN
src-tauri/icons/Square142x142Logo.png


BIN
src-tauri/icons/Square150x150Logo.png


BIN
src-tauri/icons/Square284x284Logo.png


BIN
src-tauri/icons/Square30x30Logo.png


BIN
src-tauri/icons/Square310x310Logo.png


BIN
src-tauri/icons/Square44x44Logo.png


BIN
src-tauri/icons/Square71x71Logo.png


BIN
src-tauri/icons/Square89x89Logo.png


BIN
src-tauri/icons/StoreLogo.png


BIN
src-tauri/icons/icon.icns


BIN
src-tauri/icons/icon.ico


BIN
src-tauri/icons/icon.png


Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov