Skip to content

Commit

Permalink
Merge pull request #193420 from microsoft/merogge/comment-help
Browse files Browse the repository at this point in the history
add comment widget help dialog
  • Loading branch information
meganrogge authored Sep 21, 2023
2 parents a67f435 + d30859f commit 2f4371e
Show file tree
Hide file tree
Showing 9 changed files with 253 additions and 111 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ import { IAccessibleViewService, AccessibleViewService } from 'vs/workbench/cont
import { UnfocusedViewDimmingContribution } from 'vs/workbench/contrib/accessibility/browser/unfocusedViewDimmingContribution';
import { EditorAccessibilityHelpContribution, HoverAccessibleViewContribution, InlineCompletionsAccessibleViewContribution, NotificationAccessibleViewContribution } from 'vs/workbench/contrib/accessibility/browser/accessibilityContributions';
import { AccessibilityStatus } from 'vs/workbench/contrib/accessibility/browser/accessibilityStatus';
import { CommentsAccessibilityHelpContribution } from 'vs/workbench/contrib/comments/browser/comments.contribution';

registerAccessibilityConfiguration();
registerSingleton(IAccessibleViewService, AccessibleViewService, InstantiationType.Delayed);

const workbenchRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
workbenchRegistry.registerWorkbenchContribution(EditorAccessibilityHelpContribution, LifecyclePhase.Eventually);
workbenchRegistry.registerWorkbenchContribution(CommentsAccessibilityHelpContribution, LifecyclePhase.Eventually);
workbenchRegistry.registerWorkbenchContribution(UnfocusedViewDimmingContribution, LifecyclePhase.Restored);

const workbenchContributionsRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ export const enum AccessibilityVerbositySettingId {
Editor = 'accessibility.verbosity.editor',
Hover = 'accessibility.verbosity.hover',
Notification = 'accessibility.verbosity.notification',
EmptyEditorHint = 'accessibility.verbosity.emptyEditorHint'
EmptyEditorHint = 'accessibility.verbosity.emptyEditorHint',
Comments = 'accessibility.verbosity.comments'
}

