597 lines
19 KiB
TypeScript
597 lines
19 KiB
TypeScript
export {};
|
|
// import { useState, useEffect, useMemo, HTMLProps, useRef } 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 EyeIcon from "../icons/eye.svg";
|
|
// import {
|
|
// Input,
|
|
// List,
|
|
// ListItem,
|
|
// Modal,
|
|
// PasswordInput,
|
|
// Popover,
|
|
// Select,
|
|
// } 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 { Path, UPDATE_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";
|
|
|
|
// function EditPromptModal(props: { id: number; 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.update(
|
|
// 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.update(
|
|
// 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<number>();
|
|
|
|
// 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={() =>
|
|
// promptStore.add({
|
|
// title: "Empty Prompt",
|
|
// content: "Empty Prompt Content",
|
|
// })
|
|
// }
|
|
// 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 formatVersionDate(t: string) {
|
|
// const d = new Date(+t);
|
|
// const year = d.getUTCFullYear();
|
|
// const month = d.getUTCMonth() + 1;
|
|
// const day = d.getUTCDate();
|
|
|
|
// return [
|
|
// year.toString(),
|
|
// month.toString().padStart(2, "0"),
|
|
// day.toString().padStart(2, "0"),
|
|
// ].join("");
|
|
// }
|
|
|
|
// export function Settings() {
|
|
// const navigate = useNavigate();
|
|
// const [showEmojiPicker, setShowEmojiPicker] = useState(false);
|
|
// const config = useAppConfig();
|
|
// const updateConfig = config.update;
|
|
// const resetConfig = config.reset;
|
|
// const chatStore = useChatStore();
|
|
|
|
// const updateStore = useUpdateStore();
|
|
// const [checkingUpdate, setCheckingUpdate] = useState(false);
|
|
// const currentVersion = formatVersionDate(updateStore.version);
|
|
// const remoteId = formatVersionDate(updateStore.remoteVersion);
|
|
// const hasNewVersion = currentVersion !== remoteId;
|
|
|
|
// function checkUpdate(force = false) {
|
|
// setCheckingUpdate(true);
|
|
// updateStore.getLatestVersion(force).then(() => {
|
|
// setCheckingUpdate(false);
|
|
// });
|
|
|
|
// console.log(
|
|
// "[Update] local version ",
|
|
// new Date(+updateStore.version).toLocaleString(),
|
|
// );
|
|
// console.log(
|
|
// "[Update] remote version ",
|
|
// new Date(+updateStore.remoteVersion).toLocaleString(),
|
|
// );
|
|
// }
|
|
|
|
// const usage = {
|
|
// used: updateStore.used,
|
|
// subscription: updateStore.subscription,
|
|
// };
|
|
// const [loadingUsage, setLoadingUsage] = useState(false);
|
|
// function checkUsage(force = false) {
|
|
// setLoadingUsage(true);
|
|
// updateStore.updateUsage(force).finally(() => {
|
|
// setLoadingUsage(false);
|
|
// });
|
|
// }
|
|
|
|
// const accessStore = useAccessStore();
|
|
// 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);
|
|
// }
|
|
// };
|
|
// document.addEventListener("keydown", keydownEvent);
|
|
// return () => {
|
|
// document.removeEventListener("keydown", keydownEvent);
|
|
// };
|
|
// // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
// }, []);
|
|
|
|
// return (
|
|
// <ErrorBoundary>
|
|
// <div className="window-header">
|
|
// <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">
|
|
// <IconButton
|
|
// icon={<ClearIcon />}
|
|
// onClick={() => {
|
|
// if (confirm(Locale.Settings.Actions.ConfirmClearAll)) {
|
|
// chatStore.clearAllData();
|
|
// }
|
|
// }}
|
|
// bordered
|
|
// title={Locale.Settings.Actions.ClearAll}
|
|
// />
|
|
// </div>
|
|
// <div className="window-action-button">
|
|
// <IconButton
|
|
// icon={<ResetIcon />}
|
|
// onClick={() => {
|
|
// if (confirm(Locale.Settings.Actions.ConfirmResetAll)) {
|
|
// resetConfig();
|
|
// }
|
|
// }}
|
|
// bordered
|
|
// title={Locale.Settings.Actions.ResetAll}
|
|
// />
|
|
// </div>
|
|
// <div className="window-action-button">
|
|
// <IconButton
|
|
// icon={<CloseIcon />}
|
|
// onClick={() => navigate(Path.Home)}
|
|
// bordered
|
|
// title={Locale.Settings.Actions.Close}
|
|
// />
|
|
// </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
|
|
// className={styles.avatar}
|
|
// onClick={() => setShowEmojiPicker(true)}
|
|
// >
|
|
// <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={UPDATE_URL} target="_blank" className="link">
|
|
// {Locale.Settings.Update.GoToUpdate}
|
|
// </Link>
|
|
// ) : (
|
|
// <IconButton
|
|
// icon={<ResetIcon></ResetIcon>}
|
|
// text={Locale.Settings.Update.CheckUpdate}
|
|
// onClick={() => checkUpdate(true)}
|
|
// />
|
|
// )}
|
|
// </ListItem>
|
|
|
|
// <ListItem title={Locale.Settings.SendKey}>
|
|
// <Select
|
|
// value={config.submitKey}
|
|
// onChange={(e) => {
|
|
// updateConfig(
|
|
// (config) =>
|
|
// (config.submitKey = e.target.value as any as SubmitKey),
|
|
// );
|
|
// }}
|
|
// >
|
|
// {Object.values(SubmitKey).map((v) => (
|
|
// <option value={v} key={v}>
|
|
// {v}
|
|
// </option>
|
|
// ))}
|
|
// </Select>
|
|
// </ListItem>
|
|
|
|
// <ListItem title={Locale.Settings.Theme}>
|
|
// <Select
|
|
// value={config.theme}
|
|
// onChange={(e) => {
|
|
// updateConfig(
|
|
// (config) => (config.theme = e.target.value as any as Theme),
|
|
// );
|
|
// }}
|
|
// >
|
|
// {Object.values(Theme).map((v) => (
|
|
// <option value={v} key={v}>
|
|
// {v}
|
|
// </option>
|
|
// ))}
|
|
// </Select>
|
|
// </ListItem>
|
|
|
|
// <ListItem title={Locale.Settings.Lang.Name}>
|
|
// <Select
|
|
// value={getLang()}
|
|
// onChange={(e) => {
|
|
// changeLang(e.target.value as any);
|
|
// }}
|
|
// >
|
|
// {AllLangs.map((lang) => (
|
|
// <option value={lang} key={lang}>
|
|
// {ALL_LANG_OPTIONS[lang]}
|
|
// </option>
|
|
// ))}
|
|
// </Select>
|
|
// </ListItem>
|
|
|
|
// <ListItem
|
|
// title={Locale.Settings.FontSize.Title}
|
|
// subTitle={Locale.Settings.FontSize.SubTitle}
|
|
// >
|
|
// <InputRange
|
|
// title={`${config.fontSize ?? 14}px`}
|
|
// value={config.fontSize}
|
|
// min="12"
|
|
// max="18"
|
|
// step="1"
|
|
// onChange={(e) =>
|
|
// updateConfig(
|
|
// (config) =>
|
|
// (config.fontSize = Number.parseInt(e.currentTarget.value)),
|
|
// )
|
|
// }
|
|
// ></InputRange>
|
|
// </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.Mask.Title}
|
|
// subTitle={Locale.Settings.Mask.SubTitle}
|
|
// >
|
|
// <input
|
|
// type="checkbox"
|
|
// checked={!config.dontShowMaskSplashScreen}
|
|
// onChange={(e) =>
|
|
// updateConfig(
|
|
// (config) =>
|
|
// (config.dontShowMaskSplashScreen =
|
|
// !e.currentTarget.checked),
|
|
// )
|
|
// }
|
|
// ></input>
|
|
// </ListItem>
|
|
// </List>
|
|
|
|
// <List>
|
|
// {enabledAccessControl ? (
|
|
// <ListItem
|
|
// title={Locale.Settings.AccessCode.Title}
|
|
// subTitle={Locale.Settings.AccessCode.SubTitle}
|
|
// >
|
|
// <PasswordInput
|
|
// value={accessStore.accessCode}
|
|
// type="text"
|
|
// placeholder={Locale.Settings.AccessCode.Placeholder}
|
|
// onChange={(e) => {
|
|
// accessStore.updateCode(e.currentTarget.value);
|
|
// }}
|
|
// />
|
|
// </ListItem>
|
|
// ) : (
|
|
// <></>
|
|
// )}
|
|
|
|
// {!accessStore.hideUserApiKey ? (
|
|
// <ListItem
|
|
// title={Locale.Settings.Token.Title}
|
|
// subTitle={Locale.Settings.Token.SubTitle}
|
|
// >
|
|
// <PasswordInput
|
|
// value={accessStore.token}
|
|
// type="text"
|
|
// placeholder={Locale.Settings.Token.Placeholder}
|
|
// onChange={(e) => {
|
|
// accessStore.updateToken(e.currentTarget.value);
|
|
// }}
|
|
// />
|
|
// </ListItem>
|
|
// ) : null}
|
|
|
|
// <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>
|
|
// </List>
|
|
|
|
// <List>
|
|
// <ListItem
|
|
// title={Locale.Settings.Prompt.Disable.Title}
|
|
// subTitle={Locale.Settings.Prompt.Disable.SubTitle}
|
|
// >
|
|
// <input
|
|
// type="checkbox"
|
|
// checked={config.disablePromptHint}
|
|
// onChange={(e) =>
|
|
// updateConfig(
|
|
// (config) =>
|
|
// (config.disablePromptHint = e.currentTarget.checked),
|
|
// )
|
|
// }
|
|
// ></input>
|
|
// </ListItem>
|
|
|
|
// <ListItem
|
|
// title={Locale.Settings.Prompt.List}
|
|
// subTitle={Locale.Settings.Prompt.ListCount(
|
|
// builtinCount,
|
|
// customCount,
|
|
// )}
|
|
// >
|
|
// <IconButton
|
|
// icon={<EditIcon />}
|
|
// text={Locale.Settings.Prompt.Edit}
|
|
// onClick={() => setShowPromptModal(true)}
|
|
// />
|
|
// </ListItem>
|
|
// </List>
|
|
|
|
// <List>
|
|
// <ModelConfigList
|
|
// modelConfig={config.modelConfig}
|
|
// updateConfig={(updater) => {
|
|
// const modelConfig = { ...config.modelConfig };
|
|
// updater(modelConfig);
|
|
// config.update((config) => (config.modelConfig = modelConfig));
|
|
// }}
|
|
// />
|
|
// </List>
|
|
|
|
// {shouldShowPromptModal && (
|
|
// <UserPromptModal onClose={() => setShowPromptModal(false)} />
|
|
// )}
|
|
// </div>
|
|
// </ErrorBoundary>
|
|
// );
|
|
// }
|