mirror of
https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web.git
synced 2025-10-01 23:56:39 +08:00
Merge remote-tracking branch 'upstream/main' into dev
# Conflicts: # app/components/settings.tsx # app/components/sidebar.tsx
This commit is contained in:
commit
0b930db371
@ -51,6 +51,8 @@ export interface LLMConfig {
|
||||
presence_penalty?: number;
|
||||
frequency_penalty?: number;
|
||||
size?: DalleRequestPayload["size"];
|
||||
quality?: DalleRequestPayload["quality"];
|
||||
style?: DalleRequestPayload["style"];
|
||||
}
|
||||
|
||||
export interface ChatOptions {
|
||||
|
@ -18,7 +18,7 @@ import {
|
||||
base64Image2Blob,
|
||||
} from "@/app/utils/chat";
|
||||
import { cloudflareAIGatewayUrl } from "@/app/utils/cloudflare";
|
||||
import { DalleSize } from "@/app/typing";
|
||||
import { DalleSize, DalleQuality, DalleStyle } from "@/app/typing";
|
||||
|
||||
import {
|
||||
ChatOptions,
|
||||
@ -71,6 +71,8 @@ export interface DalleRequestPayload {
|
||||
response_format: "url" | "b64_json";
|
||||
n: number;
|
||||
size: DalleSize;
|
||||
quality: DalleQuality;
|
||||
style: DalleStyle;
|
||||
}
|
||||
|
||||
export class ChatGPTApi implements LLMApi {
|
||||
@ -163,6 +165,8 @@ export class ChatGPTApi implements LLMApi {
|
||||
response_format: "b64_json", // using b64_json, and save image in CacheStorage
|
||||
n: 1,
|
||||
size: options.config?.size ?? "1024x1024",
|
||||
quality: options.config?.quality ?? "standard",
|
||||
style: options.config?.style ?? "vivid",
|
||||
};
|
||||
} else {
|
||||
const visionModel = isVisionModel(options.config.model);
|
||||
|
@ -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>
|
||||
);
|
||||
|
@ -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 UploadIcon from "../icons/upload.svg";
|
||||
|
||||
@ -72,7 +74,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";
|
||||
|
||||
@ -509,9 +511,17 @@ export function ChatActions(props: {
|
||||
const current_day_token = localStorage.getItem("current_day_token") ?? "";
|
||||
|
||||
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);
|
||||
@ -686,6 +696,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}
|
||||
@ -1436,6 +1500,8 @@ function _Chat() {
|
||||
<IconButton
|
||||
icon={<RenameIcon />}
|
||||
bordered
|
||||
title={Locale.Chat.EditMessage.Title}
|
||||
aria={Locale.Chat.EditMessage.Title}
|
||||
onClick={() => setIsEditingMessage(true)}
|
||||
/>
|
||||
</div>
|
||||
@ -1455,6 +1521,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),
|
||||
@ -1506,6 +1574,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%" }}
|
||||
|
@ -135,6 +135,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)}
|
||||
@ -1496,29 +1546,30 @@ export function Settings() {
|
||||
{/* <>*/}
|
||||
{/* {useCustomConfigComponent}*/}
|
||||
|
||||
{/* {accessStore.useCustomConfig && (*/}
|
||||
{/* <>*/}
|
||||
{/* <ListItem*/}
|
||||
{/* title={Locale.Settings.Access.Provider.Title}*/}
|
||||
{/* subTitle={Locale.Settings.Access.Provider.SubTitle}*/}
|
||||
{/* >*/}
|
||||
{/* <Select*/}
|
||||
{/* value={accessStore.provider}*/}
|
||||
{/* onChange={(e) => {*/}
|
||||
{/* accessStore.update(*/}
|
||||
{/* (access) =>*/}
|
||||
{/* (access.provider = e.target*/}
|
||||
{/* .value as ServiceProvider),*/}
|
||||
{/* );*/}
|
||||
{/* }}*/}
|
||||
{/* >*/}
|
||||
{/* {Object.entries(ServiceProvider).map(([k, v]) => (*/}
|
||||
{/* <option value={v} key={k}>*/}
|
||||
{/* {k}*/}
|
||||
{/* </option>*/}
|
||||
{/* ))}*/}
|
||||
{/* </Select>*/}
|
||||
{/* </ListItem>*/}
|
||||
{/*{accessStore.useCustomConfig && (*/}
|
||||
{/* <>*/}
|
||||
{/* <ListItem*/}
|
||||
{/* title={Locale.Settings.Access.Provider.Title}*/}
|
||||
{/* subTitle={Locale.Settings.Access.Provider.SubTitle}*/}
|
||||
{/* >*/}
|
||||
{/* <Select*/}
|
||||
{/* aria-label={Locale.Settings.Access.Provider.Title}*/}
|
||||
{/* value={accessStore.provider}*/}
|
||||
{/* onChange={(e) => {*/}
|
||||
{/* accessStore.update(*/}
|
||||
{/* (access) =>*/}
|
||||
{/* (access.provider = e.target*/}
|
||||
{/* .value as ServiceProvider),*/}
|
||||
{/* );*/}
|
||||
{/* }}*/}
|
||||
{/* >*/}
|
||||
{/* {Object.entries(ServiceProvider).map(([k, v]) => (*/}
|
||||
{/* <option value={v} key={k}>*/}
|
||||
{/* {k}*/}
|
||||
{/* </option>*/}
|
||||
{/* ))}*/}
|
||||
{/* </Select>*/}
|
||||
{/* </ListItem>*/}
|
||||
|
||||
{/* {openAIConfigComponent}*/}
|
||||
{/* {azureConfigComponent}*/}
|
||||
@ -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"*/}
|
||||
|
@ -348,13 +348,22 @@ 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>*/}
|
||||
|
||||
<IconButton
|
||||
onClick={async () => {
|
||||
if (await showConfirm(Locale.Settings.Danger.Clear.Confirm)) {
|
||||
|
@ -282,9 +282,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);
|
||||
}
|
||||
@ -292,6 +293,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"}
|
||||
|
@ -245,6 +245,7 @@ export const KnowledgeCutOffDate: Record<string, string> = {
|
||||
"gpt-4-turbo-2024-04-09": "2023-12",
|
||||
"gpt-4-turbo-preview": "2023-12",
|
||||
"gpt-4o-2024-05-13": "2023-10",
|
||||
"gpt-4o-2024-08-06": "2023-10",
|
||||
"gpt-4o-mini": "2023-10",
|
||||
"gpt-4o-mini-2024-07-18": "2023-10",
|
||||
"gpt-4-vision-preview": "2023-04",
|
||||
@ -266,6 +267,7 @@ const openaiModels = [
|
||||
"gpt-4-turbo-preview",
|
||||
"gpt-4o",
|
||||
"gpt-4o-2024-05-13",
|
||||
"gpt-4o-2024-08-06",
|
||||
"gpt-4o-mini",
|
||||
"gpt-4o-mini-2024-07-18",
|
||||
"gpt-4-vision-preview",
|
||||
|
4
app/icons/hd.svg
Normal file
4
app/icons/hd.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#333" class="bi bi-badge-hd" viewBox="0 0 16 16">
|
||||
<path d="M7.396 11V5.001H6.209v2.44H3.687V5H2.5v6h1.187V8.43h2.522V11zM8.5 5.001V11h2.188c1.811 0 2.685-1.107 2.685-3.015 0-1.894-.86-2.984-2.684-2.984zm1.187.967h.843c1.112 0 1.622.686 1.622 2.04 0 1.353-.505 2.02-1.622 2.02h-.843z"/>
|
||||
<path d="M14 3a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1zM2 2a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 514 B |
4
app/icons/palette.svg
Normal file
4
app/icons/palette.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#333" class="bi bi-palette" viewBox="0 0 16 16">
|
||||
<path d="M8 5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3m4 3a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3M5.5 7a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0m.5 6a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3"/>
|
||||
<path d="M16 8c0 3.15-1.866 2.585-3.567 2.07C11.42 9.763 10.465 9.473 10 10c-.603.683-.475 1.819-.351 2.92C9.826 14.495 9.996 16 8 16a8 8 0 1 1 8-8m-8 7c.611 0 .654-.171.655-.176.078-.146.124-.464.07-1.119-.014-.168-.037-.37-.061-.591-.052-.464-.112-1.005-.118-1.462-.01-.707.083-1.61.704-2.314.369-.417.845-.578 1.272-.618.404-.038.812.026 1.16.104.343.077.702.186 1.025.284l.028.008c.346.105.658.199.953.266.653.148.904.083.991.024C14.717 9.38 15 9.161 15 8a7 7 0 1 0-7 7"/>
|
||||
</svg>
|
After Width: | Height: | Size: 781 B |
@ -82,6 +82,7 @@ const cn = {
|
||||
PinToastAction: "查看",
|
||||
Delete: "删除",
|
||||
Edit: "编辑",
|
||||
FullScreen: "全屏",
|
||||
},
|
||||
Commands: {
|
||||
new: "新建聊天",
|
||||
@ -172,6 +173,7 @@ const cn = {
|
||||
Settings: {
|
||||
Title: "设置",
|
||||
SubTitle: "所有设置选项",
|
||||
ShowPassword: "显示密码",
|
||||
|
||||
Danger: {
|
||||
Reset: {
|
||||
|
@ -84,6 +84,7 @@ const en: LocaleType = {
|
||||
PinToastAction: "View",
|
||||
Delete: "Delete",
|
||||
Edit: "Edit",
|
||||
FullScreen: "FullScreen",
|
||||
},
|
||||
Commands: {
|
||||
new: "Start a new chat",
|
||||
@ -175,6 +176,7 @@ const en: LocaleType = {
|
||||
Settings: {
|
||||
Title: "Settings",
|
||||
SubTitle: "All Settings",
|
||||
ShowPassword: "ShowPassword",
|
||||
Danger: {
|
||||
Reset: {
|
||||
Title: "Reset All Settings",
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { LLMModel } from "../client/api";
|
||||
import { DalleSize } from "../typing";
|
||||
import { DalleSize, DalleQuality, DalleStyle } from "../typing";
|
||||
import { getClientConfig } from "../config/client";
|
||||
import {
|
||||
DEFAULT_INPUT_TEMPLATE,
|
||||
@ -68,6 +68,8 @@ export const DEFAULT_CONFIG = {
|
||||
enableInjectSystemPrompts: true,
|
||||
template: config?.template ?? DEFAULT_INPUT_TEMPLATE,
|
||||
size: "1024x1024" as DalleSize,
|
||||
quality: "standard" as DalleQuality,
|
||||
style: "vivid" as DalleStyle,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -9,3 +9,5 @@ export interface RequestMessage {
|
||||
}
|
||||
|
||||
export type DalleSize = "1024x1024" | "1792x1024" | "1024x1792";
|
||||
export type DalleQuality = "standard" | "hd";
|
||||
export type DalleStyle = "vivid" | "natural";
|
||||
|
Loading…
Reference in New Issue
Block a user