Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion example/src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,6 @@ export enum Commands {
CLEAR_CONTEXT_ITEMS = '/clear-context-items',
CLEAR_LOGS = '/clear-logs',
SHOW_CUSTOM_FORM = '/show-custom-form',
VOTE = '/vote'
VOTE = '/vote',
MODIFIED_FILES_TRACKER = '/modified-files-tracker'
}
5 changes: 5 additions & 0 deletions example/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ export const tabbarButtons: TabBarMainAction[] = [
text: 'Show code diff!',
icon: MynahIcons.CODE_BLOCK,
},
{
id: 'show-modified-files',
text: 'Show modified files tracker demo',
icon: MynahIcons.FILE,
},
{
id: 'insert-code',
icon: MynahIcons.CURSOR_INSERT,
Expand Down
274 changes: 189 additions & 85 deletions example/src/main.ts

Large diffs are not rendered by default.

174 changes: 173 additions & 1 deletion example/src/samples/sample-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,10 @@ export const defaultFollowUps: ChatItem = {
pillText: 'Sticky card',
command: Commands.SHOW_STICKY_CARD,
},
{
pillText: 'Modified Files Tracker',
command: Commands.MODIFIED_FILES_TRACKER,
},
{
pillText: 'Some auto reply',
prompt: 'Some random auto reply here.',
Expand Down Expand Up @@ -2660,4 +2664,172 @@ export const sampleMCPDetails = (title: string): DetailedList => {
export const sampleRulesList: DetailedList = {selectable: 'clickable', list: [{children: [{id: 'README', icon: MynahIcons.CHECK_LIST,
description: 'README',actions: [{ id: 'README.md', icon: MynahIcons.OK, status: 'clear' }]}]},
{groupName: '.amazonq/rules', childrenIndented: true, icon: MynahIcons.FOLDER , actions: [{ id: 'java-expert.md', icon: MynahIcons.OK, status: 'clear' }], children: [{id: 'java-expert.md', icon: MynahIcons.CHECK_LIST,
description: 'java-expert',actions: [{ id: 'java-expert.md', icon: MynahIcons.OK, status: 'clear' }]}]}]}
description: 'java-expert',actions: [{ id: 'java-expert.md', icon: MynahIcons.OK, status: 'clear' }]}]}]}

// Sample modified files data using the new ModifiedFilesTrackerData structure
export const sampleModifiedFiles = {
title: 'Modified Files',
visible: true,
showUndoAll: true,
showFileCount: true,
initialCollapsed: false,
fileList: {
filePaths: [
'src/components/Button.tsx',
'src/utils/helpers.ts',
'README.md',
'package.json',
'tests/Button.test.tsx'
],
deletedFiles: [
'src/styles/main.scss'
],
details: {
'src/components/Button.tsx': {
visibleName: 'Button.tsx',
icon: MynahIcons.CODE_BLOCK,
status: 'warning' as const, // modified
description: 'Modified component file'
},
'src/utils/helpers.ts': {
visibleName: 'helpers.ts',
icon: MynahIcons.CODE_BLOCK,
status: 'success' as const, // added
description: 'New utility functions'
},
'README.md': {
icon: MynahIcons.DOC,
status: 'warning' as const, // modified
description: 'Updated documentation'
},
'package.json': {
icon: MynahIcons.CODE_BLOCK,
status: 'warning' as const, // modified
description: 'Updated dependencies'
},
'src/styles/main.scss': {
visibleName: 'main.scss',
icon: MynahIcons.CODE_BLOCK,
status: 'error' as const, // deleted
description: 'Removed stylesheet'
},
'tests/Button.test.tsx': {
visibleName: 'Button.test.tsx',
icon: MynahIcons.CHECK_LIST,
status: 'success' as const, // added
description: 'New test file'
}
},
collapsed: false,
hideFileCount: false
}
};

export const sampleModifiedFilesEmpty = {
title: 'Empty State',
visible: true,
showUndoAll: false,
showFileCount: true,
initialCollapsed: false,
fileList: {
filePaths: [],
deletedFiles: [],
details: {},
collapsed: false,
hideFileCount: false
}
};