export const enum AccessibleViewProviderId {
Expand All @@ -57,7 +58,8 @@ export const enum AccessibleViewProviderId {
Editor = 'editor',
Hover = 'hover',
Notification = 'notification',
EmptyEditorHint = 'emptyEditorHint'
EmptyEditorHint = 'emptyEditorHint',
Comments = 'comments'
}

const baseProperty: object = {
Expand Down Expand Up @@ -110,6 +112,10 @@ const configuration: IConfigurationNode = {
[AccessibilityVerbositySettingId.EmptyEditorHint]: {
description: localize('verbosity.emptyEditorHint', 'Provide information about relevant actions in an empty text editor.'),
...baseProperty
},
[AccessibilityVerbositySettingId.Comments]: {
description: localize('verbosity.comments', 'Provide information about actions that can be taken in the comment widget or in a file which contains comments.'),
...baseProperty
}
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ 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';
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { CommentContextKeys } from 'vs/workbench/contrib/comments/common/commentContextKeys';
import { CommentAccessibilityHelpNLS } from 'vs/workbench/contrib/comments/browser/comments.contribution';
import { CommentCommandId } from 'vs/workbench/contrib/comments/common/commentCommandIds';

export class EditorAccessibilityHelpContribution extends Disposable {
static ID: 'editorAccessibilityHelpContribution';
Expand Down Expand Up @@ -66,7 +69,8 @@ class AccessibilityHelpProvider implements IAccessibleContentProvider {
verbositySettingKey = AccessibilityVerbositySettingId.Editor;
constructor(
private readonly _editor: ICodeEditor,
@IKeybindingService private readonly _keybindingService: IKeybindingService
@IKeybindingService private readonly _keybindingService: IKeybindingService,
@IContextKeyService private readonly _contextKeyService: IContextKeyService
) {
}

Expand Down Expand Up @@ -96,6 +100,15 @@ class AccessibilityHelpProvider implements IAccessibleContentProvider {
}
}

const editorContext = this._contextKeyService.getContext(this._editor.getDomNode()!);
if (editorContext.getValue<boolean>(CommentContextKeys.activeEditorHasCommentingRange.key)) {
content.push(this._descriptionForCommand(CommentCommandId.Add, CommentAccessibilityHelpNLS.addComment, CommentAccessibilityHelpNLS.addCommentNoKb));
content.push(this._descriptionForCommand(CommentCommandId.NextThread, CommentAccessibilityHelpNLS.nextCommentThreadKb, CommentAccessibilityHelpNLS.nextCommentThreadNoKb));
content.push(this._descriptionForCommand(CommentCommandId.PreviousThread, CommentAccessibilityHelpNLS.previousCommentThreadKb, CommentAccessibilityHelpNLS.previousCommentThreadNoKb));
content.push(this._descriptionForCommand(CommentCommandId.NextRange, CommentAccessibilityHelpNLS.nextRange, CommentAccessibilityHelpNLS.nextRangeNoKb));
content.push(this._descriptionForCommand(CommentCommandId.PreviousRange, CommentAccessibilityHelpNLS.previousRange, CommentAccessibilityHelpNLS.previousRangeNoKb));
}

if (options.get(EditorOption.stickyScroll).enabled) {
content.push(this._descriptionForCommand('editor.action.focusStickyScroll', AccessibilityHelpNLS.stickScrollKb, AccessibilityHelpNLS.stickScrollNoKb));
}
Expand Down
35 changes: 31 additions & 4 deletions src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView
import { registerNavigableContainer } from 'vs/workbench/browser/actions/widgetNavigationCommands';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { COMMENTS_SECTION, ICommentsConfiguration } from 'vs/workbench/contrib/comments/common/commentsConfiguration';
import { localize } from 'vs/nls';
import { AccessibilityVerbositySettingId } from 'vs/workbench/contrib/accessibility/browser/accessibilityConfiguration';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { AccessibilityCommandId } from 'vs/workbench/contrib/accessibility/common/accessibilityCommands';

export const COMMENTEDITOR_DECORATION_KEY = 'commenteditordecoration';

Expand All @@ -45,6 +49,7 @@ export class CommentThreadWidget<T extends IRange | ICellRange = IRange> extends
private _threadIsEmpty: IContextKey<boolean>;
private _styleElement: HTMLStyleElement;
private _commentThreadContextValue: IContextKey<string | undefined>;
private _focusedContextKey: IContextKey<boolean>;
private _onDidResize = new Emitter<dom.Dimension>();
onDidResize = this._onDidResize.event;

Expand All @@ -53,7 +58,6 @@ export class CommentThreadWidget<T extends IRange | ICellRange = IRange> extends
get commentThread() {
return this._commentThread;
}

constructor(
readonly container: HTMLElement,
private _owner: string,
Expand All @@ -71,12 +75,14 @@ export class CommentThreadWidget<T extends IRange | ICellRange = IRange> extends
},
@ICommentService private commentService: ICommentService,
@IContextMenuService contextMenuService: IContextMenuService,
@IConfigurationService private configurationService: IConfigurationService
@IConfigurationService private configurationService: IConfigurationService,
@IKeybindingService private _keybindingService: IKeybindingService
) {
super();

this._threadIsEmpty = CommentContextKeys.commentThreadIsEmpty.bindTo(this._contextKeyService);
this._threadIsEmpty.set(!_commentThread.comments || !_commentThread.comments.length);
this._focusedContextKey = CommentContextKeys.commentFocused.bindTo(this._contextKeyService);

this._commentMenus = this.commentService.getCommentMenus(this._owner);

Expand Down Expand Up @@ -111,7 +117,13 @@ export class CommentThreadWidget<T extends IRange | ICellRange = IRange> extends
}
}
}));

this._register(tracker.onDidFocus(() => this._focusedContextKey.set(true)));
this._register(tracker.onDidBlur(() => this._focusedContextKey.reset()));
this._register(this.configurationService.onDidChangeConfiguration(e => {
if (e.affectsConfiguration(AccessibilityVerbositySettingId.Comments)) {
this._setAriaLabel();
}
}));
this._body = this._scopedInstantiationService.createInstance(
CommentThreadBody,
this._owner,
Expand All @@ -124,7 +136,7 @@ export class CommentThreadWidget<T extends IRange | ICellRange = IRange> extends
this
) as unknown as CommentThreadBody<T>;
this._register(this._body);

this._setAriaLabel();
this._styleElement = dom.createStyleSheet(this.container);


Expand All @@ -141,6 +153,21 @@ export class CommentThreadWidget<T extends IRange | ICellRange = IRange> extends
this.currentThreadListeners();
}

