Skip to content

Commit fe92963

Browse files
author
Benjamin Pasero
committed
notifications - hide when secondary action is invoked in some cases
1 parent fb06298 commit fe92963

22 files changed

Lines changed: 98 additions & 72 deletions

File tree

src/vs/base/browser/contextmenu.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
'use strict';
6+
7+
import { IAction, IActionRunner, Action } from 'vs/base/common/actions';
8+
import { IActionItem } from 'vs/base/browser/ui/actionbar/actionbar';
9+
import { TPromise } from 'vs/base/common/winjs.base';
10+
import { ResolvedKeybinding } from 'vs/base/common/keyCodes';
11+
12+
export interface IEvent {
13+
shiftKey?: boolean;
14+
ctrlKey?: boolean;
15+
altKey?: boolean;
16+
metaKey?: boolean;
17+
}
18+
19+
export class ContextSubMenu extends Action {
20+
constructor(label: string, public entries: (ContextSubMenu | IAction)[]) {
21+
super('contextsubmenu', label, '', true);
22+
}
23+
}
24+
25+
export interface IContextMenuDelegate {
26+
getAnchor(): HTMLElement | { x: number; y: number; };
27+
getActions(): TPromise<(IAction | ContextSubMenu)[]>;
28+
getActionItem?(action: IAction): IActionItem;
29+
getActionsContext?(event?: IEvent): any;
30+
getKeyBinding?(action: IAction): ResolvedKeybinding;
31+
getMenuClassName?(): string;
32+
onHide?(didCancel: boolean): void;
33+
actionRunner?: IActionRunner;
34+
autoSelectFirstItem?: boolean;
35+
}

src/vs/base/browser/ui/dropdown/dropdown.ts

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@ import { Builder, $ } from 'vs/base/browser/builder';
1010
import { TPromise } from 'vs/base/common/winjs.base';
1111
import { Gesture, EventType as GestureEventType } from 'vs/base/browser/touch';
1212
import { ActionRunner, IAction, IActionRunner } from 'vs/base/common/actions';
13-
import { IActionItem, BaseActionItem, IActionItemProvider } from 'vs/base/browser/ui/actionbar/actionbar';
13+
import { BaseActionItem, IActionItemProvider } from 'vs/base/browser/ui/actionbar/actionbar';
1414
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
1515
import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';
1616
import { IMenuOptions } from 'vs/base/browser/ui/menu/menu';
1717
import { ResolvedKeybinding } from 'vs/base/common/keyCodes';
1818
import { EventHelper, EventType } from 'vs/base/browser/dom';
19+
import { IContextMenuDelegate } from 'vs/base/browser/contextmenu';
1920

2021
export interface ILabelRenderer {
2122
(container: HTMLElement): IDisposable;
@@ -164,16 +165,6 @@ export class Dropdown extends BaseDropdown {
164165
}
165166
}
166167

167-
export interface IContextMenuDelegate {
168-
getAnchor(): HTMLElement | { x: number; y: number; };
169-
getActions(): TPromise<IAction[]>;
170-
getActionItem?(action: IAction): IActionItem;
171-
getActionsContext?(): any;
172-
getKeyBinding?(action: IAction): ResolvedKeybinding;
173-
getMenuClassName?(): string;
174-
onHide?(didCancel: boolean): void;
175-
}
176-
177168
export interface IContextMenuProvider {
178169
showContextMenu(delegate: IContextMenuDelegate): void;
179170
}
@@ -235,7 +226,8 @@ export class DropdownMenu extends BaseDropdown {
235226
getActionItem: (action) => this.menuOptions && this.menuOptions.actionItemProvider ? this.menuOptions.actionItemProvider(action) : null,
236227
getKeyBinding: (action: IAction) => this.menuOptions && this.menuOptions.getKeyBinding ? this.menuOptions.getKeyBinding(action) : null,
237228
getMenuClassName: () => this.menuClassName,
238-
onHide: () => this.element.removeClass('active')
229+
onHide: () => this.element.removeClass('active'),
230+
actionRunner: this.menuOptions ? this.menuOptions.actionRunner : null
239231
});
240232
}
241233

src/vs/platform/contextview/browser/contextMenuHandler.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
1212
import { IActionRunner, ActionRunner, IAction, IRunEvent } from 'vs/base/common/actions';
1313
import { Menu } from 'vs/base/browser/ui/menu/menu';
1414

