mirror of
				https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web.git
				synced 2025-11-04 16:23:41 +08:00 
			
		
		
		
	Merge pull request #5219 from ConnectAI-E/feature/access
修复ChatGPTNextWeb页面的无障碍问题
This commit is contained in:
		@@ -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>
 | 
			
		||||
  );
 | 
			
		||||
 
 | 
			
		||||
@@ -1337,6 +1337,8 @@ function _Chat() {
 | 
			
		||||
              <IconButton
 | 
			
		||||
                icon={<RenameIcon />}
 | 
			
		||||
                bordered
 | 
			
		||||
                title={Locale.Chat.EditMessage.Title}
 | 
			
		||||
                aria={Locale.Chat.EditMessage.Title}
 | 
			
		||||
                onClick={() => setIsEditingMessage(true)}
 | 
			
		||||
              />
 | 
			
		||||
            </div>
 | 
			
		||||
@@ -1356,6 +1358,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),
 | 
			
		||||
@@ -1407,6 +1411,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,
 | 
			
		||||
 
 | 
			
		||||
@@ -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}
 | 
			
		||||
 
 | 
			
		||||
@@ -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) => {
 | 
			
		||||
 
 | 
			
		||||
@@ -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) =>
 | 
			
		||||
 
 | 
			
		||||
@@ -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%" }}
 | 
			
		||||
 
 | 
			
		||||
@@ -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={() => {
 | 
			
		||||
 
 | 
			
		||||
@@ -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)) {
 | 
			
		||||
@@ -513,6 +515,7 @@ function SyncItems() {
 | 
			
		||||
        >
 | 
			
		||||
          <div style={{ display: "flex" }}>
 | 
			
		||||
            <IconButton
 | 
			
		||||
              aria={Locale.Settings.Sync.CloudState + Locale.UI.Config}
 | 
			
		||||
              icon={<ConfigIcon />}
 | 
			
		||||
              text={Locale.UI.Config}
 | 
			
		||||
              onClick={() => {
 | 
			
		||||
@@ -543,6 +546,7 @@ function SyncItems() {
 | 
			
		||||
        >
 | 
			
		||||
          <div style={{ display: "flex" }}>
 | 
			
		||||
            <IconButton
 | 
			
		||||
              aria={Locale.Settings.Sync.LocalState + Locale.UI.Export}
 | 
			
		||||
              icon={<UploadIcon />}
 | 
			
		||||
              text={Locale.UI.Export}
 | 
			
		||||
              onClick={() => {
 | 
			
		||||
@@ -550,6 +554,7 @@ function SyncItems() {
 | 
			
		||||
              }}
 | 
			
		||||
            />
 | 
			
		||||
            <IconButton
 | 
			
		||||
              aria={Locale.Settings.Sync.LocalState + Locale.UI.Import}
 | 
			
		||||
              icon={<DownloadIcon />}
 | 
			
		||||
              text={Locale.UI.Import}
 | 
			
		||||
              onClick={() => {
 | 
			
		||||
@@ -687,6 +692,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) =>
 | 
			
		||||
@@ -706,6 +712,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}
 | 
			
		||||
@@ -721,6 +728,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}
 | 
			
		||||
@@ -744,6 +753,7 @@ export function Settings() {
 | 
			
		||||
        }
 | 
			
		||||
      >
 | 
			
		||||
        <input
 | 
			
		||||
          aria-label={Locale.Settings.Access.Azure.Endpoint.Title}
 | 
			
		||||
          type="text"
 | 
			
		||||
          value={accessStore.azureUrl}
 | 
			
		||||
          placeholder={Azure.ExampleEndpoint}
 | 
			
		||||
@@ -759,6 +769,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}
 | 
			
		||||
@@ -774,6 +785,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"
 | 
			
		||||
@@ -798,6 +810,7 @@ export function Settings() {
 | 
			
		||||
        }
 | 
			
		||||
      >
 | 
			
		||||
        <input
 | 
			
		||||
          aria-label={Locale.Settings.Access.Google.Endpoint.Title}
 | 
			
		||||
          type="text"
 | 
			
		||||
          value={accessStore.googleUrl}
 | 
			
		||||
          placeholder={Google.ExampleEndpoint}
 | 
			
		||||
@@ -813,6 +826,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}
 | 
			
		||||
@@ -828,6 +842,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"
 | 
			
		||||
@@ -843,6 +858,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(
 | 
			
		||||
@@ -873,6 +889,7 @@ export function Settings() {
 | 
			
		||||
        }
 | 
			
		||||
      >
 | 
			
		||||
        <input
 | 
			
		||||
          aria-label={Locale.Settings.Access.Anthropic.Endpoint.Title}
 | 
			
		||||
          type="text"
 | 
			
		||||
          value={accessStore.anthropicUrl}
 | 
			
		||||
          placeholder={Anthropic.ExampleEndpoint}
 | 
			
		||||
@@ -888,6 +905,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}
 | 
			
		||||
@@ -903,6 +921,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}
 | 
			
		||||
@@ -924,6 +943,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}
 | 
			
		||||
@@ -939,6 +959,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}
 | 
			
		||||
