Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add comment widget help dialog #193420

Merged
merged 17 commits into from
Sep 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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';

meganrogge marked this conversation as resolved.
Show resolved Hide resolved
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();
meganrogge marked this conversation as resolved.
Show resolved Hide resolved
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 {
meganrogge marked this conversation as resolved.
Show resolved Hide resolved
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