diff --git a/src/components/FileTree.jsx b/src/components/FileTree.jsx
index 1048bdb..725ae7c 100644
--- a/src/components/FileTree.jsx
+++ b/src/components/FileTree.jsx
@@ -1,7 +1,8 @@
import React, { useState, useEffect } from 'react';
import { ScrollArea } from './ui/scroll-area';
import { Button } from './ui/button';
-import { Folder, FolderOpen, File, FileText, FileCode, List, TableProperties, Eye } from 'lucide-react';
+import { Input } from './ui/input';
+import { Folder, FolderOpen, File, FileText, FileCode, List, TableProperties, Eye, Search, X } from 'lucide-react';
import { cn } from '../lib/utils';
import CodeEditor from './CodeEditor';
import ImageViewer from './ImageViewer';
@@ -14,6 +15,8 @@ function FileTree({ selectedProject }) {
const [selectedFile, setSelectedFile] = useState(null);
const [selectedImage, setSelectedImage] = useState(null);
const [viewMode, setViewMode] = useState('detailed'); // 'simple', 'detailed', 'compact'
+ const [searchQuery, setSearchQuery] = useState('');
+ const [filteredFiles, setFilteredFiles] = useState([]);
useEffect(() => {
if (selectedProject) {
@@ -29,6 +32,51 @@ function FileTree({ selectedProject }) {
}
}, []);
+ // Filter files based on search query
+ useEffect(() => {
+ if (!searchQuery.trim()) {
+ setFilteredFiles(files);
+ } else {
+ const filtered = filterFiles(files, searchQuery.toLowerCase());
+ setFilteredFiles(filtered);
+
+ // Auto-expand directories that contain matches
+ const expandMatches = (items) => {
+ items.forEach(item => {
+ if (item.type === 'directory' && item.children && item.children.length > 0) {
+ setExpandedDirs(prev => new Set(prev.add(item.path)));
+ expandMatches(item.children);
+ }
+ });
+ };
+ expandMatches(filtered);
+ }
+ }, [files, searchQuery]);
+
+ // Recursively filter files and directories based on search query
+ const filterFiles = (items, query) => {
+ return items.reduce((filtered, item) => {
+ const matchesName = item.name.toLowerCase().includes(query);
+ let filteredChildren = [];
+
+ if (item.type === 'directory' && item.children) {
+ filteredChildren = filterFiles(item.children, query);
+ }
+
+ // Include item if:
+ // 1. It matches the search query, or
+ // 2. It's a directory with matching children
+ if (matchesName || filteredChildren.length > 0) {
+ filtered.push({
+ ...item,
+ children: filteredChildren
+ });
+ }
+
+ return filtered;
+ }, []);
+ };
+
const fetchFiles = async () => {
setLoading(true);
try {
@@ -308,42 +356,67 @@ function FileTree({ selectedProject }) {
return (
- {/* View Mode Toggle */}
-
-
Files
-
-
-
-
+ {/* Header with Search and View Mode Toggle */}
+
+
+
Files
+
+
+
+
+
+
+
+ {/* Search Bar */}
+
+
+ setSearchQuery(e.target.value)}
+ className="pl-8 pr-8 h-8 text-sm"
+ />
+ {searchQuery && (
+
+ )}
{/* Column Headers for Detailed View */}
- {viewMode === 'detailed' && files.length > 0 && (
+ {viewMode === 'detailed' && filteredFiles.length > 0 && (
Name
@@ -365,11 +438,21 @@ function FileTree({ selectedProject }) {
Check if the project path is accessible
+ ) : filteredFiles.length === 0 && searchQuery ? (
+
+
+
+
+
No matches found
+
+ Try a different search term or clear the search
+
+
) : (
- {viewMode === 'simple' && renderFileTree(files)}
- {viewMode === 'compact' && renderCompactView(files)}
- {viewMode === 'detailed' && renderDetailedView(files)}
+ {viewMode === 'simple' && renderFileTree(filteredFiles)}
+ {viewMode === 'compact' && renderCompactView(filteredFiles)}
+ {viewMode === 'detailed' && renderDetailedView(filteredFiles)}
)}
diff --git a/src/components/Settings.jsx b/src/components/Settings.jsx
index 15884fe..4398cbc 100644
--- a/src/components/Settings.jsx
+++ b/src/components/Settings.jsx
@@ -1992,8 +1992,8 @@ function Settings({ isOpen, onClose, projects = [] }) {
{/* Login Modal */}
{showLoginModal && (
-
-
+
+
{loginProvider === 'claude' ? 'Claude CLI Login' : 'Cursor CLI Login'}