From a0ccd311ebdfd8afb64098461390aa8af70c8155 Mon Sep 17 00:00:00 2001 From: salman Date: Fri, 9 Oct 2026 12:52:23 +0200 Subject: [PATCH] Remember one shared folder for all file dialogs All native file dialogs (Plot Profiles/Fractions/Mean, Open, Save Folder, Save As, and the in-page browse button) now reopen in the single folder last used by any of them, persisted in userData/dialog-folders.json across restarts, falling back to the work path. Replaces the earlier per-dialog-type memory. --- main.js | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/main.js b/main.js index 0310641..9abb208 100644 --- a/main.js +++ b/main.js @@ -183,6 +183,48 @@ function getDefaultDialogPath() { return currentWorkPath || process.cwd(); } +// Remember the folder in which the last file dialog opened or saved, so the +// dialogs reopen where the user actually works rather than at an OS default +// (or always at process.cwd()). Shared by every dialog type, stored in the +// app's userData dir, and durable across restarts; falls back to the current +// work path. +const DIALOG_FOLDERS_FILE = path.join(app.getPath('userData'), 'dialog-folders.json'); +let dialogFolders = null; + +function loadDialogFolders() { + if (dialogFolders === null) { + try { + dialogFolders = JSON.parse(fs.readFileSync(DIALOG_FOLDERS_FILE, 'utf8')); + } catch (err) { + dialogFolders = {}; + } + } + return dialogFolders; +} + +function rememberLastDialogFolder(folder) { + if (!folder) return; + loadDialogFolders(); + dialogFolders.lastUsed = folder; + try { + fs.writeFileSync(DIALOG_FOLDERS_FILE, JSON.stringify(dialogFolders, null, 2)); + } catch (err) { + console.log('could not save dialog folder memory:', err); + } +} + +function rememberLastDialogFolderFromFiles(filePaths) { + if (!filePaths || filePaths.length === 0) return; + rememberLastDialogFolder(path.dirname(filePaths[0])); +} + +function lastDialogFolder() { + const fallback = getDefaultDialogPath(); + const saved = loadDialogFolders().lastUsed; + if (saved && fs.existsSync(saved)) return saved; + return fallback; +} + function getWindowIconPath() { if (app.isPackaged) { return path.join(process.resourcesPath, 'app.asar', 'icon.png'); @@ -253,7 +295,7 @@ function createWindow () { click () { dialog.showOpenDialog(win, { title : "Load configuration file", - defaultPath : getDefaultDialogPath(), + defaultPath : lastDialogFolder(), //buttonLabel : "Custom button", filters :[ {name: 'Config file type', extensions: ['cfg']}, @@ -263,6 +305,7 @@ function createWindow () { console.log(result.canceled); console.log(result.filePaths); if (!result.canceled) { + rememberLastDialogFolderFromFiles(result.filePaths); setImmediate(function() { var focusedWindow = win; focusedWindow.webContents.send('openFile',result.filePaths); @@ -279,11 +322,14 @@ function createWindow () { click () { dialog.showOpenDialog(win, { title: "Select folder", - defaultPath : getDefaultDialogPath(), + defaultPath : lastDialogFolder(), properties:["openDirectory"]} ).then(result => { setImmediate(function() { console.log(result.filePaths) + if (!result.canceled) { + rememberLastDialogFolder(result.filePaths[0]); + } var focusedWindow = win; focusedWindow.webContents.send('selectFolder',result.filePaths); }); @@ -308,7 +354,7 @@ function createWindow () { click () { dialog.showSaveDialog(win, { title : "Save configuration file", - defaultPath : path.join(getDefaultDialogPath(), 'TrimSP.cfg'), + defaultPath : path.join(lastDialogFolder(), 'TrimSP.cfg'), filters :[ {name: 'Config file type', extensions: ['cfg']}, {name: 'All Files', extensions: ['*']} @@ -318,6 +364,7 @@ function createWindow () { if (result.canceled || !result.filePath) { return; } + rememberLastDialogFolder(path.dirname(result.filePath)); setImmediate(function() { var focusedWindow = win; focusedWindow.webContents.send('saveFile',result.filePath); @@ -357,6 +404,7 @@ function createWindow () { click () { dialog.showOpenDialog(win, { title : "Select rge files", + defaultPath : lastDialogFolder(), filters :[ {name: 'Profile file type', extensions: ['rge']}, {name: 'All Files', extensions: ['*']} @@ -366,6 +414,7 @@ function createWindow () { console.log(result.canceled); console.log(result.filePaths); if (!result.canceled) { + rememberLastDialogFolderFromFiles(result.filePaths); setImmediate(function() { var focusedWindow = win; focusedWindow.webContents.send('plotProf',result.filePaths); @@ -382,6 +431,7 @@ function createWindow () { click () { dialog.showOpenDialog(win, { title : "Select sequence file", + defaultPath : lastDialogFolder(), filters :[ {name: 'Sequence file type', extensions: ['dat']}, {name: 'All Files', extensions: ['*']} @@ -391,6 +441,7 @@ function createWindow () { console.log(result.canceled); console.log(result.filePaths); if (!result.canceled) { + rememberLastDialogFolderFromFiles(result.filePaths); setImmediate(function() { var focusedWindow = win; focusedWindow.webContents.send('plotFrac',result.filePaths); @@ -407,6 +458,7 @@ function createWindow () { click () { dialog.showOpenDialog(win, { title : "Select sequence file", + defaultPath : lastDialogFolder(), filters :[ {name: 'Sequence file type', extensions: ['dat']}, {name: 'All Files', extensions: ['*']} @@ -416,6 +468,7 @@ function createWindow () { console.log(result.canceled); console.log(result.filePaths); if (!result.canceled) { + rememberLastDialogFolderFromFiles(result.filePaths); setImmediate(function() { var focusedWindow = win; focusedWindow.webContents.send('plotMean',result.filePaths); @@ -475,7 +528,7 @@ ipcMain.on('browseFolder', (event, args) => { console.log('received a message: '+args); const senderWindow = BrowserWindow.fromWebContents(event.sender); dialog.showOpenDialog(senderWindow, { title: "Select folder", - defaultPath : getDefaultDialogPath(), + defaultPath : lastDialogFolder(), properties:["openDirectory"]} ).then(result => { console.log(result) @@ -483,6 +536,7 @@ ipcMain.on('browseFolder', (event, args) => { event.reply('browseFolderFallback'); return; } + rememberLastDialogFolder(result.filePaths[0]); event.reply('browseFolder', result.filePaths); app.setPath('temp',result.filePaths[0]); }).catch(err => {