Commit Graph

8219 Commits

Author SHA1 Message Date
Nuwan 0144a984d0 docs(7): create phase 7 plans
Create 3 TDD-focused plans for Phase 7 (Chat Infrastructure & State Management):
- Plan 7.1: Redux Slice & Core Reducers (7 reducers, message deduplication, unread tracking)
- Plan 7.2: Async Thunks & API Integration (REST methods, fetchChatHistory, sendMessage with optimistic updates)
- Plan 7.3: WebSocket Integration & Selectors (CHAT_MESSAGE handler, 8 memoized selectors, localStorage persistence)

All plans follow TDD methodology per CLAUDE.md requirements (RED-GREEN-REFACTOR).
Total: 10-12 tasks estimated for Phase 7.

Phase 7 builds Redux foundation for chat feature following patterns from Phase 5 (JamTrack).
Ready for execution with /gsd:execute-plan commands.
2026-01-27 08:00:21 +05:30
Nuwan a5aef4bbb4 docs(06-02): complete react architecture design plan
Phase 6 Plan 2 complete - React architecture designed for Phases 7-11:

Summary:
- All 3 tasks completed successfully
- 3 design documents created (3,224 lines total)
- Component architecture, Redux state, and implementation roadmap ready
- Phase 6 complete, ready for Phase 7

Design Documents Created:
- CHAT_COMPONENT_DESIGN.md (954 lines): 8 components, WindowPortal integration, auto-scroll logic
- CHAT_REDUX_DESIGN.md (1,132 lines): sessionChatSlice, 3 async thunks, 8 selectors, WebSocket integration
- IMPLEMENTATION_ROADMAP.md (1,138 lines): 11-13 plans for Phases 7-11, risk analysis, TDD strategy

Key Architectural Decisions:
- Component hierarchy: JKSessionChatWindow (WindowPortal) with 6 sub-components
- Props vs Redux: Heavy Redux usage (minimal props)
- Auto-scroll: Track isUserScrolling, disable when scrolled up
- Multi-channel state: messagesByChannel keyed by channel ID
- Read/unread tracking: Client-side with localStorage (NEW functionality)
- Message deduplication: By msg_id in Redux reducer
- WebSocket integration: CHAT_MESSAGE handler in useSessionWebSocket

Redux Architecture:
- sessionChatSlice (new): 7 reducers, 3 async thunks, 8 memoized selectors
- Reducers: addMessageFromWebSocket, openChatWindow, markAsRead, etc.
- Thunks: fetchChatHistory, sendMessage, markMessagesAsRead (future)
- Selectors: selectChatMessages, selectUnreadCount, selectTotalUnreadCount, etc.

Implementation Roadmap (Phases 7-11):
- Phase 7: Chat Infrastructure (3 plans) - Redux, API, WebSocket
- Phase 8: Chat UI (3 plans) - Window, MessageList, Button
- Phase 9: Message Composition (2 plans) - Composer, Send/Receive
- Phase 10: Read/Unread Tracking (2 plans) - Badge, Channel Switching
- Phase 11: Finalization (3 plans) - Error Handling, Performance, UAT

Risk Analysis:
- 2 HIGH: WebSocket deduplication, localStorage persistence
- 4 MEDIUM: Auto-scroll, multi-tab sync, API errors, WindowPortal styling
- 2 LOW: Character count, timestamp formatting

TDD Strategy:
- Phase 7: 100% TDD (data layer)
- Phase 8-10: 50-100% TDD (behavior)
- Phase 11: 70% TDD (error handling)

Testing Strategy:
- Unit tests: 80%+ coverage (Redux, API, WebSocket)
- Integration tests: 7 test files (window, send, receive, badge, scroll, channel, errors)
- E2E tests: Complete workflow + multi-user
- UAT: 40+ test cases across 9 categories

Deferred Features (Next Milestone):
- Server-side read/unread tracking
- File attachments
- Message search/filtering
- Message editing/deletion
- Typing indicators
- Emoji picker
- Multi-channel tabs
- Notification sounds
- Desktop notifications

Updated STATE.md and ROADMAP.md to reflect Phase 6 completion.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-26 15:55:22 +05:30
Nuwan df87713ff1 feat(06-02): create implementation roadmap for Phases 7-11
Create comprehensive implementation roadmap for session chat:

Phase Breakdown (11-13 plans estimated):
- Phase 7: Chat Infrastructure & State Management (3 plans)
  - 7.1: Redux Slice & Core Reducers (TDD)
  - 7.2: Async Thunks & API Integration (TDD)
  - 7.3: WebSocket Integration & Selectors (TDD)
- Phase 8: Chat Window UI & Message Display (3 plans)
  - 8.1: Chat Window Shell & WindowPortal Integration
  - 8.2: Message List & Auto-Scroll
  - 8.3: Chat Button & Unread Badge
