Skip to content

Commit d267dd7

Browse files
meganroggeAlex0007
authored andcommitted
Merge pull request microsoft#195517 from microsoft/merogge/clear-cue
add clear audio cue, accessible notification service
2 parents d7461e4 + d1ab8a6 commit d267dd7

File tree

14 files changed

+82
-26
lines changed

14 files changed

+82
-26
lines changed

src/vs/platform/accessibility/browser/accessibilityService.ts

+1-7
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { addDisposableListener } from 'vs/base/browser/dom';
77
import { alert } from 'vs/base/browser/ui/aria/aria';
88
import { Emitter, Event } from 'vs/base/common/event';
99
import { Disposable } from 'vs/base/common/lifecycle';
10-
import { localize } from 'vs/nls';
1110
import { AccessibilitySupport, CONTEXT_ACCESSIBILITY_MODE_ENABLED, IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
1211
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
1312
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
@@ -27,7 +26,7 @@ export class AccessibilityService extends Disposable implements IAccessibilitySe
2726
constructor(
2827
@IContextKeyService private readonly _contextKeyService: IContextKeyService,
2928
@ILayoutService private readonly _layoutService: ILayoutService,
30-
@IConfigurationService protected readonly _configurationService: IConfigurationService,
29+
@IConfigurationService protected readonly _configurationService: IConfigurationService
3130
) {
3231
super();
3332
this._accessibilityModeEnabledContext = CONTEXT_ACCESSIBILITY_MODE_ENABLED.bindTo(this._contextKeyService);
@@ -116,9 +115,4 @@ export class AccessibilityService extends Disposable implements IAccessibilitySe
116115
alert(message: string): void {
117116
alert(message);
118117
}
119-
alertCleared(): void {
120-
if (this.isScreenReaderOptimized()) {
121-
alert(localize('cleared', "Cleared"));
122-
}
123-
}
124118
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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+
6+
import { Disposable } from 'vs/base/common/lifecycle';
7+
import { localize } from 'vs/nls';
8+
import { IAccessibilityService, IAccessibleNotificationService } from 'vs/platform/accessibility/common/accessibility';
9+
import { AudioCue, IAudioCueService } from 'vs/platform/audioCues/browser/audioCueService';
10+
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
11+
12+
export class AccessibleNotificationService extends Disposable implements IAccessibleNotificationService {
13+
declare readonly _serviceBrand: undefined;
14+
15+
constructor(
16+
@IAudioCueService private readonly _audioCueService: IAudioCueService,
17+
@IConfigurationService private readonly _configurationService: IConfigurationService,
18+
@IAccessibilityService private readonly _accessibilityService: IAccessibilityService) {
19+
super();
20+
}
21+
22+
notifyCleared(): void {
23+
const audioCueValue = this._configurationService.getValue(AudioCue.clear.settingsKey);
24+
if (audioCueValue === 'on' || audioCueValue === 'auto' && this._accessibilityService.isScreenReaderOptimized()) {
25+
this._audioCueService.playAudioCue(AudioCue.clear);
26+
} else {
27+
alert(localize('cleared', "Cleared"));
28+
}
29+
}
30+
}
31+
32+
export class TestAccessibleNotificationService extends Disposable implements IAccessibleNotificationService {
33+
34+
declare readonly _serviceBrand: undefined;
35+
36+
notifyCleared(): void { }
37+
}

src/vs/platform/accessibility/common/accessibility.ts

+12-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ export interface IAccessibilityService {
2121
getAccessibilitySupport(): AccessibilitySupport;
2222
setAccessibilitySupport(accessibilitySupport: AccessibilitySupport): void;
2323
alert(message: string): void;
24-
alertCleared(): void;
2524
}
2625

2726
export const enum AccessibilitySupport {
@@ -47,3 +46,15 @@ export function isAccessibilityInformation(obj: any): obj is IAccessibilityInfor
4746
&& typeof obj.label === 'string'
4847
&& (typeof obj.role === 'undefined' || typeof obj.role === 'string');
4948
}
49+
50+
export const IAccessibleNotificationService = createDecorator<IAccessibleNotificationService>('accessibleNotificationService');
51+
/**
52+
* Manages whether an audio cue or an aria alert will be used
53+
* in response to actions taken around the workbench.
54+
* Targets screen reader and braille users.
55+
*/
56+
export interface IAccessibleNotificationService {
57+
readonly _serviceBrand: undefined;
58+
notifyCleared(): void;
59+
}
60+

src/vs/platform/accessibility/test/common/testAccessibilityService.ts

-1
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,4 @@ export class TestAccessibilityService implements IAccessibilityService {
1919
setAccessibilitySupport(accessibilitySupport: AccessibilitySupport): void { }
2020
getAccessibilitySupport(): AccessibilitySupport { return AccessibilitySupport.Unknown; }
2121
alert(message: string): void { }
22-
alertCleared(): void { }
2322
}

src/vs/platform/audioCues/browser/audioCueService.ts

+7
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ export class Sound {
254254
public static readonly chatResponseReceived2 = Sound.register({ fileName: 'chatResponseReceived2.mp3' });
255255
public static readonly chatResponseReceived3 = Sound.register({ fileName: 'chatResponseReceived3.mp3' });
256256
public static readonly chatResponseReceived4 = Sound.register({ fileName: 'chatResponseReceived4.mp3' });
257+
public static readonly clear = Sound.register({ fileName: 'clear.mp3' });
257258

258259
private constructor(public readonly fileName: string) { }
259260
}
@@ -419,6 +420,12 @@ export class AudioCue {
419420
settingsKey: 'audioCues.chatResponsePending'
420421
});
421422

423+
public static readonly clear = AudioCue.register({
424+
name: localize('audioCues.clear', 'Clear'),
425+
sound: Sound.clear,
426+
settingsKey: 'audioCues.clear'
427+
});
428+
422429
private constructor(
423430
public readonly sound: SoundSource,
424431
public readonly name: string,
Binary file not shown.

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

+3
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,12 @@ import { UnfocusedViewDimmingContribution } from 'vs/workbench/contrib/accessibi
1313
import { EditorAccessibilityHelpContribution, HoverAccessibleViewContribution, InlineCompletionsAccessibleViewContribution, NotificationAccessibleViewContribution } from 'vs/workbench/contrib/accessibility/browser/accessibilityContributions';
1414
import { AccessibilityStatus } from 'vs/workbench/contrib/accessibility/browser/accessibilityStatus';
1515
import { CommentsAccessibilityHelpContribution } from 'vs/workbench/contrib/comments/browser/comments.contribution';
16+
import { IAccessibleNotificationService } from 'vs/platform/accessibility/common/accessibility';
17+
import { AccessibleNotificationService } from 'vs/platform/accessibility/browser/accessibleNotificationService';
1618

1719
registerAccessibilityConfiguration();
1820
registerSingleton(IAccessibleViewService, AccessibleViewService, InstantiationType.Delayed);
21+
registerSingleton(IAccessibleNotificationService, AccessibleNotificationService, InstantiationType.Delayed);
1922

2023
const workbenchRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
2124
workbenchRegistry.registerWorkbenchContribution(EditorAccessibilityHelpContribution, LifecyclePhase.Eventually);

src/vs/workbench/contrib/audioCues/browser/audioCues.contribution.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,13 @@ Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration).regis
131131
'description': localize('audioCues.chatResponseReceived', "Plays a sound on loop while the response has been received."),
132132
...audioCueFeatureBase,
133133
default: 'off'
134-
}
135-
}
134+
},
135+
'audioCues.clear': {
136+
'description': localize('audioCues.clear', "Plays a sound when a feature is cleared (for example, the terminal, debug console, or output channel). When this is disabled, an aria alert will announce 'Cleared'."),
137+
...audioCueFeatureBase,
138+
default: 'off'
139+
},
140+
},
136141
});
137142

