1- import React from "react"
1+ import React , { useState } from "react"
22import { useTranslation } from "react-i18next"
33import Thumbnails from "../common/Thumbnails"
44import { QueuedMessage } from "@roo-code/types"
@@ -8,45 +8,93 @@ import { Button } from "@src/components/ui"
88interface QueuedMessagesProps {
99 queue : QueuedMessage [ ]
1010 onRemove : ( index : number ) => void
11+ onUpdate : ( index : number , newText : string ) => void
1112}
1213
13- const QueuedMessages : React . FC < QueuedMessagesProps > = ( { queue, onRemove } ) => {
14+ const QueuedMessages : React . FC < QueuedMessagesProps > = ( { queue, onRemove, onUpdate } ) => {
1415 const { t } = useTranslation ( "chat" )
16+ const [ editingStates , setEditingStates ] = useState < Record < string , { isEditing : boolean ; value : string } > > ( { } )
1517
1618 if ( queue . length === 0 ) {
1719 return null
1820 }
1921
22+ const getEditState = ( messageId : string , currentText : string ) => {
23+ return editingStates [ messageId ] || { isEditing : false , value : currentText }
24+ }
25+
26+ const setEditState = ( messageId : string , isEditing : boolean , value ?: string ) => {
27+ setEditingStates ( ( prev ) => ( {
28+ ...prev ,
29+ [ messageId ] : { isEditing, value : value ?? prev [ messageId ] ?. value ?? "" } ,
30+ } ) )
31+ }
32+
33+ const handleSaveEdit = ( index : number , messageId : string , newValue : string ) => {
34+ onUpdate ( index , newValue )
35+ setEditState ( messageId , false )
36+ }
37+
2038 return (
2139 < div className = "px-[15px] py-[10px] pr-[6px]" data-testid = "queued-messages" >
2240 < div className = "text-vscode-descriptionForeground text-md mb-2" > { t ( "queuedMessages.title" ) } </ div >
2341 < div className = "flex flex-col gap-2" >
24- { queue . map ( ( message , index ) => (
25- < div
26- key = { message . id }
27- className = "bg-vscode-editor-background border rounded-xs p-1 overflow-hidden whitespace-pre-wrap" >
28- < div className = "flex justify-between" >
29- < div className = "flex-grow px-2 py-1 wrap-anywhere" >
30- < Mention text = { message . text } withShadow />
31- </ div >
32- < div className = "flex" >
33- < Button
34- variant = "ghost"
35- size = "icon"
36- className = "shrink-0"
37- onClick = { ( e ) => {
38- e . stopPropagation ( )
39- onRemove ( index )
40- } } >
41- < span className = "codicon codicon-trash" />
42- </ Button >
42+ { queue . map ( ( message , index ) => {
43+ const editState = getEditState ( message . id , message . text )
44+
45+ return (
46+ < div
47+ key = { message . id }
48+ className = "bg-vscode-editor-background border rounded-xs p-1 overflow-hidden whitespace-pre-wrap" >
49+ < div className = "flex justify-between" >
50+ < div className = "flex-grow px-2 py-1 wrap-anywhere" >
51+ { editState . isEditing ? (
52+ < textarea
53+ value = { editState . value }
54+ onChange = { ( e ) => setEditState ( message . id , true , e . target . value ) }
55+ onBlur = { ( ) => handleSaveEdit ( index , message . id , editState . value ) }
56+ onKeyDown = { ( e ) => {
57+ if ( e . key === "Enter" && ! e . shiftKey ) {
58+ e . preventDefault ( )
59+ handleSaveEdit ( index , message . id , editState . value )
60+ }
61+ if ( e . key === "Escape" ) {
62+ setEditState ( message . id , false , message . text )
63+ }
64+ } }
65+ className = "w-full bg-vscode-input-background text-vscode-input-foreground border border-vscode-input-border rounded px-2 py-1 resize-none focus:outline-0 focus:ring-1 focus:ring-vscode-focusBorder"
66+ placeholder = { t ( "chat:editMessage.placeholder" ) }
67+ autoFocus
68+ rows = { Math . min ( editState . value . split ( "\n" ) . length , 10 ) }
69+ />
70+ ) : (
71+ < div
72+ onClick = { ( ) => setEditState ( message . id , true , message . text ) }
73+ className = "cursor-pointer hover:bg-vscode-list-hoverBackground px-1 py-0.5 -mx-1 -my-0.5 rounded transition-colors"
74+ title = { t ( "chat:queuedMessages.clickToEdit" ) } >
75+ < Mention text = { message . text } withShadow />
76+ </ div >
77+ ) }
78+ </ div >
79+ < div className = "flex" >
80+ < Button
81+ variant = "ghost"
82+ size = "icon"
83+ className = "shrink-0"
84+ onClick = { ( e ) => {
85+ e . stopPropagation ( )
86+ onRemove ( index )
87+ } } >
88+ < span className = "codicon codicon-trash" />
89+ </ Button >
90+ </ div >
4391 </ div >
92+ { message . images && message . images . length > 0 && (
93+ < Thumbnails images = { message . images } style = { { marginTop : "8px" } } />
94+ ) }
4495 </ div >
45- { message . images && message . images . length > 0 && (
46- < Thumbnails images = { message . images } style = { { marginTop : "8px" } } />
47- ) }
48- </ div >
49- ) ) }
96+ )
97+ } ) }
5098 </ div >
5199 </ div >
52100 )
0 commit comments