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' ;
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' ;
10
11
import { Disposable , DisposableStore } from '../../../../../base/common/lifecycle.js' ;
11
12
import { Schemas } from '../../../../../base/common/network.js' ;
12
13
import { basename , dirname } from '../../../../../base/common/resources.js' ;
@@ -19,12 +20,11 @@ import { IMenuService, MenuId } from '../../../../../platform/actions/common/act
19
20
import { IContextKeyService } from '../../../../../platform/contextkey/common/contextkey.js' ;
20
21
import { IContextMenuService } from '../../../../../platform/contextview/browser/contextView.js' ;
21
22
import { FileKind , IFileService } from '../../../../../platform/files/common/files.js' ;
23
+ import { IHoverService } from '../../../../../platform/hover/browser/hover.js' ;
22
24
import { ILabelService } from '../../../../../platform/label/common/label.js' ;
23
25
import { ResourceLabels } from '../../../../browser/labels.js' ;
24
26
import { ResourceContextKey } from '../../../../common/contextkeys.js' ;
25
27
import { IChatRequestImplicitVariableEntry } from '../../common/chatVariableEntries.js' ;
26
- import { IChatWidgetService } from '../chat.js' ;
27
- import { ChatAttachmentModel } from '../chatAttachmentModel.js' ;
28
28
29
29
export class ImplicitContextAttachmentWidget extends Disposable {
30
30
public readonly domNode : HTMLElement ;
@@ -34,15 +34,14 @@ export class ImplicitContextAttachmentWidget extends Disposable {
34
34
constructor (
35
35
private readonly attachment : IChatRequestImplicitVariableEntry ,
36
36
private readonly resourceLabels : ResourceLabels ,
37
- private readonly attachmentModel : ChatAttachmentModel ,
38
37
@IContextKeyService private readonly contextKeyService : IContextKeyService ,
39
38
@IContextMenuService private readonly contextMenuService : IContextMenuService ,
40
39
@ILabelService private readonly labelService : ILabelService ,
41
40
@IMenuService private readonly menuService : IMenuService ,
42
41
@IFileService private readonly fileService : IFileService ,
43
42
@ILanguageService private readonly languageService : ILanguageService ,
44
43
@IModelService private readonly modelService : IModelService ,
45
- @IChatWidgetService private readonly chatWidgetService : IChatWidgetService ,
44
+ @IHoverService private readonly hoverService : IHoverService ,
46
45
) {
47
46
super ( ) ;
48
47
@@ -54,17 +53,17 @@ export class ImplicitContextAttachmentWidget extends Disposable {
54
53
dom . clearNode ( this . domNode ) ;
55
54
this . renderDisposables . clear ( ) ;
56
55
57
- this . domNode . classList . add ( 'disabled' ) ;
56
+ this . domNode . classList . toggle ( 'disabled' , ! this . attachment . enabled ) ;
58
57
const label = this . resourceLabels . create ( this . domNode , { supportIcons : true } ) ;
59
58
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 ;
61
60
62
61
const attachmentTypeName = file . scheme === Schemas . vscodeNotebookCell ? localize ( 'cell.lowercase' , "cell" ) : localize ( 'file.lowercase' , "file" ) ;
63
62
64
63
const fileBasename = basename ( file ) ;
65
64
const fileDirname = dirname ( file ) ;
66
65
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 ) ;
68
67
69
68
const uriLabel = this . labelService . getUriLabel ( file , { relative : true } ) ;
70
69
const currentFile = localize ( 'openEditor' , "Suggested context (current file)" ) ;
@@ -79,17 +78,16 @@ export class ImplicitContextAttachmentWidget extends Disposable {
79
78
this . domNode . ariaLabel = ariaLabel ;
80
79
this . domNode . tabIndex = 0 ;
81
80
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 ) ) ;
85
84
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 ;
93
91
} ) ) ;
94
92
95
93
// Context menu
@@ -112,14 +110,4 @@ export class ImplicitContextAttachmentWidget extends Disposable {
112
110
} ) ;
113
111
} ) ) ;
114
112
}
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
- }
125
113
}
0 commit comments