# Phase 6 Plan 1: Legacy Chat Analysis & API Documentation Summary

**Documented legacy chat implementation, APIs, and React integration patterns**

**Date:** 2026-01-26
**Status:** Complete
**Commits:** 940009c22, 2cb263542, 14ef88572

---

## Accomplishments

### Task 1: Research Legacy Chat Implementation ✅

**File Created:** `.planning/codebase/CHAT_LEGACY.md`

**Key Findings:**
- Legacy chat uses **React CoffeeScript components** (ChatDialog, ChatWindow) with Reflux state management
- **Multi-channel architecture** supports global, session, and lesson chat
- **Hybrid delivery**: REST API for history, WebSocket (Protocol Buffers) for real-time
- **jQuery + React hybrid**: React for rendering, jQuery for DOM manipulation (scrolling, timeago)
- **Modeless dialogs** via custom layout system (not in jam-ui yet)
- **Unread tracking** only exists for lesson chat (teacher_unread_messages, student_unread_messages flags)
  - ❌ Session chat has NO persistent read/unread tracking
  - ✅ Sidebar badge counts unread messages while chat is closed (resets on open)

**Data Flow Documented:**
- Message send: UI → ChatActions → ChatStore → REST API → WebSocket broadcast → All clients
- Message receive: WebSocket → chatPanel → ChatActions → ChatStore → ChatWindow re-render
- Session lifecycle: Join → fetchHistory → activate channel → enable UI

**Components Analyzed:**
- `ChatDialog.js.jsx.coffee` - Modal wrapper (beforeShow, afterHide hooks)
- `ChatWindow.js.jsx.coffee` - Main UI (tabs, messages, composition, attachments)
- `ChatStore.js.coffee` - Reflux store (multi-channel state, fetch history, send message)
- `ChatActions.js.coffee` - Reflux actions (msgReceived, sendMsg, activateChannel)
- `chatPanel.js` - jQuery sidebar integration (unread badge, infinite scroll)

**Identified Patterns:**
- Channel parsing: `session_123`, `lesson_456`, `global`
- Message format: `{msg_id, sender_id, sender_name, msg, created_at, channel, purpose, ...}`
- Auto-scroll logic: jQuery animate to scrollHeight
- Attachment rendering: purpose field indicates file type (Notation File, JamKazam Recording, etc.)

---

### Task 2: Document Chat API Surface ✅

**File Created:** `.planning/codebase/CHAT_API.md`

**REST Endpoints:**
1. **POST /api/chat** - Create message
   - Params: message, channel, music_session, lesson_session, client_id, target_user
   - Response: message object with id, created_at
   - Access control: validates session/lesson access, blocks school users from global

2. **GET /api/chat** - Get history
   - Params: channel, music_session, lesson_session, limit, page, start (cursor)
   - Response: `{chats: [...], next: cursor}`
   - Orders by created_at DESC (newest first)

**WebSocket Messages:**
- **Type:** CHAT_MESSAGE (Protocol Buffer)
- **Routing:**
  - Session: `session:{session_id}` (excludes sender)
  - Global: `__ALL_ACTIVE_CLIENTS__`
  - Lesson: `user:{user_id}` (teacher + student)
- **Fields:** sender_name, sender_id, msg, msg_id, created_at, channel, lesson_session_id, purpose, attachment_*

**Database Schema:**
```sql
CREATE TABLE chat_messages (
  id VARCHAR(64) PRIMARY KEY,
  user_id VARCHAR(64) REFERENCES users(id),
  music_session_id VARCHAR(64),
  message TEXT NOT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  channel VARCHAR(128) DEFAULT 'session',
  target_user_id VARCHAR(64),
  lesson_session_id VARCHAR(64),
  purpose VARCHAR(200),
  music_notation_id VARCHAR(64),
  claimed_recording_id VARCHAR(64)
);
```

**Indexes:**
- chat_messages_idx_channels (channel)
- chat_messages_idx_created_at (created_at)
- chat_messages_idx_music_session_id (music_session_id)

**Business Logic:**
- HTML sanitization (strips all tags)
- Profanity filter
- Message length validation (1-255 chars)
- School protection: Can only chat with same school (unless platform instructor)
- Email notifications for offline lesson chat recipients

**Missing Functionality:**
- ❌ Read/unread tracking for session/global chat (only exists for lesson chat)
- ❌ Rate limiting
- ❌ Message deletion/editing
- ❌ File attachments for session chat (only lesson chat supported)

---

### Task 3: Analyze React Patterns ✅

**File Created:** `.planning/codebase/CHAT_REACT_PATTERNS.md`

**Available Components:**
- ✅ **WindowPortal** - Modeless popup window (used by Metronome, JamTrack)
  - Auto-copies stylesheets from parent
  - Cross-window message passing (postMessage)
  - Auto-cleanup on close
  - Can be reused AS-IS for chat window

- ✅ **Button/Input patterns** - Standard HTML elements with CSS classes
  - `.button-orange` (primary action)
  - `.button-grey` (secondary action)
  - Standard `<textarea>` with Enter-to-send logic

