diff --git a/build/lib/stylelint/vscode-known-variables.json b/build/lib/stylelint/vscode-known-variables.json index c66764a9761..a4b270551ff 100644 --- a/build/lib/stylelint/vscode-known-variables.json +++ b/build/lib/stylelint/vscode-known-variables.json @@ -825,6 +825,7 @@ "--dropdown-padding-bottom", "--dropdown-padding-top", "--inline-chat-frame-progress", + "--inline-chat-hint-progress", "--insert-border-color", "--last-tab-margin-right", "--monaco-monospace-font", diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatCurrentLine.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatCurrentLine.ts index 78a792955d1..c7317928ad2 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatCurrentLine.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatCurrentLine.ts @@ -27,6 +27,7 @@ import './media/inlineChat.css'; import { IKeybindingService } from '../../../../platform/keybinding/common/keybinding.js'; import { ICommandService } from '../../../../platform/commands/common/commands.js'; import { InlineCompletionsController } from '../../../../editor/contrib/inlineCompletions/browser/controller/inlineCompletionsController.js'; +import { ChatAgentLocation, IChatAgentService } from '../../chat/common/chatAgents.js'; export const CTX_INLINE_CHAT_SHOWING_HINT = new RawContextKey('inlineChatShowingHint', false, localize('inlineChatShowingHint', "Whether inline chat shows a contextual hint")); @@ -154,6 +155,7 @@ export class InlineChatHintsController extends Disposable implements IEditorCont @IContextKeyService contextKeyService: IContextKeyService, @ICommandService commandService: ICommandService, @IKeybindingService keybindingService: IKeybindingService, + @IChatAgentService chatAgentService: IChatAgentService, ) { super(); this._editor = editor; @@ -179,44 +181,51 @@ export class InlineChatHintsController extends Disposable implements IEditorCont } })); - const posObs = observableFromEvent(editor.onDidChangeCursorPosition, () => editor.getPosition()); - const decos = this._editor.createDecorationsCollection(); + const modelObs = observableFromEvent(editor.onDidChangeModel, () => editor.getModel()); + const posObs = observableFromEvent(editor.onDidChangeCursorPosition, () => editor.getPosition()); const keyObs = observableFromEvent(keybindingService.onDidUpdateKeybindings, _ => keybindingService.lookupKeybinding(ACTION_START)?.getLabel()); - this._store.add(autorun(r => { const ghostState = ghostCtrl?.model.read(r)?.state.read(r); const visible = this._visibilityObs.read(r); const kb = keyObs.read(r); const position = posObs.read(r); + const model = modelObs.read(r); // update context key this._ctxShowingHint.set(visible); - if (!visible || !kb || !position || ghostState !== undefined) { + if (!visible || !kb || !position || ghostState !== undefined || !model) { decos.clear(); return; } - const column = this._editor.getModel()?.getLineMaxColumn(position.lineNumber); - if (!column) { - return; + const isEol = model.getLineMaxColumn(position.lineNumber) === position.column; + + let content: string; + let inlineClassName: string; + + if (isEol) { + const agentName = chatAgentService.getDefaultAgent(ChatAgentLocation.Editor)?.fullName ?? localize('defaultTitle', "Chat"); + content = '\u00A0' + localize('title', "{0} to continue with {1}...", kb, agentName); + inlineClassName = `inline-chat-hint${decos.length === 0 ? ' first' : ''}`; + } else { + content = '\u200a' + kb + '\u200a'; + inlineClassName = 'inline-chat-hint embedded'; } - const range = Range.fromPositions(position); - decos.set([{ - range, + range: Range.fromPositions(position), options: { description: 'inline-chat-hint-line', showIfCollapsed: true, stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, after: { - inlineClassName: 'inline-chat-hint', - content: '\u00A0' + localize('ddd', "{0} to chat", kb), + content, + inlineClassName, inlineClassNameAffectsLetterSpacing: true, cursorStops: InjectedTextCursorStops.Both, attachedData: this diff --git a/src/vs/workbench/contrib/inlineChat/browser/media/inlineChat.css b/src/vs/workbench/contrib/inlineChat/browser/media/inlineChat.css index 5b10211a242..5cc3f844d1b 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/media/inlineChat.css +++ b/src/vs/workbench/contrib/inlineChat/browser/media/inlineChat.css @@ -340,10 +340,37 @@ /* HINT */ + .monaco-workbench .monaco-editor .inline-chat-hint { /* padding: 0 8px; */ cursor: pointer; color: var(--vscode-editorGhostText-foreground); - border: 1px solid var(--vscode-editorGhostText-border); + background-image: linear-gradient(45deg, var(--vscode-editorGhostText-foreground), 95%, transparent); + background-clip: text; + -webkit-text-fill-color: transparent; +} + +.monaco-workbench .monaco-editor .inline-chat-hint.embedded { + border: 1px solid var(--vscode-editorSuggestWidget-border); border-radius: 3px; } + +@property --inline-chat-hint-progress { + syntax: ''; + initial-value: 33%; + inherits: false; +} + +@keyframes ltr { + 0% { + --inline-chat-hint-progress: 33%; + } + 100% { + --inline-chat-hint-progress: 95%; + } +} + +.monaco-workbench .monaco-editor .inline-chat-hint.first { + background-image: linear-gradient(45deg, var(--vscode-editorGhostText-foreground), var(--inline-chat-hint-progress), transparent); + animation: 75ms ltr ease-in forwards; +}