Format file paths and truncate in menu

This commit is contained in:
Saoud Rizwan
2024-09-17 17:42:24 -04:00
parent f4c401343f
commit 3f63428580
3 changed files with 88 additions and 22 deletions

View File

@@ -3,6 +3,8 @@ import * as path from "path"
import { listFiles } from "../parse-source-code/index" import { listFiles } from "../parse-source-code/index"
import { ClaudeDevProvider } from "../providers/ClaudeDevProvider" import { ClaudeDevProvider } from "../providers/ClaudeDevProvider"
const cwd = vscode.workspace.workspaceFolders?.map((folder) => folder.uri.fsPath).at(0)
class WorkspaceTracker { class WorkspaceTracker {
private providerRef: WeakRef<ClaudeDevProvider> private providerRef: WeakRef<ClaudeDevProvider>
private disposables: vscode.Disposable[] = [] private disposables: vscode.Disposable[] = []
@@ -15,12 +17,17 @@ class WorkspaceTracker {
async initializeFilePaths() { async initializeFilePaths() {
// should not auto get filepaths for desktop since it would immediately show permission popup before claude every creates a file // should not auto get filepaths for desktop since it would immediately show permission popup before claude every creates a file
const cwd = vscode.workspace.workspaceFolders?.map((folder) => folder.uri.fsPath).at(0)
if (!cwd) { if (!cwd) {
return return
} }
const [files, _] = await listFiles(cwd, true, 500) const [files, _] = await listFiles(cwd, true, 500)
files.forEach((file) => this.filePaths.add(file)) files
.map((file) => {
const relativePath = path.relative(cwd, file)
return file.endsWith("/") ? relativePath + "/" : relativePath
})
.forEach((file) => this.filePaths.add(file))
this.workspaceDidUpdate() this.workspaceDidUpdate()
} }
@@ -74,8 +81,16 @@ class WorkspaceTracker {
private async onWorkspaceFoldersChanged(event: vscode.WorkspaceFoldersChangeEvent) { private async onWorkspaceFoldersChanged(event: vscode.WorkspaceFoldersChangeEvent) {
for (const folder of event.added) { for (const folder of event.added) {
const [files, _] = await listFiles(folder.uri.fsPath, true, 50) const [files, _] = await listFiles(folder.uri.fsPath, true, 50) // at most 50 files
files.forEach((file) => this.filePaths.add(file)) if (!cwd) {
continue
}
files
.map((file) => {
const relativePath = path.relative(cwd, file)
return file.endsWith("/") ? relativePath + "/" : relativePath
})
.forEach((file) => this.filePaths.add(file))
} }
for (const folder of event.removed) { for (const folder of event.removed) {
this.filePaths.forEach((filePath) => { this.filePaths.forEach((filePath) => {

View File

@@ -55,10 +55,12 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
const searchPaths = React.useMemo(() => { const searchPaths = React.useMemo(() => {
return [ return [
{ type: "problems", path: "problems" }, { type: "problems", path: "problems" },
...filePaths.map((path) => ({ ...filePaths
type: path.endsWith("/") ? "folder" : "file", .map((file) => "/" + file)
path: path, .map((path) => ({
})), type: path.endsWith("/") ? "folder" : "file",
path: path,
})),
] ]
}, [filePaths]) }, [filePaths])

View File

@@ -1,5 +1,6 @@
import React, { useEffect, useRef, useState } from "react" import React, { useEffect, useRef, useState } from "react"
import { getContextMenuOptions } from "../utils/mention-context" import { getContextMenuOptions } from "../utils/mention-context"
import { removeLeadingNonAlphanumeric } from "./CodeAccordian"
interface ContextMenuProps { interface ContextMenuProps {
onSelect: (type: string, value: string) => void onSelect: (type: string, value: string) => void
@@ -45,6 +46,46 @@ const ContextMenu: React.FC<ContextMenuProps> = ({
} }
}, [selectedIndex]) }, [selectedIndex])
const renderOptionContent = (option: { type: string; value: string }) => {
switch (option.value) {
case "file":
case "folder":
case "problems":
case "url":
return (
<span
style={{
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "ellipsis",
}}>
{option.value === "file"
? "Add File"
: option.value === "folder"
? "Add Folder"
: option.value === "problems"
? "Problems"
: option.value === "url"
? "Paste URL to scrape"
: ""}
</span>
)
default:
return (
<span
style={{
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "ellipsis",
direction: "rtl",
textAlign: "left",
}}>
{removeLeadingNonAlphanumeric(option.value) + "\u200E"}
</span>
)
}
}
return ( return (
<div <div
style={{ style={{
@@ -52,6 +93,7 @@ const ContextMenu: React.FC<ContextMenuProps> = ({
bottom: "calc(100% - 10px)", bottom: "calc(100% - 10px)",
left: 15, left: 15,
right: 15, right: 15,
overflowX: "hidden",
}} }}
onMouseDown={onMouseDown}> onMouseDown={onMouseDown}>
<div <div
@@ -83,29 +125,36 @@ const ContextMenu: React.FC<ContextMenuProps> = ({
index === selectedIndex && option.type !== "url" index === selectedIndex && option.type !== "url"
? "var(--vscode-list-activeSelectionBackground)" ? "var(--vscode-list-activeSelectionBackground)"
: "", : "",
// opacity: option.type === "url" ? 0.5 : 1, // Make URL option appear disabled
}} }}
onMouseEnter={() => option.type !== "url" && setSelectedIndex(index)}> onMouseEnter={() => option.type !== "url" && setSelectedIndex(index)}>
<div style={{ display: "flex", alignItems: "center" }}> <div
<i className={`codicon codicon-${option.icon}`} style={{ marginRight: "8px" }} /> style={{
{option.value === "file" display: "flex",
? "Add File" alignItems: "center",
: option.value === "folder" flex: 1,
? "Add Folder" minWidth: 0, // Allows child to shrink below content size
: option.value === "problems" overflow: "hidden", // Ensures content doesn't overflow
? "Problems" }}>
: option.value === "url" <i
? "Paste URL to scrape" className={`codicon codicon-${option.icon}`}
: option.value} style={{ marginRight: "8px", flexShrink: 0, fontSize: "14px" }}
/>
{renderOptionContent(option)}
</div> </div>
{(option.value === "file" || option.value === "folder") && ( {(option.value === "file" || option.value === "folder") && (
<i className="codicon codicon-chevron-right" style={{ fontSize: "14px" }} /> <i
className="codicon codicon-chevron-right"
style={{ fontSize: "14px", flexShrink: 0, marginLeft: 8 }}
/>
)} )}
{(option.type === "problems" || {(option.type === "problems" ||
((option.type === "file" || option.type === "folder") && ((option.type === "file" || option.type === "folder") &&
option.value !== "file" && option.value !== "file" &&
option.value !== "folder")) && ( option.value !== "folder")) && (
<i className="codicon codicon-add" style={{ fontSize: "14px" }} /> <i
className="codicon codicon-add"
style={{ fontSize: "14px", flexShrink: 0, marginLeft: 8 }}
/>
)} )}
</div> </div>
))} ))}