Skip to content

Commit 9434e79

Browse files
committed
1 parent a9c39b8 commit 9434e79

File tree

4 files changed

+64
-3
lines changed

4 files changed

+64
-3
lines changed

src/vs/workbench/contrib/inlineChat/browser/inlineChat.contribution.ts

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,20 @@ import { registerAction2 } from 'vs/platform/actions/common/actions';
77
import { EditorContributionInstantiation, registerEditorContribution } from 'vs/editor/browser/editorExtensions';
88
import { InlineChatController } from 'vs/workbench/contrib/inlineChat/browser/inlineChatController';
99
import * as InlineChatActions from 'vs/workbench/contrib/inlineChat/browser/inlineChatActions';
10-
import { IInlineChatService, INLINE_CHAT_ID, INTERACTIVE_EDITOR_ACCESSIBILITY_HELP_ID } from 'vs/workbench/contrib/inlineChat/common/inlineChat';
10+
import { CTX_INLINE_CHAT_FOCUSED, CTX_INLINE_CHAT_MESSAGE_FOCUSED, IInlineChatService, INLINE_CHAT_ID, INTERACTIVE_EDITOR_ACCESSIBILITY_HELP_ID } from 'vs/workbench/contrib/inlineChat/common/inlineChat';
1111
import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
1212
import { InlineChatServiceImpl } from 'vs/workbench/contrib/inlineChat/common/inlineChatServiceImpl';
1313
import { IInlineChatSessionService, InlineChatSessionService } from 'vs/workbench/contrib/inlineChat/browser/inlineChatSession';
1414
import { Registry } from 'vs/platform/registry/common/platform';
15-
import { IWorkbenchContributionsRegistry, Extensions } from 'vs/workbench/common/contributions';
1615
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
1716
import { InlineChatNotebookContribution } from 'vs/workbench/contrib/inlineChat/browser/inlineChatNotebook';
17+
import { AccessibilityVerbositySettingId, AccessibleViewAction } from 'vs/workbench/contrib/accessibility/browser/accessibilityContribution';
18+
import { AccessibleViewType, IAccessibleViewService } from 'vs/workbench/contrib/accessibility/browser/accessibleView';
19+
import { Disposable } from 'vs/base/common/lifecycle';
20+
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
21+
import { localize } from 'vs/nls';
22+
import { Extensions, IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
23+
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
1824

1925
registerSingleton(IInlineChatService, InlineChatServiceImpl, InstantiationType.Delayed);
2026
registerSingleton(IInlineChatSessionService, InlineChatSessionService, InstantiationType.Delayed);
@@ -51,3 +57,44 @@ registerAction2(InlineChatActions.CopyRecordings);
5157

5258
Registry.as<IWorkbenchContributionsRegistry>(Extensions.Workbench)
5359
.registerWorkbenchContribution(InlineChatNotebookContribution, LifecyclePhase.Restored);
60+
61+
62+
class InlineChatAccessibleViewContribution extends Disposable {
63+
static ID: 'chatAccessibleViewContribution';
64+
constructor() {
65+
super();
66+
this._register(AccessibleViewAction.addImplementation(100, 'inlineChat', accessor => {
67+
const accessibleViewService = accessor.get(IAccessibleViewService);
68+
const codeEditorService = accessor.get(ICodeEditorService);
69+
70+
const editor = (codeEditorService.getActiveCodeEditor() || codeEditorService.getFocusedCodeEditor());
71+
if (!editor) {
72+
return false;
73+
}
74+
const controller = InlineChatController.get(editor);
75+
if (!controller) {
76+
return false;
77+
}
78+
const inputFocused = editor.hasWidgetFocus();
79+
const responseContent = controller?.getMessage();
80+
if (!responseContent) {
81+
return false;
82+
}
83+
accessibleViewService.show({
84+
verbositySettingKey: AccessibilityVerbositySettingId.InlineChat,
85+
provideContent(): string { return responseContent; },
86+
onClose() {
87+
if (inputFocused) {
88+
controller.focus();
89+
}
90+
},
91+
92+
options: { ariaLabel: localize('inlineChatAccessibleView', "Inline Chat Accessible View"), type: AccessibleViewType.View }
93+
});
94+
return true;
95+
}, ContextKeyExpr.or(CTX_INLINE_CHAT_FOCUSED, CTX_INLINE_CHAT_MESSAGE_FOCUSED)));
96+
}
97+
}
98+
99+
const workbenchContributionsRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
100+
workbenchContributionsRegistry.registerWorkbenchContribution(InlineChatAccessibleViewContribution, LifecyclePhase.Eventually);

src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,10 @@ export class InlineChatController implements IEditorContribution {
158158
}
159159
}
160160

