feat: v1.2.0 搜索替换 + 文件树侧边栏

This commit is contained in:
thzxx
2026-05-21 11:37:02 +08:00
parent c773a0d8e6
commit 543af93802
7 changed files with 797 additions and 2 deletions
+82
View File
@@ -305,6 +305,88 @@ ipcMain.handle('file:reload', async () => {
}
});
// ===== File Tree (Sidebar) =====
const SKIP_DIRS = new Set(['node_modules', '.git', '.svn', '.hg', 'dist', 'out', '.next', '.nuxt', '__pycache__', '.DS_Store']);
const MARKDOWN_EXTS = new Set(['.md', '.markdown', '.txt']);
async function buildDirTree(dirPath) {
const entries = await fs.promises.readdir(dirPath, { withFileTypes: true });
// Sort: directories first, then files, alphabetically
entries.sort((a, b) => {
if (a.isDirectory() && !b.isDirectory()) return -1;
if (!a.isDirectory() && b.isDirectory()) return 1;
return a.name.localeCompare(b.name);
});
const children = [];
for (const entry of entries) {
if (SKIP_DIRS.has(entry.name)) continue;
if (entry.name.startsWith('.')) continue;
const childPath = path.join(dirPath, entry.name);
if (entry.isDirectory()) {
const subChildren = await buildDirTree(childPath);
if (subChildren.length > 0) {
children.push({ name: entry.name, path: childPath, type: 'dir', children: subChildren });
}
} else {
const ext = path.extname(entry.name).toLowerCase();
if (MARKDOWN_EXTS.has(ext)) {
children.push({ name: entry.name, path: childPath, type: 'file' });
}
}
}
return children;
}
ipcMain.handle('dir:readTree', async (event, dirPath) => {
try {
const tree = await buildDirTree(dirPath);
return { success: true, tree, rootPath: dirPath };
} catch (err) {
return { success: false, error: err.message };
}
});
let sidebarWatcher = null;
let sidebarWatchPath = null;
function startSidebarWatching(dirPath) {
stopSidebarWatching();
if (!dirPath) return;
try {
sidebarWatchPath = dirPath;
sidebarWatcher = fs.watch(dirPath, { recursive: true }, (eventType, filename) => {
if (mainWindow && !mainWindow.isDestroyed()) {
mainWindow.webContents.send('sidebar:dirChanged');
}
});
} catch (err) { /* ignore */ }
}
function stopSidebarWatching() {
if (sidebarWatcher) { sidebarWatcher.close(); sidebarWatcher = null; }
sidebarWatchPath = null;
}
ipcMain.handle('dir:watch', (event, dirPath) => {
startSidebarWatching(dirPath);
});
ipcMain.handle('dir:unwatch', () => {
stopSidebarWatching();
});
ipcMain.handle('dir:openDialog', async () => {
const result = await dialog.showOpenDialog(mainWindow, {
properties: ['openDirectory']
});
if (!result.canceled && result.filePaths.length > 0) {
return result.filePaths[0];
}
return null;
});
// Tab switched - update active file tracking
ipcMain.handle('tab:switched', (event, filePath) => {
switchActiveFile(filePath);