@@ -16,10 +16,9 @@ import { basename, dirname } from '../../../../../base/common/path.js';
16
16
import { localize } from '../../../../../nls.js' ;
17
17
import { ChatResponseReferencePartStatusKind , IChatContentReference } from '../../common/chatService.js' ;
18
18
import { IOpenerService } from '../../../../../platform/opener/common/opener.js' ;
19
- import { StandardKeyboardEvent } from '../../../../../base/browser/keyboardEvent.js' ;
20
- import { KeyCode } from '../../../../../base/common/keyCodes.js' ;
21
19
import { IHoverService } from '../../../../../platform/hover/browser/hover.js' ;
22
20
import { createInstantHoverDelegate } from '../../../../../base/browser/ui/hover/hoverDelegateFactory.js' ;
21
+ import { IManagedHoverContentOrFactory } from '../../../../../base/browser/ui/hover/hover.js' ;
23
22
24
23
export class ChatAttachmentsContentPart extends Disposable {
25
24
private readonly attachedContextDisposables = this . _register ( new DisposableStore ( ) ) ;
@@ -49,19 +48,22 @@ export class ChatAttachmentsContentPart extends Disposable {
49
48
50
49
this . variables . forEach ( async ( attachment ) => {
51
50
const widget = dom . append ( container , dom . $ ( '.chat-attached-context-attachment.show-file-icons' ) ) ;
52
- const label = this . _contextResourceLabels . create ( widget , { supportIcons : true } ) ;
51
+ const label = this . _contextResourceLabels . create ( widget , { supportIcons : true , hoverDelegate } ) ;
53
52
const file = URI . isUri ( attachment . value ) ? attachment . value : attachment . value && typeof attachment . value === 'object' && 'uri' in attachment . value && URI . isUri ( attachment . value . uri ) ? attachment . value . uri : undefined ;
54
53
const range = attachment . value && typeof attachment . value === 'object' && 'range' in attachment . value && Range . isIRange ( attachment . value . range ) ? attachment . value . range : undefined ;
55
54
56
55
const correspondingContentReference = this . contentReferences . find ( ( ref ) => typeof ref . reference === 'object' && 'variableName' in ref . reference && ref . reference . variableName === attachment . name ) ;
57
56
const isAttachmentOmitted = correspondingContentReference ?. options ?. status ?. kind === ChatResponseReferencePartStatusKind . Omitted ;
58
57
const isAttachmentPartialOrOmitted = isAttachmentOmitted || correspondingContentReference ?. options ?. status ?. kind === ChatResponseReferencePartStatusKind . Partial ;
59
58
59
+ let hoverElement : IManagedHoverContentOrFactory ;
60
+ let ariaLabel : string | undefined ;
61
+
60
62
if ( file && attachment . isFile ) {
61
63
const fileBasename = basename ( file . path ) ;
62
64
const fileDirname = dirname ( file . path ) ;
63
65
const friendlyName = `${ fileBasename } ${ fileDirname } ` ;
64
- let ariaLabel ;
66
+
65
67
if ( isAttachmentOmitted ) {
66
68
ariaLabel = range ? localize ( 'chat.omittedFileAttachmentWithRange' , "Omitted: {0}, line {1} to line {2}." , friendlyName , range . startLineNumber , range . endLineNumber ) : localize ( 'chat.omittedFileAttachment' , "Omitted: {0}." , friendlyName ) ;
67
69
} else if ( isAttachmentPartialOrOmitted ) {
@@ -70,42 +72,27 @@ export class ChatAttachmentsContentPart extends Disposable {
70
72
ariaLabel = range ? localize ( 'chat.fileAttachmentWithRange3' , "Attached: {0}, line {1} to line {2}." , friendlyName , range . startLineNumber , range . endLineNumber ) : localize ( 'chat.fileAttachment3' , "Attached: {0}." , friendlyName ) ;
71
73
}
72
74
75
+ hoverElement = file . fsPath ;
76
+
73
77
label . setFile ( file , {
74
78
fileKind : FileKind . FILE ,
75
79
hidePath : true ,
76
80
range,
77
81
title : correspondingContentReference ?. options ?. status ?. description
78
82
} ) ;
79
- widget . ariaLabel = ariaLabel ;
80
- widget . tabIndex = 0 ;
81
- widget . style . cursor = 'pointer' ;
82
-
83
- this . attachedContextDisposables . add ( dom . addDisposableListener ( widget , dom . EventType . CLICK , async ( e : MouseEvent ) => {
84
- dom . EventHelper . stop ( e , true ) ;
85
- if ( file ) {
86
- this . openerService . open (
87
- file ,
88
- {
89
- fromUserGesture : true ,
90
- editorOptions : {
91
- selection : range
92
- } as any
93
- } ) ;
94
- }
95
- } ) ) ;
96
83
} else if ( attachment . isImage ) {
97
- let buffer : Uint8Array ;
98
- const ariaLabel = localize ( 'chat.imageAttachment' , "Attached image, {0}" , attachment . name ) ;
99
- const pillIcon = dom . $ ( 'div.chat-attached-context-pill' , { } , dom . $ ( 'span.codicon.codicon-file-media' ) ) ;
84
+ ariaLabel = localize ( 'chat.imageAttachment' , "Attached image, {0}" , attachment . name ) ;
100
85
101
- const hoverElement = dom . $ ( 'div.chat-attached-context-hover' ) ;
86
+ hoverElement = dom . $ ( 'div.chat-attached-context-hover' ) ;
102
87
hoverElement . setAttribute ( 'aria-label' , ariaLabel ) ;
103
88
104
89
// Custom label
90
+ const pillIcon = dom . $ ( 'div.chat-attached-context-pill' , { } , dom . $ ( 'span.codicon.codicon-file-media' ) ) ;
105
91
const textLabel = dom . $ ( 'span.chat-attached-context-custom-text' , { } , attachment . name ) ;
106
92
widget . appendChild ( pillIcon ) ;
107
93
widget . appendChild ( textLabel ) ;
108
94
95
+ let buffer : Uint8Array ;
109
96
try {
110
97
if ( attachment . value instanceof URI ) {
111
98
const readFile = await this . fileService . readFile ( attachment . value ) ;
@@ -120,43 +107,50 @@ export class ChatAttachmentsContentPart extends Disposable {
120
107
}
121
108
122
109
widget . style . position = 'relative' ;
123
- widget . ariaLabel = ariaLabel ;
124
- widget . tabIndex = 0 ;
125
-
126
- if ( ! this . attachedContextDisposables . isDisposed ) {
127
- this . attachedContextDisposables . add ( this . hoverService . setupManagedHover ( hoverDelegate , widget , hoverElement ) ) ;
128
-
129
- // No delay for keyboard
130
- this . attachedContextDisposables . add ( dom . addDisposableListener ( widget , 'keydown' , ( event ) => {
131
- const keyboardEvent = new StandardKeyboardEvent ( event ) ;
132
- if ( keyboardEvent . keyCode === KeyCode . Enter || keyboardEvent . keyCode === KeyCode . Space ) {
133
- this . hoverService . showManagedHover ( widget ) ;
134
- }
135
- } ) ) ;
136
- }
137
-
138
110
} else {
139
111
const attachmentLabel = attachment . fullName ?? attachment . name ;
140
112
const withIcon = attachment . icon ?. id ? `$(${ attachment . icon . id } ) ${ attachmentLabel } ` : attachmentLabel ;
141
113
label . setLabel ( withIcon , correspondingContentReference ?. options ?. status ?. description ) ;
142
114
143
- widget . ariaLabel = localize ( 'chat.attachment3' , "Attached context: {0}." , attachment . name ) ;
144
- widget . tabIndex = 0 ;
115
+ hoverElement = attachmentLabel ;
116
+ ariaLabel = localize ( 'chat.attachment3' , "Attached context: {0}." , attachment . name ) ;
145
117
}
146
118
147
119
if ( isAttachmentPartialOrOmitted ) {
148
120
widget . classList . add ( 'warning' ) ;
149
121
}
150
122
const description = correspondingContentReference ?. options ?. status ?. description ;
151
123
if ( isAttachmentPartialOrOmitted ) {
152
- widget . ariaLabel = `${ widget . ariaLabel } ${ description ? ` ${ description } ` : '' } ` ;
124
+ ariaLabel = `${ ariaLabel } ${ description ? ` ${ description } ` : '' } ` ;
125
+ hoverElement = description ;
153
126
for ( const selector of [ '.monaco-icon-suffix-container' , '.monaco-icon-name-container' ] ) {
154
127
const element = label . element . querySelector ( selector ) ;
155
128
if ( element ) {
156
129
element . classList . add ( 'warning' ) ;
157
130
}
158
131
}
159
132
}
133
+
134
+ if ( file ) {
135
+ widget . style . cursor = 'pointer' ;
136
+ this . attachedContextDisposables . add ( dom . addDisposableListener ( widget , dom . EventType . CLICK , async ( e : MouseEvent ) => {
137
+ dom . EventHelper . stop ( e , true ) ;
138
+ this . openerService . open (
139
+ file ,
140
+ {
141
+ fromUserGesture : true ,
142
+ editorOptions : {
143
+ selection : range
144
+ } as any
145
+ } ) ;
146
+ } ) ) ;
147
+ }
148
+
149
+ widget . ariaLabel = ariaLabel ;
150
+ widget . tabIndex = 0 ;
151
+ if ( ! this . attachedContextDisposables . isDisposed ) {
152
+ this . attachedContextDisposables . add ( this . hoverService . setupManagedHover ( hoverDelegate , widget , hoverElement ) ) ;
153
+ }
160
154
} ) ;
161
155
}
162
156
0 commit comments