Skip to content

Commit 6ee4542

Browse files
authored
Merge pull request #190186 from microsoft/merogge/actions-in-view
add actions from notifications to accessible view
2 parents 7daa5a2 + ea21651 commit 6ee4542

File tree

2 files changed

+69
-15
lines changed

2 files changed

+69
-15
lines changed

src/vs/workbench/contrib/accessibility/browser/accessibilityContributions.ts

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ import { IAccessibleViewService, IAccessibleContentProvider, IAccessibleViewOpti
3131
import { IHoverService } from 'vs/workbench/services/hover/browser/hover';
3232
import { alert } from 'vs/base/browser/ui/aria/aria';
3333
import { AccessibilityHelpAction, AccessibleViewAction } from 'vs/workbench/contrib/accessibility/browser/accessibleViewActions';
34+
import { IAction } from 'vs/base/common/actions';
35+
import { INotificationViewItem } from 'vs/workbench/common/notifications';
36+
import { ThemeIcon } from 'vs/base/common/themables';
37+
import { Codicon } from 'vs/base/common/codicons';
3438

3539
export class EditorAccessibilityHelpContribution extends Disposable {
3640
static ID: 'editorAccessibilityHelpContribution';
@@ -220,7 +224,8 @@ export class NotificationAccessibleViewContribution extends Disposable {
220224
options: {
221225
ariaLabel: localize('notification', "Notification Accessible View"),
222226
type: AccessibleViewType.View
223-
}
227+
},
228+
actions: getActionsFromNotification(notification)
224229
});
225230
return true;
226231
}
@@ -229,6 +234,33 @@ export class NotificationAccessibleViewContribution extends Disposable {
229234
}
230235
}
231236

