mirror of
https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web.git
synced 2026-04-25 04:24:27 +08:00
Compare commits
13 Commits
v2.14.1
...
cec7ca6fd5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cec7ca6fd5 | ||
|
|
cf1c8e8f2a | ||
|
|
d948be2372 | ||
|
|
cc28aef625 | ||
|
|
036358de7c | ||
|
|
0958b9ee12 | ||
|
|
aff1d7ecd6 | ||
|
|
42fdbd9bb8 | ||
|
|
034c82e514 | ||
|
|
14ff46b5cd | ||
|
|
c9099ca0a5 | ||
|
|
58b144b345 | ||
|
|
af21c57e77 |
@@ -13,7 +13,7 @@ function getModels(remoteModelRes: OpenAIListModelResponse) {
|
|||||||
|
|
||||||
if (config.disableGPT4) {
|
if (config.disableGPT4) {
|
||||||
remoteModelRes.data = remoteModelRes.data.filter(
|
remoteModelRes.data = remoteModelRes.data.filter(
|
||||||
(m) => !m.id.startsWith("gpt-4"),
|
(m) => !m.id.startsWith("gpt-4") || m.id.startsWith("gpt-4o-mini"),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ export function IconButton(props: {
|
|||||||
tabIndex?: number;
|
tabIndex?: number;
|
||||||
autoFocus?: boolean;
|
autoFocus?: boolean;
|
||||||
style?: CSSProperties;
|
style?: CSSProperties;
|
||||||
|
aria?: string;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
@@ -34,9 +35,11 @@ export function IconButton(props: {
|
|||||||
tabIndex={props.tabIndex}
|
tabIndex={props.tabIndex}
|
||||||
autoFocus={props.autoFocus}
|
autoFocus={props.autoFocus}
|
||||||
style={props.style}
|
style={props.style}
|
||||||
|
aria-label={props.aria}
|
||||||
>
|
>
|
||||||
{props.icon && (
|
{props.icon && (
|
||||||
<div
|
<div
|
||||||
|
aria-label={props.text || props.title}
|
||||||
className={
|
className={
|
||||||
styles["icon-button-icon"] +
|
styles["icon-button-icon"] +
|
||||||
` ${props.type === "primary" && "no-dark"}`
|
` ${props.type === "primary" && "no-dark"}`
|
||||||
@@ -47,7 +50,12 @@ export function IconButton(props: {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{props.text && (
|
{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>
|
</button>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -231,10 +231,12 @@
|
|||||||
|
|
||||||
animation: slide-in ease 0.3s;
|
animation: slide-in ease 0.3s;
|
||||||
|
|
||||||
$linear: linear-gradient(to right,
|
$linear: linear-gradient(
|
||||||
rgba(0, 0, 0, 0),
|
to right,
|
||||||
rgba(0, 0, 0, 1),
|
rgba(0, 0, 0, 0),
|
||||||
rgba(0, 0, 0, 0));
|
rgba(0, 0, 0, 1),
|
||||||
|
rgba(0, 0, 0, 0)
|
||||||
|
);
|
||||||
mask-image: $linear;
|
mask-image: $linear;
|
||||||
|
|
||||||
@mixin show {
|
@mixin show {
|
||||||
@@ -340,10 +342,14 @@
|
|||||||
margin: 0 10px;
|
margin: 0 10px;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
.chat-input-actions {
|
.chat-input-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
|
transition: all ease 0.3s;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 12px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -367,7 +373,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-message-user>.chat-message-container {
|
.chat-message-user > .chat-message-container {
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -450,23 +456,27 @@
|
|||||||
border: rgba($color: #888, $alpha: 0.2) 1px solid;
|
border: rgba($color: #888, $alpha: 0.2) 1px solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@media only screen and (max-width: 600px) {
|
@media only screen and (max-width: 600px) {
|
||||||
$calc-image-width: calc(100vw/3*2/var(--image-count));
|
$calc-image-width: calc(100vw / 3 * 2 / var(--image-count));
|
||||||
|
|
||||||
.chat-message-item-image-multi {
|
.chat-message-item-image-multi {
|
||||||
width: $calc-image-width;
|
width: $calc-image-width;
|
||||||
height: $calc-image-width;
|
height: $calc-image-width;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-message-item-image {
|
.chat-message-item-image {
|
||||||
max-width: calc(100vw/3*2);
|
max-width: calc(100vw / 3 * 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (min-width: 600px) {
|
@media screen and (min-width: 600px) {
|
||||||
$max-image-width: calc(calc(1200px - var(--sidebar-width))/3*2/var(--image-count));
|
$max-image-width: calc(
|
||||||
$image-width: calc(calc(var(--window-width) - var(--sidebar-width))/3*2/var(--image-count));
|
calc(1200px - var(--sidebar-width)) / 3 * 2 / var(--image-count)
|
||||||
|
);
|
||||||
|
$image-width: calc(
|
||||||
|
calc(var(--window-width) - var(--sidebar-width)) / 3 * 2 /
|
||||||
|
var(--image-count)
|
||||||
|
);
|
||||||
|
|
||||||
.chat-message-item-image-multi {
|
.chat-message-item-image-multi {
|
||||||
width: $image-width;
|
width: $image-width;
|
||||||
@@ -476,7 +486,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.chat-message-item-image {
|
.chat-message-item-image {
|
||||||
max-width: calc(calc(1200px - var(--sidebar-width))/3*2);
|
max-width: calc(calc(1200px - var(--sidebar-width)) / 3 * 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -494,7 +504,7 @@
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-message-user>.chat-message-container>.chat-message-item {
|
.chat-message-user > .chat-message-container > .chat-message-item {
|
||||||
background-color: var(--second);
|
background-color: var(--second);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
@@ -605,7 +615,8 @@
|
|||||||
min-height: 68px;
|
min-height: 68px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-input:focus {}
|
.chat-input:focus {
|
||||||
|
}
|
||||||
|
|
||||||
.chat-input-send {
|
.chat-input-send {
|
||||||
background-color: var(--primary);
|
background-color: var(--primary);
|
||||||
@@ -624,4 +635,4 @@
|
|||||||
.chat-input-send {
|
.chat-input-send {
|
||||||
bottom: 30px;
|
bottom: 30px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ import {
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
copyToClipboard,
|
copyToClipboard,
|
||||||
selectOrCopy,
|
isNotSelectRange,
|
||||||
autoGrowTextArea,
|
autoGrowTextArea,
|
||||||
useMobileScreen,
|
useMobileScreen,
|
||||||
getMessageTextContent,
|
getMessageTextContent,
|
||||||
@@ -250,6 +250,108 @@ function useSubmitHandler() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ChatMessageActions(props: {
|
||||||
|
index: number;
|
||||||
|
message: ChatMessage;
|
||||||
|
position: { x: number; y: number };
|
||||||
|
isHover: boolean;
|
||||||
|
onUserStop: (messageId: string) => void;
|
||||||
|
onResend: (message: ChatMessage) => void;
|
||||||
|
onDelete: (messageId: string) => void;
|
||||||
|
onPinMessage: (message: ChatMessage) => void;
|
||||||
|
}) {
|
||||||
|
const {
|
||||||
|
index,
|
||||||
|
message,
|
||||||
|
position,
|
||||||
|
isHover,
|
||||||
|
onUserStop,
|
||||||
|
onResend,
|
||||||
|
onDelete,
|
||||||
|
onPinMessage,
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
const actionsRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
const [rect, setRect] = useState<DOMRect>({
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
top: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
toJSON: () => ({}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const isUserMessage = message.role === "user";
|
||||||
|
|
||||||
|
const [translate, setTranslate] = useState({ x: 0, y: 0 });
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (position.x && position.y && isHover) {
|
||||||
|
const x = position.x - rect.x - (isUserMessage ? rect.width : 0);
|
||||||
|
const y = position.y - rect.y - (isUserMessage ? rect.height : 0);
|
||||||
|
setTranslate({ x, y });
|
||||||
|
} else {
|
||||||
|
setTranslate({ x: 0, y: 0 });
|
||||||
|
}
|
||||||
|
}, [position, isHover]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const div = actionsRef.current;
|
||||||
|
if (div) {
|
||||||
|
const rect = div.getBoundingClientRect();
|
||||||
|
setRect(rect);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div ref={actionsRef} className={styles["chat-message-actions"]}>
|
||||||
|
<div
|
||||||
|
className={`${styles["chat-input-actions"]}`}
|
||||||
|
style={{
|
||||||
|
transform: `translate3d(${translate.x}px, ${translate.y}px, 0)`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{message.streaming ? (
|
||||||
|
<ChatAction
|
||||||
|
text={Locale.Chat.Actions.Stop}
|
||||||
|
icon={<StopIcon />}
|
||||||
|
onClick={() => onUserStop(message.id ?? index)}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<ChatAction
|
||||||
|
text={Locale.Chat.Actions.Retry}
|
||||||
|
icon={<ResetIcon />}
|
||||||
|
onClick={() => onResend(message)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ChatAction
|
||||||
|
text={Locale.Chat.Actions.Delete}
|
||||||
|
icon={<DeleteIcon />}
|
||||||
|
onClick={() => onDelete(message.id ?? index)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ChatAction
|
||||||
|
text={Locale.Chat.Actions.Pin}
|
||||||
|
icon={<PinIcon />}
|
||||||
|
onClick={() => onPinMessage(message)}
|
||||||
|
/>
|
||||||
|
<ChatAction
|
||||||
|
text={Locale.Chat.Actions.Copy}
|
||||||
|
icon={<CopyIcon />}
|
||||||
|
onClick={() => copyToClipboard(getMessageTextContent(message))}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export type RenderPrompt = Pick<Prompt, "title" | "content">;
|
export type RenderPrompt = Pick<Prompt, "title" | "content">;
|
||||||
|
|
||||||
export function PromptHints(props: {
|
export function PromptHints(props: {
|
||||||
@@ -792,6 +894,13 @@ function _Chat() {
|
|||||||
const [attachImages, setAttachImages] = useState<string[]>([]);
|
const [attachImages, setAttachImages] = useState<string[]>([]);
|
||||||
const [uploading, setUploading] = useState(false);
|
const [uploading, setUploading] = useState(false);
|
||||||
|
|
||||||
|
const [isMessageContainerHover, setIsMessageContainerHover] =
|
||||||
|
useState<boolean>(false);
|
||||||
|
const [actionsPosition, setActionsPosition] = useState<{
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
}>({ x: 0, y: 0 });
|
||||||
|
|
||||||
// prompt hints
|
// prompt hints
|
||||||
const promptStore = usePromptStore();
|
const promptStore = usePromptStore();
|
||||||
const [promptHints, setPromptHints] = useState<RenderPrompt[]>([]);
|
const [promptHints, setPromptHints] = useState<RenderPrompt[]>([]);
|
||||||
@@ -947,16 +1056,24 @@ function _Chat() {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const onRightClick = (e: any, message: ChatMessage) => {
|
|
||||||
// copy to clipboard
|
|
||||||
if (selectOrCopy(e.currentTarget, getMessageTextContent(message))) {
|
|
||||||
if (userInput.length === 0) {
|
|
||||||
setUserInput(getMessageTextContent(message));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const onRightClick = (e: any) => {
|
||||||
|
// move actions to the right click position
|
||||||
|
if (isNotSelectRange()) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
|
setActionsPosition({
|
||||||
|
x: e.clientX,
|
||||||
|
y: e.clientY,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
// handle mouse hover to reset actions position
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isMessageContainerHover) {
|
||||||
|
setActionsPosition({ x: 0, y: 0 });
|
||||||
|
}
|
||||||
|
}, [isMessageContainerHover]);
|
||||||
|
|
||||||
const deleteMessage = (msgId?: string) => {
|
const deleteMessage = (msgId?: string) => {
|
||||||
chatStore.updateCurrentSession(
|
chatStore.updateCurrentSession(
|
||||||
@@ -1337,6 +1454,8 @@ function _Chat() {
|
|||||||
<IconButton
|
<IconButton
|
||||||
icon={<RenameIcon />}
|
icon={<RenameIcon />}
|
||||||
bordered
|
bordered
|
||||||
|
title={Locale.Chat.EditMessage.Title}
|
||||||
|
aria={Locale.Chat.EditMessage.Title}
|
||||||
onClick={() => setIsEditingMessage(true)}
|
onClick={() => setIsEditingMessage(true)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -1356,6 +1475,8 @@ function _Chat() {
|
|||||||
<IconButton
|
<IconButton
|
||||||
icon={config.tightBorder ? <MinIcon /> : <MaxIcon />}
|
icon={config.tightBorder ? <MinIcon /> : <MaxIcon />}
|
||||||
bordered
|
bordered
|
||||||
|
title={Locale.Chat.Actions.FullScreen}
|
||||||
|
aria={Locale.Chat.Actions.FullScreen}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
config.update(
|
config.update(
|
||||||
(config) => (config.tightBorder = !config.tightBorder),
|
(config) => (config.tightBorder = !config.tightBorder),
|
||||||
@@ -1401,12 +1522,20 @@ function _Chat() {
|
|||||||
isUser ? styles["chat-message-user"] : styles["chat-message"]
|
isUser ? styles["chat-message-user"] : styles["chat-message"]
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div className={styles["chat-message-container"]}>
|
<div
|
||||||
|
className={styles["chat-message-container"]}
|
||||||
|
onClick={() => {
|
||||||
|
setActionsPosition({ x: 0, y: 0 });
|
||||||
|
}}
|
||||||
|
onMouseEnter={() => setIsMessageContainerHover(true)}
|
||||||
|
onMouseLeave={() => setIsMessageContainerHover(false)}
|
||||||
|
>
|
||||||
<div className={styles["chat-message-header"]}>
|
<div className={styles["chat-message-header"]}>
|
||||||
<div className={styles["chat-message-avatar"]}>
|
<div className={styles["chat-message-avatar"]}>
|
||||||
<div className={styles["chat-message-edit"]}>
|
<div className={styles["chat-message-edit"]}>
|
||||||
<IconButton
|
<IconButton
|
||||||
icon={<EditIcon />}
|
icon={<EditIcon />}
|
||||||
|
aria={Locale.Chat.Actions.Edit}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
const newMessage = await showPrompt(
|
const newMessage = await showPrompt(
|
||||||
Locale.Chat.Actions.Edit,
|
Locale.Chat.Actions.Edit,
|
||||||
@@ -1457,46 +1586,16 @@ function _Chat() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{showActions && (
|
{showActions && (
|
||||||
<div className={styles["chat-message-actions"]}>
|
<ChatMessageActions
|
||||||
<div className={styles["chat-input-actions"]}>
|
index={i}
|
||||||
{message.streaming ? (
|
message={message}
|
||||||
<ChatAction
|
position={actionsPosition}
|
||||||
text={Locale.Chat.Actions.Stop}
|
isHover={isMessageContainerHover}
|
||||||
icon={<StopIcon />}
|
onUserStop={onUserStop}
|
||||||
onClick={() => onUserStop(message.id ?? i)}
|
onResend={onResend}
|
||||||
/>
|
onDelete={onDelete}
|
||||||
) : (
|
onPinMessage={onPinMessage}
|
||||||
<>
|
/>
|
||||||
<ChatAction
|
|
||||||
text={Locale.Chat.Actions.Retry}
|
|
||||||
icon={<ResetIcon />}
|
|
||||||
onClick={() => onResend(message)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ChatAction
|
|
||||||
text={Locale.Chat.Actions.Delete}
|
|
||||||
icon={<DeleteIcon />}
|
|
||||||
onClick={() => onDelete(message.id ?? i)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ChatAction
|
|
||||||
text={Locale.Chat.Actions.Pin}
|
|
||||||
icon={<PinIcon />}
|
|
||||||
onClick={() => onPinMessage(message)}
|
|
||||||
/>
|
|
||||||
<ChatAction
|
|
||||||
text={Locale.Chat.Actions.Copy}
|
|
||||||
icon={<CopyIcon />}
|
|
||||||
onClick={() =>
|
|
||||||
copyToClipboard(
|
|
||||||
getMessageTextContent(message),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{showTyping && (
|
{showTyping && (
|
||||||
@@ -1513,7 +1612,7 @@ function _Chat() {
|
|||||||
message.content.length === 0 &&
|
message.content.length === 0 &&
|
||||||
!isUser
|
!isUser
|
||||||
}
|
}
|
||||||
onContextMenu={(e) => onRightClick(e, message)}
|
onContextMenu={(e) => onRightClick(e)}
|
||||||
onDoubleClickCapture={() => {
|
onDoubleClickCapture={() => {
|
||||||
if (!isMobileScreen) return;
|
if (!isMobileScreen) return;
|
||||||
setUserInput(getMessageTextContent(message));
|
setUserInput(getMessageTextContent(message));
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ interface InputRangeProps {
|
|||||||
min: string;
|
min: string;
|
||||||
max: string;
|
max: string;
|
||||||
step: string;
|
step: string;
|
||||||
|
aria: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function InputRange({
|
export function InputRange({
|
||||||
@@ -19,11 +20,13 @@ export function InputRange({
|
|||||||
min,
|
min,
|
||||||
max,
|
max,
|
||||||
step,
|
step,
|
||||||
|
aria,
|
||||||
}: InputRangeProps) {
|
}: InputRangeProps) {
|
||||||
return (
|
return (
|
||||||
<div className={styles["input-range"] + ` ${className ?? ""}`}>
|
<div className={styles["input-range"] + ` ${className ?? ""}`}>
|
||||||
{title || value}
|
{title || value}
|
||||||
<input
|
<input
|
||||||
|
aria-label={aria}
|
||||||
type="range"
|
type="range"
|
||||||
title={title}
|
title={title}
|
||||||
value={value}
|
value={value}
|
||||||
|
|||||||
@@ -127,6 +127,8 @@ export function MaskConfig(props: {
|
|||||||
onClose={() => setShowPicker(false)}
|
onClose={() => setShowPicker(false)}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
tabIndex={0}
|
||||||
|
aria-label={Locale.Mask.Config.Avatar}
|
||||||
onClick={() => setShowPicker(true)}
|
onClick={() => setShowPicker(true)}
|
||||||
style={{ cursor: "pointer" }}
|
style={{ cursor: "pointer" }}
|
||||||
>
|
>
|
||||||
@@ -139,6 +141,7 @@ export function MaskConfig(props: {
|
|||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem title={Locale.Mask.Config.Name}>
|
<ListItem title={Locale.Mask.Config.Name}>
|
||||||
<input
|
<input
|
||||||
|
aria-label={Locale.Mask.Config.Name}
|
||||||
type="text"
|
type="text"
|
||||||
value={props.mask.name}
|
value={props.mask.name}
|
||||||
onInput={(e) =>
|
onInput={(e) =>
|
||||||
@@ -153,6 +156,7 @@ export function MaskConfig(props: {
|
|||||||
subTitle={Locale.Mask.Config.HideContext.SubTitle}
|
subTitle={Locale.Mask.Config.HideContext.SubTitle}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
aria-label={Locale.Mask.Config.HideContext.Title}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={props.mask.hideContext}
|
checked={props.mask.hideContext}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
@@ -169,6 +173,7 @@ export function MaskConfig(props: {
|
|||||||
subTitle={Locale.Mask.Config.Share.SubTitle}
|
subTitle={Locale.Mask.Config.Share.SubTitle}
|
||||||
>
|
>
|
||||||
<IconButton
|
<IconButton
|
||||||
|
aria={Locale.Mask.Config.Share.Title}
|
||||||
icon={<CopyIcon />}
|
icon={<CopyIcon />}
|
||||||
text={Locale.Mask.Config.Share.Action}
|
text={Locale.Mask.Config.Share.Action}
|
||||||
onClick={copyMaskLink}
|
onClick={copyMaskLink}
|
||||||
@@ -182,6 +187,7 @@ export function MaskConfig(props: {
|
|||||||
subTitle={Locale.Mask.Config.Sync.SubTitle}
|
subTitle={Locale.Mask.Config.Sync.SubTitle}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
aria-label={Locale.Mask.Config.Sync.Title}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={props.mask.syncGlobalConfig}
|
checked={props.mask.syncGlobalConfig}
|
||||||
onChange={async (e) => {
|
onChange={async (e) => {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ export function ModelConfigList(props: {
|
|||||||
<>
|
<>
|
||||||
<ListItem title={Locale.Settings.Model}>
|
<ListItem title={Locale.Settings.Model}>
|
||||||
<Select
|
<Select
|
||||||
|
aria-label={Locale.Settings.Model}
|
||||||
value={value}
|
value={value}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const [model, providerName] = e.currentTarget.value.split("@");
|
const [model, providerName] = e.currentTarget.value.split("@");
|
||||||
@@ -40,6 +41,7 @@ export function ModelConfigList(props: {
|
|||||||
subTitle={Locale.Settings.Temperature.SubTitle}
|
subTitle={Locale.Settings.Temperature.SubTitle}
|
||||||
>
|
>
|
||||||
<InputRange
|
<InputRange
|
||||||
|
aria={Locale.Settings.Temperature.Title}
|
||||||
value={props.modelConfig.temperature?.toFixed(1)}
|
value={props.modelConfig.temperature?.toFixed(1)}
|
||||||
min="0"
|
min="0"
|
||||||
max="1" // lets limit it to 0-1
|
max="1" // lets limit it to 0-1
|
||||||
@@ -59,6 +61,7 @@ export function ModelConfigList(props: {
|
|||||||
subTitle={Locale.Settings.TopP.SubTitle}
|
subTitle={Locale.Settings.TopP.SubTitle}
|
||||||
>
|
>
|
||||||
<InputRange
|
<InputRange
|
||||||
|
aria={Locale.Settings.TopP.Title}
|
||||||
value={(props.modelConfig.top_p ?? 1).toFixed(1)}
|
value={(props.modelConfig.top_p ?? 1).toFixed(1)}
|
||||||
min="0"
|
min="0"
|
||||||
max="1"
|
max="1"
|
||||||
@@ -78,6 +81,7 @@ export function ModelConfigList(props: {
|
|||||||
subTitle={Locale.Settings.MaxTokens.SubTitle}
|
subTitle={Locale.Settings.MaxTokens.SubTitle}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
aria-label={Locale.Settings.MaxTokens.Title}
|
||||||
type="number"
|
type="number"
|
||||||
min={1024}
|
min={1024}
|
||||||
max={512000}
|
max={512000}
|
||||||
@@ -100,6 +104,7 @@ export function ModelConfigList(props: {
|
|||||||
subTitle={Locale.Settings.PresencePenalty.SubTitle}
|
subTitle={Locale.Settings.PresencePenalty.SubTitle}
|
||||||
>
|
>
|
||||||
<InputRange
|
<InputRange
|
||||||
|
aria={Locale.Settings.PresencePenalty.Title}
|
||||||
value={props.modelConfig.presence_penalty?.toFixed(1)}
|
value={props.modelConfig.presence_penalty?.toFixed(1)}
|
||||||
min="-2"
|
min="-2"
|
||||||
max="2"
|
max="2"
|
||||||
@@ -121,6 +126,7 @@ export function ModelConfigList(props: {
|
|||||||
subTitle={Locale.Settings.FrequencyPenalty.SubTitle}
|
subTitle={Locale.Settings.FrequencyPenalty.SubTitle}
|
||||||
>
|
>
|
||||||
<InputRange
|
<InputRange
|
||||||
|
aria={Locale.Settings.FrequencyPenalty.Title}
|
||||||
value={props.modelConfig.frequency_penalty?.toFixed(1)}
|
value={props.modelConfig.frequency_penalty?.toFixed(1)}
|
||||||
min="-2"
|
min="-2"
|
||||||
max="2"
|
max="2"
|
||||||
@@ -142,6 +148,7 @@ export function ModelConfigList(props: {
|
|||||||
subTitle={Locale.Settings.InjectSystemPrompts.SubTitle}
|
subTitle={Locale.Settings.InjectSystemPrompts.SubTitle}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
aria-label={Locale.Settings.InjectSystemPrompts.Title}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={props.modelConfig.enableInjectSystemPrompts}
|
checked={props.modelConfig.enableInjectSystemPrompts}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
@@ -159,6 +166,7 @@ export function ModelConfigList(props: {
|
|||||||
subTitle={Locale.Settings.InputTemplate.SubTitle}
|
subTitle={Locale.Settings.InputTemplate.SubTitle}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
aria-label={Locale.Settings.InputTemplate.Title}
|
||||||
type="text"
|
type="text"
|
||||||
value={props.modelConfig.template}
|
value={props.modelConfig.template}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
@@ -175,6 +183,7 @@ export function ModelConfigList(props: {
|
|||||||
subTitle={Locale.Settings.HistoryCount.SubTitle}
|
subTitle={Locale.Settings.HistoryCount.SubTitle}
|
||||||
>
|
>
|
||||||
<InputRange
|
<InputRange
|
||||||
|
aria={Locale.Settings.HistoryCount.Title}
|
||||||
title={props.modelConfig.historyMessageCount.toString()}
|
title={props.modelConfig.historyMessageCount.toString()}
|
||||||
value={props.modelConfig.historyMessageCount}
|
value={props.modelConfig.historyMessageCount}
|
||||||
min="0"
|
min="0"
|
||||||
@@ -193,6 +202,7 @@ export function ModelConfigList(props: {
|
|||||||
subTitle={Locale.Settings.CompressThreshold.SubTitle}
|
subTitle={Locale.Settings.CompressThreshold.SubTitle}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
aria-label={Locale.Settings.CompressThreshold.Title}
|
||||||
type="number"
|
type="number"
|
||||||
min={500}
|
min={500}
|
||||||
max={4000}
|
max={4000}
|
||||||
@@ -208,6 +218,7 @@ export function ModelConfigList(props: {
|
|||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem title={Locale.Memory.Title} subTitle={Locale.Memory.Send}>
|
<ListItem title={Locale.Memory.Title} subTitle={Locale.Memory.Send}>
|
||||||
<input
|
<input
|
||||||
|
aria-label={Locale.Memory.Title}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={props.modelConfig.sendMemory}
|
checked={props.modelConfig.sendMemory}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
|
|||||||
@@ -192,6 +192,7 @@ export function ControlParam(props: {
|
|||||||
required={item.required}
|
required={item.required}
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
|
aria-label={item.name}
|
||||||
value={props.data[item.value]}
|
value={props.data[item.value]}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
props.onChange(item.value, e.currentTarget.value);
|
props.onChange(item.value, e.currentTarget.value);
|
||||||
@@ -216,6 +217,7 @@ export function ControlParam(props: {
|
|||||||
required={item.required}
|
required={item.required}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
aria-label={item.name}
|
||||||
type="number"
|
type="number"
|
||||||
min={item.min}
|
min={item.min}
|
||||||
max={item.max}
|
max={item.max}
|
||||||
@@ -235,6 +237,7 @@ export function ControlParam(props: {
|
|||||||
required={item.required}
|
required={item.required}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
aria-label={item.name}
|
||||||
type="text"
|
type="text"
|
||||||
value={props.data[item.value]}
|
value={props.data[item.value]}
|
||||||
style={{ maxWidth: "100%", width: "100%" }}
|
style={{ maxWidth: "100%", width: "100%" }}
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ export function Sd() {
|
|||||||
{showMaxIcon && (
|
{showMaxIcon && (
|
||||||
<div className="window-action-button">
|
<div className="window-action-button">
|
||||||
<IconButton
|
<IconButton
|
||||||
|
aria={Locale.Chat.Actions.FullScreen}
|
||||||
icon={config.tightBorder ? <MinIcon /> : <MaxIcon />}
|
icon={config.tightBorder ? <MinIcon /> : <MaxIcon />}
|
||||||
bordered
|
bordered
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|||||||
@@ -246,6 +246,7 @@ function DangerItems() {
|
|||||||
subTitle={Locale.Settings.Danger.Reset.SubTitle}
|
subTitle={Locale.Settings.Danger.Reset.SubTitle}
|
||||||
>
|
>
|
||||||
<IconButton
|
<IconButton
|
||||||
|
aria={Locale.Settings.Danger.Reset.Title}
|
||||||
text={Locale.Settings.Danger.Reset.Action}
|
text={Locale.Settings.Danger.Reset.Action}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
if (await showConfirm(Locale.Settings.Danger.Reset.Confirm)) {
|
if (await showConfirm(Locale.Settings.Danger.Reset.Confirm)) {
|
||||||
@@ -260,6 +261,7 @@ function DangerItems() {
|
|||||||
subTitle={Locale.Settings.Danger.Clear.SubTitle}
|
subTitle={Locale.Settings.Danger.Clear.SubTitle}
|
||||||
>
|
>
|
||||||
<IconButton
|
<IconButton
|
||||||
|
aria={Locale.Settings.Danger.Clear.Title}
|
||||||
text={Locale.Settings.Danger.Clear.Action}
|
text={Locale.Settings.Danger.Clear.Action}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
if (await showConfirm(Locale.Settings.Danger.Clear.Confirm)) {
|
if (await showConfirm(Locale.Settings.Danger.Clear.Confirm)) {
|
||||||
@@ -513,6 +515,7 @@ function SyncItems() {
|
|||||||
>
|
>
|
||||||
<div style={{ display: "flex" }}>
|
<div style={{ display: "flex" }}>
|
||||||
<IconButton
|
<IconButton
|
||||||
|
aria={Locale.Settings.Sync.CloudState + Locale.UI.Config}
|
||||||
icon={<ConfigIcon />}
|
icon={<ConfigIcon />}
|
||||||
text={Locale.UI.Config}
|
text={Locale.UI.Config}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -543,6 +546,7 @@ function SyncItems() {
|
|||||||
>
|
>
|
||||||
<div style={{ display: "flex" }}>
|
<div style={{ display: "flex" }}>
|
||||||
<IconButton
|
<IconButton
|
||||||
|
aria={Locale.Settings.Sync.LocalState + Locale.UI.Export}
|
||||||
icon={<UploadIcon />}
|
icon={<UploadIcon />}
|
||||||
text={Locale.UI.Export}
|
text={Locale.UI.Export}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -550,6 +554,7 @@ function SyncItems() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<IconButton
|
<IconButton
|
||||||
|
aria={Locale.Settings.Sync.LocalState + Locale.UI.Import}
|
||||||
icon={<DownloadIcon />}
|
icon={<DownloadIcon />}
|
||||||
text={Locale.UI.Import}
|
text={Locale.UI.Import}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -687,6 +692,7 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.Access.CustomEndpoint.SubTitle}
|
subTitle={Locale.Settings.Access.CustomEndpoint.SubTitle}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
aria-label={Locale.Settings.Access.CustomEndpoint.Title}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={accessStore.useCustomConfig}
|
checked={accessStore.useCustomConfig}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
@@ -706,6 +712,7 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.Access.OpenAI.Endpoint.SubTitle}
|
subTitle={Locale.Settings.Access.OpenAI.Endpoint.SubTitle}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
aria-label={Locale.Settings.Access.OpenAI.Endpoint.Title}
|
||||||
type="text"
|
type="text"
|
||||||
value={accessStore.openaiUrl}
|
value={accessStore.openaiUrl}
|
||||||
placeholder={OPENAI_BASE_URL}
|
placeholder={OPENAI_BASE_URL}
|
||||||
@@ -721,6 +728,8 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.Access.OpenAI.ApiKey.SubTitle}
|
subTitle={Locale.Settings.Access.OpenAI.ApiKey.SubTitle}
|
||||||
>
|
>
|
||||||
<PasswordInput
|
<PasswordInput
|
||||||
|
aria={Locale.Settings.ShowPassword}
|
||||||
|
aria-label={Locale.Settings.Access.OpenAI.ApiKey.Title}
|
||||||
value={accessStore.openaiApiKey}
|
value={accessStore.openaiApiKey}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={Locale.Settings.Access.OpenAI.ApiKey.Placeholder}
|
placeholder={Locale.Settings.Access.OpenAI.ApiKey.Placeholder}
|
||||||
@@ -744,6 +753,7 @@ export function Settings() {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
aria-label={Locale.Settings.Access.Azure.Endpoint.Title}
|
||||||
type="text"
|
type="text"
|
||||||
value={accessStore.azureUrl}
|
value={accessStore.azureUrl}
|
||||||
placeholder={Azure.ExampleEndpoint}
|
placeholder={Azure.ExampleEndpoint}
|
||||||
@@ -759,6 +769,7 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.Access.Azure.ApiKey.SubTitle}
|
subTitle={Locale.Settings.Access.Azure.ApiKey.SubTitle}
|
||||||
>
|
>
|
||||||
<PasswordInput
|
<PasswordInput
|
||||||
|
aria-label={Locale.Settings.Access.Azure.ApiKey.Title}
|
||||||
value={accessStore.azureApiKey}
|
value={accessStore.azureApiKey}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={Locale.Settings.Access.Azure.ApiKey.Placeholder}
|
placeholder={Locale.Settings.Access.Azure.ApiKey.Placeholder}
|
||||||
@@ -774,6 +785,7 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.Access.Azure.ApiVerion.SubTitle}
|
subTitle={Locale.Settings.Access.Azure.ApiVerion.SubTitle}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
aria-label={Locale.Settings.Access.Azure.ApiVerion.Title}
|
||||||
type="text"
|
type="text"
|
||||||
value={accessStore.azureApiVersion}
|
value={accessStore.azureApiVersion}
|
||||||
placeholder="2023-08-01-preview"
|
placeholder="2023-08-01-preview"
|
||||||
@@ -798,6 +810,7 @@ export function Settings() {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
aria-label={Locale.Settings.Access.Google.Endpoint.Title}
|
||||||
type="text"
|
type="text"
|
||||||
value={accessStore.googleUrl}
|
value={accessStore.googleUrl}
|
||||||
placeholder={Google.ExampleEndpoint}
|
placeholder={Google.ExampleEndpoint}
|
||||||
@@ -813,6 +826,7 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.Access.Google.ApiKey.SubTitle}
|
subTitle={Locale.Settings.Access.Google.ApiKey.SubTitle}
|
||||||
>
|
>
|
||||||
<PasswordInput
|
<PasswordInput
|
||||||
|
aria-label={Locale.Settings.Access.Google.ApiKey.Title}
|
||||||
value={accessStore.googleApiKey}
|
value={accessStore.googleApiKey}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={Locale.Settings.Access.Google.ApiKey.Placeholder}
|
placeholder={Locale.Settings.Access.Google.ApiKey.Placeholder}
|
||||||
@@ -828,6 +842,7 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.Access.Google.ApiVersion.SubTitle}
|
subTitle={Locale.Settings.Access.Google.ApiVersion.SubTitle}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
aria-label={Locale.Settings.Access.Google.ApiVersion.Title}
|
||||||
type="text"
|
type="text"
|
||||||
value={accessStore.googleApiVersion}
|
value={accessStore.googleApiVersion}
|
||||||
placeholder="2023-08-01-preview"
|
placeholder="2023-08-01-preview"
|
||||||
@@ -843,6 +858,7 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.Access.Google.GoogleSafetySettings.SubTitle}
|
subTitle={Locale.Settings.Access.Google.GoogleSafetySettings.SubTitle}
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
|
aria-label={Locale.Settings.Access.Google.GoogleSafetySettings.Title}
|
||||||
value={accessStore.googleSafetySettings}
|
value={accessStore.googleSafetySettings}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
accessStore.update(
|
accessStore.update(
|
||||||
@@ -873,6 +889,7 @@ export function Settings() {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
aria-label={Locale.Settings.Access.Anthropic.Endpoint.Title}
|
||||||
type="text"
|
type="text"
|
||||||
value={accessStore.anthropicUrl}
|
value={accessStore.anthropicUrl}
|
||||||
placeholder={Anthropic.ExampleEndpoint}
|
placeholder={Anthropic.ExampleEndpoint}
|
||||||
@@ -888,6 +905,7 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.Access.Anthropic.ApiKey.SubTitle}
|
subTitle={Locale.Settings.Access.Anthropic.ApiKey.SubTitle}
|
||||||
>
|
>
|
||||||
<PasswordInput
|
<PasswordInput
|
||||||
|
aria-label={Locale.Settings.Access.Anthropic.ApiKey.Title}
|
||||||
value={accessStore.anthropicApiKey}
|
value={accessStore.anthropicApiKey}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={Locale.Settings.Access.Anthropic.ApiKey.Placeholder}
|
placeholder={Locale.Settings.Access.Anthropic.ApiKey.Placeholder}
|
||||||
@@ -903,6 +921,7 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.Access.Anthropic.ApiVerion.SubTitle}
|
subTitle={Locale.Settings.Access.Anthropic.ApiVerion.SubTitle}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
aria-label={Locale.Settings.Access.Anthropic.ApiVerion.Title}
|
||||||
type="text"
|
type="text"
|
||||||
value={accessStore.anthropicApiVersion}
|
value={accessStore.anthropicApiVersion}
|
||||||
placeholder={Anthropic.Vision}
|
placeholder={Anthropic.Vision}
|
||||||
@@ -924,6 +943,7 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.Access.Baidu.Endpoint.SubTitle}
|
subTitle={Locale.Settings.Access.Baidu.Endpoint.SubTitle}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
aria-label={Locale.Settings.Access.Baidu.Endpoint.Title}
|
||||||
type="text"
|
type="text"
|
||||||
value={accessStore.baiduUrl}
|
value={accessStore.baiduUrl}
|
||||||
placeholder={Baidu.ExampleEndpoint}
|
placeholder={Baidu.ExampleEndpoint}
|
||||||
@@ -939,6 +959,7 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.Access.Baidu.ApiKey.SubTitle}
|
subTitle={Locale.Settings.Access.Baidu.ApiKey.SubTitle}
|
||||||
>
|
>
|
||||||
<PasswordInput
|
<PasswordInput
|
||||||
|
aria-label={Locale.Settings.Access.Baidu.ApiKey.Title}
|
||||||
value={accessStore.baiduApiKey}
|
value={accessStore.baiduApiKey}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={Locale.Settings.Access.Baidu.ApiKey.Placeholder}
|
placeholder={Locale.Settings.Access.Baidu.ApiKey.Placeholder}
|
||||||
@@ -954,6 +975,7 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.Access.Baidu.SecretKey.SubTitle}
|
subTitle={Locale.Settings.Access.Baidu.SecretKey.SubTitle}
|
||||||
>
|
>
|
||||||
<PasswordInput
|
<PasswordInput
|
||||||
|
aria-label={Locale.Settings.Access.Baidu.SecretKey.Title}
|
||||||
value={accessStore.baiduSecretKey}
|
value={accessStore.baiduSecretKey}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={Locale.Settings.Access.Baidu.SecretKey.Placeholder}
|
placeholder={Locale.Settings.Access.Baidu.SecretKey.Placeholder}
|
||||||
@@ -975,6 +997,7 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.Access.Tencent.Endpoint.SubTitle}
|
subTitle={Locale.Settings.Access.Tencent.Endpoint.SubTitle}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
aria-label={Locale.Settings.Access.Tencent.Endpoint.Title}
|
||||||
type="text"
|
type="text"
|
||||||
value={accessStore.tencentUrl}
|
value={accessStore.tencentUrl}
|
||||||
placeholder={Tencent.ExampleEndpoint}
|
placeholder={Tencent.ExampleEndpoint}
|
||||||
@@ -990,6 +1013,7 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.Access.Tencent.ApiKey.SubTitle}
|
subTitle={Locale.Settings.Access.Tencent.ApiKey.SubTitle}
|
||||||
>
|
>
|
||||||
<PasswordInput
|
<PasswordInput
|
||||||
|
aria-label={Locale.Settings.Access.Tencent.ApiKey.Title}
|
||||||
value={accessStore.tencentSecretId}
|
value={accessStore.tencentSecretId}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={Locale.Settings.Access.Tencent.ApiKey.Placeholder}
|
placeholder={Locale.Settings.Access.Tencent.ApiKey.Placeholder}
|
||||||
@@ -1005,6 +1029,7 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.Access.Tencent.SecretKey.SubTitle}
|
subTitle={Locale.Settings.Access.Tencent.SecretKey.SubTitle}
|
||||||
>
|
>
|
||||||
<PasswordInput
|
<PasswordInput
|
||||||
|
aria-label={Locale.Settings.Access.Tencent.SecretKey.Title}
|
||||||
value={accessStore.tencentSecretKey}
|
value={accessStore.tencentSecretKey}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={Locale.Settings.Access.Tencent.SecretKey.Placeholder}
|
placeholder={Locale.Settings.Access.Tencent.SecretKey.Placeholder}
|
||||||
@@ -1029,6 +1054,7 @@ export function Settings() {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
aria-label={Locale.Settings.Access.ByteDance.Endpoint.Title}
|
||||||
type="text"
|
type="text"
|
||||||
value={accessStore.bytedanceUrl}
|
value={accessStore.bytedanceUrl}
|
||||||
placeholder={ByteDance.ExampleEndpoint}
|
placeholder={ByteDance.ExampleEndpoint}
|
||||||
@@ -1044,6 +1070,7 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.Access.ByteDance.ApiKey.SubTitle}
|
subTitle={Locale.Settings.Access.ByteDance.ApiKey.SubTitle}
|
||||||
>
|
>
|
||||||
<PasswordInput
|
<PasswordInput
|
||||||
|
aria-label={Locale.Settings.Access.ByteDance.ApiKey.Title}
|
||||||
value={accessStore.bytedanceApiKey}
|
value={accessStore.bytedanceApiKey}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={Locale.Settings.Access.ByteDance.ApiKey.Placeholder}
|
placeholder={Locale.Settings.Access.ByteDance.ApiKey.Placeholder}
|
||||||
@@ -1068,6 +1095,7 @@ export function Settings() {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
aria-label={Locale.Settings.Access.Alibaba.Endpoint.Title}
|
||||||
type="text"
|
type="text"
|
||||||
value={accessStore.alibabaUrl}
|
value={accessStore.alibabaUrl}
|
||||||
placeholder={Alibaba.ExampleEndpoint}
|
placeholder={Alibaba.ExampleEndpoint}
|
||||||
@@ -1083,6 +1111,7 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.Access.Alibaba.ApiKey.SubTitle}
|
subTitle={Locale.Settings.Access.Alibaba.ApiKey.SubTitle}
|
||||||
>
|
>
|
||||||
<PasswordInput
|
<PasswordInput
|
||||||
|
aria-label={Locale.Settings.Access.Alibaba.ApiKey.Title}
|
||||||
value={accessStore.alibabaApiKey}
|
value={accessStore.alibabaApiKey}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={Locale.Settings.Access.Alibaba.ApiKey.Placeholder}
|
placeholder={Locale.Settings.Access.Alibaba.ApiKey.Placeholder}
|
||||||
@@ -1107,6 +1136,7 @@ export function Settings() {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
aria-label={Locale.Settings.Access.Moonshot.Endpoint.Title}
|
||||||
type="text"
|
type="text"
|
||||||
value={accessStore.moonshotUrl}
|
value={accessStore.moonshotUrl}
|
||||||
placeholder={Moonshot.ExampleEndpoint}
|
placeholder={Moonshot.ExampleEndpoint}
|
||||||
@@ -1122,6 +1152,7 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.Access.Moonshot.ApiKey.SubTitle}
|
subTitle={Locale.Settings.Access.Moonshot.ApiKey.SubTitle}
|
||||||
>
|
>
|
||||||
<PasswordInput
|
<PasswordInput
|
||||||
|
aria-label={Locale.Settings.Access.Moonshot.ApiKey.Title}
|
||||||
value={accessStore.moonshotApiKey}
|
value={accessStore.moonshotApiKey}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={Locale.Settings.Access.Moonshot.ApiKey.Placeholder}
|
placeholder={Locale.Settings.Access.Moonshot.ApiKey.Placeholder}
|
||||||
@@ -1146,6 +1177,7 @@ export function Settings() {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
aria-label={Locale.Settings.Access.Stability.Endpoint.Title}
|
||||||
type="text"
|
type="text"
|
||||||
value={accessStore.stabilityUrl}
|
value={accessStore.stabilityUrl}
|
||||||
placeholder={Stability.ExampleEndpoint}
|
placeholder={Stability.ExampleEndpoint}
|
||||||
@@ -1161,6 +1193,7 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.Access.Stability.ApiKey.SubTitle}
|
subTitle={Locale.Settings.Access.Stability.ApiKey.SubTitle}
|
||||||
>
|
>
|
||||||
<PasswordInput
|
<PasswordInput
|
||||||
|
aria-label={Locale.Settings.Access.Stability.ApiKey.Title}
|
||||||
value={accessStore.stabilityApiKey}
|
value={accessStore.stabilityApiKey}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={Locale.Settings.Access.Stability.ApiKey.Placeholder}
|
placeholder={Locale.Settings.Access.Stability.ApiKey.Placeholder}
|
||||||
@@ -1184,6 +1217,7 @@ export function Settings() {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
aria-label={Locale.Settings.Access.Iflytek.Endpoint.Title}
|
||||||
type="text"
|
type="text"
|
||||||
value={accessStore.iflytekUrl}
|
value={accessStore.iflytekUrl}
|
||||||
placeholder={Iflytek.ExampleEndpoint}
|
placeholder={Iflytek.ExampleEndpoint}
|
||||||
@@ -1199,6 +1233,7 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.Access.Iflytek.ApiKey.SubTitle}
|
subTitle={Locale.Settings.Access.Iflytek.ApiKey.SubTitle}
|
||||||
>
|
>
|
||||||
<PasswordInput
|
<PasswordInput
|
||||||
|
aria-label={Locale.Settings.Access.Iflytek.ApiKey.Title}
|
||||||
value={accessStore.iflytekApiKey}
|
value={accessStore.iflytekApiKey}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={Locale.Settings.Access.Iflytek.ApiKey.Placeholder}
|
placeholder={Locale.Settings.Access.Iflytek.ApiKey.Placeholder}
|
||||||
@@ -1215,6 +1250,7 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.Access.Iflytek.ApiSecret.SubTitle}
|
subTitle={Locale.Settings.Access.Iflytek.ApiSecret.SubTitle}
|
||||||
>
|
>
|
||||||
<PasswordInput
|
<PasswordInput
|
||||||
|
aria-label={Locale.Settings.Access.Iflytek.ApiSecret.Title}
|
||||||
value={accessStore.iflytekApiSecret}
|
value={accessStore.iflytekApiSecret}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={Locale.Settings.Access.Iflytek.ApiSecret.Placeholder}
|
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"></div>
|
||||||
<div className="window-action-button">
|
<div className="window-action-button">
|
||||||
<IconButton
|
<IconButton
|
||||||
|
aria={Locale.UI.Close}
|
||||||
icon={<CloseIcon />}
|
icon={<CloseIcon />}
|
||||||
onClick={() => navigate(Path.Home)}
|
onClick={() => navigate(Path.Home)}
|
||||||
bordered
|
bordered
|
||||||
@@ -1267,6 +1304,8 @@ export function Settings() {
|
|||||||
open={showEmojiPicker}
|
open={showEmojiPicker}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
aria-label={Locale.Settings.Avatar}
|
||||||
|
tabIndex={0}
|
||||||
className={styles.avatar}
|
className={styles.avatar}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setShowEmojiPicker(!showEmojiPicker);
|
setShowEmojiPicker(!showEmojiPicker);
|
||||||
@@ -1304,6 +1343,7 @@ export function Settings() {
|
|||||||
|
|
||||||
<ListItem title={Locale.Settings.SendKey}>
|
<ListItem title={Locale.Settings.SendKey}>
|
||||||
<Select
|
<Select
|
||||||
|
aria-label={Locale.Settings.SendKey}
|
||||||
value={config.submitKey}
|
value={config.submitKey}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
updateConfig(
|
updateConfig(
|
||||||
@@ -1322,6 +1362,7 @@ export function Settings() {
|
|||||||
|
|
||||||
<ListItem title={Locale.Settings.Theme}>
|
<ListItem title={Locale.Settings.Theme}>
|
||||||
<Select
|
<Select
|
||||||
|
aria-label={Locale.Settings.Theme}
|
||||||
value={config.theme}
|
value={config.theme}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
updateConfig(
|
updateConfig(
|
||||||
@@ -1339,6 +1380,7 @@ export function Settings() {
|
|||||||
|
|
||||||
<ListItem title={Locale.Settings.Lang.Name}>
|
<ListItem title={Locale.Settings.Lang.Name}>
|
||||||
<Select
|
<Select
|
||||||
|
aria-label={Locale.Settings.Lang.Name}
|
||||||
value={getLang()}
|
value={getLang()}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
changeLang(e.target.value as any);
|
changeLang(e.target.value as any);
|
||||||
@@ -1357,6 +1399,7 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.FontSize.SubTitle}
|
subTitle={Locale.Settings.FontSize.SubTitle}
|
||||||
>
|
>
|
||||||
<InputRange
|
<InputRange
|
||||||
|
aria={Locale.Settings.FontSize.Title}
|
||||||
title={`${config.fontSize ?? 14}px`}
|
title={`${config.fontSize ?? 14}px`}
|
||||||
value={config.fontSize}
|
value={config.fontSize}
|
||||||
min="12"
|
min="12"
|
||||||
@@ -1376,6 +1419,7 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.FontFamily.SubTitle}
|
subTitle={Locale.Settings.FontFamily.SubTitle}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
aria-label={Locale.Settings.FontFamily.Title}
|
||||||
type="text"
|
type="text"
|
||||||
value={config.fontFamily}
|
value={config.fontFamily}
|
||||||
placeholder={Locale.Settings.FontFamily.Placeholder}
|
placeholder={Locale.Settings.FontFamily.Placeholder}
|
||||||
@@ -1392,6 +1436,7 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.AutoGenerateTitle.SubTitle}
|
subTitle={Locale.Settings.AutoGenerateTitle.SubTitle}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
aria-label={Locale.Settings.AutoGenerateTitle.Title}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={config.enableAutoGenerateTitle}
|
checked={config.enableAutoGenerateTitle}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
@@ -1408,6 +1453,7 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.SendPreviewBubble.SubTitle}
|
subTitle={Locale.Settings.SendPreviewBubble.SubTitle}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
aria-label={Locale.Settings.SendPreviewBubble.Title}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={config.sendPreviewBubble}
|
checked={config.sendPreviewBubble}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
@@ -1428,6 +1474,7 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.Mask.Splash.SubTitle}
|
subTitle={Locale.Settings.Mask.Splash.SubTitle}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
aria-label={Locale.Settings.Mask.Splash.Title}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={!config.dontShowMaskSplashScreen}
|
checked={!config.dontShowMaskSplashScreen}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
@@ -1445,6 +1492,7 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.Mask.Builtin.SubTitle}
|
subTitle={Locale.Settings.Mask.Builtin.SubTitle}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
aria-label={Locale.Settings.Mask.Builtin.Title}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={config.hideBuiltinMasks}
|
checked={config.hideBuiltinMasks}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
@@ -1463,6 +1511,7 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.Prompt.Disable.SubTitle}
|
subTitle={Locale.Settings.Prompt.Disable.SubTitle}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
aria-label={Locale.Settings.Prompt.Disable.Title}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={config.disablePromptHint}
|
checked={config.disablePromptHint}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
@@ -1482,6 +1531,7 @@ export function Settings() {
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<IconButton
|
<IconButton
|
||||||
|
aria={Locale.Settings.Prompt.List + Locale.Settings.Prompt.Edit}
|
||||||
icon={<EditIcon />}
|
icon={<EditIcon />}
|
||||||
text={Locale.Settings.Prompt.Edit}
|
text={Locale.Settings.Prompt.Edit}
|
||||||
onClick={() => setShowPromptModal(true)}
|
onClick={() => setShowPromptModal(true)}
|
||||||
@@ -1503,6 +1553,7 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.Access.Provider.SubTitle}
|
subTitle={Locale.Settings.Access.Provider.SubTitle}
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
|
aria-label={Locale.Settings.Access.Provider.Title}
|
||||||
value={accessStore.provider}
|
value={accessStore.provider}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
accessStore.update(
|
accessStore.update(
|
||||||
@@ -1567,6 +1618,7 @@ export function Settings() {
|
|||||||
subTitle={Locale.Settings.Access.CustomModel.SubTitle}
|
subTitle={Locale.Settings.Access.CustomModel.SubTitle}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
aria-label={Locale.Settings.Access.CustomModel.Title}
|
||||||
type="text"
|
type="text"
|
||||||
value={config.customModels}
|
value={config.customModels}
|
||||||
placeholder="model1,model2,model3"
|
placeholder="model1,model2,model3"
|
||||||
|
|||||||
@@ -297,12 +297,20 @@ export function SideBar(props: { className?: string }) {
|
|||||||
</div>
|
</div>
|
||||||
<div className={styles["sidebar-action"]}>
|
<div className={styles["sidebar-action"]}>
|
||||||
<Link to={Path.Settings}>
|
<Link to={Path.Settings}>
|
||||||
<IconButton icon={<SettingsIcon />} shadow />
|
<IconButton
|
||||||
|
aria={Locale.Settings.Title}
|
||||||
|
icon={<SettingsIcon />}
|
||||||
|
shadow
|
||||||
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles["sidebar-action"]}>
|
<div className={styles["sidebar-action"]}>
|
||||||
<a href={REPO_URL} target="_blank" rel="noopener noreferrer">
|
<a href={REPO_URL} target="_blank" rel="noopener noreferrer">
|
||||||
<IconButton icon={<GithubIcon />} shadow />
|
<IconButton
|
||||||
|
aria={Locale.Export.MessageFromChatGPT}
|
||||||
|
icon={<GithubIcon />}
|
||||||
|
shadow
|
||||||
|
/>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</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);
|
const [visible, setVisible] = useState(false);
|
||||||
|
|
||||||
function changeVisibility() {
|
function changeVisibility() {
|
||||||
setVisible(!visible);
|
setVisible(!visible);
|
||||||
}
|
}
|
||||||
@@ -275,6 +276,7 @@ export function PasswordInput(props: HTMLProps<HTMLInputElement>) {
|
|||||||
return (
|
return (
|
||||||
<div className={"password-input-container"}>
|
<div className={"password-input-container"}>
|
||||||
<IconButton
|
<IconButton
|
||||||
|
aria={props.aria}
|
||||||
icon={visible ? <EyeIcon /> : <EyeOffIcon />}
|
icon={visible ? <EyeIcon /> : <EyeOffIcon />}
|
||||||
onClick={changeVisibility}
|
onClick={changeVisibility}
|
||||||
className={"password-eye"}
|
className={"password-eye"}
|
||||||
|
|||||||
@@ -119,10 +119,16 @@ export const getServerSideConfig = () => {
|
|||||||
|
|
||||||
if (disableGPT4) {
|
if (disableGPT4) {
|
||||||
if (customModels) customModels += ",";
|
if (customModels) customModels += ",";
|
||||||
customModels += DEFAULT_MODELS.filter((m) => m.name.startsWith("gpt-4"))
|
customModels += DEFAULT_MODELS.filter(
|
||||||
|
(m) => m.name.startsWith("gpt-4") && !m.name.startsWith("gpt-4o-mini"),
|
||||||
|
)
|
||||||
.map((m) => "-" + m.name)
|
.map((m) => "-" + m.name)
|
||||||
.join(",");
|
.join(",");
|
||||||
if (defaultModel.startsWith("gpt-4")) defaultModel = "";
|
if (
|
||||||
|
defaultModel.startsWith("gpt-4") &&
|
||||||
|
!defaultModel.startsWith("gpt-4o-mini")
|
||||||
|
)
|
||||||
|
defaultModel = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
const isStability = !!process.env.STABILITY_API_KEY;
|
const isStability = !!process.env.STABILITY_API_KEY;
|
||||||
|
|||||||
@@ -243,6 +243,7 @@ export const KnowledgeCutOffDate: Record<string, string> = {
|
|||||||
"gpt-4-turbo-preview": "2023-12",
|
"gpt-4-turbo-preview": "2023-12",
|
||||||
"gpt-4o": "2023-10",
|
"gpt-4o": "2023-10",
|
||||||
"gpt-4o-2024-05-13": "2023-10",
|
"gpt-4o-2024-05-13": "2023-10",
|
||||||
|
"gpt-4o-2024-08-06": "2023-10",
|
||||||
"gpt-4o-mini": "2023-10",
|
"gpt-4o-mini": "2023-10",
|
||||||
"gpt-4o-mini-2024-07-18": "2023-10",
|
"gpt-4o-mini-2024-07-18": "2023-10",
|
||||||
"gpt-4-vision-preview": "2023-04",
|
"gpt-4-vision-preview": "2023-04",
|
||||||
@@ -264,6 +265,7 @@ const openaiModels = [
|
|||||||
"gpt-4-turbo-preview",
|
"gpt-4-turbo-preview",
|
||||||
"gpt-4o",
|
"gpt-4o",
|
||||||
"gpt-4o-2024-05-13",
|
"gpt-4o-2024-05-13",
|
||||||
|
"gpt-4o-2024-08-06",
|
||||||
"gpt-4o-mini",
|
"gpt-4o-mini",
|
||||||
"gpt-4o-mini-2024-07-18",
|
"gpt-4o-mini-2024-07-18",
|
||||||
"gpt-4-vision-preview",
|
"gpt-4-vision-preview",
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ const cn = {
|
|||||||
PinToastAction: "查看",
|
PinToastAction: "查看",
|
||||||
Delete: "删除",
|
Delete: "删除",
|
||||||
Edit: "编辑",
|
Edit: "编辑",
|
||||||
|
FullScreen: "全屏",
|
||||||
},
|
},
|
||||||
Commands: {
|
Commands: {
|
||||||
new: "新建聊天",
|
new: "新建聊天",
|
||||||
@@ -132,6 +133,7 @@ const cn = {
|
|||||||
Settings: {
|
Settings: {
|
||||||
Title: "设置",
|
Title: "设置",
|
||||||
SubTitle: "所有设置选项",
|
SubTitle: "所有设置选项",
|
||||||
|
ShowPassword: "显示密码",
|
||||||
|
|
||||||
Danger: {
|
Danger: {
|
||||||
Reset: {
|
Reset: {
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ const en: LocaleType = {
|
|||||||
PinToastAction: "View",
|
PinToastAction: "View",
|
||||||
Delete: "Delete",
|
Delete: "Delete",
|
||||||
Edit: "Edit",
|
Edit: "Edit",
|
||||||
|
FullScreen: "FullScreen",
|
||||||
},
|
},
|
||||||
Commands: {
|
Commands: {
|
||||||
new: "Start a new chat",
|
new: "Start a new chat",
|
||||||
@@ -135,6 +136,7 @@ const en: LocaleType = {
|
|||||||
Settings: {
|
Settings: {
|
||||||
Title: "Settings",
|
Title: "Settings",
|
||||||
SubTitle: "All Settings",
|
SubTitle: "All Settings",
|
||||||
|
ShowPassword: "ShowPassword",
|
||||||
Danger: {
|
Danger: {
|
||||||
Reset: {
|
Reset: {
|
||||||
Title: "Reset All Settings",
|
Title: "Reset All Settings",
|
||||||
|
|||||||
@@ -145,15 +145,13 @@ export function isFirefox() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function selectOrCopy(el: HTMLElement, content: string) {
|
export function isNotSelectRange() {
|
||||||
const currentSelection = window.getSelection();
|
const currentSelection = window.getSelection();
|
||||||
|
|
||||||
if (currentSelection?.type === "Range") {
|
if (currentSelection?.type === "Range") {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
copyToClipboard(content);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user