138143
registerAction2(ShowAudioCueHelp);

src/vs/workbench/contrib/chat/browser/actions/chatClearActions.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { Codicon } from 'vs/base/common/codicons';
77
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
88
import { ServicesAccessor } from 'vs/editor/browser/editorExtensions';
99
import { localize } from 'vs/nls';
10+
import { IAccessibleNotificationService } from 'vs/platform/accessibility/common/accessibility';
1011
import { Action2, IAction2Options, MenuId, registerAction2 } from 'vs/platform/actions/common/actions';
1112
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
1213
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
@@ -18,7 +19,6 @@ import { IChatWidgetService } from 'vs/workbench/contrib/chat/browser/chat';
1819
import { ChatEditorInput } from 'vs/workbench/contrib/chat/browser/chatEditorInput';
1920
import { ChatViewPane } from 'vs/workbench/contrib/chat/browser/chatViewPane';
2021
import { CONTEXT_IN_CHAT_SESSION, CONTEXT_PROVIDER_EXISTS } from 'vs/workbench/contrib/chat/common/chatContextKeys';
21-
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
2222

2323
export const ACTION_ID_CLEAR_CHAT = `workbench.action.chat.clear`;
2424

@@ -118,5 +118,5 @@ export function getClearAction(viewId: string, providerId: string) {
118118
}
119119

120120
function announceChatCleared(accessor: ServicesAccessor): void {
121-
accessor.get(IAccessibilityService).alertCleared();
121+
accessor.get(IAccessibleNotificationService).notifyCleared();
122122
}

src/vs/workbench/contrib/debug/browser/repl.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ import { Variable } from 'vs/workbench/contrib/debug/common/debugModel';
6969
import { ReplEvaluationResult, ReplGroup } from 'vs/workbench/contrib/debug/common/replModel';
7070
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
7171
import { registerNavigableContainer } from 'vs/workbench/browser/actions/widgetNavigationCommands';
72-
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
72+
import { IAccessibleNotificationService } from 'vs/platform/accessibility/common/accessibility';
7373

7474
const $ = dom.$;
7575