**Redux State Patterns:**
- ✅ **lobbyChatMessagesSlice.js** - Lobby chat (can be reference)
  - State: `{records: {messages: [], next: null}, status, error}`
  - Async thunks: fetchLobbyChatMessages, postNewChatMessage
  - Sorts messages by created_at, adds status: 'delivered'
  - ❌ No deduplication, no channel switching

- ✅ **textMessagesSlice.js** - 1-on-1 messages (can be reference)
  - Message deduplication by id
  - Restructures server format to local format
  - ❌ No WebSocket integration, no channels

- ✅ **mediaSlice.js** - Async thunk patterns (Backing Track, JamTrack)
  - Error handling: pending/fulfilled/rejected states
  - jamClient integration (native calls)
  - Complex download/packaging logic

- ✅ **activeSessionSlice.js** - Session state
  - Participants, tracks, jamTracks, backingTracks
  - Add/remove/update reducers for real-time updates

- ✅ **sessionUISlice.js** - UI state patterns
  - Window open/close state
  - Unread counts
  - UI-specific state (not data state)

**WebSocket Integration:**
- ✅ **useSessionWebSocket hook** - Registers WebSocket callbacks, dispatches Redux actions
- ✅ **JamServer.js** - EventEmitter wrapper, CHAT_MESSAGE type already defined
- ✅ **JamServerContext** - Provides jamServer instance, connection status

**API Integration:**
- ✅ REST client pattern: `fetch()` with `credentials: 'include'`
- ✅ Async thunk pattern: `createAsyncThunk` with rejectWithValue
- ✅ Existing methods: getLobbyChatMessages, createLobbyChatMessage

**Gaps Identified:**

**Missing Components:**
- ❌ JKSessionChatWindow (main chat UI)
- ❌ JKChatMessageList (scrollable message list)
- ❌ JKChatInput (composition area)
- ❌ JKChatButton (with unread badge)

**Missing Redux:**
- ❌ sessionChatSlice (multi-channel chat state)
- ❌ Channel switching logic
- ❌ Unread tracking per channel
- ❌ Message deduplication by msg_id

