Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
meganrogge authored and Krzysztof-Cieslak committed Sep 18, 2023
1 parent 6d7cafc commit 6b238b1
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { alert } from 'vs/base/browser/ui/aria/aria';
import { alert, status } from 'vs/base/browser/ui/aria/aria';
import { Event } from 'vs/base/common/event';
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { ITransaction, autorun, constObservable, disposableObservableValue, observableFromEvent, observableValue, transaction } from 'vs/base/common/observable';
Expand All @@ -22,11 +22,13 @@ import { InlineCompletionContextKeys } from 'vs/editor/contrib/inlineCompletions
import { InlineCompletionsHintsWidget, InlineSuggestionHintsContentWidget } from 'vs/editor/contrib/inlineCompletions/browser/inlineCompletionsHintsWidget';
import { InlineCompletionsModel, VersionIdChangeReason } from 'vs/editor/contrib/inlineCompletions/browser/inlineCompletionsModel';
import { SuggestWidgetAdaptor } from 'vs/editor/contrib/inlineCompletions/browser/suggestWidgetInlineCompletionProvider';
import { localize } from 'vs/nls';
import { AudioCue, IAudioCueService } from 'vs/platform/audioCues/browser/audioCueService';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';

export class InlineCompletionsController extends Disposable {
static ID = 'editor.contrib.inlineCompletionsController';
Expand Down Expand Up @@ -73,6 +75,7 @@ export class InlineCompletionsController extends Disposable {
@ILanguageFeatureDebounceService private readonly debounceService: ILanguageFeatureDebounceService,
@ILanguageFeaturesService private readonly languageFeaturesService: ILanguageFeaturesService,
@IAudioCueService private readonly audioCueService: IAudioCueService,
@IKeybindingService private readonly _keybindingService: IKeybindingService
) {
super();

Expand Down Expand Up @@ -191,6 +194,7 @@ export class InlineCompletionsController extends Disposable {
this.audioCueService.playAudioCue(AudioCue.inlineSuggestion).then(() => {
if (this.editor.getOption(EditorOption.screenReaderAnnounceInlineSuggestion)) {
alert(state.ghostText.renderForScreenReader(lineText));
this.provideScreenReaderHint();
}
});
}
Expand All @@ -199,6 +203,24 @@ export class InlineCompletionsController extends Disposable {
this._register(new InlineCompletionsHintsWidget(this.editor, this.model, this.instantiationService));
}

private provideScreenReaderHint(): void {
const showHoverKeybinding = this._keybindingService.lookupKeybinding('editor.action.showHover');
const accessibleViewKeybinding = this._keybindingService.lookupKeybinding('editor.action.accessibleView');
if (this.configurationService.getValue('accessibility.verbosity.inlineCompletions')) {
let hint: string | undefined;
if (showHoverKeybinding && accessibleViewKeybinding) {
hint = localize('showBothHints', "View more actions ({0}) or inspect this in the accessible view ({1})", showHoverKeybinding.getAriaLabel(), accessibleViewKeybinding.getAriaLabel());
} else if (showHoverKeybinding) {
hint = localize('showHoverHint', "View more actions ({0})", showHoverKeybinding.getAriaLabel());
} else if (accessibleViewKeybinding) {
hint = localize('showAccessibleViewHint', "Inspect this in the accessible view ({0})", accessibleViewKeybinding.getAriaLabel());
}
if (hint) {
status(hint);
}
}
}

/**
* Copies over the relevant state from the text model to observables.
* This solves all kind of eventing issues, as we make sure we always operate on the latest state,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle
import { Registry } from 'vs/platform/registry/common/platform';
import { IAccessibleViewService, AccessibleViewService } from 'vs/workbench/contrib/accessibility/browser/accessibleView';
import { UnfocusedViewDimmingContribution } from 'vs/workbench/contrib/accessibility/browser/unfocusedViewDimmingContribution';
import { EditorAccessibilityHelpContribution, HoverAccessibleViewContribution, NotificationAccessibleViewContribution } from 'vs/workbench/contrib/accessibility/browser/accessibilityContributions';
import { EditorAccessibilityHelpContribution, HoverAccessibleViewContribution, InlineCompletionsAccessibleViewContribution, NotificationAccessibleViewContribution } from 'vs/workbench/contrib/accessibility/browser/accessibilityContributions';

registerAccessibilityConfiguration();
registerSingleton(IAccessibleViewService, AccessibleViewService, InstantiationType.Delayed);
Expand All @@ -22,3 +22,4 @@ workbenchRegistry.registerWorkbenchContribution(UnfocusedViewDimmingContribution
const workbenchContributionsRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
workbenchContributionsRegistry.registerWorkbenchContribution(HoverAccessibleViewContribution, LifecyclePhase.Eventually);
workbenchContributionsRegistry.registerWorkbenchContribution(NotificationAccessibleViewContribution, LifecyclePhase.Eventually);
workbenchContributionsRegistry.registerWorkbenchContribution(InlineCompletionsAccessibleViewContribution, LifecyclePhase.Eventually);
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const enum AccessibilityVerbositySettingId {
DiffEditor = 'accessibility.verbosity.diffEditor',
Chat = 'accessibility.verbosity.panelChat',
InlineChat = 'accessibility.verbosity.inlineChat',
InlineCompletions = 'accessibility.verbosity.inlineCompletions',
KeybindingsEditor = 'accessibility.verbosity.keybindingsEditor',
Notebook = 'accessibility.verbosity.notebook',
Editor = 'accessibility.verbosity.editor',
Expand Down Expand Up @@ -55,6 +56,10 @@ const configuration: IConfigurationNode = {
description: localize('verbosity.interactiveEditor.description', 'Provide information about how to access the inline editor chat accessibility help menu and alert with hints which describe how to use the feature when the input is focused'),
...baseProperty
},
[AccessibilityVerbositySettingId.InlineCompletions]: {
description: localize('verbosity.inlineCompletions.description', 'Provide information about how to access the inline completions hover and accessible view'),
...baseProperty
},
[AccessibilityVerbositySettingId.KeybindingsEditor]: {
description: localize('verbosity.keybindingsEditor.description', 'Provide information about how to change a keybinding in the keybindings editor when a row is focused'),
...baseProperty
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ import { IAction } from 'vs/base/common/actions';
import { INotificationViewItem } from 'vs/workbench/common/notifications';
import { ThemeIcon } from 'vs/base/common/themables';
import { Codicon } from 'vs/base/common/codicons';
import { InlineCompletionsController } from 'vs/editor/contrib/inlineCompletions/browser/inlineCompletionsController';
import { InlineCompletionContextKeys } from 'vs/editor/contrib/inlineCompletions/browser/inlineCompletionContextKeys';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';

export class EditorAccessibilityHelpContribution extends Disposable {
static ID: 'editorAccessibilityHelpContribution';
Expand Down Expand Up @@ -276,3 +279,44 @@ export function alertFocusChange(index: number | undefined, length: number | und
return;
}

export class InlineCompletionsAccessibleViewContribution extends Disposable {
static ID: 'inlineCompletionsAccessibleViewContribution';
private _options: IAccessibleViewOptions = {
ariaLabel: localize('inlineCompletionsAccessibleView', "Inline Completions Accessible View"), language: 'typescript', type: AccessibleViewType.View
};
constructor() {
super();
this._register(AccessibleViewAction.addImplementation(95, 'inline-completions', accessor => {
const accessibleViewService = accessor.get(IAccessibleViewService);
const codeEditorService = accessor.get(ICodeEditorService);
const editor = codeEditorService.getActiveCodeEditor() || codeEditorService.getFocusedCodeEditor();
if (!editor) {
return false;
}
const model = InlineCompletionsController.get(editor)?.model.get();
const state = model?.state.get();
if (!state) {
return false;
}
const lineText = model?.textModel.getLineContent(state.ghostText.lineNumber);
if (!lineText) {
return false;
}
const content = InlineCompletionsController.get(editor)?.model.get()?.ghostText.get()?.renderForScreenReader(lineText);
if (!content) {
return false;
}
accessibleViewService.show({
verbositySettingKey: AccessibilityVerbositySettingId.InlineCompletions,
provideContent() { return content; },
onClose() {

},
options: this._options
});
return true;
}, ContextKeyExpr.and(InlineCompletionContextKeys.inlineSuggestionVisible, EditorContextKeys.focus, EditorContextKeys.hasCodeActionsProvider)
)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ class AccessibleView extends Disposable {
}
}

const fragment = message + provider.provideContent() + readMoreLink + disableHelpHint + localize('exit-tip', 'Exit this dialog via the Escape key.');
const fragment = message + provider.provideContent() + readMoreLink + disableHelpHint + localize('exit-tip', '\nExit this dialog via the Escape key.');

this._getTextModel(URI.from({ path: `accessible-view-${provider.verbositySettingKey}`, scheme: 'accessible-view', fragment })).then((model) => {
if (!model) {
Expand Down

0 comments on commit 6b238b1

Please sign in to comment.