diff --git a/webview-ui/src/components/chat/ChatTextArea.tsx b/webview-ui/src/components/chat/ChatTextArea.tsx index fb105056b5..1076c59a8d 100644 --- a/webview-ui/src/components/chat/ChatTextArea.tsx +++ b/webview-ui/src/components/chat/ChatTextArea.tsx @@ -339,6 +339,48 @@ export const ChatTextArea = forwardRef( } } + // Special handling for folder selection - keep menu open and update input + if (type === ContextMenuOptionType.Folder && value) { + // Update the input to show the folder path with trailing slash + const beforeCursor = textAreaRef.current?.value.slice(0, cursorPosition) || "" + const _afterCursor = textAreaRef.current?.value.slice(cursorPosition) || "" + + // Find the position of the last '@' symbol before the cursor + const lastAtIndex = beforeCursor.lastIndexOf("@") + + if (lastAtIndex !== -1) { + // Replace everything after @ with the folder path + const beforeMention = textAreaRef.current?.value.slice(0, lastAtIndex) || "" + // Add folder path with trailing slash to allow continued typing + const folderPath = value.endsWith("/") ? value : value + "/" + const newValue = beforeMention + "@" + folderPath + + setInputValue(newValue) + const newCursorPosition = newValue.length + setCursorPosition(newCursorPosition) + setIntendedCursorPosition(newCursorPosition) + + // Update search query to the folder path to show its contents + setSearchQuery(folderPath) + setSelectedType(ContextMenuOptionType.Folder) + + // Request folder contents from the extension + vscode.postMessage({ + type: "searchFiles", + query: folderPath, + requestId: Math.random().toString(36).substring(2, 9), + }) + + // Focus the textarea but keep menu open + setTimeout(() => { + if (textAreaRef.current) { + textAreaRef.current.focus() + } + }, 0) + return + } + } + setShowContextMenu(false) setSelectedType(null) @@ -347,7 +389,7 @@ export const ChatTextArea = forwardRef( if (type === ContextMenuOptionType.URL) { insertValue = value || "" - } else if (type === ContextMenuOptionType.File || type === ContextMenuOptionType.Folder) { + } else if (type === ContextMenuOptionType.File) { insertValue = value || "" } else if (type === ContextMenuOptionType.Problems) { insertValue = "problems" diff --git a/webview-ui/src/utils/context-mentions.ts b/webview-ui/src/utils/context-mentions.ts index d7aeb0fdd5..eaa425e51a 100644 --- a/webview-ui/src/utils/context-mentions.ts +++ b/webview-ui/src/utils/context-mentions.ts @@ -259,28 +259,35 @@ export function getContextMenuOptions( ] } + // Special handling for folder paths - if query ends with /, we're looking inside a folder + const isLookingInsideFolder = query.endsWith("/") + // const _folderPath = isLookingInsideFolder ? query.slice(0, -1) : "" + const lowerQuery = query.toLowerCase() const suggestions: ContextMenuQueryItem[] = [] - // Check for top-level option matches - if ("git".startsWith(lowerQuery)) { - suggestions.push({ - type: ContextMenuOptionType.Git, - label: "Git Commits", - description: "Search repository history", - icon: "$(git-commit)", - }) - } else if ("git-changes".startsWith(lowerQuery)) { - suggestions.push(workingChanges) - } - if ("problems".startsWith(lowerQuery)) { - suggestions.push({ type: ContextMenuOptionType.Problems }) - } - if ("terminal".startsWith(lowerQuery)) { - suggestions.push({ type: ContextMenuOptionType.Terminal }) - } - if (query.startsWith("http")) { - suggestions.push({ type: ContextMenuOptionType.URL, value: query }) + // Only show top-level options if we're not looking inside a folder + if (!isLookingInsideFolder) { + // Check for top-level option matches + if ("git".startsWith(lowerQuery)) { + suggestions.push({ + type: ContextMenuOptionType.Git, + label: "Git Commits", + description: "Search repository history", + icon: "$(git-commit)", + }) + } else if ("git-changes".startsWith(lowerQuery)) { + suggestions.push(workingChanges) + } + if ("problems".startsWith(lowerQuery)) { + suggestions.push({ type: ContextMenuOptionType.Problems }) + } + if ("terminal".startsWith(lowerQuery)) { + suggestions.push({ type: ContextMenuOptionType.Terminal }) + } + if (query.startsWith("http")) { + suggestions.push({ type: ContextMenuOptionType.URL, value: query }) + } } // Add exact SHA matches to suggestions