diff --git a/src/frontend/src/modals/IOModal/components/chatView/chatInput/hooks/use-auto-resize-text-area.tsx b/src/frontend/src/modals/IOModal/components/chatView/chatInput/hooks/use-auto-resize-text-area.tsx new file mode 100644 index 000000000..d4102fe9d --- /dev/null +++ b/src/frontend/src/modals/IOModal/components/chatView/chatInput/hooks/use-auto-resize-text-area.tsx @@ -0,0 +1,14 @@ +import { useEffect } from "react"; + +const useAutoResizeTextArea = (value, inputRef) => { + useEffect(() => { + if (inputRef.current && inputRef.current.scrollHeight! !== 0) { + inputRef.current.style!.height = "inherit"; // Reset the height + inputRef.current.style!.height = `${inputRef.current.scrollHeight!}px`; // Set it to the scrollHeight + } + }, [value]); + + return inputRef; +}; + +export default useAutoResizeTextArea; diff --git a/src/frontend/src/modals/IOModal/components/chatView/chatInput/hooks/use-focus-unlock.tsx b/src/frontend/src/modals/IOModal/components/chatView/chatInput/hooks/use-focus-unlock.tsx new file mode 100644 index 000000000..15dfe70ae --- /dev/null +++ b/src/frontend/src/modals/IOModal/components/chatView/chatInput/hooks/use-focus-unlock.tsx @@ -0,0 +1,13 @@ +import { useEffect } from "react"; + +const useFocusOnUnlock = (lockChat, inputRef) => { + useEffect(() => { + if (!lockChat && inputRef.current) { + inputRef.current.focus(); + } + }, [lockChat, inputRef]); + + return inputRef; +}; + +export default useFocusOnUnlock; diff --git a/src/frontend/src/modals/IOModal/components/chatView/chatInput/hooks/use-upload.tsx b/src/frontend/src/modals/IOModal/components/chatView/chatInput/hooks/use-upload.tsx new file mode 100644 index 000000000..30e6559e6 --- /dev/null +++ b/src/frontend/src/modals/IOModal/components/chatView/chatInput/hooks/use-upload.tsx @@ -0,0 +1,57 @@ +import { useEffect } from "react"; +import { uploadFile } from "../../../../../../controllers/API"; + +const useUpload = (uploadFile, currentFlowId, setFiles, uid) => { + useEffect(() => { + const handlePaste = (event: ClipboardEvent): void => { + const items = event.clipboardData?.items; + if (items) { + for (let i = 0; i < items.length; i++) { + const type = items[0].type.split("/")[0]; + + const blob = items[i].getAsFile(); + if (blob) { + const id = uid(); + setFiles((prevFiles) => [ + ...prevFiles, + { file: blob, loading: true, error: false, id, type }, + ]); + + uploadFiles(blob, currentFlowId, setFiles, id); + } + } + } + }; + + document.addEventListener("paste", handlePaste); + return () => { + document.removeEventListener("paste", handlePaste); + }; + }, [uploadFile, currentFlowId]); + + return null; +}; + +const uploadFiles = (blob, currentFlowId, setFiles, id) => { + uploadFile(blob, currentFlowId) + .then((res) => { + setFiles((prev) => { + const newFiles = [...prev]; + const updatedIndex = newFiles.findIndex((file) => file.id === id); + newFiles[updatedIndex].loading = false; + newFiles[updatedIndex].path = res.data.file_path; + return newFiles; + }); + }) + .catch(() => { + setFiles((prev) => { + const newFiles = [...prev]; + const updatedIndex = newFiles.findIndex((file) => file.id === id); + newFiles[updatedIndex].loading = false; + newFiles[updatedIndex].error = true; + return newFiles; + }); + }); +}; + +export default useUpload; diff --git a/src/frontend/src/modals/IOModal/components/chatView/chatInput/index.tsx b/src/frontend/src/modals/IOModal/components/chatView/chatInput/index.tsx index 1ef238f79..8a57fc768 100644 --- a/src/frontend/src/modals/IOModal/components/chatView/chatInput/index.tsx +++ b/src/frontend/src/modals/IOModal/components/chatView/chatInput/index.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from "react"; +import { useState } from "react"; import ShortUniqueId from "short-unique-id"; import IconComponent from "../../../../../components/genericIconComponent"; import { Textarea } from "../../../../../components/ui/textarea"; @@ -7,6 +7,7 @@ import { CHAT_INPUT_PLACEHOLDER_SEND, } from "../../../../../constants/constants"; import { uploadFile } from "../../../../../controllers/API"; +import { Case } from "../../../../../shared/components/caseComponent"; import useFlowsManagerStore from "../../../../../stores/flowsManagerStore"; import { FilePreviewType, @@ -14,6 +15,9 @@ import { } from "../../../../../types/components"; import { classNames } from "../../../../../utils/utils"; import FilePreview from "../filePreviewChat"; +import useAutoResizeTextArea from "./hooks/use-auto-resize-text-area"; +import useFocusOnUnlock from "./hooks/use-focus-unlock"; +import useUpload from "./hooks/use-upload"; export default function ChatInput({ lockChat, chatValue, @@ -28,74 +32,17 @@ export default function ChatInput({ const uid = new ShortUniqueId({ length: 3 }); const [files, setFiles] = useState([]); - useEffect(() => { - if (!lockChat && inputRef.current) { - inputRef.current.focus(); - } - }, [lockChat, inputRef]); + useFocusOnUnlock(lockChat, inputRef); + useAutoResizeTextArea(chatValue, inputRef); + useUpload(uploadFile, currentFlowId, setFiles, uid); - useEffect(() => { - if (inputRef.current && inputRef.current.scrollHeight !== 0) { - inputRef.current.style.height = "inherit"; // Reset the height - inputRef.current.style.height = `${inputRef.current.scrollHeight}px`; // Set it to the scrollHeight - } - }, [chatValue]); - - //listen to ctrl-v to paste images - useEffect(() => { - const handlePaste = (event: ClipboardEvent): void => { - const items = event.clipboardData?.items; - if (items) { - for (let i = 0; i < items.length; i++) { - if (items[i].type.indexOf("image") !== -1) { - const blob = items[i].getAsFile(); - if (blob) { - const id = uid(); - setFiles([ - ...files, - { file: blob, loading: true, error: false, id }, - ]); - uploadFile(blob, currentFlowId) - .then((res) => { - setFiles((prev) => { - const newFiles = [...prev]; - const updatedIndex = newFiles.findIndex( - (file) => file.id === id - ); - newFiles[updatedIndex].loading = false; - newFiles[updatedIndex].path = res.data.file_path; - return newFiles; - }); - }) - .catch((err) => { - setFiles((prev) => { - const newFiles = [...prev]; - const updatedIndex = newFiles.findIndex( - (file) => file.id === id - ); - newFiles[updatedIndex].loading = false; - newFiles[updatedIndex].error = true; - return newFiles; - }); - }); - } - } - } - } - }; - document.addEventListener("paste", handlePaste); - return () => { - document.removeEventListener("paste", handlePaste); - }; - }, []); - - function send() { + const send = () => { sendMessage({ repeat, files: files.map((file) => file.path ?? "").filter((file) => file !== ""), }); setFiles([]); - } + }; return (
@@ -135,10 +82,10 @@ export default function ChatInput({ lockChat || saveLoading ? " form-modal-lock-true bg-input" : noInput - ? "form-modal-no-input bg-input" - : " form-modal-lock-false bg-background", + ? "form-modal-no-input bg-input" + : " form-modal-lock-false bg-background", - "form-modal-lockchat" + "form-modal-lockchat", )} placeholder={ noInput ? CHAT_INPUT_PLACEHOLDER : CHAT_INPUT_PLACEHOLDER_SEND @@ -151,31 +98,35 @@ export default function ChatInput({ noInput ? "bg-high-indigo text-background" : chatValue === "" - ? "text-primary" - : "bg-chat-send text-background" + ? "text-primary" + : "bg-chat-send text-background", )} disabled={lockChat || saveLoading} onClick={(): void => send()} > - {lockChat || saveLoading ? ( + + + + +
@@ -188,32 +139,10 @@ export default function ChatInput({ key={file.id} onDelete={() => { setFiles((prev) => prev.filter((f) => f.id !== file.id)); - // TODO: delete file on backend }} /> ))} - {/* - - - - - -
- Repetitions: - { - handleChange(parseInt(e.target.value)); - }} - className="w-16" - type="number" - min={0} - /> -
-
-
*/} ); }