private _setAriaLabel(): void {
let ariaLabel = localize('commentLabel', "Comment");
let keybinding: string | undefined;
const verbose = this.configurationService.getValue(AccessibilityVerbositySettingId.Comments);
if (verbose) {
keybinding = this._keybindingService.lookupKeybinding(AccessibilityCommandId.OpenAccessibilityHelp, this._contextKeyService)?.getLabel() ?? undefined;
}
if (keybinding) {
ariaLabel = localize('commentLabelWithKeybinding', "{0}, use ({1}) for accessibility help", ariaLabel, keybinding);
} else {
ariaLabel = localize('commentLabelWithKeybindingNoKeybinding', "{0}, run the command Open Accessibility Help which is currently not triggerable via keybinding.", ariaLabel);
}
this._body.container.ariaLabel = ariaLabel;
}

private updateCurrentThread(hasMouse: boolean, hasFocus: boolean) {
if (hasMouse || hasFocus) {
this.commentService.setCurrentCommentThread(this.commentThread);
Expand Down
71 changes: 71 additions & 0 deletions src/vs/workbench/contrib/comments/browser/comments.contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,17 @@ import { Registry } from 'vs/platform/registry/common/platform';
import 'vs/workbench/contrib/comments/browser/commentsEditorContribution';
import { ICommentService, CommentService } from 'vs/workbench/contrib/comments/browser/commentService';
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
import { ctxCommentEditorFocused } from 'vs/workbench/contrib/comments/browser/simpleCommentEditor';
import * as strings from 'vs/base/common/strings';
import { AccessibilityVerbositySettingId } from 'vs/workbench/contrib/accessibility/browser/accessibilityConfiguration';
import { AccessibleViewType, IAccessibleContentProvider, IAccessibleViewOptions, IAccessibleViewService } from 'vs/workbench/contrib/accessibility/browser/accessibleView';
import { AccessibilityHelpAction } from 'vs/workbench/contrib/accessibility/browser/accessibleViewActions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { Disposable } from 'vs/base/common/lifecycle';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { CommentContextKeys } from 'vs/workbench/contrib/comments/common/commentContextKeys';
import { CommentCommandId } from 'vs/workbench/contrib/comments/common/commentCommandIds';

Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration).registerConfiguration({
id: 'comments',
Expand Down Expand Up @@ -54,3 +65,63 @@ Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration).regis
});

registerSingleton(ICommentService, CommentService, InstantiationType.Delayed);


export namespace CommentAccessibilityHelpNLS {
export const escape = nls.localize('escape', "Dismiss the comment widget via Escape.");
export const nextRange = nls.localize('next', "Navigate to the next commenting range via ({0}).");
export const nextRangeNoKb = nls.localize('nextNoKb', "Run the command: Go to Next Commenting Range, which is currently not triggerable via keybinding.");
export const previousRange = nls.localize('previous', "Navigate to the previous comment range via ({0}).");
export const previousRangeNoKb = nls.localize('previousNoKb', "Run the command: Go to Previous Commenting Range, which is currently not triggerable via keybinding.");
export const nextCommentThreadKb = nls.localize('nextCommentThreadKb', "Navigate to the next comment thread via ({0}).");
export const nextCommentThreadNoKb = nls.localize('nextCommentThreadNoKb', "Run the command: Go to Next Comment Thread, which is currently not triggerable via keybinding.");
export const previousCommentThreadKb = nls.localize('previousCommentThreadKb', "Navigate to the previous comment thread via ({0}).");
export const previousCommentThreadNoKb = nls.localize('previousCommentThreadNoKb', "Run the command: Go to Previous Comment Thread, which is currently not triggerable via keybinding.");
export const addComment = nls.localize('addComment', "Add a comment via ({0}).");
export const addCommentNoKb = nls.localize('addCommentNoKb', "Add a comment via the command: Add Comment on Current Selection, which is currently not triggerable via keybinding.");
export const submitComment = nls.localize('submitComment', "Submit the comment via ({0}).");
export const submitCommentNoKb = nls.localize('submitCommentNoKb', "Submit the comment by navigating with tab to the button, as it's currently not triggerable via keybinding.");
}

