diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts b/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts index 781bd9bc98f29..a2ea11ab46368 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts @@ -13,7 +13,8 @@ import { ServicesAccessor } from 'vs/editor/browser/editorExtensions'; import { KeyCode } from 'vs/base/common/keyCodes'; import { IChatWidgetService } from 'vs/workbench/contrib/chat/browser/chat'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { EditMode } from 'vs/workbench/contrib/interactiveEditor/common/interactiveEditor'; +import { CTX_INTERACTIVE_EDITOR_ACCESSIBILTY_HELP_VISIBLE, EditMode } from 'vs/workbench/contrib/interactiveEditor/common/interactiveEditor'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; export function getAccessibilityHelpText(accessor: ServicesAccessor, type: 'chat' | 'editor', currentInput?: string): string { const keybindingService = accessor.get(IKeybindingService); @@ -24,11 +25,11 @@ export function getAccessibilityHelpText(accessor: ServicesAccessor, type: 'chat content.push(descriptionForCommand('chat.action.focus', localize('workbench.action.chat.focus', 'The Focus Chat command ({0}) focuses the chat request/response list, which can be navigated with UpArrow/DownArrow.',), localize('workbench.action.chat.focusNoKb', 'The Focus Chat List command focuses the chat request/response list, which can be navigated with UpArrow/DownArrow and is currently not triggerable by a keybinding.'), keybindingService)); content.push(descriptionForCommand('workbench.action.chat.focusInput', localize('workbench.action.chat.focusInput', 'The Focus Chat Input command ({0}) focuses the input box for chat requests.'), localize('workbench.action.interactiveSession.focusInputNoKb', 'Focus Chat Input command focuses the input box for chat requests and is currently not triggerable by a keybinding.'), keybindingService)); } else { - content.push(localize('interactiveSession.makeRequest', "Tab once to reach the make request button, which will re-run the request.")); const regex = /^(\/fix|\/explain)/; const match = currentInput?.match(regex); const command = match && match.length ? match[0].substring(1) : undefined; if (command === 'fix') { + content.push(localize('interactiveSession.makeRequest', "Tab once to reach the make request button, which will re-run the request.")); const editMode = configurationService.getValue('interactiveEditor.editMode'); if (editMode === EditMode.Preview) { const keybinding = keybindingService.lookupKeybinding('editor.action.diffReview.next')?.getAriaLabel(); @@ -36,11 +37,11 @@ export function getAccessibilityHelpText(accessor: ServicesAccessor, type: 'chat content.push(localize('interactiveSession.acceptReject', "Tab again to reach the action bar, which can be navigated with Left/RightArrow.")); } } else if (command === 'explain') { + content.push(localize('interactiveSession.makeRequest', "Tab once to reach the make request button, which will re-run the request.")); content.push(localize('interactiveSession.explain', "/explain commands will be run in the chat view.")); content.push(localize('interactiveSession.chatViewFocus', "To focus the chat view, run the GitHub Copilot: Focus on GitHub Copilot View command, which will focus the input box.")); } else { - content.push(localize('interactiveSession.toolbar', "Tab again to reach the action bar, if any, which can be navigated with Left/RightArrow.")); - content.push(localize('interactiveSession.toolbarButtons', "Tab again to focus the response.")); + content.push(localize('interactiveSession.toolbar', "Use tab to reach conditional parts like commands, status message, message responses and more")); } } return content.join('\n'); @@ -56,6 +57,8 @@ function descriptionForCommand(commandId: string, msg: string, noKbMsg: string, export async function runAccessibilityHelpAction(accessor: ServicesAccessor, editor: ICodeEditor, type: 'chat' | 'editor'): Promise { const widgetService = accessor.get(IChatWidgetService); + const contextKeyService = accessor.get(IContextKeyService); + const contextKey = type === 'editor' ? CTX_INTERACTIVE_EDITOR_ACCESSIBILTY_HELP_VISIBLE.bindTo(contextKeyService) : undefined; const inputEditor: ICodeEditor | undefined = type === 'chat' ? widgetService.lastFocusedWidget?.inputEditor : editor; const editorUri = editor.getModel()?.uri; @@ -69,8 +72,8 @@ export async function runAccessibilityHelpAction(accessor: ServicesAccessor, edi const cachedInput = inputEditor.getValue(); const cachedPosition = inputEditor.getPosition(); - inputEditor.getSupportedActions(); const helpText = getAccessibilityHelpText(accessor, type, type === 'editor' ? cachedInput : undefined); + contextKey?.set(true); inputEditor.setValue(helpText); inputEditor.updateOptions({ readOnly: true }); inputEditor.focus(); @@ -79,6 +82,7 @@ export async function runAccessibilityHelpAction(accessor: ServicesAccessor, edi return; } if (e.keyCode === KeyCode.Escape && inputEditor.getValue() === helpText) { + contextKey?.reset(); inputEditor.updateOptions({ readOnly: false }); inputEditor.setValue(cachedInput); if (cachedPosition) { diff --git a/src/vs/workbench/contrib/interactiveEditor/browser/interactiveEditorActions.ts b/src/vs/workbench/contrib/interactiveEditor/browser/interactiveEditorActions.ts index c997ada83b06e..f03fc347d3f7b 100644 --- a/src/vs/workbench/contrib/interactiveEditor/browser/interactiveEditorActions.ts +++ b/src/vs/workbench/contrib/interactiveEditor/browser/interactiveEditorActions.ts @@ -10,7 +10,7 @@ import { EditorAction2 } from 'vs/editor/browser/editorExtensions'; import { EmbeddedCodeEditorWidget, EmbeddedDiffEditorWidget } from 'vs/editor/browser/widget/embeddedCodeEditorWidget'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { InteractiveEditorController, InteractiveEditorRunOptions } from 'vs/workbench/contrib/interactiveEditor/browser/interactiveEditorController'; -import { CTX_INTERACTIVE_EDITOR_FOCUSED, CTX_INTERACTIVE_EDITOR_HAS_ACTIVE_REQUEST, CTX_INTERACTIVE_EDITOR_HAS_PROVIDER, CTX_INTERACTIVE_EDITOR_INNER_CURSOR_FIRST, CTX_INTERACTIVE_EDITOR_INNER_CURSOR_LAST, CTX_INTERACTIVE_EDITOR_EMPTY, CTX_INTERACTIVE_EDITOR_OUTER_CURSOR_POSITION, CTX_INTERACTIVE_EDITOR_VISIBLE, MENU_INTERACTIVE_EDITOR_WIDGET, MENU_INTERACTIVE_EDITOR_WIDGET_DISCARD, MENU_INTERACTIVE_EDITOR_WIDGET_STATUS, CTX_INTERACTIVE_EDITOR_LAST_FEEDBACK, CTX_INTERACTIVE_EDITOR_SHOWING_DIFF, CTX_INTERACTIVE_EDITOR_EDIT_MODE, EditMode, CTX_INTERACTIVE_EDITOR_LAST_RESPONSE_TYPE, MENU_INTERACTIVE_EDITOR_WIDGET_MARKDOWN_MESSAGE, CTX_INTERACTIVE_EDITOR_MESSAGE_CROP_STATE, CTX_INTERACTIVE_EDITOR_DOCUMENT_CHANGED, CTX_INTERACTIVE_EDITOR_DID_EDIT, CTX_INTERACTIVE_EDITOR_HAS_STASHED_SESSION, MENU_INTERACTIVE_EDITOR_WIDGET_FEEDBACK, ACTION_ACCEPT_CHANGES } from 'vs/workbench/contrib/interactiveEditor/common/interactiveEditor'; +import { CTX_INTERACTIVE_EDITOR_FOCUSED, CTX_INTERACTIVE_EDITOR_HAS_ACTIVE_REQUEST, CTX_INTERACTIVE_EDITOR_HAS_PROVIDER, CTX_INTERACTIVE_EDITOR_INNER_CURSOR_FIRST, CTX_INTERACTIVE_EDITOR_INNER_CURSOR_LAST, CTX_INTERACTIVE_EDITOR_EMPTY, CTX_INTERACTIVE_EDITOR_OUTER_CURSOR_POSITION, CTX_INTERACTIVE_EDITOR_VISIBLE, MENU_INTERACTIVE_EDITOR_WIDGET, MENU_INTERACTIVE_EDITOR_WIDGET_DISCARD, MENU_INTERACTIVE_EDITOR_WIDGET_STATUS, CTX_INTERACTIVE_EDITOR_LAST_FEEDBACK, CTX_INTERACTIVE_EDITOR_SHOWING_DIFF, CTX_INTERACTIVE_EDITOR_EDIT_MODE, EditMode, CTX_INTERACTIVE_EDITOR_LAST_RESPONSE_TYPE, MENU_INTERACTIVE_EDITOR_WIDGET_MARKDOWN_MESSAGE, CTX_INTERACTIVE_EDITOR_MESSAGE_CROP_STATE, CTX_INTERACTIVE_EDITOR_DOCUMENT_CHANGED, CTX_INTERACTIVE_EDITOR_DID_EDIT, CTX_INTERACTIVE_EDITOR_HAS_STASHED_SESSION, MENU_INTERACTIVE_EDITOR_WIDGET_FEEDBACK, ACTION_ACCEPT_CHANGES, CTX_INTERACTIVE_EDITOR_ACCESSIBILTY_HELP_VISIBLE } from 'vs/workbench/contrib/interactiveEditor/common/interactiveEditor'; import { localize } from 'vs/nls'; import { IAction2Options, MenuRegistry } from 'vs/platform/actions/common/actions'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; @@ -135,7 +135,7 @@ export class MakeRequestAction extends AbstractInteractiveEditorAction { id: 'interactiveEditor.accept', title: localize('accept', 'Make Request'), icon: Codicon.send, - precondition: ContextKeyExpr.and(CTX_INTERACTIVE_EDITOR_VISIBLE, CTX_INTERACTIVE_EDITOR_EMPTY.negate()), + precondition: ContextKeyExpr.and(CTX_INTERACTIVE_EDITOR_VISIBLE, CTX_INTERACTIVE_EDITOR_ACCESSIBILTY_HELP_VISIBLE.negate(), CTX_INTERACTIVE_EDITOR_EMPTY.negate()), keybinding: { when: CTX_INTERACTIVE_EDITOR_FOCUSED, weight: KeybindingWeight.EditorCore + 7, diff --git a/src/vs/workbench/contrib/interactiveEditor/browser/interactiveEditorController.ts b/src/vs/workbench/contrib/interactiveEditor/browser/interactiveEditorController.ts index bf06a174e86f4..c5b233513b716 100644 --- a/src/vs/workbench/contrib/interactiveEditor/browser/interactiveEditorController.ts +++ b/src/vs/workbench/contrib/interactiveEditor/browser/interactiveEditorController.ts @@ -110,14 +110,14 @@ export class InteractiveEditorController implements IEditorContribution { @IModelService private readonly _modelService: IModelService, @INotebookEditorService private readonly _notebookEditorService: INotebookEditorService, @IDialogService private readonly _dialogService: IDialogService, - @IContextKeyService contextKeyService: IContextKeyService, + @IContextKeyService private readonly _contextKeyService: IContextKeyService, @IAccessibilityService private readonly _accessibilityService: IAccessibilityService, @IKeybindingService private readonly _keybindingService: IKeybindingService, ) { - this._ctxHasActiveRequest = CTX_INTERACTIVE_EDITOR_HAS_ACTIVE_REQUEST.bindTo(contextKeyService); - this._ctxDidEdit = CTX_INTERACTIVE_EDITOR_DID_EDIT.bindTo(contextKeyService); - this._ctxLastResponseType = CTX_INTERACTIVE_EDITOR_LAST_RESPONSE_TYPE.bindTo(contextKeyService); - this._ctxLastFeedbackKind = CTX_INTERACTIVE_EDITOR_LAST_FEEDBACK.bindTo(contextKeyService); + this._ctxHasActiveRequest = CTX_INTERACTIVE_EDITOR_HAS_ACTIVE_REQUEST.bindTo(_contextKeyService); + this._ctxDidEdit = CTX_INTERACTIVE_EDITOR_DID_EDIT.bindTo(_contextKeyService); + this._ctxLastResponseType = CTX_INTERACTIVE_EDITOR_LAST_RESPONSE_TYPE.bindTo(_contextKeyService); + this._ctxLastFeedbackKind = CTX_INTERACTIVE_EDITOR_LAST_FEEDBACK.bindTo(_contextKeyService); this._zone = this._store.add(_instaService.createInstance(InteractiveEditorZoneWidget, this._editor)); this._store.add(this._editor.onDidChangeModel(async e => { @@ -438,7 +438,9 @@ export class InteractiveEditorController implements IEditorContribution { }); const typeListener = this._zone.widget.onDidChangeInput(() => { - requestCts.cancel(); + if (this._contextKeyService.getContextKeyValue('interactiveEditorAccessibilityHelpVisible') === false) { + requestCts.cancel(); + } }); const sw = StopWatch.create(); diff --git a/src/vs/workbench/contrib/interactiveEditor/common/interactiveEditor.ts b/src/vs/workbench/contrib/interactiveEditor/common/interactiveEditor.ts index e43266f00c66e..a5ca781c51d3e 100644 --- a/src/vs/workbench/contrib/interactiveEditor/common/interactiveEditor.ts +++ b/src/vs/workbench/contrib/interactiveEditor/common/interactiveEditor.ts @@ -109,6 +109,7 @@ export const CTX_INTERACTIVE_EDITOR_INNER_CURSOR_LAST = new RawContextKey('interactiveEditorMarkdownMessageCropState', 'not_cropped', localize('interactiveEditorMarkdownMessageCropState', "Whether the interactive editor message is cropped, not cropped or expanded")); export const CTX_INTERACTIVE_EDITOR_OUTER_CURSOR_POSITION = new RawContextKey<'above' | 'below' | ''>('interactiveEditorOuterCursorPosition', '', localize('interactiveEditorOuterCursorPosition', "Whether the cursor of the outer editor is above or below the interactive editor input")); export const CTX_INTERACTIVE_EDITOR_HAS_ACTIVE_REQUEST = new RawContextKey('interactiveEditorHasActiveRequest', false, localize('interactiveEditorHasActiveRequest', "Whether interactive editor has an active request")); +export const CTX_INTERACTIVE_EDITOR_ACCESSIBILTY_HELP_VISIBLE = new RawContextKey('interactiveEditorAccessibilityHelpVisible', false, localize('interactiveEditorAccessibilityHelpVisible', "Whether the interactive editor accessibility help menu is visible")); export const CTX_INTERACTIVE_EDITOR_HAS_STASHED_SESSION = new RawContextKey('interactiveEditorHasStashedSession', false, localize('interactiveEditorHasStashedSession', "Whether interactive editor has kept a session for quick restore")); export const CTX_INTERACTIVE_EDITOR_SHOWING_DIFF = new RawContextKey('interactiveEditorDiff', false, localize('interactiveEditorDiff', "Whether interactive editor show diffs for changes")); export const CTX_INTERACTIVE_EDITOR_LAST_RESPONSE_TYPE = new RawContextKey('interactiveEditorLastResponseType', undefined, localize('interactiveEditorResponseType', "What type was the last response of the current interactive editor session"));