diff --git a/lib/folder-monitor.js b/lib/folder-monitor.js index 6fde2ca..1c6914f 100644 --- a/lib/folder-monitor.js +++ b/lib/folder-monitor.js @@ -35,6 +35,11 @@ class FolderMonitor extends EventEmitter { this._watcher = chokidar.watch(folderPath, watchOptions); this._watcher.on('add', (filePath) => this._onNewFile(filePath)); + this._watcher.on('unlink', (filePath) => { + // Allow re-added files (e.g. re-encoded) to be detected again + const normalized = filePath.replace(/\\/g, '/').toLowerCase(); + this._seenFiles.delete(normalized); + }); this._watcher.on('error', (err) => this.emit('error', err)); } diff --git a/main.js b/main.js index cef8d0c..8f5c539 100644 --- a/main.js +++ b/main.js @@ -883,11 +883,22 @@ ipcMain.handle('save-global-settings', async (_event, globalSettings) => { }); // Synchronous save for beforeunload — blocks renderer until write completes +// Uses atomic write pattern (tmp + backup + rename) to prevent corruption ipcMain.on('save-global-settings-sync', (event, globalSettings) => { try { const current = configStore.load(); current.globalSettings = globalSettings; - fs.writeFileSync(configStore.filePath, JSON.stringify(current, null, 2)); + const data = JSON.stringify(current, null, 2); + const tmpPath = configStore.filePath + '.tmp'; + const backupPath = configStore.filePath + '.bak'; + fs.writeFileSync(tmpPath, data, 'utf-8'); + if (fs.existsSync(configStore.filePath)) { + const existing = fs.readFileSync(configStore.filePath, 'utf-8'); + if (existing && existing.trim().length > 2) { + fs.writeFileSync(backupPath, existing, 'utf-8'); + } + } + fs.renameSync(tmpPath, configStore.filePath); } catch {} event.returnValue = true; });