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' ;
9- import { KeyCode } from '../../../../../base/common/keyCodes.js' ;
8+ import { Button } from '../../../../../base/browser/ui/button/button.js' ;
9+ import { getDefaultHoverDelegate } from '../../../../../base/browser/ui/hover/hoverDelegateFactory.js' ;
10+ import { Codicon } from '../../../../../base/common/codicons.js' ;
1011import { Disposable , DisposableStore } from '../../../../../base/common/lifecycle.js' ;
1112import { Schemas } from '../../../../../base/common/network.js' ;
1213import { basename , dirname } from '../../../../../base/common/resources.js' ;
@@ -19,12 +20,11 @@ import { IMenuService, MenuId } from '../../../../../platform/actions/common/act
1920import { IContextKeyService } from '../../../../../platform/contextkey/common/contextkey.js' ;
2021import { IContextMenuService } from '../../../../../platform/contextview/browser/contextView.js' ;
2122import { FileKind , IFileService } from '../../../../../platform/files/common/files.js' ;
23+ import { IHoverService } from '../../../../../platform/hover/browser/hover.js' ;
2224import { ILabelService } from '../../../../../platform/label/common/label.js' ;
2325import { ResourceLabels } from '../../../../browser/labels.js' ;
2426import { ResourceContextKey } from '../../../../common/contextkeys.js' ;
2527import { IChatRequestImplicitVariableEntry } from '../../common/chatVariableEntries.js' ;
26- import { IChatWidgetService } from '../chat.js' ;
27- import { ChatAttachmentModel } from '../chatAttachmentModel.js' ;
2828
2929export class ImplicitContextAttachmentWidget extends Disposable {
3030 public readonly domNode : HTMLElement ;
@@ -34,15 +34,14 @@ export class ImplicitContextAttachmentWidget extends Disposable {
3434 constructor (
3535 private readonly attachment : IChatRequestImplicitVariableEntry ,
3636 private readonly resourceLabels : ResourceLabels ,
37- private readonly attachmentModel : ChatAttachmentModel ,
3837 @IContextKeyService private readonly contextKeyService : IContextKeyService ,
3938 @IContextMenuService private readonly contextMenuService : IContextMenuService ,
4039 @ILabelService private readonly labelService : ILabelService ,
4140 @IMenuService private readonly menuService : IMenuService ,
4241 @IFileService private readonly fileService : IFileService ,
4342 @ILanguageService private readonly languageService : ILanguageService ,
4443 @IModelService private readonly modelService : IModelService ,
45- @IChatWidgetService private readonly chatWidgetService : IChatWidgetService ,
44+ @IHoverService private readonly hoverService : IHoverService ,
4645 ) {
4746 super ( ) ;
4847
@@ -54,17 +53,17 @@ export class ImplicitContextAttachmentWidget extends Disposable {
5453 dom . clearNode ( this . domNode ) ;
5554 this . renderDisposables . clear ( ) ;
5655
57- this . domNode . classList . add ( 'disabled' ) ;
56+ this . domNode . classList . toggle ( 'disabled' , ! this . attachment . enabled ) ;
5857 const label = this . resourceLabels . create ( this . domNode , { supportIcons : true } ) ;
5958 const file = URI . isUri ( this . attachment . value ) ? this . attachment . value : this . attachment . value ! . uri ;
60- const range = undefined ;
59+ const range = URI . isUri ( this . attachment . value ) || ! this . attachment . isSelection ? undefined : this . attachment . value ! . range ;
6160
6261 const attachmentTypeName = file . scheme === Schemas . vscodeNotebookCell ? localize ( 'cell.lowercase' , "cell" ) : localize ( 'file.lowercase' , "file" ) ;
6362
6463 const fileBasename = basename ( file ) ;
6564 const fileDirname = dirname ( file ) ;
6665 const friendlyName = `${ fileBasename } ${ fileDirname } ` ;
67- const ariaLabel = localize ( 'chat.fileAttachment' , "Attached {0}, {1}" , attachmentTypeName , friendlyName ) ;
66+ 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 ) ;
6867
6968 const uriLabel = this . labelService . getUriLabel ( file , { relative : true } ) ;
7069 const currentFile = localize ( 'openEditor' , "Suggested context (current file)" ) ;
@@ -79,17 +78,16 @@ export class ImplicitContextAttachmentWidget extends Disposable {
7978 this . domNode . ariaLabel = ariaLabel ;
8079 this . domNode . tabIndex = 0 ;
8180
82- this . renderDisposables . add ( dom . addDisposableListener ( this . domNode , dom . EventType . CLICK , e => {
83- this . convertToRegularAttachment ( ) ;
84- } ) ) ;
81+ const hintLabel = localize ( 'hint.label.current' , "Current {0}" , attachmentTypeName ) ;
82+ const hintElement = dom . append ( this . domNode , dom . $ ( 'span.chat-implicit-hint' , undefined , hintLabel ) ) ;
83+ this . _register ( this . hoverService . setupManagedHover ( getDefaultHoverDelegate ( 'element' ) , hintElement , title ) ) ;
8584
86- this . renderDisposables . add ( dom . addDisposableListener ( this . domNode , dom . EventType . KEY_DOWN , e => {
87- const event = new StandardKeyboardEvent ( e ) ;
88- if ( event . equals ( KeyCode . Enter ) || event . equals ( KeyCode . Space ) ) {
89- e . preventDefault ( ) ;
90- e . stopPropagation ( ) ;
91- this . convertToRegularAttachment ( ) ;
92- }
85+ const buttonMsg = this . attachment . enabled ? localize ( 'disable' , "Disable current {0} context" , attachmentTypeName ) : localize ( 'enable' , "Enable current {0} context" , attachmentTypeName ) ;
86+ const toggleButton = this . renderDisposables . add ( new Button ( this . domNode , { supportIcons : true , title : buttonMsg } ) ) ;
87+ toggleButton . icon = this . attachment . enabled ? Codicon . eye : Codicon . eyeClosed ;
88+ this . renderDisposables . add ( toggleButton . onDidClick ( ( e ) => {
89+ e . stopPropagation ( ) ; // prevent it from triggering the click handler on the parent immediately after rerendering
90+ this . attachment . enabled = ! this . attachment . enabled ;
9391 } ) ) ;
9492
9593 // Context menu
@@ -112,14 +110,4 @@ export class ImplicitContextAttachmentWidget extends Disposable {
112110 } ) ;
113111 } ) ) ;
114112 }
115-
116- private convertToRegularAttachment ( ) : void {
117- if ( ! this . attachment . value ) {
118- return ;
119- }
120-
121- const file = URI . isUri ( this . attachment . value ) ? this . attachment . value : this . attachment . value . uri ;
122- this . attachmentModel . addFile ( file ) ;
123- this . chatWidgetService . lastFocusedWidget ?. focusInput ( ) ;
124- }
125113}
0 commit comments