| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710 |
- import { useState, useEffect, useMemo } from "react";
- import styles from "./settings.module.scss";
- import ResetIcon from "../icons/reload.svg";
- import AddIcon from "../icons/add.svg";
- import CloseIcon from "../icons/close.svg";
- import CopyIcon from "../icons/copy.svg";
- import ClearIcon from "../icons/clear.svg";
- import LoadingIcon from "../icons/three-dots.svg";
- import EditIcon from "../icons/edit.svg";
- import FireIcon from "../icons/fire.svg";
- import EyeIcon from "../icons/eye.svg";
- import DownloadIcon from "../icons/download.svg";
- import UploadIcon from "../icons/upload.svg";
- import ConfigIcon from "../icons/config.svg";
- import ConfirmIcon from "../icons/confirm.svg";
- import ConnectionIcon from "../icons/connection.svg";
- import CloudSuccessIcon from "../icons/cloud-success.svg";
- import CloudFailIcon from "../icons/cloud-fail.svg";
- import { trackSettingsPageGuideToCPaymentClick } from "../utils/auth-settings-events";
- import {
- Input,
- List,
- ListItem,
- Modal,
- PasswordInput,
- Popover,
- Select,
- showConfirm,
- showToast,
- } from "./ui-lib";
- import { ModelConfigList } from "./model-config";
- import { IconButton } from "./button";
- import {
- SubmitKey,
- useChatStore,
- Theme,
- useUpdateStore,
- useAccessStore,
- useAppConfig,
- } from "../store";
- import Locale, {
- AllLangs,
- ALL_LANG_OPTIONS,
- changeLang,
- getLang,
- } from "../locales";
- import { copyToClipboard } from "../utils";
- import Link from "next/link";
- import {
- Anthropic,
- Azure,
- Baidu,
- Tencent,
- ByteDance,
- Alibaba,
- Moonshot,
- Google,
- GoogleSafetySettingsThreshold,
- OPENAI_BASE_URL,
- Path,
- RELEASE_URL,
- STORAGE_KEY,
- ServiceProvider,
- SlotID,
- UPDATE_URL,
- Stability,
- Iflytek,
- SAAS_CHAT_URL,
- } from "../constant";
- import { Prompt, SearchService, usePromptStore } from "../store/prompt";
- import { ErrorBoundary } from "./error";
- import { InputRange } from "./input-range";
- import { useNavigate } from "react-router-dom";
- import { Avatar, AvatarPicker } from "./emoji";
- import { getClientConfig } from "../config/client";
- import { useSyncStore } from "../store/sync";
- import { nanoid } from "nanoid";
- import { useMaskStore } from "../store/mask";
- import { ProviderType } from "../utils/cloud";
- import { TTSConfigList } from "./tts-config";
- function EditPromptModal(props: { id: string; onClose: () => void }) {
- const promptStore = usePromptStore();
- const prompt = promptStore.get(props.id);
- return prompt ? (
- <div className="modal-mask">
- <Modal
- title={Locale.Settings.Prompt.EditModal.Title}
- onClose={props.onClose}
- actions={[
- <IconButton
- key=""
- onClick={props.onClose}
- text={Locale.UI.Confirm}
- bordered
- />,
- ]}
- >
- <div className={styles["edit-prompt-modal"]}>
- <input
- type="text"
- value={prompt.title}
- readOnly={!prompt.isUser}
- className={styles["edit-prompt-title"]}
- onInput={(e) =>
- promptStore.updatePrompt(
- props.id,
- (prompt) => (prompt.title = e.currentTarget.value),
- )
- }
- ></input>
- <Input
- value={prompt.content}
- readOnly={!prompt.isUser}
- className={styles["edit-prompt-content"]}
- rows={10}
- onInput={(e) =>
- promptStore.updatePrompt(
- props.id,
- (prompt) => (prompt.content = e.currentTarget.value),
- )
- }
- ></Input>
- </div>
- </Modal>
- </div>
- ) : null;
- }
- function UserPromptModal(props: { onClose?: () => void }) {
- const promptStore = usePromptStore();
- const userPrompts = promptStore.getUserPrompts();
- const builtinPrompts = SearchService.builtinPrompts;
- const allPrompts = userPrompts.concat(builtinPrompts);
- const [searchInput, setSearchInput] = useState("");
- const [searchPrompts, setSearchPrompts] = useState<Prompt[]>([]);
- const prompts = searchInput.length > 0 ? searchPrompts : allPrompts;
- const [editingPromptId, setEditingPromptId] = useState<string>();
- useEffect(() => {
- if (searchInput.length > 0) {
- const searchResult = SearchService.search(searchInput);
- setSearchPrompts(searchResult);
- } else {
- setSearchPrompts([]);
- }
- }, [searchInput]);
- return (
- <div className="modal-mask">
- <Modal
- title={Locale.Settings.Prompt.Modal.Title}
- onClose={() => props.onClose?.()}
- actions={[
- <IconButton
- key="add"
- onClick={() => {
- const promptId = promptStore.add({
- id: nanoid(),
- createdAt: Date.now(),
- title: "Empty Prompt",
- content: "Empty Prompt Content",
- });
- setEditingPromptId(promptId);
- }}
- icon={<AddIcon />}
- bordered
- text={Locale.Settings.Prompt.Modal.Add}
- />,
- ]}
- >
- <div className={styles["user-prompt-modal"]}>
- <input
- type="text"
- className={styles["user-prompt-search"]}
- placeholder={Locale.Settings.Prompt.Modal.Search}
- value={searchInput}
- onInput={(e) => setSearchInput(e.currentTarget.value)}
- ></input>
- <div className={styles["user-prompt-list"]}>
- {prompts.map((v, _) => (
- <div className={styles["user-prompt-item"]} key={v.id ?? v.title}>
- <div className={styles["user-prompt-header"]}>
- <div className={styles["user-prompt-title"]}>{v.title}</div>
- <div className={styles["user-prompt-content"] + " one-line"}>
- {v.content}
- </div>
- </div>
- <div className={styles["user-prompt-buttons"]}>
- {v.isUser && (
- <IconButton
- icon={<ClearIcon />}
- className={styles["user-prompt-button"]}
- onClick={() => promptStore.remove(v.id!)}
- />
- )}
- {v.isUser ? (
- <IconButton
- icon={<EditIcon />}
- className={styles["user-prompt-button"]}
- onClick={() => setEditingPromptId(v.id)}
- />
- ) : (
- <IconButton
- icon={<EyeIcon />}
- className={styles["user-prompt-button"]}
- onClick={() => setEditingPromptId(v.id)}
- />
- )}
- <IconButton
- icon={<CopyIcon />}
- className={styles["user-prompt-button"]}
- onClick={() => copyToClipboard(v.content)}
- />
- </div>
- </div>
- ))}
- </div>
- </div>
- </Modal>
- {editingPromptId !== undefined && (
- <EditPromptModal
- id={editingPromptId!}
- onClose={() => setEditingPromptId(undefined)}
- />
- )}
- </div>
- );
- }
- function DangerItems() {
- const chatStore = useChatStore();
- const appConfig = useAppConfig();
- return (
- <List>
- <ListItem
- title={Locale.Settings.Danger.Reset.Title}
- subTitle={Locale.Settings.Danger.Reset.SubTitle}
- >
- <IconButton
- aria={Locale.Settings.Danger.Reset.Title}
- text={Locale.Settings.Danger.Reset.Action}
- onClick={async () => {
- if (await showConfirm(Locale.Settings.Danger.Reset.Confirm)) {
- appConfig.reset();
- }
- }}
- type="danger"
- />
- </ListItem>
- <ListItem
- title={Locale.Settings.Danger.Clear.Title}
- subTitle={Locale.Settings.Danger.Clear.SubTitle}
- >
- <IconButton
- aria={Locale.Settings.Danger.Clear.Title}
- text={Locale.Settings.Danger.Clear.Action}
- onClick={async () => {
- if (await showConfirm(Locale.Settings.Danger.Clear.Confirm)) {
- chatStore.clearAllData();
- }
- }}
- type="danger"
- />
- </ListItem>
- </List>
- );
- }
- function CheckButton() {
- const syncStore = useSyncStore();
- const couldCheck = useMemo(() => {
- return syncStore.cloudSync();
- }, [syncStore]);
- const [checkState, setCheckState] = useState<
- "none" | "checking" | "success" | "failed"
- >("none");
- async function check() {
- setCheckState("checking");
- const valid = await syncStore.check();
- setCheckState(valid ? "success" : "failed");
- }
- if (!couldCheck) return null;
- return (
- <IconButton
- text={Locale.Settings.Sync.Config.Modal.Check}
- bordered
- onClick={check}
- icon={
- checkState === "none" ? (
- <ConnectionIcon />
- ) : checkState === "checking" ? (
- <LoadingIcon />
- ) : checkState === "success" ? (
- <CloudSuccessIcon />
- ) : checkState === "failed" ? (
- <CloudFailIcon />
- ) : (
- <ConnectionIcon />
- )
- }
- ></IconButton>
- );
- }
- function SyncConfigModal(props: { onClose?: () => void }) {
- const syncStore = useSyncStore();
- return (
- <div className="modal-mask">
- <Modal
- title={Locale.Settings.Sync.Config.Modal.Title}
- onClose={() => props.onClose?.()}
- actions={[
- <CheckButton key="check" />,
- <IconButton
- key="confirm"
- onClick={props.onClose}
- icon={<ConfirmIcon />}
- bordered
- text={Locale.UI.Confirm}
- />,
- ]}
- >
- <List>
- <ListItem
- title={Locale.Settings.Sync.Config.SyncType.Title}
- subTitle={Locale.Settings.Sync.Config.SyncType.SubTitle}
- >
- <select
- value={syncStore.provider}
- onChange={(e) => {
- syncStore.update(
- (config) =>
- (config.provider = e.target.value as ProviderType),
- );
- }}
- >
- {Object.entries(ProviderType).map(([k, v]) => (
- <option value={v} key={k}>
- {k}
- </option>
- ))}
- </select>
- </ListItem>
- <ListItem
- title={Locale.Settings.Sync.Config.Proxy.Title}
- subTitle={Locale.Settings.Sync.Config.Proxy.SubTitle}
- >
- <input
- type="checkbox"
- checked={syncStore.useProxy}
- onChange={(e) => {
- syncStore.update(
- (config) => (config.useProxy = e.currentTarget.checked),
- );
- }}
- ></input>
- </ListItem>
- {syncStore.useProxy ? (
- <ListItem
- title={Locale.Settings.Sync.Config.ProxyUrl.Title}
- subTitle={Locale.Settings.Sync.Config.ProxyUrl.SubTitle}
- >
- <input
- type="text"
- value={syncStore.proxyUrl}
- onChange={(e) => {
- syncStore.update(
- (config) => (config.proxyUrl = e.currentTarget.value),
- );
- }}
- ></input>
- </ListItem>
- ) : null}
- </List>
- {syncStore.provider === ProviderType.WebDAV && (
- <>
- <List>
- <ListItem title={Locale.Settings.Sync.Config.WebDav.Endpoint}>
- <input
- type="text"
- value={syncStore.webdav.endpoint}
- onChange={(e) => {
- syncStore.update(
- (config) =>
- (config.webdav.endpoint = e.currentTarget.value),
- );
- }}
- ></input>
- </ListItem>
- <ListItem title={Locale.Settings.Sync.Config.WebDav.UserName}>
- <input
- type="text"
- value={syncStore.webdav.username}
- onChange={(e) => {
- syncStore.update(
- (config) =>
- (config.webdav.username = e.currentTarget.value),
- );
- }}
- ></input>
- </ListItem>
- <ListItem title={Locale.Settings.Sync.Config.WebDav.Password}>
- <PasswordInput
- value={syncStore.webdav.password}
- onChange={(e) => {
- syncStore.update(
- (config) =>
- (config.webdav.password = e.currentTarget.value),
- );
- }}
- ></PasswordInput>
- </ListItem>
- </List>
- </>
- )}
- {syncStore.provider === ProviderType.UpStash && (
- <List>
- <ListItem title={Locale.Settings.Sync.Config.UpStash.Endpoint}>
- <input
- type="text"
- value={syncStore.upstash.endpoint}
- onChange={(e) => {
- syncStore.update(
- (config) =>
- (config.upstash.endpoint = e.currentTarget.value),
- );
- }}
- ></input>
- </ListItem>
- <ListItem title={Locale.Settings.Sync.Config.UpStash.UserName}>
- <input
- type="text"
- value={syncStore.upstash.username}
- placeholder={STORAGE_KEY}
- onChange={(e) => {
- syncStore.update(
- (config) =>
- (config.upstash.username = e.currentTarget.value),
- );
- }}
- ></input>
- </ListItem>
- <ListItem title={Locale.Settings.Sync.Config.UpStash.Password}>
- <PasswordInput
- value={syncStore.upstash.apiKey}
- onChange={(e) => {
- syncStore.update(
- (config) => (config.upstash.apiKey = e.currentTarget.value),
- );
- }}
- ></PasswordInput>
- </ListItem>
- </List>
- )}
- </Modal>
- </div>
- );
- }
- function SyncItems() {
- const syncStore = useSyncStore();
- const chatStore = useChatStore();
- const promptStore = usePromptStore();
- const maskStore = useMaskStore();
- const couldSync = useMemo(() => {
- return syncStore.cloudSync();
- }, [syncStore]);
- const [showSyncConfigModal, setShowSyncConfigModal] = useState(false);
- const stateOverview = useMemo(() => {
- const sessions = chatStore.sessions;
- const messageCount = sessions.reduce((p, c) => p + c.messages.length, 0);
- return {
- chat: sessions.length,
- message: messageCount,
- prompt: Object.keys(promptStore.prompts).length,
- mask: Object.keys(maskStore.masks).length,
- };
- }, [chatStore.sessions, maskStore.masks, promptStore.prompts]);
- return (
- <>
- <List>
- <ListItem
- title={Locale.Settings.Sync.CloudState}
- subTitle={
- syncStore.lastProvider
- ? `${new Date(syncStore.lastSyncTime).toLocaleString()} [${
- syncStore.lastProvider
- }]`
- : Locale.Settings.Sync.NotSyncYet
- }
- >
- <div style={{ display: "flex" }}>
- <IconButton
- aria={Locale.Settings.Sync.CloudState + Locale.UI.Config}
- icon={<ConfigIcon />}
- text={Locale.UI.Config}
- onClick={() => {
- setShowSyncConfigModal(true);
- }}
- />
- {couldSync && (
- <IconButton
- icon={<ResetIcon />}
- text={Locale.UI.Sync}
- onClick={async () => {
- try {
- await syncStore.sync();
- showToast(Locale.Settings.Sync.Success);
- } catch (e) {
- showToast(Locale.Settings.Sync.Fail);
- console.error("[Sync]", e);
- }
- }}
- />
- )}
- </div>
- </ListItem>
- <ListItem
- title={Locale.Settings.Sync.LocalState}
- subTitle={Locale.Settings.Sync.Overview(stateOverview)}
- >
- <div style={{ display: "flex" }}>
- <IconButton
- aria={Locale.Settings.Sync.LocalState + Locale.UI.Export}
- icon={<UploadIcon />}
- text={Locale.UI.Export}
- onClick={() => {
- syncStore.export();
- }}
- />
- <IconButton
- aria={Locale.Settings.Sync.LocalState + Locale.UI.Import}
- icon={<DownloadIcon />}
- text={Locale.UI.Import}
- onClick={() => {
- syncStore.import();
- }}
- />
- </div>
- </ListItem>
- </List>
- {showSyncConfigModal && (
- <SyncConfigModal onClose={() => setShowSyncConfigModal(false)} />
- )}
- </>
- );
- }
- export function Settings() {
- const navigate = useNavigate();
- const [showEmojiPicker, setShowEmojiPicker] = useState(false);
- const config = useAppConfig();
- const updateConfig = config.update;
- const updateStore = useUpdateStore();
- const [checkingUpdate, setCheckingUpdate] = useState(false);
- const currentVersion = updateStore.formatVersion(updateStore.version);
- const remoteId = updateStore.formatVersion(updateStore.remoteVersion);
- const hasNewVersion = currentVersion !== remoteId;
- const updateUrl = getClientConfig()?.isApp ? RELEASE_URL : UPDATE_URL;
- function checkUpdate(force = false) {
- setCheckingUpdate(true);
- updateStore.getLatestVersion(force).then(() => {
- setCheckingUpdate(false);
- });
- console.log("[Update] local version ", updateStore.version);
- console.log("[Update] remote version ", updateStore.remoteVersion);
- }
- const accessStore = useAccessStore();
- const shouldHideBalanceQuery = useMemo(() => {
- const isOpenAiUrl = accessStore.openaiUrl.includes(OPENAI_BASE_URL);
- return (
- accessStore.hideBalanceQuery ||
- isOpenAiUrl ||
- accessStore.provider === ServiceProvider.Azure
- );
- }, [
- accessStore.hideBalanceQuery,
- accessStore.openaiUrl,
- accessStore.provider,
- ]);
- const usage = {
- used: updateStore.used,
- subscription: updateStore.subscription,
- };
- const [loadingUsage, setLoadingUsage] = useState(false);
- function checkUsage(force = false) {
- if (shouldHideBalanceQuery) {
- return;
- }
- setLoadingUsage(true);
- updateStore.updateUsage(force).finally(() => {
- setLoadingUsage(false);
- });
- }
- const enabledAccessControl = useMemo(
- () => accessStore.enabledAccessControl(),
- // eslint-disable-next-line react-hooks/exhaustive-deps
- [],
- );
- const promptStore = usePromptStore();
- const builtinCount = SearchService.count.builtin;
- const customCount = promptStore.getUserPrompts().length ?? 0;
- const [shouldShowPromptModal, setShowPromptModal] = useState(false);
- const showUsage = accessStore.isAuthorized();
- useEffect(() => {
- // checks per minutes
- checkUpdate();
- showUsage && checkUsage();
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, []);
- useEffect(() => {
- const keydownEvent = (e: KeyboardEvent) => {
- if (e.key === "Escape") {
- navigate(Path.Home);
- }
- };
- if (clientConfig?.isApp) {
- // Force to set custom endpoint to true if it's app
- accessStore.update((state) => {
- state.useCustomConfig = true;
- });
- }
- document.addEventListener("keydown", keydownEvent);
- return () => {
- document.removeEventListener("keydown", keydownEvent);
- };
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, []);
- const clientConfig = useMemo(() => getClientConfig(), []);
- const showAccessCode = enabledAccessControl && !clientConfig?.isApp;
- const accessCodeComponent = 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>
- );
- const saasStartComponent = (
- <ListItem
- className={styles["subtitle-button"]}
- title={
- Locale.Settings.Access.SaasStart.Title +
- `${Locale.Settings.Access.SaasStart.Label}`
- }
- subTitle={Locale.Settings.Access.SaasStart.SubTitle}
- >
- <IconButton
- aria={
- Locale.Settings.Access.SaasStart.Title +
- Locale.Settings.Access.SaasStart.ChatNow
- }
- icon={<FireIcon />}
- type={"primary"}
- text={Locale.Settings.Access.SaasStart.ChatNow}
- onClick={() => {
- trackSettingsPageGuideToCPaymentClick();
- window.location.href = SAAS_CHAT_URL;
- }}
- />
- </ListItem>
- );
- const useCustomConfigComponent = // 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
- aria-label={Locale.Settings.Access.CustomEndpoint.Title}
- type="checkbox"
- checked={accessStore.useCustomConfig}
- onChange={(e) =>
- accessStore.update(
- (access) => (access.useCustomConfig = e.currentTarget.checked),
- )
- }
- ></input>
- </ListItem>
- );
- const openAIConfigComponent = accessStore.provider ===
- ServiceProvider.OpenAI && (
- <>
- <ListItem
- title={Locale.Settings.Access.OpenAI.Endpoint.Title}
- subTitle={Locale.Settings.Access.OpenAI.Endpoint.SubTitle}
- >
- <input
- aria-label={Locale.Settings.Access.OpenAI.Endpoint.Title}
- 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
- aria={Locale.Settings.ShowPassword}
- aria-label={Locale.Settings.Access.OpenAI.ApiKey.Title}
- value={accessStore.openaiApiKey}
- type="text"
- placeholder={Locale.Settings.Access.OpenAI.ApiKey.Placeholder}
- onChange={(e) => {
- accessStore.update(
- (access) => (access.openaiApiKey = e.currentTarget.value),
- );
- }}
- />
- </ListItem>
- </>
- );
- const azureConfigComponent = accessStore.provider ===
- ServiceProvider.Azure && (
- <>
- <ListItem
- title={Locale.Settings.Access.Azure.Endpoint.Title}
- subTitle={
- Locale.Settings.Access.Azure.Endpoint.SubTitle + Azure.ExampleEndpoint
- }
- >
- <input
- aria-label={Locale.Settings.Access.Azure.Endpoint.Title}
- 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
- aria-label={Locale.Settings.Access.Azure.ApiKey.Title}
- 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
- aria-label={Locale.Settings.Access.Azure.ApiVerion.Title}
- type="text"
- value={accessStore.azureApiVersion}
- placeholder="2023-08-01-preview"
- onChange={(e) =>
- accessStore.update(
- (access) => (access.azureApiVersion = e.currentTarget.value),
- )
- }
- ></input>
- </ListItem>
- </>
- );
- const googleConfigComponent = accessStore.provider ===
- ServiceProvider.Google && (
- <>
- <ListItem
- title={Locale.Settings.Access.Google.Endpoint.Title}
- subTitle={
- Locale.Settings.Access.Google.Endpoint.SubTitle +
- Google.ExampleEndpoint
- }
- >
- <input
- aria-label={Locale.Settings.Access.Google.Endpoint.Title}
- 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
- aria-label={Locale.Settings.Access.Google.ApiKey.Title}
- 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
- aria-label={Locale.Settings.Access.Google.ApiVersion.Title}
- type="text"
- value={accessStore.googleApiVersion}
- placeholder="2023-08-01-preview"
- onChange={(e) =>
- accessStore.update(
- (access) => (access.googleApiVersion = e.currentTarget.value),
- )
- }
- ></input>
- </ListItem>
- <ListItem
- title={Locale.Settings.Access.Google.GoogleSafetySettings.Title}
- subTitle={Locale.Settings.Access.Google.GoogleSafetySettings.SubTitle}
- >
- <Select
- aria-label={Locale.Settings.Access.Google.GoogleSafetySettings.Title}
- value={accessStore.googleSafetySettings}
- onChange={(e) => {
- accessStore.update(
- (access) =>
- (access.googleSafetySettings = e.target
- .value as GoogleSafetySettingsThreshold),
- );
- }}
- >
- {Object.entries(GoogleSafetySettingsThreshold).map(([k, v]) => (
- <option value={v} key={k}>
- {k}
- </option>
- ))}
- </Select>
- </ListItem>
- </>
- );
- const anthropicConfigComponent = accessStore.provider ===
- ServiceProvider.Anthropic && (
- <>
- <ListItem
- title={Locale.Settings.Access.Anthropic.Endpoint.Title}
- subTitle={
- Locale.Settings.Access.Anthropic.Endpoint.SubTitle +
- Anthropic.ExampleEndpoint
- }
- >
- <input
- aria-label={Locale.Settings.Access.Anthropic.Endpoint.Title}
- 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
- aria-label={Locale.Settings.Access.Anthropic.ApiKey.Title}
- 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
- aria-label={Locale.Settings.Access.Anthropic.ApiVerion.Title}
- type="text"
- value={accessStore.anthropicApiVersion}
- placeholder={Anthropic.Vision}
- onChange={(e) =>
- accessStore.update(
- (access) => (access.anthropicApiVersion = e.currentTarget.value),
- )
- }
- ></input>
- </ListItem>
- </>
- );
- const baiduConfigComponent = accessStore.provider ===
- ServiceProvider.Baidu && (
- <>
- <ListItem
- title={Locale.Settings.Access.Baidu.Endpoint.Title}
- subTitle={Locale.Settings.Access.Baidu.Endpoint.SubTitle}
- >
- <input
- aria-label={Locale.Settings.Access.Baidu.Endpoint.Title}
- type="text"
- value={accessStore.baiduUrl}
- placeholder={Baidu.ExampleEndpoint}
- onChange={(e) =>
- accessStore.update(
- (access) => (access.baiduUrl = e.currentTarget.value),
- )
- }
- ></input>
- </ListItem>
- <ListItem
- title={Locale.Settings.Access.Baidu.ApiKey.Title}
- subTitle={Locale.Settings.Access.Baidu.ApiKey.SubTitle}
- >
- <PasswordInput
- aria-label={Locale.Settings.Access.Baidu.ApiKey.Title}
- value={accessStore.baiduApiKey}
- type="text"
- placeholder={Locale.Settings.Access.Baidu.ApiKey.Placeholder}
- onChange={(e) => {
- accessStore.update(
- (access) => (access.baiduApiKey = e.currentTarget.value),
- );
- }}
- />
- </ListItem>
- <ListItem
- title={Locale.Settings.Access.Baidu.SecretKey.Title}
- subTitle={Locale.Settings.Access.Baidu.SecretKey.SubTitle}
- >
- <PasswordInput
- aria-label={Locale.Settings.Access.Baidu.SecretKey.Title}
- value={accessStore.baiduSecretKey}
- type="text"
- placeholder={Locale.Settings.Access.Baidu.SecretKey.Placeholder}
- onChange={(e) => {
- accessStore.update(
- (access) => (access.baiduSecretKey = e.currentTarget.value),
- );
- }}
- />
- </ListItem>
- </>
- );
- const tencentConfigComponent = accessStore.provider ===
- ServiceProvider.Tencent && (
- <>
- <ListItem
- title={Locale.Settings.Access.Tencent.Endpoint.Title}
- subTitle={Locale.Settings.Access.Tencent.Endpoint.SubTitle}
- >
- <input
- aria-label={Locale.Settings.Access.Tencent.Endpoint.Title}
- type="text"
- value={accessStore.tencentUrl}
- placeholder={Tencent.ExampleEndpoint}
- onChange={(e) =>
- accessStore.update(
- (access) => (access.tencentUrl = e.currentTarget.value),
- )
- }
- ></input>
- </ListItem>
- <ListItem
- title={Locale.Settings.Access.Tencent.ApiKey.Title}
- subTitle={Locale.Settings.Access.Tencent.ApiKey.SubTitle}
- >
- <PasswordInput
- aria-label={Locale.Settings.Access.Tencent.ApiKey.Title}
- value={accessStore.tencentSecretId}
- type="text"
- placeholder={Locale.Settings.Access.Tencent.ApiKey.Placeholder}
- onChange={(e) => {
- accessStore.update(
- (access) => (access.tencentSecretId = e.currentTarget.value),
- );
- }}
- />
- </ListItem>
- <ListItem
- title={Locale.Settings.Access.Tencent.SecretKey.Title}
- subTitle={Locale.Settings.Access.Tencent.SecretKey.SubTitle}
- >
- <PasswordInput
- aria-label={Locale.Settings.Access.Tencent.SecretKey.Title}
- value={accessStore.tencentSecretKey}
- type="text"
- placeholder={Locale.Settings.Access.Tencent.SecretKey.Placeholder}
- onChange={(e) => {
- accessStore.update(
- (access) => (access.tencentSecretKey = e.currentTarget.value),
- );
- }}
- />
- </ListItem>
- </>
- );
- const byteDanceConfigComponent = accessStore.provider ===
- ServiceProvider.ByteDance && (
- <>
- <ListItem
- title={Locale.Settings.Access.ByteDance.Endpoint.Title}
- subTitle={
- Locale.Settings.Access.ByteDance.Endpoint.SubTitle +
- ByteDance.ExampleEndpoint
- }
- >
- <input
- aria-label={Locale.Settings.Access.ByteDance.Endpoint.Title}
- type="text"
- value={accessStore.bytedanceUrl}
- placeholder={ByteDance.ExampleEndpoint}
- onChange={(e) =>
- accessStore.update(
- (access) => (access.bytedanceUrl = e.currentTarget.value),
- )
- }
- ></input>
- </ListItem>
- <ListItem
- title={Locale.Settings.Access.ByteDance.ApiKey.Title}
- subTitle={Locale.Settings.Access.ByteDance.ApiKey.SubTitle}
- >
- <PasswordInput
- aria-label={Locale.Settings.Access.ByteDance.ApiKey.Title}
- value={accessStore.bytedanceApiKey}
- type="text"
- placeholder={Locale.Settings.Access.ByteDance.ApiKey.Placeholder}
- onChange={(e) => {
- accessStore.update(
- (access) => (access.bytedanceApiKey = e.currentTarget.value),
- );
- }}
- />
- </ListItem>
- </>
- );
- const alibabaConfigComponent = accessStore.provider ===
- ServiceProvider.Alibaba && (
- <>
- <ListItem
- title={Locale.Settings.Access.Alibaba.Endpoint.Title}
- subTitle={
- Locale.Settings.Access.Alibaba.Endpoint.SubTitle +
- Alibaba.ExampleEndpoint
- }
- >
- <input
- aria-label={Locale.Settings.Access.Alibaba.Endpoint.Title}
- type="text"
- value={accessStore.alibabaUrl}
- placeholder={Alibaba.ExampleEndpoint}
- onChange={(e) =>
- accessStore.update(
- (access) => (access.alibabaUrl = e.currentTarget.value),
- )
- }
- ></input>
- </ListItem>
- <ListItem
- title={Locale.Settings.Access.Alibaba.ApiKey.Title}
- subTitle={Locale.Settings.Access.Alibaba.ApiKey.SubTitle}
- >
- <PasswordInput
- aria-label={Locale.Settings.Access.Alibaba.ApiKey.Title}
- value={accessStore.alibabaApiKey}
- type="text"
- placeholder={Locale.Settings.Access.Alibaba.ApiKey.Placeholder}
- onChange={(e) => {
- accessStore.update(
- (access) => (access.alibabaApiKey = e.currentTarget.value),
- );
- }}
- />
- </ListItem>
- </>
- );
- const moonshotConfigComponent = accessStore.provider ===
- ServiceProvider.Moonshot && (
- <>
- <ListItem
- title={Locale.Settings.Access.Moonshot.Endpoint.Title}
- subTitle={
- Locale.Settings.Access.Moonshot.Endpoint.SubTitle +
- Moonshot.ExampleEndpoint
- }
- >
- <input
- aria-label={Locale.Settings.Access.Moonshot.Endpoint.Title}
- type="text"
- value={accessStore.moonshotUrl}
- placeholder={Moonshot.ExampleEndpoint}
- onChange={(e) =>
- accessStore.update(
- (access) => (access.moonshotUrl = e.currentTarget.value),
- )
- }
- ></input>
- </ListItem>
- <ListItem
- title={Locale.Settings.Access.Moonshot.ApiKey.Title}
- subTitle={Locale.Settings.Access.Moonshot.ApiKey.SubTitle}
- >
- <PasswordInput
- aria-label={Locale.Settings.Access.Moonshot.ApiKey.Title}
- value={accessStore.moonshotApiKey}
- type="text"
- placeholder={Locale.Settings.Access.Moonshot.ApiKey.Placeholder}
- onChange={(e) => {
- accessStore.update(
- (access) => (access.moonshotApiKey = e.currentTarget.value),
- );
- }}
- />
- </ListItem>
- </>
- );
- const stabilityConfigComponent = accessStore.provider ===
- ServiceProvider.Stability && (
- <>
- <ListItem
- title={Locale.Settings.Access.Stability.Endpoint.Title}
- subTitle={
- Locale.Settings.Access.Stability.Endpoint.SubTitle +
- Stability.ExampleEndpoint
- }
- >
- <input
- aria-label={Locale.Settings.Access.Stability.Endpoint.Title}
- type="text"
- value={accessStore.stabilityUrl}
- placeholder={Stability.ExampleEndpoint}
- onChange={(e) =>
- accessStore.update(
- (access) => (access.stabilityUrl = e.currentTarget.value),
- )
- }
- ></input>
- </ListItem>
- <ListItem
- title={Locale.Settings.Access.Stability.ApiKey.Title}
- subTitle={Locale.Settings.Access.Stability.ApiKey.SubTitle}
- >
- <PasswordInput
- aria-label={Locale.Settings.Access.Stability.ApiKey.Title}
- value={accessStore.stabilityApiKey}
- type="text"
- placeholder={Locale.Settings.Access.Stability.ApiKey.Placeholder}
- onChange={(e) => {
- accessStore.update(
- (access) => (access.stabilityApiKey = e.currentTarget.value),
- );
- }}
- />
- </ListItem>
- </>
- );
- const lflytekConfigComponent = accessStore.provider ===
- ServiceProvider.Iflytek && (
- <>
- <ListItem
- title={Locale.Settings.Access.Iflytek.Endpoint.Title}
- subTitle={
- Locale.Settings.Access.Iflytek.Endpoint.SubTitle +
- Iflytek.ExampleEndpoint
- }
- >
- <input
- aria-label={Locale.Settings.Access.Iflytek.Endpoint.Title}
- type="text"
- value={accessStore.iflytekUrl}
- placeholder={Iflytek.ExampleEndpoint}
- onChange={(e) =>
- accessStore.update(
- (access) => (access.iflytekUrl = e.currentTarget.value),
- )
- }
- ></input>
- </ListItem>
- <ListItem
- title={Locale.Settings.Access.Iflytek.ApiKey.Title}
- subTitle={Locale.Settings.Access.Iflytek.ApiKey.SubTitle}
- >
- <PasswordInput
- aria-label={Locale.Settings.Access.Iflytek.ApiKey.Title}
- value={accessStore.iflytekApiKey}
- type="text"
- placeholder={Locale.Settings.Access.Iflytek.ApiKey.Placeholder}
- onChange={(e) => {
- accessStore.update(
- (access) => (access.iflytekApiKey = e.currentTarget.value),
- );
- }}
- />
- </ListItem>
- <ListItem
- title={Locale.Settings.Access.Iflytek.ApiSecret.Title}
- subTitle={Locale.Settings.Access.Iflytek.ApiSecret.SubTitle}
- >
- <PasswordInput
- aria-label={Locale.Settings.Access.Iflytek.ApiSecret.Title}
- value={accessStore.iflytekApiSecret}
- type="text"
- placeholder={Locale.Settings.Access.Iflytek.ApiSecret.Placeholder}
- onChange={(e) => {
- accessStore.update(
- (access) => (access.iflytekApiSecret = e.currentTarget.value),
- );
- }}
- />
- </ListItem>
- </>
- );
- return (
- <ErrorBoundary>
- <div className="window-header" data-tauri-drag-region>
- <div className="window-header-title">
- <div className="window-header-main-title">
- {Locale.Settings.Title}
- </div>
- <div className="window-header-sub-title">
- {Locale.Settings.SubTitle}
- </div>
- </div>
- <div className="window-actions">
- <div className="window-action-button"></div>
- <div className="window-action-button"></div>
- <div className="window-action-button">
- <IconButton
- aria={Locale.UI.Close}
- icon={<CloseIcon />}
- onClick={() => navigate(Path.Home)}
- bordered
- />
- </div>
- </div>
- </div>
- <div className={styles["settings"]}>
- <List>
- <ListItem title={Locale.Settings.Avatar}>
- <Popover
- onClose={() => setShowEmojiPicker(false)}
- content={
- <AvatarPicker
- onEmojiClick={(avatar: string) => {
- updateConfig((config) => (config.avatar = avatar));
- setShowEmojiPicker(false);
- }}
- />
- }
- open={showEmojiPicker}
- >
- <div
- aria-label={Locale.Settings.Avatar}
- tabIndex={0}
- className={styles.avatar}
- onClick={() => {
- setShowEmojiPicker(!showEmojiPicker);
- }}
- >
- <Avatar avatar={config.avatar} />
- </div>
- </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
- aria-label={Locale.Settings.SendKey}
- 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
- aria-label={Locale.Settings.Theme}
- 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
- aria-label={Locale.Settings.Lang.Name}
- 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}
- subTitle={Locale.Settings.FontSize.SubTitle}
- >
- <InputRange
- aria={Locale.Settings.FontSize.Title}
- title={`${config.fontSize ?? 14}px`}
- value={config.fontSize}
- min="12"
- max="40"
- step="1"
- onChange={(e) =>
- updateConfig(
- (config) =>
- (config.fontSize = Number.parseInt(e.currentTarget.value)),
- )
- }
- ></InputRange>
- </ListItem>
- <ListItem
- title={Locale.Settings.FontFamily.Title}
- subTitle={Locale.Settings.FontFamily.SubTitle}
- >
- <input
- aria-label={Locale.Settings.FontFamily.Title}
- type="text"
- value={config.fontFamily}
- placeholder={Locale.Settings.FontFamily.Placeholder}
- onChange={(e) =>
- updateConfig(
- (config) => (config.fontFamily = e.currentTarget.value),
- )
- }
- ></input>
- </ListItem>
- <ListItem
- title={Locale.Settings.AutoGenerateTitle.Title}
- subTitle={Locale.Settings.AutoGenerateTitle.SubTitle}
- >
- <input
- aria-label={Locale.Settings.AutoGenerateTitle.Title}
- 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
- aria-label={Locale.Settings.SendPreviewBubble.Title}
- type="checkbox"
- checked={config.sendPreviewBubble}
- onChange={(e) =>
- updateConfig(
- (config) =>
- (config.sendPreviewBubble = e.currentTarget.checked),
- )
- }
- ></input>
- </ListItem>
- <ListItem
- title={Locale.Mask.Config.Artifacts.Title}
- subTitle={Locale.Mask.Config.Artifacts.SubTitle}
- >
- <input
- aria-label={Locale.Mask.Config.Artifacts.Title}
- type="checkbox"
- checked={config.enableArtifacts}
- onChange={(e) =>
- updateConfig(
- (config) =>
- (config.enableArtifacts = e.currentTarget.checked),
- )
- }
- ></input>
- </ListItem>
- </List>
- <SyncItems />
- <List>
- <ListItem
- title={Locale.Settings.Mask.Splash.Title}
- subTitle={Locale.Settings.Mask.Splash.SubTitle}
- >
- <input
- aria-label={Locale.Settings.Mask.Splash.Title}
- 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
- aria-label={Locale.Settings.Mask.Builtin.Title}
- 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
- aria-label={Locale.Settings.Prompt.Disable.Title}
- 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
- aria={Locale.Settings.Prompt.List + Locale.Settings.Prompt.Edit}
- icon={<EditIcon />}
- text={Locale.Settings.Prompt.Edit}
- onClick={() => setShowPromptModal(true)}
- />
- </ListItem>
- </List>
- <List id={SlotID.CustomModel}>
- {saasStartComponent}
- {accessCodeComponent}
- {!accessStore.hideUserApiKey && (
- <>
- {useCustomConfigComponent}
- {accessStore.useCustomConfig && (
- <>
- <ListItem
- title={Locale.Settings.Access.Provider.Title}
- subTitle={Locale.Settings.Access.Provider.SubTitle}
- >
- <Select
- aria-label={Locale.Settings.Access.Provider.Title}
- 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>
- {openAIConfigComponent}
- {azureConfigComponent}
- {googleConfigComponent}
- {anthropicConfigComponent}
- {baiduConfigComponent}
- {byteDanceConfigComponent}
- {alibabaConfigComponent}
- {tencentConfigComponent}
- {moonshotConfigComponent}
- {stabilityConfigComponent}
- {lflytekConfigComponent}
- </>
- )}
- </>
- )}
- {!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
- aria-label={Locale.Settings.Access.CustomModel.Title}
- 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>
- {shouldShowPromptModal && (
- <UserPromptModal onClose={() => setShowPromptModal(false)} />
- )}
- <List>
- <TTSConfigList
- ttsConfig={config.ttsConfig}
- updateConfig={(updater) => {
- const ttsConfig = { ...config.ttsConfig };
- updater(ttsConfig);
- config.update((config) => (config.ttsConfig = ttsConfig));
- }}
- />
- </List>
- <DangerItems />
- </div>
- </ErrorBoundary>
- );
- }
|