1
0
mirror of synced 2026-10-23 07:08:55 +03:00

Restore remembering the last visited directory in Desktop file dialogs. #10226 (#10327)

Electron 43 deliberately stopped remembering the last folder used by the
native open and save dialogs, so they always opened in Downloads. Track the
last visited directory in the runtime's config store and pass it as
defaultPath whenever the caller has not specified a location.
This commit is contained in:
Dave Page
2026-10-12 17:17:52 +01:00
parent b3a941c469
commit 7c974c005c

View File

@@ -478,9 +478,60 @@ function notifyUpdateInstalled() {
}
}
// Native file dialogs don't reliably remember the last used directory across
// calls, so we track it ourselves and use it as the default when the caller
// hasn't asked for a specific location.
async function withLastVisitedDirectory(options) {
if (options.defaultPath) {
return options;
}
const lastVisitedDirectory = configStore.get('lastVisitedDirectory');
if (!lastVisitedDirectory) {
return options;
}
try {
const stats = await fs.promises.stat(lastVisitedDirectory);
if (stats.isDirectory()) {
return { ...options, defaultPath: lastVisitedDirectory };
}
} catch {
// Remembered directory no longer exists (e.g. removable/network drive) - fall through.
}
return options;
}
function rememberVisitedDirectory(options, result) {
const chosenPath = result.filePath || result.filePaths?.[0];
if (!chosenPath) {
return;
}
const isDirectory = options.properties?.includes('openDirectory');
try {
configStore.set('lastVisitedDirectory', isDirectory ? chosenPath : path.dirname(chosenPath));
} catch (error) {
try {
misc.writeServerLog(`Error remembering last visited directory: ${error}`);
} catch (logError) {
console.error('Error remembering last visited directory:', error, logError);
}
}
}
// setup preload events.
ipcMain.handle('showOpenDialog', (e, options) => dialog.showOpenDialog(BrowserWindow.fromWebContents(e.sender), options));
ipcMain.handle('showSaveDialog', (e, options) => dialog.showSaveDialog(BrowserWindow.fromWebContents(e.sender), options));
ipcMain.handle('showOpenDialog', async (e, options) => {
const result = await dialog.showOpenDialog(BrowserWindow.fromWebContents(e.sender), await withLastVisitedDirectory(options));
if (!result.canceled) {
rememberVisitedDirectory(options, result);
}
return result;
});
ipcMain.handle('showSaveDialog', async (e, options) => {
const result = await dialog.showSaveDialog(BrowserWindow.fromWebContents(e.sender), await withLastVisitedDirectory(options));
if (!result.canceled) {
rememberVisitedDirectory(options, result);
}
return result;
});
ipcMain.handle('showMessageBox', (e, options) => dialog.showMessageBox(BrowserWindow.fromWebContents(e.sender), options));
ipcMain.handle('getStoreData', (_e, key) => key ? configStore.get(key) : configStore.store);
ipcMain.handle('setStoreData', (_e, newValues) => {