Merge remote-tracking branch 'up/website' into website

This commit is contained in:
织梦人
2024-08-18 20:22:30 +08:00
41 changed files with 6002 additions and 1706 deletions

View File

@@ -18,6 +18,7 @@ export function IconButton(props: {
tabIndex?: number;
autoFocus?: boolean;
style?: CSSProperties;
aria?: string;
}) {
return (
<button
@@ -34,9 +35,11 @@ export function IconButton(props: {
tabIndex={props.tabIndex}
autoFocus={props.autoFocus}
style={props.style}
aria-label={props.aria}
>
{props.icon && (
<div
aria-label={props.text || props.title}
className={
styles["icon-button-icon"] +
` ${props.type === "primary" && "no-dark"}`
@@ -47,7 +50,12 @@ export function IconButton(props: {
)}
{props.text && (
<div className={styles["icon-button-text"]}>{props.text}</div>
<div
aria-label={props.text || props.title}
className={styles["icon-button-text"]}
>
{props.text}
</div>
)}
</button>
);

View File

@@ -346,6 +346,12 @@
flex-wrap: nowrap;
}
}
.chat-model-name {
font-size: 12px;
color: var(--black);
margin-left: 6px;
}
}
.chat-message-container {

View File

@@ -38,6 +38,8 @@ import BottomIcon from "../icons/bottom.svg";
import StopIcon from "../icons/pause.svg";
import RobotIcon from "../icons/robot.svg";
import SizeIcon from "../icons/size.svg";
import QualityIcon from "../icons/hd.svg";
import StyleIcon from "../icons/palette.svg";
import PluginIcon from "../icons/plugin.svg";
import {
@@ -70,7 +72,7 @@ import { uploadImage as uploadImageRemote } from "@/app/utils/chat";
import dynamic from "next/dynamic";
import { ChatControllerPool } from "../client/controller";
import { DalleSize } from "../typing";
import { DalleSize, DalleQuality, DalleStyle } from "../typing";
import { Prompt, usePromptStore } from "../store/prompt";
import Locale from "../locales";
@@ -486,9 +488,17 @@ export function ChatActions(props: {
const [showUploadImage, setShowUploadImage] = useState(false);
const [showSizeSelector, setShowSizeSelector] = useState(false);
const [showQualitySelector, setShowQualitySelector] = useState(false);
const [showStyleSelector, setShowStyleSelector] = useState(false);
const dalle3Sizes: DalleSize[] = ["1024x1024", "1792x1024", "1024x1792"];
const dalle3Qualitys: DalleQuality[] = ["standard", "hd"];
const dalle3Styles: DalleStyle[] = ["vivid", "natural"];
const currentSize =
chatStore.currentSession().mask.modelConfig?.size ?? "1024x1024";
const currentQuality =
chatStore.currentSession().mask.modelConfig?.quality ?? "standard";
const currentStyle =
chatStore.currentSession().mask.modelConfig?.style ?? "vivid";
useEffect(() => {
const show = isVisionModel(currentModel);
@@ -660,6 +670,60 @@ export function ChatActions(props: {
/>
)}
{isDalle3(currentModel) && (
<ChatAction
onClick={() => setShowQualitySelector(true)}
text={currentQuality}
icon={<QualityIcon />}
/>
)}
{showQualitySelector && (
<Selector
defaultSelectedValue={currentQuality}
items={dalle3Qualitys.map((m) => ({
title: m,
value: m,
}))}
onClose={() => setShowQualitySelector(false)}
onSelection={(q) => {
if (q.length === 0) return;
const quality = q[0];
chatStore.updateCurrentSession((session) => {
session.mask.modelConfig.quality = quality;
});
showToast(quality);
}}
/>
)}
{isDalle3(currentModel) && (
<ChatAction
onClick={() => setShowStyleSelector(true)}
text={currentStyle}
icon={<StyleIcon />}
/>
)}
{showStyleSelector && (
<Selector
defaultSelectedValue={currentStyle}
items={dalle3Styles.map((m) => ({
title: m,
value: m,
}))}
onClose={() => setShowStyleSelector(false)}
onSelection={(s) => {
if (s.length === 0) return;
const style = s[0];
chatStore.updateCurrentSession((session) => {
session.mask.modelConfig.style = style;
});
showToast(style);
}}
/>
)}
<ChatAction
onClick={() => setShowPluginSelector(true)}
text={Locale.Plugin.Name}
@@ -1348,6 +1412,8 @@ function _Chat() {
<IconButton
icon={<RenameIcon />}
bordered
title={Locale.Chat.EditMessage.Title}
aria={Locale.Chat.EditMessage.Title}
onClick={() => setIsEditingMessage(true)}
/>
</div>
@@ -1367,6 +1433,8 @@ function _Chat() {
<IconButton
icon={config.tightBorder ? <MinIcon /> : <MaxIcon />}
bordered
title={Locale.Chat.Actions.FullScreen}
aria={Locale.Chat.Actions.FullScreen}
onClick={() => {
config.update(
(config) => (config.tightBorder = !config.tightBorder),
@@ -1418,6 +1486,7 @@ function _Chat() {
<div className={styles["chat-message-edit"]}>
<IconButton
icon={<EditIcon />}
aria={Locale.Chat.Actions.Edit}
onClick={async () => {
const newMessage = await showPrompt(
Locale.Chat.Actions.Edit,
@@ -1466,6 +1535,11 @@ function _Chat() {
</>
)}
</div>
{!isUser && (
<div className={styles["chat-model-name"]}>
{message.model}
</div>
)}
{showActions && (
<div className={styles["chat-message-actions"]}>

View File

@@ -9,6 +9,7 @@ interface InputRangeProps {
min: string;
max: string;
step: string;
aria: string;
}
export function InputRange({
@@ -19,11 +20,13 @@ export function InputRange({
min,
max,
step,
aria,
}: InputRangeProps) {
return (
<div className={styles["input-range"] + ` ${className ?? ""}`}>
{title || value}
<input
aria-label={aria}
type="range"
title={title}
value={value}

View File

@@ -156,6 +156,46 @@ export function PreCode(props: { children: any }) {
);
}
function CustomCode(props: { children: any }) {
const ref = useRef<HTMLPreElement>(null);
const [collapsed, setCollapsed] = useState(true);
const [showToggle, setShowToggle] = useState(false);
useEffect(() => {
if (ref.current) {
const codeHeight = ref.current.scrollHeight;
setShowToggle(codeHeight > 400);
ref.current.scrollTop = ref.current.scrollHeight;
}
}, [props.children]);
const toggleCollapsed = () => {
setCollapsed((collapsed) => !collapsed);
};
return (
<>
<code
ref={ref}
style={{
maxHeight: collapsed ? "400px" : "none",
overflowY: "hidden",
}}
>
{props.children}
{showToggle && collapsed && (
<div
className={`show-hide-button ${
collapsed ? "collapsed" : "expanded"
}`}
>
<button onClick={toggleCollapsed}></button>
</div>
)}
</code>
</>
);
}
function escapeDollarNumber(text: string) {
let escapedText = "";
@@ -211,6 +251,7 @@ function _MarkDownContent(props: { content: string }) {
]}
components={{
pre: PreCode,
code: CustomCode,
p: (pProps) => <p {...pProps} dir="auto" />,
a: (aProps) => {
const href = aProps.href || "";

View File

@@ -127,6 +127,8 @@ export function MaskConfig(props: {
onClose={() => setShowPicker(false)}
>
<div
tabIndex={0}
aria-label={Locale.Mask.Config.Avatar}
onClick={() => setShowPicker(true)}
style={{ cursor: "pointer" }}
>
@@ -139,6 +141,7 @@ export function MaskConfig(props: {
</ListItem>
<ListItem title={Locale.Mask.Config.Name}>
<input
aria-label={Locale.Mask.Config.Name}
type="text"
value={props.mask.name}
onInput={(e) =>
@@ -153,6 +156,7 @@ export function MaskConfig(props: {
subTitle={Locale.Mask.Config.HideContext.SubTitle}
>
<input
aria-label={Locale.Mask.Config.HideContext.Title}
type="checkbox"
checked={props.mask.hideContext}
onChange={(e) => {
@@ -169,6 +173,7 @@ export function MaskConfig(props: {
subTitle={Locale.Mask.Config.Share.SubTitle}
>
<IconButton
aria={Locale.Mask.Config.Share.Title}
icon={<CopyIcon />}
text={Locale.Mask.Config.Share.Action}
onClick={copyMaskLink}
@@ -182,6 +187,7 @@ export function MaskConfig(props: {
subTitle={Locale.Mask.Config.Sync.SubTitle}
>
<input
aria-label={Locale.Mask.Config.Sync.Title}
type="checkbox"
checked={props.mask.syncGlobalConfig}
onChange={async (e) => {

View File

@@ -17,6 +17,7 @@ export function ModelConfigList(props: {
<>
<ListItem title={Locale.Settings.Model}>
<Select
aria-label={Locale.Settings.Model}
value={value}
onChange={(e) => {
const [model, providerName] = e.currentTarget.value.split("@");
@@ -40,6 +41,7 @@ export function ModelConfigList(props: {
subTitle={Locale.Settings.Temperature.SubTitle}
>
<InputRange
aria={Locale.Settings.Temperature.Title}
value={props.modelConfig.temperature?.toFixed(1)}
min="0"
max="1" // lets limit it to 0-1
@@ -59,6 +61,7 @@ export function ModelConfigList(props: {
subTitle={Locale.Settings.TopP.SubTitle}
>
<InputRange
aria={Locale.Settings.TopP.Title}
value={(props.modelConfig.top_p ?? 1).toFixed(1)}
min="0"
max="1"
@@ -78,6 +81,7 @@ export function ModelConfigList(props: {
subTitle={Locale.Settings.MaxTokens.SubTitle}
>
<input
aria-label={Locale.Settings.MaxTokens.Title}
type="number"
min={1024}
max={512000}
@@ -100,6 +104,7 @@ export function ModelConfigList(props: {
subTitle={Locale.Settings.PresencePenalty.SubTitle}
>
<InputRange
aria={Locale.Settings.PresencePenalty.Title}
value={props.modelConfig.presence_penalty?.toFixed(1)}
min="-2"
max="2"
@@ -121,6 +126,7 @@ export function ModelConfigList(props: {
subTitle={Locale.Settings.FrequencyPenalty.SubTitle}
>
<InputRange
aria={Locale.Settings.FrequencyPenalty.Title}
value={props.modelConfig.frequency_penalty?.toFixed(1)}
min="-2"
max="2"
@@ -142,6 +148,7 @@ export function ModelConfigList(props: {
subTitle={Locale.Settings.InjectSystemPrompts.SubTitle}
>
<input
aria-label={Locale.Settings.InjectSystemPrompts.Title}
type="checkbox"
checked={props.modelConfig.enableInjectSystemPrompts}
onChange={(e) =>
@@ -159,6 +166,7 @@ export function ModelConfigList(props: {
subTitle={Locale.Settings.InputTemplate.SubTitle}
>
<input
aria-label={Locale.Settings.InputTemplate.Title}
type="text"
value={props.modelConfig.template}
onChange={(e) =>
@@ -175,6 +183,7 @@ export function ModelConfigList(props: {
subTitle={Locale.Settings.HistoryCount.SubTitle}
>
<InputRange
aria={Locale.Settings.HistoryCount.Title}
title={props.modelConfig.historyMessageCount.toString()}
value={props.modelConfig.historyMessageCount}
min="0"
@@ -193,6 +202,7 @@ export function ModelConfigList(props: {
subTitle={Locale.Settings.CompressThreshold.SubTitle}
>
<input
aria-label={Locale.Settings.CompressThreshold.Title}
type="number"
min={500}
max={4000}
@@ -208,6 +218,7 @@ export function ModelConfigList(props: {
</ListItem>
<ListItem title={Locale.Memory.Title} subTitle={Locale.Memory.Send}>
<input
aria-label={Locale.Memory.Title}
type="checkbox"
checked={props.modelConfig.sendMemory}
onChange={(e) =>

View File

@@ -192,6 +192,7 @@ export function ControlParam(props: {
required={item.required}
>
<Select
aria-label={item.name}
value={props.data[item.value]}
onChange={(e) => {
props.onChange(item.value, e.currentTarget.value);
@@ -216,6 +217,7 @@ export function ControlParam(props: {
required={item.required}
>
<input
aria-label={item.name}
type="number"
min={item.min}
max={item.max}
@@ -235,6 +237,7 @@ export function ControlParam(props: {
required={item.required}
>
<input
aria-label={item.name}
type="text"
value={props.data[item.value]}
style={{ maxWidth: "100%", width: "100%" }}

View File

@@ -133,6 +133,7 @@ export function Sd() {
{showMaxIcon && (
<div className="window-action-button">
<IconButton
aria={Locale.Chat.Actions.FullScreen}
icon={config.tightBorder ? <MinIcon /> : <MaxIcon />}
bordered
onClick={() => {

View File

@@ -246,6 +246,7 @@ function DangerItems() {
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)) {
@@ -260,6 +261,7 @@ function DangerItems() {
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)) {
@@ -528,6 +530,7 @@ function SyncItems() {
>
<div style={{ display: "flex" }}>
<IconButton
aria={Locale.Settings.Sync.CloudState + Locale.UI.Config}
icon={<ConfigIcon />}
text={Locale.UI.Config}
onClick={() => {
@@ -558,6 +561,7 @@ function SyncItems() {
>
<div style={{ display: "flex" }}>
<IconButton
aria={Locale.Settings.Sync.LocalState + Locale.UI.Export}
icon={<UploadIcon />}
text={Locale.UI.Export}
onClick={() => {
@@ -565,6 +569,7 @@ function SyncItems() {
}}
/>
<IconButton
aria={Locale.Settings.Sync.LocalState + Locale.UI.Import}
icon={<DownloadIcon />}
text={Locale.UI.Import}
onClick={() => {
@@ -702,6 +707,7 @@ export function Settings() {
subTitle={Locale.Settings.Access.CustomEndpoint.SubTitle}
>
<input
aria-label={Locale.Settings.Access.CustomEndpoint.Title}
type="checkbox"
checked={accessStore.useCustomConfig}
onChange={(e) =>
@@ -721,6 +727,7 @@ export function Settings() {
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}
@@ -736,6 +743,8 @@ export function Settings() {
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}
@@ -759,6 +768,7 @@ export function Settings() {
}
>
<input
aria-label={Locale.Settings.Access.Azure.Endpoint.Title}
type="text"
value={accessStore.azureUrl}
placeholder={Azure.ExampleEndpoint}
@@ -774,6 +784,7 @@ export function Settings() {
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}
@@ -789,6 +800,7 @@ export function Settings() {
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"
@@ -813,6 +825,7 @@ export function Settings() {
}
>
<input
aria-label={Locale.Settings.Access.Google.Endpoint.Title}
type="text"
value={accessStore.googleUrl}
placeholder={Google.ExampleEndpoint}
@@ -828,6 +841,7 @@ export function Settings() {
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}
@@ -843,6 +857,7 @@ export function Settings() {
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"
@@ -858,6 +873,7 @@ export function Settings() {
subTitle={Locale.Settings.Access.Google.GoogleSafetySettings.SubTitle}
>
<Select
aria-label={Locale.Settings.Access.Google.GoogleSafetySettings.Title}
value={accessStore.googleSafetySettings}
onChange={(e) => {
accessStore.update(
@@ -888,6 +904,7 @@ export function Settings() {
}
>
<input
aria-label={Locale.Settings.Access.Anthropic.Endpoint.Title}
type="text"
value={accessStore.anthropicUrl}
placeholder={Anthropic.ExampleEndpoint}
@@ -903,6 +920,7 @@ export function Settings() {
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}
@@ -918,6 +936,7 @@ export function Settings() {
subTitle={Locale.Settings.Access.Anthropic.ApiVerion.SubTitle}
>
<input
aria-label={Locale.Settings.Access.Anthropic.ApiVerion.Title}
type="text"
value={accessStore.anthropicApiVersion}
placeholder={Anthropic.Vision}
@@ -939,6 +958,7 @@ export function Settings() {
subTitle={Locale.Settings.Access.Baidu.Endpoint.SubTitle}
>
<input
aria-label={Locale.Settings.Access.Baidu.Endpoint.Title}
type="text"
value={accessStore.baiduUrl}
placeholder={Baidu.ExampleEndpoint}
@@ -954,6 +974,7 @@ export function Settings() {
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}
@@ -969,6 +990,7 @@ export function Settings() {
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}
@@ -990,6 +1012,7 @@ export function Settings() {
subTitle={Locale.Settings.Access.Tencent.Endpoint.SubTitle}
>
<input
aria-label={Locale.Settings.Access.Tencent.Endpoint.Title}
type="text"
value={accessStore.tencentUrl}
placeholder={Tencent.ExampleEndpoint}
@@ -1005,6 +1028,7 @@ export function Settings() {
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}
@@ -1020,6 +1044,7 @@ export function Settings() {
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}
@@ -1044,6 +1069,7 @@ export function Settings() {
}
>
<input
aria-label={Locale.Settings.Access.ByteDance.Endpoint.Title}
type="text"
value={accessStore.bytedanceUrl}
placeholder={ByteDance.ExampleEndpoint}
@@ -1059,6 +1085,7 @@ export function Settings() {
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}
@@ -1083,6 +1110,7 @@ export function Settings() {
}
>
<input
aria-label={Locale.Settings.Access.Alibaba.Endpoint.Title}
type="text"
value={accessStore.alibabaUrl}
placeholder={Alibaba.ExampleEndpoint}
@@ -1098,6 +1126,7 @@ export function Settings() {
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}
@@ -1122,6 +1151,7 @@ export function Settings() {
}
>
<input
aria-label={Locale.Settings.Access.Moonshot.Endpoint.Title}
type="text"
value={accessStore.moonshotUrl}
placeholder={Moonshot.ExampleEndpoint}
@@ -1137,6 +1167,7 @@ export function Settings() {
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}
@@ -1161,6 +1192,7 @@ export function Settings() {
}
>
<input
aria-label={Locale.Settings.Access.Stability.Endpoint.Title}
type="text"
value={accessStore.stabilityUrl}
placeholder={Stability.ExampleEndpoint}
@@ -1176,6 +1208,7 @@ export function Settings() {
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}
@@ -1199,6 +1232,7 @@ export function Settings() {
}
>
<input
aria-label={Locale.Settings.Access.Iflytek.Endpoint.Title}
type="text"
value={accessStore.iflytekUrl}
placeholder={Iflytek.ExampleEndpoint}
@@ -1214,6 +1248,7 @@ export function Settings() {
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}
@@ -1230,6 +1265,7 @@ export function Settings() {
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}
@@ -1259,6 +1295,7 @@ export function Settings() {
<div className="window-action-button"></div>
<div className="window-action-button">
<IconButton
aria={Locale.UI.Close}
icon={<CloseIcon />}
onClick={() => navigate(Path.Home)}
bordered
@@ -1282,6 +1319,8 @@ export function Settings() {
open={showEmojiPicker}
>
<div
aria-label={Locale.Settings.Avatar}
tabIndex={0}
className={styles.avatar}
onClick={() => {
setShowEmojiPicker(!showEmojiPicker);
@@ -1319,6 +1358,7 @@ export function Settings() {
<ListItem title={Locale.Settings.SendKey}>
<Select
aria-label={Locale.Settings.SendKey}
value={config.submitKey}
onChange={(e) => {
updateConfig(
@@ -1337,6 +1377,7 @@ export function Settings() {
<ListItem title={Locale.Settings.Theme}>
<Select
aria-label={Locale.Settings.Theme}
value={config.theme}
onChange={(e) => {
updateConfig(
@@ -1354,6 +1395,7 @@ export function Settings() {
<ListItem title={Locale.Settings.Lang.Name}>
<Select
aria-label={Locale.Settings.Lang.Name}
value={getLang()}
onChange={(e) => {
changeLang(e.target.value as any);
@@ -1372,6 +1414,7 @@ export function Settings() {
subTitle={Locale.Settings.FontSize.SubTitle}
>
<InputRange
aria={Locale.Settings.FontSize.Title}
title={`${config.fontSize ?? 14}px`}
value={config.fontSize}
min="12"
@@ -1391,6 +1434,7 @@ export function Settings() {
subTitle={Locale.Settings.FontFamily.SubTitle}
>
<input
aria-label={Locale.Settings.FontFamily.Title}
type="text"
value={config.fontFamily}
placeholder={Locale.Settings.FontFamily.Placeholder}
@@ -1407,6 +1451,7 @@ export function Settings() {
subTitle={Locale.Settings.AutoGenerateTitle.SubTitle}
>
<input
aria-label={Locale.Settings.AutoGenerateTitle.Title}
type="checkbox"
checked={config.enableAutoGenerateTitle}
onChange={(e) =>
@@ -1423,6 +1468,7 @@ export function Settings() {
subTitle={Locale.Settings.SendPreviewBubble.SubTitle}
>
<input
aria-label={Locale.Settings.SendPreviewBubble.Title}
type="checkbox"
checked={config.sendPreviewBubble}
onChange={(e) =>
@@ -1443,6 +1489,7 @@ export function Settings() {
subTitle={Locale.Settings.Mask.Splash.SubTitle}
>
<input
aria-label={Locale.Settings.Mask.Splash.Title}
type="checkbox"
checked={!config.dontShowMaskSplashScreen}
onChange={(e) =>
@@ -1460,6 +1507,7 @@ export function Settings() {
subTitle={Locale.Settings.Mask.Builtin.SubTitle}
>
<input
aria-label={Locale.Settings.Mask.Builtin.Title}
type="checkbox"
checked={config.hideBuiltinMasks}
onChange={(e) =>
@@ -1478,6 +1526,7 @@ export function Settings() {
subTitle={Locale.Settings.Prompt.Disable.SubTitle}
>
<input
aria-label={Locale.Settings.Prompt.Disable.Title}
type="checkbox"
checked={config.disablePromptHint}
onChange={(e) =>
@@ -1497,6 +1546,7 @@ export function Settings() {
)}
>
<IconButton
aria={Locale.Settings.Prompt.List + Locale.Settings.Prompt.Edit}
icon={<EditIcon />}
text={Locale.Settings.Prompt.Edit}
onClick={() => setShowPromptModal(true)}
@@ -1518,6 +1568,7 @@ export function Settings() {
subTitle={Locale.Settings.Access.Provider.SubTitle}
>
<Select
aria-label={Locale.Settings.Access.Provider.Title}
value={accessStore.provider}
onChange={(e) => {
accessStore.update(
@@ -1582,6 +1633,7 @@ export function Settings() {
subTitle={Locale.Settings.Access.CustomModel.SubTitle}
>
<input
aria-label={Locale.Settings.Access.CustomModel.Title}
type="text"
value={config.customModels}
placeholder="model1,model2,model3"

View File

@@ -297,12 +297,20 @@ export function SideBar(props: { className?: string }) {
</div>
<div className={styles["sidebar-action"]}>
<Link to={Path.Settings}>
<IconButton icon={<SettingsIcon />} shadow />
<IconButton
aria={Locale.Settings.Title}
icon={<SettingsIcon />}
shadow
/>
</Link>
</div>
<div className={styles["sidebar-action"]}>
<a href={REPO_URL} target="_blank" rel="noopener noreferrer">
<IconButton icon={<GithubIcon />} shadow />
<IconButton
aria={Locale.Export.MessageFromChatGPT}
icon={<GithubIcon />}
shadow
/>
</a>
</div>
</>

View File

@@ -265,9 +265,10 @@ export function Input(props: InputProps) {
);
}
export function PasswordInput(props: HTMLProps<HTMLInputElement>) {
export function PasswordInput(
props: HTMLProps<HTMLInputElement> & { aria?: string },
) {
const [visible, setVisible] = useState(false);
function changeVisibility() {
setVisible(!visible);
}
@@ -275,6 +276,7 @@ export function PasswordInput(props: HTMLProps<HTMLInputElement>) {
return (
<div className={"password-input-container"}>
<IconButton
aria={props.aria}
icon={visible ? <EyeIcon /> : <EyeOffIcon />}
onClick={changeVisibility}
className={"password-eye"}