161+
getMessage(): string | undefined {
162+
return this._zone.value.widget.message;
163+
}
164+
161165
getId(): string {
162166
return INLINE_CHAT_ID;
163167
}

src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { localize } from 'vs/nls';
1212
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
1313
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
1414
import { ZoneWidget } from 'vs/editor/contrib/zoneWidget/browser/zoneWidget';
15-
import { CTX_INLINE_CHAT_FOCUSED, CTX_INLINE_CHAT_EMPTY, CTX_INLINE_CHAT_OUTER_CURSOR_POSITION, CTX_INLINE_CHAT_VISIBLE, MENU_INLINE_CHAT_WIDGET, MENU_INLINE_CHAT_WIDGET_STATUS, MENU_INLINE_CHAT_WIDGET_MARKDOWN_MESSAGE, CTX_INLINE_CHAT_MESSAGE_CROP_STATE, IInlineChatSlashCommand, MENU_INLINE_CHAT_WIDGET_FEEDBACK, ACTION_REGENERATE_RESPONSE, ACTION_VIEW_IN_CHAT, MENU_INLINE_CHAT_WIDGET_TOGGLE, CTX_INLINE_CHAT_INNER_CURSOR_FIRST, CTX_INLINE_CHAT_INNER_CURSOR_LAST, CTX_INLINE_CHAT_INNER_CURSOR_START, CTX_INLINE_CHAT_INNER_CURSOR_END } from 'vs/workbench/contrib/inlineChat/common/inlineChat';
15+
import { CTX_INLINE_CHAT_FOCUSED, CTX_INLINE_CHAT_EMPTY, CTX_INLINE_CHAT_OUTER_CURSOR_POSITION, CTX_INLINE_CHAT_VISIBLE, MENU_INLINE_CHAT_WIDGET, MENU_INLINE_CHAT_WIDGET_STATUS, MENU_INLINE_CHAT_WIDGET_MARKDOWN_MESSAGE, CTX_INLINE_CHAT_MESSAGE_CROP_STATE, IInlineChatSlashCommand, MENU_INLINE_CHAT_WIDGET_FEEDBACK, ACTION_REGENERATE_RESPONSE, ACTION_VIEW_IN_CHAT, MENU_INLINE_CHAT_WIDGET_TOGGLE, CTX_INLINE_CHAT_INNER_CURSOR_FIRST, CTX_INLINE_CHAT_INNER_CURSOR_LAST, CTX_INLINE_CHAT_INNER_CURSOR_START, CTX_INLINE_CHAT_INNER_CURSOR_END, CTX_INLINE_CHAT_MESSAGE_FOCUSED } from 'vs/workbench/contrib/inlineChat/common/inlineChat';
1616
import { IModelDeltaDecoration, ITextModel } from 'vs/editor/common/model';
1717
import { EventType, Dimension, addDisposableListener, getActiveElement, getTotalHeight, getTotalWidth, h, reset } from 'vs/base/browser/dom';
1818
import { Emitter, Event, MicrotaskEmitter } from 'vs/base/common/event';
@@ -163,6 +163,7 @@ export class InlineChatWidget {
163163
private readonly _ctxInnerCursorStart: IContextKey<boolean>;
164164
private readonly _ctxInnerCursorEnd: IContextKey<boolean>;
165165
private readonly _ctxInputEditorFocused: IContextKey<boolean>;
166+
private readonly _ctxMessageFocused: IContextKey<boolean>;
166167

167168
private readonly _progressBar: ProgressBar;
168169

@@ -215,6 +216,9 @@ export class InlineChatWidget {
215216
this._store.add(this._inputEditor.onDidChangeModelContent(() => this._onDidChangeInput.fire(this)));
216217
this._store.add(this._inputEditor.onDidLayoutChange(() => this._onDidChangeHeight.fire()));
217218
this._store.add(this._inputEditor.onDidContentSizeChange(() => this._onDidChangeHeight.fire()));
219+
this._store.add(addDisposableListener(this._elements.message, 'focus', () => this._ctxMessageFocused.set(true)));
220+
this._store.add(addDisposableListener(this._elements.message, 'blur', () => this._ctxMessageFocused.reset()));
221+
218222
this._store.add(this._configurationService.onDidChangeConfiguration(e => {
219223
if (e.affectsConfiguration(AccessibilityVerbositySettingId.InlineChat)) {
220224
this._updateAriaLabel();
@@ -235,6 +239,7 @@ export class InlineChatWidget {
235239
this._ctxInnerCursorStart = CTX_INLINE_CHAT_INNER_CURSOR_START.bindTo(this._contextKeyService);
236240
this._ctxInnerCursorEnd = CTX_INLINE_CHAT_INNER_CURSOR_END.bindTo(this._contextKeyService);
237241
this._ctxInputEditorFocused = CTX_INLINE_CHAT_FOCUSED.bindTo(this._contextKeyService);
242+
this._ctxMessageFocused = CTX_INLINE_CHAT_MESSAGE_FOCUSED.bindTo(this._contextKeyService);
238243

239244
// (1) inner cursor position (last/first line selected)
240245
const updateInnerCursorFirstLast = () => {
@@ -489,6 +494,10 @@ export class InlineChatWidget {
489494
this._preferredExpansionState = expansionState;
490495
}
491496

497+
get message(): string | undefined {
498+
return this._elements.markdownMessage.textContent ?? undefined;
499+
}
500+
492501
updateMarkdownMessage(message: Node | undefined) {
493502
this._elements.markdownMessage.classList.toggle('hidden', !message);
494503
let expansionState: ExpansionState;

src/vs/workbench/contrib/inlineChat/common/inlineChat.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ export const INTERACTIVE_EDITOR_ACCESSIBILITY_HELP_ID = 'interactiveEditorAccess
121121
export const CTX_INLINE_CHAT_HAS_PROVIDER = new RawContextKey<boolean>('inlineChatHasProvider', false, localize('inlineChatHasProvider', "Whether a provider for interactive editors exists"));
122122
export const CTX_INLINE_CHAT_VISIBLE = new RawContextKey<boolean>('inlineChatVisible', false, localize('inlineChatVisible', "Whether the interactive editor input is visible"));
123123
export const CTX_INLINE_CHAT_FOCUSED = new RawContextKey<boolean>('inlineChatFocused', false, localize('inlineChatFocused', "Whether the interactive editor input is focused"));
124+
export const CTX_INLINE_CHAT_MESSAGE_FOCUSED = new RawContextKey<boolean>('inlineChatMessageFocused', false, localize('inlineChatMessageFocused', "Whether the interactive widget's message is focused"));
124125
export const CTX_INLINE_CHAT_EMPTY = new RawContextKey<boolean>('inlineChatEmpty', false, localize('inlineChatEmpty', "Whether the interactive editor input is empty"));
125126
export const CTX_INLINE_CHAT_INNER_CURSOR_FIRST = new RawContextKey<boolean>('inlineChatInnerCursorFirst', false, localize('inlineChatInnerCursorFirst', "Whether the cursor of the iteractive editor input is on the first line"));
126127
export const CTX_INLINE_CHAT_INNER_CURSOR_LAST = new RawContextKey<boolean>('inlineChatInnerCursorLast', false, localize('inlineChatInnerCursorLast', "Whether the cursor of the iteractive editor input is on the last line"));

0 commit comments

Comments
 (0)