@@ -11,7 +11,7 @@ import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
11
11
import { IOpenerService } from 'vs/platform/opener/common/opener' ;
12
12
import { IResourceLabel , ResourceLabels } from 'vs/workbench/browser/labels' ;
13
13
import { CommentNode , CommentsModel , ResourceWithCommentThreads } from 'vs/workbench/contrib/comments/common/commentModel' ;
14
- import { IAsyncDataSource , ITreeNode } from 'vs/base/browser/ui/tree/tree' ;
14
+ import { IAsyncDataSource , ITreeFilter , ITreeNode , TreeFilterResult , TreeVisibility } from 'vs/base/browser/ui/tree/tree' ;
15
15
import { IListVirtualDelegate , IListRenderer } from 'vs/base/browser/ui/list/list' ;
16
16
import { IConfigurationService } from 'vs/platform/configuration/common/configuration' ;
17
17
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey' ;
@@ -25,6 +25,9 @@ import { IMarkdownString } from 'vs/base/common/htmlContent';
25
25
import { commentViewThreadStateColorVar , getCommentThreadStateColor } from 'vs/workbench/contrib/comments/browser/commentColors' ;
26
26
import { CommentThreadState } from 'vs/editor/common/languages' ;
27
27
import { Color } from 'vs/base/common/color' ;
28
+ import { IMatch } from 'vs/base/common/filters' ;
29
+ import { FilterOptions } from 'vs/workbench/contrib/comments/browser/commentsFilterOptions' ;
30
+ import { basename } from 'vs/base/common/resources' ;
28
31
29
32
export const COMMENTS_VIEW_ID = 'workbench.panel.comments' ;
30
33
export const COMMENTS_VIEW_STORAGE_ID = 'Comments' ;
@@ -70,7 +73,7 @@ interface ICommentThreadTemplateData {
70
73
disposables : IDisposable [ ] ;
71
74
}
72
75
73
- export class CommentsModelVirualDelegate implements IListVirtualDelegate < any > {
76
+ export class CommentsModelVirualDelegate implements IListVirtualDelegate < ResourceWithCommentThreads | CommentNode > {
74
77
private static readonly RESOURCE_ID = 'resource-with-comments' ;
75
78
private static readonly COMMENT_ID = 'comment-node' ;
76
79
@@ -253,7 +256,81 @@ export interface ICommentsListOptions extends IWorkbenchAsyncDataTreeOptions<any
253
256
overrideStyles ?: IColorMapping ;
254
257
}
255
258
256
- export class CommentsList extends WorkbenchAsyncDataTree < any , any > {
259
+ const enum FilterDataType {
260
+ Resource ,
261
+ Comment
262
+ }
263
+
264
+ interface ResourceFilterData {
265
+ type : FilterDataType . Resource ;
266
+ uriMatches : IMatch [ ] ;
267
+ }
268
+
269
+ interface CommentFilterData {
270
+ type : FilterDataType . Comment ;
271
+ textMatches : IMatch [ ] ;
272
+ }
273
+
274
+ export type FilterData = ResourceFilterData | CommentFilterData ;
275
+
276
+ export class Filter implements ITreeFilter < ResourceWithCommentThreads | CommentNode , FilterData > {
277
+
278
+ constructor ( public options : FilterOptions ) { }
279
+
280
+ filter ( element : ResourceWithCommentThreads | CommentNode , parentVisibility : TreeVisibility ) : TreeFilterResult < FilterData > {
281
+ if ( element instanceof ResourceWithCommentThreads ) {
282
+ return this . filterResourceMarkers ( element ) ;
283
+ } else {
284
+ return this . filterCommentNode ( element , parentVisibility ) ;
285
+ }
286
+ }
287
+
288
+ private filterResourceMarkers ( resourceMarkers : ResourceWithCommentThreads ) : TreeFilterResult < FilterData > {
289
+ // Filter by text. Do not apply negated filters on resources instead use exclude patterns
290
+ if ( this . options . textFilter . text && ! this . options . textFilter . negate ) {
291
+ const uriMatches = FilterOptions . _filter ( this . options . textFilter . text , basename ( resourceMarkers . resource ) ) ;
292
+ if ( uriMatches ) {
293
+ return { visibility : true , data : { type : FilterDataType . Resource , uriMatches : uriMatches || [ ] } } ;
294
+ }
295
+ }
296
+
297
+ return TreeVisibility . Recurse ;
298
+ }
299
+
300
+ private filterCommentNode ( comment : CommentNode , parentVisibility : TreeVisibility ) : TreeFilterResult < FilterData > {
301
+ const matchesResolvedState = ( comment . threadState === undefined ) || ( this . options . showResolved && CommentThreadState . Resolved === comment . threadState ) ||
302
+ ( this . options . showUnresolved && CommentThreadState . Unresolved === comment . threadState ) ;
303
+
304
+ if ( ! matchesResolvedState ) {
305
+ return false ;
306
+ }
307
+
308
+ if ( ! this . options . textFilter . text ) {
309
+ return true ;
310
+ }
311
+
312
+ const textMatches = FilterOptions . _messageFilter ( this . options . textFilter . text , typeof comment . comment . body === 'string' ? comment . comment . body : comment . comment . body . value ) ;
313
+
314
+ // Matched and not negated
315
+ if ( textMatches && ! this . options . textFilter . negate ) {
316
+ return { visibility : true , data : { type : FilterDataType . Comment , textMatches } } ;
317
+ }
318
+
319
+ // Matched and negated - exclude it only if parent visibility is not set
320
+ if ( textMatches && this . options . textFilter . negate && parentVisibility === TreeVisibility . Recurse ) {
321
+ return false ;
322
+ }
323
+
324
+ // Not matched and negated - include it only if parent visibility is not set
325
+ if ( ! textMatches && this . options . textFilter . negate && parentVisibility === TreeVisibility . Recurse ) {
326
+ return true ;
327
+ }
328
+
329
+ return parentVisibility ;
330
+ }
331
+ }
332
+
333
+ export class CommentsList extends WorkbenchAsyncDataTree < CommentsModel | ResourceWithCommentThreads | CommentNode , any > {
257
334
constructor (
258
335
labels : ResourceLabels ,
259
336
container : HTMLElement ,
@@ -304,7 +381,9 @@ export class CommentsList extends WorkbenchAsyncDataTree<any, any> {
304
381
collapseByDefault : ( ) => {
305
382
return false ;
306
383
} ,
307
- overrideStyles : options . overrideStyles
384
+ overrideStyles : options . overrideStyles ,
385
+ filter : options . filter ,
386
+ findWidgetEnabled : false
308
387
} ,
309
388
instantiationService ,
310
389
contextKeyService ,
@@ -313,4 +392,23 @@ export class CommentsList extends WorkbenchAsyncDataTree<any, any> {
313
392
configurationService
314
393
) ;
315
394
}
395
+
396
+ filterComments ( ) : void {
397
+ this . refilter ( ) ;
398
+ }
399
+
400
+ getVisibleItemCount ( ) : number {
401
+ let filtered = 0 ;
402
+ const root = this . getNode ( ) ;
403
+
404
+ for ( const resourceNode of root . children ) {
405
+ for ( const commentNode of resourceNode . children ) {
406
+ if ( commentNode . visible && resourceNode . visible ) {
407
+ filtered ++ ;
408
+ }
409
+ }
410
+ }
411
+
412
+ return filtered ;
413
+ }
316
414
}
0 commit comments