@@ -22,11 +22,12 @@ export class ModifiedFilesTracker {
2222 private readonly props : ModifiedFilesTrackerProps ;
2323 private readonly collapsibleContent : CollapsibleContent ;
2424 public titleText : string = 'No files modified!' ;
25+ private readonly allFiles : Map < string , { fileList : NonNullable < ChatItemContent [ 'fileList' ] > ; messageId : string } > = new Map ( ) ;
2526
2627 constructor ( props : ModifiedFilesTrackerProps ) {
2728 console . log ( '[ModifiedFilesTracker] Constructor called with props:' , {
2829 tabId : props . tabId ,
29- hasChatItem : ! ! props . chatItem ,
30+ hasChatItem : ! ( props . chatItem == null ) ,
3031 chatItem : props . chatItem ,
3132 fileList : props . chatItem ?. header ?. fileList
3233 } ) ;
@@ -53,23 +54,30 @@ export class ModifiedFilesTracker {
5354
5455 console . log ( '[ModifiedFilesTracker] Render element created:' , this . render ) ;
5556
56- if ( this . props . chatItem ?. header ?. fileList ) {
57+ if ( ( this . props . chatItem ?. header ?. fileList ) != null ) {
5758 console . log ( '[ModifiedFilesTracker] Rendering modified files with fileList:' , this . props . chatItem . header . fileList ) ;
58- this . renderModifiedFiles ( this . props . chatItem . header . fileList ) ;
59+ this . renderModifiedFiles ( this . props . chatItem . header . fileList , this . props . chatItem . messageId ) ;
5960 } else {
6061 console . log ( '[ModifiedFilesTracker] No fileList found, rendering empty state' ) ;
6162 this . renderModifiedFiles ( null ) ;
6263 }
6364 }
6465
65- private renderModifiedFiles ( fileList : ChatItemContent [ 'fileList' ] | null ) : void {
66+ private renderModifiedFiles ( fileList : ChatItemContent [ 'fileList' ] | null , chatItemMessageId ?: string ) : void {
6667 const contentWrapper = this . collapsibleContent . render . querySelector ( '.mynah-collapsible-content-label-content-wrapper' ) ;
6768 if ( contentWrapper == null ) return ;
6869
70+ // Add files to the collection if provided
71+ if ( fileList != null && ( fileList . filePaths ?. length ?? 0 ) > 0 ) {
72+ const messageId = chatItemMessageId ?? `modified-files-tracker-${ this . props . tabId } ` ;
73+ this . allFiles . set ( messageId , { fileList, messageId } ) ;
74+ }
75+
76+ // Clear and re-render all files
6977 contentWrapper . innerHTML = '' ;
7078
71- if ( ( fileList ?. filePaths ?. length ?? 0 ) > 0 && fileList != null ) {
72- this . renderFilePills ( contentWrapper , fileList ) ;
79+ if ( this . allFiles . size > 0 ) {
80+ this . renderAllFilePills ( contentWrapper ) ;
7381 } else {
7482 this . renderEmptyState ( contentWrapper ) ;
7583 }
@@ -83,44 +91,61 @@ export class ModifiedFilesTracker {
8391 } ) ) ;
8492 }
8593
86- private renderFilePills ( contentWrapper : Element , fileList : NonNullable < ChatItemContent [ 'fileList' ] > & { messageId ?: string } ) : void {
87- const messageId = fileList . messageId ?? `modified-files-tracker-${ this . props . tabId } ` ;
88-
89- // Render the file tree with actions and buttons as provided by the data
90- contentWrapper . appendChild ( new ChatItemTreeViewWrapper ( {
91- tabId : this . props . tabId ,
92- messageId,
93- files : fileList . filePaths ?? [ ] ,
94- cardTitle : '' ,
95- rootTitle : fileList . rootFolderTitle ,
96- deletedFiles : fileList . deletedFiles ?? [ ] ,
97- flatList : fileList . flatList ?? true ,
98- actions : ( fileList as any ) . actions ?? { } ,
99- details : fileList . details ?? { } ,
100- hideFileCount : fileList . hideFileCount ?? true ,
101- collapsed : fileList . collapsed ?? false ,
102- referenceSuggestionLabel : '' ,
103- references : [ ] ,
104- onRootCollapsedStateChange : ( ) => { }
105- } ) . render ) ;
106-
107- // Render buttons if they exist
108- const fileListWithButtons = fileList as ChatItemContent [ 'fileList' ] & { buttons ?: ChatItemButton [ ] } ;
109- const buttons : ChatItemButton [ ] | undefined = fileListWithButtons . buttons ;
110- if ( Array . isArray ( buttons ) && buttons . length > 0 ) {
111- const buttonsWrapper = new ChatItemButtonsWrapper ( {
112- tabId : this . props . tabId ,
113- buttons,
114- onActionClick : ( action : ChatItemButton ) => {
115- MynahUIGlobalEvents . getInstance ( ) . dispatch ( MynahEventNames . BODY_ACTION_CLICKED , {
116- tabId : this . props . tabId ,
117- messageId : ( action as any ) . messageId != null ? ( action as any ) . messageId : messageId ,
118- actionId : action . id ,
119- actionText : action . text
120- } ) ;
121- }
94+ private renderAllFilePills ( contentWrapper : Element ) : void {
95+ this . allFiles . forEach ( ( { fileList, messageId } ) => {
96+ const { filePaths = [ ] , deletedFiles = [ ] , actions, details, flatList } = fileList ;
97+
98+ // Create a wrapper for each file group
99+ const fileGroupWrapper = DomBuilder . getInstance ( ) . build ( {
100+ type : 'div' ,
101+ classNames : [ 'mynah-modified-files-group' ] ,
102+ children : [ ]
122103 } ) ;
123- contentWrapper . appendChild ( buttonsWrapper . render ) ;
104+
105+ // Render the file tree with actions and buttons as provided by the data
106+ fileGroupWrapper . appendChild ( new ChatItemTreeViewWrapper ( {
107+ tabId : this . props . tabId ,
108+ messageId,
109+ files : filePaths ,
110+ cardTitle : '' ,
111+ rootTitle : fileList . rootFolderTitle ,
112+ deletedFiles,
113+ flatList,
114+ actions,
115+ details,
116+ hideFileCount : fileList . hideFileCount ?? true ,
117+ collapsed : fileList . collapsed ?? false ,
118+ referenceSuggestionLabel : '' ,
119+ references : [ ] ,
120+ onRootCollapsedStateChange : ( ) => { }
121+ } ) . render ) ;
122+
123+ // Render buttons if they exist
124+ const fileListWithButtons = fileList as ChatItemContent [ 'fileList' ] & { buttons ?: ChatItemButton [ ] } ;
125+ const buttons : ChatItemButton [ ] | undefined = fileListWithButtons . buttons ;
126+ if ( Array . isArray ( buttons ) && buttons . length > 0 ) {
127+ const buttonsWrapper = new ChatItemButtonsWrapper ( {
128+ tabId : this . props . tabId ,
129+ buttons,
130+ onActionClick : ( action : ChatItemButton ) => {
131+ MynahUIGlobalEvents . getInstance ( ) . dispatch ( MynahEventNames . BODY_ACTION_CLICKED , {
132+ tabId : this . props . tabId ,
133+ messageId : ( action as any ) . messageId != null ? ( action as any ) . messageId : messageId ,
134+ actionId : action . id ,
135+ actionText : action . text
136+ } ) ;
137+ }
138+ } ) ;
139+ fileGroupWrapper . appendChild ( buttonsWrapper . render ) ;
140+ }
141+
142+ contentWrapper . appendChild ( fileGroupWrapper ) ;
143+ } ) ;
144+ }
145+
146+ public addChatItem ( chatItem : ChatItem ) : void {
147+ if ( chatItem . header ?. fileList != null ) {
148+ this . renderModifiedFiles ( chatItem . header . fileList , chatItem . messageId ) ;
124149 }
125150 }
126151
0 commit comments