4
4
*--------------------------------------------------------------------------------------------*/
5
5
6
6
import * as dom from '../../../../../base/browser/dom.js' ;
7
- import { StandardKeyboardEvent } from '../../../../../base/browser/keyboardEvent.js' ;
8
7
import { 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' ;
9
10
import { Codicon } from '../../../../../base/common/codicons.js' ;
10
- import { KeyCode } from '../../../../../base/common/keyCodes.js' ;
11
11
import { Disposable , DisposableStore } from '../../../../../base/common/lifecycle.js' ;
12
12
import { Schemas } from '../../../../../base/common/network.js' ;
13
13
import { basename , dirname } from '../../../../../base/common/resources.js' ;
@@ -21,12 +21,11 @@ import { IMenuService, MenuId } from '../../../../../platform/actions/common/act
21
21
import { IContextKeyService } from '../../../../../platform/contextkey/common/contextkey.js' ;
22
22
import { IContextMenuService } from '../../../../../platform/contextview/browser/contextView.js' ;
23
23
import { FileKind , IFileService } from '../../../../../platform/files/common/files.js' ;
24
+ import { IHoverService } from '../../../../../platform/hover/browser/hover.js' ;
24
25
import { ILabelService } from '../../../../../platform/label/common/label.js' ;
25
26
import { ResourceLabels } from '../../../../browser/labels.js' ;
26
27
import { ResourceContextKey } from '../../../../common/contextkeys.js' ;
27
28
import { IChatRequestImplicitVariableEntry } from '../../common/chatModel.js' ;
28
- import { IChatWidgetService } from '../chat.js' ;
29
- import { ChatAttachmentModel } from '../chatAttachmentModel.js' ;
30
29
31
30
export class ImplicitContextAttachmentWidget extends Disposable {
32
31
public readonly domNode : HTMLElement ;
@@ -36,15 +35,14 @@ export class ImplicitContextAttachmentWidget extends Disposable {
36
35
constructor (
37
36
private readonly attachment : IChatRequestImplicitVariableEntry ,
38
37
private readonly resourceLabels : ResourceLabels ,
39
- private readonly attachmentModel : ChatAttachmentModel ,
40
38
@IContextKeyService private readonly contextKeyService : IContextKeyService ,
41
39
@IContextMenuService private readonly contextMenuService : IContextMenuService ,
42
40
@ILabelService private readonly labelService : ILabelService ,
43
41
@IMenuService private readonly menuService : IMenuService ,
44
42
@IFileService private readonly fileService : IFileService ,
45
43
@ILanguageService private readonly languageService : ILanguageService ,
46
44
@IModelService private readonly modelService : IModelService ,
47
- @IChatWidgetService private readonly chatWidgetService : IChatWidgetService ,
45
+ @IHoverService private readonly hoverService : IHoverService ,
48
46
) {
49
47
super ( ) ;
50
48
@@ -56,10 +54,10 @@ export class ImplicitContextAttachmentWidget extends Disposable {
56
54
dom . clearNode ( this . domNode ) ;
57
55
this . renderDisposables . clear ( ) ;
58
56
59
- this . domNode . classList . add ( 'disabled' ) ;
57
+ this . domNode . classList . toggle ( 'disabled' , ! this . attachment . enabled ) ;
60
58
const label = this . resourceLabels . create ( this . domNode , { supportIcons : true } ) ;
61
59
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 ;
63
61
64
62
const attachmentTypeName = ( this . attachment . isPromptFile === false )
65
63
? file . scheme === Schemas . vscodeNotebookCell ? localize ( 'cell.lowercase' , "cell" ) : localize ( 'file.lowercase' , "file" )
@@ -68,7 +66,7 @@ export class ImplicitContextAttachmentWidget extends Disposable {
68
66
const fileBasename = basename ( file ) ;
69
67
const fileDirname = dirname ( file ) ;
70
68
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 ) ;
72
70
73
71
const uriLabel = this . labelService . getUriLabel ( file , { relative : true } ) ;
74
72
const currentFile = localize ( 'openEditor' , "Suggested context (current file)" ) ;
@@ -88,17 +86,16 @@ export class ImplicitContextAttachmentWidget extends Disposable {
88
86
this . domNode . ariaLabel = ariaLabel ;
89
87
this . domNode . tabIndex = 0 ;
90
88
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 ) ) ;
94
92
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 ;
102
99
} ) ) ;
103
100
104
101
// Context menu
@@ -121,14 +118,4 @@ export class ImplicitContextAttachmentWidget extends Disposable {
121
118
} ) ;
122
119
} ) ) ;
123
120
}
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
- }
134
121
}
0 commit comments