feat(webui): add search functionality to file browser#1228
feat(webui): add search functionality to file browser#1228Audionut merged 3 commits intoAudionut:masterfrom
Conversation
📝 WalkthroughWalkthroughA file browser search feature was added: a backend Changes
Sequence DiagramsequenceDiagram
actor User
participant Frontend as Frontend (React)
participant Server as API Server (/api/browse_search)
participant FS as File System (os.walk)
User->>Frontend: Type search query
Note over Frontend: Debounce 300ms, set loading
Frontend->>Server: POST query + auth token
Server->>Server: Validate auth, CSRF, same-origin
Server->>Server: Tokenize query with _BROWSE_SEARCH_SEP_RE
Server->>FS: Recursively traverse configured browse roots
FS-->>Server: Return directories & files
Server->>Server: Match ordered whole-word subsequences, filter extensions, perform path safety checks
Server->>Server: Sort results (folders first), truncate if needed
Server-->>Frontend: Return JSON (results, count, truncated)
Frontend->>Frontend: Verify query still current, clear loading, render results
Frontend-->>User: Display matching files/folders
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@web_ui/static/js/app.js`:
- Around line 786-788: The display logic that computes the parent path uses
item.path.lastIndexOf('/') and thus misses Windows backslashes; update the
separator computation in the code that sets separatorIdx/parentPath (referencing
item.path, separatorIdx, parentPath) to consider both separators (e.g., take
Math.max(item.path.lastIndexOf('/'), item.path.lastIndexOf('\\'))), then keep
the existing substring logic so parentPath is correctly derived on Windows and
POSIX paths.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@web_ui/static/js/app.js`:
- Around line 752-773: The search handler should check response.ok before
calling response.json and handle non-2xx responses by setting an empty result
(using setFileBrowserSearchResults) and avoiding parsing errors; update the
async callback in the setTimeout to inspect response.ok and branch to the same
error/result-handling path used on catches, preserving the early-return that
compares fileBrowserSearchQuery.current to searchQuery. Also add a component
cleanup effect (useEffect with a return cleanup) that clears the pending timeout
stored in fileBrowserSearchTimer.current on unmount so the delayed callback
cannot call setFileBrowserSearchResults or setFileBrowserSearchLoading after the
component is unmounted. Ensure you reference/modify the existing
fileBrowserSearchTimer.current, fileBrowserSearchQuery.current,
setFileBrowserSearchResults and setFileBrowserSearchLoading symbols.
| fileBrowserSearchTimer.current = setTimeout(async () => { | ||
| try { | ||
| const response = await apiFetch(`${API_BASE}/browse_search?q=${encodeURIComponent(searchQuery)}`); | ||
| const data = await response.json(); | ||
| // Early return if the search has changed since this request | ||
| if (fileBrowserSearchQuery.current !== searchQuery) return; | ||
| if (data.success) { | ||
| setFileBrowserSearchResults(data); | ||
| } else { | ||
| setFileBrowserSearchResults({ items: [], query: searchQuery, count: 0 }); | ||
| } | ||
| } catch (error) { | ||
| console.error('File browser search failed:', error); | ||
| if (fileBrowserSearchQuery.current === searchQuery) { | ||
| setFileBrowserSearchResults({ items: [], query: searchQuery, count: 0 }); | ||
| } | ||
| } finally { | ||
| if (fileBrowserSearchQuery.current === searchQuery) { | ||
| setFileBrowserSearchLoading(false); | ||
| } | ||
| } | ||
| }, 300); //300ms debounce so we dont spam requests for every keystroke |
There was a problem hiding this comment.
Missing response.ok check before parsing JSON.
If the server returns a non-2xx status (e.g. 500), response.json() will either throw a parse error on an HTML error page or silently yield unexpected data. Check response.ok before parsing, similar to how executeCommand handles it (line 1009).
Additionally, the debounce timer stored in fileBrowserSearchTimer.current is never cleaned up on component unmount. If the component unmounts mid-debounce, the callback fires and calls setFileBrowserSearchResults / setFileBrowserSearchLoading on an unmounted component.
Proposed fix
Add a response.ok guard:
const response = await apiFetch(`${API_BASE}/browse_search?q=${encodeURIComponent(searchQuery)}`);
+ if (!response.ok) {
+ throw new Error(`Search request failed (${response.status})`);
+ }
const data = await response.json();Add a cleanup effect near the other search state declarations:
useEffect(() => {
return () => {
if (fileBrowserSearchTimer.current) {
clearTimeout(fileBrowserSearchTimer.current);
}
};
}, []);🤖 Prompt for AI Agents
In `@web_ui/static/js/app.js` around lines 752 - 773, The search handler should
check response.ok before calling response.json and handle non-2xx responses by
setting an empty result (using setFileBrowserSearchResults) and avoiding parsing
errors; update the async callback in the setTimeout to inspect response.ok and
branch to the same error/result-handling path used on catches, preserving the
early-return that compares fileBrowserSearchQuery.current to searchQuery. Also
add a component cleanup effect (useEffect with a return cleanup) that clears the
pending timeout stored in fileBrowserSearchTimer.current on unmount so the
delayed callback cannot call setFileBrowserSearchResults or
setFileBrowserSearchLoading after the component is unmounted. Ensure you
reference/modify the existing fileBrowserSearchTimer.current,
fileBrowserSearchQuery.current, setFileBrowserSearchResults and
setFileBrowserSearchLoading symbols.
This PR adds search functionality to the file browser in the web UI sidebar.
Some key points:
Summary by CodeRabbit