diff --git a/README.md b/README.md index 805c084..9b71abc 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/docs/04-development/issues/conversation-title-not-updating-in-ui.md b/docs/04-development/issues/conversation-title-not-updating-in-ui.md index 03a5f65..c7bd0e8 100644 --- a/docs/04-development/issues/conversation-title-not-updating-in-ui.md +++ b/docs/04-development/issues/conversation-title-not-updating-in-ui.md @@ -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 @@ -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. diff --git a/src/__tests__/components/conversation-title.test.tsx b/src/__tests__/components/conversation-title.test.tsx index 65f230c..80832bb 100644 --- a/src/__tests__/components/conversation-title.test.tsx +++ b/src/__tests__/components/conversation-title.test.tsx @@ -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(); - expect(screen.getByText('New Conversation')).toBeInTheDocument(); + expect(screen.getByText('Test Conversation')).toBeInTheDocument(); }); it('shows edit button on hover (non-new conversations)', () => { @@ -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(); + + // 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(); + expect(screen.getByText('New Conversation')).toBeInTheDocument(); + }); + + it('updates from "New Conversation" to custom title in real-time', () => { + const { rerender } = render( + + ); + expect(screen.getByText('New Conversation')).toBeInTheDocument(); + + // User sets custom title - should update immediately + rerender(); + expect(screen.getByText('Research Notes')).toBeInTheDocument(); + expect(screen.queryByText('New Conversation')).not.toBeInTheDocument(); + }); + }); }); + diff --git a/src/components/conversation-title.tsx b/src/components/conversation-title.tsx index 872c238..d8762cf 100644 --- a/src/components/conversation-title.tsx +++ b/src/components/conversation-title.tsx @@ -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 (