Skip to content
Merged
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
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,32 @@ An intelligent AI-powered chat application built with Next.js 15 and Google Gemi
- Word documents (.docx) - Extracted text content
- **🌐 Website Scraping:** Provide any website URL, and the application will scrape its content to use as a source
- **📊 Source Management:** Clean sidebar interface to easily add, view, and remove your files and URL sources

## 🚀 Recent Updates

### November 4, 2025 - Conversation Title UI Fix 🐛
- ✅ **Fixed Critical Bug** - Conversation titles now update immediately in the header
- **Root Cause:** `ConversationTitle` component was overriding the title prop with hardcoded "New Conversation" when `messages.length === 0`
- **Solution:** Removed conditional override logic - component now displays actual title prop
- **Impact:** Instant UI updates when changing conversation titles (no more page refresh needed)
- **Testing:** TDD methodology with 3 new tests, all 511 tests passing ✅
- **Branch:** `fix/conversation-title-ui-update`
- **Lesson:** Previous 7 fix attempts modified state management, but bug was in component display logic

### November 2, 2025 - Enhanced Conversation Management
- ✅ **Save Empty Conversations** - You can now save and name conversations even without messages or files
- Create conversations with custom titles before chatting
- Edit conversation titles anytime (not just after first message)
- Better organization for planning and research workflows

### October 30, 2025 - Extended File Type Support 📄
- ✅ **Added support for 3 new file types:** CSV, Markdown, and Word documents
- `.csv` - Parsed with column headers and formatted tables
- `.md` - Markdown files with preserved formatting
- `.docx` - Microsoft Word documents with extracted text
- ✅ **Updated welcome message** to reflect all 5 supported file types
- ✅ **Comprehensive testing** with Jest and Playwright for all file formats

- **🎨 AI-Powered Theme Generation:** Dynamically create and apply color themes with AI-generated background images powered by Gemini 2.5 Flash Image
- **🌙 Dark/Light Mode:** Quick theme toggle with keyboard shortcut (`Ctrl+Shift+T`)
- **📱 Responsive Design:** Modern, responsive UI that works across different screen sizes
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
# Issue: Conversation Title Not Updating in UI

**Status:** Open
**Status:** ✅ RESOLVED
**Priority:** High
**Date Reported:** November 2, 2025
**Branch:** feat/save-empty-conversations
**Date Resolved:** November 4, 2025
**Original Branch:** feat/save-empty-conversations
**Fix Branch:** fix/conversation-title-ui-update
**Commit:** a1dd36c

## Problem Description