@@ -976,9 +976,9 @@ registerAction2(class extends ViewAction<Repl> {
976976
}
977977

978978
runInView(_accessor: ServicesAccessor, view: Repl): void {
979-
const accessibilityService = _accessor.get(IAccessibilityService);
979+
const accessibleNotificationService = _accessor.get(IAccessibleNotificationService);
980980
view.clearRepl();
981-
accessibilityService.alertCleared();
981+
accessibleNotificationService.notifyCleared();
982982
}
983983
});
984984

src/vs/workbench/contrib/output/browser/output.contribution.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import { registerIcon } from 'vs/platform/theme/common/iconRegistry';
2828
import { Categories } from 'vs/platform/action/common/actionCommonCategories';
2929
import { Disposable, dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
3030
import { IFilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
31-
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
31+
import { IAccessibleNotificationService } from 'vs/platform/accessibility/common/accessibility';
3232

3333
// Register Service
3434
registerSingleton(IOutputService, OutputService, InstantiationType.Delayed);
@@ -221,11 +221,11 @@ class OutputContribution extends Disposable implements IWorkbenchContribution {
221221
}
222222
async run(accessor: ServicesAccessor): Promise<void> {
223223
const outputService = accessor.get(IOutputService);
224-
const accesibilityService = accessor.get(IAccessibilityService);
224+
const accessibleNotificationService = accessor.get(IAccessibleNotificationService);
225225
const activeChannel = outputService.getActiveChannel();
226226
if (activeChannel) {
227227
activeChannel.clear();
228-
accesibilityService.alertCleared();
228+
accessibleNotificationService.notifyCleared();
229229
}
230230
}
231231
}));

src/vs/workbench/contrib/terminal/browser/terminalInstance.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
355355
@IOpenerService private readonly _openerService: IOpenerService,
356356
@ICommandService private readonly _commandService: ICommandService,
357357
@IAudioCueService private readonly _audioCueService: IAudioCueService,
358-
@IViewDescriptorService private readonly _viewDescriptorService: IViewDescriptorService,
358+
@IViewDescriptorService private readonly _viewDescriptorService: IViewDescriptorService
359359
) {
360360
super();
361361

src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService
4343
import { debounce } from 'vs/base/common/decorators';
4444
import { MouseWheelClassifier } from 'vs/base/browser/ui/scrollbar/scrollableElement';
4545
import { IMouseWheelEvent, StandardWheelEvent } from 'vs/base/browser/mouseEvent';
46-
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
46+
import { IAccessibleNotificationService } from 'vs/platform/accessibility/common/accessibility';
4747

4848
const enum RenderConstants {
4949
/**
@@ -204,7 +204,7 @@ export class XtermTerminal extends Disposable implements IXtermTerminal, IDetach
204204
@ITelemetryService private readonly _telemetryService: ITelemetryService,
205205
@IClipboardService private readonly _clipboardService: IClipboardService,
206206
@IContextKeyService contextKeyService: IContextKeyService,
207-
@IAccessibilityService private readonly _accessibilityService: IAccessibilityService
207+
@IAccessibleNotificationService private readonly _accessibleNotificationService: IAccessibleNotificationService
208208
) {
209209
super();
210210
const font = this._configHelper.getFont(undefined, true);
@@ -590,7 +590,7 @@ export class XtermTerminal extends Disposable implements IXtermTerminal, IDetach
590590
// the prompt being written
591591
this._capabilities.get(TerminalCapability.CommandDetection)?.handlePromptStart();
592592
this._capabilities.get(TerminalCapability.CommandDetection)?.handleCommandStart();
593-
this._accessibilityService.alertCleared();
593+
this._accessibleNotificationService.notifyCleared();
594594
}
595595

596596
hasSelection(): boolean {

src/vs/workbench/contrib/terminalContrib/accessibility/test/browser/bufferContentTracker.test.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import * as assert from 'assert';
77
import { importAMDNodeModule } from 'vs/amdX';
88
import { isWindows } from 'vs/base/common/platform';
99
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
10-
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
11-
import { TestAccessibilityService } from 'vs/platform/accessibility/test/common/testAccessibilityService';
10+
import { TestAccessibleNotificationService } from 'vs/platform/accessibility/browser/accessibleNotificationService';
11+
import { IAccessibleNotificationService } from 'vs/platform/accessibility/common/accessibility';
1212
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
1313
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
1414
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
@@ -67,7 +67,7 @@ suite('Buffer Content Tracker', () => {
6767
instantiationService.stub(IContextMenuService, store.add(instantiationService.createInstance(ContextMenuService)));
6868
instantiationService.stub(ILifecycleService, store.add(new TestLifecycleService()));
6969
instantiationService.stub(IContextKeyService, store.add(new MockContextKeyService()));
70-
instantiationService.stub(IAccessibilityService, new TestAccessibilityService());
70+
instantiationService.stub(IAccessibleNotificationService, store.add(new TestAccessibleNotificationService()));
7171
configHelper = store.add(instantiationService.createInstance(TerminalConfigHelper));
7272
capabilities = store.add(new TerminalCapabilityStore());
7373
if (!isWindows) {

0 commit comments

Comments
 (0)