44 *--------------------------------------------------------------------------------------------*/
55
66import * as dom from '../../../../../base/browser/dom.js' ;
7- import { StandardKeyboardEvent } from '../../../../../base/browser/keyboardEvent.js' ;
87import { StandardMouseEvent } from '../../../../../base/browser/mouseEvent.js' ;
8+ import { Button } from '../../../../../base/browser/ui/button/button.js' ;
9+ import { getDefaultHoverDelegate } from '../../../../../base/browser/ui/hover/hoverDelegateFactory.js' ;
910import { Codicon } from '../../../../../base/common/codicons.js' ;
10- import { KeyCode } from '../../../../../base/common/keyCodes.js' ;
1111import { Disposable , DisposableStore } from '../../../../../base/common/lifecycle.js' ;
1212import { Schemas } from '../../../../../base/common/network.js' ;
1313import { basename , dirname } from '../../../../../base/common/resources.js' ;
@@ -21,12 +21,11 @@ import { IMenuService, MenuId } from '../../../../../platform/actions/common/act
2121import { IContextKeyService } from '../../../../../platform/contextkey/common/contextkey.js' ;
2222import { IContextMenuService } from '../../../../../platform/contextview/browser/contextView.js' ;
2323import { FileKind , IFileService } from '../../../../../platform/files/common/files.js' ;
24+ import { IHoverService } from '../../../../../platform/hover/browser/hover.js' ;
2425import { ILabelService } from '../../../../../platform/label/common/label.js' ;
2526import { ResourceLabels } from '../../../../browser/labels.js' ;
2627import { ResourceContextKey } from '../../../../common/contextkeys.js' ;
2728import { IChatRequestImplicitVariableEntry } from '../../common/chatModel.js' ;
28- import { IChatWidgetService } from '../chat.js' ;
29- import { ChatAttachmentModel } from '../chatAttachmentModel.js' ;
3029
3130export class ImplicitContextAttachmentWidget extends Disposable {
3231 public readonly domNode : HTMLElement ;
@@ -36,15 +35,14 @@ export class ImplicitContextAttachmentWidget extends Disposable {
3635 constructor (
3736 private readonly attachment : IChatRequestImplicitVariableEntry ,
3837 private readonly resourceLabels : ResourceLabels ,
39- private readonly attachmentModel : ChatAttachmentModel ,
4038 @IContextKeyService private readonly contextKeyService : IContextKeyService ,
4139 @IContextMenuService private readonly contextMenuService : IContextMenuService ,
4240 @ILabelService private readonly labelService : ILabelService ,
4341 @IMenuService private readonly menuService : IMenuService ,
4442 @IFileService private readonly fileService : IFileService ,
4543 @ILanguageService private readonly languageService : ILanguageService ,
4644 @IModelService private readonly modelService : IModelService ,
47- @IChatWidgetService private readonly chatWidgetService : IChatWidgetService ,
45+ @IHoverService private readonly hoverService : IHoverService ,
4846 ) {
4947 super ( ) ;
5048
@@ -56,10 +54,10 @@ export class ImplicitContextAttachmentWidget extends Disposable {
5654 dom . clearNode ( this . domNode ) ;
5755 this . renderDisposables . clear ( ) ;
5856
59- this . domNode . classList . add ( 'disabled' ) ;
57+ this . domNode . classList . toggle ( 'disabled' , ! this . attachment . enabled ) ;
6058 const label = this . resourceLabels . create ( this . domNode , { supportIcons : true } ) ;
6159 const file = URI . isUri ( this . attachment . value ) ? this . attachment . value : this . attachment . value ! . uri ;
62- const range = undefined ;
60+ const range = URI . isUri ( this . attachment . value ) || ! this . attachment . isSelection ? undefined : this . attachment . value ! . range ;
6361
6462 const attachmentTypeName = ( this . attachment . isPromptFile === false )
6563 ? file . scheme === Schemas . vscodeNotebookCell ? localize ( 'cell.lowercase' , "cell" ) : localize ( 'file.lowercase' , "file" )
@@ -68,7 +66,7 @@ export class ImplicitContextAttachmentWidget extends Disposable {
6866 const fileBasename = basename ( file ) ;
6967 const fileDirname = dirname ( file ) ;
7068 const friendlyName = `${ fileBasename } ${ fileDirname } ` ;
71- const ariaLabel = localize ( 'chat.fileAttachment' , "Attached {0}, {1}" , attachmentTypeName , friendlyName ) ;
69+ const ariaLabel = range ? localize ( 'chat.fileAttachmentWithRange' , "Attached {0}, {1}, line {2} to line {3}" , attachmentTypeName , friendlyName , range . startLineNumber , range . endLineNumber ) : localize ( 'chat.fileAttachment' , "Attached {0}, {1}" , attachmentTypeName , friendlyName ) ;
7270
7371 const uriLabel = this . labelService . getUriLabel ( file , { relative : true } ) ;
7472 const currentFile = localize ( 'openEditor' , "Suggested context (current file)" ) ;
@@ -88,17 +86,16 @@ export class ImplicitContextAttachmentWidget extends Disposable {
8886 this . domNode . ariaLabel = ariaLabel ;
8987 this . domNode . tabIndex = 0 ;
9088
91- this . renderDisposables . add ( dom . addDisposableListener ( this . domNode , dom . EventType . CLICK , e => {
92- this . convertToRegularAttachment ( ) ;
93- } ) ) ;
89+ const hintLabel = localize ( 'hint.label.current' , "Current {0}" , attachmentTypeName ) ;
90+ const hintElement = dom . append ( this . domNode , dom . $ ( 'span.chat-implicit-hint' , undefined , hintLabel ) ) ;
91+ this . _register ( this . hoverService . setupManagedHover ( getDefaultHoverDelegate ( 'element' ) , hintElement , title ) ) ;
9492
95- this . renderDisposables . add ( dom . addDisposableListener ( this . domNode , dom . EventType . KEY_DOWN , e => {
96- const event = new StandardKeyboardEvent ( e ) ;
97- if ( event . equals ( KeyCode . Enter ) || event . equals ( KeyCode . Space ) ) {
98- e . preventDefault ( ) ;
99- e . stopPropagation ( ) ;
100- this . convertToRegularAttachment ( ) ;
101- }
93+ const buttonMsg = this . attachment . enabled ? localize ( 'disable' , "Disable current {0} context" , attachmentTypeName ) : localize ( 'enable' , "Enable current {0} context" , attachmentTypeName ) ;
94+ const toggleButton = this . renderDisposables . add ( new Button ( this . domNode , { supportIcons : true , title : buttonMsg } ) ) ;
95+ toggleButton . icon = this . attachment . enabled ? Codicon . eye : Codicon . eyeClosed ;
96+ this . renderDisposables . add ( toggleButton . onDidClick ( ( e ) => {
97+ e . stopPropagation ( ) ; // prevent it from triggering the click handler on the parent immediately after rerendering
98+ this . attachment . enabled = ! this . attachment . enabled ;
10299 } ) ) ;
103100
104101 // Context menu
@@ -121,14 +118,4 @@ export class ImplicitContextAttachmentWidget extends Disposable {
121118 } ) ;
122119 } ) ) ;
123120 }
124-
125- private convertToRegularAttachment ( ) : void {
126- if ( ! this . attachment . value ) {
127- return ;
128- }
129-
130- const file = URI . isUri ( this . attachment . value ) ? this . attachment . value : this . attachment . value . uri ;
131- this . attachmentModel . addFile ( file ) ;
132- this . chatWidgetService . lastFocusedWidget ?. focusInput ( ) ;
133- }
134121}
0 commit comments