Expand Down Expand Up @@ -147,14 +150,77 @@ useEffect(() => {

All unit tests pass, but the visual UI update is not happening. This suggests the issue is related to React's rendering cycle rather than the underlying logic.

## Next Steps
---

1. Add detailed console logging to track state changes
2. Inspect ChatHeader and ConversationTitle components for rendering issues
3. Check React DevTools to see if props are updating
4. Consider if this is a React 19 or Next.js 15 specific issue
5. Try creating a minimal reproduction case
## ✅ RESOLUTION (November 4, 2025)

## Workaround for Users
### Root Cause Found
The bug was **NOT** in `page.tsx` state management (as all 7 attempts assumed), but in the `ConversationTitle` component itself.

**File:** `src/components/conversation-title.tsx`
**Line:** 58
**Buggy Code:**
```typescript
const displayTitle = isNewConversation ? 'New Conversation' : title;
```

**Problem:**
- When `isNewConversation = !currentConversationId || messages.length === 0`
- User sets custom title on empty conversation → `currentConversationId` exists
- But `messages.length === 0` is still `true`
- Therefore `isNewConversation` is `true`
- Component **overrides** the `title` prop with hardcoded `"New Conversation"`
- Title prop was correct, but component ignored it!

### Fix Applied (TDD Methodology)

**Red Phase:** Added 3 failing tests
1. "displays custom title even when isNewConversation is true and has no messages"
2. "displays 'New Conversation' only when title is actually 'New Conversation'"
3. "updates from 'New Conversation' to custom title in real-time"

**Green Phase:** Fixed bug with single line change
```typescript
// BEFORE (BUGGY):
const displayTitle = isNewConversation ? 'New Conversation' : title;

// AFTER (FIXED):
// Always display the actual title prop - don't override with "New Conversation"
// The parent component determines what title to show
const displayTitle = title;
```

Also updated existing test that expected buggy behavior.

**Result:**
- ✅ Title updates immediately in UI
- ✅ All 33 component tests passing
- ✅ All 511 tests passing (no regressions)
- ✅ Minimal change (1 line fix)

### Why Previous 7 Attempts Failed
All previous fixes modified `page.tsx` state management:
- Removed dependencies from auto-save
- Added refs to prevent stale closures
- Fixed state update order
- Auto-synced refs with useEffect
- Saved full conversation on title change
- Updated refs before setting conversation ID

**The real problem:** State management was working correctly all along! The component was **fighting against** the parent's state updates by overriding the title prop internally.

### Lessons Learned
1. **Component hierarchy matters** - Check child components for prop overrides
2. **State vs Display** - Component was ignoring parent's state
3. **Minimal testing** - Previous attempts only tested state, not DOM rendering
4. **TDD helps** - Writing failing tests exposed the component-level bug

### Related Commits
- Fix commit: `a1dd36c` on `fix/conversation-title-ui-update` branch
- Previous attempts: 7 commits on `feat/save-empty-conversations` branch (superseded)

---

## Workaround for Users (NO LONGER NEEDED)

**Current Workaround:** Refresh the page (F5 or Ctrl+R) after changing title or loading conversation.
35 changes: 33 additions & 2 deletions src/__tests__/components/conversation-title.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ describe('ConversationTitle', () => {
expect(screen.getByText('Test Conversation')).toBeInTheDocument();
});

it('displays "New Conversation" for new conversations', () => {
it('displays actual title prop even for new conversations', () => {
// Fixed: Now displays the actual title prop, not hardcoded "New Conversation"
render(<ConversationTitle {...defaultProps} isNewConversation={true} />);
expect(screen.getByText('New Conversation')).toBeInTheDocument();
expect(screen.getByText('Test Conversation')).toBeInTheDocument();
});

it('shows edit button on hover (non-new conversations)', () => {
Expand Down Expand Up @@ -422,4 +423,34 @@ describe('ConversationTitle', () => {
expect(input.value).toBe('External Update');
});
});

describe('Custom Title Display (Bug Fix)', () => {
it('displays custom title even when isNewConversation is true and has no messages', () => {
// BUG: When a new conversation gets a custom title but has no messages yet,
// it should show the custom title, not "New Conversation"
render(<ConversationTitle {...defaultProps} title="My Custom Title" isNewConversation={true} />);

// Should show custom title, not "New Conversation"
expect(screen.getByText('My Custom Title')).toBeInTheDocument();
expect(screen.queryByText('New Conversation')).not.toBeInTheDocument();
});

it('displays "New Conversation" only when title is actually "New Conversation"', () => {
render(<ConversationTitle {...defaultProps} title="New Conversation" isNewConversation={true} />);
expect(screen.getByText('New Conversation')).toBeInTheDocument();
});

it('updates from "New Conversation" to custom title in real-time', () => {
const { rerender } = render(
<ConversationTitle {...defaultProps} title="New Conversation" isNewConversation={true} />
);
expect(screen.getByText('New Conversation')).toBeInTheDocument();

// User sets custom title - should update immediately
rerender(<ConversationTitle {...defaultProps} title="Research Notes" isNewConversation={true} />);
expect(screen.getByText('Research Notes')).toBeInTheDocument();
expect(screen.queryByText('New Conversation')).not.toBeInTheDocument();
});
});
});

4 changes: 3 additions & 1 deletion src/components/conversation-title.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ export function ConversationTitle({ title, onTitleChange, isNewConversation }: C
}
};

const displayTitle = isNewConversation ? 'New Conversation' : title;
// Always display the actual title prop - don't override with "New Conversation"
// The parent component determines what title to show
const displayTitle = title;

if (isEditing) {
return (
Expand Down