Path: blob/main/src/vs/workbench/contrib/accessibilitySignals/browser/commands.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 { Codicon } from '../../../../base/common/codicons.js';6import { ThemeIcon } from '../../../../base/common/themables.js';7import { localize, localize2 } from '../../../../nls.js';8import { IAccessibilityService } from '../../../../platform/accessibility/common/accessibility.js';9import { Action2 } from '../../../../platform/actions/common/actions.js';10import { AccessibilitySignal, AcknowledgeDocCommentsToken, IAccessibilitySignalService } from '../../../../platform/accessibilitySignal/browser/accessibilitySignalService.js';11import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';12import { ServicesAccessor } from '../../../../platform/instantiation/common/instantiation.js';13import { IQuickInputService, IQuickPickItem } from '../../../../platform/quickinput/common/quickInput.js';14import { IPreferencesService } from '../../../services/preferences/common/preferences.js';15import { DisposableStore } from '../../../../base/common/lifecycle.js';1617export class ShowSignalSoundHelp extends Action2 {18static readonly ID = 'signals.sounds.help';1920constructor() {21super({22id: ShowSignalSoundHelp.ID,23title: localize2('signals.sound.help', "Help: List Signal Sounds"),24f1: true,25metadata: {26description: localize('accessibility.sound.help.description', "List all accessibility sounds, noises, or audio cues and configure their settings")27}28});29}3031override async run(accessor: ServicesAccessor): Promise<void> {32const accessibilitySignalService = accessor.get(IAccessibilitySignalService);33const quickInputService = accessor.get(IQuickInputService);34const configurationService = accessor.get(IConfigurationService);35const accessibilityService = accessor.get(IAccessibilityService);36const preferencesService = accessor.get(IPreferencesService);37const userGestureSignals = [AccessibilitySignal.save, AccessibilitySignal.format];38const items: (IQuickPickItem & { signal: AccessibilitySignal })[] = AccessibilitySignal.allAccessibilitySignals.map((signal, idx) => ({39label: userGestureSignals.includes(signal) ? `${signal.name} (${configurationService.getValue(signal.settingsKey + '.sound')})` : signal.name,40signal,41buttons: userGestureSignals.includes(signal) ? [{42iconClass: ThemeIcon.asClassName(Codicon.settingsGear),43tooltip: localize('sounds.help.settings', 'Configure Sound'),44alwaysVisible: true45}] : []46})).sort((a, b) => a.label.localeCompare(b.label));47const disposables = new DisposableStore();48const qp = disposables.add(quickInputService.createQuickPick<IQuickPickItem & { signal: AccessibilitySignal }>());49qp.items = items;50qp.selectedItems = items.filter(i => accessibilitySignalService.isSoundEnabled(i.signal) || userGestureSignals.includes(i.signal) && configurationService.getValue(i.signal.settingsKey + '.sound') !== 'never');51disposables.add(qp.onDidAccept(() => {52const enabledSounds = qp.selectedItems.map(i => i.signal);53const disabledSounds = qp.items.map(i => (i as any).signal).filter(i => !enabledSounds.includes(i));54for (const signal of enabledSounds) {55let { sound, announcement } = configurationService.getValue<{ sound: string; announcement?: string }>(signal.settingsKey);56sound = userGestureSignals.includes(signal) ? 'userGesture' : accessibilityService.isScreenReaderOptimized() ? 'auto' : 'on';57if (announcement) {58configurationService.updateValue(signal.settingsKey, { sound, announcement });59} else {60configurationService.updateValue(signal.settingsKey, { sound });61}62}6364for (const signal of disabledSounds) {65const announcement = configurationService.getValue(signal.settingsKey + '.announcement');66const sound = getDisabledSettingValue(userGestureSignals.includes(signal), accessibilityService.isScreenReaderOptimized());67const value = announcement ? { sound, announcement } : { sound };68configurationService.updateValue(signal.settingsKey, value);69}70qp.hide();71}));72disposables.add(qp.onDidTriggerItemButton(e => {73preferencesService.openUserSettings({ jsonEditor: true, revealSetting: { key: e.item.signal.settingsKey, edit: true } });74}));75disposables.add(qp.onDidChangeActive(() => {76accessibilitySignalService.playSound(qp.activeItems[0].signal.sound.getSound(true), true, AcknowledgeDocCommentsToken);77}));78disposables.add(qp.onDidHide(() => disposables.dispose()));79qp.placeholder = localize('sounds.help.placeholder', 'Select a sound to play and configure');80qp.canSelectMany = true;81await qp.show();82}83}8485function getDisabledSettingValue(isUserGestureSignal: boolean, isScreenReaderOptimized: boolean): string {86return isScreenReaderOptimized ? (isUserGestureSignal ? 'never' : 'off') : (isUserGestureSignal ? 'never' : 'auto');87}8889export class ShowAccessibilityAnnouncementHelp extends Action2 {90static readonly ID = 'accessibility.announcement.help';9192constructor() {93super({94id: ShowAccessibilityAnnouncementHelp.ID,95title: localize2('accessibility.announcement.help', "Help: List Signal Announcements"),96f1: true,97metadata: {98description: localize('accessibility.announcement.help.description', "List all accessibility announcements, alerts, braille messages, and configure their settings")99}100});101}102103override async run(accessor: ServicesAccessor): Promise<void> {104const accessibilitySignalService = accessor.get(IAccessibilitySignalService);105const quickInputService = accessor.get(IQuickInputService);106const configurationService = accessor.get(IConfigurationService);107const accessibilityService = accessor.get(IAccessibilityService);108const preferencesService = accessor.get(IPreferencesService);109const userGestureSignals = [AccessibilitySignal.save, AccessibilitySignal.format];110const items: (IQuickPickItem & { signal: AccessibilitySignal })[] = AccessibilitySignal.allAccessibilitySignals.filter(c => !!c.legacyAnnouncementSettingsKey).map((signal, idx) => ({111label: userGestureSignals.includes(signal) ? `${signal.name} (${configurationService.getValue(signal.settingsKey + '.announcement')})` : signal.name,112signal,113buttons: userGestureSignals.includes(signal) ? [{114iconClass: ThemeIcon.asClassName(Codicon.settingsGear),115tooltip: localize('announcement.help.settings', 'Configure Announcement'),116alwaysVisible: true,117}] : []118})).sort((a, b) => a.label.localeCompare(b.label));119const disposables = new DisposableStore();120const qp = disposables.add(quickInputService.createQuickPick<IQuickPickItem & { signal: AccessibilitySignal }>());121qp.items = items;122qp.selectedItems = items.filter(i => accessibilitySignalService.isAnnouncementEnabled(i.signal) || userGestureSignals.includes(i.signal) && configurationService.getValue(i.signal.settingsKey + '.announcement') !== 'never');123const screenReaderOptimized = accessibilityService.isScreenReaderOptimized();124disposables.add(qp.onDidAccept(() => {125if (!screenReaderOptimized) {126// announcements are off by default when screen reader is not active127qp.hide();128return;129}130const enabledAnnouncements = qp.selectedItems.map(i => i.signal);131const disabledAnnouncements = AccessibilitySignal.allAccessibilitySignals.filter(cue => !!cue.legacyAnnouncementSettingsKey && !enabledAnnouncements.includes(cue));132for (const signal of enabledAnnouncements) {133let { sound, announcement } = configurationService.getValue<{ sound: string; announcement?: string }>(signal.settingsKey);134announcement = userGestureSignals.includes(signal) ? 'userGesture' : signal.announcementMessage && accessibilityService.isScreenReaderOptimized() ? 'auto' : undefined;135configurationService.updateValue(signal.settingsKey, { sound, announcement });136}137138for (const signal of disabledAnnouncements) {139const announcement = getDisabledSettingValue(userGestureSignals.includes(signal), true);140const sound = configurationService.getValue(signal.settingsKey + '.sound');141const value = announcement ? { sound, announcement } : { sound };142configurationService.updateValue(signal.settingsKey, value);143}144qp.hide();145}));146disposables.add(qp.onDidTriggerItemButton(e => {147preferencesService.openUserSettings({ jsonEditor: true, revealSetting: { key: e.item.signal.settingsKey, edit: true } });148}));149disposables.add(qp.onDidHide(() => disposables.dispose()));150qp.placeholder = screenReaderOptimized ? localize('announcement.help.placeholder', 'Select an announcement to configure') : localize('announcement.help.placeholder.disabled', 'Screen reader is not active, announcements are disabled by default.');151qp.canSelectMany = true;152await qp.show();153}154}155156157