- Phase 9: Message Composition & Sending (2 plans)
  - 9.1: Message Composer & Validation (TDD)
  - 9.2: Send Message & Real-Time Delivery (TDD)
- Phase 10: Read/Unread Status Management (2 plans)
  - 10.1: Unread Tracking & Badge Updates (TDD)
  - 10.2: Channel Switching & Read State Sync
- Phase 11: Chat Finalization & Polish (3 plans)
  - 11.1: Error Handling & Retry Logic
  - 11.2: Performance Optimization & Accessibility
  - 11.3: UAT & Final Integration Testing

Risk Analysis:
- 2 HIGH risks: WebSocket deduplication, localStorage persistence
- 4 MEDIUM risks: Auto-scroll conflicts, multi-tab sync, API errors, WindowPortal styling
- 2 LOW risks: Character count validation, timestamp formatting

TDD Strategy:
- Phase 7: 100% TDD (all data layer)
- Phase 8: 50% TDD (component behavior, skip styling)
- Phase 9: 100% TDD (composition logic)
- Phase 10: 100% TDD (unread tracking)
- Phase 11: 70% TDD (error handling, skip performance)

Testing Strategy:
- Unit tests: 80%+ coverage (Redux, API, WebSocket)
- Integration tests: 7 test files (window, send, receive, badge, scroll, channel, errors)
- E2E tests: Complete workflow + multi-user scenario
- UAT: 40+ test cases across 9 categories

Complexity Estimation:
- 1.5-2x more complex than Backing Track (Phase 3: 3 plans)
- 0.6x less complex than JamTrack (Phase 5: 9 plans)
- Estimated 11-13 plans, 28-32 tasks total

Critical Decisions:
- Message virtualization: Defer until needed
- Optimistic UI updates: Implement for better UX
- localStorage persistence: Store lastReadAt timestamps
- Multi-tab sync: Defer to next milestone
- Auto-scroll strategy: Track scroll position (smart)

Deferred Features (Next Milestone):
- Server-side read/unread tracking
- File attachments
- Message search/filtering
- Message editing/deletion
- Typing indicators
- Emoji picker
- Multi-channel tabs
- Notification sounds
- Desktop notifications

Dependency graph and success metrics documented.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-26 15:52:21 +05:30
Nuwan 3206c12685 feat(06-02): design Redux state and WebSocket integration for chat
Create comprehensive Redux architecture for session chat:

Redux State Structure:
- sessionChatSlice with multi-channel message storage
- messagesByChannel keyed by channel ID (efficient lookup)
- unreadCounts per channel (NEW functionality)
- lastReadAt timestamps for read tracking
- fetchStatus/sendStatus per channel

Async Thunks (3):
- fetchChatHistory: Load message history via REST API
- sendMessage: Send new message with optimistic update
- markMessagesAsRead: Mark as read (future server-side tracking)

Reducers (7):
- addMessageFromWebSocket: Handle real-time messages, deduplicate by msg_id
- setActiveChannel: Switch between global/session/lesson
- openChatWindow: Reset unread count, mark as read
- closeChatWindow: Close window state
- markAsRead: Client-side read tracking with localStorage persistence
- incrementUnreadCount: Increment on message receive
- setWindowPosition: Save window position

Selectors (8 memoized):
- selectChatMessages, selectUnreadCount, selectTotalUnreadCount
- selectIsChatWindowOpen, selectActiveChannel
- selectFetchStatus, selectSendStatus, selectSendError

WebSocket Integration:
- CHAT_MESSAGE handler in useSessionWebSocket
- Protocol Buffer to Redux format conversion
- Unread count increment logic (if window closed)
- Message deduplication by msg_id

Read/Unread Tracking System (NEW):
- Client-side tracking with localStorage persistence
- lastReadAt timestamp per channel
- Unread count calculation on message receive
- Reset on window open / channel switch
- Server-side tracking deferred to future milestone

Error Handling:
- API errors: 404, 403, 422, 500
- WebSocket errors: Connection lost, duplicate messages
- Retry logic and user feedback

Testing Strategy:
- Unit tests: Reducers, async thunks, deduplication logic
- Integration tests: Send/receive flow, unread badge behavior

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-26 15:48:44 +05:30
Nuwan 192703f592 feat(06-02): design session chat component architecture
Create comprehensive component design for session chat following JamTrack
and Backing Track patterns:

- 8 components: JKSessionChatButton, JKSessionChatWindow, 6 sub-components
- WindowPortal integration for modeless dialog (reuse existing)
- Props vs Redux decision matrix (heavy Redux, minimal props)
- Auto-scroll logic for message list
- Enter-to-send keyboard handling for composer
- Integration plan with JKSessionScreen
- Component lifecycle patterns documented
- Testing strategy defined (unit, integration, E2E)