export class CommentsAccessibilityHelpContribution extends Disposable {
static ID: 'commentsAccessibilityHelpContribution';
constructor() {
super();
this._register(AccessibilityHelpAction.addImplementation(110, 'comments', accessor => {
const instantiationService = accessor.get(IInstantiationService);
const accessibleViewService = accessor.get(IAccessibleViewService);
accessibleViewService.show(instantiationService.createInstance(CommentsAccessibilityHelpProvider));
return true;
}, ContextKeyExpr.or(ctxCommentEditorFocused, CommentContextKeys.commentFocused)));
}
}
export class CommentsAccessibilityHelpProvider implements IAccessibleContentProvider {
verbositySettingKey: AccessibilityVerbositySettingId = AccessibilityVerbositySettingId.Comments;
options: IAccessibleViewOptions = { type: AccessibleViewType.Help };
private _element: HTMLElement | undefined;
constructor(
@IKeybindingService private readonly _keybindingService: IKeybindingService
) {

}
private _descriptionForCommand(commandId: string, msg: string, noKbMsg: string): string {
const kb = this._keybindingService.lookupKeybinding(commandId);
if (kb) {
return strings.format(msg, kb.getAriaLabel());
}
return strings.format(noKbMsg, commandId);
}
provideContent(): string {
this._element = document.activeElement as HTMLElement;
const content: string[] = [];
content.push(CommentAccessibilityHelpNLS.escape);
content.push(this._descriptionForCommand(CommentCommandId.Add, CommentAccessibilityHelpNLS.addComment, CommentAccessibilityHelpNLS.addCommentNoKb));
content.push(this._descriptionForCommand(CommentCommandId.NextRange, CommentAccessibilityHelpNLS.nextRange, CommentAccessibilityHelpNLS.nextRangeNoKb));
content.push(this._descriptionForCommand(CommentCommandId.PreviousRange, CommentAccessibilityHelpNLS.previousRange, CommentAccessibilityHelpNLS.previousRangeNoKb));
content.push(this._descriptionForCommand(CommentCommandId.Submit, CommentAccessibilityHelpNLS.submitComment, CommentAccessibilityHelpNLS.submitCommentNoKb));
return content.join('\n\n');
}
onClose(): void {
this._element?.focus();
}
}
18 changes: 16 additions & 2 deletions src/vs/workbench/contrib/comments/browser/commentsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ import { ICursorSelectionChangedEvent } from 'vs/editor/common/cursorEvents';
import { CommentsPanel } from 'vs/workbench/contrib/comments/browser/commentsView';
import { status } from 'vs/base/browser/ui/aria/aria';
import { CommentContextKeys } from 'vs/workbench/contrib/comments/common/commentContextKeys';
import { AccessibilityVerbositySettingId } from 'vs/workbench/contrib/accessibility/browser/accessibilityConfiguration';
import { AccessibilityCommandId } from 'vs/workbench/contrib/accessibility/common/accessibilityCommands';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';

export const ID = 'editor.contrib.review';

Expand Down Expand Up @@ -380,7 +383,8 @@ export class CommentController implements IEditorContribution {
@IViewsService private readonly viewsService: IViewsService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IContextKeyService contextKeyService: IContextKeyService,
@IEditorService private readonly editorService: IEditorService
@IEditorService private readonly editorService: IEditorService,
@IKeybindingService private readonly keybindingService: IKeybindingService
) {
this._commentInfos = [];
this._commentWidgets = [];
Expand Down Expand Up @@ -848,7 +852,17 @@ export class CommentController implements IEditorContribution {
if (this._commentInfos.some(commentInfo => commentInfo.commentingRanges.ranges.length > 0 || commentInfo.commentingRanges.fileComments)) {
this._hasRespondedToEditorChange = true;
this._activeEditorHasCommentingRange.set(true);
status(nls.localize('hasCommentRanges', "Editor has commenting ranges."));
const verbose = this.configurationService.getValue(AccessibilityVerbositySettingId.Comments);
if (verbose) {
const keybinding = this.keybindingService.lookupKeybinding(AccessibilityCommandId.OpenAccessibilityHelp)?.getAriaLabel();
if (keybinding) {
status(nls.localize('hasCommentRangesKb', "Editor has commenting ranges, run the command Open Accessibility Help ({0}), for more information.", keybinding));
} else {
status(nls.localize('hasCommentRangesNoKb', "Editor has commenting ranges, run the command Open Accessibility Help, which is currently not triggerable via keybinding, for more information."));
}
} else {
status(nls.localize('hasCommentRanges', "Editor has commenting ranges."));
}
} else {
this._activeEditorHasCommentingRange.set(false);
}
Expand Down
Loading

0 comments on commit 2f4371e

Please sign in to comment.