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

notifications - extract a reusable notifications list

上级 b6bfdd4d
......@@ -7,7 +7,7 @@
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { RawContextKey, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { INotificationViewItem, isNotificationViewItem } from 'vs/workbench/common/notifications';
......@@ -15,6 +15,7 @@ import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
import { localize } from 'vs/nls';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { IListService, WorkbenchList } from 'vs/platform/list/browser/listService';
export const SHOW_NOTFICATIONS_CENTER_COMMAND_ID = 'notifications.show';
export const HIDE_NOTFICATIONS_CENTER_COMMAND_ID = 'notifications.hide';
......@@ -25,17 +26,14 @@ export const TOGGLE_NOTIFICATION = 'notification.toggle';
export const CLEAR_NOTFICATION = 'notification.clear';
export const CLEAR_ALL_NOTFICATIONS = 'notifications.clearAll';
const notificationsCenterFocusedId = 'notificationsCenterFocus';
export const NotificationsCenterFocusedContext = new RawContextKey<boolean>(notificationsCenterFocusedId, true);
const notificationFocusedId = 'notificationFocus';
export const NotificationFocusedContext = new RawContextKey<boolean>(notificationFocusedId, true);
const notificationsCenterVisibleId = 'notificationsCenterVisible';
export const NotificationsCenterVisibleContext = new RawContextKey<boolean>(notificationsCenterVisibleId, false);
export const InNotificationsCenterContext = ContextKeyExpr.and(ContextKeyExpr.has(notificationsCenterFocusedId), ContextKeyExpr.has(notificationsCenterVisibleId));
export interface INotificationsCenterController {
readonly isVisible: boolean;
readonly selected: INotificationViewItem;
show(): void;
hide(): void;
......@@ -61,14 +59,30 @@ export function registerNotificationCommands(center: INotificationsCenterControl
}
}
function getNotificationFromContext(listService: IListService, context?: any): INotificationViewItem {
if (isNotificationViewItem(context)) {
return context;
}
const list = listService.lastFocusedList;
if (list instanceof WorkbenchList) {
const focusedElement = list.getFocusedElements()[0];
if (isNotificationViewItem(focusedElement)) {
return focusedElement;
}
}
return void 0;
}
// Show Notifications Cneter
CommandsRegistry.registerCommand(SHOW_NOTFICATIONS_CENTER_COMMAND_ID, () => showCenter());
// Hide Notifications Center
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: HIDE_NOTFICATIONS_CENTER_COMMAND_ID,
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
when: InNotificationsCenterContext,
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(50),
when: NotificationsCenterVisibleContext,
primary: KeyCode.Escape,
handler: accessor => hideCenter(accessor)
});
......@@ -80,19 +94,13 @@ export function registerNotificationCommands(center: INotificationsCenterControl
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: CLEAR_NOTFICATION,
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
when: InNotificationsCenterContext,
when: NotificationFocusedContext,
primary: KeyCode.Delete,
mac: {
primary: KeyMod.CtrlCmd | KeyCode.Backspace
},
handler: (accessor, args?: any) => {
let notification: INotificationViewItem;
if (isNotificationViewItem(args)) {
notification = args;
} else {
notification = center.selected;
}
const notification = getNotificationFromContext(accessor.get(IListService), args);
if (notification) {
notification.dispose();
}
......@@ -103,16 +111,10 @@ export function registerNotificationCommands(center: INotificationsCenterControl
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: EXPAND_NOTIFICATION,
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
when: InNotificationsCenterContext,
when: NotificationFocusedContext,
primary: KeyCode.RightArrow,
handler: (accessor, args?: any) => {
let notification: INotificationViewItem;
if (isNotificationViewItem(args)) {
notification = args;
} else {
notification = center.selected;
}
const notification = getNotificationFromContext(accessor.get(IListService), args);
if (notification) {
notification.expand();
}
......@@ -123,16 +125,10 @@ export function registerNotificationCommands(center: INotificationsCenterControl
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: COLLAPSE_NOTIFICATION,
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
when: InNotificationsCenterContext,
when: NotificationFocusedContext,
primary: KeyCode.LeftArrow,
handler: (accessor, args?: any) => {
let notification: INotificationViewItem;
if (isNotificationViewItem(args)) {
notification = args;
} else {
notification = center.selected;
}
const notification = getNotificationFromContext(accessor.get(IListService), args);
if (notification) {
notification.collapse();
}
......@@ -143,10 +139,10 @@ export function registerNotificationCommands(center: INotificationsCenterControl
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: TOGGLE_NOTIFICATION,
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
when: InNotificationsCenterContext,
when: NotificationFocusedContext,
primary: KeyCode.Space,
handler: accessor => {
const notification = center.selected;
const notification = getNotificationFromContext(accessor.get(IListService));
if (notification) {
notification.toggle();
}
......@@ -165,7 +161,7 @@ export function registerNotificationCommands(center: INotificationsCenterControl
// TODO@Notification remove me
// TODO@notifications remove me
CommandsRegistry.registerCommand('notifications.showInfo', accessor => {
accessor.get(INotificationService).info('This is an information message!');
});
......
......@@ -13,7 +13,6 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { toErrorMessage } from 'vs/base/common/errorMessage';
export class NotificationsAlerts {
private toDispose: IDisposable[];
constructor(private model: INotificationsModel) {
......
......@@ -5,31 +5,22 @@
'use strict';
import 'vs/css!./media/notificationsCenter';
import { addClass, removeClass, isAncestor } from 'vs/base/browser/dom';
import { WorkbenchList } from 'vs/platform/list/browser/listService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IListOptions } from 'vs/base/browser/ui/list/listWidget';
import { localize } from 'vs/nls';
import { Themable, NOTIFICATIONS_BORDER, NOTIFICATIONS_LINKS, NOTIFICATIONS_BACKGROUND, NOTIFICATIONS_FOREGROUND } from 'vs/workbench/common/theme';
import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
import { contrastBorder, widgetShadow } from 'vs/platform/theme/common/colorRegistry';
import { INotificationViewItem, INotificationsModel, INotificationChangeEvent, NotificationChangeType } from 'vs/workbench/common/notifications';
import { NotificationsListDelegate, NotificationRenderer } from 'vs/workbench/browser/parts/notifications/notificationsViewer';
import { NotificationActionRunner } from 'vs/workbench/browser/parts/notifications/notificationsActions';
import { Themable } from 'vs/workbench/common/theme';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { INotificationsModel, INotificationChangeEvent, NotificationChangeType } from 'vs/workbench/common/notifications';
import { Dimension } from 'vs/base/browser/builder';
import { IPartService, Parts } from 'vs/workbench/services/part/common/partService';
import Event, { Emitter } from 'vs/base/common/event';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { NotificationsCenterFocusedContext, NotificationsCenterVisibleContext } from 'vs/workbench/browser/parts/notifications/notificationCommands';
import { NotificationsCenterVisibleContext } from 'vs/workbench/browser/parts/notifications/notificationCommands';
import { NotificationsList } from 'vs/workbench/browser/parts/notifications/notificationsList';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
export class NotificationsCenter extends Themable {
private static MAX_DIMENSIONS = new Dimension(600, 600);
private listContainer: HTMLElement;
private list: WorkbenchList<INotificationViewItem>;
private viewModel: INotificationViewItem[];
private notificationsList: NotificationsList;
private _isVisible: boolean;
private workbenchDimensions: Dimension;
private _onDidChangeVisibility: Emitter<void>;
......@@ -38,8 +29,8 @@ export class NotificationsCenter extends Themable {
constructor(
private container: HTMLElement,
private model: INotificationsModel,
@IInstantiationService private instantiationService: IInstantiationService,
@IThemeService themeService: IThemeService,
@IInstantiationService private instantiationService: IInstantiationService,
@IPartService private partService: IPartService,
@IContextKeyService contextKeyService: IContextKeyService
) {
......@@ -50,10 +41,13 @@ export class NotificationsCenter extends Themable {
this.notificationsCenterVisibleContextKey = NotificationsCenterVisibleContext.bindTo(contextKeyService);
this.viewModel = [];
this.registerListeners();
}
private registerListeners(): void {
this.toUnbind.push(this.model.onDidNotificationChange(e => this.onDidNotificationChange(e)));
}
public get onDidChangeVisibility(): Event<void> {
return this._onDidChangeVisibility.event;
}
......@@ -62,41 +56,22 @@ export class NotificationsCenter extends Themable {
return this._isVisible;
}
public get selected(): INotificationViewItem {
if (!this._isVisible || !this.list) {
return null;
}
const focusedIndex = this.list.getFocus()[0];
return this.viewModel[focusedIndex];
}
private registerListeners(): void {
this.toUnbind.push(this.model.onDidNotificationChange(e => this.onDidNotificationChange(e)));
}
public show(): void {
if (this._isVisible) {
this.focusNotificationsList();
return; // already visible
}
// Lazily create if showing for the first time
if (!this.list) {
this.createNotificationsList();
if (!this.notificationsList) {
this.notificationsList = this.instantiationService.createInstance(NotificationsList, this.container);
}
// Make visible
this._isVisible = true;
addClass(this.listContainer, 'visible');
this.notificationsList.show();
// Show all notifications that are present now
this.onNotificationsAdded(0, this.model.notifications);
// Layout
this.layoutList();
// Focus
this.focusNotificationsList();
// Show all notifications that are present now
this.notificationsList.updateNotificationsList(0, 0, this.model.notifications);
// Context Key
this.notificationsCenterVisibleContextKey.set(true);
......@@ -105,142 +80,38 @@ export class NotificationsCenter extends Themable {
this._onDidChangeVisibility.fire();
}
private focusNotificationsList(): void {
if (!this._isVisible) {
return;
}
this.list.domFocus();
}
private createNotificationsList(): void {
// List Container
this.listContainer = document.createElement('div');
addClass(this.listContainer, 'notifications-list-container');
// Notification Renderer
const renderer = this.instantiationService.createInstance(NotificationRenderer, this.instantiationService.createInstance(NotificationActionRunner));
this.toUnbind.push(renderer);
// List
this.list = this.instantiationService.createInstance(
WorkbenchList,
this.listContainer,
new NotificationsListDelegate(this.listContainer),
[renderer],
{
ariaLabel: localize('notificationsList', "Notifications List")
} as IListOptions<INotificationViewItem>
);
this.toUnbind.push(this.list);
this.toUnbind.push(this.list.onMouseDblClick(event => {
const item = event.element;
item.toggle();
}));
// Context key
NotificationsCenterFocusedContext.bindTo(this.list.contextKeyService);
// Only allow for focus in notifications, as the
// selection is too strong over the contents of
// the notification
this.toUnbind.push(this.list.onSelectionChange(e => {
if (e.indexes.length > 0) {
this.list.setSelection([]);
}
}));
this.container.appendChild(this.listContainer);
this.updateStyles();
this.layoutList();
}
private onDidNotificationChange(e: INotificationChangeEvent): void {
if (!this._isVisible) {
return; // only if visible
}
// Update notifications list based on event
switch (e.kind) {
case NotificationChangeType.ADD:
return this.onNotificationsAdded(e.index, [e.item]);
this.notificationsList.updateNotificationsList(e.index, 0, [e.item]);
break;
case NotificationChangeType.CHANGE:
return this.onNotificationChanged(e.index, e.item);
this.notificationsList.updateNotificationsList(e.index, 1, [e.item]);
break;
case NotificationChangeType.REMOVE:
return this.onNotificationRemoved(e.index, e.item);
this.notificationsList.updateNotificationsList(e.index, 1);
break;
}
}
private onNotificationsAdded(index: number, items: INotificationViewItem[]): void {
this.updateNotificationsList(index, 0, items);
}
private onNotificationChanged(index: number, item: INotificationViewItem): void {
this.updateNotificationsList(index, 1, [item]);
}
private onNotificationRemoved(index: number, item: INotificationViewItem): void {
this.updateNotificationsList(index, 1);
}
private updateNotificationsList(start: number, deleteCount: number, items: INotificationViewItem[] = []) {
const listHasDOMFocus = isAncestor(document.activeElement, this.listContainer);
// Remember focus
const focusedIndex = this.list.getFocus()[0];
const focusedItem = this.viewModel[focusedIndex];
// Update view model
this.viewModel.splice(start, deleteCount, ...items);
// Update list
this.list.splice(start, deleteCount, items);
this.list.layout();
// Hide if no more notifications to show
if (this.viewModel.length === 0) {
if (this.model.notifications.length === 0) {
this.hide();
}
// Otherwise restore focus if we had
else if (typeof focusedIndex === 'number') {
let indexToFocus = 0;
if (focusedItem) {
let indexToFocusCandidate = this.viewModel.indexOf(focusedItem);
if (indexToFocusCandidate === -1) {
indexToFocusCandidate = focusedIndex - 1; // item could have been removed
}
if (indexToFocusCandidate < this.viewModel.length && indexToFocusCandidate >= 0) {
indexToFocus = indexToFocusCandidate;
}
}
this.list.setFocus([indexToFocus]);
}
// Restore DOM focus if we had focus before
if (listHasDOMFocus) {
this.list.domFocus();
}
}
public hide(): void {
if (!this._isVisible || !this.list) {
if (!this._isVisible || !this.notificationsList) {
return; // already hidden
}
// Hide
this._isVisible = false;
removeClass(this.listContainer, 'visible');
// Clear list
this.list.splice(0, this.viewModel.length);
// Clear view model
this.viewModel = [];
this.notificationsList.hide();
// Context Key
this.notificationsCenterVisibleContextKey.set(false);
......@@ -249,26 +120,10 @@ export class NotificationsCenter extends Themable {
this._onDidChangeVisibility.fire();
}
protected updateStyles(): void {
if (this.listContainer) {
const foreground = this.getColor(NOTIFICATIONS_FOREGROUND);
this.listContainer.style.color = foreground ? foreground.toString() : null;
const background = this.getColor(NOTIFICATIONS_BACKGROUND);
this.listContainer.style.background = background ? background.toString() : null;
const outlineColor = this.getColor(contrastBorder);
this.listContainer.style.outlineColor = outlineColor ? outlineColor.toString() : null;
const widgetShadowColor = this.getColor(widgetShadow);
this.listContainer.style.boxShadow = widgetShadowColor ? `0 5px 8px ${widgetShadowColor}` : null;
}
}
public layout(dimension: Dimension): void {
this.workbenchDimensions = dimension;
if (this._isVisible && this.listContainer) {
if (this._isVisible && this.notificationsList) {
this.layoutList();
}
}
......@@ -304,9 +159,7 @@ export class NotificationsCenter extends Themable {
}
}
this.listContainer.style.width = `${width}px`;
this.list.getHTMLElement().style.maxHeight = `${maxHeight}px`;
this.list.layout();
this.notificationsList.layout(new Dimension(width, maxHeight));
}
public clearAll(): void {
......@@ -319,16 +172,4 @@ export class NotificationsCenter extends Themable {
this.model.notifications[0].dispose();
}
}
}
registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const linkColor = theme.getColor(NOTIFICATIONS_LINKS);
if (linkColor) {
collector.addRule(`.monaco-workbench > .notifications-list-container .notification-list-item .notification-list-item-message a { color: ${linkColor}; }`);
}
const notificationBorderColor = theme.getColor(NOTIFICATIONS_BORDER);
if (notificationBorderColor) {
collector.addRule(`.monaco-workbench > .notifications-list-container .notification-list-item { border-bottom: 1px solid ${notificationBorderColor}; }`);
}
});
}
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./media/notificationsList';
import { addClass, removeClass, isAncestor } from 'vs/base/browser/dom';
import { WorkbenchList } from 'vs/platform/list/browser/listService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IListOptions } from 'vs/base/browser/ui/list/listWidget';
import { localize } from 'vs/nls';
import { Themable, NOTIFICATIONS_BORDER, NOTIFICATIONS_LINKS, NOTIFICATIONS_BACKGROUND, NOTIFICATIONS_FOREGROUND } from 'vs/workbench/common/theme';
import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
import { contrastBorder, widgetShadow } from 'vs/platform/theme/common/colorRegistry';
import { INotificationViewItem } from 'vs/workbench/common/notifications';
import { NotificationsListDelegate, NotificationRenderer } from 'vs/workbench/browser/parts/notifications/notificationsViewer';
import { NotificationActionRunner } from 'vs/workbench/browser/parts/notifications/notificationsActions';
import { Dimension } from 'vs/base/browser/builder';
import { NotificationFocusedContext } from 'vs/workbench/browser/parts/notifications/notificationCommands';
export class NotificationsList extends Themable {
private listContainer: HTMLElement;
private list: WorkbenchList<INotificationViewItem>;
private viewModel: INotificationViewItem[];
private dimensions: Dimension;
private isVisible: boolean;
constructor(
private container: HTMLElement,
@IInstantiationService private instantiationService: IInstantiationService,
@IThemeService themeService: IThemeService
) {
super(themeService);
this.viewModel = [];
}
public show(): void {
if (this.isVisible) {
this.list.domFocus();
return; // already visible
}
// Lazily create if showing for the first time
if (!this.list) {
this.createNotificationsList();
}
// Make visible
this.isVisible = true;
addClass(this.listContainer, 'visible');
// Focus
this.list.domFocus();
}
private createNotificationsList(): void {
// List Container
this.listContainer = document.createElement('div');
addClass(this.listContainer, 'notifications-list-container');
// Notification Renderer
const renderer = this.instantiationService.createInstance(NotificationRenderer, this.instantiationService.createInstance(NotificationActionRunner));
this.toUnbind.push(renderer);
// List
this.list = this.instantiationService.createInstance(
WorkbenchList,
this.listContainer,
new NotificationsListDelegate(this.listContainer),
[renderer],
{
ariaLabel: localize('notificationsList', "Notifications List")
} as IListOptions<INotificationViewItem>
);
this.toUnbind.push(this.list);
// Toggle on double click
this.toUnbind.push(this.list.onMouseDblClick(event => (event.element as INotificationViewItem).toggle()));
// Context key
NotificationFocusedContext.bindTo(this.list.contextKeyService);
// Only allow for focus in notifications, as the
// selection is too strong over the contents of
// the notification
this.toUnbind.push(this.list.onSelectionChange(e => {
if (e.indexes.length > 0) {
this.list.setSelection([]);
}
}));
this.container.appendChild(this.listContainer);
this.updateStyles();
}
public updateNotificationsList(start: number, deleteCount: number, items: INotificationViewItem[] = []) {
const listHasDOMFocus = isAncestor(document.activeElement, this.listContainer);
// Remember focus
const focusedIndex = this.list.getFocus()[0];
const focusedItem = this.viewModel[focusedIndex];
// Update view model
this.viewModel.splice(start, deleteCount, ...items);
// Update list
this.list.splice(start, deleteCount, items);
this.list.layout();
// Hide if no more notifications to show
if (this.viewModel.length === 0) {
this.hide();
}
// Otherwise restore focus if we had
else if (typeof focusedIndex === 'number') {
let indexToFocus = 0;
if (focusedItem) {
let indexToFocusCandidate = this.viewModel.indexOf(focusedItem);
if (indexToFocusCandidate === -1) {
indexToFocusCandidate = focusedIndex - 1; // item could have been removed
}
if (indexToFocusCandidate < this.viewModel.length && indexToFocusCandidate >= 0) {
indexToFocus = indexToFocusCandidate;
}
}
this.list.setFocus([indexToFocus]);
}
// Restore DOM focus if we had focus before
if (listHasDOMFocus) {
this.list.domFocus();
}
}
public hide(): void {
if (!this.isVisible || !this.list) {
return; // already hidden
}
// Hide
this.isVisible = false;
removeClass(this.listContainer, 'visible');
// Clear list
this.list.splice(0, this.viewModel.length);
// Clear view model
this.viewModel = [];
}
protected updateStyles(): void {
if (this.listContainer) {
const foreground = this.getColor(NOTIFICATIONS_FOREGROUND);
this.listContainer.style.color = foreground ? foreground.toString() : null;
const background = this.getColor(NOTIFICATIONS_BACKGROUND);
this.listContainer.style.background = background ? background.toString() : null;
const outlineColor = this.getColor(contrastBorder);
this.listContainer.style.outlineColor = outlineColor ? outlineColor.toString() : null;
const widgetShadowColor = this.getColor(widgetShadow);
this.listContainer.style.boxShadow = widgetShadowColor ? `0 5px 8px ${widgetShadowColor}` : null;
}
}
public layout(dimension: Dimension): void {
this.dimensions = dimension;
this.layoutList();
}
private layoutList(): void {
if (this.list) {
this.listContainer.style.width = `${this.dimensions.width}px`;
this.list.getHTMLElement().style.maxHeight = `${this.dimensions.height}px`;
this.list.layout();
}
}
public dispose(): void {
this.hide();
super.dispose();
}
}
registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const linkColor = theme.getColor(NOTIFICATIONS_LINKS);
if (linkColor) {
collector.addRule(`.monaco-workbench > .notifications-list-container .notification-list-item .notification-list-item-message a { color: ${linkColor}; }`);
}
const notificationBorderColor = theme.getColor(NOTIFICATIONS_BORDER);
if (notificationBorderColor) {
collector.addRule(`.monaco-workbench > .notifications-list-container .notification-list-item { border-bottom: 1px solid ${notificationBorderColor}; }`);
}
});
......@@ -14,7 +14,7 @@ import { localize } from 'vs/nls';
export class NotificationsStatus {
private statusItem: IDisposable;
private toDispose: IDisposable[];
private isCenterVisible: boolean;
private isNotificationsCenterVisible: boolean;
constructor(
private model: INotificationsModel,
......@@ -26,8 +26,8 @@ export class NotificationsStatus {
}
public update(isCenterVisible: boolean): void {
if (this.isCenterVisible !== isCenterVisible) {
this.isCenterVisible = isCenterVisible;
if (this.isNotificationsCenterVisible !== isCenterVisible) {
this.isNotificationsCenterVisible = isCenterVisible;
this.updateNotificationsStatusItem();
}
}
......@@ -55,9 +55,9 @@ export class NotificationsStatus {
const notificationsCount = this.model.notifications.length;
if (notificationsCount > 0) {
this.statusItem = this.statusbarService.addEntry({
text: this.isCenterVisible ? '$(megaphone) ' + localize('hideNotifications', "Hide Notifications") : `$(megaphone) ${notificationsCount}`,
command: this.isCenterVisible ? HIDE_NOTFICATIONS_CENTER_COMMAND_ID : SHOW_NOTFICATIONS_CENTER_COMMAND_ID,
tooltip: this.isCenterVisible ? localize('hideNotifications', "Hide Notifications") : localize('notifications', "{0} notifications", notificationsCount)
text: this.isNotificationsCenterVisible ? '$(megaphone) ' + localize('hideNotifications', "Hide Notifications") : `$(megaphone) ${notificationsCount}`,
command: this.isNotificationsCenterVisible ? HIDE_NOTFICATIONS_CENTER_COMMAND_ID : SHOW_NOTFICATIONS_CENTER_COMMAND_ID,
tooltip: this.isNotificationsCenterVisible ? localize('hideNotifications', "Hide Notifications") : localize('notifications', "{0} notifications", notificationsCount)
}, StatusbarAlignment.RIGHT, -1000 /* towards the far end of the right hand side */);
}
}
......
......@@ -260,7 +260,7 @@ export class NotificationViewItem implements INotificationViewItem {
}
public expand(): void {
if (this._expanded) {
if (this._expanded || !this.canCollapse) {
return;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册