**Missing API:**
- ❌ getChatMessages (generic, not lobby-specific)
- ❌ sendChatMessage (generic)
- ❌ markChatAsRead (NEW endpoint - doesn't exist in legacy)

**Missing WebSocket:**
- ❌ CHAT_MESSAGE handler in useSessionWebSocket
- ❌ Unread count increment on message receive

**Missing Utilities:**
- ❌ Timestamp formatting (e.g., "5 minutes ago")
- ❌ Auto-scroll to bottom logic
- ❌ Enter-to-send keyboard handler

**TDD Candidates (per CLAUDE.md):**
- 🧪 sessionChatSlice reducers (add/remove/update messages)
- 🧪 fetchChatHistory async thunk
- 🧪 sendMessage async thunk
- 🧪 Message deduplication logic
- 🧪 Unread count increment/reset logic
- 🧪 CHAT_MESSAGE WebSocket handler
- 🧪 API client methods (getChatMessages, sendChatMessage)
- 🧪 Component behavior tests (send on Enter, auto-scroll, unread badge)

---

## Decisions Made

### 1. Read/Unread Tracking Strategy

**Current State:**
- ✅ Lesson chat: `teacher_unread_messages`, `student_unread_messages` boolean flags in database
- ❌ Session/global chat: No persistent tracking, badge resets on panel open

**Decision for Phase 6:**
- Use **client-side unread tracking** (Redux state + localStorage)
- Store last_read_at timestamp per channel
- Calculate unread count: messages with created_at > last_read_at
- **Benefits:** No schema changes, simpler implementation, cross-device consistency
- **Tradeoff:** Unread counts reset on logout (acceptable for MVP)

**Future Enhancement (next milestone):**
- Server-side tracking with new `chat_message_reads` table
- Per-message read receipts
- Cross-device synchronization

---

### 2. Multi-Channel Architecture

**Decision:**
- Use **keyed message storage** in Redux: `messagesByChannel: { 'session-uuid': [...], 'global': [...] }`
- Store active channel: `activeChannel: 'session-uuid'`
- Store unread counts per channel: `unreadCounts: { 'session-uuid': 3 }`
- Switch channels on session join/leave

**Benefits:**
- Efficient lookups (no filtering)
- Supports multiple sessions (future: multi-session jam)
- Clean separation of global vs session messages

---

### 3. WindowPortal for Chat Dialog

**Decision:**
- Reuse existing **WindowPortal** component for modeless chat window
- No modifications needed (already handles styling, lifecycle, cleanup)
- Matches legacy behavior (repositionable, stays open during session)

**Alternative Considered:**
- Create JKModal component for modal-style dialog
- **Rejected:** WindowPortal is better UX (non-blocking, repositionable)

---

### 4. TDD Approach

**Decision:**
- Follow **TDD for all data layer** (Redux, API, WebSocket)
- Follow **TDD for component behavior** (send message, auto-scroll, unread badge)
- **Skip TDD for styling-only** changes (CSS, layout)

**Rationale:**
- CLAUDE.md requires TDD for jam-ui
- Data layer has clear test criteria (state transitions, API responses)
- Component behavior has measurable outcomes (DOM updates, API calls)
- Styling is visual and hard to test programmatically

---

### 5. File Attachments

**Decision:**
- **Out of scope for Phase 6** (deferred to next milestone)
- Database fields already exist (music_notation_id, claimed_recording_id, purpose)
- Can be added later without breaking changes

**Rationale:**
- Focus on core chat functionality (send, receive, history, unread)
- Attachments only used in lesson chat (not session chat)
- Complex UI and file upload logic

---

## Issues Encountered

### None

All three tasks completed without blockers. The legacy codebase was well-structured and easy to analyze. All necessary files were located and documented.

---

## Key Insights

### 1. Legacy Chat is Feature-Rich

The legacy implementation supports:
- Multi-channel chat (global, session, lesson)
- Lesson-specific features (file attachments, email notifications, unread flags)
- System messages (user activity changes)
- Infinite scroll pagination
- Purpose-based message types (attachments)

**For Phase 6:** We're implementing a **subset** (session chat only, no attachments)

---

### 2. Reflux → Redux Migration

Legacy uses Reflux (Flux architecture), jam-ui uses Redux Toolkit.

**Key Differences:**
- Reflux: `listenTo(Store, callback)` → Redux: `useSelector()`
- Reflux: `Actions.trigger()` → Redux: `dispatch(action)`
- Reflux: `Store.trigger(state)` → Redux: reducers return new state
- Reflux: Manual state updates → Redux: Immer (immutable updates)

**Migration Pattern:**
- ChatActions → async thunks (fetchChatHistory, sendMessage)
- ChatStore → sessionChatSlice (reducers + state)
- listenTo → useSelector hooks

---

### 3. jQuery → React Migration

Legacy uses jQuery for DOM manipulation (scrolling, timeago, menu plugins).

**Migration Strategy:**
- jQuery `$scroller.animate({scrollTop: ...})` → React ref + `scrollTo()`
- jQuery timeago → dayjs relative time formatting
- jQuery event handlers → React event props
- `getDOMNode()` → `useRef()`

---

### 4. Unread Tracking is NEW

**Critical Finding:** Session/global chat has NO persistent read/unread tracking in legacy.

**Implications:**
- We're adding NEW functionality (not porting legacy)
- Need to design from scratch (no legacy patterns to follow)
- Must align with lesson chat patterns (teacher_unread_messages, student_unread_messages)
- Client-side tracking acceptable for MVP (localStorage + Redux)

---

### 5. WebSocket Already Integrated

jam-ui already has robust WebSocket infrastructure:
- JamServer.js handles connection/reconnection
- useSessionWebSocket hook registers callbacks
- CHAT_MESSAGE type already defined
- Pattern established from MIXER_CHANGES, JAM_TRACK_CHANGES

**Implication:** Chat WebSocket integration will be straightforward (add one callback)

---

## Next Phase Readiness

**Phase 6 Plan 2: React Architecture & Implementation Roadmap**

Ready to begin design phase with:
- ✅ Complete understanding of legacy patterns
- ✅ Full API surface documented
- ✅ Available patterns and gaps identified
- ✅ TDD candidates defined
- ✅ Key decisions made (read/unread, multi-channel, WindowPortal)

**Inputs for Plan 2:**
- CHAT_LEGACY.md → Legacy patterns to modernize
- CHAT_API.md → API contracts to implement
- CHAT_REACT_PATTERNS.md → Available patterns and gaps

**Outputs from Plan 2:**
- Redux state design (sessionChatSlice structure)
- Component hierarchy (JKSessionChatWindow, JKChatMessageList, JKChatInput)
- API client design (getChatMessages, sendChatMessage)
- WebSocket integration design (CHAT_MESSAGE handler)
- TDD test plan (unit, integration, E2E)
- Implementation roadmap (Phases 7-11 task breakdown)

---

## Files Created/Modified

**Created:**
- `.planning/codebase/CHAT_LEGACY.md` (679 lines) - Legacy implementation analysis
- `.planning/codebase/CHAT_API.md` (798 lines) - Complete API reference
- `.planning/codebase/CHAT_REACT_PATTERNS.md` (1255 lines) - React pattern analysis and gaps

**Total:** 2,732 lines of documentation

**Commits:**
- `940009c22` - feat(06-01): document legacy chat implementation patterns
- `2cb263542` - feat(06-01): document complete chat API surface
- `14ef88572` - feat(06-01): analyze React patterns and identify chat implementation gaps

---

## Documentation Quality

**Strengths:**
- ✅ Comprehensive coverage (all legacy components analyzed)
- ✅ Code examples and data structures included
- ✅ Clear distinction between what's available and what's missing
- ✅ Actionable recommendations for implementation
- ✅ TDD candidates identified per CLAUDE.md requirements
- ✅ Integration checklist for Phases 7-11

**Future Reference:**
- These documents will serve as primary reference during Phases 7-11
- Can be shared with other developers for onboarding
- Can be used to compare jam-ui implementation with legacy

---

**Summary Complete. Ready for Phase 6 Plan 2: React Architecture & Implementation Roadmap.**
