From fd68fa632cea9ab627b52c1ec9a4ad908f6200c6 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 19 Jul 2023 11:30:47 -0700 Subject: [PATCH 01/14] add basics --- .../accessibility/browser/accessibleView.ts | 24 ++++++++++++++++++- .../contrib/chat/browser/chatListRenderer.ts | 20 +++++++++++++--- .../contrib/chat/browser/chatWidget.ts | 5 ++-- 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts index 52e818673be..897352f3dd6 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts @@ -25,6 +25,8 @@ import { IOpenerService } from 'vs/platform/opener/common/opener'; import { alert } from 'vs/base/browser/ui/aria/aria'; import { getSimpleEditorOptions } from 'vs/workbench/contrib/codeEditor/browser/simpleEditorOptions'; import { SelectionClipboardContributionID } from 'vs/workbench/contrib/codeEditor/browser/selectionClipboard'; +import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; +import { AccessibilityVerbositySettingId, AccessibleViewAction, AccessibleViewNextAction } from 'vs/workbench/contrib/accessibility/browser/accessibilityContribution'; const enum DEFAULT { WIDTH = 800, @@ -48,6 +50,8 @@ export interface IAccessibleViewService { show(provider: IAccessibleContentProvider): void; next(): void; previous(): void; + getOpenAriaHint(verbositySettingKey: AccessibilityVerbositySettingId): string; + getNavigationAriaHint(verbositySettingKey: AccessibilityVerbositySettingId): string; } export const enum AccessibleViewType { @@ -242,7 +246,9 @@ export class AccessibleViewService extends Disposable implements IAccessibleView private _accessibleView: AccessibleView | undefined; constructor( - @IInstantiationService private readonly _instantiationService: IInstantiationService + @IInstantiationService private readonly _instantiationService: IInstantiationService, + @IConfigurationService private readonly _configurationService: IConfigurationService, + @IKeybindingService private readonly _keybindingService: IKeybindingService ) { super(); } @@ -259,4 +265,20 @@ export class AccessibleViewService extends Disposable implements IAccessibleView previous(): void { this._accessibleView?.previous(); } + getOpenAriaHint(verbositySettingKey: AccessibilityVerbositySettingId): string { + let hint = ''; + const keybinding = this._keybindingService.lookupKeybinding(AccessibleViewAction.id)?.getAriaLabel(); + if (this._configurationService.getValue(verbositySettingKey)) { + hint = keybinding ? localize('chatAccessibleViewHint', "Inspect the response in the accessible view with {0}", keybinding) : localize('chatAccessibleViewHintNoKb', "Inspect the response in the accessible view via the command Open Accessible View which is currently not triggerable via keybinding"); + } + return hint; + } + getNavigationAriaHint(verbositySettingKey: AccessibilityVerbositySettingId): string { + let hint = ''; + const nextKeybinding = this._keybindingService.lookupKeybinding(AccessibleViewNextAction.id)?.getAriaLabel(); + if (this._configurationService.getValue(verbositySettingKey)) { + hint = nextKeybinding ? localize('chatAccessibleViewHint', "Inspect the response in the accessible view with {0}", nextKeybinding) : localize('chatAccessibleViewHintNoKb', "Inspect the response in the accessible view via the command Open Accessible View which is currently not triggerable via keybinding"); + } + return hint; + } } diff --git a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts index bbac658da6f..ee93693be68 100644 --- a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts +++ b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts @@ -50,6 +50,7 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle import { ILogService } from 'vs/platform/log/common/log'; import { defaultButtonStyles } from 'vs/platform/theme/browser/defaultStyles'; import { AccessibilityVerbositySettingId } from 'vs/workbench/contrib/accessibility/browser/accessibilityContribution'; +import { IAccessibleViewService } from 'vs/workbench/contrib/accessibility/browser/accessibleView'; import { IChatCodeBlockActionContext } from 'vs/workbench/contrib/chat/browser/actions/chatCodeblockActions'; import { ChatTreeItem, IChatCodeBlockInfo } from 'vs/workbench/contrib/chat/browser/chat'; import { ChatFollowups } from 'vs/workbench/contrib/chat/browser/chatFollowups'; @@ -513,6 +514,12 @@ export class ChatListDelegate implements IListVirtualDelegate { } export class ChatAccessibilityProvider implements IListAccessibilityProvider { + + constructor( + @IAccessibleViewService private readonly _accessibleViewService: IAccessibleViewService + ) { + + } getWidgetRole(): AriaRole { return 'list'; } @@ -542,15 +549,22 @@ export class ChatAccessibilityProvider implements IListAccessibilityProvider token.type === 'code')?.length ?? 0; switch (codeBlockCount) { case 0: - return element.response.value; + label = localize('noCodeBlocks', "{0} {1}", element.response.value, accessibleViewHint); + break; case 1: - return localize('singleCodeBlock', "1 code block: {0}", element.response.value); + label = localize('singleCodeBlock', "1 code block: {0} {1}", element.response.value, accessibleViewHint); + break; default: - return localize('multiCodeBlock', "{0} code blocks: {1}", codeBlockCount, element.response.value); + label = localize('multiCodeBlock', "{0} code blocks: {1}", codeBlockCount, element.response.value, accessibleViewHint); + break; } + label = label.trim(); + return label; } } diff --git a/src/vs/workbench/contrib/chat/browser/chatWidget.ts b/src/vs/workbench/contrib/chat/browser/chatWidget.ts index 38b3a62da6e..0792427a5c0 100644 --- a/src/vs/workbench/contrib/chat/browser/chatWidget.ts +++ b/src/vs/workbench/contrib/chat/browser/chatWidget.ts @@ -114,7 +114,8 @@ export class ChatWidget extends Disposable implements IChatWidget { @IChatService private readonly chatService: IChatService, @IChatWidgetService chatWidgetService: IChatWidgetService, @IContextMenuService private readonly contextMenuService: IContextMenuService, - @IChatAccessibilityService private readonly _chatAccessibilityService: IChatAccessibilityService + @IChatAccessibilityService private readonly _chatAccessibilityService: IChatAccessibilityService, + @IInstantiationService private readonly _instantiationService: IInstantiationService ) { super(); CONTEXT_IN_CHAT_SESSION.bindTo(contextKeyService).set(true); @@ -274,7 +275,7 @@ export class ChatWidget extends Disposable implements IChatWidget { horizontalScrolling: false, supportDynamicHeights: true, hideTwistiesOfChildlessElements: true, - accessibilityProvider: new ChatAccessibilityProvider(), + accessibilityProvider: this._instantiationService.createInstance(ChatAccessibilityProvider), keyboardNavigationLabelProvider: { getKeyboardNavigationLabel: (e: ChatTreeItem) => isRequestVM(e) ? e.message : isResponseVM(e) ? e.response.value : '' }, // TODO setRowLineHeight: false, overrideStyles: { From 924ae6cdf0256e05c71960c8fc2e92c55871161a Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 19 Jul 2023 13:10:27 -0700 Subject: [PATCH 02/14] add a bunch more --- .../browser/accessibility.contribution.ts | 10 +-- .../browser/accessibilityContribution.ts | 17 +++- .../accessibility/browser/accessibleView.ts | 30 ++++--- .../browser/actions/chatAccessibilityHelp.ts | 3 +- .../contrib/chat/browser/chat.contribution.ts | 83 +++++++++++-------- src/vs/workbench/contrib/chat/browser/chat.ts | 2 + .../contrib/chat/browser/chatWidget.ts | 44 +++++++++- .../codeEditor/browser/diffEditorHelper.ts | 4 +- .../browser/notebookAccessibilityHelp.ts | 3 +- .../browser/terminalAccessibilityHelp.ts | 3 +- 10 files changed, 138 insertions(+), 61 deletions(-) diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibility.contribution.ts b/src/vs/workbench/contrib/accessibility/browser/accessibility.contribution.ts index 63adda5f1fa..29976a108a5 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibility.contribution.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibility.contribution.ts @@ -12,7 +12,7 @@ import { ToggleTabFocusModeAction } from 'vs/editor/contrib/toggleTabFocusMode/b import { localize } from 'vs/nls'; import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { AccessibilityHelpAction, AccessibleViewAction, AccessibleViewNextAction, AccessibleViewPreviousAction, registerAccessibilityConfiguration } from 'vs/workbench/contrib/accessibility/browser/accessibilityContribution'; +import { AccessibilityHelpAction, AccessibilityVerbositySettingId, AccessibleViewAction, AccessibleViewNextAction, AccessibleViewPreviousAction, registerAccessibilityConfiguration } from 'vs/workbench/contrib/accessibility/browser/accessibilityContribution'; import * as strings from 'vs/base/common/strings'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; @@ -36,7 +36,7 @@ class AccessibilityHelpProvider implements IAccessibleContentProvider { this._editor.focus(); } options: IAccessibleViewOptions = { type: AccessibleViewType.HelpMenu, ariaLabel: localize('editor-help', "editor accessibility help"), readMoreUrl: 'https://go.microsoft.com/fwlink/?linkid=851010' }; - verbositySettingKey: string = 'editor'; + verbositySettingKey = AccessibilityVerbositySettingId.Editor; constructor( private readonly _editor: ICodeEditor, @IKeybindingService private readonly _keybindingService: IKeybindingService @@ -118,7 +118,7 @@ class HoverAccessibleViewContribution extends Disposable { return false; } accessibleViewService.show({ - verbositySettingKey: 'hover', + verbositySettingKey: AccessibilityVerbositySettingId.Hover, provideContent() { return editorHoverContent; }, onClose() { }, options: this._options @@ -135,7 +135,7 @@ class HoverAccessibleViewContribution extends Disposable { return false; } accessibleViewService.show({ - verbositySettingKey: 'hover', + verbositySettingKey: AccessibilityVerbositySettingId.Hover, provideContent() { return extensionHoverContent; }, onClose() { }, options: this._options @@ -208,7 +208,7 @@ class NotificationAccessibleViewContribution extends Disposable { list.focusPrevious(); renderAccessibleView(); }, - verbositySettingKey: 'notifications', + verbositySettingKey: AccessibilityVerbositySettingId.Notification, options: { ariaLabel: localize('notification', "Notification Accessible View"), type: AccessibleViewType.View diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibilityContribution.ts b/src/vs/workbench/contrib/accessibility/browser/accessibilityContribution.ts index 9dc863f3efd..80e55ef368e 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibilityContribution.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibilityContribution.ts @@ -17,7 +17,10 @@ export const enum AccessibilityVerbositySettingId { Chat = 'accessibility.verbosity.panelChat', InlineChat = 'accessibility.verbosity.inlineChat', KeybindingsEditor = 'accessibility.verbosity.keybindingsEditor', - Notebook = 'accessibility.verbosity.notebook' + Notebook = 'accessibility.verbosity.notebook', + Editor = 'accessibility.verbosity.editor', + Hover = 'accessibility.verbosity.hover', + Notification = 'accessibility.verbosity.notification' } const baseProperty: object = { @@ -54,6 +57,14 @@ const configuration: IConfigurationNode = { [AccessibilityVerbositySettingId.Notebook]: { description: localize('verbosity.notebook', 'Provide information about how to focus the cell container or inner editor when a notebook cell is focused.'), ...baseProperty + }, + [AccessibilityVerbositySettingId.Hover]: { + description: localize('verbosity.hover', 'Provide information about how to open the hover in an accessible view.'), + ...baseProperty + }, + [AccessibilityVerbositySettingId.Notification]: { + description: localize('verbosity.notification', 'Provide information about how to open the notification in an accessible view.'), + ...baseProperty } } }; @@ -118,7 +129,7 @@ export const AccessibleViewNextAction = registerCommand(new MultiCommand({ menuOpts: [{ menuId: MenuId.CommandPalette, group: '', - title: localize('editor.action.accessibleViewNext', "Next Accessible View"), + title: localize('editor.action.accessibleViewNext', "Show Next in Accessible View"), order: 1 }], })); @@ -133,7 +144,7 @@ export const AccessibleViewPreviousAction = registerCommand(new MultiCommand({ menuOpts: [{ menuId: MenuId.CommandPalette, group: '', - title: localize('editor.action.accessibleViewPrevious', "Previous Accessible View"), + title: localize('editor.action.accessibleViewPrevious', "Show Previous in Accessible View"), order: 1 }], })); diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts index 897352f3dd6..df10b0f0cae 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts @@ -34,7 +34,7 @@ const enum DEFAULT { } export interface IAccessibleContentProvider { - verbositySettingKey: string; + verbositySettingKey: AccessibilityVerbositySettingId; provideContent(): string; onClose(): void; onKeyDown?(e: IKeyboardEvent): void; @@ -51,7 +51,6 @@ export interface IAccessibleViewService { next(): void; previous(): void; getOpenAriaHint(verbositySettingKey: AccessibilityVerbositySettingId): string; - getNavigationAriaHint(verbositySettingKey: AccessibilityVerbositySettingId): string; } export const enum AccessibleViewType { @@ -83,7 +82,8 @@ class AccessibleView extends Disposable { @IModelService private readonly _modelService: IModelService, @IContextViewService private readonly _contextViewService: IContextViewService, @IContextKeyService private readonly _contextKeyService: IContextKeyService, - @IAccessibilityService private readonly _accessibilityService: IAccessibilityService + @IAccessibilityService private readonly _accessibilityService: IAccessibilityService, + @IKeybindingService private readonly _keybindingService: IKeybindingService ) { super(); this._accessiblityHelpIsShown = accessibilityHelpIsShown.bindTo(this._contextKeyService); @@ -173,7 +173,7 @@ class AccessibleView extends Disposable { ? AccessibilityHelpNLS.changeConfigToOnMac : AccessibilityHelpNLS.changeConfigToOnWinLinux ); - if (accessibilitySupport && provider.verbositySettingKey === 'editor') { + if (accessibilitySupport && provider.verbositySettingKey === AccessibilityVerbositySettingId.Editor) { message = AccessibilityHelpNLS.auto_on; message += '\n'; } else if (!accessibilitySupport) { @@ -197,7 +197,7 @@ class AccessibleView extends Disposable { model.setLanguage(provider.options.language); } container.appendChild(this._editorContainer); - this._editorWidget.updateOptions({ ariaLabel: provider.options.ariaLabel }); + this._editorWidget.updateOptions({ ariaLabel: provider.next && provider.previous ? localize('accessibleViewAriaLabelWithNav', "{0} {1}", provider.options.ariaLabel, this._getNavigationAriaHint(provider.verbositySettingKey)) : localize('accessibleViewAriaLabel', "{0}", provider.options.ariaLabel) }); this._editorWidget.focus(); }); const disposableStore = new DisposableStore(); @@ -239,6 +239,16 @@ class AccessibleView extends Disposable { } return this._modelService.createModel(resource.fragment, null, resource, false); } + + private _getNavigationAriaHint(verbositySettingKey: AccessibilityVerbositySettingId): string { + let hint = ''; + const nextKeybinding = this._keybindingService.lookupKeybinding(AccessibleViewNextAction.id)?.getAriaLabel(); + const previousKeybinding = this._keybindingService.lookupKeybinding(AccessibleViewNextAction.id)?.getAriaLabel(); + if (this._configurationService.getValue(verbositySettingKey)) { + hint = (nextKeybinding && previousKeybinding) ? localize('chatAccessibleViewNextPreviousHint', "Focus the next {0} or previous {1} item without leaving the accessible view", nextKeybinding, previousKeybinding) : localize('chatAccessibleViewNextPreviousHintNoKb', "Focus the next or previous item without leaving the accessible view by configuring keybindings for Show Next / Previous in Accessible View"); + } + return hint; + } } export class AccessibleViewService extends Disposable implements IAccessibleViewService { @@ -273,12 +283,6 @@ export class AccessibleViewService extends Disposable implements IAccessibleView } return hint; } - getNavigationAriaHint(verbositySettingKey: AccessibilityVerbositySettingId): string { - let hint = ''; - const nextKeybinding = this._keybindingService.lookupKeybinding(AccessibleViewNextAction.id)?.getAriaLabel(); - if (this._configurationService.getValue(verbositySettingKey)) { - hint = nextKeybinding ? localize('chatAccessibleViewHint', "Inspect the response in the accessible view with {0}", nextKeybinding) : localize('chatAccessibleViewHintNoKb', "Inspect the response in the accessible view via the command Open Accessible View which is currently not triggerable via keybinding"); - } - return hint; - } } + + diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts b/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts index fd147f172ea..b1aeb256378 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts @@ -12,6 +12,7 @@ import { ServicesAccessor } from 'vs/editor/browser/editorExtensions'; import { IChatWidgetService } from 'vs/workbench/contrib/chat/browser/chat'; import { InlineChatController } from 'vs/workbench/contrib/inlineChat/browser/inlineChatController'; import { AccessibleViewType, IAccessibleViewService } from 'vs/workbench/contrib/accessibility/browser/accessibleView'; +import { AccessibilityVerbositySettingId } from 'vs/workbench/contrib/accessibility/browser/accessibilityContribution'; export function getAccessibilityHelpText(accessor: ServicesAccessor, type: 'panelChat' | 'inlineChat'): string { const keybindingService = accessor.get(IKeybindingService); @@ -70,7 +71,7 @@ export async function runAccessibilityHelpAction(accessor: ServicesAccessor, edi inputEditor.getSupportedActions(); const helpText = getAccessibilityHelpText(accessor, type); accessibleViewService.show({ - verbositySettingKey: type, + verbositySettingKey: type as AccessibilityVerbositySettingId, provideContent: () => helpText, onClose: () => { if (type === 'panelChat' && cachedPosition) { diff --git a/src/vs/workbench/contrib/chat/browser/chat.contribution.ts b/src/vs/workbench/contrib/chat/browser/chat.contribution.ts index 656485ed70a..d27847fd437 100644 --- a/src/vs/workbench/contrib/chat/browser/chat.contribution.ts +++ b/src/vs/workbench/contrib/chat/browser/chat.contribution.ts @@ -37,7 +37,7 @@ import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle import '../common/chatColors'; import { registerMoveActions } from 'vs/workbench/contrib/chat/browser/actions/chatMoveActions'; import { registerClearActions } from 'vs/workbench/contrib/chat/browser/actions/chatClearActions'; -import { AccessibleViewAction } from 'vs/workbench/contrib/accessibility/browser/accessibilityContribution'; +import { AccessibilityVerbositySettingId, AccessibleViewAction } from 'vs/workbench/contrib/accessibility/browser/accessibilityContribution'; import { AccessibleViewType, IAccessibleViewService } from 'vs/workbench/contrib/accessibility/browser/accessibleView'; import { isResponseVM } from 'vs/workbench/contrib/chat/common/chatViewModel'; import { CONTEXT_IN_CHAT_SESSION } from 'vs/workbench/contrib/chat/common/chatContextKeys'; @@ -135,48 +135,63 @@ class ChatAccessibleViewContribution extends Disposable { const accessibleViewService = accessor.get(IAccessibleViewService); const widgetService = accessor.get(IChatWidgetService); const codeEditorService = accessor.get(ICodeEditorService); + return renderAccessibleView(false, accessibleViewService, widgetService, codeEditorService); + function renderAccessibleView(ignoreChatInput: boolean, accessibleViewService: IAccessibleViewService, widgetService: IChatWidgetService, codeEditorService: ICodeEditorService): boolean { - let widget = widgetService.lastFocusedWidget; - if (!widget) { - return false; - } + let widget = widgetService.lastFocusedWidget; + if (!widget) { + return false; + } - const chatInputFocused = !!(codeEditorService.getActiveCodeEditor() || codeEditorService.getFocusedCodeEditor()); + const chatInputFocused = !ignoreChatInput && !!(codeEditorService.getActiveCodeEditor() || codeEditorService.getFocusedCodeEditor()); - if (chatInputFocused) { - widget.focusLastMessage(); - widget = widgetService.lastFocusedWidget; - } + if (chatInputFocused) { + widget.focusLastMessage(); + widget = widgetService.lastFocusedWidget; + } - if (!widget) { - return false; - } + if (!widget) { + return false; + } - const verifiedWidget: IChatWidget = widget; - const focusedItem = verifiedWidget.getFocus(); + const verifiedWidget: IChatWidget = widget; + const focusedItem = verifiedWidget.getFocus(); - if (!focusedItem) { - return false; - } + if (!focusedItem) { + return false; + } - const responseContent = isResponseVM(focusedItem) ? focusedItem.response.value : undefined; - if (!responseContent) { - return false; - } + widget.focus(focusedItem); - accessibleViewService.show({ - verbositySettingKey: 'panelChat', - provideContent(): string { return responseContent; }, - onClose() { - if (chatInputFocused) { - verifiedWidget.focusInput(); - } else { + const responseContent = isResponseVM(focusedItem) ? focusedItem.response.value : undefined; + if (!responseContent) { + return false; + } + + accessibleViewService.show({ + verbositySettingKey: AccessibilityVerbositySettingId.Chat, + provideContent(): string { return responseContent; }, + onClose() { + if (chatInputFocused) { + verifiedWidget.focusInput(); + } else { + verifiedWidget.focus(focusedItem); + } + }, + next() { verifiedWidget.focus(focusedItem); - } - }, - options: { ariaLabel: nls.localize('chatAccessibleView', "Chat Accessible View"), language: 'typescript', type: AccessibleViewType.View } - }); - return true; + verifiedWidget.focusNext(focusedItem.id); + renderAccessibleView(true, accessibleViewService, widgetService, codeEditorService); + }, + previous() { + verifiedWidget.focus(focusedItem); + verifiedWidget.focusPrevious(focusedItem.id); + renderAccessibleView(true, accessibleViewService, widgetService, codeEditorService); + }, + options: { ariaLabel: nls.localize('chatAccessibleView', "Chat Accessible View"), language: 'typescript', type: AccessibleViewType.View } + }); + return true; + } }, CONTEXT_IN_CHAT_SESSION)); } } diff --git a/src/vs/workbench/contrib/chat/browser/chat.ts b/src/vs/workbench/contrib/chat/browser/chat.ts index 996a999286c..b454aaf0795 100644 --- a/src/vs/workbench/contrib/chat/browser/chat.ts +++ b/src/vs/workbench/contrib/chat/browser/chat.ts @@ -56,6 +56,8 @@ export interface IChatWidget { reveal(item: ChatTreeItem): void; focus(item: ChatTreeItem): void; + focusNext(id: string): void; + focusPrevious(id: string): void; getFocus(): ChatTreeItem | undefined; acceptInput(query?: string): void; focusLastMessage(): void; diff --git a/src/vs/workbench/contrib/chat/browser/chatWidget.ts b/src/vs/workbench/contrib/chat/browser/chatWidget.ts index 0792427a5c0..523a4974382 100644 --- a/src/vs/workbench/contrib/chat/browser/chatWidget.ts +++ b/src/vs/workbench/contrib/chat/browser/chatWidget.ts @@ -168,6 +168,46 @@ export class ChatWidget extends Disposable implements IChatWidget { this.inputPart.focus(); } + focusNext(id: string): void { + const items = this.viewModel?.getItems(); + if (!items) { + return; + } + const focusedElement = items?.find(i => i.id === id) as any as IChatResponseViewModel; + const responseItems = items?.filter(i => isResponseVM(i)); + if (!focusedElement) { + return; + } + const currentlyFocusedIndex = responseItems?.indexOf(focusedElement); + if (currentlyFocusedIndex === undefined || !responseItems) { + return; + } + if (currentlyFocusedIndex === responseItems.length - 1) { + return; + } + this.focus(responseItems[currentlyFocusedIndex + 1], true); + } + + focusPrevious(id: string): void { + const items = this.viewModel?.getItems(); + if (!items) { + return; + } + const focusedElement = items.find(i => i.id === id) as any as IChatResponseViewModel; + const responseItems = items.filter(i => isResponseVM(i)); + if (!focusedElement) { + return; + } + const currentlyFocusedIndex = responseItems?.indexOf(focusedElement); + if (!currentlyFocusedIndex || !responseItems) { + return; + } + if (currentlyFocusedIndex - 1 < 0) { + return; + } + this.focus(responseItems[currentlyFocusedIndex - 1], true); + } + private onDidChangeItems() { if (this.tree && this.visible) { const treeItems = (this.viewModel?.getItems() ?? []) @@ -387,7 +427,7 @@ export class ChatWidget extends Disposable implements IChatWidget { this.tree.reveal(item); } - focus(item: ChatTreeItem): void { + focus(item: ChatTreeItem, noDomFocus?: boolean): void { const items = this.tree.getNode(null).children; const node = items.find(i => i.element?.id === item.id); if (!node) { @@ -395,7 +435,9 @@ export class ChatWidget extends Disposable implements IChatWidget { } this.tree.setFocus([node.element]); + // if (!noDomFocus) { this.tree.domFocus(); + // } } async acceptInput(query?: string | IChatReplyFollowup): Promise { diff --git a/src/vs/workbench/contrib/codeEditor/browser/diffEditorHelper.ts b/src/vs/workbench/contrib/codeEditor/browser/diffEditorHelper.ts index 7f017f54f5c..c759bc6f8b5 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/diffEditorHelper.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/diffEditorHelper.ts @@ -17,7 +17,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { FloatingClickWidget } from 'vs/workbench/browser/codeeditor'; -import { AccessibilityHelpAction } from 'vs/workbench/contrib/accessibility/browser/accessibilityContribution'; +import { AccessibilityHelpAction, AccessibilityVerbositySettingId } from 'vs/workbench/contrib/accessibility/browser/accessibilityContribution'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { AccessibleViewType, IAccessibleViewService } from 'vs/workbench/contrib/accessibility/browser/accessibleView'; import { localize } from 'vs/nls'; @@ -101,7 +101,7 @@ function createScreenReaderHelp(): IDisposable { const keys = ['audioCues.diffLineDeleted', 'audioCues.diffLineInserted', 'audioCues.diffLineModified']; accessibleViewService.show({ - verbositySettingKey: 'diffEditor', + verbositySettingKey: AccessibilityVerbositySettingId.DiffEditor, provideContent: () => [ localize('msg1', "You are in a diff editor."), localize('msg2', "Press {0} or {1} to view the next or previous diff in the diff review mode that is optimized for screen readers.", next, previous), diff --git a/src/vs/workbench/contrib/notebook/browser/notebookAccessibilityHelp.ts b/src/vs/workbench/contrib/notebook/browser/notebookAccessibilityHelp.ts index 717b6167614..c5671a24877 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookAccessibilityHelp.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookAccessibilityHelp.ts @@ -9,6 +9,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { ServicesAccessor } from 'vs/editor/browser/editorExtensions'; import { AccessibleViewType, IAccessibleViewService } from 'vs/workbench/contrib/accessibility/browser/accessibleView'; +import { AccessibilityVerbositySettingId } from 'vs/workbench/contrib/accessibility/browser/accessibilityContribution'; export function getAccessibilityHelpText(accessor: ServicesAccessor): string { const keybindingService = accessor.get(IKeybindingService); @@ -46,7 +47,7 @@ export async function runAccessibilityHelpAction(accessor: ServicesAccessor, edi const accessibleViewService = accessor.get(IAccessibleViewService); const helpText = getAccessibilityHelpText(accessor); accessibleViewService.show({ - verbositySettingKey: 'notebook', + verbositySettingKey: AccessibilityVerbositySettingId.Notebook, provideContent: () => helpText, onClose: () => { editor.focus(); diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibilityHelp.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibilityHelp.ts index d5d73c308a1..a442d9933fa 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibilityHelp.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibilityHelp.ts @@ -10,6 +10,7 @@ import { IAccessibilityService } from 'vs/platform/accessibility/common/accessib import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { ShellIntegrationStatus, WindowsShellType } from 'vs/platform/terminal/common/terminal'; +import { AccessibilityVerbositySettingId } from 'vs/workbench/contrib/accessibility/browser/accessibilityContribution'; import { AccessibleViewType, IAccessibleContentProvider, IAccessibleViewOptions } from 'vs/workbench/contrib/accessibility/browser/accessibleView'; import { ITerminalInstance, IXtermTerminal } from 'vs/workbench/contrib/terminal/browser/terminal'; import { TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal'; @@ -34,7 +35,7 @@ export class TerminalAccessibleContentProvider extends Disposable implements IAc ariaLabel: localize('terminal-help-label', "terminal accessibility help"), readMoreUrl: 'https://code.visualstudio.com/docs/editor/accessibility#_terminal-accessibility' }; - verbositySettingKey: string = 'terminal'; + verbositySettingKey = AccessibilityVerbositySettingId.Terminal; constructor( private readonly _instance: Pick, From 85371faf398236fc00119d8eecc0c65fa9cff8e2 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 19 Jul 2023 13:19:20 -0700 Subject: [PATCH 03/14] use hint for notifications --- .../notifications/notificationsToasts.ts | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts b/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts index 62d27bfc8ec..aa936423b46 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts @@ -25,6 +25,8 @@ import { IHostService } from 'vs/workbench/services/host/browser/host'; import { IntervalCounter } from 'vs/base/common/async'; import { assertIsDefined } from 'vs/base/common/types'; import { NotificationsToastsVisibleContext } from 'vs/workbench/common/contextkeys'; +import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; interface INotificationToast { readonly item: INotificationViewItem; @@ -83,7 +85,9 @@ export class NotificationsToasts extends Themable implements INotificationsToast @IEditorGroupsService private readonly editorGroupService: IEditorGroupsService, @IContextKeyService private readonly contextKeyService: IContextKeyService, @ILifecycleService private readonly lifecycleService: ILifecycleService, - @IHostService private readonly hostService: IHostService + @IHostService private readonly hostService: IHostService, + @IKeybindingService private readonly _keybindingService: IKeybindingService, + @IConfigurationService private readonly _configurationService: IConfigurationService ) { super(themeService); @@ -187,11 +191,24 @@ export class NotificationsToasts extends Themable implements INotificationsToast const notificationList = this.instantiationService.createInstance(NotificationsList, notificationToast, { verticalScrollMode: ScrollbarVisibility.Hidden, widgetAriaLabel: (() => { - if (!item.source) { - return localize('notificationAriaLabel', "{0}, notification", item.message.raw); + let accessibleViewHint: string | undefined; + const keybinding = this._keybindingService.lookupKeybinding('editor.action.accessibleView')?.getAriaLabel(); + if (this._configurationService.getValue('accessibility.verbosity.notification')) { + accessibleViewHint = keybinding ? localize('chatAccessibleViewHint', "Inspect the response in the accessible view with {0}", keybinding) : localize('chatAccessibleViewHintNoKb', "Inspect the response in the accessible view via the command Open Accessible View which is currently not triggerable via keybinding"); } - return localize('notificationWithSourceAriaLabel', "{0}, source: {1}, notification", item.message.raw, item.source); + if (!item.source) { + if (accessibleViewHint) { + return localize('notificationAriaLabelViewHint', "{0}, notification {1}", item.message.raw, accessibleViewHint); + } else { + return localize('notificationAriaLabel', "{0}, notification", item.message.raw); + } + } + if (accessibleViewHint) { + return localize('notificationWithSourceAriaLabelViewHint', "{0}, source: {1}, notification {2}", item.message.raw, item.source, accessibleViewHint); + } else { + return localize('notificationWithSourceAriaLabel', "{0}, source: {1}, notification", item.message.raw, item.source); + } })() }); itemDisposables.add(notificationList); From 3ed9e5606d38eacd883b7912a3ff5cb56695242b Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 19 Jul 2023 14:13:58 -0700 Subject: [PATCH 04/14] clean up --- .../workbench/contrib/accessibility/browser/accessibleView.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts index df10b0f0cae..fad255a9efb 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts @@ -245,7 +245,7 @@ class AccessibleView extends Disposable { const nextKeybinding = this._keybindingService.lookupKeybinding(AccessibleViewNextAction.id)?.getAriaLabel(); const previousKeybinding = this._keybindingService.lookupKeybinding(AccessibleViewNextAction.id)?.getAriaLabel(); if (this._configurationService.getValue(verbositySettingKey)) { - hint = (nextKeybinding && previousKeybinding) ? localize('chatAccessibleViewNextPreviousHint', "Focus the next {0} or previous {1} item without leaving the accessible view", nextKeybinding, previousKeybinding) : localize('chatAccessibleViewNextPreviousHintNoKb', "Focus the next or previous item without leaving the accessible view by configuring keybindings for Show Next / Previous in Accessible View"); + hint = (nextKeybinding && previousKeybinding) ? localize('chatAccessibleViewNextPreviousHint', "Show the next {0} or previous {1} item in the accessible view", nextKeybinding, previousKeybinding) : localize('chatAccessibleViewNextPreviousHintNoKb', "Show the next or previous item in the accessible view by configuring keybindings for Show Next / Previous in Accessible View"); } return hint; } @@ -284,5 +284,3 @@ export class AccessibleViewService extends Disposable implements IAccessibleView return hint; } } - - From fc411d58f2ee059866622393587c5a730693dbb7 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 19 Jul 2023 14:19:47 -0700 Subject: [PATCH 05/14] clean up --- .../contrib/chat/browser/chat.contribution.ts | 4 +-- src/vs/workbench/contrib/chat/browser/chat.ts | 3 +- .../contrib/chat/browser/chatWidget.ts | 35 ++++--------------- 3 files changed, 10 insertions(+), 32 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/chat.contribution.ts b/src/vs/workbench/contrib/chat/browser/chat.contribution.ts index d27847fd437..e47a319b532 100644 --- a/src/vs/workbench/contrib/chat/browser/chat.contribution.ts +++ b/src/vs/workbench/contrib/chat/browser/chat.contribution.ts @@ -180,12 +180,12 @@ class ChatAccessibleViewContribution extends Disposable { }, next() { verifiedWidget.focus(focusedItem); - verifiedWidget.focusNext(focusedItem.id); + verifiedWidget.focusWithId(focusedItem.id, 'next'); renderAccessibleView(true, accessibleViewService, widgetService, codeEditorService); }, previous() { verifiedWidget.focus(focusedItem); - verifiedWidget.focusPrevious(focusedItem.id); + verifiedWidget.focusWithId(focusedItem.id, 'previous'); renderAccessibleView(true, accessibleViewService, widgetService, codeEditorService); }, options: { ariaLabel: nls.localize('chatAccessibleView', "Chat Accessible View"), language: 'typescript', type: AccessibleViewType.View } diff --git a/src/vs/workbench/contrib/chat/browser/chat.ts b/src/vs/workbench/contrib/chat/browser/chat.ts index b454aaf0795..3c0244ad52a 100644 --- a/src/vs/workbench/contrib/chat/browser/chat.ts +++ b/src/vs/workbench/contrib/chat/browser/chat.ts @@ -56,8 +56,7 @@ export interface IChatWidget { reveal(item: ChatTreeItem): void; focus(item: ChatTreeItem): void; - focusNext(id: string): void; - focusPrevious(id: string): void; + focusWithId(id: string, type: 'next' | 'previous'): void; getFocus(): ChatTreeItem | undefined; acceptInput(query?: string): void; focusLastMessage(): void; diff --git a/src/vs/workbench/contrib/chat/browser/chatWidget.ts b/src/vs/workbench/contrib/chat/browser/chatWidget.ts index 523a4974382..96f89464194 100644 --- a/src/vs/workbench/contrib/chat/browser/chatWidget.ts +++ b/src/vs/workbench/contrib/chat/browser/chatWidget.ts @@ -168,44 +168,25 @@ export class ChatWidget extends Disposable implements IChatWidget { this.inputPart.focus(); } - focusNext(id: string): void { + focusWithId(id: string, type: 'next' | 'previous'): void { const items = this.viewModel?.getItems(); if (!items) { return; } - const focusedElement = items?.find(i => i.id === id) as any as IChatResponseViewModel; - const responseItems = items?.filter(i => isResponseVM(i)); + const focusedElement = items.find(i => i.id === id); if (!focusedElement) { return; } + const responseItems = items.filter(i => isResponseVM(i)); const currentlyFocusedIndex = responseItems?.indexOf(focusedElement); if (currentlyFocusedIndex === undefined || !responseItems) { return; } - if (currentlyFocusedIndex === responseItems.length - 1) { + const indexToFocus = type === 'next' ? currentlyFocusedIndex + 1 : currentlyFocusedIndex - 1; + if (indexToFocus < 0 || indexToFocus === responseItems.length - 1) { return; } - this.focus(responseItems[currentlyFocusedIndex + 1], true); - } - - focusPrevious(id: string): void { - const items = this.viewModel?.getItems(); - if (!items) { - return; - } - const focusedElement = items.find(i => i.id === id) as any as IChatResponseViewModel; - const responseItems = items.filter(i => isResponseVM(i)); - if (!focusedElement) { - return; - } - const currentlyFocusedIndex = responseItems?.indexOf(focusedElement); - if (!currentlyFocusedIndex || !responseItems) { - return; - } - if (currentlyFocusedIndex - 1 < 0) { - return; - } - this.focus(responseItems[currentlyFocusedIndex - 1], true); + this.focus(responseItems[indexToFocus]); } private onDidChangeItems() { @@ -427,7 +408,7 @@ export class ChatWidget extends Disposable implements IChatWidget { this.tree.reveal(item); } - focus(item: ChatTreeItem, noDomFocus?: boolean): void { + focus(item: ChatTreeItem): void { const items = this.tree.getNode(null).children; const node = items.find(i => i.element?.id === item.id); if (!node) { @@ -435,9 +416,7 @@ export class ChatWidget extends Disposable implements IChatWidget { } this.tree.setFocus([node.element]); - // if (!noDomFocus) { this.tree.domFocus(); - // } } async acceptInput(query?: string | IChatReplyFollowup): Promise { From 8180c273023f470af14de86020b6cc9dfa60e098 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 19 Jul 2023 14:27:07 -0700 Subject: [PATCH 06/14] make it more concise --- .../contrib/chat/browser/chat.contribution.ts | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/chat.contribution.ts b/src/vs/workbench/contrib/chat/browser/chat.contribution.ts index e47a319b532..b57bb5ad970 100644 --- a/src/vs/workbench/contrib/chat/browser/chat.contribution.ts +++ b/src/vs/workbench/contrib/chat/browser/chat.contribution.ts @@ -135,15 +135,14 @@ class ChatAccessibleViewContribution extends Disposable { const accessibleViewService = accessor.get(IAccessibleViewService); const widgetService = accessor.get(IChatWidgetService); const codeEditorService = accessor.get(ICodeEditorService); - return renderAccessibleView(false, accessibleViewService, widgetService, codeEditorService); - function renderAccessibleView(ignoreChatInput: boolean, accessibleViewService: IAccessibleViewService, widgetService: IChatWidgetService, codeEditorService: ICodeEditorService): boolean { - + return renderAccessibleView(accessibleViewService, widgetService, codeEditorService, true); + function renderAccessibleView(accessibleViewService: IAccessibleViewService, widgetService: IChatWidgetService, codeEditorService: ICodeEditorService, initialRender?: boolean): boolean { let widget = widgetService.lastFocusedWidget; if (!widget) { return false; } - const chatInputFocused = !ignoreChatInput && !!(codeEditorService.getActiveCodeEditor() || codeEditorService.getFocusedCodeEditor()); + const chatInputFocused = initialRender && !!(codeEditorService.getActiveCodeEditor() || codeEditorService.getFocusedCodeEditor()); if (chatInputFocused) { widget.focusLastMessage(); @@ -179,14 +178,12 @@ class ChatAccessibleViewContribution extends Disposable { } }, next() { - verifiedWidget.focus(focusedItem); verifiedWidget.focusWithId(focusedItem.id, 'next'); - renderAccessibleView(true, accessibleViewService, widgetService, codeEditorService); + renderAccessibleView(accessibleViewService, widgetService, codeEditorService); }, previous() { - verifiedWidget.focus(focusedItem); verifiedWidget.focusWithId(focusedItem.id, 'previous'); - renderAccessibleView(true, accessibleViewService, widgetService, codeEditorService); + renderAccessibleView(accessibleViewService, widgetService, codeEditorService); }, options: { ariaLabel: nls.localize('chatAccessibleView', "Chat Accessible View"), language: 'typescript', type: AccessibleViewType.View } }); From 4707bf8e74241757e94e9248bd535b0e154165cb Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 19 Jul 2023 14:35:20 -0700 Subject: [PATCH 07/14] reveal --- src/vs/workbench/contrib/chat/browser/chat.contribution.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/contrib/chat/browser/chat.contribution.ts b/src/vs/workbench/contrib/chat/browser/chat.contribution.ts index b57bb5ad970..530a0e8dbd5 100644 --- a/src/vs/workbench/contrib/chat/browser/chat.contribution.ts +++ b/src/vs/workbench/contrib/chat/browser/chat.contribution.ts @@ -174,6 +174,7 @@ class ChatAccessibleViewContribution extends Disposable { if (chatInputFocused) { verifiedWidget.focusInput(); } else { + verifiedWidget.reveal(focusedItem); verifiedWidget.focus(focusedItem); } }, From 588116e1ae05f80b9ee9fd19a27d83685c2f10d3 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 19 Jul 2023 14:51:52 -0700 Subject: [PATCH 08/14] go with move focus --- src/vs/workbench/contrib/chat/browser/chat.contribution.ts | 4 ++-- src/vs/workbench/contrib/chat/browser/chat.ts | 2 +- src/vs/workbench/contrib/chat/browser/chatWidget.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/chat.contribution.ts b/src/vs/workbench/contrib/chat/browser/chat.contribution.ts index 530a0e8dbd5..a148099eef1 100644 --- a/src/vs/workbench/contrib/chat/browser/chat.contribution.ts +++ b/src/vs/workbench/contrib/chat/browser/chat.contribution.ts @@ -179,11 +179,11 @@ class ChatAccessibleViewContribution extends Disposable { } }, next() { - verifiedWidget.focusWithId(focusedItem.id, 'next'); + verifiedWidget.moveFocus(focusedItem.id, 'next'); renderAccessibleView(accessibleViewService, widgetService, codeEditorService); }, previous() { - verifiedWidget.focusWithId(focusedItem.id, 'previous'); + verifiedWidget.moveFocus(focusedItem.id, 'previous'); renderAccessibleView(accessibleViewService, widgetService, codeEditorService); }, options: { ariaLabel: nls.localize('chatAccessibleView', "Chat Accessible View"), language: 'typescript', type: AccessibleViewType.View } diff --git a/src/vs/workbench/contrib/chat/browser/chat.ts b/src/vs/workbench/contrib/chat/browser/chat.ts index 3c0244ad52a..33f5ab4a7d7 100644 --- a/src/vs/workbench/contrib/chat/browser/chat.ts +++ b/src/vs/workbench/contrib/chat/browser/chat.ts @@ -56,7 +56,7 @@ export interface IChatWidget { reveal(item: ChatTreeItem): void; focus(item: ChatTreeItem): void; - focusWithId(id: string, type: 'next' | 'previous'): void; + moveFocus(id: string, type: 'next' | 'previous'): void; getFocus(): ChatTreeItem | undefined; acceptInput(query?: string): void; focusLastMessage(): void; diff --git a/src/vs/workbench/contrib/chat/browser/chatWidget.ts b/src/vs/workbench/contrib/chat/browser/chatWidget.ts index 96f89464194..d9ca280db96 100644 --- a/src/vs/workbench/contrib/chat/browser/chatWidget.ts +++ b/src/vs/workbench/contrib/chat/browser/chatWidget.ts @@ -168,7 +168,7 @@ export class ChatWidget extends Disposable implements IChatWidget { this.inputPart.focus(); } - focusWithId(id: string, type: 'next' | 'previous'): void { + moveFocus(id: string, type: 'next' | 'previous'): void { const items = this.viewModel?.getItems(); if (!items) { return; From ef634eed103522fc44a9dd93387a4524f26d9208 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 19 Jul 2023 14:53:08 -0700 Subject: [PATCH 09/14] remove ? --- src/vs/workbench/contrib/chat/browser/chatWidget.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/chat/browser/chatWidget.ts b/src/vs/workbench/contrib/chat/browser/chatWidget.ts index d9ca280db96..fe399856767 100644 --- a/src/vs/workbench/contrib/chat/browser/chatWidget.ts +++ b/src/vs/workbench/contrib/chat/browser/chatWidget.ts @@ -178,7 +178,7 @@ export class ChatWidget extends Disposable implements IChatWidget { return; } const responseItems = items.filter(i => isResponseVM(i)); - const currentlyFocusedIndex = responseItems?.indexOf(focusedElement); + const currentlyFocusedIndex = responseItems.indexOf(focusedElement); if (currentlyFocusedIndex === undefined || !responseItems) { return; } From 4c9028c392fa1ed04a82ecc0c80f90b8203c9440 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 19 Jul 2023 14:55:51 -0700 Subject: [PATCH 10/14] trim before localizing --- src/vs/workbench/contrib/chat/browser/chatListRenderer.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts index ee93693be68..c9bf3480367 100644 --- a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts +++ b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts @@ -549,7 +549,7 @@ export class ChatAccessibilityProvider implements IListAccessibilityProvider token.type === 'code')?.length ?? 0; switch (codeBlockCount) { @@ -563,7 +563,6 @@ export class ChatAccessibilityProvider implements IListAccessibilityProvider Date: Wed, 19 Jul 2023 14:59:17 -0700 Subject: [PATCH 11/14] rename --- src/vs/workbench/contrib/chat/browser/chatWidget.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/chatWidget.ts b/src/vs/workbench/contrib/chat/browser/chatWidget.ts index fe399856767..a00a5d7507f 100644 --- a/src/vs/workbench/contrib/chat/browser/chatWidget.ts +++ b/src/vs/workbench/contrib/chat/browser/chatWidget.ts @@ -173,16 +173,16 @@ export class ChatWidget extends Disposable implements IChatWidget { if (!items) { return; } - const focusedElement = items.find(i => i.id === id); - if (!focusedElement) { + const targetElement = items.find(i => i.id === id); + if (!targetElement) { return; } const responseItems = items.filter(i => isResponseVM(i)); - const currentlyFocusedIndex = responseItems.indexOf(focusedElement); - if (currentlyFocusedIndex === undefined || !responseItems) { + const targetIndex = responseItems.indexOf(targetElement); + if (targetIndex === undefined || !responseItems) { return; } - const indexToFocus = type === 'next' ? currentlyFocusedIndex + 1 : currentlyFocusedIndex - 1; + const indexToFocus = type === 'next' ? targetIndex + 1 : targetIndex - 1; if (indexToFocus < 0 || indexToFocus === responseItems.length - 1) { return; } From d967ccfce4e4a9b9dad335e94e04960f46f03ddb Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 19 Jul 2023 15:06:00 -0700 Subject: [PATCH 12/14] pass in item --- src/vs/workbench/contrib/chat/browser/chat.contribution.ts | 4 ++-- src/vs/workbench/contrib/chat/browser/chat.ts | 2 +- src/vs/workbench/contrib/chat/browser/chatWidget.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/chat.contribution.ts b/src/vs/workbench/contrib/chat/browser/chat.contribution.ts index a148099eef1..a9742eba96f 100644 --- a/src/vs/workbench/contrib/chat/browser/chat.contribution.ts +++ b/src/vs/workbench/contrib/chat/browser/chat.contribution.ts @@ -179,11 +179,11 @@ class ChatAccessibleViewContribution extends Disposable { } }, next() { - verifiedWidget.moveFocus(focusedItem.id, 'next'); + verifiedWidget.moveFocus(focusedItem, 'next'); renderAccessibleView(accessibleViewService, widgetService, codeEditorService); }, previous() { - verifiedWidget.moveFocus(focusedItem.id, 'previous'); + verifiedWidget.moveFocus(focusedItem, 'previous'); renderAccessibleView(accessibleViewService, widgetService, codeEditorService); }, options: { ariaLabel: nls.localize('chatAccessibleView', "Chat Accessible View"), language: 'typescript', type: AccessibleViewType.View } diff --git a/src/vs/workbench/contrib/chat/browser/chat.ts b/src/vs/workbench/contrib/chat/browser/chat.ts index 33f5ab4a7d7..a2ad6867efa 100644 --- a/src/vs/workbench/contrib/chat/browser/chat.ts +++ b/src/vs/workbench/contrib/chat/browser/chat.ts @@ -56,7 +56,7 @@ export interface IChatWidget { reveal(item: ChatTreeItem): void; focus(item: ChatTreeItem): void; - moveFocus(id: string, type: 'next' | 'previous'): void; + moveFocus(item: ChatTreeItem, type: 'next' | 'previous'): void; getFocus(): ChatTreeItem | undefined; acceptInput(query?: string): void; focusLastMessage(): void; diff --git a/src/vs/workbench/contrib/chat/browser/chatWidget.ts b/src/vs/workbench/contrib/chat/browser/chatWidget.ts index a00a5d7507f..a38a4059343 100644 --- a/src/vs/workbench/contrib/chat/browser/chatWidget.ts +++ b/src/vs/workbench/contrib/chat/browser/chatWidget.ts @@ -168,12 +168,12 @@ export class ChatWidget extends Disposable implements IChatWidget { this.inputPart.focus(); } - moveFocus(id: string, type: 'next' | 'previous'): void { + moveFocus(item: ChatTreeItem, type: 'next' | 'previous'): void { const items = this.viewModel?.getItems(); if (!items) { return; } - const targetElement = items.find(i => i.id === id); + const targetElement = items.find(i => i.id === item.id); if (!targetElement) { return; } From 499266dee9b99d3772ee69fce9b323583515b33d Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 19 Jul 2023 15:07:02 -0700 Subject: [PATCH 13/14] don't mess w id --- src/vs/workbench/contrib/chat/browser/chatWidget.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/chatWidget.ts b/src/vs/workbench/contrib/chat/browser/chatWidget.ts index a38a4059343..2f3957a4c28 100644 --- a/src/vs/workbench/contrib/chat/browser/chatWidget.ts +++ b/src/vs/workbench/contrib/chat/browser/chatWidget.ts @@ -173,12 +173,8 @@ export class ChatWidget extends Disposable implements IChatWidget { if (!items) { return; } - const targetElement = items.find(i => i.id === item.id); - if (!targetElement) { - return; - } const responseItems = items.filter(i => isResponseVM(i)); - const targetIndex = responseItems.indexOf(targetElement); + const targetIndex = responseItems.indexOf(item); if (targetIndex === undefined || !responseItems) { return; } From 45908d8979af59fbf4e1ba643e1cab850ffbfb8b Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 19 Jul 2023 15:07:29 -0700 Subject: [PATCH 14/14] rm check --- src/vs/workbench/contrib/chat/browser/chatWidget.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/chat/browser/chatWidget.ts b/src/vs/workbench/contrib/chat/browser/chatWidget.ts index 2f3957a4c28..6a7768c2aa1 100644 --- a/src/vs/workbench/contrib/chat/browser/chatWidget.ts +++ b/src/vs/workbench/contrib/chat/browser/chatWidget.ts @@ -175,7 +175,7 @@ export class ChatWidget extends Disposable implements IChatWidget { } const responseItems = items.filter(i => isResponseVM(i)); const targetIndex = responseItems.indexOf(item); - if (targetIndex === undefined || !responseItems) { + if (targetIndex === undefined) { return; } const indexToFocus = type === 'next' ? targetIndex + 1 : targetIndex - 1;