From 985de26b3446636f86e2bb2b14dbeb9ec1e33207 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Tue, 18 Jun 2019 13:47:40 +0200 Subject: [PATCH] Add availableFileSystems to save as (#75681) This adds the suggested filename to the local path --- .../browser/actions/workspaceActions.ts | 14 +++++++++--- .../dialogs/browser/remoteFileDialog.ts | 22 +++++++++---------- .../textfile/common/textFileService.ts | 11 +++++----- .../services/textfile/common/textfiles.ts | 1 + 4 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/vs/workbench/browser/actions/workspaceActions.ts b/src/vs/workbench/browser/actions/workspaceActions.ts index 2c7298ebcdd..68fe0859f59 100644 --- a/src/vs/workbench/browser/actions/workspaceActions.ts +++ b/src/vs/workbench/browser/actions/workspaceActions.ts @@ -17,6 +17,9 @@ import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { Schemas } from 'vs/base/common/network'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; +import { ITextFileService, ISaveOptions } from 'vs/workbench/services/textfile/common/textfiles'; +import { toResource } from 'vs/workbench/common/editor'; +import { URI } from 'vs/base/common/uri'; export class OpenFileAction extends Action { @@ -62,13 +65,18 @@ export class SaveLocalFileAction extends Action { constructor( id: string, label: string, - @IFileDialogService private readonly dialogService: IFileDialogService + @ITextFileService private readonly textFileService: ITextFileService, + @IEditorService private readonly editorService: IEditorService ) { super(id, label); } - run(event?: any, data?: ITelemetryData): Promise { - return this.dialogService.pickFileToSave({ availableFileSystems: [Schemas.file] }); + async run(event?: any, data?: ITelemetryData): Promise { + let resource: URI | undefined = toResource(this.editorService.activeEditor); + const options: ISaveOptions = { force: true, availableFileSystems: [Schemas.file] }; + if (resource) { + return this.textFileService.saveAs(resource, undefined, options); + } } } diff --git a/src/vs/workbench/services/dialogs/browser/remoteFileDialog.ts b/src/vs/workbench/services/dialogs/browser/remoteFileDialog.ts index 06ae69f7b9c..73aa2adcd4e 100644 --- a/src/vs/workbench/services/dialogs/browser/remoteFileDialog.ts +++ b/src/vs/workbench/services/dialogs/browser/remoteFileDialog.ts @@ -98,7 +98,7 @@ export class RemoteFileDialog { } public async showOpenDialog(options: IOpenDialogOptions = {}): Promise { - this.scheme = this.getScheme(options.defaultUri, options.availableFileSystems); + this.scheme = this.getScheme(options.availableFileSystems); this.userHome = await this.getUserHome(); const newOptions = await this.getOptions(options); if (!newOptions) { @@ -109,7 +109,7 @@ export class RemoteFileDialog { } public async showSaveDialog(options: ISaveDialogOptions): Promise { - this.scheme = this.getScheme(options.defaultUri, options.availableFileSystems); + this.scheme = this.getScheme(options.availableFileSystems); this.userHome = await this.getUserHome(); this.requiresTrailing = true; const newOptions = await this.getOptions(options, true); @@ -128,9 +128,13 @@ export class RemoteFileDialog { } private getOptions(options: ISaveDialogOptions | IOpenDialogOptions, isSave: boolean = false): IOpenDialogOptions | undefined { - let defaultUri = options.defaultUri; - const filename = (defaultUri && isSave && (resources.dirname(defaultUri).path === '/')) ? resources.basename(defaultUri) : undefined; - if (!defaultUri || filename) { + let defaultUri: URI | undefined = undefined; + let filename: string | undefined = undefined; + if (options.defaultUri) { + defaultUri = (this.scheme === options.defaultUri.scheme) ? options.defaultUri : undefined; + filename = isSave ? resources.basename(options.defaultUri) : undefined; + } + if (!defaultUri) { defaultUri = this.userHome; if (filename) { defaultUri = resources.joinPath(defaultUri, filename); @@ -150,8 +154,8 @@ export class RemoteFileDialog { return resources.toLocalResource(URI.from({ scheme: this.scheme, path }), this.scheme === Schemas.file ? undefined : this.remoteAuthority); } - private getScheme(defaultUri: URI | undefined, available: string[] | undefined): string { - return defaultUri ? defaultUri.scheme : (available ? available[0] : Schemas.file); + private getScheme(available: string[] | undefined): string { + return available ? available[0] : Schemas.file; } private async getRemoteAgentEnvironment(): Promise { @@ -254,12 +258,8 @@ export class RemoteFileDialog { if (this.options.availableFileSystems && (this.options.availableFileSystems.length > 1)) { this.options.availableFileSystems.shift(); } - this.options.defaultUri = undefined; this.filePickBox.hide(); if (isSave) { - // Remove defaultUri and filters to get a consistant experience with the keybinding. - this.options.defaultUri = undefined; - this.options.filters = undefined; return this.fileDialogService.showSaveDialog(this.options).then(result => { doResolve(this, result); }); diff --git a/src/vs/workbench/services/textfile/common/textFileService.ts b/src/vs/workbench/services/textfile/common/textFileService.ts index 4c092ee588b..b5e83926419 100644 --- a/src/vs/workbench/services/textfile/common/textFileService.ts +++ b/src/vs/workbench/services/textfile/common/textFileService.ts @@ -648,18 +648,19 @@ export abstract class TextFileService extends Disposable implements ITextFileSer return result; } - protected async promptForPath(resource: URI, defaultUri: URI): Promise { + protected async promptForPath(resource: URI, defaultUri: URI, availableFileSystems?: string[]): Promise { // Help user to find a name for the file by opening it first await this.editorService.openEditor({ resource, options: { revealIfOpened: true, preserveFocus: true, } }); - return this.fileDialogService.pickFileToSave(this.getSaveDialogOptions(defaultUri)); + return this.fileDialogService.pickFileToSave(this.getSaveDialogOptions(defaultUri, availableFileSystems)); } - private getSaveDialogOptions(defaultUri: URI): ISaveDialogOptions { + private getSaveDialogOptions(defaultUri: URI, availableFileSystems?: string[]): ISaveDialogOptions { const options: ISaveDialogOptions = { defaultUri, - title: nls.localize('saveAsTitle', "Save As") + title: nls.localize('saveAsTitle', "Save As"), + availableFileSystems, }; // Filters are only enabled on Windows where they work properly @@ -765,7 +766,7 @@ export abstract class TextFileService extends Disposable implements ITextFileSer dialogPath = this.suggestFileName(resource); } - targetResource = await this.promptForPath(resource, dialogPath); + targetResource = await this.promptForPath(resource, dialogPath, options ? options.availableFileSystems : undefined); } if (!targetResource) { diff --git a/src/vs/workbench/services/textfile/common/textfiles.ts b/src/vs/workbench/services/textfile/common/textfiles.ts index d2178242607..a83474a5806 100644 --- a/src/vs/workbench/services/textfile/common/textfiles.ts +++ b/src/vs/workbench/services/textfile/common/textfiles.ts @@ -428,6 +428,7 @@ export interface ISaveOptions { overwriteEncoding?: boolean; skipSaveParticipants?: boolean; writeElevated?: boolean; + availableFileSystems?: string[]; } export interface ILoadOptions { -- GitLab