ChatGPT-Next-Web/app/components/settings.tsx

203 lines
6.3 KiB
TypeScript
Raw Normal View History

2023-03-13 16:25:07 +00:00
import { useState, useRef, useEffect } from "react";
2023-03-20 16:17:45 +00:00
import EmojiPicker, { Theme as EmojiTheme } from "emoji-picker-react";
2023-03-13 16:25:07 +00:00
import styles from "./settings.module.scss";
import ResetIcon from "../icons/reload.svg";
2023-03-14 17:44:42 +00:00
import CloseIcon from "../icons/close.svg";
2023-03-19 15:13:10 +00:00
import ClearIcon from "../icons/clear.svg";
2023-03-13 16:25:07 +00:00
import { List, ListItem, Popover } from "./ui-lib";
import { IconButton } from "./button";
import { SubmitKey, useChatStore, Theme } from "../store";
import { Avatar } from "./home";
2023-03-20 16:17:45 +00:00
import Locale, { changeLang, getLang } from '../locales'
2023-03-14 17:44:42 +00:00
export function Settings(props: { closeSettings: () => void }) {
2023-03-13 16:25:07 +00:00
const [showEmojiPicker, setShowEmojiPicker] = useState(false);
2023-03-19 15:13:10 +00:00
const [config, updateConfig, resetConfig, clearAllData] = useChatStore((state) => [
2023-03-13 16:25:07 +00:00
state.config,
state.updateConfig,
state.resetConfig,
2023-03-19 15:13:10 +00:00
state.clearAllData,
2023-03-13 16:25:07 +00:00
]);
return (
<>
<div className={styles["window-header"]}>
2023-03-19 16:09:30 +00:00
<div className={styles["window-header-title"]}>
2023-03-20 16:17:45 +00:00
<div className={styles["window-header-main-title"]}>{Locale.Settings.Title}</div>
<div className={styles["window-header-sub-title"]}>{Locale.Settings.SubTitle}</div>
2023-03-13 16:25:07 +00:00
</div>
<div className={styles["window-actions"]}>
2023-03-14 17:44:42 +00:00
<div className={styles["window-action-button"]}>
<IconButton
2023-03-19 15:13:10 +00:00
icon={<ClearIcon />}
onClick={clearAllData}
2023-03-14 17:44:42 +00:00
bordered
2023-03-20 16:17:45 +00:00
title={Locale.Settings.Actions.ClearAll}
2023-03-14 17:44:42 +00:00
/>
</div>
2023-03-13 16:25:07 +00:00
<div className={styles["window-action-button"]}>
<IconButton
icon={<ResetIcon />}
onClick={resetConfig}
bordered
2023-03-20 16:17:45 +00:00
title={Locale.Settings.Actions.ResetAll}
2023-03-13 16:25:07 +00:00
/>
</div>
2023-03-19 15:13:10 +00:00
<div className={styles["window-action-button"]}>
<IconButton
icon={<CloseIcon />}
onClick={props.closeSettings}
bordered
2023-03-20 16:17:45 +00:00
title={Locale.Settings.Actions.Close}
2023-03-19 15:13:10 +00:00
/>
</div>
2023-03-13 16:25:07 +00:00
</div>
</div>
<div className={styles["settings"]}>
<List>
<ListItem>
2023-03-20 16:17:45 +00:00
<div className={styles["settings-title"]}>{Locale.Settings.Avatar}</div>
2023-03-13 16:25:07 +00:00
<Popover
onClose={() => setShowEmojiPicker(false)}
content={
<EmojiPicker
lazyLoadEmojis
theme={EmojiTheme.AUTO}
onEmojiClick={(e) => {
updateConfig((config) => (config.avatar = e.unified));
setShowEmojiPicker(false);
}}
/>
}
open={showEmojiPicker}
>
<div
className={styles.avatar}
onClick={() => setShowEmojiPicker(true)}
>
<Avatar role="user" />
</div>
</Popover>
</ListItem>
<ListItem>
2023-03-20 16:17:45 +00:00
<div className={styles["settings-title"]}>{Locale.Settings.SendKey}</div>
2023-03-13 16:25:07 +00:00
<div className="">
<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>
</div>
</ListItem>
<ListItem>
2023-03-20 16:17:45 +00:00
<div className={styles["settings-title"]}>{Locale.Settings.Theme}</div>
2023-03-13 16:25:07 +00:00
<div className="">
<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>
</div>
</ListItem>
<ListItem>
2023-03-20 16:17:45 +00:00
<div className={styles["settings-title"]}>{Locale.Settings.TightBorder}</div>
2023-03-13 16:25:07 +00:00
<input
type="checkbox"
checked={config.tightBorder}
onChange={(e) =>
updateConfig(
(config) => (config.tightBorder = e.currentTarget.checked)
)
}
></input>
</ListItem>
2023-03-20 16:17:45 +00:00
<ListItem>
<div className={styles["settings-title"]}>{Locale.Settings.Lang.Name}</div>
<div className="">
<select
value={getLang()}
onChange={(e) => {
changeLang(e.target.value as any)
}}
>
<option value='en' key='en'>
{Locale.Settings.Lang.Options.en}
</option>
<option value='cn' key='cn'>
{Locale.Settings.Lang.Options.cn}
</option>
</select>
</div>
</ListItem>
2023-03-13 16:25:07 +00:00
</List>
<List>
<ListItem>
2023-03-20 16:17:45 +00:00
<div className={styles["settings-title"]}>{Locale.Settings.HistoryCount}</div>
2023-03-13 16:25:07 +00:00
<input
type="range"
title={config.historyMessageCount.toString()}
value={config.historyMessageCount}
2023-03-19 16:09:30 +00:00
min="2"
max="25"
step="2"
2023-03-13 16:25:07 +00:00
onChange={(e) =>
updateConfig(
(config) =>
(config.historyMessageCount = e.target.valueAsNumber)
)
}
></input>
</ListItem>
2023-03-19 15:13:10 +00:00
<ListItem>
<div className={styles["settings-title"]}>
2023-03-20 16:17:45 +00:00
{Locale.Settings.CompressThreshold}
2023-03-19 15:13:10 +00:00
</div>
<input
type="number"
min={500}
max={4000}
value={config.compressMessageLengthThreshold}
onChange={(e) =>
updateConfig(
(config) => (config.compressMessageLengthThreshold = e.currentTarget.valueAsNumber)
)
}
></input>
</ListItem>
2023-03-13 16:25:07 +00:00
</List>
</div>
</>
);
}