Path: blob/main/src/vs/workbench/contrib/accessibility/browser/accessibilityStatus.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { Disposable, MutableDisposable } from '../../../../base/common/lifecycle.js';6import { Event } from '../../../../base/common/event.js';7import Severity from '../../../../base/common/severity.js';8import { localize } from '../../../../nls.js';9import { IAccessibilityService } from '../../../../platform/accessibility/common/accessibility.js';10import { CommandsRegistry } from '../../../../platform/commands/common/commands.js';11import { ConfigurationTarget, IConfigurationService } from '../../../../platform/configuration/common/configuration.js';12import { INotificationHandle, INotificationService, NotificationPriority } from '../../../../platform/notification/common/notification.js';13import { IWorkbenchContribution } from '../../../common/contributions.js';14import { IStatusbarEntryAccessor, IStatusbarService, StatusbarAlignment } from '../../../services/statusbar/browser/statusbar.js';15import { IOpenerService } from '../../../../platform/opener/common/opener.js';1617export class AccessibilityStatus extends Disposable implements IWorkbenchContribution {1819static readonly ID = 'workbench.contrib.accessibilityStatus';2021private screenReaderNotification: INotificationHandle | null = null;22private promptedScreenReader: boolean = false;23private readonly screenReaderModeElement = this._register(new MutableDisposable<IStatusbarEntryAccessor>());2425constructor(26@IConfigurationService private readonly configurationService: IConfigurationService,27@INotificationService private readonly notificationService: INotificationService,28@IAccessibilityService private readonly accessibilityService: IAccessibilityService,29@IStatusbarService private readonly statusbarService: IStatusbarService,30@IOpenerService private readonly openerService: IOpenerService,31) {32super();3334this._register(CommandsRegistry.registerCommand({ id: 'showEditorScreenReaderNotification', handler: () => this.showScreenReaderNotification() }));3536this.updateScreenReaderModeElement(this.accessibilityService.isScreenReaderOptimized());3738this.registerListeners();39}4041private registerListeners(): void {42this._register(this.accessibilityService.onDidChangeScreenReaderOptimized(() => this.onScreenReaderModeChange()));4344this._register(this.configurationService.onDidChangeConfiguration(c => {45if (c.affectsConfiguration('editor.accessibilitySupport')) {46this.onScreenReaderModeChange();47}48}));49}5051private showScreenReaderNotification(): void {52this.screenReaderNotification = this.notificationService.prompt(53Severity.Info,54localize('screenReaderDetectedExplanation.question', "Screen reader usage detected. Do you want to enable {0} to optimize the editor for screen reader usage?", 'editor.accessibilitySupport'),55[{56label: localize('screenReaderDetectedExplanation.answerYes', "Yes"),57run: () => {58this.configurationService.updateValue('editor.accessibilitySupport', 'on', ConfigurationTarget.USER);59}60}, {61label: localize('screenReaderDetectedExplanation.answerNo', "No"),62run: () => {63this.configurationService.updateValue('editor.accessibilitySupport', 'off', ConfigurationTarget.USER);64}65},66{67label: localize('screenReaderDetectedExplanation.answerLearnMore', "Learn More"),68run: () => {69this.openerService.open('https://code.visualstudio.com/docs/editor/accessibility#_screen-readers');70}71}],72{73sticky: true,74priority: NotificationPriority.URGENT75}76);7778Event.once(this.screenReaderNotification.onDidClose)(() => this.screenReaderNotification = null);79}80private updateScreenReaderModeElement(visible: boolean): void {81if (visible) {82if (!this.screenReaderModeElement.value) {83const text = localize('screenReaderDetected', "Screen Reader Optimized");84this.screenReaderModeElement.value = this.statusbarService.addEntry({85name: localize('status.editor.screenReaderMode', "Screen Reader Mode"),86text,87ariaLabel: text,88command: 'showEditorScreenReaderNotification',89kind: 'prominent',90showInAllWindows: true91}, 'status.editor.screenReaderMode', StatusbarAlignment.RIGHT, 100.6);92}93} else {94this.screenReaderModeElement.clear();95}96}9798private onScreenReaderModeChange(): void {99100// We only support text based editors101const screenReaderDetected = this.accessibilityService.isScreenReaderOptimized();102if (screenReaderDetected) {103const screenReaderConfiguration = this.configurationService.getValue('editor.accessibilitySupport');104if (screenReaderConfiguration === 'auto') {105if (!this.promptedScreenReader) {106this.promptedScreenReader = true;107setTimeout(() => this.showScreenReaderNotification(), 100);108}109}110}111112if (this.screenReaderNotification) {113this.screenReaderNotification.close();114}115this.updateScreenReaderModeElement(this.accessibilityService.isScreenReaderOptimized());116}117}118119120