237+
function getActionsFromNotification(notification: INotificationViewItem): IAction[] | undefined {
238+
let actions = undefined;
239+
if (notification.actions) {
240+
actions = [];
241+
if (notification.actions.primary) {
242+
actions.push(...notification.actions.primary);
243+
}
244+
if (notification.actions.secondary) {
245+
actions.push(...notification.actions.secondary);
246+
}
247+
}
248+
if (actions) {
249+
for (const action of actions) {
250+
action.class = ThemeIcon.asClassName(Codicon.bell);
251+
const initialAction = action.run;
252+
action.run = () => {
253+
initialAction();
254+
notification.close();
255+
};
256+
}
257+
}
258+
if (actions) {
259+
actions.push({ id: 'clearNotification', label: localize('clearNotification', "Clear Notification"), tooltip: localize('clearNotification', "Clear Notification"), run: () => notification.close(), enabled: true, class: ThemeIcon.asClassName(Codicon.clearAll) });
260+
}
261+
return actions;
262+
}
263+
232264
export function alertFocusChange(index: number | undefined, length: number | undefined, type: 'next' | 'previous'): void {
233265
if (index === undefined || length === undefined) {
234266
return;

src/vs/workbench/contrib/accessibility/browser/accessibleView.ts

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ import { AccessibilityHelpNLS } from 'vs/editor/common/standaloneStrings';
2020
import { CodeActionController } from 'vs/editor/contrib/codeAction/browser/codeActionController';
2121
import { localize } from 'vs/nls';
2222
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
23-
import { MenuWorkbenchToolBar } from 'vs/platform/actions/browser/toolbar';
24-
import { MenuId } from 'vs/platform/actions/common/actions';
23+
import { WorkbenchToolBar } from 'vs/platform/actions/browser/toolbar';
24+
import { IMenuService, MenuId } from 'vs/platform/actions/common/actions';
2525
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
2626
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
2727
import { IContextViewDelegate, IContextViewService } from 'vs/platform/contextview/browser/contextView';
@@ -34,13 +34,23 @@ import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
3434
import { AccessibilityCommandId } from 'vs/workbench/contrib/accessibility/common/accessibilityCommands';
3535
import { AccessibilityVerbositySettingId, accessibilityHelpIsShown, accessibleViewIsShown } from 'vs/workbench/contrib/accessibility/browser/accessibilityConfiguration';
3636
import { getSimpleEditorOptions } from 'vs/workbench/contrib/codeEditor/browser/simpleEditorOptions';
37+
import { IAction } from 'vs/base/common/actions';
38+
import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
39+
import { Codicon } from 'vs/base/common/codicons';
40+
import { ThemeIcon } from 'vs/base/common/themables';
3741

3842
const enum DIMENSIONS {
3943
MAX_WIDTH = 600
4044
}
4145

4246
export interface IAccessibleContentProvider {
4347
verbositySettingKey: AccessibilityVerbositySettingId;
48+
options: IAccessibleViewOptions;
49+
/**
50+
* Note that a Codicon class should be provided for each action.
51+
* If not, a default will be used.
52+
*/
53+
actions?: IAction[];
4454
provideContent(): string;
4555
onClose(): void;
4656
onKeyDown?(e: IKeyboardEvent): void;
@@ -50,7 +60,6 @@ export interface IAccessibleContentProvider {
5060
* When the language is markdown, this is provided by default.
5161
*/
5262
getSymbols?(): IAccessibleViewSymbol[];
53-
options: IAccessibleViewOptions;
5463
}
5564

5665
export const IAccessibleViewService = createDecorator<IAccessibleViewService>('accessibleViewService');
@@ -63,7 +72,6 @@ export interface IAccessibleViewService {
6372
previous(): void;
6473
goToSymbol(): void;
6574
disableHint(): void;
66-
focusToolbar(): void;
6775
/**
6876
* If the setting is enabled, provides the open accessible view hint as a localized string.
6977
* @param verbositySettingKey The setting key for the verbosity of the feature
@@ -93,7 +101,7 @@ class AccessibleView extends Disposable {
93101
get editorWidget() { return this._editorWidget; }
94102
private _editorContainer: HTMLElement;
95103
private _currentProvider: IAccessibleContentProvider | undefined;
96-
private readonly _toolbar: MenuWorkbenchToolBar;
104+
private readonly _toolbar: WorkbenchToolBar;
97105

98106
constructor(
99107
@IOpenerService private readonly _openerService: IOpenerService,
@@ -104,7 +112,8 @@ class AccessibleView extends Disposable {
104112
@IContextKeyService private readonly _contextKeyService: IContextKeyService,
105113
@IAccessibilityService private readonly _accessibilityService: IAccessibilityService,
106114
@IKeybindingService private readonly _keybindingService: IKeybindingService,
107-
@ILayoutService private readonly _layoutService: ILayoutService
115+
@ILayoutService private readonly _layoutService: ILayoutService,
116+
@IMenuService private readonly _menuService: IMenuService
108117
) {
109118
super();
110119
this._accessiblityHelpIsShown = accessibilityHelpIsShown.bindTo(this._contextKeyService);
@@ -114,7 +123,11 @@ class AccessibleView extends Disposable {
114123
const codeEditorWidgetOptions: ICodeEditorWidgetOptions = {
115124
contributions: EditorExtensionsRegistry.getEditorContributions().filter(c => c.id !== CodeActionController.ID)
116125
};
117-
this._toolbar = this._register(_instantiationService.createInstance(MenuWorkbenchToolBar, this._editorContainer, MenuId.AccessibleView, { ariaLabel: localize('accessibleViewToolbar', "Accessible View Toolbar"), orientation: ActionsOrientation.HORIZONTAL }));
126+
this._toolbar = this._register(_instantiationService.createInstance(WorkbenchToolBar, this._editorContainer, { ariaLabel: localize('accessibleViewToolbar', "Accessible View Toolbar"), orientation: ActionsOrientation.HORIZONTAL }));
127+
this._toolbar.context = { viewId: 'accessibleView' };
128+
const toolbarElt = this._toolbar.getElement();
129+
toolbarElt.tabIndex = 0;
130+
118131
const editorOptions: IEditorConstructionOptions = {
119132
...getSimpleEditorOptions(this._configurationService),
120133
lineDecorationsWidth: 6,
@@ -313,8 +326,8 @@ class AccessibleView extends Disposable {
313326
this._editorWidget.updateOptions({ ariaLabel });
314327
this._editorWidget.focus();
315328
});
316-
this._toolbar.context = { viewId: 'accessibleView' };
317-
this._toolbar.getElement().tabIndex = 0;
329+
this._updateToolbar(provider.actions);
330+
318331
const disposableStore = new DisposableStore();
319332
disposableStore.add(this._editorWidget.onKeyUp((e) => provider.onKeyDown?.(e)));
320333
disposableStore.add(this._editorWidget.onKeyDown((e) => {
@@ -342,8 +355,20 @@ class AccessibleView extends Disposable {
342355
return disposableStore;
343356
}
344357

345-
focusToolbar(): void {
346-
this._toolbar.focus();
358+
private _updateToolbar(providedActions?: IAction[]): void {
359+
this._toolbar.setActions([]);
360+
const menuActions: IAction[] = [];
361+
const toolbarMenu = this._register(this._menuService.createMenu(MenuId.AccessibleView, this._contextKeyService));
362+
createAndFillInActionBarActions(toolbarMenu, {}, menuActions);
363+
if (providedActions) {
364+
for (const providedAction of providedActions) {
365+
providedAction.class = providedAction.class || ThemeIcon.asClassName(Codicon.primitiveSquare);
366+
providedAction.checked = undefined;
367+
}
368+
this._toolbar.setActions([...providedActions, ...menuActions]);
369+
} else {
370+
this._toolbar.setActions(menuActions);
371+
}
347372
}
348373

349374
private _layout(): void {
@@ -488,9 +513,6 @@ export class AccessibleViewService extends Disposable implements IAccessibleView
488513
showAccessibleViewHelp(): void {
489514
this._accessibleView?.showAccessibleViewHelp();
490515
}
491-
focusToolbar(): void {
492-
this._accessibleView?.focusToolbar();
493-
}
494516
}
495517

496518

0 commit comments

Comments
 (0)