Skip to content

Commit 90b35b1

Browse files
xiaojingmingxjm
andauthored
feat: Refactors hover event handling and text input updates (#413)
Improves the event listener management for file path highlights by introducing a MutationObserver to dynamically bind events to new elements. Enhances text input handling to maintain proper spacing when appending new text. This update addresses potential issues with event listeners not being applied to newly added elements and ensures consistent user input behavior. Co-authored-by: xjm <[email protected]>
1 parent 3494cdc commit 90b35b1

File tree

3 files changed

+42
-16
lines changed

3 files changed

+42
-16
lines changed

src/core/webview/ClineProvider.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,7 @@ export class ClineProvider
571571
const prompt = supportPrompt.create(promptType as SupportPromptType, params, customSupportPrompts)
572572

573573
if (command === "addToContext") {
574-
const pathWithSelectedTextResult = supportPrompt.createPathWithSelectedText(
574+
const { pathOnly, selectedText } = supportPrompt.createPathWithSelectedText(
575575
promptType as SupportPromptType,
576576
params,
577577
customSupportPrompts,
@@ -580,8 +580,8 @@ export class ClineProvider
580580
await visibleProvider.postMessageToWebview({
581581
type: "invoke",
582582
invoke: "setChatBoxMessage",
583-
text: pathWithSelectedTextResult.pathOnly,
584-
selectText: pathWithSelectedTextResult.selectedText,
583+
text: pathOnly.length > 0 ? `${pathOnly} ` : "",
584+
selectText: selectedText,
585585
})
586586
return
587587
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -655,16 +655,16 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
655655
let newValue = text
656656

657657
if (inputValue !== "") {
658-
newValue = inputValue + " " + text
658+
newValue = `${inputValue}${inputValue.endsWith(" ") ? "" : " "}${text}`
659659
}
660-
661660
setInputValue(newValue)
662661
setSelectedImages([...selectedImages, ...images])
663662

664663
const filePathMatch = text.match(/\b[\w/\\.-]+:\d+-\d+\b/)
665664
if (filePathMatch) {
666665
setHoverPreviewMap((prev) => new Map(prev.set(filePathMatch[0], selectText)))
667666
}
667+
textAreaRef.current?.focus()
668668
},
669669
[inputValue, selectedImages],
670670
)

webview-ui/src/components/chat/hooks/useHoverEvent.ts

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -210,25 +210,49 @@ export const useHoverEvent = (
210210
[clearHoverTimeout, customSetHoverPreview],
211211
)
212212

213-
// Use useEffect to manage event listeners
213+
// Use useEffect to manage event listeners and MutationObserver
214214
useEffect(() => {
215215
const highlightLayer = highlightLayerRef.current
216216
if (!highlightLayer) return
217217

218-
const filePathElements = highlightLayer.querySelectorAll(".file-path-highlight")
219-
const eventListeners: Array<() => void> = []
218+
// Function to bind events to all .file-path-highlight elements
219+
const bindEventsToElements = () => {
220+
const filePathElements = highlightLayer.querySelectorAll(".file-path-highlight")
221+
const eventListeners: Array<() => void> = []
220222

221-
filePathElements.forEach((element: Element) => {
222-
const enterHandler = (event: Event) => handleHighlightMouseEnter(event)
223-
const leaveHandler = (event: Event) => handleHighlightMouseLeave(event as MouseEvent)
223+
filePathElements.forEach((element: Element) => {
224+
const enterHandler = (event: Event) => handleHighlightMouseEnter(event)
225+
const leaveHandler = (event: Event) => handleHighlightMouseLeave(event as MouseEvent)
224226

225-
element.addEventListener("mouseenter", enterHandler)
226-
element.addEventListener("mouseleave", leaveHandler)
227+
element.addEventListener("mouseenter", enterHandler)
228+
element.addEventListener("mouseleave", leaveHandler)
227229

228-
eventListeners.push(() => {
229-
element.removeEventListener("mouseenter", enterHandler)
230-
element.removeEventListener("mouseleave", leaveHandler)
230+
eventListeners.push(() => {
231+
element.removeEventListener("mouseenter", enterHandler)
232+
element.removeEventListener("mouseleave", leaveHandler)
233+
})
231234
})
235+
236+
return eventListeners
237+
}
238+
239+
// Initial event binding
240+
let eventListeners: Array<() => void> = bindEventsToElements()
241+
242+
// Set up MutationObserver to watch for DOM changes
243+
const observer = new MutationObserver(() => {
244+
// Clean up existing event listeners
245+
eventListeners.forEach((cleanup) => cleanup())
246+
247+
// Re-bind events to new elements
248+
eventListeners = bindEventsToElements()
249+
})
250+
251+
// Start observing the highlight layer for child changes
252+
observer.observe(highlightLayer, {
253+
childList: true, // Watch for addition/removal of child elements
254+
subtree: true, // Watch all descendants
255+
characterData: true, // Watch for text content changes
232256
})
233257

234258
// Return cleanup function
@@ -238,6 +262,8 @@ export const useHoverEvent = (
238262
// Clean up timers
239263
clearHoverTimeout()
240264
currentHoverRef.current = null
265+
// Disconnect MutationObserver
266+
observer.disconnect()
241267
}
242268
}, [handleHighlightMouseEnter, handleHighlightMouseLeave, clearHoverTimeout, highlightLayerRef])
243269

0 commit comments

Comments
 (0)