@@ -954,6 +975,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}
 | 
			
		||||
@@ -975,6 +997,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}
 | 
			
		||||
@@ -990,6 +1013,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}
 | 
			
		||||
@@ -1005,6 +1029,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}
 | 
			
		||||
@@ -1029,6 +1054,7 @@ export function Settings() {
 | 
			
		||||
        }
 | 
			
		||||
      >
 | 
			
		||||
        <input
 | 
			
		||||
          aria-label={Locale.Settings.Access.ByteDance.Endpoint.Title}
 | 
			
		||||
          type="text"
 | 
			
		||||
          value={accessStore.bytedanceUrl}
 | 
			
		||||
          placeholder={ByteDance.ExampleEndpoint}
 | 
			
		||||
@@ -1044,6 +1070,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}
 | 
			
		||||
@@ -1068,6 +1095,7 @@ export function Settings() {
 | 
			
		||||
        }
 | 
			
		||||
      >
 | 
			
		||||
        <input
 | 
			
		||||
          aria-label={Locale.Settings.Access.Alibaba.Endpoint.Title}
 | 
			
		||||
          type="text"
 | 
			
		||||
          value={accessStore.alibabaUrl}
 | 
			
		||||
          placeholder={Alibaba.ExampleEndpoint}
 | 
			
		||||
@@ -1083,6 +1111,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}
 | 
			
		||||
@@ -1107,6 +1136,7 @@ export function Settings() {
 | 
			
		||||
        }
 | 
			
		||||
      >
 | 
			
		||||
        <input
 | 
			
		||||
          aria-label={Locale.Settings.Access.Moonshot.Endpoint.Title}
 | 
			
		||||
          type="text"
 | 
			
		||||
          value={accessStore.moonshotUrl}
 | 
			
		||||
          placeholder={Moonshot.ExampleEndpoint}
 | 
			
		||||
@@ -1122,6 +1152,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}
 | 
			
		||||
@@ -1146,6 +1177,7 @@ export function Settings() {
 | 
			
		||||
        }
 | 
			
		||||
      >
 | 
			
		||||
        <input
 | 
			
		||||
          aria-label={Locale.Settings.Access.Stability.Endpoint.Title}
 | 
			
		||||
          type="text"
 | 
			
		||||
          value={accessStore.stabilityUrl}
 | 
			
		||||
          placeholder={Stability.ExampleEndpoint}
 | 
			
		||||
@@ -1161,6 +1193,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}
 | 
			
		||||
@@ -1184,6 +1217,7 @@ export function Settings() {
 | 
			
		||||
        }
 | 
			
		||||
      >
 | 
			
		||||
        <input
 | 
			
		||||
          aria-label={Locale.Settings.Access.Iflytek.Endpoint.Title}
 | 
			
		||||
          type="text"
 | 
			
		||||
          value={accessStore.iflytekUrl}
 | 
			
		||||
          placeholder={Iflytek.ExampleEndpoint}
 | 
			
		||||
@@ -1199,6 +1233,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}
 | 
			
		||||
@@ -1215,6 +1250,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}
 | 
			
		||||
@@ -1244,6 +1280,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
 | 
			
		||||
