Skip to content

Commit 77a6e2b

Browse files
committed
File drag and drop
1 parent 82b282b commit 77a6e2b

File tree

5 files changed

+27
-6
lines changed

5 files changed

+27
-6
lines changed

src/core/webview/ClineProvider.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2386,6 +2386,8 @@ export class ClineProvider implements vscode.WebviewViewProvider {
23862386

23872387
const allowedCommands = vscode.workspace.getConfiguration("roo-cline").get<string[]>("allowedCommands") || []
23882388

2389+
const cwd = vscode.workspace.workspaceFolders?.map((folder) => folder.uri.fsPath).at(0) || ""
2390+
23892391
return {
23902392
version: this.context.extension?.packageJSON?.version ?? "",
23912393
apiConfiguration,
@@ -2432,6 +2434,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
24322434
experiments: experiments ?? experimentDefault,
24332435
mcpServers: this.mcpHub?.getAllServers() ?? [],
24342436
maxOpenTabsContext: maxOpenTabsContext ?? 20,
2437+
cwd: cwd,
24352438
}
24362439
}
24372440

src/shared/ExtensionMessage.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ export interface ExtensionState {
129129
customModes: ModeConfig[]
130130
toolRequirements?: Record<string, boolean> // Map of tool names to their requirements (e.g. {"apply_diff": true} if diffEnabled)
131131
maxOpenTabsContext: number // Maximum number of VSCode open tabs to include in context (0-500)
132+
cwd?: string // Current working directory
132133
}
133134

134135
export interface ClineMessage {

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

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
5050
},
5151
ref,
5252
) => {
53-
const { filePaths, openedTabs, currentApiConfigName, listApiConfigMeta, customModes } = useExtensionState()
53+
const { filePaths, openedTabs, currentApiConfigName, listApiConfigMeta, customModes, cwd } = useExtensionState()
5454
const [gitCommits, setGitCommits] = useState<any[]>([])
5555
const [showDropdown, setShowDropdown] = useState(false)
5656

@@ -589,18 +589,35 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
589589
const files = Array.from(e.dataTransfer.files)
590590
const text = e.dataTransfer.getData("text")
591591
if (text) {
592-
const newValue = inputValue.slice(0, cursorPosition) + text + inputValue.slice(cursorPosition)
592+
let mentionText = text
593+
const normalizedText = text.replace(/\\/g, "/")
594+
const normalizedCwd = cwd ? cwd.replace(/\\/g, "/") : ""
595+
596+
// Always use case-insensitive comparison for path matching
597+
if (normalizedCwd) {
598+
const lowerText = normalizedText.toLowerCase()
599+
const lowerCwd = normalizedCwd.toLowerCase()
600+
601+
if (lowerText.startsWith(lowerCwd)) {
602+
mentionText = "@" + normalizedText.substring(normalizedCwd.length)
603+
}
604+
}
605+
606+
const newValue =
607+
inputValue.slice(0, cursorPosition) + mentionText + " " + inputValue.slice(cursorPosition)
593608
setInputValue(newValue)
594-
const newCursorPosition = cursorPosition + text.length
609+
const newCursorPosition = cursorPosition + mentionText.length + 1
595610
setCursorPosition(newCursorPosition)
596611
setIntendedCursorPosition(newCursorPosition)
597612
return
598613
}
614+
599615
const acceptedTypes = ["png", "jpeg", "webp"]
600616
const imageFiles = files.filter((file) => {
601617
const [type, subtype] = file.type.split("/")
602618
return type === "image" && acceptedTypes.includes(subtype)
603619
})
620+
604621
if (!shouldDisableImages && imageFiles.length > 0) {
605622
const imagePromises = imageFiles.map((file) => {
606623
return new Promise<string | null>((resolve) => {

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -880,9 +880,8 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
880880
const placeholderText = useMemo(() => {
881881
const baseText = task ? "Type a message..." : "Type your task here..."
882882
const contextText = "(@ to add context, / to switch modes"
883-
const imageText = shouldDisableImages ? "" : ", hold shift to drag in images"
884-
const helpText = imageText ? `\n${contextText}${imageText})` : `\n${contextText})`
885-
return baseText + helpText
883+
const imageText = shouldDisableImages ? "hold shift to drag in files" : ", hold shift to drag in files/images"
884+
return baseText + `\n${contextText}${imageText})`
886885
}, [task, shouldDisableImages])
887886

888887
const itemContent = useCallback(

webview-ui/src/context/ExtensionStateContext.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
118118
autoApprovalEnabled: false,
119119
customModes: [],
120120
maxOpenTabsContext: 20,
121+
cwd: "",
121122
})
122123

123124
const [didHydrateState, setDidHydrateState] = useState(false)

0 commit comments

Comments
 (0)