@@ -18,6 +18,7 @@ import {
1818 $isRangeSelection ,
1919 $createParagraphNode ,
2020 $createTextNode ,
21+ $isTextNode ,
2122} from "lexical"
2223
2324import { cn } from "@/lib/utils"
@@ -30,7 +31,7 @@ import { AutoApproveDropdown } from "./AutoApproveDropdown"
3031import { StandardTooltip } from "../ui"
3132import { IndexingStatusBadge } from "./IndexingStatusBadge"
3233
33- import { MentionNode } from "./lexical/MentionNode"
34+ import { MentionNode , $isMentionNode } from "./lexical/MentionNode"
3435import { LexicalMentionPlugin , type MentionInfo , type LexicalMentionPluginRef } from "./lexical/LexicalMentionPlugin"
3536import { LexicalSelectAllPlugin } from "./lexical/LexicalSelectAllPlugin"
3637import { LexicalPromptHistoryPlugin } from "./lexical/LexicalPromptHistoryPlugin"
@@ -41,7 +42,6 @@ import { ContextMenuOptionType, SearchResult } from "@/utils/context-mentions"
4142import { MAX_IMAGES_PER_MESSAGE } from "./ChatView"
4243import { CloudAccountSwitcher } from "../cloud/CloudAccountSwitcher"
4344import { ChatContextBar } from "./ChatContextBar"
44- import { usePromptHistoryData } from "./hooks/usePromptHistoryData"
4545
4646type ChatTextAreaProps = {
4747 inputValue : string
@@ -51,7 +51,7 @@ type ChatTextAreaProps = {
5151 placeholderText : string
5252 selectedImages : string [ ]
5353 setSelectedImages : React . Dispatch < React . SetStateAction < string [ ] > >
54- onSend : ( ) => void
54+ onSend : ( serializedContent : string ) => void
5555 onSelectImages : ( ) => void
5656 shouldDisableImages : boolean
5757 onHeightChange ?: ( height : number ) => void
@@ -96,11 +96,8 @@ export const ChatLexicalTextArea = forwardRef<LexicalEditor, ChatTextAreaProps>(
9696 listApiConfigMeta,
9797 customModes,
9898 customModePrompts,
99- cwd,
10099 pinnedApiConfigs,
101100 togglePinnedApiConfig,
102- taskHistory,
103- clineMessages,
104101 commands,
105102 cloudUserInfo,
106103 } = useExtensionState ( )
@@ -119,12 +116,6 @@ export const ChatLexicalTextArea = forwardRef<LexicalEditor, ChatTextAreaProps>(
119116 const [ isMouseDownOnMenu , setIsMouseDownOnMenu ] = useState ( false )
120117 const editorRef = useRef < LexicalEditor | null > ( null )
121118
122- const { promptHistory } = usePromptHistoryData ( {
123- clineMessages,
124- taskHistory,
125- cwd,
126- } )
127-
128119 // Find the ID and display text for the currently selected API configuration.
129120 const { currentConfigId, displayName } = useMemo ( ( ) => {
130121 const currentConfig = listApiConfigMeta ?. find ( ( config ) => config . name === currentApiConfigName )
@@ -493,15 +484,93 @@ export const ChatLexicalTextArea = forwardRef<LexicalEditor, ChatTextAreaProps>(
493484 setIsMouseDownOnMenu ( true )
494485 } , [ ] )
495486
496- const handleEditorChange = useCallback (
497- ( editorState : EditorState ) => {
498- editorState . read ( ( ) => {
487+ const serializeEditorContent = useCallback ( ( editorState : EditorState ) : string => {
488+ return editorState . read ( ( ) => {
489+ const root = $getRoot ( )
490+ let serializedText = ""
491+
492+ const traverse = ( node : any ) => {
493+ if ( $isMentionNode ( node ) ) {
494+ const trigger = node . getTrigger ( )
495+ const value = node . getValue ( )
496+ const data = node . getData ( )
497+
498+ if ( trigger === "@" ) {
499+ const type = data ?. type
500+ if ( type === "problems" ) {
501+ serializedText += "@problems"
502+ } else if ( type === "terminal" ) {
503+ serializedText += "@terminal"
504+ } else {
505+ // File or folder mention
506+ serializedText += `@${ value } `
507+ }
508+ } else if ( trigger === "/" ) {
509+ // Command mention
510+ serializedText += `/${ value } `
511+ }
512+ } else if ( $isTextNode ( node ) ) {
513+ serializedText += node . getTextContent ( )
514+ } else {
515+ // Traverse children for other node types
516+ const children = node . getChildren ?.( ) || [ ]
517+ for ( const child of children ) {
518+ traverse ( child )
519+ }
520+ }
521+ }
522+
523+ const children = root . getChildren ( )
524+ for ( const child of children ) {
525+ traverse ( child )
526+ }
527+
528+ return serializedText
529+ } )
530+ } , [ ] )
531+
532+ const getDisplayText = useCallback ( ( editorState : EditorState ) : string => {
533+ return editorState . read ( ( ) => {
534+ const root = $getRoot ( )
535+ return root . getTextContent ( )
536+ } )
537+ } , [ ] )
538+
539+ const getSerializedContent = useCallback ( ( ) : string => {
540+ if ( editorRef . current ) {
541+ return serializeEditorContent ( editorRef . current . getEditorState ( ) )
542+ }
543+ return inputValue
544+ } , [ serializeEditorContent , inputValue ] )
545+
546+ // Function to clear the editor content
547+ const clearEditor = useCallback ( ( ) => {
548+ if ( editorRef . current ) {
549+ editorRef . current . update ( ( ) => {
499550 const root = $getRoot ( )
500- const textContent = root . getTextContent ( )
501- setInputValue ( textContent )
551+ root . clear ( )
502552 } )
553+ }
554+ setInputValue ( "" )
555+ setSelectedImages ( [ ] )
556+ } , [ setInputValue , setSelectedImages ] )
557+
558+ // Wrapper function for onSend that resets the textarea after sending
559+ const handleSend = useCallback (
560+ ( serializedContent : string ) => {
561+ onSend ( serializedContent )
562+ clearEditor ( )
503563 } ,
504- [ setInputValue ] ,
564+ [ onSend , clearEditor ] ,
565+ )
566+
567+ const handleEditorChange = useCallback (
568+ ( editorState : EditorState ) => {
569+ // Update display text for UI
570+ const displayText = getDisplayText ( editorState )
571+ setInputValue ( displayText )
572+ } ,
573+ [ setInputValue , getDisplayText ] ,
505574 )
506575
507576 const placeholderBottomText = `\n(${ t ( "chat:addContext" ) } ${ shouldDisableImages ? `, ${ t ( "chat:dragFiles" ) } ` : `, ${ t ( "chat:dragFilesImages" ) } ` } )`
@@ -600,10 +669,8 @@ export const ChatLexicalTextArea = forwardRef<LexicalEditor, ChatTextAreaProps>(
600669 { /* see: https://github.com/facebook/lexical/discussions/3590#discussioncomment-8955421 */ }
601670 < EditorRefPlugin
602671 editorRef = { ( el ) => {
603- // Store editor ref locally
604672 editorRef . current = el
605673
606- // Also forward to parent ref
607674 if ( typeof ref === "function" ) {
608675 ref ( el )
609676 } else if ( ref ) {
@@ -685,8 +752,11 @@ export const ChatLexicalTextArea = forwardRef<LexicalEditor, ChatTextAreaProps>(
685752 materialIconsBaseUri = { materialIconsBaseUri }
686753 />
687754 < LexicalPromptHistoryPlugin
688- promptHistory = { promptHistory }
689755 showContextMenu = { showContextMenu }
756+ onSend = { ( ) => {
757+ handleSend ( getSerializedContent ( ) )
758+ } }
759+ sendingDisabled = { sendingDisabled || ! hasInputContent }
690760 />
691761 < LexicalContextMenuPlugin
692762 showContextMenu = { showContextMenu }
@@ -778,7 +848,7 @@ export const ChatLexicalTextArea = forwardRef<LexicalEditor, ChatTextAreaProps>(
778848 < button
779849 aria-label = { t ( "chat:sendMessage" ) }
780850 disabled = { sendingDisabled || ! hasInputContent }
781- onClick = { onSend }
851+ onClick = { ( ) => handleSend ( getSerializedContent ( ) ) }
782852 className = { cn (
783853 "relative inline-flex items-center justify-center" ,
784854 "bg-transparent border-none p-1.5" ,
0 commit comments