提交 bc59b294 编写于 作者: B Benjamin Pasero

debt - add new prompt method to notification service

上级 55ea9fe2
......@@ -38,7 +38,7 @@ import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKe
import { OS } from 'vs/base/common/platform';
import { IRange } from 'vs/editor/common/core/range';
import { ITextModel } from 'vs/editor/common/model';
import { INotificationService, INotification, INotificationHandle, NoOpNotification } from 'vs/platform/notification/common/notification';
import { INotificationService, INotification, INotificationHandle, NoOpNotification, PromptOption } from 'vs/platform/notification/common/notification';
import { IConfirmation, IConfirmationResult, IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { IPosition, Position as Pos } from 'vs/editor/common/core/position';
......@@ -296,6 +296,10 @@ export class SimpleNotificationService implements INotificationService {
return SimpleNotificationService.NO_OP;
}
public prompt(severity: Severity, message: string, choices: PromptOption[]): TPromise<number> {
return TPromise.as(0);
}
}
export class StandaloneCommandService implements ICommandService {
......
......@@ -14,7 +14,7 @@ import URI from 'vs/base/common/uri';
import Severity from 'vs/base/common/severity';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { IChoiceService, Choice } from 'vs/platform/dialogs/common/dialogs';
import { INotificationService, PromptOption } from 'vs/platform/notification/common/notification';
interface IStorageData {
dontShowPrompt: boolean;
......@@ -62,7 +62,7 @@ export class IntegrityServiceImpl implements IIntegrityService {
private _isPurePromise: Thenable<IntegrityTestResult>;
constructor(
@IChoiceService private choiceService: IChoiceService,
@INotificationService private notificationService: INotificationService,
@IStorageService storageService: IStorageService,
@ILifecycleService private lifecycleService: ILifecycleService
) {
......@@ -86,9 +86,9 @@ export class IntegrityServiceImpl implements IIntegrityService {
return;
}
const choices: Choice[] = [nls.localize('integrity.moreInformation', "More Information"), { label: nls.localize('integrity.dontShowAgain', "Don't Show Again") }];
const choices: PromptOption[] = [nls.localize('integrity.moreInformation', "More Information"), { label: nls.localize('integrity.dontShowAgain', "Don't Show Again") }];
this.choiceService.choose(Severity.Warning, nls.localize('integrity.prompt', "Your {0} installation appears to be corrupt. Please reinstall.", product.nameShort), choices).then(choice => {
this.notificationService.prompt(Severity.Warning, nls.localize('integrity.prompt', "Your {0} installation appears to be corrupt. Please reinstall.", product.nameShort), choices).then(choice => {
switch (choice) {
case 0 /* More Information */:
const uri = URI.parse(product.checksumFailMoreInfoUrl);
......
......@@ -138,6 +138,9 @@ suite('AbstractKeybindingService', () => {
error: (message: any) => {
showMessageCalls.push({ sev: Severity.Error, message });
return new NoOpNotification();
},
prompt: () => {
return TPromise.as(0);
}
};
......
......@@ -10,6 +10,7 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'
import { IDisposable } from 'vs/base/common/lifecycle';
import { IAction } from 'vs/base/common/actions';
import Event, { Emitter } from 'vs/base/common/event';
import { TPromise } from 'vs/base/common/winjs.base';
export import Severity = Severity;
......@@ -44,7 +45,7 @@ export interface INotification {
* close automatically when invoking a secondary action.
*
* **Note:** If your intent is to show a message with actions to the user, consider
* the `IChoiceService` or `IDialogService` instead which are optimized for
* the `INotificationService.prompt()` method instead which are optimized for
* this usecase and much easier to use!
*/
actions?: INotificationActions;
......@@ -120,6 +121,27 @@ export interface INotificationHandle extends IDisposable {
updateActions(actions?: INotificationActions): void;
}
/**
* Primary choices show up as buttons in the notification below the message.
*/
export type PrimaryPromptChoice = string;
/**
* Secondary choices show up under the gear icon in the header of the notification.
*/
export interface SecondaryPromptChoice {
label: string;
/**
* Wether to keep the notification open after the secondary choice was selected
* by the user. By default, will close the notification upon click.
*/
keepOpen?: boolean;
}
export type PromptOption = PrimaryPromptChoice | SecondaryPromptChoice;
export interface INotificationService {
_serviceBrand: any;
......@@ -129,8 +151,10 @@ export interface INotificationService {
* can be used to control the notification afterwards.
*
* **Note:** If your intent is to show a message with actions to the user, consider
* the `IChoiceService` or `IDialogService` instead which are optimized for
* the `INotificationService.prompt()` method instead which are optimized for
* this usecase and much easier to use!
*
* @returns a handle on the notification to e.g. hide it or update message, buttons, etc.
*/
notify(notification: INotification): INotificationHandle;
......@@ -151,6 +175,15 @@ export interface INotificationService {
* method if you need more control over the notification.
*/
error(message: NotificationMessage | NotificationMessage[]): void;
/**
* Shows a prompt in the notification area with the provided choices. The prompt
* is non-modal. If you want to show a modal dialog instead, use `IDialogService`.
*
* @returns a promise that will resolve to the index of the choice that was picked.
* The promise can be cancelled to hide the notification prompt.
*/
prompt(severity: Severity, message: string, choices: PromptOption[]): TPromise<number>;
}
export class NoOpNotification implements INotificationHandle {
......
......@@ -44,7 +44,6 @@ import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
import { PICK_WORKSPACE_FOLDER_COMMAND_ID } from 'vs/workbench/browser/actions/workspaceCommands';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { IChoiceService } from 'vs/platform/dialogs/common/dialogs';
import { mnemonicButtonLabel } from 'vs/base/common/labels';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IQuickOpenService, IPickOpenEntry } from 'vs/platform/quickOpen/common/quickOpen';
......@@ -1881,7 +1880,7 @@ export class InstallVSIXAction extends Action {
id = InstallVSIXAction.ID,
label = InstallVSIXAction.LABEL,
@IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService,
@IChoiceService private choiceService: IChoiceService,
@INotificationService private notificationService: INotificationService,
@IWindowService private windowsService: IWindowService
) {
super(id, label, 'extension-action install-vsix', true);
......@@ -1899,7 +1898,7 @@ export class InstallVSIXAction extends Action {
}
return TPromise.join(result.map(vsix => this.extensionsWorkbenchService.install(vsix))).then(() => {
return this.choiceService.choose(Severity.Info, localize('InstallVSIXAction.success', "Successfully installed the extension. Reload to enable it."), [localize('InstallVSIXAction.reloadNow', "Reload Now")]).then(choice => {
return this.notificationService.prompt(Severity.Info, localize('InstallVSIXAction.success', "Successfully installed the extension. Reload to enable it."), [localize('InstallVSIXAction.reloadNow', "Reload Now")]).then(choice => {
if (choice === 0) {
return this.windowsService.reloadWindow();
}
......
......@@ -34,10 +34,9 @@ import { getHashedRemotesFromUri } from 'vs/workbench/parts/stats/node/workspace
import { IRequestService } from 'vs/platform/request/node/request';
import { asJson } from 'vs/base/node/request';
import { isNumber } from 'vs/base/common/types';
import { IChoiceService, Choice } from 'vs/platform/dialogs/common/dialogs';
import { language, LANGUAGE_DEFAULT } from 'vs/base/common/platform';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { INotificationService, PromptOption } from 'vs/platform/notification/common/notification';
interface IExtensionsContent {
recommendations: string[];
......@@ -72,7 +71,6 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
@IExtensionGalleryService private readonly _galleryService: IExtensionGalleryService,
@IModelService private readonly _modelService: IModelService,
@IStorageService private storageService: IStorageService,
@IChoiceService private choiceService: IChoiceService,
@IExtensionManagementService private extensionsService: IExtensionManagementService,
@IInstantiationService private instantiationService: IInstantiationService,
@IFileService private fileService: IFileService,
......@@ -163,12 +161,12 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
return;
}
const message = localize('showLanguagePackExtensions', "The Marketplace has extensions that can help localizing VS Code to '{0}' locale", language);
const options: Choice[] = [
const options: PromptOption[] = [
searchMarketplace,
{ label: choiceNever }
];
this.choiceService.choose(Severity.Info, message, options).done(choice => {
this.notificationService.prompt(Severity.Info, message, options).done(choice => {
switch (choice) {
case 0 /* Search Marketplace */:
/* __GDPR__
......@@ -491,13 +489,13 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
const recommendationsAction = this.instantiationService.createInstance(ShowRecommendedExtensionsAction, ShowRecommendedExtensionsAction.ID, localize('showRecommendations', "Show Recommendations"));
const installAction = this.instantiationService.createInstance(InstallRecommendedExtensionAction, id);
const options: Choice[] = [
const options: PromptOption[] = [
localize('install', 'Install'),
recommendationsAction.label,
{ label: choiceNever }
];
this.choiceService.choose(Severity.Info, message, options).done(choice => {
this.notificationService.prompt(Severity.Info, message, options).done(choice => {
switch (choice) {
case 0 /* Install */:
/* __GDPR__
......@@ -571,12 +569,12 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
}
const message = localize('showLanguageExtensions', "The Marketplace has extensions that can help with '.{0}' files", fileExtension);
const options: Choice[] = [
const options: PromptOption[] = [
searchMarketplace,
{ label: choiceNever }
];
this.choiceService.choose(Severity.Info, message, options).done(choice => {
this.notificationService.prompt(Severity.Info, message, options).done(choice => {
switch (choice) {
case 0 /* Search Marketplace */:
/* __GDPR__
......@@ -644,13 +642,13 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
const showAction = this.instantiationService.createInstance(ShowRecommendedExtensionsAction, ShowRecommendedExtensionsAction.ID, localize('showRecommendations', "Show Recommendations"));
const installAllAction = this.instantiationService.createInstance(InstallWorkspaceRecommendedExtensionsAction, InstallWorkspaceRecommendedExtensionsAction.ID, localize('installAll', "Install All"));
const options: Choice[] = [
const options: PromptOption[] = [
installAllAction.label,
showAction.label,
{ label: choiceNever }
];
return this.choiceService.choose(Severity.Info, message, options).done(choice => {
return this.notificationService.prompt(Severity.Info, message, options).done(choice => {
switch (choice) {
case 0 /* Install */:
/* __GDPR__
......@@ -696,7 +694,7 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
localize('no', "No")
];
this.choiceService.choose(Severity.Info, message, options).done(choice => {
this.notificationService.prompt(Severity.Info, message, options).done(choice => {
switch (choice) {
case 0: // If the user ignores the current message and selects different file type
return this.setIgnoreRecommendationsConfig(true);
......
......@@ -14,7 +14,6 @@ import { IFileService } from 'vs/platform/files/common/files';
import URI from 'vs/base/common/uri';
import Severity from 'vs/base/common/severity';
import { mnemonicButtonLabel } from 'vs/base/common/labels';
import { IChoiceService } from 'vs/platform/dialogs/common/dialogs';
import { IQuickOpenService, IPickOpenEntry } from 'vs/platform/quickOpen/common/quickOpen';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { LocalExtensionType } from 'vs/platform/extensionManagement/common/extensionManagement';
......@@ -59,7 +58,7 @@ export class InstallVSIXAction extends Action {
id = InstallVSIXAction.ID,
label = InstallVSIXAction.LABEL,
@IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService,
@IChoiceService private choiceService: IChoiceService,
@INotificationService private notificationService: INotificationService,
@IWindowService private windowsService: IWindowService
) {
super(id, label, 'extension-action install-vsix', true);
......@@ -77,7 +76,7 @@ export class InstallVSIXAction extends Action {
}
return TPromise.join(result.map(vsix => this.extensionsWorkbenchService.install(vsix))).then(() => {
return this.choiceService.choose(Severity.Info, localize('InstallVSIXAction.success', "Successfully installed the extension. Reload to enable it."), [localize('InstallVSIXAction.reloadNow', "Reload Now")]).then(choice => {
return this.notificationService.prompt(Severity.Info, localize('InstallVSIXAction.success', "Successfully installed the extension. Reload to enable it."), [localize('InstallVSIXAction.reloadNow', "Reload Now")]).then(choice => {
if (choice === 0) {
return this.windowsService.reloadWindow();
}
......
......@@ -20,8 +20,7 @@ import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiati
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { BetterMergeDisabledNowKey, BetterMergeId, areSameExtensions, adoptToGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { getIdAndVersionFromLocalExtensionId } from 'vs/platform/extensionManagement/node/extensionManagementUtil';
import { IChoiceService } from 'vs/platform/dialogs/common/dialogs';
import { Severity } from 'vs/platform/notification/common/notification';
import { Severity, INotificationService } from 'vs/platform/notification/common/notification';
export interface IExtensionStatus {
identifier: IExtensionIdentifier;
......@@ -37,8 +36,8 @@ export class KeymapExtensions implements IWorkbenchContribution {
@IInstantiationService private instantiationService: IInstantiationService,
@IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService,
@IExtensionTipsService private tipsService: IExtensionTipsService,
@IChoiceService private choiceService: IChoiceService,
@ILifecycleService lifecycleService: ILifecycleService,
@INotificationService private notificationService: INotificationService,
@ITelemetryService private telemetryService: ITelemetryService,
) {
this.disposables.push(
......@@ -70,7 +69,7 @@ export class KeymapExtensions implements IWorkbenchContribution {
localize('yes', "Yes"),
localize('no', "No")
];
return this.choiceService.choose(Severity.Info, message, options)
return this.notificationService.prompt(Severity.Info, message, options)
.then(value => {
const confirmed = value === 0;
const telemetryData: { [key: string]: any; } = {
......@@ -149,7 +148,7 @@ export class BetterMergeDisabled implements IWorkbenchContribution {
constructor(
@IStorageService storageService: IStorageService,
@IChoiceService choiceService: IChoiceService,
@INotificationService notificationService: INotificationService,
@IExtensionService extensionService: IExtensionService,
@IExtensionManagementService extensionManagementService: IExtensionManagementService,
@ITelemetryService telemetryService: ITelemetryService,
......@@ -158,7 +157,7 @@ export class BetterMergeDisabled implements IWorkbenchContribution {
if (storageService.getBoolean(BetterMergeDisabledNowKey, StorageScope.GLOBAL, false)) {
storageService.remove(BetterMergeDisabledNowKey, StorageScope.GLOBAL);
choiceService.choose(Severity.Info, localize('betterMergeDisabled', "The Better Merge extension is now built-in, the installed extension was disabled and can be uninstalled."), [localize('uninstall', "Uninstall")]).then(choice => {
notificationService.prompt(Severity.Info, localize('betterMergeDisabled', "The Better Merge extension is now built-in, the installed extension was disabled and can be uninstalled."), [localize('uninstall', "Uninstall")]).then(choice => {
if (choice === 0) {
extensionManagementService.getInstalled(LocalExtensionType.User).then(extensions => {
return Promise.all(extensions.filter(e => stripVersion(e.identifier.id) === BetterMergeId)
......
......@@ -52,7 +52,6 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView
import { getGalleryExtensionIdFromLocal, getMaliciousExtensionsSet } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { ILogService } from 'vs/platform/log/common/log';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IChoiceService } from 'vs/platform/dialogs/common/dialogs';
import { IWindowService } from 'vs/platform/windows/common/windows';
import { IPartService } from 'vs/workbench/services/part/common/partService';
......@@ -488,7 +487,7 @@ export class MaliciousExtensionChecker implements IWorkbenchContribution {
@IExtensionManagementService private extensionsManagementService: IExtensionManagementService,
@IWindowService private windowService: IWindowService,
@ILogService private logService: ILogService,
@IChoiceService private choiceService: IChoiceService
@INotificationService private notificationService: INotificationService
) {
this.loopCheckForMaliciousExtensions();
}
......@@ -509,7 +508,7 @@ export class MaliciousExtensionChecker implements IWorkbenchContribution {
if (maliciousExtensions.length) {
return TPromise.join(maliciousExtensions.map(e => this.extensionsManagementService.uninstall(e, true).then(() => {
return this.choiceService.choose(Severity.Warning, localize('malicious warning', "We have uninstalled '{0}' which was reported to be problematic.", getGalleryExtensionIdFromLocal(e)), [localize('reloadNow', "Reload Now")]).then(choice => {
return this.notificationService.prompt(Severity.Warning, localize('malicious warning', "We have uninstalled '{0}' which was reported to be problematic.", getGalleryExtensionIdFromLocal(e)), [localize('reloadNow', "Reload Now")]).then(choice => {
if (choice === 0) {
return this.windowService.reloadWindow();
}
......
......@@ -35,7 +35,7 @@ import { ExtensionsInput } from 'vs/workbench/parts/extensions/common/extensions
import product from 'vs/platform/node/product';
import { ILogService } from 'vs/platform/log/common/log';
import { IProgressService2, ProgressLocation } from 'vs/platform/progress/common/progress';
import { IChoiceService, IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { INotificationService } from 'vs/platform/notification/common/notification';
interface IExtensionStateProvider<T> {
......@@ -370,9 +370,8 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService {
@IExtensionGalleryService private galleryService: IExtensionGalleryService,
@IConfigurationService private configurationService: IConfigurationService,
@ITelemetryService private telemetryService: ITelemetryService,
@INotificationService private notificationService: INotificationService,
@IDialogService private dialogService: IDialogService,
@IChoiceService private choiceService: IChoiceService,
@INotificationService private notificationService: INotificationService,
@IURLService urlService: IURLService,
@IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService,
@IWindowService private windowService: IWindowService,
......@@ -1001,7 +1000,7 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService {
const options = [
nls.localize('install', "Install")
];
return this.choiceService.choose(Severity.Info, message, options).then(value => {
return this.notificationService.prompt(Severity.Info, message, options).then(value => {
if (value === 0) {
return this.install(extension);
}
......
......@@ -46,7 +46,6 @@ import product from 'vs/platform/node/product';
import { ITextModel } from 'vs/editor/common/model';
import { IModelService } from 'vs/editor/common/services/modelService';
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { IChoiceService } from 'vs/platform/dialogs/common/dialogs';
import { INotificationService } from 'vs/platform/notification/common/notification';
const mockExtensionGallery: IGalleryExtension[] = [
......@@ -222,12 +221,15 @@ suite('ExtensionsTipsService Test', () => {
instantiationService.stub(IExtensionsWorkbenchService, extensionsWorkbenchService);
prompted = false;
instantiationService.stub(IChoiceService, {
choose: () => {
class TestNotificationService2 extends TestNotificationService {
public prompt() {
prompted = true;
return TPromise.as(3);
}
});
}
instantiationService.stub(INotificationService, new TestNotificationService2());
testConfigurationService.setUserConfiguration(ConfigurationKey, { ignoreRecommendations: false, showRecommendationsOnlyOnDemand: false });
instantiationService.stub(IStorageService, { get: (a, b, c) => c, getBoolean: (a, b, c) => c, store: () => { } });
......
......@@ -35,7 +35,8 @@ import { ILogService, NullLogService } from 'vs/platform/log/common/log';
import { IWindowService } from 'vs/platform/windows/common/windows';
import { IProgressService2 } from 'vs/platform/progress/common/progress';
import { ProgressService2 } from 'vs/workbench/services/progress/browser/progressService2';
import { IChoiceService, IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { INotificationService } from 'vs/platform/notification/common/notification';
suite('ExtensionsWorkbenchService Test', () => {
......@@ -76,7 +77,7 @@ suite('ExtensionsWorkbenchService Test', () => {
instantiationService.stub(IExtensionTipsService, ExtensionTipsService);
instantiationService.stub(IExtensionTipsService, 'getKeymapRecommendations', () => []);
instantiationService.stub(IChoiceService, { choose: () => null });
instantiationService.stub(INotificationService, { prompt: () => null });
instantiationService.stub(IDialogService, { show: () => TPromise.as(0) });
});
......@@ -85,7 +86,7 @@ suite('ExtensionsWorkbenchService Test', () => {
instantiationService.stubPromise(IExtensionManagementService, 'getExtensionsReport', []);
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage());
instantiationService.stub(IDialogService, { show: () => TPromise.as(0) });
instantiationService.stubPromise(IChoiceService, 'choose', 0);
instantiationService.stubPromise(INotificationService, 'prompt', 0);
(<TestExtensionEnablementService>instantiationService.get(IExtensionEnablementService)).reset();
});
......
......@@ -17,8 +17,7 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag
import pkg from 'vs/platform/node/package';
import product, { ISurveyData } from 'vs/platform/node/product';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { IChoiceService, Choice } from 'vs/platform/dialogs/common/dialogs';
import { Severity } from 'vs/platform/notification/common/notification';
import { Severity, INotificationService, PromptOption } from 'vs/platform/notification/common/notification';
class LanguageSurvey {
......@@ -26,7 +25,7 @@ class LanguageSurvey {
data: ISurveyData,
instantiationService: IInstantiationService,
storageService: IStorageService,
choiceService: IChoiceService,
notificationService: INotificationService,
telemetryService: ITelemetryService,
fileService: IFileService,
modelService: IModelService
......@@ -88,8 +87,8 @@ class LanguageSurvey {
// __GDPR__TODO__ Need to move away from dynamic event names as those cannot be registered statically
telemetryService.publicLog(`${data.surveyId}.survey/userAsked`);
const choices: Choice[] = [nls.localize('takeShortSurvey', "Take Short Survey"), nls.localize('remindLater', "Remind Me later"), { label: nls.localize('neverAgain', "Don't Show Again") }];
choiceService.choose(Severity.Info, nls.localize('helpUs', "Help us improve our support for {0}", data.languageId), choices).then(choice => {
const choices: PromptOption[] = [nls.localize('takeShortSurvey', "Take Short Survey"), nls.localize('remindLater', "Remind Me later"), { label: nls.localize('neverAgain', "Don't Show Again") }];
notificationService.prompt(Severity.Info, nls.localize('helpUs', "Help us improve our support for {0}", data.languageId), choices).then(choice => {
switch (choice) {
case 0 /* Take Survey */:
telemetryService.publicLog(`${data.surveyId}.survey/takeShortSurvey`);
......@@ -119,13 +118,13 @@ class LanguageSurveysContribution implements IWorkbenchContribution {
constructor(
@IInstantiationService instantiationService: IInstantiationService,
@IStorageService storageService: IStorageService,
@IChoiceService choiceService: IChoiceService,
@INotificationService notificationService: INotificationService,
@ITelemetryService telemetryService: ITelemetryService,
@IFileService fileService: IFileService,
@IModelService modelService: IModelService
) {
product.surveys.filter(surveyData => surveyData.surveyId && surveyData.editCount && surveyData.languageId && surveyData.surveyUrl && surveyData.userProbability).map(surveyData =>
new LanguageSurvey(surveyData, instantiationService, storageService, choiceService, telemetryService, fileService, modelService));
new LanguageSurvey(surveyData, instantiationService, storageService, notificationService, telemetryService, fileService, modelService));
}
}
......
......@@ -15,8 +15,7 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag
import pkg from 'vs/platform/node/package';
import product from 'vs/platform/node/product';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { IChoiceService, Choice } from 'vs/platform/dialogs/common/dialogs';
import { Severity } from 'vs/platform/notification/common/notification';
import { Severity, INotificationService, PromptOption } from 'vs/platform/notification/common/notification';
const PROBABILITY = 0.15;
const SESSION_COUNT_KEY = 'nps/sessionCount';
......@@ -29,7 +28,7 @@ class NPSContribution implements IWorkbenchContribution {
constructor(
@IInstantiationService instantiationService: IInstantiationService,
@IStorageService storageService: IStorageService,
@IChoiceService choiceService: IChoiceService,
@INotificationService notificationService: INotificationService,
@ITelemetryService telemetryService: ITelemetryService
) {
const skipVersion = storageService.get(SKIP_VERSION_KEY, StorageScope.GLOBAL, '');
......@@ -63,8 +62,8 @@ class NPSContribution implements IWorkbenchContribution {
return;
}
const choices: Choice[] = [nls.localize('takeSurvey', "Take Survey"), nls.localize('remindLater', "Remind Me later"), { label: nls.localize('neverAgain', "Don't Show Again") }];
choiceService.choose(Severity.Info, nls.localize('surveyQuestion', "Do you mind taking a quick feedback survey?"), choices).then(choice => {
const choices: PromptOption[] = [nls.localize('takeSurvey', "Take Survey"), nls.localize('remindLater', "Remind Me later"), { label: nls.localize('neverAgain', "Don't Show Again") }];
notificationService.prompt(Severity.Info, nls.localize('surveyQuestion', "Do you mind taking a quick feedback survey?"), choices).then(choice => {
switch (choice) {
case 0 /* Take Survey */:
telemetryService.getTelemetryInfo().then(info => {
......
......@@ -46,7 +46,7 @@ import { IProgressService2, IProgressOptions, ProgressLocation } from 'vs/platfo
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { IWindowService } from 'vs/platform/windows/common/windows';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IDialogService, IChoiceService, IConfirmationResult } from 'vs/platform/dialogs/common/dialogs';
import { IDialogService, IConfirmationResult } from 'vs/platform/dialogs/common/dialogs';
import { IModelService } from 'vs/editor/common/services/modelService';
......@@ -472,8 +472,7 @@ class TaskService implements ITaskService {
@IOpenerService private openerService: IOpenerService,
@IWindowService private readonly _windowService: IWindowService,
@IDialogService private dialogService: IDialogService,
@INotificationService private notificationService: INotificationService,
@IChoiceService private choiceService: IChoiceService
@INotificationService private notificationService: INotificationService
) {
this._configHasErrors = false;
this._workspaceTasksPromise = undefined;
......@@ -491,7 +490,7 @@ class TaskService implements ITaskService {
let folderSetup = this.computeWorkspaceFolderSetup();
if (this.executionEngine !== folderSetup[2]) {
if (this._taskSystem && this._taskSystem.getActiveTasks().length > 0) {
this.choiceService.choose(Severity.Info, nls.localize(
this.notificationService.prompt(Severity.Info, nls.localize(
'TaskSystem.noHotSwap',
'Changing the task execution engine with an active task running requires to reload the Window'
), [nls.localize('reloadWindow', "Reload Window")]).then(choice => {
......
......@@ -13,8 +13,8 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag
import { ITerminalConfiguration, ITerminalConfigHelper, ITerminalFont, IShellLaunchConfig, IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY, TERMINAL_CONFIG_SECTION } from 'vs/workbench/parts/terminal/common/terminal';
import Severity from 'vs/base/common/severity';
import { isFedora } from 'vs/workbench/parts/terminal/electron-browser/terminal';
import { IChoiceService } from 'vs/platform/dialogs/common/dialogs';
import { Terminal as XTermTerminal } from 'vscode-xterm';
import { INotificationService } from 'vs/platform/notification/common/notification';
const DEFAULT_LINE_HEIGHT = 1.0;
......@@ -35,7 +35,7 @@ export class TerminalConfigHelper implements ITerminalConfigHelper {
public constructor(
@IConfigurationService private readonly _configurationService: IConfigurationService,
@IWorkspaceConfigurationService private readonly _workspaceConfigurationService: IWorkspaceConfigurationService,
@IChoiceService private readonly _choiceService: IChoiceService,
@INotificationService private readonly _notificationService: INotificationService,
@IStorageService private readonly _storageService: IStorageService
) {
this._updateConfig();
......@@ -165,7 +165,7 @@ export class TerminalConfigHelper implements ITerminalConfigHelper {
}
const message = nls.localize('terminal.integrated.allowWorkspaceShell', "Do you allow {0} (defined as a workspace setting) to be launched in the terminal?", changeString);
const options = [nls.localize('allow', "Allow"), nls.localize('disallow', "Disallow")];
this._choiceService.choose(Severity.Info, message, options).then(choice => {
this._notificationService.prompt(Severity.Info, message, options).then(choice => {
switch (choice) {
case 0: /* Allow */
this._storageService.store(IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY, true, StorageScope.WORKSPACE);
......
......@@ -22,7 +22,8 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag
import { getTerminalDefaultShellWindows } from 'vs/workbench/parts/terminal/electron-browser/terminal';
import { TerminalPanel } from 'vs/workbench/parts/terminal/electron-browser/terminalPanel';
import { TerminalTab } from 'vs/workbench/parts/terminal/electron-browser/terminalTab';
import { IChoiceService, IDialogService, Choice } from 'vs/platform/dialogs/common/dialogs';
import { IDialogService, Choice } from 'vs/platform/dialogs/common/dialogs';
import { INotificationService } from 'vs/platform/notification/common/notification';
export class TerminalService extends AbstractTerminalService implements ITerminalService {
private _configHelper: TerminalConfigHelper;
......@@ -42,7 +43,7 @@ export class TerminalService extends AbstractTerminalService implements ITermina
@IConfigurationService private readonly _configurationService: IConfigurationService,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@IQuickOpenService private readonly _quickOpenService: IQuickOpenService,
@IChoiceService private readonly _choiceService: IChoiceService,
@INotificationService private readonly _notificationService: INotificationService,
@IDialogService private readonly _dialogService: IDialogService
) {
super(contextKeyService, panelService, partService, lifecycleService, storageService);
......@@ -128,7 +129,7 @@ export class TerminalService extends AbstractTerminalService implements ITermina
const message = nls.localize('terminal.integrated.chooseWindowsShellInfo', "You can change the default terminal shell by selecting the customize button.");
const options: Choice[] = [nls.localize('customize', "Customize"), { label: nls.localize('never again', "Don't Show Again") }];
this._choiceService.choose(Severity.Info, message, options).then(choice => {
this._notificationService.prompt(Severity.Info, message, options).then(choice => {
switch (choice) {
case 0 /* Customize */:
this.selectDefaultWindowsShell().then(shell => {
......
......@@ -14,8 +14,7 @@ import { IPreferencesService } from 'vs/workbench/parts/preferences/common/prefe
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IChoiceService, Choice } from 'vs/platform/dialogs/common/dialogs';
import { Severity } from 'vs/platform/notification/common/notification';
import { Severity, INotificationService, PromptOption } from 'vs/platform/notification/common/notification';
class UnsupportedWorkspaceSettingsContribution implements IWorkbenchContribution {
......@@ -28,8 +27,8 @@ class UnsupportedWorkspaceSettingsContribution implements IWorkbenchContribution
@IWorkspaceContextService workspaceContextService: IWorkspaceContextService,
@IWorkspaceConfigurationService private workspaceConfigurationService: IWorkspaceConfigurationService,
@IPreferencesService private preferencesService: IPreferencesService,
@IChoiceService private choiceService: IChoiceService,
@IStorageService private storageService: IStorageService
@IStorageService private storageService: IStorageService,
@INotificationService private notificationService: INotificationService
) {
lifecycleService.onShutdown(this.dispose, this);
this.toDispose.push(this.workspaceConfigurationService.onDidChangeConfiguration(e => this.checkWorkspaceSettings()));
......@@ -61,8 +60,8 @@ class UnsupportedWorkspaceSettingsContribution implements IWorkbenchContribution
}
private showWarning(unsupportedKeys: string[]): void {
const choices: Choice[] = [nls.localize('openWorkspaceSettings', 'Open Workspace Settings'), { label: nls.localize('dontShowAgain', 'Don\'t Show Again') }];
this.choiceService.choose(Severity.Warning, nls.localize('unsupportedWorkspaceSettings', 'This Workspace contains settings that can only be set in User Settings ({0}). Click [here]({1}) to learn more.', unsupportedKeys.join(', '), 'https://go.microsoft.com/fwlink/?linkid=839878'), choices).then(choice => {
const choices: PromptOption[] = [nls.localize('openWorkspaceSettings', 'Open Workspace Settings'), { label: nls.localize('dontShowAgain', 'Don\'t Show Again') }];
this.notificationService.prompt(Severity.Warning, nls.localize('unsupportedWorkspaceSettings', 'This Workspace contains settings that can only be set in User Settings ({0}). Click [here]({1}) to learn more.', unsupportedKeys.join(', '), 'https://go.microsoft.com/fwlink/?linkid=839878'), choices).then(choice => {
switch (choice) {
case 0 /* Open Workspace Settings */:
this.rememberWarningWasShown();
......
......@@ -39,7 +39,6 @@ import { IWorkspaceIdentifier, getWorkspaceLabel, ISingleFolderWorkspaceIdentifi
import { IEditorInputFactory, EditorInput } from 'vs/workbench/common/editor';
import { getIdAndVersionFromLocalExtensionId } from 'vs/platform/extensionManagement/node/extensionManagementUtil';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { IChoiceService } from 'vs/platform/dialogs/common/dialogs';
used();
......@@ -227,7 +226,6 @@ class WelcomePage {
@IConfigurationService private configurationService: IConfigurationService,
@IEnvironmentService private environmentService: IEnvironmentService,
@INotificationService private notificationService: INotificationService,
@IChoiceService private choiceService: IChoiceService,
@IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService,
@IExtensionGalleryService private extensionGalleryService: IExtensionGalleryService,
@IExtensionManagementService private extensionManagementService: IExtensionManagementService,
......@@ -429,7 +427,7 @@ class WelcomePage {
});
});
this.choiceService.choose(Severity.Info, strings.reloadAfterInstall.replace('{0}', extensionSuggestion.name), [localize('ok', "OK"), localize('details', "Details")]).then(choice => {
this.notificationService.prompt(Severity.Info, strings.reloadAfterInstall.replace('{0}', extensionSuggestion.name), [localize('ok', "OK"), localize('details', "Details")]).then(choice => {
switch (choice) {
case 0 /* OK */:
const messageDelay = TPromise.timeout(300);
......
......@@ -30,7 +30,6 @@ import { OVERRIDE_PROPERTY_PATTERN, IConfigurationRegistry, Extensions as Config
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { ITextModel } from 'vs/editor/common/model';
import { IChoiceService } from 'vs/platform/dialogs/common/dialogs';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
export enum ConfigurationEditingErrorCode {
......@@ -127,7 +126,6 @@ export class ConfigurationEditingService {
@IFileService private fileService: IFileService,
@ITextModelService private textModelResolverService: ITextModelService,
@ITextFileService private textFileService: ITextFileService,
@IChoiceService private choiceService: IChoiceService,
@INotificationService private notificationService: INotificationService,
@ICommandService private commandService: ICommandService,
@IWorkbenchEditorService private editorService: IWorkbenchEditorService
......@@ -194,14 +192,14 @@ export class ConfigurationEditingService {
: operation.workspaceStandAloneConfigurationKey === LAUNCH_CONFIGURATION_KEY ? nls.localize('openLaunchConfiguration', "Open Launch Configuration")
: null;
if (openStandAloneConfigurationActionLabel) {
this.choiceService.choose(Severity.Error, error.message, [openStandAloneConfigurationActionLabel])
this.notificationService.prompt(Severity.Error, error.message, [openStandAloneConfigurationActionLabel])
.then(option => {
if (option === 0) {
this.openFile(operation.resource);
}
});
} else {
this.choiceService.choose(Severity.Error, error.message, [nls.localize('open', "Open Settings")])
this.notificationService.prompt(Severity.Error, error.message, [nls.localize('open', "Open Settings")])
.then(option => {
if (option === 0) {
this.openSettings(operation);
......@@ -215,7 +213,7 @@ export class ConfigurationEditingService {
: operation.workspaceStandAloneConfigurationKey === LAUNCH_CONFIGURATION_KEY ? nls.localize('openLaunchConfiguration', "Open Launch Configuration")
: null;
if (openStandAloneConfigurationActionLabel) {
this.choiceService.choose(Severity.Error, error.message, [nls.localize('saveAndRetry', "Save and Retry"), openStandAloneConfigurationActionLabel])
this.notificationService.prompt(Severity.Error, error.message, [nls.localize('saveAndRetry', "Save and Retry"), openStandAloneConfigurationActionLabel])
.then(option => {
switch (option) {
case 0 /* Save & Retry */:
......@@ -228,7 +226,7 @@ export class ConfigurationEditingService {
}
});
} else {
this.choiceService.choose(Severity.Error, error.message, [nls.localize('saveAndRetry', "Save and Retry"), nls.localize('open', "Open Settings")])
this.notificationService.prompt(Severity.Error, error.message, [nls.localize('saveAndRetry', "Save and Retry"), nls.localize('open', "Open Settings")])
.then(option => {
switch (option) {
case 0 /* Save and Retry */:
......
......@@ -34,7 +34,7 @@ import { TextModelResolverService } from 'vs/workbench/services/textmodelResolve
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { IWindowConfiguration } from 'vs/platform/windows/common/windows';
import { mkdirp } from 'vs/base/node/pfs';
import { IChoiceService } from 'vs/platform/dialogs/common/dialogs';
import { INotificationService } from 'vs/platform/notification/common/notification';
class SettingsTestEnvironmentService extends EnvironmentService {
......@@ -176,7 +176,7 @@ suite('ConfigurationEditingService', () => {
test('do not notify error', () => {
instantiationService.stub(ITextFileService, 'isDirty', true);
const target = sinon.stub();
instantiationService.stubPromise(IChoiceService, 'choose', target);
instantiationService.stubPromise(INotificationService, 'prompt', target);
return testObject.writeConfiguration(ConfigurationTarget.USER, { key: 'configurationEditing.service.testSetting', value: 'value' }, { donotNotifyError: true })
.then(() => assert.fail('Should fail with ERROR_CONFIGURATION_FILE_DIRTY error.'),
(error: ConfigurationEditingError) => {
......
......@@ -36,7 +36,6 @@ import { IRemoteConsoleLog, log, parse } from 'vs/base/node/console';
import { getScopes } from 'vs/platform/configuration/common/configurationRegistry';
import { ILogService } from 'vs/platform/log/common/log';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { IChoiceService } from 'vs/platform/dialogs/common/dialogs';
export class ExtensionHostProcessWorker {
......@@ -73,7 +72,6 @@ export class ExtensionHostProcessWorker {
@IWorkspaceConfigurationService private readonly _configurationService: IWorkspaceConfigurationService,
@ITelemetryService private readonly _telemetryService: ITelemetryService,
@ICrashReporterService private readonly _crashReporterService: ICrashReporterService,
@IChoiceService private readonly _choiceService: IChoiceService,
@ILogService private readonly _logService: ILogService
) {
// handle extension host lifecycle a bit special when we know we are developing an extension that runs inside
......@@ -238,7 +236,7 @@ export class ExtensionHostProcessWorker {
? nls.localize('extensionHostProcess.startupFailDebug', "Extension host did not start in 10 seconds, it might be stopped on the first line and needs a debugger to continue.")
: nls.localize('extensionHostProcess.startupFail', "Extension host did not start in 10 seconds, that might be a problem.");
this._choiceService.choose(Severity.Warning, msg, [nls.localize('reloadWindow', "Reload Window")]).then(choice => {
this._notificationService.prompt(Severity.Warning, msg, [nls.localize('reloadWindow', "Reload Window")]).then(choice => {
if (choice === 0) {
this._windowService.reloadWindow();
}
......
......@@ -41,7 +41,6 @@ import product from 'vs/platform/node/product';
import * as strings from 'vs/base/common/strings';
import { RPCProtocol } from 'vs/workbench/services/extensions/node/rpcProtocol';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { IChoiceService } from 'vs/platform/dialogs/common/dialogs';
let _SystemExtensionsRoot: string = null;
function getSystemExtensionsRoot(): string {
......@@ -144,7 +143,6 @@ export class ExtensionService extends Disposable implements IExtensionService {
constructor(
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@INotificationService private readonly _notificationService: INotificationService,
@IChoiceService private readonly _choiceService: IChoiceService,
@IEnvironmentService private readonly _environmentService: IEnvironmentService,
@ITelemetryService private readonly _telemetryService: ITelemetryService,
@IExtensionEnablementService private readonly _extensionEnablementService: IExtensionEnablementService,
......@@ -280,7 +278,7 @@ export class ExtensionService extends Disposable implements IExtensionService {
message = nls.localize('extensionHostProcess.unresponsiveCrash', "Extension host terminated because it was not responsive.");
}
this._choiceService.choose(Severity.Error, message, [nls.localize('devTools', "Developer Tools"), nls.localize('restart', "Restart Extension Host")]).then(choice => {
this._notificationService.prompt(Severity.Error, message, [nls.localize('devTools', "Developer Tools"), nls.localize('restart', "Restart Extension Host")]).then(choice => {
switch (choice) {
case 0 /* Open Dev Tools */:
this._windowService.openDevTools();
......@@ -455,7 +453,7 @@ export class ExtensionService extends Disposable implements IExtensionService {
this._logOrShowMessage(severity, this._isDev ? messageWithSource2(source, message) : message);
});
return ExtensionService._scanInstalledExtensions(this._windowService, this._choiceService, this._environmentService, log)
return ExtensionService._scanInstalledExtensions(this._windowService, this._notificationService, this._environmentService, log)
.then(({ system, user, development }) => {
return this._extensionEnablementService.getDisabledExtensions()
.then(disabledExtensions => {
......@@ -547,7 +545,7 @@ export class ExtensionService extends Disposable implements IExtensionService {
}
}
private static async _validateExtensionsCache(windowService: IWindowService, choiceService: IChoiceService, environmentService: IEnvironmentService, cacheKey: string, input: ExtensionScannerInput): TPromise<void> {
private static async _validateExtensionsCache(windowService: IWindowService, notificationService: INotificationService, environmentService: IEnvironmentService, cacheKey: string, input: ExtensionScannerInput): TPromise<void> {
const cacheFolder = path.join(environmentService.userDataPath, MANIFEST_CACHE_FOLDER);
const cacheFile = path.join(cacheFolder, cacheKey);
......@@ -572,7 +570,7 @@ export class ExtensionService extends Disposable implements IExtensionService {
console.error(err);
}
choiceService.choose(Severity.Error, nls.localize('extensionCache.invalid', "Extensions have been modified on disk. Please reload the window."), [nls.localize('reloadWindow', "Reload Window")]).then(choice => {
notificationService.prompt(Severity.Error, nls.localize('extensionCache.invalid', "Extensions have been modified on disk. Please reload the window."), [nls.localize('reloadWindow', "Reload Window")]).then(choice => {
if (choice === 0) {
windowService.reloadWindow();
}
......@@ -610,7 +608,7 @@ export class ExtensionService extends Disposable implements IExtensionService {
}
}
private static async _scanExtensionsWithCache(windowService: IWindowService, choiceService: IChoiceService, environmentService: IEnvironmentService, cacheKey: string, input: ExtensionScannerInput, log: ILog): TPromise<IExtensionDescription[]> {
private static async _scanExtensionsWithCache(windowService: IWindowService, notificationService: INotificationService, environmentService: IEnvironmentService, cacheKey: string, input: ExtensionScannerInput, log: ILog): TPromise<IExtensionDescription[]> {
if (input.devMode) {
// Do not cache when running out of sources...
return ExtensionScanner.scanExtensions(input, log);
......@@ -628,7 +626,7 @@ export class ExtensionService extends Disposable implements IExtensionService {
// Validate the cache asynchronously after 5s
setTimeout(async () => {
try {
await this._validateExtensionsCache(windowService, choiceService, environmentService, cacheKey, input);
await this._validateExtensionsCache(windowService, notificationService, environmentService, cacheKey, input);
} catch (err) {
errors.onUnexpectedError(err);
}
......@@ -650,7 +648,7 @@ export class ExtensionService extends Disposable implements IExtensionService {
return result;
}
private static _scanInstalledExtensions(windowService: IWindowService, choiceService: IChoiceService, environmentService: IEnvironmentService, log: ILog): TPromise<{ system: IExtensionDescription[], user: IExtensionDescription[], development: IExtensionDescription[] }> {
private static _scanInstalledExtensions(windowService: IWindowService, notificationService: INotificationService, environmentService: IEnvironmentService, log: ILog): TPromise<{ system: IExtensionDescription[], user: IExtensionDescription[], development: IExtensionDescription[] }> {
const translationConfig: TPromise<Translations> = platform.translationsConfigFile
? pfs.readFile(platform.translationsConfigFile, 'utf8').then((content) => {
......@@ -672,7 +670,7 @@ export class ExtensionService extends Disposable implements IExtensionService {
const builtinExtensions = this._scanExtensionsWithCache(
windowService,
choiceService,
notificationService,
environmentService,
BUILTIN_MANIFEST_CACHE_FILE,
new ExtensionScannerInput(version, commit, locale, devMode, getSystemExtensionsRoot(), true, translations),
......@@ -726,7 +724,7 @@ export class ExtensionService extends Disposable implements IExtensionService {
? TPromise.as([])
: this._scanExtensionsWithCache(
windowService,
choiceService,
notificationService,
environmentService,
USER_MANIFEST_CACHE_FILE,
new ExtensionScannerInput(version, commit, locale, devMode, environmentService.extensionsPath, false, translations),
......
......@@ -24,8 +24,7 @@ import { ITextResourceConfigurationService } from 'vs/editor/common/services/res
import { isMacintosh, isWindows } from 'vs/base/common/platform';
import product from 'vs/platform/node/product';
import { Schemas } from 'vs/base/common/network';
import { Severity } from 'vs/platform/notification/common/notification';
import { IChoiceService, Choice } from 'vs/platform/dialogs/common/dialogs';
import { Severity, INotificationService, PromptOption } from 'vs/platform/notification/common/notification';
export class FileService implements IFileService {
......@@ -50,7 +49,7 @@ export class FileService implements IFileService {
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IEnvironmentService private environmentService: IEnvironmentService,
@ILifecycleService private lifecycleService: ILifecycleService,
@IChoiceService private choiceService: IChoiceService,
@INotificationService private notificationService: INotificationService,
@IStorageService private storageService: IStorageService,
@ITextResourceConfigurationService textResourceConfigurationService: ITextResourceConfigurationService
) {
......@@ -109,8 +108,8 @@ export class FileService implements IFileService {
// Detect if we run < .NET Framework 4.5 (TODO@ben remove with new watcher impl)
if (msg.indexOf(FileService.NET_VERSION_ERROR) >= 0 && !this.storageService.getBoolean(FileService.NET_VERSION_ERROR_IGNORE_KEY, StorageScope.WORKSPACE)) {
const choices: Choice[] = [nls.localize('installNet', "Download .NET Framework 4.5"), { label: nls.localize('neverShowAgain', "Don't Show Again") }];
this.choiceService.choose(Severity.Warning, nls.localize('netVersionError', "The Microsoft .NET Framework 4.5 is required. Please follow the link to install it."), choices).then(choice => {
const choices: PromptOption[] = [nls.localize('installNet', "Download .NET Framework 4.5"), { label: nls.localize('neverShowAgain', "Don't Show Again") }];
this.notificationService.prompt(Severity.Warning, nls.localize('netVersionError', "The Microsoft .NET Framework 4.5 is required. Please follow the link to install it."), choices).then(choice => {
switch (choice) {
case 0 /* Read More */:
window.open('https://go.microsoft.com/fwlink/?LinkId=786533');
......@@ -124,8 +123,8 @@ export class FileService implements IFileService {
// Detect if we run into ENOSPC issues
if (msg.indexOf(FileService.ENOSPC_ERROR) >= 0 && !this.storageService.getBoolean(FileService.ENOSPC_ERROR_IGNORE_KEY, StorageScope.WORKSPACE)) {
const choices: Choice[] = [nls.localize('learnMore', "Instructions"), { label: nls.localize('neverShowAgain', "Don't Show Again") }];
this.choiceService.choose(Severity.Warning, nls.localize('enospcError', "{0} is running out of file handles. Please follow the instructions link to resolve this issue.", product.nameLong), choices).then(choice => {
const choices: PromptOption[] = [nls.localize('learnMore', "Instructions"), { label: nls.localize('neverShowAgain', "Don't Show Again") }];
this.notificationService.prompt(Severity.Warning, nls.localize('enospcError', "{0} is running out of file handles. Please follow the instructions link to resolve this issue.", product.nameLong), choices).then(choice => {
switch (choice) {
case 0 /* Read More */:
window.open('https://go.microsoft.com/fwlink/?linkid=867693');
......
......@@ -25,7 +25,7 @@ import { IExtensionService } from 'vs/workbench/services/extensions/common/exten
import { maxBufferLen, detectMimeAndEncodingFromBuffer } from 'vs/base/node/mime';
import { MIME_BINARY } from 'vs/base/common/mime';
import { localize } from 'vs/nls';
import { IChoiceService } from 'vs/platform/dialogs/common/dialogs';
import { INotificationService } from 'vs/platform/notification/common/notification';
function toIFileStat(provider: IFileSystemProvider, tuple: [URI, IStat], recurse?: (tuple: [URI, IStat]) => boolean): TPromise<IFileStat> {
const [resource, stat] = tuple;
......@@ -86,7 +86,7 @@ export class RemoteFileService extends FileService {
@IWorkspaceContextService contextService: IWorkspaceContextService,
@IEnvironmentService environmentService: IEnvironmentService,
@ILifecycleService lifecycleService: ILifecycleService,
@IChoiceService choiceService: IChoiceService,
@INotificationService notificationService: INotificationService,
@ITextResourceConfigurationService textResourceConfigurationService: ITextResourceConfigurationService,
) {
super(
......@@ -94,7 +94,7 @@ export class RemoteFileService extends FileService {
contextService,
environmentService,
lifecycleService,
choiceService,
notificationService,
_storageService,
textResourceConfigurationService,
);
......
......@@ -5,9 +5,12 @@
'use strict';
import { INotificationService, INotification, INotificationHandle, Severity, NotificationMessage } from 'vs/platform/notification/common/notification';
import { INotificationService, INotification, INotificationHandle, Severity, NotificationMessage, PromptOption, INotificationActions } from 'vs/platform/notification/common/notification';
import { INotificationsModel, NotificationsModel } from 'vs/workbench/common/notifications';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { TPromise } from 'vs/base/common/winjs.base';
import { Action } from 'vs/base/common/actions';
import { once } from 'vs/base/common/event';
export class NotificationService implements INotificationService {
......@@ -62,6 +65,60 @@ export class NotificationService implements INotificationService {
return this.model.notify(notification);
}
public prompt(severity: Severity, message: string, choices: PromptOption[]): TPromise<number> {
let handle: INotificationHandle;
const promise = new TPromise<number>((c, e) => {
// Complete promise with index of action that was picked
const callback = (index: number, closeNotification: boolean) => () => {
c(index);
if (closeNotification) {
handle.dispose();
}
return TPromise.as(void 0);
};
// Convert choices into primary/secondary actions
const actions: INotificationActions = {
primary: [],
secondary: []
};
choices.forEach((choice, index) => {
let isPrimary = true;
let label: string;
let closeNotification = false;
if (typeof choice === 'string') {
label = choice;
} else {
isPrimary = false;
label = choice.label;
closeNotification = !choice.keepOpen;
}
const action = new Action(`workbench.dialog.choice.${index}`, label, null, true, callback(index, closeNotification));
if (isPrimary) {
actions.primary.push(action);
} else {
actions.secondary.push(action);
}
});
// Show notification with actions
handle = this.notify({ severity, message, actions });
// Cancel promise when notification gets disposed
once(handle.onDidDispose)(() => promise.cancel());
}, () => handle.dispose());
return promise;
}
public dispose(): void {
this.toDispose = dispose(this.toDispose);
}
......
......@@ -27,7 +27,6 @@ import { ICommandService } from 'vs/platform/commands/common/commands';
import { distinct } from 'vs/base/common/arrays';
import { isLinux } from 'vs/base/common/platform';
import { isEqual } from 'vs/base/common/resources';
import { IChoiceService } from 'vs/platform/dialogs/common/dialogs';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
export class WorkspaceEditingService implements IWorkspaceEditingService {
......@@ -42,7 +41,6 @@ export class WorkspaceEditingService implements IWorkspaceEditingService {
@IStorageService private storageService: IStorageService,
@IExtensionService private extensionService: IExtensionService,
@IBackupFileService private backupFileService: IBackupFileService,
@IChoiceService private choiceService: IChoiceService,
@INotificationService private notificationService: INotificationService,
@ICommandService private commandService: ICommandService
) {
......@@ -176,7 +174,7 @@ export class WorkspaceEditingService implements IWorkspaceEditingService {
}
private askToOpenWorkspaceConfigurationFile(message: string): TPromise<void> {
return this.choiceService.choose(Severity.Error, message, [nls.localize('openWorkspaceConfigurationFile', "Open Workspace Configuration")])
return this.notificationService.prompt(Severity.Error, message, [nls.localize('openWorkspaceConfigurationFile', "Open Workspace Configuration")])
.then(option => {
if (option === 0) {
this.commandService.executeCommand('workbench.action.openWorkspaceConfigFile');
......
......@@ -9,7 +9,7 @@ import * as assert from 'assert';
import { MainThreadMessageService } from 'vs/workbench/api/electron-browser/mainThreadMessageService';
import { TPromise as Promise, TPromise } from 'vs/base/common/winjs.base';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { INotificationService, INotification, NoOpNotification, INotificationHandle } from 'vs/platform/notification/common/notification';
import { INotificationService, INotification, NoOpNotification, INotificationHandle, PromptOption, Severity } from 'vs/platform/notification/common/notification';
import { ICommandService } from 'vs/platform/commands/common/commands';
const emptyDialogService = new class implements IDialogService {
......@@ -45,6 +45,9 @@ const emptyNotificationService = new class implements INotificationService {
error(...args: any[]): never {
throw new Error('not implemented');
}
prompt(severity: Severity, message: string, choices: PromptOption[]): TPromise<number> {
throw new Error('not implemented');
}
};
class EmptyNotificationService implements INotificationService {
......@@ -68,6 +71,9 @@ class EmptyNotificationService implements INotificationService {
error(message: any): void {
throw new Error('Method not implemented.');
}
prompt(severity: Severity, message: string, choices: PromptOption[]): Promise<number, any> {
throw new Error('Method not implemented.');
}
}
suite('ExtHostMessageService', function () {
......
......@@ -62,8 +62,8 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
import { ITextBufferFactory, DefaultEndOfLine, EndOfLinePreference } from 'vs/editor/common/model';
import { Range } from 'vs/editor/common/core/range';
import { IChoiceService, IConfirmation, IConfirmationResult, IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { INotificationService, INotificationHandle, INotification, NoOpNotification } from 'vs/platform/notification/common/notification';
import { IConfirmation, IConfirmationResult, IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { INotificationService, INotificationHandle, INotification, NoOpNotification, PromptOption } from 'vs/platform/notification/common/notification';
export function createFileInput(instantiationService: IInstantiationService, resource: URI): FileEditorInput {
return instantiationService.createInstance(FileEditorInput, resource, void 0);
......@@ -263,11 +263,6 @@ export function workbenchInstantiationService(): IInstantiationService {
instantiationService.stub(IEnvironmentService, TestEnvironmentService);
instantiationService.stub(IThemeService, new TestThemeService());
instantiationService.stub(IHashService, new TestHashService());
instantiationService.stub(IChoiceService, {
choose: (severity, message, options): TPromise<number> => {
return TPromise.as(0);
}
} as IChoiceService);
return instantiationService;
}
......@@ -331,6 +326,10 @@ export class TestNotificationService implements INotificationService {
public notify(notification: INotification): INotificationHandle {
return TestNotificationService.NO_OP;
}
public prompt(severity: Severity, message: string, choices: PromptOption[]): TPromise<number> {
return TPromise.as(0);
}
}
export class TestDialogService implements IDialogService {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册