Component hierarchy:
- JKSessionChatButton (top nav with unread badge)
- JKSessionChatWindow (WindowPortal wrapper)
  - JKChatHeader
  - JKChatMessageList (with auto-scroll)
    - JKChatMessage (avatar, name, text, timestamp)
    - JKChatLoadingSpinner
    - JKChatEmptyState
  - JKChatComposer (textarea + send button)

File structure: jam-ui/src/components/client/chat/

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-26 15:46:15 +05:30
Nuwan d839be3ca4 docs(06-01): complete legacy chat analysis plan
Summary of accomplishments:
- Created 3 comprehensive documentation files (2,732 lines total)
- CHAT_LEGACY.md: Legacy implementation patterns
- CHAT_API.md: Complete API surface documentation
- CHAT_REACT_PATTERNS.md: React patterns and gap analysis

Key findings:
- Multi-channel architecture (global, session, lesson)
- Hybrid delivery (REST + WebSocket Protocol Buffers)
- Read/unread tracking is NEW (not in legacy session chat)
- WindowPortal available for modeless dialog
- TDD candidates identified per CLAUDE.md

Ready for Phase 6 Plan 2: React Architecture Design

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-26 15:26:10 +05:30
Nuwan 14ef885721 feat(06-01): analyze React patterns and identify chat implementation gaps
- Document available components (WindowPortal, buttons, inputs)
- Analyze Redux state patterns (existing chat slices, media patterns)
- Map WebSocket integration (useSessionWebSocket hook, JamServer)
- Document API integration patterns (REST client, async thunks)
- Identify gaps (missing components, Redux slices, API methods)
- Define TDD candidates per CLAUDE.md requirements
- Provide implementation roadmap for Phases 7-11

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-26 15:23:41 +05:30
Nuwan 2cb263542e feat(06-01): document complete chat API surface
- Map REST endpoints (create, index) with request/response formats
- Document WebSocket Protocol Buffer messages
- Capture database schema and ActiveRecord model
- Identify security, validation, and access control
- Document data flow and routing patterns
- Note missing functionality (read/unread tracking)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-26 15:20:17 +05:30
Nuwan 940009c22d feat(06-01): document legacy chat implementation patterns
- Analyze React CoffeeScript components (ChatDialog, ChatWindow)
- Document Reflux state management (ChatStore, ChatActions)
- Map jQuery sidebar integration (chatPanel.js)
- Capture message flow and data structures
- Identify UI patterns and integration points
- Note quirks and modernization opportunities

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-26 15:17:26 +05:30
Nuwan eca7f95c23 docs(6): create phase plan
Phase 6: Session Chat Research & Design
- 2 plans created
- 6 total tasks defined (3 per plan)
- Ready for execution

Plan 1: Legacy Chat Analysis & API Documentation
Plan 2: React Architecture & Implementation Roadmap
2026-01-26 15:04:31 +05:30
Nuwan 3f9602346c docs(6): capture phase context
Phase 6: Session Chat Research & Design
- Vision and goals documented
- Essential requirements identified
- Scope boundaries defined
2026-01-26 14:58:07 +05:30
Nuwan 38a9361d75 docs: create milestone v1.1 Music Session Chat (6 phases)
Phases:
- 6. Session Chat Research & Design: Explore legacy implementation, design React patterns
- 7. Chat Infrastructure & State Management: Redux state, WebSocket handlers, API integration
- 8. Chat Window UI & Message Display: Modeless dialog, message list with user info
- 9. Message Composition & Sending: Text input, send functionality, real-time delivery
- 10. Read/Unread Status Management: Unread tracking, indicator badge, mark-as-read logic
- 11. Chat Finalization: Error handling, edge cases, performance optimization
2026-01-26 09:29:35 +05:30
Nuwan 78c523204e chore: remove phase 6 (Metronome Research & Design) 2026-01-26 08:59:57 +05:30
Nuwan aa129fed56 chore: remove phase 7 (Metronome Implementation) 2026-01-26 08:57:48 +05:30
Nuwan 73ac37b97b Merge branch '5670-session_screen_base' of ssh://altssh.bitbucket.org:443/jamkazam/jam-cloud into 5670-session_screen_base 2026-01-25 14:08:43 +05:30
Nuwan c3eb6b7d1a fix: enable VU meter updates by calling SetVURefreshRate
VU meters were not lighting up because the native audio client was
never told to start sending VU data. This fix adds the SetVURefreshRate(150)
call when joining a session to enable VU updates every 150ms.

