Disable message send while content is embedding (#3832)

* Disable message send while content is embedding

* opacity

* normalize langs

* remove console log

---------

Co-authored-by: shatfield4 <seanhatfield5@gmail.com>
This commit is contained in:
Timothy Carambat 2025-05-16 11:35:33 -07:00 committed by GitHub
parent 0e1de19408
commit f259fef6ee
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 98 additions and 24 deletions

View File

@ -10,6 +10,8 @@ export const DndUploaderContext = createContext();
export const REMOVE_ATTACHMENT_EVENT = "ATTACHMENT_REMOVE";
export const CLEAR_ATTACHMENTS_EVENT = "ATTACHMENT_CLEAR";
export const PASTE_ATTACHMENT_EVENT = "ATTACHMENT_PASTED";
export const ATTACHMENTS_PROCESSING_EVENT = "ATTACHMENTS_PROCESSING";
export const ATTACHMENTS_PROCESSED_EVENT = "ATTACHMENTS_PROCESSED";
/**
* File Attachment for automatic upload on the chat container page.
@ -169,34 +171,44 @@ export function DnDFileUploaderProvider({ workspace, children }) {
* @param {Attachment[]} newAttachments
*/
function embedEligibleAttachments(newAttachments = []) {
window.dispatchEvent(new CustomEvent(ATTACHMENTS_PROCESSING_EVENT));
const promises = [];
for (const attachment of newAttachments) {
// Images/attachments are chat specific.
if (attachment.type === "attachment") continue;
const formData = new FormData();
formData.append("file", attachment.file, attachment.file.name);
Workspace.uploadAndEmbedFile(workspace.slug, formData).then(
({ response, data }) => {
const updates = {
status: response.ok ? "success" : "failed",
error: data?.error ?? null,
document: data?.document,
};
promises.push(
Workspace.uploadAndEmbedFile(workspace.slug, formData).then(
({ response, data }) => {
const updates = {
status: response.ok ? "success" : "failed",
error: data?.error ?? null,
document: data?.document,
};
setFiles((prev) => {
return prev.map(
(
/** @type {Attachment} */
prevFile
) => {
if (prevFile.uid !== attachment.uid) return prevFile;
return { ...prevFile, ...updates };
}
);
});
}
setFiles((prev) => {
return prev.map(
(
/** @type {Attachment} */
prevFile
) => {
if (prevFile.uid !== attachment.uid) return prevFile;
return { ...prevFile, ...updates };
}
);
});
}
)
);
}
// Wait for all promises to resolve in some way before dispatching the event to unlock the send button
Promise.all(promises).finally(() =>
window.dispatchEvent(new CustomEvent(ATTACHMENTS_PROCESSED_EVENT))
);
}
return (

View File

@ -15,7 +15,11 @@ import SpeechToText from "./SpeechToText";
import { Tooltip } from "react-tooltip";
import AttachmentManager from "./Attachments";
import AttachItem from "./AttachItem";
import { PASTE_ATTACHMENT_EVENT } from "../DnDWrapper";
import {
ATTACHMENTS_PROCESSED_EVENT,
ATTACHMENTS_PROCESSING_EVENT,
PASTE_ATTACHMENT_EVENT,
} from "../DnDWrapper";
import useTextSize from "@/hooks/useTextSize";
import { useTranslation } from "react-i18next";
import Appearance from "@/models/appearance";
@ -31,6 +35,7 @@ export default function PromptInput({
attachments = [],
}) {
const { t } = useTranslation();
const { isDisabled } = useIsDisabled();
const [promptInput, setPromptInput] = useState("");
const { showAgents, setShowAgents } = useAvailableAgents();
const { showSlashCommand, setShowSlashCommand } = useSlashCommands();
@ -112,7 +117,7 @@ export default function PromptInput({
// Is simple enter key press w/o shift key
if (event.keyCode === 13 && !event.shiftKey) {
event.preventDefault();
if (isStreaming) return;
if (isStreaming || isDisabled) return; // Prevent submission if streaming or disabled
return submit(event);
}
@ -280,14 +285,19 @@ export default function PromptInput({
<button
ref={formRef}
type="submit"
className="border-none inline-flex justify-center rounded-2xl cursor-pointer opacity-60 hover:opacity-100 light:opacity-100 light:hover:opacity-60 ml-4"
disabled={isDisabled}
className="border-none inline-flex justify-center rounded-2xl cursor-pointer opacity-60 hover:opacity-100 light:opacity-100 light:hover:opacity-60 ml-4 disabled:cursor-not-allowed group"
data-tooltip-id="send-prompt"
data-tooltip-content={t("chat_window.send")}
data-tooltip-content={
isDisabled
? t("chat_window.attachments_processing")
: t("chat_window.send")
}
aria-label={t("chat_window.send")}
>
<PaperPlaneRight
color="var(--theme-sidebar-footer-icon-fill)"
className="w-[22px] h-[22px] pointer-events-none text-theme-text-primary"
className="w-[22px] h-[22px] pointer-events-none text-theme-text-primary group-disabled:opacity-[25%]"
weight="fill"
/>
<span className="sr-only">Send message</span>
@ -324,3 +334,37 @@ export default function PromptInput({
</div>
);
}
/**
* Handle event listeners to prevent the send button from being used
* for whatever reason that may we may want to prevent the user from sending a message.
*/
function useIsDisabled() {
const [isDisabled, setIsDisabled] = useState(false);
/**
* Handle attachments processing and processed events
* to prevent the send button from being clicked when attachments are processing
* or else the query may not have relevant context since RAG is not yet ready.
*/
useEffect(() => {
if (!window) return;
window.addEventListener(ATTACHMENTS_PROCESSING_EVENT, () =>
setIsDisabled(true)
);
window.addEventListener(ATTACHMENTS_PROCESSED_EVENT, () =>
setIsDisabled(false)
);
return () => {
window?.removeEventListener(ATTACHMENTS_PROCESSING_EVENT, () =>
setIsDisabled(true)
);
window?.removeEventListener(ATTACHMENTS_PROCESSED_EVENT, () =>
setIsDisabled(false)
);
};
}, []);
return { isDisabled };
}

View File

@ -667,6 +667,7 @@ const TRANSLATIONS = {
text_size: null,
microphone: null,
send: null,
attachments_processing: null,
},
profile_settings: {
edit_account: null,

View File

@ -705,6 +705,7 @@ const TRANSLATIONS = {
text_size: "Ændr tekststørrelse.",
microphone: "Tal din prompt.",
send: "Send promptbesked til arbejdsområdet",
attachments_processing: null,
},
profile_settings: {
edit_account: "Rediger konto",

View File

@ -703,6 +703,7 @@ const TRANSLATIONS = {
text_size: "Ändere die Größe des Textes.",
microphone: "Spreche deinen Prompt ein.",
send: "Versende den Prompt an den Arbeitsbereich.",
attachments_processing: null,
},
profile_settings: {
edit_account: "Account bearbeiten",

View File

@ -925,6 +925,7 @@ const TRANSLATIONS = {
get_started_default: "To get started",
upload: "upload a document",
or: "or",
attachments_processing: "Attachments are processing. Please wait...",
send_chat: "send a chat.",
send_message: "Send a message",
attach_file: "Attach a file to this chat",

View File

@ -666,6 +666,7 @@ const TRANSLATIONS = {
text_size: null,
microphone: null,
send: null,
attachments_processing: null,
},
profile_settings: {
edit_account: null,

View File

@ -659,6 +659,7 @@ const TRANSLATIONS = {
text_size: null,
microphone: null,
send: null,
attachments_processing: null,
},
profile_settings: {
edit_account: null,

View File

@ -667,6 +667,7 @@ const TRANSLATIONS = {
text_size: null,
microphone: null,
send: null,
attachments_processing: null,
},
profile_settings: {
edit_account: null,

View File

@ -652,6 +652,7 @@ const TRANSLATIONS = {
text_size: null,
microphone: null,
send: null,
attachments_processing: null,
},
profile_settings: {
edit_account: null,

View File

@ -665,6 +665,7 @@ const TRANSLATIONS = {
text_size: null,
microphone: null,
send: null,
attachments_processing: null,
},
profile_settings: {
edit_account: null,

View File

@ -697,6 +697,7 @@ const TRANSLATIONS = {
text_size: "テキストサイズを変更",
microphone: "プロンプトを音声入力",
send: "ワークスペースにプロンプトメッセージを送信",
attachments_processing: null,
},
profile_settings: {
edit_account: "アカウントを編集",

View File

@ -652,6 +652,7 @@ const TRANSLATIONS = {
text_size: null,
microphone: null,
send: null,
attachments_processing: null,
},
profile_settings: {
edit_account: null,

View File

@ -662,6 +662,7 @@ const TRANSLATIONS = {
text_size: null,
microphone: null,
send: null,
attachments_processing: null,
},
profile_settings: {
edit_account: null,

View File

@ -671,6 +671,7 @@ const TRANSLATIONS = {
text_size: null,
microphone: null,
send: null,
attachments_processing: null,
},
profile_settings: {
edit_account: null,

View File

@ -706,6 +706,7 @@ const TRANSLATIONS = {
text_size: "Изменить размер текста.",
microphone: "Произнесите ваш запрос.",
send: "Отправить запрос в рабочее пространство",
attachments_processing: null,
},
profile_settings: {
edit_account: "Редактировать учётную запись",

View File

@ -662,6 +662,7 @@ const TRANSLATIONS = {
text_size: null,
microphone: null,
send: null,
attachments_processing: null,
},
profile_settings: {
edit_account: null,

View File

@ -661,6 +661,7 @@ const TRANSLATIONS = {
text_size: null,
microphone: null,
send: null,
attachments_processing: null,
},
profile_settings: {
edit_account: null,

View File

@ -830,6 +830,7 @@ const TRANSLATIONS = {
text_size: "更改文字大小。",
microphone: "语音输入你的提示。",
send: "将提示消息发送到工作区",
attachments_processing: null,
},
profile_settings: {
edit_account: "编辑帐户",

View File

@ -664,6 +664,7 @@ const TRANSLATIONS = {
text_size: "變更文字大小。",
microphone: "語音輸入提示。",
send: "將提示訊息發送到工作區",
attachments_processing: null,
},
profile_settings: {
edit_account: null,