Skip to content

Commit 03ac80f

Browse files
committed
fix(webview-ui): preserve edit mode across virtualization; focus textarea before scroll; lift editing state into ChatView and satisfy hook deps
1 parent 823ab00 commit 03ac80f

File tree

2 files changed

+20
-7
lines changed

2 files changed

+20
-7
lines changed

webview-ui/src/components/chat/ChatRow.tsx

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ interface ChatRowProps {
7575
onFollowUpUnmount?: () => void
7676
isFollowUpAnswered?: boolean
7777
editable?: boolean
78+
// External edit controls to avoid losing state during virtualization re-mounts
79+
editingTs?: number | null
80+
onStartEditing?: (ts: number) => void
81+
onCancelEditing?: () => void
7882
}
7983

8084
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
@@ -127,12 +131,15 @@ export const ChatRowContent = ({
127131
onBatchFileResponse,
128132
isFollowUpAnswered,
129133
editable,
134+
editingTs,
135+
onStartEditing,
136+
onCancelEditing,
130137
}: ChatRowContentProps) => {
131138
const { t } = useTranslation()
132139

133140
const { mcpServers, alwaysAllowMcp, currentCheckpoint, mode, apiConfiguration } = useExtensionState()
134141
const { info: model } = useSelectedModel(apiConfiguration)
135-
const [isEditing, setIsEditing] = useState(false)
142+
const isEditing = (editingTs ?? null) === message.ts
136143
const [editedContent, setEditedContent] = useState("")
137144
const [editMode, setEditMode] = useState<Mode>(mode || "code")
138145
const [editImages, setEditImages] = useState<string[]>([])
@@ -170,13 +177,13 @@ export const ChatRowContent = ({
170177
// no-op
171178
}
172179

173-
setIsEditing(true)
180+
onStartEditing?.(message.ts)
174181
setEditedContent(message.text || "")
175182
setEditImages(message.images || [])
176183
setEditMode(mode || "code")
177184
// Edit mode is now handled entirely in the frontend
178185
// No need to notify the backend
179-
}, [message.text, message.images, mode])
186+
}, [message.ts, message.text, message.images, mode, onStartEditing])
180187

181188
// Ensure the edit textarea is focused and scrolled into view when entering edit mode.
182189
// Uses a short delay and a few animation frames to allow virtualization reflow before scrolling.
@@ -256,23 +263,24 @@ export const ChatRowContent = ({
256263

257264
// Handle cancel edit
258265
const handleCancelEdit = useCallback(() => {
259-
setIsEditing(false)
266+
onCancelEditing?.()
260267
setEditedContent(message.text || "")
261268
setEditImages(message.images || [])
262269
setEditMode(mode || "code")
263-
}, [message.text, message.images, mode])
270+
}, [message.text, message.images, mode, onCancelEditing])
264271

265272
// Handle save edit
266273
const handleSaveEdit = useCallback(() => {
267-
setIsEditing(false)
268274
// Send edited message to backend
269275
vscode.postMessage({
270276
type: "submitEditedMessage",
271277
value: message.ts,
272278
editedMessageContent: editedContent,
273279
images: editImages,
274280
})
275-
}, [message.ts, editedContent, editImages])
281+
// Exit edit mode
282+
onCancelEditing?.()
283+
}, [message.ts, editedContent, editImages, onCancelEditing])
276284

277285
// Handle image selection for editing
278286
const handleSelectImages = useCallback(() => {

webview-ui/src/components/chat/ChatView.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
185185
const [didClickCancel, setDidClickCancel] = useState(false)
186186
const virtuosoRef = useRef<VirtuosoHandle>(null)
187187
const [expandedRows, setExpandedRows] = useState<Record<number, boolean>>({})
188+
const [editingTs, setEditingTs] = useState<number | null>(null)
188189
const prevExpandedRowsRef = useRef<Record<number, boolean>>()
189190
const scrollContainerRef = useRef<HTMLDivElement>(null)
190191
const disableAutoScrollRef = useRef(false)
@@ -1561,6 +1562,9 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
15611562
return tool.tool === "updateTodoList" && enableButtons && !!primaryButtonText
15621563
})()
15631564
}
1565+
editingTs={editingTs}
1566+
onStartEditing={setEditingTs}
1567+
onCancelEditing={() => setEditingTs(null)}
15641568
/>
15651569
)
15661570
},
@@ -1578,6 +1582,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
15781582
alwaysAllowUpdateTodoList,
15791583
enableButtons,
15801584
primaryButtonText,
1585+
editingTs,
15811586
],
15821587
)
15831588

0 commit comments

Comments
 (0)