import { app, BrowserWindow, clipboard, dialog, ipcMain, shell } from 'electron' import * as path from 'node:path' import * as fssync from 'node:fs' import { getDrivesWin, listDirectory, computeFolderSize, findLargeFiles, getProcessesWin, getServicesWin, getInstalledPrograms, getSystemSnapshot, getNetworkInterfaces, getEnvSnapshot, getStartupFolders, getTempAudit, getScheduledTasksSummary, openPathInExplorer, killProcess, getWindowsFeaturesSnippet, } from './audit' import { startPythonBackend, stopPythonBackend } from './pythonBackend' const isDev = !!process.env.VITE_DEV_SERVER_URL function notesPath() { return path.join(app.getPath('userData'), 'auditor-notes.json') } function loadNotes(): Record { try { const raw = fssync.readFileSync(notesPath(), 'utf8') return JSON.parse(raw) as Record } catch { return {} } } function saveNotes(n: Record) { fssync.mkdirSync(path.dirname(notesPath()), { recursive: true }) fssync.writeFileSync(notesPath(), JSON.stringify(n, null, 2), 'utf8') } function createWindow() { const win = new BrowserWindow({ width: 1280, height: 800, minWidth: 960, minHeight: 640, backgroundColor: '#0d0f12', titleBarStyle: process.platform === 'darwin' ? 'hiddenInset' : 'default', webPreferences: { preload: path.join(__dirname, 'preload.js'), contextIsolation: true, nodeIntegration: false, sandbox: false, }, }) if (isDev) { win.loadURL(process.env.VITE_DEV_SERVER_URL!) } else { win.loadFile(path.join(__dirname, '../dist/index.html')) } } app.whenReady().then(async () => { try { await startPythonBackend() } catch (e) { dialog.showErrorBox( 'Python backend required', `${String(e)}\n\nInstall: cd backend && pip install -r requirements.txt` ) app.quit() return } ipcMain.handle('audit:drives', () => getDrivesWin()) ipcMain.handle('audit:listDir', (_e, dirPath: string, opts?: { maxEntries?: number }) => listDirectory(dirPath, opts ?? {}) ) ipcMain.handle('audit:folderSize', (_e, dirPath: string) => computeFolderSize(dirPath)) ipcMain.handle('audit:largeFiles', (_e, rootPath: string, minBytes: number, maxResults: number) => findLargeFiles(rootPath, minBytes, maxResults) ) ipcMain.handle('audit:processes', () => getProcessesWin()) ipcMain.handle('audit:services', () => getServicesWin()) ipcMain.handle('audit:installed', () => getInstalledPrograms()) ipcMain.handle('audit:system', () => getSystemSnapshot()) ipcMain.handle('audit:network', () => getNetworkInterfaces()) ipcMain.handle('audit:env', (_e, keys?: string[]) => getEnvSnapshot(keys)) ipcMain.handle('audit:startup', () => getStartupFolders()) ipcMain.handle('audit:temp', () => getTempAudit()) ipcMain.handle('audit:tasks', () => getScheduledTasksSummary()) ipcMain.handle('audit:features', () => getWindowsFeaturesSnippet()) ipcMain.handle('audit:openExplorer', (_e, p: string) => openPathInExplorer(p)) ipcMain.handle('audit:killProcess', (_e, pid: number) => killProcess(pid)) ipcMain.handle('audit:openExternal', (_e, url: string) => shell.openExternal(url)) ipcMain.handle('clipboard:writeText', (_e, text: string) => { clipboard.writeText(text) }) ipcMain.handle('notes:getAll', () => loadNotes()) ipcMain.handle('notes:set', (_e, key: string, value: string) => { const all = loadNotes() if (value.trim() === '') delete all[key] else all[key] = value saveNotes(all) return all }) ipcMain.handle('notes:delete', (_e, key: string) => { const all = loadNotes() delete all[key] saveNotes(all) return all }) createWindow() app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) createWindow() }) }) app.on('window-all-closed', () => { if (process.platform !== 'darwin') app.quit() }) app.on('before-quit', () => { stopPythonBackend() })