Also adds a ref pattern in useMixerStore to prevent potential stale
closure issues in the handleBridgeCallback VU callback handler.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-25 14:07:48 +05:30
Nuwan d8ae60e251 add test data files 2026-01-25 14:07:29 +05:30
Nuwan 091af31bb4 feat: redesign metronome popup controls and fix WindowPortal styling
Metronome Popup Redesign:
- Replace Apply button with Play/Stop circular icon buttons
- Change BPM from slider to dropdown with common BPM values (40-300)
- Update layout: Play/Stop buttons on left, form controls on right
- Add real-time updates: changes apply immediately when metronome is playing
- Use SessionStopPlay instead of SessionCloseMetronome to preserve state
- Center Close button at bottom with minimal styling

WindowPortal CSS Fix:
- Copy all stylesheets from parent window to popup window
- Support both <link> and <style> elements
- Fix issue where popup windows didn't inherit parent styles

Session Screen Improvements:
- Fix metronome auto-start issue: stop playback immediately after initialization
- Add SetVURefreshRate call to enable VU meter updates
- Update metronome opening to not play audio until user clicks Play

Design matches user-provided screenshot with minimal, clean styling.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-25 14:02:06 +05:30
Nuwan 3887f4fdda feat: update metronome track layout and improve test infrastructure
- Change metronome track to horizontal layout: VU meter on left, volume slider on right
- Add three dots menu button without diagnostics circle (metronome doesn't need diagnostics)
- Move Close functionality to three dots menu dropdown
- Update test selectors to match new layout (.track-title, .track-menu-button)
- Add jamClient mocking in tests to prevent hanging on native client calls
- Increase test timeout to 60s to accommodate session creation time
- Configure global test setup to use existing user accounts instead of creating new ones
- Add conditional fake client support in JamClientContext for test environments

Tests: 3 passed, 2 skipped (as expected)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-25 13:59:29 +05:30
Nuwan a2be53bc0d feat: redesign metronome controls popup with improved UX
Complete redesign of metronome controls popup based on user requirements:

UI Changes:
- Added Play/Stop buttons at top for clear playback control
- Replaced BPM slider with dropdown (40-300, steps of 4)
- Reorganized layout: labels on left, controls on right
- Moved Close button to bottom center
- Removed Apply button - changes apply in real-time when playing

Functionality:
- Play button starts metronome with current settings
- Stop button stops metronome playback
- All control changes (sound, tempo, meter) apply immediately when playing
- Metronome track initializes on open but remains silent until Play is clicked
- Improved visual hierarchy and spacing

CSS Updates:
- New playback controls styling with hover states
- Form grid layout for aligned labels/controls
- Enhanced button and dropdown styling with better focus states
- Cleaner, more modern appearance

Tests:
- All 3 existing tests still pass
- UI improvements don't break test selectors
- Metronome track appears correctly on open

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-25 07:50:03 +05:30
Nuwan 9229d3fe8c fix: prevent metronome from auto-starting when opening controls
The metronome was starting immediately when opening the controls popup,
which is incorrect behavior. Users should explicitly click the Apply
button to start the metronome.

Changes:
- Removed SessionOpenMetronome() call from handleMetronomeSelected
- Metronome controls now show without starting audio
- Apply button calls SessionSetMetronome() to start/update metronome
- Subsequent opens still don't auto-start

Behavior:
- Open metronome → Controls appear, no audio
- Click Apply → Metronome starts with chosen settings
- Close & reopen → Controls appear, no auto-start

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-25 07:15:17 +05:30
Nuwan 746cfd72fa test: add Playwright tests for metronome functionality
Add comprehensive test suite for metronome feature including:
- Opening metronome from Open menu
- Displaying metronome track with VU meter and gain controls
- Closing metronome from main window
- Helper function for opening metronome in tests
- Documentation for test suite

Tests verify core metronome UI behavior and user interactions.
WindowPortal popup tests are skipped due to complexity (manual testing recommended).

Test results:
- 3 tests passing
- 2 tests skipped (popup window controls)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-23 19:31:03 +05:30
Nuwan b29a8b6ac1 fix: enable VU meter updates by calling SetVURefreshRate
VU meters were not lighting up because the native audio client was
never told to start sending VU data. This fix adds the SetVURefreshRate(150)
call when joining a session to enable VU updates every 150ms.

Also adds a ref pattern in useMixerStore to prevent potential stale
closure issues in the handleBridgeCallback VU callback handler.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-23 18:47:52 +05:30
Nuwan ad12d4030a chore: untrack .claude/settings.local.json from version control
Removed .claude/settings.local.json from git tracking since it's now
in .gitignore. The file will remain on disk but won't be tracked by git.

This completes the setup to keep user-specific Claude Code settings local.
2026-01-23 15:47:20 +05:30
Nuwan d9f697de7b chore: add Claude Code local settings to .gitignore
Added .claude/settings.local.json to .gitignore to prevent user-specific
Claude Code CLI settings from being committed to version control.

These settings contain local paths and session-specific permissions that
are unique to each developer's environment.
2026-01-23 15:46:10 +05:30
Nuwan b5f7f25698 test: add Playwright test infrastructure for session flow verification
Added comprehensive test infrastructure to verify session join flow and
track sync implementation:

Test Configuration:
- playwright.chrome.config.ts: Chrome-specific test configuration
- playwright.verification.config.ts: Verification test settings

Test Documentation:
- IMPLEMENTATION_APPROACH.md: TDD approach for trackSync
- JAM_UI_TESTING_PLAN.md: Overall testing strategy

Test Utilities:
- api-interceptor.ts: Intercepts and logs API calls
- websocket-monitor.ts: Monitors WebSocket messages
- sequence-comparator.ts: Compares API call sequences
- test-helpers.ts: Shared test helper functions

Test Suites:
- e2e/complete-session-flow.spec.ts: Full session flow E2E test
- api-verification/*.spec.ts: API call verification tests
- websocket-verification/ws-connection.spec.ts: WebSocket tests
- capture-session-flow*.spec.ts: Session flow analysis tests

Test Fixtures & Results:
- fixtures/legacy-sequences/: Recorded API call sequences
- test-results/: Test output, comparisons, and analysis

These tests were instrumental in debugging the VU meter issue and
verifying the trackSync implementation.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-23 15:42:35 +05:30
Nuwan 23594959f3 docs: add VU meter fix documentation and test results
Added comprehensive documentation of the VU meter race condition fix:
- VU_METER_FIX_SUMMARY.md: Detailed root cause analysis and solution
- VU_METER_INVESTIGATION.md: Updated with test results

Documents the race condition between trackSync and mixer initialization,
the solution using mixersReady dependency, and testing evidence.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-23 14:57:39 +05:30
Nuwan 5645284511 fix: resolve VU meter race condition by waiting for mixers ready
Fixed issue where VU meters were not lighting up on session join due to
a race condition between mixer initialization and track sync.

## Root Cause
When hasJoined became true, both the mixer initialization effect and the
trackSync effect would fire simultaneously. TrackSync was executing before
mixers were fully organized, causing isReady to still be false when VU
updates started coming in. This resulted in all VU updates being rejected.

## Solution
1. Added mixersReady dependency to trackSync effect in JKSessionScreen
2. TrackSync now waits until mixers are fully initialized before scheduling
   API calls
3. This ensures proper happens-before relationship:
   Session joined → Mixers fetched → organizeMixers → isReady=true → TrackSync

## Changes
- JKSessionScreen.js: Added mixersReady selector and dependency
- useMixerHelper.js: Added minimal logging for isReady state changes
- trackSyncService.js: Changed to accept clientId string instead of jamClient
  - Fixes "Client ID not available" issue by using server.clientId
- trackSyncService.test.js: Updated tests to pass clientId directly

## Testing
Verified VU meters now light up correctly within 1-2 seconds of session join.
TrackSync still executes at 1s, 1.4s, and 6s as expected.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-23 14:55:45 +05:30
Nuwan 68f9eb607b Merge branch 'feature/track-sync-implementation' into session_migration_plan 2026-01-23 13:36:35 +05:30
Nuwan b5850e2aec docs: add VU meter investigation documentation
- Document soft reset process to isolate trackSync impact
- Preserve verification results
- Add testing instructions for VU meter functionality
2026-01-23 13:35:47 +05:30
Nuwan e48048ac4e WIP: Track sync implementation with TDD approach
- Implemented trackSyncService with full test coverage
- Added 13 unit tests (all passing)
- Added 7 integration tests
- Wired up track sync in session join, instrument change, and media actions
- Fixed jamClient.clientID() async call issue
- Fixed hasJoined vs sessionJoined property mismatch

Note: Rails API endpoint PUT /api/sessions/:id/tracks still needs implementation
Note: Investigating VU meter issue that may be unrelated to this feature
2026-01-23 12:28:40 +05:30
Nuwan 4d141c93c0 feat: integrate metronome UI into session screen
Adds metronome display to JKSessionScreen:
- Imports JKSessionMetronome and JKSessionMetronomePlayer
- Redux selector for metronomeTrackMixers
- handleMetronomeClose callback with jamClient.SessionCloseMetronome
- Metronome track section (conditional on metronomeState.isOpen)
- WindowPortal popup for metronome controls

Updates handleMetronomeSelected to call updateMetronomeState
immediately when metronome opens, triggering popup display.

Completes full metronome feature: popup + track display + audio.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-16 19:05:35 +05:30
Nuwan fc3bbeeafe feat: implement mixer categorization by group_id
Adds useEffect to categorize mixers into track-specific arrays:
- metronomeTrackMixers (group_id: 16)
- backingTrackMixers (group_id: 11)
- jamTrackMixers (group_id: 12)
- recordingTrackMixers (group_id: 13)
- adhocTrackMixers (other types)

Each mixer categorized as {master, personal, mixer} pair.
Dispatches to Redux for component consumption.

Resolves TODO at line 243 about groupMixersByType logic.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-16 19:05:27 +05:30
Nuwan be3d39bff6 feat: add metronome track display component
Implements JKSessionMetronome track strip for session screen with:
- Metronome icon with fallback
- Horizontal VU meters (SessionTrackVU)
- Vertical volume fader (SessionTrackGain)
- Close button

Follows JKSessionBackingTrack pattern for consistency.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-16 19:05:19 +05:30
Nuwan fa5f8c97cb feat: add metronome player popup component
Implements JKSessionMetronomePlayer with controls for:
- Tempo slider/input (BPM: 40-300)
- Sound selector (Beep, Click, Kick, Snare, etc.)
- Meter selector (1-12)
- Visual metronome toggle (Cricket)
- Apply and Close buttons

Supports both WindowPortal popup mode and Modal fallback.
Uses jamClient.SessionSetMetronome to apply settings.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-16 19:05:13 +05:30
Nuwan 4fa9ed17fd fix(05-03): prevent tracks from disappearing when metronome clicked
Fixed critical bug where all tracks (Audio Inputs and Session Mix) disappeared
when user clicked "Open" → "Metronome".

Root cause: useEffect in JKSessionScreen.js depended on entire sessionHelper
object, which got new reference whenever currentSession updated (including when
metronome_open flag changed). This triggered unnecessary onSessionChange() calls
that refetched all mixers, causing race condition where myTracks became empty.

Changes:
1. **JKSessionScreen.js (line 540)**: Changed useEffect dependency from
   `sessionHelper` to `sessionHelper.id()` (primitive value that only changes
   when session ID changes, not on metadata updates)

2. **useMixerHelper.js (lines 63, 388-396, 453-454)**: Added previousMyTracksRef
   to store last known good myTracks. Returns previous value instead of empty
   array when allMixers is temporarily empty during state transitions.

3. **useMixerStore.js (lines 198-201, 213-220, 231)**: Added verification logging
   to confirm onSessionChange is not called unnecessarily. Can be removed after
   testing confirms fix works.

Expected behavior after fix:
-  Tracks DO NOT disappear when metronome clicked
-  onSessionChange only called on initial session join, not on metadata updates
-  Audio Inputs and Session Mix remain visible throughout metronome operations
-  Backing tracks and jam tracks still work correctly (regression test)

NOTE: This fix does NOT implement metronome UI display. Metronome audio will
play but no mixer controls will appear in session screen. That can be added
later as separate task.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-16 16:39:20 +05:30
Nuwan d264241c78 chore(05-03): clean up debug logging after finding root cause 2026-01-16 13:14:12 +05:30
Nuwan 56573c6db7 fix(05-03): parse session response before passing to updateSessionInfo
CRITICAL BUG:
- refreshCurrentSessionRest passed raw Response object to updateSessionInfo
- Should parse with response.json() first
- Caused two major issues:

ISSUE 1: Redux Serialization Error
- Response object dispatched to Redux (non-serializable)
- Error: "A non-serializable value was detected in an action"

ISSUE 2: Backing Tracks Never Extracted
- updateSessionInfo received Response instead of parsed data
- response.participants was undefined (Response has no participants property)
- Backing track extraction code never ran
- mixerHelper.backingTracks stayed empty

SOLUTION:
Parse response before passing to updateSessionInfo:
  const response = await getSession(currentSessionIdRef.current);
  const data = await response.json();  // ← ADDED
  updateSessionInfo(data, callback, force);

Now data.participants exists and backing tracks are extracted correctly.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-16 13:13:50 +05:30
Nuwan 3c2930092b debug(05-03): add detailed logging for alert callback flow 2026-01-16 13:11:08 +05:30
Nuwan a88beb3f4e fix(05-03): register alert callback to receive backend mixer changes
PROBLEM:
- onBackendMixerChanged never being called
- No [HandleAlertCallback] logs
- Backing track changes not triggering session refresh

ROOT CAUSE:
- Alert callback never registered with native client
- In legacy code: jamClient.SessionSetAlertCallback("JK.AlertCallback")
- React app had no equivalent setup
- Backend mixer change alerts (type=2) never delivered to app
- So onBackendMixerChanged never called, session never refreshed

SOLUTION:
1. Add JK.HandleAlertCallback global function in JKSessionScreen
2. Routes BACKEND_MIXER_CHANGE (type=2) to sessionModel.onBackendMixerChanged
3. Register callback with jamClient.SessionSetAlertCallback on session join
4. Unregister callback on session leave for cleanup

FLOW NOW:
1. User opens backing track via jamClient
2. Native client detects change
3. Native client calls JK.HandleAlertCallback(type=2, 'RebuildMediaControl')
4. Handler routes to sessionModel.onBackendMixerChanged()
5. Syncs tracks and calls refreshCurrentSession()
6. REST API returns session with participants[].backing_tracks
7. updateSessionInfo() extracts and dispatches to Redux
8. mixerHelper.backingTracks populated
9. Component displays backing track

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-16 13:06:20 +05:30
Nuwan e4651ae1cb fix(05-03): trigger session refresh when backing tracks change
PROBLEM:
- Backing track still not appearing in session screen after previous fix
- updateSessionInfo() extraction code not being called

ROOT CAUSE:
- onBackendMixerChanged() handler detects when backing tracks change
- It calls syncTracks() to update server but doesn't refresh session
- Without refreshCurrentSession(), the REST API is never called
- So updateSessionInfo() never runs and backing tracks never extracted

SOLUTION:
- Call refreshCurrentSession(true) after syncTracks() when backing tracks change
- Also add for metronome changes for consistency
- Now the full flow works:
  1. User opens backing track via jamClient
  2. Backend mixer changes, triggers 'RebuildMediaControl'
  3. onBackendMixerChanged detects backing track change
  4. Syncs tracks to server
  5. Refreshes session from server (REST API call)
  6. updateSessionInfo extracts backing tracks from response
  7. Dispatches to Redux mediaSlice
  8. mixerHelper.backingTracks populated
  9. Component displays backing track

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-16 12:59:43 +05:30
Nuwan 973d0c6ef2 chore(05-03): clean up debug logs and document MIXER_CHANGES handler
- Remove debug logs from JKSessionScreen backing track display
- Add comment to MIXER_CHANGES handler explaining it's not currently used
- Document that media arrays are now extracted from REST API in useSessionModel

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-16 12:16:34 +05:30
Nuwan 251788d799 fix(05-03): extract backing tracks from session response to Redux
PROBLEM:
- mixerHelper.backingTracks was always empty/null
- Backing track not appearing in session screen
- useSessionWebSocket had MIXER_CHANGES callback that never fired

ROOT CAUSE:
- MIXER_CHANGES WebSocket message doesn't exist on server
- Backing track data comes from REST API /api/sessions/:id response
- Session data stored in activeSessionSlice but never extracted to mediaSlice
- useMixerHelper reads from mediaSlice.backingTracks which was never populated

SOLUTION:
- Import mediaSlice actions (setBackingTracks, setJamTracks, setRecordedTracks) in useSessionModel
- Update updateSessionInfo() to extract backing tracks from session.participants[].backing_tracks
- Dispatch extracted arrays to Redux mediaSlice when session updates
- Also extract jamTracks and recordedTracks for consistency

DATA FLOW:
1. User opens backing track via jamClient.SessionOpenBackingTrackFile()
2. Server updates session state
3. Server sends TRACKS_CHANGED WebSocket message
4. Client calls refreshCurrentSession() -> REST API /api/sessions/:id
5. Response includes participants with backing_tracks (containing mixers)
6. updateSessionInfo() extracts backing tracks and dispatches to Redux
7. useMixerHelper reads from mediaSlice.backingTracks
8. Components access via mixerHelper.backingTracks

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-16 12:16:02 +05:30
Nuwan c487679fc8 debug(05-03): add comprehensive logging for backing track display
Adds detailed console logging to trace backing track data flow:

1. MIXER_CHANGES handler logs:
   - Full sessionMixers payload
   - mixers.backingTracks array
   - mixers.jamTracks array
   - mixers.recordedTracks array

2. JKSessionScreen logs:
   - showBackingTrackPlayer state
   - backingTrackData from Redux
   - mixerHelper.backingTracks value
   - mixerHelper.backingTracks length

This will help identify where the data flow breaks:
- If MIXER_CHANGES shows data but SESSION_SCREEN doesn't: dispatch issue
- If MIXER_CHANGES shows empty arrays: WebSocket/server issue
- If SESSION_SCREEN shows data but no render: conditional logic issue

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-16 12:05:23 +05:30
Nuwan d19754bf54 refactor(05-03): revert workaround and remove debug logs
Now that useMixerHelper properly exposes backingTracks, we can:
- Revert the loading state workaround
- Restore original conditional requiring both showBackingTrackPlayer
  and mixerHelper.backingTracks
- Remove debug console.log statements

The backing track section now waits for both conditions:
1. Player popup is open (showBackingTrackPlayer)
2. WebSocket data has arrived (mixerHelper.backingTracks)

This provides a cleaner implementation without loading placeholders.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-16 11:53:54 +05:30
Nuwan a60a508330 fix(05-03): expose backingTracks, jamTracks, recordedTracks from useMixerHelper
Root cause fix: useMixerHelper was reading backingTracks from Redux
but not returning it in the hook's return object, causing
mixerHelper.backingTracks to always be undefined.

The issue:
- Line 88: Reads backingTracks from Redux mediaSlice
- Line 89: Reads jamTracks from Redux mediaSlice
- Line 90: Reads recordedTracks from Redux mediaSlice
- Line 831-847: Return object MISSING these three properties

This caused:
- WebSocket MIXER_CHANGES dispatches setBackingTracks() ✓
- Redux mediaSlice.backingTracks updates ✓
- useMixerHelper reads it via selector ✓
- But doesn't expose it to components ✗
- Result: mixerHelper.backingTracks always undefined

Fix:
Added backingTracks, jamTracks, recordedTracks to return object.

Now the full data flow works:
1. WebSocket MIXER_CHANGES arrives
2. Dispatches setBackingTracks(mixers.backingTracks)
3. Redux mediaSlice updates
4. useMixerHelper reads via selector
5. Returns in hook object
6. Components access via mixerHelper.backingTracks

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-16 11:53:19 +05:30
Nuwan e74c3ab44f fix(05-03): show backing track section immediately when player opens
Fixes issue where backing track wasn't appearing because mixerHelper
data hadn't arrived yet via WebSocket. Now shows section immediately
with loading state until mixer data arrives.

Changes:
- Removed dependency on mixerHelper.backingTracks for initial display
- Section now shows when showBackingTrackPlayer is true
- Header shows filename from backingTrackData.backingTrack immediately
- Displays "Loading backing track controls..." until mixer data arrives
- Once MIXER_CHANGES WebSocket message arrives, shows full track with VU/gain

Display flow:
1. Player opens → showBackingTrackPlayer = true
2. Section immediately appears with header and filename
3. Shows loading message for controls
4. WebSocket MIXER_CHANGES arrives → mixerHelper.backingTracks populated
5. Full track controls appear (VU meter, gain, pan menu)

This provides immediate visual feedback while waiting for server data.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-16 09:32:35 +05:30
Nuwan e4d51fb452 fix(05-03): show backing track when player opens and fix close
Fixes backing track display to show when the player popup is open,
matching JamTrack behavior. Also properly clears all state when closed.

Changes:
- Added showBackingTrackPlayer boolean from backingTrackData
- Updated conditional render to check showBackingTrackPlayer
- Track now displays only when popup is actually open
- handleBackingTrackMainClose now clears backingTrackData
- Also closes the modal to ensure popup is hidden

Display flow:
1. User selects backing track
2. handleBackingTrackSelected opens file and sets backingTrackData
3. Player popup opens (showBackingTrackPlayer = true)
4. WebSocket MIXER_CHANGES updates mixerHelper.backingTracks
5. Track appears in session screen (both conditions met)
6. Clicking close removes track and closes popup

Close flow:
1. Calls closeMedia() to close native client media
2. Clears backingTrackData (hides track and popup)
3. Closes modal (ensures popup window closes)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-15 23:11:19 +05:30
Nuwan 281c6eba7f feat(05-03): add header with close link to backing track section
Matches JamTrack section format by adding a header showing
"Backing Track: {filename}" with a close link.

Changes:
- Added h5 header in JKSessionScreen with backing track filename
- Added close link with FontAwesome times icon
- Removed duplicate internal header from JKSessionBackingTrack component
- Now displays: "Backing Track: {shortFilename}" at the top
- Close link triggers handleBackingTrackMainClose

Format now matches JamTrack section:
- Header with name and close link
- Single track with instrument icon and mixer controls
- Consistent styling with border separator

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-15 23:00:12 +05:30
Nuwan c3d8076590 feat(05-03): show JamTrack stems when player is ready
Shows JamTrack stems in session screen only when the player is ready
to play (after download/packaging is complete), matching backing track
behavior.

Changes:
- Added jamTrackDownloadState selector
- Updated conditional render to check download state
- Stems now show when state is 'synchronized' or 'idle'
- Prevents showing stems during packaging/downloading

Stems display flow:
1. User selects JamTrack from modal
2. handleJamTrackSelect fetches JamTrack with stems
3. Sets selectedJamTrack and jamTrackStems in Redux
4. Player opens and begins packaging/downloading if needed
5. Once downloadState becomes 'synchronized', stems appear in session
6. Clicking close (player or session) removes stems and closes player

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-15 22:40:15 +05:30