123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- import { useState } from "react";
- import EmojiPicker, { Theme as EmojiTheme } from "emoji-picker-react";
- import styles from "./settings.module.scss";
- import ResetIcon from "../icons/reload.svg";
- import CloseIcon from "../icons/close.svg";
- import ClearIcon from "../icons/clear.svg";
- import { List, ListItem, Popover } from "./ui-lib";
- import { IconButton } from "./button";
- import { SubmitKey, useChatStore, Theme, ALL_MODELS } from "../store";
- import { Avatar } from "./home";
- import Locale, { changeLang, getLang } from "../locales";
- function SettingItem(props: {
- title: string;
- subTitle?: string;
- children: JSX.Element;
- }) {
- return (
- <ListItem>
- <div className={styles["settings-title"]}>
- <div>{props.title}</div>
- {props.subTitle && (
- <div className={styles["settings-sub-title"]}>{props.subTitle}</div>
- )}
- </div>
- <div>{props.children}</div>
- </ListItem>
- );
- }
- export function Settings(props: { closeSettings: () => void }) {
- const [showEmojiPicker, setShowEmojiPicker] = useState(false);
- const [config, updateConfig, resetConfig, clearAllData] = useChatStore(
- (state) => [
- state.config,
- state.updateConfig,
- state.resetConfig,
- state.clearAllData,
- ]
- );
- return (
- <>
- <div className={styles["window-header"]}>
- <div className={styles["window-header-title"]}>
- <div className={styles["window-header-main-title"]}>
- {Locale.Settings.Title}
- </div>
- <div className={styles["window-header-sub-title"]}>
- {Locale.Settings.SubTitle}
- </div>
- </div>
- <div className={styles["window-actions"]}>
- <div className={styles["window-action-button"]}>
- <IconButton
- icon={<ClearIcon />}
- onClick={clearAllData}
- bordered
- title={Locale.Settings.Actions.ClearAll}
- />
- </div>
- <div className={styles["window-action-button"]}>
- <IconButton
- icon={<ResetIcon />}
- onClick={resetConfig}
- bordered
- title={Locale.Settings.Actions.ResetAll}
- />
- </div>
- <div className={styles["window-action-button"]}>
- <IconButton
- icon={<CloseIcon />}
- onClick={props.closeSettings}
- bordered
- title={Locale.Settings.Actions.Close}
- />
- </div>
- </div>
- </div>
- <div className={styles["settings"]}>
- <List>
- <SettingItem title={Locale.Settings.Avatar}>
- <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>
- </SettingItem>
- <SettingItem 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>
- </SettingItem>
- <ListItem>
- <div className={styles["settings-title"]}>
- {Locale.Settings.Theme}
- </div>
- <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>
- <SettingItem title={Locale.Settings.Lang.Name}>
- <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>
- </SettingItem>
- <div className="no-mobile">
- <SettingItem title={Locale.Settings.TightBorder}>
- <input
- type="checkbox"
- checked={config.tightBorder}
- onChange={(e) =>
- updateConfig(
- (config) => (config.tightBorder = e.currentTarget.checked)
- )
- }
- ></input>
- </SettingItem>
- </div>
- </List>
- <List>
- <SettingItem
- title={Locale.Settings.HistoryCount.Title}
- subTitle={Locale.Settings.HistoryCount.SubTitle}
- >
- <input
- type="range"
- title={config.historyMessageCount.toString()}
- value={config.historyMessageCount}
- min="2"
- max="25"
- step="2"
- onChange={(e) =>
- updateConfig(
- (config) =>
- (config.historyMessageCount = e.target.valueAsNumber)
- )
- }
- ></input>
- </SettingItem>
- <SettingItem
- title={Locale.Settings.CompressThreshold.Title}
- subTitle={Locale.Settings.CompressThreshold.SubTitle}
- >
- <input
- type="number"
- min={500}
- max={4000}
- value={config.compressMessageLengthThreshold}
- onChange={(e) =>
- updateConfig(
- (config) =>
- (config.compressMessageLengthThreshold =
- e.currentTarget.valueAsNumber)
- )
- }
- ></input>
- </SettingItem>
- </List>
- <List>
- <SettingItem title={Locale.Settings.Model}>
- <select
- value={config.modelConfig.model}
- onChange={(e) => {
- updateConfig(
- (config) => (config.modelConfig.model = e.currentTarget.value)
- );
- }}
- >
- {ALL_MODELS.map((v) => (
- <option value={v.name} key={v.name} disabled={!v.available}>
- {v.name}
- </option>
- ))}
- </select>
- </SettingItem>
- <SettingItem
- title={Locale.Settings.Temperature.Title}
- subTitle={Locale.Settings.Temperature.SubTitle}
- >
- <input
- type="range"
- value={config.modelConfig.temperature.toFixed(1)}
- min="0"
- max="1"
- step="0.1"
- onChange={(e) => {
- updateConfig(
- (config) =>
- (config.modelConfig.temperature =
- e.currentTarget.valueAsNumber)
- );
- }}
- ></input>
- </SettingItem>
- <SettingItem
- title={Locale.Settings.MaxTokens.Title}
- subTitle={Locale.Settings.MaxTokens.SubTitle}
- >
- <input
- type="number"
- min={100}
- max={4000}
- value={config.modelConfig.max_tokens}
- onChange={(e) =>
- updateConfig(
- (config) =>
- (config.modelConfig.max_tokens =
- e.currentTarget.valueAsNumber)
- )
- }
- ></input>
- </SettingItem>
- <SettingItem
- title={Locale.Settings.PresencePenlty.Title}
- subTitle={Locale.Settings.PresencePenlty.SubTitle}
- >
- <input
- type="range"
- value={config.modelConfig.presence_penalty.toFixed(1)}
- min="-2"
- max="2"
- step="0.5"
- onChange={(e) => {
- updateConfig(
- (config) =>
- (config.modelConfig.presence_penalty =
- e.currentTarget.valueAsNumber)
- );
- }}
- ></input>
- </SettingItem>
- </List>
- </div>
- </>
- );
- }
|