From 683a76f2951894ca8fee6ba6e626797b68adf65e Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Wed, 3 Oct 2018 16:54:02 +0200 Subject: [PATCH] use FileDialogService with vscode APIs --- src/vs/platform/dialogs/common/dialogs.ts | 19 +++-- .../api/electron-browser/mainThreadDialogs.ts | 70 +++++-------------- src/vs/workbench/api/node/extHost.protocol.ts | 4 +- src/vs/workbench/api/node/extHostDialogs.ts | 4 +- .../browser/actions/workspaceActions.ts | 2 +- .../dialogs/electron-browser/dialogService.ts | 55 ++++++++------- 6 files changed, 62 insertions(+), 92 deletions(-) diff --git a/src/vs/platform/dialogs/common/dialogs.ts b/src/vs/platform/dialogs/common/dialogs.ts index 5a050503f35..4fcf3796db4 100644 --- a/src/vs/platform/dialogs/common/dialogs.ts +++ b/src/vs/platform/dialogs/common/dialogs.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { TPromise } from 'vs/base/common/winjs.base'; import Severity from 'vs/base/common/severity'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { URI } from 'vs/base/common/uri'; @@ -66,7 +65,7 @@ export interface ISaveDialogOptions { /** * A human-readable string for the ok button */ - buttonLabel?: string; + saveLabel?: string; } export interface IOpenDialogOptions { @@ -128,7 +127,7 @@ export interface IDialogService { /** * Ask the user for confirmation with a modal dialog. */ - confirm(confirmation: IConfirmation): TPromise; + confirm(confirmation: IConfirmation): Thenable; /** * Present a modal dialog to the user. @@ -137,7 +136,7 @@ export interface IDialogService { * then a promise with index of `cancelId` option is returned. If there is no such * option then promise with index `0` is returned. */ - show(severity: Severity, message: string, buttons: string[], options?: IDialogOptions): TPromise; + show(severity: Severity, message: string, buttons: string[], options?: IDialogOptions): Thenable; } @@ -171,32 +170,32 @@ export interface IFileDialogService { /** * Shows a file-folder selection dialog and opens the selected entry. */ - pickFileFolderAndOpen(options: IPickAndOpenOptions): TPromise; + pickFileFolderAndOpen(options: IPickAndOpenOptions): Thenable; /** * Shows a file selection dialog and opens the selected entry. */ - pickFileAndOpen(options: IPickAndOpenOptions): TPromise; + pickFileAndOpen(options: IPickAndOpenOptions): Thenable; /** * Shows a folder selection dialog and opens the selected entry. */ - pickFolderAndOpen(options: IPickAndOpenOptions): TPromise; + pickFolderAndOpen(options: IPickAndOpenOptions): Thenable; /** * Shows a workspace selection dialog and opens the selected entry. */ - pickWorkspaceAndOpen(options: IPickAndOpenOptions): TPromise; + pickWorkspaceAndOpen(options: IPickAndOpenOptions): Thenable; /** * Shows a save file dialog and returns the chosen file URI. */ - showSaveDialog(options: ISaveDialogOptions): TPromise; + showSaveDialog(options: ISaveDialogOptions): Thenable; /** * Shows a open file dialog and returns the chosen file URI. */ - showOpenDialog(options: IOpenDialogOptions): TPromise; + showOpenDialog(options: IOpenDialogOptions): Thenable; } diff --git a/src/vs/workbench/api/electron-browser/mainThreadDialogs.ts b/src/vs/workbench/api/electron-browser/mainThreadDialogs.ts index bb44fe45601..8ff02a01d93 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadDialogs.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadDialogs.ts @@ -4,18 +4,17 @@ *--------------------------------------------------------------------------------------------*/ import { URI } from 'vs/base/common/uri'; -import { isFalsyOrEmpty } from 'vs/base/common/arrays'; import { MainThreadDiaglogsShape, MainContext, IExtHostContext, MainThreadDialogOpenOptions, MainThreadDialogSaveOptions } from '../node/extHost.protocol'; import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; -import { IWindowService } from 'vs/platform/windows/common/windows'; import { forEach } from 'vs/base/common/collections'; +import { IFileDialogService, IOpenDialogOptions, ISaveDialogOptions } from 'vs/platform/dialogs/common/dialogs'; @extHostNamedCustomer(MainContext.MainThreadDialogs) export class MainThreadDialogs implements MainThreadDiaglogsShape { constructor( context: IExtHostContext, - @IWindowService private readonly _windowService: IWindowService + @IFileDialogService private readonly _fileDialogService: IFileDialogService, ) { // } @@ -24,52 +23,22 @@ export class MainThreadDialogs implements MainThreadDiaglogsShape { // } - $showOpenDialog(options: MainThreadDialogOpenOptions): Promise { - // TODO@joh what about remote dev setup? - if (options.defaultUri && options.defaultUri.scheme !== 'file') { - return Promise.reject(new Error('Not supported - Open-dialogs can only be opened on `file`-uris.')); - } - return new Promise(resolve => { - this._windowService.showOpenDialog( - MainThreadDialogs._convertOpenOptions(options) - ).then(filenames => resolve(isFalsyOrEmpty(filenames) ? undefined : filenames)); - }); + $showOpenDialog(options: MainThreadDialogOpenOptions): Promise { + return Promise.resolve(this._fileDialogService.showOpenDialog(MainThreadDialogs._convertOpenOptions(options))); } - $showSaveDialog(options: MainThreadDialogSaveOptions): Promise { - // TODO@joh what about remote dev setup? - if (options.defaultUri && options.defaultUri.scheme !== 'file') { - return Promise.reject(new Error('Not supported - Save-dialogs can only be opened on `file`-uris.')); - } - return new Promise(resolve => { - this._windowService.showSaveDialog( - MainThreadDialogs._convertSaveOptions(options) - ).then(filename => resolve(!filename ? undefined : filename)); - }); + $showSaveDialog(options: MainThreadDialogSaveOptions): Promise { + return Promise.resolve(this._fileDialogService.showSaveDialog(MainThreadDialogs._convertSaveOptions(options))); } - private static _convertOpenOptions(options: MainThreadDialogOpenOptions): Electron.OpenDialogOptions { - const result: Electron.OpenDialogOptions = { - properties: ['createDirectory'] + private static _convertOpenOptions(options: MainThreadDialogOpenOptions): IOpenDialogOptions { + const result: IOpenDialogOptions = { + openLabel: options.openLabel, + canSelectFiles: options.canSelectFiles || (!options.canSelectFiles && !options.canSelectFolders), + canSelectFolders: options.canSelectFolders, + canSelectMany: options.canSelectMany, + defaultUri: URI.revive(options.defaultUri) }; - if (options.openLabel) { - result.buttonLabel = options.openLabel; - } - if (options.defaultUri) { - result.defaultPath = URI.revive(options.defaultUri).fsPath; - } - if (!options.canSelectFiles && !options.canSelectFolders) { - options.canSelectFiles = true; - } - if (options.canSelectFiles) { - result.properties.push('openFile'); - } - if (options.canSelectFolders) { - result.properties.push('openDirectory'); - } - if (options.canSelectMany) { - result.properties.push('multiSelections'); - } if (options.filters) { result.filters = []; forEach(options.filters, entry => result.filters.push({ name: entry.key, extensions: entry.value })); @@ -77,16 +46,11 @@ export class MainThreadDialogs implements MainThreadDiaglogsShape { return result; } - private static _convertSaveOptions(options: MainThreadDialogSaveOptions): Electron.SaveDialogOptions { - const result: Electron.SaveDialogOptions = { - + private static _convertSaveOptions(options: MainThreadDialogSaveOptions): ISaveDialogOptions { + const result: ISaveDialogOptions = { + defaultUri: URI.revive(options.defaultUri), + saveLabel: options.saveLabel }; - if (options.defaultUri) { - result.defaultPath = URI.revive(options.defaultUri).fsPath; - } - if (options.saveLabel) { - result.buttonLabel = options.saveLabel; - } if (options.filters) { result.filters = []; forEach(options.filters, entry => result.filters.push({ name: entry.key, extensions: entry.value })); diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index d7f35194b3c..32bd33e10d2 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -127,8 +127,8 @@ export interface MainThreadDialogSaveOptions { } export interface MainThreadDiaglogsShape extends IDisposable { - $showOpenDialog(options: MainThreadDialogOpenOptions): Thenable; - $showSaveDialog(options: MainThreadDialogSaveOptions): Thenable; + $showOpenDialog(options: MainThreadDialogOpenOptions): Thenable; + $showSaveDialog(options: MainThreadDialogSaveOptions): Thenable; } export interface MainThreadDecorationsShape extends IDisposable { diff --git a/src/vs/workbench/api/node/extHostDialogs.ts b/src/vs/workbench/api/node/extHostDialogs.ts index c03821ab85e..b9fd874de21 100644 --- a/src/vs/workbench/api/node/extHostDialogs.ts +++ b/src/vs/workbench/api/node/extHostDialogs.ts @@ -17,13 +17,13 @@ export class ExtHostDialogs { showOpenDialog(options: vscode.OpenDialogOptions): Thenable { return this._proxy.$showOpenDialog(options).then(filepaths => { - return filepaths && filepaths.map(URI.file); + return filepaths && filepaths.map(URI.revive); }); } showSaveDialog(options: vscode.SaveDialogOptions): Thenable { return this._proxy.$showSaveDialog(options).then(filepath => { - return filepath && URI.file(filepath); + return filepath && URI.revive(filepath); }); } } diff --git a/src/vs/workbench/browser/actions/workspaceActions.ts b/src/vs/workbench/browser/actions/workspaceActions.ts index ebbc82f3d34..4131879e60c 100644 --- a/src/vs/workbench/browser/actions/workspaceActions.ts +++ b/src/vs/workbench/browser/actions/workspaceActions.ts @@ -161,7 +161,7 @@ export class SaveWorkspaceAsAction extends Action { private getNewWorkspaceConfigPath(): TPromise { return this.dialogService.showSaveDialog({ - buttonLabel: mnemonicButtonLabel(nls.localize({ key: 'save', comment: ['&& denotes a mnemonic'] }, "&&Save")), + saveLabel: mnemonicButtonLabel(nls.localize({ key: 'save', comment: ['&& denotes a mnemonic'] }, "&&Save")), title: nls.localize('saveWorkspace', "Save Workspace"), filters: WORKSPACE_FILTER, defaultUri: this.dialogService.defaultWorkspacePath(Schemas.file) diff --git a/src/vs/workbench/services/dialogs/electron-browser/dialogService.ts b/src/vs/workbench/services/dialogs/electron-browser/dialogService.ts index b15dce1818b..bdd20aa5e3c 100644 --- a/src/vs/workbench/services/dialogs/electron-browser/dialogService.ts +++ b/src/vs/workbench/services/dialogs/electron-browser/dialogService.ts @@ -5,10 +5,9 @@ import * as nls from 'vs/nls'; import product from 'vs/platform/node/product'; -import { TPromise } from 'vs/base/common/winjs.base'; import Severity from 'vs/base/common/severity'; import { isLinux, isWindows } from 'vs/base/common/platform'; -import { IWindowService, INativeOpenDialogOptions } from 'vs/platform/windows/common/windows'; +import { IWindowService, INativeOpenDialogOptions, OpenDialogOptions } from 'vs/platform/windows/common/windows'; import { mnemonicButtonLabel } from 'vs/base/common/labels'; import { IDialogService, IConfirmation, IConfirmationResult, IDialogOptions, IPickAndOpenOptions, ISaveDialogOptions, IOpenDialogOptions, IFileDialogService } from 'vs/platform/dialogs/common/dialogs'; import { ILogService } from 'vs/platform/log/common/log'; @@ -44,7 +43,7 @@ export class DialogService implements IDialogService { @ILogService private logService: ILogService ) { } - confirm(confirmation: IConfirmation): TPromise { + confirm(confirmation: IConfirmation): Thenable { this.logService.trace('DialogService#confirm', confirmation.message); const { options, buttonIndexMap } = this.massageMessageBoxOptions(this.getConfirmOptions(confirmation)); @@ -94,7 +93,7 @@ export class DialogService implements IDialogService { return opts; } - show(severity: Severity, message: string, buttons: string[], dialogOptions?: IDialogOptions): TPromise { + show(severity: Severity, message: string, buttons: string[], dialogOptions?: IDialogOptions): Thenable { this.logService.trace('DialogService#show', message); const { options, buttonIndexMap } = this.massageMessageBoxOptions({ @@ -213,7 +212,7 @@ export class FileDialogService implements IFileDialogService { }; } - public pickFileFolderAndOpen(options: IPickAndOpenOptions): TPromise { + public pickFileFolderAndOpen(options: IPickAndOpenOptions): Thenable { let defaultUri = options.defaultUri; if (!defaultUri) { options.defaultUri = this.defaultFilePath(Schemas.file); @@ -222,7 +221,7 @@ export class FileDialogService implements IFileDialogService { } - public pickFileAndOpen(options: IPickAndOpenOptions): TPromise { + public pickFileAndOpen(options: IPickAndOpenOptions): Thenable { let defaultUri = options.defaultUri; if (!defaultUri) { options.defaultUri = this.defaultFilePath(Schemas.file); @@ -230,7 +229,7 @@ export class FileDialogService implements IFileDialogService { return this.windowService.pickFileAndOpen(this.toNativeOpenDialogOptions(options)); } - public pickFolderAndOpen(options: IPickAndOpenOptions): TPromise { + public pickFolderAndOpen(options: IPickAndOpenOptions): Thenable { let defaultUri = options.defaultUri; if (!defaultUri) { options.defaultUri = this.defaultFolderPath(Schemas.file); @@ -238,7 +237,7 @@ export class FileDialogService implements IFileDialogService { return this.windowService.pickFolderAndOpen(this.toNativeOpenDialogOptions(options)); } - public pickWorkspaceAndOpen(options: IPickAndOpenOptions): TPromise { + public pickWorkspaceAndOpen(options: IPickAndOpenOptions): Thenable { let defaultUri = options.defaultUri; if (!defaultUri) { options.defaultUri = this.defaultWorkspacePath(Schemas.file); @@ -249,13 +248,17 @@ export class FileDialogService implements IFileDialogService { private toNativeSaveDialogOptions(options: ISaveDialogOptions): Electron.SaveDialogOptions { return { defaultPath: options.defaultUri && options.defaultUri.fsPath, - buttonLabel: options.buttonLabel, + buttonLabel: options.saveLabel, filters: options.filters, title: options.title }; } - public showSaveDialog(options: ISaveDialogOptions): TPromise { + public showSaveDialog(options: ISaveDialogOptions): Thenable { + const defaultUri = options.defaultUri; + if (defaultUri && defaultUri.scheme !== Schemas.file) { + return Promise.reject(new Error('Not supported - Save-dialogs can only be opened on `file`-uris.')); + } return this.windowService.showSaveDialog(this.toNativeSaveDialogOptions(options)).then(result => { if (result) { return URI.file(result); @@ -264,31 +267,35 @@ export class FileDialogService implements IFileDialogService { }); } - public showOpenDialog(options: IOpenDialogOptions): TPromise { + public showOpenDialog(options: IOpenDialogOptions): Thenable { const defaultUri = options.defaultUri; + if (defaultUri && defaultUri.scheme !== Schemas.file) { + return Promise.reject(new Error('Not supported - Open-dialogs can only be opened on `file`-uris.')); + } const filters = []; if (options.filters) { for (let name in options.filters) { filters.push({ name, extensions: options.filters[name] }); } } - const properties = []; - if (options.canSelectFiles) { - properties.push('openFile'); - } - if (options.canSelectFolders) { - properties.push('openDirectory'); - } - if (options.canSelectMany) { - properties.push('multiSelections'); - } - return this.windowService.showOpenDialog({ + const newOptions: OpenDialogOptions = { title: options.title, defaultPath: defaultUri && defaultUri.fsPath, buttonLabel: options.openLabel, filters, - properties - }).then(result => result ? result.map(URI.file) : void 0); + properties: [] + }; + newOptions.properties.push('createDirectory'); + if (options.canSelectFiles) { + newOptions.properties.push('openFile'); + } + if (options.canSelectFolders) { + newOptions.properties.push('openDirectory'); + } + if (options.canSelectMany) { + newOptions.properties.push('multiSelections'); + } + return this.windowService.showOpenDialog(newOptions).then(result => result ? result.map(URI.file) : void 0); } }