Revert "Chat gpt"
@@ -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");
 | 
			
		||||
  // 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.");
 | 
			
		||||
    }
 | 
			
		||||
  // 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,
 | 
			
		||||
 
 | 
			
		||||
@@ -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 = "";
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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 />}*/}
 | 
			
		||||
      {/*  />*/}
 | 
			
		||||
      {/*)}*/}
 | 
			
		||||
      {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}*/}
 | 
			
		||||
      {/*    </>*/}
 | 
			
		||||
      {/*  }*/}
 | 
			
		||||
      {/*/>*/}
 | 
			
		||||
      {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={props.showPromptHints}
 | 
			
		||||
        text={Locale.Chat.InputActions.Prompt}
 | 
			
		||||
        icon={<PromptIcon />}
 | 
			
		||||
      />
 | 
			
		||||
 | 
			
		||||
      {/*<ChatAction*/}
 | 
			
		||||
      {/*  onClick={() => {*/}
 | 
			
		||||
      {/*    navigate(Path.Masks);*/}
 | 
			
		||||
      {/*  }}*/}
 | 
			
		||||
      {/*  text={Locale.Chat.InputActions.Masks}*/}
 | 
			
		||||
      {/*  icon={<MaskIcon />}*/}
 | 
			
		||||
      {/*/>*/}
 | 
			
		||||
      <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
 | 
			
		||||
        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
 | 
			
		||||
 
 | 
			
		||||
@@ -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.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.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.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.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.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.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 />*/}
 | 
			
		||||
        <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>*/}
 | 
			
		||||
        <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>*/}
 | 
			
		||||
          <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>*/}
 | 
			
		||||
        <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>*/}
 | 
			
		||||
          <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>*/}
 | 
			
		||||
        {/*  )}*/}
 | 
			
		||||
        <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.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}*/}
 | 
			
		||||
        {/*        </>*/}
 | 
			
		||||
        {/*      )}*/}
 | 
			
		||||
        {/*    </>*/}
 | 
			
		||||
        {/*  )}*/}
 | 
			
		||||
                  {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}*/}
 | 
			
		||||
          {!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>*/}
 | 
			
		||||
          <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)} />
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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 = [
 | 
			
		||||
 
 | 
			
		||||
@@ -1 +0,0 @@
 | 
			
		||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="43" height="44" fill="none" viewBox="0 0 43 44"><defs><rect id="path_0" width="43" height="43.58" x="0" y="0"/></defs><g opacity="1" transform="translate(0 0.000001981943071882597) rotate(0 21.5 21.790067598135053)"><mask id="bg-mask-0" fill="#fff"><use xlink:href="#path_0"/></mask><g mask="url(#bg-mask-0)"><path id="分组 1" fill-rule="evenodd" style="fill:#8bcae0" d="M40.17 17.84L40.17 17.84C40.53 16.73 40.72 15.57 40.72 14.41C40.72 12.48 40.21 10.58 39.23 8.92C37.27 5.51 33.64 3.41 29.71 3.41C28.94 3.41 28.16 3.49 27.41 3.65C25.35 1.33 22.39 0 19.29 0L19.22 0L19.19 0C14.43 0 10.21 3.07 8.74 7.6C5.68 8.23 3.03 10.15 1.48 12.87C0.51 14.54 0 16.45 0 18.38C0 21.1 1.01 23.73 2.83 25.74C2.47 26.85 2.28 28.01 2.28 29.17C2.28 31.1 2.79 33 3.77 34.66C6.14 38.8 10.92 40.93 15.59 39.93C17.65 42.25 20.61 43.58 23.71 43.58L23.78 43.58L23.81 43.58C28.57 43.58 32.8 40.51 34.26 35.97C37.33 35.35 39.97 33.43 41.52 30.71C42.49 29.03 43 27.13 43 25.2C43 22.48 41.99 19.86 40.17 17.84Z M18.817 38.6948C18.727 38.7448 18.647 38.7948 18.557 38.8448C20.017 40.0648 21.867 40.7348 23.777 40.7348L23.787 40.7348C28.287 40.7248 31.937 37.0648 31.947 32.5648L31.947 22.4348C31.937 22.3848 31.907 22.3548 31.877 22.3348L28.207 20.2148L28.207 32.4548C28.207 32.9648 27.937 33.4348 27.487 33.6848L18.817 38.6948Z M17.3932 36.223L26.1632 31.163C26.2032 31.133 26.2232 31.093 26.2232 31.053L26.2132 31.053L26.2132 26.813L15.6232 32.933C15.1832 33.183 14.6432 33.183 14.2032 32.933L5.52317 27.923C5.44317 27.873 5.32317 27.803 5.26317 27.763C5.18317 28.223 5.14317 28.693 5.14317 29.163C5.14317 30.593 5.52317 31.993 6.23317 33.233L6.23317 33.233C7.70317 35.763 10.3932 37.313 13.3132 37.313C14.7432 37.313 16.1532 36.943 17.3932 36.223Z M8.20584 11.013C8.20584 10.923 8.20584 10.783 8.20584 10.713C6.41583 11.373 4.90584 12.643 3.95583 14.293L3.95583 14.293C3.24583 15.533 2.86583 16.943 2.86583 18.373C2.86583 21.293 4.41583 23.983 6.94584 25.443L15.7158 30.513C15.7558 30.533 15.8058 30.533 15.8358 30.503L19.5058 28.383L8.91584 22.273C8.47583 22.023 8.20584 21.553 8.20584 21.043L8.20584 21.033L8.20584 11.013Z M36.0546 18.1303L27.2846 13.0603C27.2446 13.0403 27.1946 13.0503 27.1646 13.0703L23.4946 15.1903L34.0846 21.3103C34.5246 21.5603 34.7946 22.0203 34.7946 22.5303C34.7946 22.5303 34.7946 22.5403 34.7946 22.5403L34.7946 32.8603C38.0046 31.6803 40.1446 28.6203 40.1446 25.2003C40.1446 22.2803 38.5846 19.5903 36.0546 18.1303Z M16.8345 12.4124C16.8045 12.4424 16.7845 12.4824 16.7845 12.5224L16.7845 12.5224L16.7845 16.7624L27.3745 10.6424C27.5945 10.5224 27.8445 10.4524 28.0945 10.4524C28.3445 10.4524 28.5845 10.5224 28.8045 10.6424L37.4845 15.6624C37.5645 15.7124 37.6545 15.7624 37.7345 15.8124L37.7345 15.8124C37.8145 15.3524 37.8545 14.8924 37.8545 14.4324C37.8545 9.92236 34.1945 6.26236 29.6845 6.26236C28.2545 6.26236 26.8545 6.64236 25.6045 7.35236L16.8345 12.4124Z M19.2209 2.84925C14.7109 2.84925 11.0509 6.49925 11.0509 11.0093L11.0509 21.1393C11.0609 21.1893 11.0809 21.2193 11.1209 21.2393L14.7909 23.3593L14.8009 11.1293L14.8009 11.1193C14.8009 10.6193 15.0709 10.1493 15.5109 9.89925L24.1909 4.88925C24.2609 4.83925 24.3809 4.77925 24.4409 4.73925C22.9809 3.51925 21.1309 2.84925 19.2209 2.84925Z M16.783 24.5101L21.503 27.2401L26.223 24.5101L26.223 19.0601L21.503 16.3401L16.783 19.0701L16.783 24.5101Z" opacity=".27" transform="translate(0 0) rotate(0 21.5 21.790067598135053)"/></g></g></svg>
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 3.4 KiB  | 
@@ -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>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@ const cn = {
 | 
			
		||||
  Error: {
 | 
			
		||||
    Unauthorized: isApp
 | 
			
		||||
      ? "检测到无效 API Key,请前往[设置](/#/settings)页检查 API Key 是否配置正确。"
 | 
			
		||||
      : "访问密码不正确或为空,请前往[登录](/#/auth)页输入正确的访问密码。",
 | 
			
		||||
      : "访问密码不正确或为空,请前往[登录](/#/auth)页输入正确的访问密码,或者在[设置](/#/settings)页填入你自己的 OpenAI API Key。",
 | 
			
		||||
  },
 | 
			
		||||
  Auth: {
 | 
			
		||||
    Title: "需要密码",
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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),
 | 
			
		||||
);
 | 
			
		||||
 
 | 
			
		||||
@@ -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: "",
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -65,5 +65,5 @@
 | 
			
		||||
  "resolutions": {
 | 
			
		||||
    "lint-staged/yaml": "^2.2.2"
 | 
			
		||||
  },
 | 
			
		||||
  "version": "0.0.0"
 | 
			
		||||
  "packageManager": "yarn@1.22.19"
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 16 KiB  | 
| 
		 Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 65 KiB  | 
| 
		 Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 12 KiB  | 
| 
		 Before Width: | Height: | Size: 633 B After Width: | Height: | Size: 719 B  | 
| 
		 Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.6 KiB  | 
| 
		 Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								public/macos.png
									
									
									
									
									
								
							
							
						
						| 
		 Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 58 KiB  | 
| 
		 Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 14 KiB  | 
| 
		 Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 38 KiB  | 
| 
		 Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 2.3 KiB  | 
| 
		 Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 11 KiB  | 
| 
		 Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 16 KiB  | 
| 
		 Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 18 KiB  | 
| 
		 Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 45 KiB  | 
| 
		 Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 2.1 KiB  | 
| 
		 Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 52 KiB  | 
| 
		 Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.3 KiB  | 
| 
		 Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 6.0 KiB  | 
| 
		 Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 8.2 KiB  | 
| 
		 Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.9 KiB  | 
| 
		 Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 54 KiB  | 
| 
		 Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 65 KiB  |