export const sampleModifiedFilesLarge = {
title: 'Large File Set',
visible: true,
showUndoAll: true,
showFileCount: true,
initialCollapsed: true,
fileList: {
filePaths: [
'src/components/Button.tsx',
'src/utils/helpers.ts',
'README.md',
'package.json',
'tests/Button.test.tsx',
'src/components/Modal.tsx',
'src/components/Input.tsx',
'src/hooks/useLocalStorage.ts',
'src/types/index.ts',
'docs/api.md',
'config/webpack.config.js'
],
deletedFiles: [
'src/styles/main.scss'
],
details: {
'src/components/Button.tsx': {
visibleName: 'Button.tsx',
icon: MynahIcons.CODE_BLOCK,
status: 'warning' as const,
description: 'Modified component file'
},
'src/utils/helpers.ts': {
visibleName: 'helpers.ts',
icon: MynahIcons.CODE_BLOCK,
status: 'success' as const,
description: 'New utility functions'
},
'README.md': {
icon: MynahIcons.DOC,
status: 'warning' as const,
description: 'Updated documentation'
},
'package.json': {
icon: MynahIcons.CODE_BLOCK,
status: 'warning' as const,
description: 'Updated dependencies'
},
'src/styles/main.scss': {
visibleName: 'main.scss',
icon: MynahIcons.CODE_BLOCK,
status: 'error' as const,
description: 'Removed stylesheet'
},
'tests/Button.test.tsx': {
visibleName: 'Button.test.tsx',
icon: MynahIcons.CHECK_LIST,
status: 'success' as const,
description: 'New test file'
},
'src/components/Modal.tsx': {
icon: MynahIcons.CODE_BLOCK,
status: 'success' as const,
description: 'New modal component'
},
'src/components/Input.tsx': {
icon: MynahIcons.CODE_BLOCK,
status: 'warning' as const,
description: 'Modified input component'
},
'src/hooks/useLocalStorage.ts': {
icon: MynahIcons.CODE_BLOCK,
status: 'success' as const,
description: 'New custom hook'
},
'src/types/index.ts': {
icon: MynahIcons.CODE_BLOCK,
status: 'warning' as const,
description: 'Updated type definitions'
},
'docs/api.md': {
icon: MynahIcons.DOC,
status: 'success' as const,
description: 'New API documentation'
},
'config/webpack.config.js': {
icon: MynahIcons.CODE_BLOCK,
status: 'warning' as const,
description: 'Updated webpack configuration'
}
},
collapsed: true,
hideFileCount: false
}
};
47 changes: 47 additions & 0 deletions src/components/chat-item/chat-wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { StyleLoader } from '../../helper/style-loader';
import { Icon } from '../icon';
import { cancelEvent, MynahUIGlobalEvents } from '../../helper/events';
import { TopBarButtonOverlayProps } from './prompt-input/prompt-top-bar/top-bar-button';
import { ModifiedFilesTracker, ModifiedFilesTrackerData } from '../modified-files-tracker';

export const CONTAINER_GAP = 12;
export interface ChatWrapperProps {
Expand Down Expand Up @@ -58,6 +59,8 @@ export class ChatWrapper {
private readonly dragBlurOverlay: HTMLElement;
private dragOverlayVisibility: boolean = true;
private imageContextFeatureEnabled: boolean = false;
private modifiedFilesTracker: ModifiedFilesTracker | null = null;
private readonly modifiedFilesContainer: ExtendedHTMLElement;

constructor (props: ChatWrapperProps) {
StyleLoader.getInstance().load('components/chat/_chat-wrapper.scss');
Expand Down Expand Up @@ -207,6 +210,17 @@ export class ChatWrapper {

this.promptInfo = new ChatPromptInputInfo({ tabId: this.props.tabId }).render;
this.promptStickyCard = new ChatPromptInputStickyCard({ tabId: this.props.tabId }).render;

// Initialize ModifiedFilesTracker container
this.modifiedFilesContainer = DomBuilder.getInstance().build({
type: 'div',
classNames: [ 'mynah-modified-files-container' ]
});

// Listen for modifiedFilesData changes
MynahUITabsStore.getInstance().addListenerToDataStore(this.props.tabId, 'modifiedFilesData', (modifiedFilesData: ModifiedFilesTrackerData) => {
this.updateModifiedFilesTracker(modifiedFilesData);
});
if (Config.getInstance().config.showPromptField) {
this.promptInput = new ChatPromptInput({ tabId: this.props.tabId, onStopChatResponse: this.props?.onStopChatResponse });
this.promptInputElement = this.promptInput.render;
Expand Down Expand Up @@ -310,6 +324,7 @@ export class ChatWrapper {
}
}).render,
this.promptStickyCard,
this.modifiedFilesContainer,
this.promptInputElement,
this.footerSpacer,
this.promptInfo,
Expand Down Expand Up @@ -537,4 +552,36 @@ export class ChatWrapper {
this.dragOverlayContent.style.display = visible ? 'flex' : 'none';
this.dragBlurOverlay.style.display = visible ? 'block' : 'none';
}

private updateModifiedFilesTracker (modifiedFilesData: ModifiedFilesTrackerData | null): void {
if (modifiedFilesData != null) {
if (this.modifiedFilesTracker == null) {
// Create new ModifiedFilesTracker
this.modifiedFilesTracker = new ModifiedFilesTracker({
tabId: this.props.tabId,
modifiedFilesData,
onFileUndo: (filePath: string) => {
MynahUIGlobalEvents.getInstance().dispatch(MynahEventNames.MODIFIED_FILES_FILE_UNDO, {
tabId: this.props.tabId,
filePath
});
},
onUndoAll: () => {
MynahUIGlobalEvents.getInstance().dispatch(MynahEventNames.MODIFIED_FILES_UNDO_ALL, {
tabId: this.props.tabId
});
}
});
this.modifiedFilesContainer.clear();
this.modifiedFilesContainer.insertChild('beforeend', this.modifiedFilesTracker.render);
} else {
// Update existing ModifiedFilesTracker
this.modifiedFilesTracker.updateModifiedFilesData(modifiedFilesData);
}
} else {
// Clear ModifiedFilesTracker
this.modifiedFilesContainer.clear();
this.modifiedFilesTracker = null;
}
}
}
Loading