mirror of
https://github.com/Microsoft/vscode
synced 2024-10-12 14:30:13 +00:00
debt - remove dependency of keybinding service to status bar service
This commit is contained in:
parent
7908cea2d8
commit
fa3b4d7c28
|
@ -8,7 +8,7 @@ import * as dom from 'vs/base/browser/dom';
|
|||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Keybinding, ResolvedKeybinding, SimpleKeybinding, createKeybinding } from 'vs/base/common/keyCodes';
|
||||
import { IDisposable, IReference, ImmortalReference, toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IDisposable, IReference, ImmortalReference, toDisposable, DisposableStore, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { OS, isLinux, isMacintosh } from 'vs/base/common/platform';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
|
@ -37,7 +37,7 @@ import { IKeybindingItem, KeybindingsRegistry } from 'vs/platform/keybinding/com
|
|||
import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
|
||||
import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding';
|
||||
import { ILabelService, ResourceLabelFormatter } from 'vs/platform/label/common/label';
|
||||
import { INotification, INotificationHandle, INotificationService, IPromptChoice, IPromptOptions, NoOpNotification } from 'vs/platform/notification/common/notification';
|
||||
import { INotification, INotificationHandle, INotificationService, IPromptChoice, IPromptOptions, NoOpNotification, IStatusMessageOptions } from 'vs/platform/notification/common/notification';
|
||||
import { IProgressRunner, ILocalProgressService } from 'vs/platform/progress/common/progress';
|
||||
import { ITelemetryInfo, ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IWorkspace, IWorkspaceContextService, IWorkspaceFolder, IWorkspaceFoldersChangeEvent, WorkbenchState, WorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
|
@ -220,6 +220,10 @@ export class SimpleNotificationService implements INotificationService {
|
|||
public prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions): INotificationHandle {
|
||||
return SimpleNotificationService.NO_OP;
|
||||
}
|
||||
|
||||
public status(message: string | Error, options?: IStatusMessageOptions): IDisposable {
|
||||
return Disposable.None;
|
||||
}
|
||||
}
|
||||
|
||||
export class StandaloneCommandService implements ICommandService {
|
||||
|
|
|
@ -15,7 +15,6 @@ import { IKeybindingEvent, IKeybindingService, IKeyboardEvent } from 'vs/platfor
|
|||
import { IResolveResult, KeybindingResolver } from 'vs/platform/keybinding/common/keybindingResolver';
|
||||
import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { IStatusbarService } from 'vs/platform/statusbar/common/statusbar';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
|
||||
interface CurrentChord {
|
||||
|
@ -26,45 +25,32 @@ interface CurrentChord {
|
|||
export abstract class AbstractKeybindingService extends Disposable implements IKeybindingService {
|
||||
public _serviceBrand: any;
|
||||
|
||||
protected readonly _onDidUpdateKeybindings: Emitter<IKeybindingEvent> = this._register(new Emitter<IKeybindingEvent>());
|
||||
get onDidUpdateKeybindings(): Event<IKeybindingEvent> {
|
||||
return this._onDidUpdateKeybindings ? this._onDidUpdateKeybindings.event : Event.None; // Sinon stubbing walks properties on prototype
|
||||
}
|
||||
|
||||
private _currentChord: CurrentChord | null;
|
||||
private _currentChordChecker: IntervalTimer;
|
||||
private _currentChordStatusMessage: IDisposable | null;
|
||||
protected _onDidUpdateKeybindings: Emitter<IKeybindingEvent>;
|
||||
|
||||
private _contextKeyService: IContextKeyService;
|
||||
private _statusService: IStatusbarService | undefined;
|
||||
private _notificationService: INotificationService;
|
||||
protected _commandService: ICommandService;
|
||||
protected _telemetryService: ITelemetryService;
|
||||
|
||||
constructor(
|
||||
contextKeyService: IContextKeyService,
|
||||
commandService: ICommandService,
|
||||
telemetryService: ITelemetryService,
|
||||
notificationService: INotificationService,
|
||||
statusService?: IStatusbarService
|
||||
private _contextKeyService: IContextKeyService,
|
||||
protected _commandService: ICommandService,
|
||||
protected _telemetryService: ITelemetryService,
|
||||
private _notificationService: INotificationService,
|
||||
) {
|
||||
super();
|
||||
this._contextKeyService = contextKeyService;
|
||||
this._commandService = commandService;
|
||||
this._telemetryService = telemetryService;
|
||||
this._statusService = statusService;
|
||||
this._notificationService = notificationService;
|
||||
|
||||
this._currentChord = null;
|
||||
this._currentChordChecker = new IntervalTimer();
|
||||
this._currentChordStatusMessage = null;
|
||||
this._onDidUpdateKeybindings = this._register(new Emitter<IKeybindingEvent>());
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
get onDidUpdateKeybindings(): Event<IKeybindingEvent> {
|
||||
return this._onDidUpdateKeybindings ? this._onDidUpdateKeybindings.event : Event.None; // Sinon stubbing walks properties on prototype
|
||||
}
|
||||
|
||||
protected abstract _getResolver(): KeybindingResolver;
|
||||
protected abstract _documentHasFocus(): boolean;
|
||||
public abstract resolveKeybinding(keybinding: Keybinding): ResolvedKeybinding[];
|
||||
|
@ -128,9 +114,7 @@ export abstract class AbstractKeybindingService extends Disposable implements IK
|
|||
keypress: firstPart,
|
||||
label: keypressLabel
|
||||
};
|
||||
if (this._statusService) {
|
||||
this._currentChordStatusMessage = this._statusService.setStatusMessage(nls.localize('first.chord', "({0}) was pressed. Waiting for second key of chord...", keypressLabel));
|
||||
}
|
||||
this._currentChordStatusMessage = this._notificationService.status(nls.localize('first.chord', "({0}) was pressed. Waiting for second key of chord...", keypressLabel));
|
||||
const chordEnterTime = Date.now();
|
||||
this._currentChordChecker.cancelAndSet(() => {
|
||||
|
||||
|
@ -192,9 +176,9 @@ export abstract class AbstractKeybindingService extends Disposable implements IK
|
|||
return shouldPreventDefault;
|
||||
}
|
||||
|
||||
if (this._statusService && this._currentChord) {
|
||||
if (this._currentChord) {
|
||||
if (!resolveResult || !resolveResult.commandId) {
|
||||
this._statusService.setStatusMessage(nls.localize('missing.chord', "The key combination ({0}, {1}) is not a command.", this._currentChord.label, keypressLabel), 10 * 1000 /* 10s */);
|
||||
this._notificationService.status(nls.localize('missing.chord', "The key combination ({0}, {1}) is not a command.", this._currentChord.label, keypressLabel), { hideAfter: 10 * 1000 /* 10s */ });
|
||||
shouldPreventDefault = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as assert from 'assert';
|
||||
import { KeyChord, KeyCode, KeyMod, Keybinding, ResolvedKeybinding, SimpleKeybinding, createKeybinding, createSimpleKeybinding } from 'vs/base/common/keyCodes';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { OS } from 'vs/base/common/platform';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
|
@ -14,9 +13,9 @@ import { IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding';
|
|||
import { KeybindingResolver } from 'vs/platform/keybinding/common/keybindingResolver';
|
||||
import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
|
||||
import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding';
|
||||
import { INotification, INotificationService, IPromptChoice, IPromptOptions, NoOpNotification } from 'vs/platform/notification/common/notification';
|
||||
import { IStatusbarService } from 'vs/platform/statusbar/common/statusbar';
|
||||
import { INotification, INotificationService, IPromptChoice, IPromptOptions, NoOpNotification, IStatusMessageOptions } from 'vs/platform/notification/common/notification';
|
||||
import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
function createContext(ctx: any) {
|
||||
return {
|
||||
|
@ -35,10 +34,9 @@ suite('AbstractKeybindingService', () => {
|
|||
resolver: KeybindingResolver,
|
||||
contextKeyService: IContextKeyService,
|
||||
commandService: ICommandService,
|
||||
notificationService: INotificationService,
|
||||
statusService?: IStatusbarService
|
||||
notificationService: INotificationService
|
||||
) {
|
||||
super(contextKeyService, commandService, NullTelemetryService, notificationService, statusService);
|
||||
super(contextKeyService, commandService, NullTelemetryService, notificationService);
|
||||
this._resolver = resolver;
|
||||
}
|
||||
|
||||
|
@ -129,7 +127,7 @@ suite('AbstractKeybindingService', () => {
|
|||
};
|
||||
|
||||
let notificationService: INotificationService = {
|
||||
_serviceBrand: undefined,
|
||||
_serviceBrand: {} as ServiceIdentifier<INotificationService>,
|
||||
notify: (notification: INotification) => {
|
||||
showMessageCalls.push({ sev: notification.severity, message: notification.message });
|
||||
return new NoOpNotification();
|
||||
|
@ -148,13 +146,8 @@ suite('AbstractKeybindingService', () => {
|
|||
},
|
||||
prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions) {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
};
|
||||
|
||||
let statusbarService: IStatusbarService = {
|
||||
_serviceBrand: undefined,
|
||||
addEntry: undefined!,
|
||||
setStatusMessage: (message: string, autoDisposeAfter?: number, delayBy?: number): IDisposable => {
|
||||
},
|
||||
status(message: string, options?: IStatusMessageOptions) {
|
||||
statusMessageCalls!.push(message);
|
||||
return {
|
||||
dispose: () => {
|
||||
|
@ -166,7 +159,7 @@ suite('AbstractKeybindingService', () => {
|
|||
|
||||
let resolver = new KeybindingResolver(items, []);
|
||||
|
||||
return new TestKeybindingService(resolver, contextKeyService, commandService, notificationService, statusbarService);
|
||||
return new TestKeybindingService(resolver, contextKeyService, commandService, notificationService);
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
@ -4,9 +4,10 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import BaseSeverity from 'vs/base/common/severity';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
|
||||
export import Severity = BaseSeverity;
|
||||
|
||||
|
@ -172,6 +173,21 @@ export interface IPromptOptions extends INotificationProperties {
|
|||
onCancel?: () => void;
|
||||
}
|
||||
|
||||
export interface IStatusMessageOptions {
|
||||
|
||||
/**
|
||||
* An optional timeout after which the status message should show. By default
|
||||
* the status message will show immediately.
|
||||
*/
|
||||
showAfter?: number;
|
||||
|
||||
/**
|
||||
* An optional timeout after which the status message is to be hidden. By default
|
||||
* the status message will not hide until another status message is displayed.
|
||||
*/
|
||||
hideAfter?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* A service to bring up notifications and non-modal prompts.
|
||||
*
|
||||
|
@ -179,7 +195,7 @@ export interface IPromptOptions extends INotificationProperties {
|
|||
*/
|
||||
export interface INotificationService {
|
||||
|
||||
_serviceBrand: any;
|
||||
_serviceBrand: ServiceIdentifier<INotificationService>;
|
||||
|
||||
/**
|
||||
* Show the provided notification to the user. The returned `INotificationHandle`
|
||||
|
@ -221,16 +237,24 @@ export interface INotificationService {
|
|||
* @returns a handle on the notification to e.g. hide it or update message, buttons, etc.
|
||||
*/
|
||||
prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions): INotificationHandle;
|
||||
|
||||
/**
|
||||
* Shows a status message in the status area with the provied text.
|
||||
*
|
||||
* @param message the message to show as status
|
||||
* @param options provides some optional configuration options
|
||||
*
|
||||
* @returns a disposable to hide the status message
|
||||
*/
|
||||
status(message: NotificationMessage, options?: IStatusMessageOptions): IDisposable;
|
||||
}
|
||||
|
||||
export class NoOpNotification implements INotificationHandle {
|
||||
|
||||
readonly progress = new NoOpProgress();
|
||||
|
||||
private readonly _onDidClose: Emitter<void> = new Emitter();
|
||||
|
||||
get onDidClose(): Event<void> {
|
||||
return this._onDidClose.event;
|
||||
}
|
||||
get onDidClose(): Event<void> { return this._onDidClose.event; }
|
||||
|
||||
updateSeverity(severity: Severity): void { }
|
||||
updateMessage(message: NotificationMessage): void { }
|
||||
|
|
|
@ -3,31 +3,36 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { INotificationService, INotificationHandle, NoOpNotification, Severity, INotification, IPromptChoice, IPromptOptions } from 'vs/platform/notification/common/notification';
|
||||
import { INotificationService, INotificationHandle, NoOpNotification, Severity, INotification, IPromptChoice, IPromptOptions, IStatusMessageOptions } from 'vs/platform/notification/common/notification';
|
||||
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
|
||||
export class TestNotificationService implements INotificationService {
|
||||
|
||||
public _serviceBrand: any;
|
||||
_serviceBrand: any;
|
||||
|
||||
private static readonly NO_OP: INotificationHandle = new NoOpNotification();
|
||||
|
||||
public info(message: string): INotificationHandle {
|
||||
info(message: string): INotificationHandle {
|
||||
return this.notify({ severity: Severity.Info, message });
|
||||
}
|
||||
|
||||
public warn(message: string): INotificationHandle {
|
||||
warn(message: string): INotificationHandle {
|
||||
return this.notify({ severity: Severity.Warning, message });
|
||||
}
|
||||
|
||||
public error(error: string | Error): INotificationHandle {
|
||||
error(error: string | Error): INotificationHandle {
|
||||
return this.notify({ severity: Severity.Error, message: error });
|
||||
}
|
||||
|
||||
public notify(notification: INotification): INotificationHandle {
|
||||
notify(notification: INotification): INotificationHandle {
|
||||
return TestNotificationService.NO_OP;
|
||||
}
|
||||
|
||||
public prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions): INotificationHandle {
|
||||
prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions): INotificationHandle {
|
||||
return TestNotificationService.NO_OP;
|
||||
}
|
||||
|
||||
status(message: string | Error, options?: IStatusMessageOptions): IDisposable {
|
||||
return Disposable.None;
|
||||
}
|
||||
}
|
|
@ -288,7 +288,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {
|
|||
|
||||
// --- Toggle Statusbar Visibility
|
||||
|
||||
class ToggleStatusbarVisibilityAction extends Action {
|
||||
export class ToggleStatusbarVisibilityAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.toggleStatusbarVisibility';
|
||||
static readonly LABEL = nls.localize('toggleStatusbar', "Toggle Status Bar Visibility");
|
||||
|
|
|
@ -181,14 +181,15 @@ export class ActivitybarPart extends Part implements IActivityBarService {
|
|||
|
||||
createContentArea(parent: HTMLElement): HTMLElement {
|
||||
this.element = parent;
|
||||
|
||||
const content = document.createElement('div');
|
||||
addClass(content, 'content');
|
||||
parent.appendChild(content);
|
||||
|
||||
// Top Actionbar with action items for each viewlet action
|
||||
// Viewlets action bar
|
||||
this.compositeBar.create(content);
|
||||
|
||||
// Top Actionbar with action items for each viewlet action
|
||||
// Global action bar
|
||||
const globalActivities = document.createElement('div');
|
||||
addClass(globalActivities, 'global-activity');
|
||||
content.appendChild(globalActivities);
|
||||
|
|
|
@ -3,16 +3,19 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { INotificationsModel, INotificationChangeEvent, NotificationChangeType, INotificationViewItem } from 'vs/workbench/common/notifications';
|
||||
import { INotificationsModel, INotificationChangeEvent, NotificationChangeType, INotificationViewItem, IStatusMessageChangeEvent, StatusMessageChangeType, IStatusMessageViewItem } from 'vs/workbench/common/notifications';
|
||||
import { IStatusbarService, StatusbarAlignment, IStatusbarEntryAccessor, IStatusbarEntry } from 'vs/platform/statusbar/common/statusbar';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { HIDE_NOTIFICATIONS_CENTER, SHOW_NOTIFICATIONS_CENTER } from 'vs/workbench/browser/parts/notifications/notificationsCommands';
|
||||
import { localize } from 'vs/nls';
|
||||
|
||||
export class NotificationsStatus extends Disposable {
|
||||
private statusItem: IStatusbarEntryAccessor;
|
||||
private notificationsCenterStatusItem: IStatusbarEntryAccessor;
|
||||
private isNotificationsCenterVisible: boolean;
|
||||
private _counter: Set<INotificationViewItem>;
|
||||
|
||||
private currentNotifications = new Set<INotificationViewItem>();
|
||||
|
||||
private currentStatusMessage: [IStatusMessageViewItem, IDisposable] | undefined;
|
||||
|
||||
constructor(
|
||||
private model: INotificationsModel,
|
||||
|
@ -20,29 +23,14 @@ export class NotificationsStatus extends Disposable {
|
|||
) {
|
||||
super();
|
||||
|
||||
this._counter = new Set<INotificationViewItem>();
|
||||
|
||||
this.updateNotificationsStatusItem();
|
||||
this.updateNotificationsCenterStatusItem();
|
||||
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
private get count(): number {
|
||||
return this._counter.size;
|
||||
}
|
||||
|
||||
update(isCenterVisible: boolean): void {
|
||||
if (this.isNotificationsCenterVisible !== isCenterVisible) {
|
||||
this.isNotificationsCenterVisible = isCenterVisible;
|
||||
|
||||
// Showing the notification center resets the counter to 0
|
||||
this._counter.clear();
|
||||
this.updateNotificationsStatusItem();
|
||||
}
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
this._register(this.model.onDidNotificationChange(e => this.onDidNotificationChange(e)));
|
||||
this._register(this.model.onDidStatusMessageChange(e => this.onDidStatusMessageChange(e)));
|
||||
}
|
||||
|
||||
private onDidNotificationChange(e: INotificationChangeEvent): void {
|
||||
|
@ -52,29 +40,29 @@ export class NotificationsStatus extends Disposable {
|
|||
|
||||
// Notification got Added
|
||||
if (e.kind === NotificationChangeType.ADD) {
|
||||
this._counter.add(e.item);
|
||||
this.currentNotifications.add(e.item);
|
||||
}
|
||||
|
||||
// Notification got Removed
|
||||
else if (e.kind === NotificationChangeType.REMOVE) {
|
||||
this._counter.delete(e.item);
|
||||
this.currentNotifications.delete(e.item);
|
||||
}
|
||||
|
||||
this.updateNotificationsStatusItem();
|
||||
this.updateNotificationsCenterStatusItem();
|
||||
}
|
||||
|
||||
private updateNotificationsStatusItem(): void {
|
||||
private updateNotificationsCenterStatusItem(): void {
|
||||
const statusProperties: IStatusbarEntry = {
|
||||
text: this.count === 0 ? '$(bell)' : `$(bell) ${this.count}`,
|
||||
text: this.currentNotifications.size === 0 ? '$(bell)' : `$(bell) ${this.currentNotifications.size}`,
|
||||
command: this.isNotificationsCenterVisible ? HIDE_NOTIFICATIONS_CENTER : SHOW_NOTIFICATIONS_CENTER,
|
||||
tooltip: this.getTooltip(),
|
||||
showBeak: this.isNotificationsCenterVisible
|
||||
};
|
||||
|
||||
if (!this.statusItem) {
|
||||
this.statusItem = this.statusbarService.addEntry(statusProperties, StatusbarAlignment.RIGHT, -1000 /* towards the far end of the right hand side */);
|
||||
if (!this.notificationsCenterStatusItem) {
|
||||
this.notificationsCenterStatusItem = this.statusbarService.addEntry(statusProperties, StatusbarAlignment.RIGHT, -1000 /* towards the far end of the right hand side */);
|
||||
} else {
|
||||
this.statusItem.update(statusProperties);
|
||||
this.notificationsCenterStatusItem.update(statusProperties);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,14 +75,52 @@ export class NotificationsStatus extends Disposable {
|
|||
return localize('zeroNotifications', "No Notifications");
|
||||
}
|
||||
|
||||
if (this.count === 0) {
|
||||
if (this.currentNotifications.size === 0) {
|
||||
return localize('noNotifications', "No New Notifications");
|
||||
}
|
||||
|
||||
if (this.count === 1) {
|
||||
if (this.currentNotifications.size === 1) {
|
||||
return localize('oneNotification', "1 New Notification");
|
||||
}
|
||||
|
||||
return localize('notifications', "{0} New Notifications", this.count);
|
||||
return localize('notifications', "{0} New Notifications", this.currentNotifications.size);
|
||||
}
|
||||
|
||||
update(isCenterVisible: boolean): void {
|
||||
if (this.isNotificationsCenterVisible !== isCenterVisible) {
|
||||
this.isNotificationsCenterVisible = isCenterVisible;
|
||||
|
||||
// Showing the notification center resets the counter to 0
|
||||
this.currentNotifications.clear();
|
||||
this.updateNotificationsCenterStatusItem();
|
||||
}
|
||||
}
|
||||
|
||||
private onDidStatusMessageChange(e: IStatusMessageChangeEvent): void {
|
||||
const statusItem = e.item;
|
||||
|
||||
switch (e.kind) {
|
||||
|
||||
// Show status notification
|
||||
case StatusMessageChangeType.ADD:
|
||||
const showAfter = statusItem.options ? statusItem.options.showAfter : undefined;
|
||||
const hideAfter = statusItem.options ? statusItem.options.hideAfter : undefined;
|
||||
|
||||
this.currentStatusMessage = [
|
||||
statusItem,
|
||||
this.statusbarService.setStatusMessage(statusItem.message, hideAfter, showAfter)
|
||||
];
|
||||
|
||||
break;
|
||||
|
||||
// Hide status notification (if its still the current one)
|
||||
case StatusMessageChangeType.REMOVE:
|
||||
if (this.currentStatusMessage && this.currentStatusMessage[0] === statusItem) {
|
||||
this.currentStatusMessage[1].dispose();
|
||||
this.currentStatusMessage = undefined;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,25 +17,27 @@ import { IInstantiationService, ServiceIdentifier } from 'vs/platform/instantiat
|
|||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { StatusbarAlignment, IStatusbarService, IStatusbarEntry, IStatusbarEntryAccessor } from 'vs/platform/statusbar/common/statusbar';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { Action, IAction } from 'vs/base/common/actions';
|
||||
import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector, ThemeColor } from 'vs/platform/theme/common/themeService';
|
||||
import { STATUS_BAR_BACKGROUND, STATUS_BAR_FOREGROUND, STATUS_BAR_NO_FOLDER_BACKGROUND, STATUS_BAR_ITEM_HOVER_BACKGROUND, STATUS_BAR_ITEM_ACTIVE_BACKGROUND, STATUS_BAR_PROMINENT_ITEM_FOREGROUND, STATUS_BAR_PROMINENT_ITEM_BACKGROUND, STATUS_BAR_PROMINENT_ITEM_HOVER_BACKGROUND, STATUS_BAR_BORDER, STATUS_BAR_NO_FOLDER_FOREGROUND, STATUS_BAR_NO_FOLDER_BORDER } from 'vs/workbench/common/theme';
|
||||
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
import { contrastBorder } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { isThemeColor } from 'vs/editor/common/editorCommon';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { addClass, EventHelper, createStyleSheet, addDisposableListener, addClasses, clearNode, removeClass } from 'vs/base/browser/dom';
|
||||
import { addClass, EventHelper, createStyleSheet, addDisposableListener, addClasses, clearNode, removeClass, EventType } from 'vs/base/browser/dom';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { Parts, IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { coalesce } from 'vs/base/common/arrays';
|
||||
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { ToggleStatusbarVisibilityAction } from 'vs/workbench/browser/actions/layoutActions';
|
||||
|
||||
interface PendingEntry { entry: IStatusbarEntry; alignment: StatusbarAlignment; priority: number; accessor?: IStatusbarEntryAccessor; }
|
||||
|
||||
export class StatusbarPart extends Part implements IStatusbarService {
|
||||
|
||||
_serviceBrand: ServiceIdentifier<any>;
|
||||
_serviceBrand: ServiceIdentifier<IStatusbarService>;
|
||||
|
||||
private static readonly PRIORITY_PROP = 'statusbar-entry-priority';
|
||||
private static readonly ALIGNMENT_PROP = 'statusbar-entry-alignment';
|
||||
|
@ -54,15 +56,20 @@ export class StatusbarPart extends Part implements IStatusbarService {
|
|||
|
||||
private pendingEntries: PendingEntry[] = [];
|
||||
|
||||
private hideStatusBarAction: ToggleStatusbarVisibilityAction;
|
||||
|
||||
constructor(
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
|
||||
@IStorageService storageService: IStorageService,
|
||||
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService
|
||||
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
|
||||
@IContextMenuService private contextMenuService: IContextMenuService
|
||||
) {
|
||||
super(Parts.STATUSBAR_PART, { hasTitle: false }, themeService, storageService, layoutService);
|
||||
|
||||
this.hideStatusBarAction = this._register(this.instantiationService.createInstance(ToggleStatusbarVisibilityAction, ToggleStatusbarVisibilityAction.ID, nls.localize('hideStatusBar', "Hide Status Bar")));
|
||||
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
|
@ -161,6 +168,9 @@ export class StatusbarPart extends Part implements IStatusbarService {
|
|||
createContentArea(parent: HTMLElement): HTMLElement {
|
||||
this.element = parent;
|
||||
|
||||
// Context menu support
|
||||
this._register(addDisposableListener(parent, EventType.CONTEXT_MENU, e => this.showContextMenu(e)));
|
||||
|
||||
// Fill in initial items that were contributed from the registry
|
||||
const registry = Registry.as<IStatusbarRegistry>(Extensions.Statusbar);
|
||||
|
||||
|
@ -199,6 +209,39 @@ export class StatusbarPart extends Part implements IStatusbarService {
|
|||
return this.element;
|
||||
}
|
||||
|
||||
private showContextMenu(e: MouseEvent): void {
|
||||
EventHelper.stop(e, true);
|
||||
|
||||
const event = new StandardMouseEvent(e);
|
||||
this.contextMenuService.showContextMenu({
|
||||
getAnchor: () => { return { x: event.posx, y: event.posy }; },
|
||||
getActions: () => this.getContextMenuActions()
|
||||
});
|
||||
}
|
||||
|
||||
private getContextMenuActions(): IAction[] {
|
||||
const actions: IAction[] = [];
|
||||
|
||||
// TODO@Ben collect more context menu actions
|
||||
// .map(({ id, name, activityAction }) => (<IAction>{
|
||||
// id,
|
||||
// label: name || id,
|
||||
// checked: this.isPinned(id),
|
||||
// run: () => {
|
||||
// if (this.isPinned(id)) {
|
||||
// this.unpin(id);
|
||||
// } else {
|
||||
// this.pin(id, true);
|
||||
// }
|
||||
// }
|
||||
// }));
|
||||
// actions.push(new Separator());
|
||||
|
||||
actions.push(this.hideStatusBarAction);
|
||||
|
||||
return actions;
|
||||
}
|
||||
|
||||
updateStyles(): void {
|
||||
super.updateStyles();
|
||||
|
||||
|
@ -253,9 +296,9 @@ export class StatusbarPart extends Part implements IStatusbarService {
|
|||
statusMessageEntry = this.addEntry({ text: message }, StatusbarAlignment.LEFT, -Number.MAX_VALUE /* far right on left hand side */);
|
||||
showHandle = null;
|
||||
}, delayBy);
|
||||
let hideHandle: any;
|
||||
|
||||
// Dispose function takes care of timeouts and actual entry
|
||||
let hideHandle: any;
|
||||
const statusMessageDispose = {
|
||||
dispose: () => {
|
||||
if (showHandle) {
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { INotification, INotificationHandle, INotificationActions, INotificationProgress, NoOpNotification, Severity, NotificationMessage, IPromptChoice } from 'vs/platform/notification/common/notification';
|
||||
import { INotification, INotificationHandle, INotificationActions, INotificationProgress, NoOpNotification, Severity, NotificationMessage, IPromptChoice, IStatusMessageOptions } from 'vs/platform/notification/common/notification';
|
||||
import { toErrorMessage } from 'vs/base/common/errorMessage';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { isPromiseCanceledError } from 'vs/base/common/errors';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { isErrorWithActions } from 'vs/base/common/errorsWithActions';
|
||||
|
@ -15,10 +15,25 @@ import { localize } from 'vs/nls';
|
|||
|
||||
export interface INotificationsModel {
|
||||
|
||||
//
|
||||
// Notifications as Toasts/Center
|
||||
//
|
||||
|
||||
readonly notifications: INotificationViewItem[];
|
||||
|
||||
readonly onDidNotificationChange: Event<INotificationChangeEvent>;
|
||||
|
||||
notify(notification: INotification): INotificationHandle;
|
||||
addNotification(notification: INotification): INotificationHandle;
|
||||
|
||||
//
|
||||
// Notifications as Status
|
||||
//
|
||||
|
||||
readonly statusMessage: IStatusMessageViewItem | undefined;
|
||||
|
||||
readonly onDidStatusMessageChange: Event<IStatusMessageChangeEvent>;
|
||||
|
||||
showStatusMessage(message: NotificationMessage, options?: IStatusMessageOptions): IDisposable;
|
||||
}
|
||||
|
||||
export const enum NotificationChangeType {
|
||||
|
@ -45,6 +60,29 @@ export interface INotificationChangeEvent {
|
|||
kind: NotificationChangeType;
|
||||
}
|
||||
|
||||
export const enum StatusMessageChangeType {
|
||||
ADD,
|
||||
REMOVE
|
||||
}
|
||||
|
||||
export interface IStatusMessageViewItem {
|
||||
message: string;
|
||||
options?: IStatusMessageOptions;
|
||||
}
|
||||
|
||||
export interface IStatusMessageChangeEvent {
|
||||
|
||||
/**
|
||||
* The status message item this change is about.
|
||||
*/
|
||||
item: IStatusMessageViewItem;
|
||||
|
||||
/**
|
||||
* The kind of status message change.
|
||||
*/
|
||||
kind: StatusMessageChangeType;
|
||||
}
|
||||
|
||||
export class NotificationHandle implements INotificationHandle {
|
||||
|
||||
private readonly _onDidClose: Emitter<void> = new Emitter();
|
||||
|
@ -90,13 +128,16 @@ export class NotificationsModel extends Disposable implements INotificationsMode
|
|||
private readonly _onDidNotificationChange: Emitter<INotificationChangeEvent> = this._register(new Emitter<INotificationChangeEvent>());
|
||||
get onDidNotificationChange(): Event<INotificationChangeEvent> { return this._onDidNotificationChange.event; }
|
||||
|
||||
private readonly _onDidStatusMessageChange: Emitter<IStatusMessageChangeEvent> = this._register(new Emitter<IStatusMessageChangeEvent>());
|
||||
get onDidStatusMessageChange(): Event<IStatusMessageChangeEvent> { return this._onDidStatusMessageChange.event; }
|
||||
|
||||
private readonly _notifications: INotificationViewItem[] = [];
|
||||
get notifications(): INotificationViewItem[] { return this._notifications; }
|
||||
|
||||
get notifications(): INotificationViewItem[] {
|
||||
return this._notifications;
|
||||
}
|
||||
private _statusMessage: IStatusMessageViewItem | undefined;
|
||||
get statusMessage(): IStatusMessageViewItem | undefined { return this._statusMessage; }
|
||||
|
||||
notify(notification: INotification): INotificationHandle {
|
||||
addNotification(notification: INotification): INotificationHandle {
|
||||
const item = this.createViewItem(notification);
|
||||
if (!item) {
|
||||
return NotificationsModel.NO_OP_NOTIFICATION; // return early if this is a no-op
|
||||
|
@ -174,6 +215,26 @@ export class NotificationsModel extends Disposable implements INotificationsMode
|
|||
|
||||
return item;
|
||||
}
|
||||
|
||||
showStatusMessage(message: NotificationMessage, options?: IStatusMessageOptions): IDisposable {
|
||||
const item = StatusMessageViewItem.create(message, options);
|
||||
if (!item) {
|
||||
return Disposable.None;
|
||||
}
|
||||
|
||||
// Remember as current status message and fire events
|
||||
this._statusMessage = item;
|
||||
this._onDidStatusMessageChange.fire({ kind: StatusMessageChangeType.ADD, item });
|
||||
|
||||
return toDisposable(() => {
|
||||
|
||||
// Only reset status message if the item is still the one we had remembered
|
||||
if (this._statusMessage === item) {
|
||||
this._statusMessage = undefined;
|
||||
this._onDidStatusMessageChange.fire({ kind: StatusMessageChangeType.REMOVE, item });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export interface INotificationViewItem {
|
||||
|
@ -621,4 +682,26 @@ export class ChoiceAction extends Action {
|
|||
|
||||
this._onDidRun.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
class StatusMessageViewItem {
|
||||
|
||||
static create(notification: NotificationMessage, options?: IStatusMessageOptions): IStatusMessageViewItem | null {
|
||||
if (!notification || isPromiseCanceledError(notification)) {
|
||||
return null; // we need a message to show
|
||||
}
|
||||
|
||||
let message: string | undefined;
|
||||
if (notification instanceof Error) {
|
||||
message = toErrorMessage(notification, false);
|
||||
} else if (typeof notification === 'string') {
|
||||
message = notification;
|
||||
}
|
||||
|
||||
if (!message) {
|
||||
return null; // we need a message to show
|
||||
}
|
||||
|
||||
return { message, options };
|
||||
}
|
||||
}
|
|
@ -186,7 +186,7 @@ suite('ConfigurationEditingService', () => {
|
|||
test('do not notify error', () => {
|
||||
instantiationService.stub(ITextFileService, 'isDirty', true);
|
||||
const target = sinon.stub();
|
||||
instantiationService.stub(INotificationService, <INotificationService>{ prompt: target, _serviceBrand: null, notify: null!, error: null!, info: null!, warn: null! });
|
||||
instantiationService.stub(INotificationService, <INotificationService>{ prompt: target, _serviceBrand: null!, notify: null!, error: null!, info: null!, warn: null!, status: null! });
|
||||
return testObject.writeConfiguration(EditableConfigurationTarget.USER_LOCAL, { key: 'configurationEditing.service.testSetting', value: 'value' }, { donotNotifyError: true })
|
||||
.then(() => assert.fail('Should fail with ERROR_CONFIGURATION_FILE_DIRTY error.'),
|
||||
(error: ConfigurationEditingError) => {
|
||||
|
|
|
@ -28,7 +28,6 @@ import { IKeybindingItem, IKeybindingRule2, KeybindingWeight, KeybindingsRegistr
|
|||
import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IStatusbarService } from 'vs/platform/statusbar/common/statusbar';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { keybindingsTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { ExtensionMessageCollector, ExtensionsRegistry } from 'vs/workbench/services/extensions/common/extensionsRegistry';
|
||||
|
@ -277,12 +276,11 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
|
|||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@INotificationService notificationService: INotificationService,
|
||||
@IEnvironmentService environmentService: IEnvironmentService,
|
||||
@IStatusbarService statusBarService: IStatusbarService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@IWindowService private readonly windowService: IWindowService,
|
||||
@IExtensionService extensionService: IExtensionService
|
||||
) {
|
||||
super(contextKeyService, commandService, telemetryService, notificationService, statusBarService);
|
||||
super(contextKeyService, commandService, telemetryService, notificationService);
|
||||
|
||||
updateSchema();
|
||||
|
||||
|
|
|
@ -3,15 +3,16 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { INotificationService, INotification, INotificationHandle, Severity, NotificationMessage, INotificationActions, IPromptChoice, IPromptOptions } from 'vs/platform/notification/common/notification';
|
||||
import { INotificationService, INotification, INotificationHandle, Severity, NotificationMessage, INotificationActions, IPromptChoice, IPromptOptions, IStatusMessageOptions } from 'vs/platform/notification/common/notification';
|
||||
import { INotificationsModel, NotificationsModel, ChoiceAction } from 'vs/workbench/common/notifications';
|
||||
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
export class NotificationService extends Disposable implements INotificationService {
|
||||
|
||||
_serviceBrand: any;
|
||||
_serviceBrand: ServiceIdentifier<INotificationService>;
|
||||
|
||||
private _model: INotificationsModel = this._register(new NotificationsModel());
|
||||
|
||||
|
@ -26,7 +27,7 @@ export class NotificationService extends Disposable implements INotificationServ
|
|||
return;
|
||||
}
|
||||
|
||||
this.model.notify({ severity: Severity.Info, message });
|
||||
this.model.addNotification({ severity: Severity.Info, message });
|
||||
}
|
||||
|
||||
warn(message: NotificationMessage | NotificationMessage[]): void {
|
||||
|
@ -36,7 +37,7 @@ export class NotificationService extends Disposable implements INotificationServ
|
|||
return;
|
||||
}
|
||||
|
||||
this.model.notify({ severity: Severity.Warning, message });
|
||||
this.model.addNotification({ severity: Severity.Warning, message });
|
||||
}
|
||||
|
||||
error(message: NotificationMessage | NotificationMessage[]): void {
|
||||
|
@ -46,11 +47,11 @@ export class NotificationService extends Disposable implements INotificationServ
|
|||
return;
|
||||
}
|
||||
|
||||
this.model.notify({ severity: Severity.Error, message });
|
||||
this.model.addNotification({ severity: Severity.Error, message });
|
||||
}
|
||||
|
||||
notify(notification: INotification): INotificationHandle {
|
||||
return this.model.notify(notification);
|
||||
return this.model.addNotification(notification);
|
||||
}
|
||||
|
||||
prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions): INotificationHandle {
|
||||
|
@ -104,6 +105,10 @@ export class NotificationService extends Disposable implements INotificationServ
|
|||
|
||||
return handle;
|
||||
}
|
||||
|
||||
status(message: NotificationMessage, options?: IStatusMessageOptions): IDisposable {
|
||||
return this.model.showStatusMessage(message, options);
|
||||
}
|
||||
}
|
||||
|
||||
registerSingleton(INotificationService, NotificationService, true);
|
|
@ -142,19 +142,19 @@ suite('Notifications', () => {
|
|||
let item2Duplicate: INotification = { severity: Severity.Warning, message: 'Warning Message', source: 'Some Source' };
|
||||
let item3: INotification = { severity: Severity.Info, message: 'Info Message' };
|
||||
|
||||
let item1Handle = model.notify(item1);
|
||||
let item1Handle = model.addNotification(item1);
|
||||
assert.equal(lastEvent.item.severity, item1.severity);
|
||||
assert.equal(lastEvent.item.message.value, item1.message);
|
||||
assert.equal(lastEvent.index, 0);
|
||||
assert.equal(lastEvent.kind, NotificationChangeType.ADD);
|
||||
|
||||
let item2Handle = model.notify(item2);
|
||||
let item2Handle = model.addNotification(item2);
|
||||
assert.equal(lastEvent.item.severity, item2.severity);
|
||||
assert.equal(lastEvent.item.message.value, item2.message);
|
||||
assert.equal(lastEvent.index, 0);
|
||||
assert.equal(lastEvent.kind, NotificationChangeType.ADD);
|
||||
|
||||
model.notify(item3);
|
||||
model.addNotification(item3);
|
||||
assert.equal(lastEvent.item.severity, item3.severity);
|
||||
assert.equal(lastEvent.item.message.value, item3.message);
|
||||
assert.equal(lastEvent.index, 0);
|
||||
|
@ -175,7 +175,7 @@ suite('Notifications', () => {
|
|||
assert.equal(lastEvent.index, 2);
|
||||
assert.equal(lastEvent.kind, NotificationChangeType.REMOVE);
|
||||
|
||||
model.notify(item2Duplicate);
|
||||
model.addNotification(item2Duplicate);
|
||||
assert.equal(model.notifications.length, 2);
|
||||
assert.equal(lastEvent.item.severity, item2Duplicate.severity);
|
||||
assert.equal(lastEvent.item.message.value, item2Duplicate.message);
|
||||
|
|
|
@ -6,9 +6,11 @@
|
|||
import * as assert from 'assert';
|
||||
import { MainThreadMessageService } from 'vs/workbench/api/browser/mainThreadMessageService';
|
||||
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { INotificationService, INotification, NoOpNotification, INotificationHandle, Severity, IPromptChoice, IPromptOptions } from 'vs/platform/notification/common/notification';
|
||||
import { INotificationService, INotification, NoOpNotification, INotificationHandle, Severity, IPromptChoice, IPromptOptions, IStatusMessageOptions } from 'vs/platform/notification/common/notification';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { mock } from 'vs/workbench/test/electron-browser/api/mock';
|
||||
import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
|
||||
|
||||
const emptyDialogService = new class implements IDialogService {
|
||||
_serviceBrand: 'dialogService';
|
||||
|
@ -30,7 +32,7 @@ const emptyCommandService: ICommandService = {
|
|||
};
|
||||
|
||||
const emptyNotificationService = new class implements INotificationService {
|
||||
_serviceBrand: 'notificiationService';
|
||||
_serviceBrand: ServiceIdentifier<INotificationService>;
|
||||
notify(...args: any[]): never {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
|
@ -46,11 +48,13 @@ const emptyNotificationService = new class implements INotificationService {
|
|||
prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions): INotificationHandle {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
status(message: string | Error, options?: IStatusMessageOptions): IDisposable {
|
||||
return Disposable.None;
|
||||
}
|
||||
};
|
||||
|
||||
class EmptyNotificationService implements INotificationService {
|
||||
|
||||
_serviceBrand: any;
|
||||
_serviceBrand: ServiceIdentifier<INotificationService>;
|
||||
|
||||
constructor(private withNotify: (notification: INotification) => void) {
|
||||
}
|
||||
|
@ -72,6 +76,9 @@ class EmptyNotificationService implements INotificationService {
|
|||
prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions): INotificationHandle {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
status(message: string, options?: IStatusMessageOptions): IDisposable {
|
||||
return Disposable.None;
|
||||
}
|
||||
}
|
||||
|
||||
suite('ExtHostMessageService', function () {
|
||||
|
|
Loading…
Reference in a new issue