15-
import { IContextViewService, IContextMenuDelegate } from 'vs/platform/contextview/browser/contextView';
15+
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
1616
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
1717
import { INotificationService } from 'vs/platform/notification/common/notification';
18+
import { IContextMenuDelegate } from 'vs/base/browser/contextmenu';
1819

1920
export class ContextMenuHandler {
2021

src/vs/platform/contextview/browser/contextMenuService.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
'use strict';
66

77
import { ContextMenuHandler } from './contextMenuHandler';
8-
import { IContextViewService, IContextMenuService, IContextMenuDelegate } from './contextView';
8+
import { IContextViewService, IContextMenuService } from './contextView';
99
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
1010
import Event, { Emitter } from 'vs/base/common/event';
1111
import { INotificationService } from 'vs/platform/notification/common/notification';
12+
import { IContextMenuDelegate } from 'vs/base/browser/contextmenu';
1213

1314

1415
export class ContextMenuService implements IContextMenuService {

src/vs/platform/contextview/browser/contextView.ts

Lines changed: 2 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,9 @@
55
'use strict';
66

77
import { IDisposable } from 'vs/base/common/lifecycle';
8-
import { IAction, IActionRunner, Action } from 'vs/base/common/actions';
9-
import { IActionItem } from 'vs/base/browser/ui/actionbar/actionbar';
10-
import { TPromise } from 'vs/base/common/winjs.base';
118
import Event from 'vs/base/common/event';
12-
import { ResolvedKeybinding } from 'vs/base/common/keyCodes';
139
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
10+
import { IContextMenuDelegate } from 'vs/base/browser/contextmenu';
1411

1512
export const IContextViewService = createDecorator<IContextViewService>('contextViewService');
1613

@@ -36,29 +33,4 @@ export interface IContextMenuService {
3633
showContextMenu(delegate: IContextMenuDelegate): void;
3734
// TODO@isidor these event should be removed once we get async context menus
3835
onDidContextMenu: Event<void>;
39-
}
40-
41-
export interface IEvent {
42-
shiftKey?: boolean;
43-
ctrlKey?: boolean;
44-
altKey?: boolean;
45-
metaKey?: boolean;
46-
}
47-
48-
export interface IContextMenuDelegate {
49-
getAnchor(): HTMLElement | { x: number; y: number; };
50-
getActions(): TPromise<(IAction | ContextSubMenu)[]>;
51-
getActionItem?(action: IAction): IActionItem;
52-
getActionsContext?(event?: IEvent): any;
53-
getKeyBinding?(action: IAction): ResolvedKeybinding;
54-
getMenuClassName?(): string;
55-
onHide?(didCancel: boolean): void;
56-
actionRunner?: IActionRunner;
57-
autoSelectFirstItem?: boolean;
58-
}
59-
60-
export class ContextSubMenu extends Action {
61-
constructor(label: string, public entries: (ContextSubMenu | IAction)[]) {
62-
super('contextsubmenu', label, '', true);
63-
}
64-
}
36+
}

src/vs/platform/dialogs/common/dialogs.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,17 @@ export interface IConfirmationService {
4646
export const IChoiceService = createDecorator<IChoiceService>('choiceService');
4747

4848
/**
49-
* The choices to present to the user. The `isSecondary` hint allows to control where
49+
* The choices to present to the user. The `ISecondaryChoice` hint allows to control where
5050
* choices appear when the `modal` option is set to `false`. In that case, the choices
5151
* are presented as part of a notification and secondary choices will appear less
5252
* prominent.
5353
*/
54-
export type Choice = string | { label: string; isSecondary?: boolean; };
54+
export interface SecondaryChoice {
55+
label: string;
56+
keepOpen?: boolean;
57+
}
58+
export type PrimaryChoice = string;
59+
export type Choice = PrimaryChoice | SecondaryChoice;
5560

5661
export interface IChoiceService {
5762

src/vs/platform/integrity/node/integrityServiceImpl.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ export class IntegrityServiceImpl implements IIntegrityService {
8686
return;
8787
}
8888

89-
const choices: Choice[] = [nls.localize('integrity.moreInformation', "More Information"), { label: nls.localize('integrity.dontShowAgain', "Don't Show Again"), isSecondary: true }];
89+
const choices: Choice[] = [nls.localize('integrity.moreInformation', "More Information"), { label: nls.localize('integrity.dontShowAgain', "Don't Show Again") }];
9090

9191
this.choiceService.choose(Severity.Warning, nls.localize('integrity.prompt', "Your {0} installation appears to be corrupt. Please reinstall.", product.nameShort), choices).then(choice => {
9292
switch (choice) {

src/vs/workbench/browser/parts/notifications/notificationsActions.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
1414
import { INotificationService } from 'vs/platform/notification/common/notification';
1515
import { CLEAR_NOTIFICATION, EXPAND_NOTIFICATION, COLLAPSE_NOTIFICATION } from 'vs/workbench/browser/parts/notifications/notificationsCommands';
1616
import { ICommandService } from 'vs/platform/commands/common/commands';
17+
import { toDisposable } from 'vs/base/common/lifecycle';
1718

1819
export class ClearNotificationAction extends Action {
1920

@@ -102,9 +103,8 @@ export class NotificationActionRunner extends ActionRunner {
102103
super();
103104
}
104105

105-
protected runAction(action: IAction, context?: any): TPromise<any> {
106+
protected runAction(action: IAction, context: INotificationViewItem): TPromise<any> {
106107

107-
// Telemetry
108108
/* __GDPR__
109109
"workbenchActionExecuted" : {
110110
"id" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
@@ -113,8 +113,8 @@ export class NotificationActionRunner extends ActionRunner {
113113
*/
114114
this.telemetryService.publicLog('workbenchActionExecuted', { id: action.id, from: 'message' });
115115

116-
// Run and make sure to notify on any error again
117-
super.runAction(action, context).done(null, error => this.notificationService.error(error));
116+
// Run and make sure to notify on any error again (allow to dispose from within action via context)
117+
super.runAction(action, toDisposable(() => context.dispose())).done(null, error => this.notificationService.error(error));
118118

119119
return TPromise.as(void 0);
120120
}

src/vs/workbench/browser/parts/notifications/notificationsViewer.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,14 +195,15 @@ export class NotificationRenderer implements IRenderer<INotificationViewItem, IN
195195
ariaLabel: localize('notificationActions', "Notification Actions"),
196196
actionItemProvider: action => {
197197
if (action instanceof ConfigureNotificationAction) {
198-
const item = new DropdownMenuActionItem(action, action.configurationActions, this.contextMenuService, null, null, null, action.class);
198+
const item = new DropdownMenuActionItem(action, action.configurationActions, this.contextMenuService, null, this.actionRunner, null, action.class);
199199
data.toDispose.push(item);
200200

201201
return item;
202202
}
203203

204204
return null;
205-
}
205+
},
206+
actionRunner: this.actionRunner
206207
}
207208
);
208209
data.toDispose.push(data.toolbar);
@@ -456,7 +457,7 @@ export class NotificationTemplateRenderer {
456457
this.inputDisposeables.push(button.onDidClick(() => {
457458

458459
// Run action
459-
this.actionRunner.run(action);
460+
this.actionRunner.run(action, notification);
460461

461462
// Hide notification
462463
notification.dispose();

src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
2828
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
2929
import { ICommandService } from 'vs/platform/commands/common/commands';
3030
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
31-
import { IContextMenuService, ContextSubMenu } from 'vs/platform/contextview/browser/contextView';
31+
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
3232
import { DebugHoverWidget } from 'vs/workbench/parts/debug/electron-browser/debugHover';
3333
import { RemoveBreakpointAction, EditConditionalBreakpointAction, EnableBreakpointAction, DisableBreakpointAction, AddConditionalBreakpointAction } from 'vs/workbench/parts/debug/browser/debugActions';
3434
import { IDebugEditorContribution, IDebugService, State, IBreakpoint, EDITOR_CONTRIBUTION_ID, CONTEXT_BREAKPOINT_WIDGET_VISIBLE, IStackFrame, IDebugConfiguration, IExpression, IExceptionInfo } from 'vs/workbench/parts/debug/common/debug';
@@ -41,6 +41,7 @@ import { CoreEditingCommands } from 'vs/editor/browser/controller/coreCommands';
4141
import { first } from 'vs/base/common/arrays';
4242
import { IMarginData } from 'vs/editor/browser/controller/mouseTarget';
4343
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
44+
import { ContextSubMenu } from 'vs/base/browser/contextmenu';
4445

4546
const HOVER_DELAY = 300;
4647
const LAUNCH_JSON_REGEX = /launch\.json$/;

0 commit comments

Comments
 (0)