import * as fs from 'fs' import { BrowserWindow } from 'electron' export class FileWatcher { private watcher: fs.FSWatcher | null = null private currentPath: string | null = null private isSelfWriting = false constructor(private getMainWindow: () => BrowserWindow | null) {} start(filePath: string): void { this.stop() if (!filePath) return try { this.currentPath = filePath this.watcher = fs.watch(filePath, (eventType) => { if (eventType === 'change') { if (this.isSelfWriting) return const win = this.getMainWindow() if (win && !win.isDestroyed()) { win.webContents.send('file:externallyModified', filePath) } } }) // L-02: 监听 error 事件,文件被删除时显式关闭并清理状态 this.watcher.on('error', () => { if (this.watcher) { this.watcher.close() this.watcher = null } this.currentPath = null this.isSelfWriting = false }) } catch { // silently ignore } } stop(): void { if (this.watcher) { this.watcher.close() this.watcher = null } this.currentPath = null } getCurrentPath(): string | null { return this.currentPath } setSelfWriting(value: boolean): void { this.isSelfWriting = value } } export class SidebarWatcher { private watcher: fs.FSWatcher | null = null private watchPath: string | null = null private refreshTimer: NodeJS.Timeout | null = null constructor(private getMainWindow: () => BrowserWindow | null) {} start(dirPath: string): void { this.stop() if (!dirPath) return try { this.watchPath = dirPath this.watcher = fs.watch(dirPath, { recursive: true }, () => { const win = this.getMainWindow() if (win && !win.isDestroyed()) { if (this.refreshTimer) clearTimeout(this.refreshTimer) this.refreshTimer = setTimeout(() => { // M-03: 延迟后再次检查窗口状态 const w = this.getMainWindow() if (w && !w.isDestroyed()) { w.webContents.send('sidebar:dirChanged') } }, 300) } }) // L-02: 监听 error 事件,显式关闭 this.watcher.on('error', () => { if (this.watcher) { this.watcher.close() this.watcher = null } this.watchPath = null }) } catch { // silently ignore } } stop(): void { if (this.watcher) { this.watcher.close() this.watcher = null } if (this.refreshTimer) { clearTimeout(this.refreshTimer) this.refreshTimer = null } this.watchPath = null } }