From 2527596e59f822660f6f4c81fa5d1b1fead215a9 Mon Sep 17 00:00:00 2001 From: Mark Sujew Date: Tue, 19 Dec 2023 16:53:57 +0100 Subject: [PATCH] Save untitled files to the last active folder (#13184) --- .../browser/frontend-application-module.ts | 1 + .../user-working-directory-provider.ts | 35 +++++++++++++++++-- .../file-dialog/file-dialog-service.ts | 6 ++-- ...rkspace-user-working-directory-provider.ts | 1 + 4 files changed, 38 insertions(+), 5 deletions(-) diff --git a/packages/core/src/browser/frontend-application-module.ts b/packages/core/src/browser/frontend-application-module.ts index 45e83b311720e..ca1bb7f3ab971 100644 --- a/packages/core/src/browser/frontend-application-module.ts +++ b/packages/core/src/browser/frontend-application-module.ts @@ -445,6 +445,7 @@ export const frontendApplicationModule = new ContainerModule((bind, _unbind, _is bind(SaveResourceService).toSelf().inSingletonScope(); bind(UserWorkingDirectoryProvider).toSelf().inSingletonScope(); + bind(FrontendApplicationContribution).toService(UserWorkingDirectoryProvider); bind(HoverService).toSelf().inSingletonScope(); diff --git a/packages/core/src/browser/user-working-directory-provider.ts b/packages/core/src/browser/user-working-directory-provider.ts index 002ed8e4bf475..ccc9c63a14bc5 100644 --- a/packages/core/src/browser/user-working-directory-provider.ts +++ b/packages/core/src/browser/user-working-directory-provider.ts @@ -16,14 +16,34 @@ import { inject, injectable } from 'inversify'; import URI from '../common/uri'; -import { MaybePromise, SelectionService, UriSelection } from '../common'; +import { MaybePromise, SelectionService, UNTITLED_SCHEME, UriSelection } from '../common'; import { EnvVariablesServer } from '../common/env-variables'; +import { FrontendApplication } from './frontend-application'; +import { FrontendApplicationContribution } from './frontend-application-contribution'; +import { Widget } from './widgets'; +import { Navigatable } from './navigatable-types'; @injectable() -export class UserWorkingDirectoryProvider { +export class UserWorkingDirectoryProvider implements FrontendApplicationContribution { @inject(SelectionService) protected readonly selectionService: SelectionService; @inject(EnvVariablesServer) protected readonly envVariables: EnvVariablesServer; + protected lastOpenResource: URI | undefined; + + configure(app: FrontendApplication): void { + app.shell.onDidChangeCurrentWidget(e => this.setLastOpenResource(e.newValue ?? undefined)); + this.setLastOpenResource(app.shell.currentWidget); + } + + protected setLastOpenResource(widget?: Widget): void { + if (Navigatable.is(widget)) { + const uri = widget.getResourceUri(); + if (uri && uri.scheme !== UNTITLED_SCHEME) { + this.lastOpenResource = uri; + } + } + } + /** * @returns A {@link URI} that represents a good guess about the directory in which the user is currently operating. * @@ -35,7 +55,16 @@ export class UserWorkingDirectoryProvider { } protected getFromSelection(): MaybePromise { - return this.ensureIsDirectory(UriSelection.getUri(this.selectionService.selection)); + const uri = UriSelection.getUri(this.selectionService.selection); + if (uri?.scheme === UNTITLED_SCHEME) { + // An untitled file is not a valid working directory context. + return undefined; + } + return this.ensureIsDirectory(uri); + } + + protected getFromLastOpenResource(): MaybePromise { + return this.ensureIsDirectory(this.lastOpenResource); } protected getFromUserHome(): MaybePromise { diff --git a/packages/filesystem/src/browser/file-dialog/file-dialog-service.ts b/packages/filesystem/src/browser/file-dialog/file-dialog-service.ts index a6c9f8ce28565..afc42899c64db 100644 --- a/packages/filesystem/src/browser/file-dialog/file-dialog-service.ts +++ b/packages/filesystem/src/browser/file-dialog/file-dialog-service.ts @@ -16,7 +16,7 @@ import { injectable, inject } from '@theia/core/shared/inversify'; import URI from '@theia/core/lib/common/uri'; -import { MaybeArray, nls } from '@theia/core/lib/common'; +import { MaybeArray, UNTITLED_SCHEME, nls } from '@theia/core/lib/common'; import { LabelProvider } from '@theia/core/lib/browser'; import { FileStat } from '../../common/files'; import { DirNode } from '../file-tree'; @@ -81,7 +81,9 @@ export class DefaultFileDialogService implements FileDialogService { } protected async getRootNode(folderToOpen?: FileStat): Promise { - const folderExists = folderToOpen && await this.fileService.exists(folderToOpen.resource); + const folderExists = folderToOpen + && folderToOpen.resource.scheme !== UNTITLED_SCHEME + && await this.fileService.exists(folderToOpen.resource); const folder = folderToOpen && folderExists ? folderToOpen : { resource: await this.rootProvider.getUserWorkingDir(), isDirectory: true diff --git a/packages/workspace/src/browser/workspace-user-working-directory-provider.ts b/packages/workspace/src/browser/workspace-user-working-directory-provider.ts index 26d4121f7add8..af8f69d2a2cb5 100644 --- a/packages/workspace/src/browser/workspace-user-working-directory-provider.ts +++ b/packages/workspace/src/browser/workspace-user-working-directory-provider.ts @@ -28,6 +28,7 @@ export class WorkspaceUserWorkingDirectoryProvider extends UserWorkingDirectoryP override async getUserWorkingDir(): Promise { return await this.getFromSelection() + ?? await this.getFromLastOpenResource() ?? await this.getFromWorkspace() ?? this.getFromUserHome(); }