From d7e35d08340fd56db200e2eb95f4c9d7624bfe4c Mon Sep 17 00:00:00 2001 From: Matt Rubens Date: Wed, 11 Dec 2024 15:51:06 -0500 Subject: [PATCH] Larger text area with support for dragging in images --- .../src/components/chat/ChatTextArea.tsx | 69 +++++++++++++++++-- webview-ui/src/components/chat/ChatView.tsx | 2 +- 2 files changed, 64 insertions(+), 7 deletions(-) diff --git a/webview-ui/src/components/chat/ChatTextArea.tsx b/webview-ui/src/components/chat/ChatTextArea.tsx index f465942..f48380b 100644 --- a/webview-ui/src/components/chat/ChatTextArea.tsx +++ b/webview-ui/src/components/chat/ChatTextArea.tsx @@ -13,6 +13,8 @@ import { MAX_IMAGES_PER_MESSAGE } from "./ChatView" import ContextMenu from "./ContextMenu" import Thumbnails from "../common/Thumbnails" +declare const vscode: any; + interface ChatTextAreaProps { inputValue: string setInputValue: (value: string) => void @@ -427,7 +429,62 @@ const ChatTextArea = forwardRef( opacity: textAreaDisabled ? 0.5 : 1, position: "relative", display: "flex", - }}> + }} + onDrop={async (e) => { + console.log("onDrop called") + e.preventDefault() + const files = Array.from(e.dataTransfer.files) + const text = e.dataTransfer.getData("text") + if (text) { + const newValue = + inputValue.slice(0, cursorPosition) + text + inputValue.slice(cursorPosition) + setInputValue(newValue) + const newCursorPosition = cursorPosition + text.length + setCursorPosition(newCursorPosition) + setIntendedCursorPosition(newCursorPosition) + return + } + const acceptedTypes = ["png", "jpeg", "webp"] + const imageFiles = files.filter((file) => { + const [type, subtype] = file.type.split("/") + return type === "image" && acceptedTypes.includes(subtype) + }) + if (!shouldDisableImages && imageFiles.length > 0) { + const imagePromises = imageFiles.map((file) => { + return new Promise((resolve) => { + const reader = new FileReader() + reader.onloadend = () => { + if (reader.error) { + console.error("Error reading file:", reader.error) + resolve(null) + } else { + const result = reader.result + console.log("File read successfully", result) + resolve(typeof result === "string" ? result : null) + } + } + reader.readAsDataURL(file) + }) + }) + const imageDataArray = await Promise.all(imagePromises) + const dataUrls = imageDataArray.filter((dataUrl): dataUrl is string => dataUrl !== null) + if (dataUrls.length > 0) { + setSelectedImages((prevImages) => [...prevImages, ...dataUrls].slice(0, MAX_IMAGES_PER_MESSAGE)) + if (typeof vscode !== 'undefined') { + vscode.postMessage({ + type: 'draggedImages', + dataUrls: dataUrls + }) + } + } else { + console.warn("No valid images were processed") + } + } + }} + onDragOver={(e) => { + e.preventDefault() + }} + > {showContextMenu && (
( onHeightChange?.(height) }} placeholder={placeholderText} - maxRows={10} + minRows={2} + maxRows={20} autoFocus={true} style={{ width: "100%", @@ -523,7 +581,6 @@ const ChatTextArea = forwardRef( resize: "none", overflowX: "hidden", overflowY: "scroll", - scrollbarWidth: "none", // Since we have maxRows, when text is long enough it starts to overflow the bottom padding, appearing behind the thumbnails. To fix this, we use a transparent border to push the text up instead. (https://stackoverflow.com/questions/42631947/maintaining-a-padding-inside-of-text-area/52538410#52538410) // borderTop: "9px solid transparent", borderLeft: 0, @@ -560,11 +617,11 @@ const ChatTextArea = forwardRef(
diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index 8dedae9..7a89951 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -689,7 +689,7 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie useEvent("wheel", handleWheel, window, { passive: true }) // passive improves scrolling performance const placeholderText = useMemo(() => { - const text = task ? "Type a message (@ to add context)..." : "Type your task here (@ to add context)..." + const text = task ? "Type a message...\n(@ to add context, hold shift to drag in images)" : "Type your task here...\n(@ to add context, hold shift to drag in images)" return text }, [task])