@@ -1267,6 +1304,8 @@ export function Settings() {
 | 
			
		||||
              open={showEmojiPicker}
 | 
			
		||||
            >
 | 
			
		||||
              <div
 | 
			
		||||
                aria-label={Locale.Settings.Avatar}
 | 
			
		||||
                tabIndex={0}
 | 
			
		||||
                className={styles.avatar}
 | 
			
		||||
                onClick={() => {
 | 
			
		||||
                  setShowEmojiPicker(!showEmojiPicker);
 | 
			
		||||
@@ -1304,6 +1343,7 @@ export function Settings() {
 | 
			
		||||
 | 
			
		||||
          <ListItem title={Locale.Settings.SendKey}>
 | 
			
		||||
            <Select
 | 
			
		||||
              aria-label={Locale.Settings.SendKey}
 | 
			
		||||
              value={config.submitKey}
 | 
			
		||||
              onChange={(e) => {
 | 
			
		||||
                updateConfig(
 | 
			
		||||
@@ -1322,6 +1362,7 @@ export function Settings() {
 | 
			
		||||
 | 
			
		||||
          <ListItem title={Locale.Settings.Theme}>
 | 
			
		||||
            <Select
 | 
			
		||||
              aria-label={Locale.Settings.Theme}
 | 
			
		||||
              value={config.theme}
 | 
			
		||||
              onChange={(e) => {
 | 
			
		||||
                updateConfig(
 | 
			
		||||
@@ -1339,6 +1380,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);
 | 
			
		||||
@@ -1357,6 +1399,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"
 | 
			
		||||
@@ -1376,6 +1419,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}
 | 
			
		||||
@@ -1392,6 +1436,7 @@ export function Settings() {
 | 
			
		||||
            subTitle={Locale.Settings.AutoGenerateTitle.SubTitle}
 | 
			
		||||
          >
 | 
			
		||||
            <input
 | 
			
		||||
              aria-label={Locale.Settings.AutoGenerateTitle.Title}
 | 
			
		||||
              type="checkbox"
 | 
			
		||||
              checked={config.enableAutoGenerateTitle}
 | 
			
		||||
              onChange={(e) =>
 | 
			
		||||
@@ -1408,6 +1453,7 @@ export function Settings() {
 | 
			
		||||
            subTitle={Locale.Settings.SendPreviewBubble.SubTitle}
 | 
			
		||||
          >
 | 
			
		||||
            <input
 | 
			
		||||
              aria-label={Locale.Settings.SendPreviewBubble.Title}
 | 
			
		||||
              type="checkbox"
 | 
			
		||||
              checked={config.sendPreviewBubble}
 | 
			
		||||
              onChange={(e) =>
 | 
			
		||||
@@ -1428,6 +1474,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) =>
 | 
			
		||||
@@ -1445,6 +1492,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) =>
 | 
			
		||||
@@ -1463,6 +1511,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) =>
 | 
			
		||||
@@ -1482,6 +1531,7 @@ export function Settings() {
 | 
			
		||||
            )}
 | 
			
		||||
          >
 | 
			
		||||
            <IconButton
 | 
			
		||||
              aria={Locale.Settings.Prompt.List + Locale.Settings.Prompt.Edit}
 | 
			
		||||
              icon={<EditIcon />}
 | 
			
		||||
              text={Locale.Settings.Prompt.Edit}
 | 
			
		||||
              onClick={() => setShowPromptModal(true)}
 | 
			
		||||
@@ -1503,6 +1553,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(
 | 
			
		||||
@@ -1567,6 +1618,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"
 | 
			
		||||
 
 | 
			
		||||
@@ -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>
 | 
			
		||||
          </>
 | 
			
		||||
 
 | 
			
		||||
@@ -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"}
 | 
			
		||||
 
 | 
			
		||||
@@ -42,6 +42,7 @@ const cn = {
 | 
			
		||||
      PinToastAction: "查看",
 | 
			
		||||
      Delete: "删除",
 | 
			
		||||
      Edit: "编辑",
 | 
			
		||||
      FullScreen: "全屏",
 | 
			
		||||
    },
 | 
			
		||||
    Commands: {
 | 
			
		||||
      new: "新建聊天",
 | 
			
		||||
@@ -132,6 +133,7 @@ const cn = {
 | 
			
		||||
  Settings: {
 | 
			
		||||
    Title: "设置",
 | 
			
		||||
    SubTitle: "所有设置选项",
 | 
			
		||||
    ShowPassword: "显示密码",
 | 
			
		||||
 | 
			
		||||
    Danger: {
 | 
			
		||||
      Reset: {
 | 
			
		||||
 
 | 
			
		||||
@@ -44,6 +44,7 @@ const en: LocaleType = {
 | 
			
		||||
      PinToastAction: "View",
 | 
			
		||||
      Delete: "Delete",
 | 
			
		||||
      Edit: "Edit",
 | 
			
		||||
      FullScreen: "FullScreen",
 | 
			
		||||
    },
 | 
			
		||||
    Commands: {
 | 
			
		||||
      new: "Start a new chat",
 | 
			
		||||
@@ -135,6 +136,7 @@ const en: LocaleType = {
 | 
			
		||||
  Settings: {
 | 
			
		||||
    Title: "Settings",
 | 
			
		||||
    SubTitle: "All Settings",
 | 
			
		||||
    ShowPassword: "ShowPassword",
 | 
			
		||||
    Danger: {
 | 
			
		||||
      Reset: {
 | 
			
		||||
        Title: "Reset All Settings",
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user