|
1 | | -const { app, BrowserWindow, ipcMain } = require('electron'); |
| 1 | +const { app, BrowserWindow, ipcMain, dialog } = require('electron'); |
2 | 2 | const { spawn } = require('child_process'); |
3 | 3 | const path = require('path'); |
4 | 4 | const readline = require('readline'); |
| 5 | +const fs = require('fs'); |
| 6 | +const fsp = require('fs/promises'); |
| 7 | +const os = require('os'); |
5 | 8 |
|
6 | 9 | let mainWindow; |
7 | 10 | let nodeProcess; |
@@ -150,6 +153,62 @@ ipcMain.on('console-log', (event, message) => { |
150 | 153 | console.log('Renderer:', message); |
151 | 154 | }); |
152 | 155 |
|
| 156 | +// Directory APIs |
| 157 | +ipcMain.handle('get-documents-dir', () => { |
| 158 | + return path.join(os.homedir(), 'Documents'); |
| 159 | +}); |
| 160 | + |
| 161 | +ipcMain.handle('get-app-data-dir', () => { |
| 162 | + // Returns app-specific data directory similar to Tauri's appLocalDataDir |
| 163 | + // Linux: ~/.local/share/<app-name>/ |
| 164 | + // macOS: ~/Library/Application Support/<app-name>/ |
| 165 | + // Windows: %APPDATA%/<app-name>/ |
| 166 | + return app.getPath('userData'); |
| 167 | +}); |
| 168 | + |
| 169 | +// Dialogs |
| 170 | +ipcMain.handle('show-open-dialog', async (event, options) => { |
| 171 | + const result = await dialog.showOpenDialog(mainWindow, options); |
| 172 | + return result.filePaths; |
| 173 | +}); |
| 174 | + |
| 175 | +ipcMain.handle('show-save-dialog', async (event, options) => { |
| 176 | + const result = await dialog.showSaveDialog(mainWindow, options); |
| 177 | + return result.filePath; |
| 178 | +}); |
| 179 | + |
| 180 | +// FS operations |
| 181 | +ipcMain.handle('fs-readdir', async (event, dirPath) => { |
| 182 | + const entries = await fsp.readdir(dirPath, { withFileTypes: true }); |
| 183 | + return entries.map(e => ({ name: e.name, isDirectory: e.isDirectory() })); |
| 184 | +}); |
| 185 | + |
| 186 | +ipcMain.handle('fs-stat', async (event, filePath) => { |
| 187 | + const stats = await fsp.stat(filePath); |
| 188 | + return { |
| 189 | + isFile: stats.isFile(), |
| 190 | + isDirectory: stats.isDirectory(), |
| 191 | + isSymbolicLink: stats.isSymbolicLink(), |
| 192 | + size: stats.size, |
| 193 | + mode: stats.mode, |
| 194 | + ctimeMs: stats.ctimeMs, |
| 195 | + atimeMs: stats.atimeMs, |
| 196 | + mtimeMs: stats.mtimeMs, |
| 197 | + nlink: stats.nlink, |
| 198 | + dev: stats.dev |
| 199 | + }; |
| 200 | +}); |
| 201 | + |
| 202 | +ipcMain.handle('fs-mkdir', (event, dirPath, options) => fsp.mkdir(dirPath, options)); |
| 203 | +ipcMain.handle('fs-unlink', (event, filePath) => fsp.unlink(filePath)); |
| 204 | +ipcMain.handle('fs-rmdir', (event, dirPath, options) => fsp.rm(dirPath, options)); |
| 205 | +ipcMain.handle('fs-rename', (event, oldPath, newPath) => fsp.rename(oldPath, newPath)); |
| 206 | +ipcMain.handle('fs-read-file', async (event, filePath) => { |
| 207 | + const buffer = await fsp.readFile(filePath); |
| 208 | + return buffer; // Electron serializes Buffer automatically |
| 209 | +}); |
| 210 | +ipcMain.handle('fs-write-file', (event, filePath, data) => fsp.writeFile(filePath, Buffer.from(data))); |
| 211 | + |
153 | 212 | function waitForTrue(fn, timeout) { |
154 | 213 | return new Promise((resolve) => { |
155 | 214 | const startTime = Date.now(); |
|
0 commit comments