fix: #2308 improve chat actions

This commit is contained in:
Yidadaa 2023-07-09 16:15:58 +08:00
parent 3432d4df29
commit ca295588c4
6 changed files with 112 additions and 115 deletions

View File

@ -240,24 +240,39 @@
&:last-child { &:last-child {
animation: slide-in ease 0.3s; animation: slide-in ease 0.3s;
} }
&:hover {
.chat-message-actions {
opacity: 1;
transform: translateY(0px);
max-width: 100%;
height: 40px;
}
.chat-message-action-date {
opacity: 0.2;
}
}
} }
.chat-message-user { .chat-message-user {
display: flex; display: flex;
flex-direction: row-reverse; flex-direction: row-reverse;
.chat-message-header {
flex-direction: row-reverse;
}
}
.chat-message-header {
margin-top: 20px;
display: flex;
align-items: center;
.chat-message-actions {
display: flex;
box-sizing: border-box;
font-size: 12px;
align-items: flex-end;
justify-content: space-between;
transition: all ease 0.3s;
transform: scale(0.9) translateY(5px);
margin: 0 10px;
opacity: 0;
pointer-events: none;
.chat-input-actions {
display: flex;
flex-wrap: nowrap;
}
}
} }
.chat-message-container { .chat-message-container {
@ -270,6 +285,12 @@
.chat-message-edit { .chat-message-edit {
opacity: 0.9; opacity: 0.9;
} }
.chat-message-actions {
opacity: 1;
pointer-events: all;
transform: scale(1) translateY(0);
}
} }
} }
@ -278,7 +299,6 @@
} }
.chat-message-avatar { .chat-message-avatar {
margin-top: 20px;
position: relative; position: relative;
.chat-message-edit { .chat-message-edit {
@ -318,27 +338,6 @@
border: var(--border-in-light); border: var(--border-in-light);
position: relative; position: relative;
transition: all ease 0.3s; transition: all ease 0.3s;
.chat-message-actions {
display: flex;
box-sizing: border-box;
font-size: 12px;
align-items: flex-end;
justify-content: space-between;
transition: all ease 0.3s 0.15s;
transform: translateX(-5px) scale(0.9) translateY(30px);
opacity: 0;
height: 0;
max-width: 0;
position: absolute;
left: 0;
z-index: 2;
.chat-input-actions {
display: flex;
flex-wrap: nowrap;
}
}
} }
.chat-message-action-date { .chat-message-action-date {

View File

@ -708,27 +708,26 @@ export function Chat() {
let lastUserMessageIndex: number | null = null; let lastUserMessageIndex: number | null = null;
for (let i = 0; i < session.messages.length; i += 1) { for (let i = 0; i < session.messages.length; i += 1) {
const message = session.messages[i]; const message = session.messages[i];
if (message.id === messageId) {
break;
}
if (message.role === "user") { if (message.role === "user") {
lastUserMessageIndex = i; lastUserMessageIndex = i;
} }
if (message.id === messageId) {
break;
}
} }
return lastUserMessageIndex; return lastUserMessageIndex;
}; };
const deleteMessage = (userIndex: number) => { const deleteMessage = (msgId?: number) => {
chatStore.updateCurrentSession((session) => chatStore.updateCurrentSession(
session.messages.splice(userIndex, 2), (session) =>
(session.messages = session.messages.filter((m) => m.id !== msgId)),
); );
}; };
const onDelete = (botMessageId: number) => { const onDelete = (msgId: number) => {
const userIndex = findLastUserIndex(botMessageId); deleteMessage(msgId);
if (userIndex === null) return;
deleteMessage(userIndex);
}; };
const onResend = (botMessageId: number) => { const onResend = (botMessageId: number) => {
@ -737,20 +736,16 @@ export function Chat() {
if (userIndex === null) return; if (userIndex === null) return;
setIsLoading(true); setIsLoading(true);
const content = session.messages[userIndex].content; const userMsg = session.messages[userIndex];
deleteMessage(userIndex); deleteMessage(userMsg.id);
chatStore.onUserInput(content).then(() => setIsLoading(false)); deleteMessage(botMessageId);
chatStore.onUserInput(userMsg.content).then(() => setIsLoading(false));
inputRef.current?.focus(); inputRef.current?.focus();
}; };
const onPinMessage = (botMessage: ChatMessage) => { const onPinMessage = (message: ChatMessage) => {
if (!botMessage.id) return;
const userMessageIndex = findLastUserIndex(botMessage.id);
if (userMessageIndex === null) return;
const userMessage = session.messages[userMessageIndex];
chatStore.updateCurrentSession((session) => chatStore.updateCurrentSession((session) =>
session.mask.context.push(userMessage, botMessage), session.mask.context.push(message),
); );
showToast(Locale.Chat.Actions.PinToastContent, { showToast(Locale.Chat.Actions.PinToastContent, {
@ -923,11 +918,12 @@ export function Chat() {
> >
{messages.map((message, i) => { {messages.map((message, i) => {
const isUser = message.role === "user"; const isUser = message.role === "user";
const showActions = // const showActions =
!isUser && // !isUser &&
i > 0 && // i > 0 &&
!(message.preview || message.content.length === 0) && // !(message.preview || message.content.length === 0) &&
i >= context.length; // do not show actions for context prompts // i >= context.length; // do not show actions for context prompts
const showActions = true;
const showTyping = message.preview || message.streaming; const showTyping = message.preview || message.streaming;
const shouldShowClearContextDivider = i === clearContextIndex - 1; const shouldShowClearContextDivider = i === clearContextIndex - 1;
@ -941,6 +937,7 @@ export function Chat() {
} }
> >
<div className={styles["chat-message-container"]}> <div className={styles["chat-message-container"]}>
<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
@ -968,37 +965,10 @@ export function Chat() {
<MaskAvatar mask={session.mask} /> <MaskAvatar mask={session.mask} />
)} )}
</div> </div>
{showTyping && (
<div className={styles["chat-message-status"]}>
{Locale.Chat.Typing}
</div>
)}
<div className={styles["chat-message-item"]}>
<Markdown
content={message.content}
loading={
(message.preview || message.content.length === 0) &&
!isUser
}
onContextMenu={(e) => onRightClick(e, message)}
onDoubleClickCapture={() => {
if (!isMobileScreen) return;
setUserInput(message.content);
}}
fontSize={fontSize}
parentRef={scrollRef}
defaultShow={i >= messages.length - 10}
/>
{showActions && ( {showActions && (
<div className={styles["chat-message-actions"]}> <div className={styles["chat-message-actions"]}>
<div <div className={styles["chat-input-actions"]}>
className={styles["chat-input-actions"]}
style={{
marginTop: 10,
marginBottom: 0,
}}
>
{message.streaming ? ( {message.streaming ? (
<ChatAction <ChatAction
text={Locale.Chat.Actions.Stop} text={Locale.Chat.Actions.Stop}
@ -1035,6 +1005,28 @@ export function Chat() {
</div> </div>
)} )}
</div> </div>
{showTyping && (
<div className={styles["chat-message-status"]}>
{Locale.Chat.Typing}
</div>
)}
<div className={styles["chat-message-item"]}>
<Markdown
content={message.content}
loading={
(message.preview || message.content.length === 0) &&
!isUser
}
onContextMenu={(e) => onRightClick(e, message)}
onDoubleClickCapture={() => {
if (!isMobileScreen) return;
setUserInput(message.content);
}}
fontSize={fontSize}
parentRef={scrollRef}
defaultShow={i >= messages.length - 10}
/>
</div>
{showActions && ( {showActions && (
<div className={styles["chat-message-action-date"]}> <div className={styles["chat-message-action-date"]}>

View File

@ -26,7 +26,7 @@ const cn = {
Stop: "停止", Stop: "停止",
Retry: "重试", Retry: "重试",
Pin: "固定", Pin: "固定",
PinToastContent: "已将 2 条对话固定至预设提示词", PinToastContent: "已将 1 条对话固定至预设提示词",
PinToastAction: "查看", PinToastAction: "查看",
Delete: "删除", Delete: "删除",
Edit: "编辑", Edit: "编辑",

View File

@ -28,7 +28,7 @@ const en: LocaleType = {
Stop: "Stop", Stop: "Stop",
Retry: "Retry", Retry: "Retry",
Pin: "Pin", Pin: "Pin",
PinToastContent: "Pinned 2 messages to contextual prompts", PinToastContent: "Pinned 1 messages to contextual prompts",
PinToastAction: "View", PinToastAction: "View",
Delete: "Delete", Delete: "Delete",
Edit: "Edit", Edit: "Edit",

View File

@ -24,6 +24,7 @@
"fuse.js": "^6.6.2", "fuse.js": "^6.6.2",
"html-to-image": "^1.11.11", "html-to-image": "^1.11.11",
"mermaid": "^10.2.3", "mermaid": "^10.2.3",
"nanoid": "^4.0.2",
"next": "^13.4.6", "next": "^13.4.6",
"node-fetch": "^3.3.1", "node-fetch": "^3.3.1",
"react": "^18.2.0", "react": "^18.2.0",

View File

@ -4639,6 +4639,11 @@ nanoid@^3.3.4:
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c"
integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==
nanoid@^4.0.2:
version "4.0.2"
resolved "https://registry.npmmirror.com/nanoid/-/nanoid-4.0.2.tgz#140b3c5003959adbebf521c170f282c5e7f9fb9e"
integrity sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==
natural-compare@^1.4.0: natural-compare@^1.4.0:
version "1.4.0" version "1.4.0"
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"