feat: add save and send functionality for user message

Adds a "Save" button to the edit message form in Playground, allowing users to save changes without immediately submitting them. This also introduces a new `isSend` flag to the `onEditFormSubmit` prop, enabling developers to control whether a message should be sent immediately or saved for later submission. This enhances flexibility and user control during the message editing process.
This commit is contained in:
n4ze3m 2024-11-03 23:38:41 +05:30
parent 31ca246407
commit 65ba2ff898
6 changed files with 53 additions and 44 deletions

View File

@ -8,20 +8,8 @@ import rehypeKatex from "rehype-katex"
import "property-information"
import React from "react"
import { CodeBlock } from "./CodeBlock"
export const preprocessLaTeX = (content: string) => {
// Replace block-level LaTeX delimiters \[ \] with $$ $$
import { preprocessLaTeX } from "@/utils/latex"
const blockProcessedContent = content.replace(
/\\\[(.*?)\\\]/gs,
(_, equation) => `$$${equation}$$`
)
// Replace inline LaTeX delimiters \( \) with $ $
const inlineProcessedContent = blockProcessedContent.replace(
/\\\((.*?)\\\)/gs,
(_, equation) => `$${equation}$`
)
return inlineProcessedContent
}
function Markdown({
message,
className = "prose break-words dark:prose-invert prose-p:leading-relaxed prose-pre:p-0 dark:prose-dark"

View File

@ -5,7 +5,7 @@ import useDynamicTextareaSize from "~/hooks/useDynamicTextareaSize"
type Props = {
value: string
onSumbit: (value: string) => void
onSumbit: (value: string, isSend: boolean) => void
onClose: () => void
isBot: boolean
}
@ -31,7 +31,7 @@ export const EditMessageForm = (props: Props) => {
onSubmit={form.onSubmit((data) => {
if (isComposing) return
props.onClose()
props.onSumbit(data.message)
props.onSumbit(data.message, true)
})}
className="flex flex-col gap-2">
<textarea
@ -46,19 +46,39 @@ export const EditMessageForm = (props: Props) => {
ref={textareaRef}
className="w-full bg-transparent focus-within:outline-none focus:ring-0 focus-visible:ring-0 ring-0 dark:ring-0 border-0 dark:text-gray-100"
/>
<div className="flex justify-center space-x-2 mt-2">
<div className="flex flex-wrap gap-2 mt-2">
<div
className={`w-full flex ${
!props.isBot ? "justify-between" : "justify-end"
}`}>
{!props.isBot && (
<button
type="button"
onClick={() => {
props.onSumbit(form.values.message, false)
props.onClose()
}}
aria-label={t("save")}
className="border border-gray-600 px-2 py-1.5 rounded-lg text-gray-700 dark:text-gray-300 focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-gray-500 hover:bg-gray-100 dark:hover:bg-gray-900 text-sm">
{t("save")}
</button>
)}
<div className="flex space-x-2">
<button
aria-label={t("save")}
className="bg-black px-2.5 py-2 rounded-lg text-white focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-gray-500 hover:bg-gray-900">
className="bg-black px-2 py-1.5 rounded-lg text-white focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-gray-500 hover:bg-gray-900 text-sm">
{props.isBot ? t("save") : t("saveAndSubmit")}
</button>
<button
onClick={props.onClose}
aria-label={t("cancel")}
className="border dark:border-gray-600 px-2.5 py-2 rounded-lg text-gray-700 dark:text-gray-300 focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-gray-500 hover:bg-gray-100 dark:hover:bg-gray-900">
className="border dark:border-gray-600 px-2 py-1.5 rounded-lg text-gray-700 dark:text-gray-300 focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-gray-500 hover:bg-gray-100 dark:hover:bg-gray-900 text-sm">
{t("cancel")}
</button>
</div>
</div>
</div>{" "}
</form>
)
}

View File

@ -29,7 +29,7 @@ type Props = {
currentMessageIndex: number
totalMessages: number
onRengerate: () => void
onEditFormSubmit: (value: string) => void
onEditFormSubmit: (value: string, isSend: boolean) => void
isProcessing: boolean
webSearch?: {}
isSearchingInternet?: boolean

View File

@ -46,8 +46,8 @@ export const PlaygroundChat = () => {
isProcessing={streaming}
isSearchingInternet={isSearchingInternet}
sources={message.sources}
onEditFormSubmit={(value) => {
editMessage(index, value, !message.isBot)
onEditFormSubmit={(value, isSend) => {
editMessage(index, value, !message.isBot, isSend)
}}
onSourceClick={(data) => {
setSource(data)

View File

@ -86,11 +86,10 @@ export const TTSModeSettings = ({ hideBorder }: { hideBorder?: boolean }) => {
placeholder={t("generalSettings.tts.ttsVoice.placeholder")}
className="w-full mt-4 sm:mt-0 sm:w-[200px]"
options={data?.browserTTSVoices?.map(
(voice) =>
({
(voice) => ({
label: `${voice.voiceName} - ${voice.lang}`.trim(),
value: voice.voiceName
}) || []
})
)}
{...form.getInputProps("voice")}
/>

View File

@ -910,12 +910,14 @@ export const useMessageOption = () => {
const editMessage = async (
index: number,
message: string,
isHuman: boolean
isHuman: boolean,
isSend: boolean
) => {
let newMessages = messages
let newHistory = history
if (isHuman) {
// if human message and send then only trigger the submit
if (isHuman && isSend) {
const isOk = validateBeforeSubmit()
if (!isOk) {
@ -939,14 +941,14 @@ export const useMessageOption = () => {
memory: previousHistory,
controller: abortController
})
} else {
return
}
newMessages[index].message = message
setMessages(newMessages)
newHistory[index].content = message
setHistory(newHistory)
await updateMessageByIndex(historyId, index, message)
}
}
return {
editMessage,