Implement client-side file scanning via Electron IPC with gitignore

- Add fs:scanDirectory IPC handler in main process
- Scan workspace recursively with proper gitignore support
- Use 'ignore' library for accurate gitignore pattern matching
- Expose scanDirectory via electronAPI in preload
- Call IPC from renderer instead of direct fs access
- Cache scanned files for fast filtering
- Scroll to top and highlight first item on results update
- Always exclude .git and node_modules directories
This commit is contained in:
Shantur Rathore
2025-10-24 10:10:12 +01:00
parent 6dcdd8294d
commit 1903bea1c8
4 changed files with 64 additions and 83 deletions

View File

@@ -1,6 +1,9 @@
import { ipcMain, BrowserWindow } from "electron"
import { processManager } from "./process-manager"
import { randomBytes } from "crypto"
import * as fs from "fs"
import * as path from "path"
import ignore from "ignore"
interface Instance {
id: string
@@ -80,4 +83,49 @@ export function setupInstanceIPC(mainWindow: BrowserWindow) {
ipcMain.handle("instance:list", async () => {
return Array.from(instances.values())
})
ipcMain.handle("fs:scanDirectory", async (event, workspaceFolder: string) => {
const ig = ignore()
ig.add([".git", "node_modules"])
const gitignorePath = path.join(workspaceFolder, ".gitignore")
if (fs.existsSync(gitignorePath)) {
const content = fs.readFileSync(gitignorePath, "utf-8")
ig.add(content)
}
function scanDir(dirPath: string, baseDir: string): string[] {
const results: string[] = []
try {
const entries = fs.readdirSync(dirPath, { withFileTypes: true })
for (const entry of entries) {
const fullPath = path.join(dirPath, entry.name)
const relativePath = path.relative(baseDir, fullPath)
if (ig.ignores(relativePath)) {
continue
}
if (entry.isDirectory()) {
const dirWithSlash = relativePath + "/"
if (!ig.ignores(dirWithSlash)) {
results.push(dirWithSlash)
const subFiles = scanDir(fullPath, baseDir)
results.push(...subFiles)
}
} else {
results.push(relativePath)
}
}
} catch (error) {
console.warn(`Error scanning ${dirPath}:`, error)
}
return results
}
return scanDir(workspaceFolder, workspaceFolder)
})
}

View File

@@ -14,6 +14,7 @@ export interface ElectronAPI {
}) => void,
) => void
onNewInstance: (callback: () => void) => void
scanDirectory: (workspaceFolder: string) => Promise<string[]>
}
const electronAPI: ElectronAPI = {
@@ -35,6 +36,7 @@ const electronAPI: ElectronAPI = {
onNewInstance: (callback) => {
ipcRenderer.on("menu:newInstance", () => callback())
},
scanDirectory: (workspaceFolder: string) => ipcRenderer.invoke("fs:scanDirectory", workspaceFolder),
}
contextBridge.exposeInMainWorld("electronAPI", electronAPI)