Add multi-speaker support for group conversations
Features: - Speaker management system with unique IDs and colors - Visual speaker selection with avatars and color coding - Automatic language detection per speaker - Real-time translation for all speakers' languages - Conversation history with speaker attribution - Export conversation as text file - Persistent speaker data in localStorage UI Components: - Speaker toolbar with add/remove controls - Active speaker indicators - Conversation view with color-coded messages - Settings toggle for multi-speaker mode - Mobile-responsive speaker buttons Technical Implementation: - SpeakerManager class handles all speaker operations - Automatic translation to all active languages - Conversation entries with timestamps - Translation caching per language - Clean separation of original vs translated text - Support for up to 8 concurrent speakers User Experience: - Click to switch active speaker - Visual feedback for active speaker - Conversation flows naturally with colors - Export feature for meeting minutes - Clear conversation history option - Seamless single/multi speaker mode switching This enables group conversations where each participant can speak in their native language and see translations in real-time. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
		| @@ -450,4 +450,110 @@ | ||||
| /* Smooth text appearance for streaming */ | ||||
| .streaming-text { | ||||
|     transition: all 0.1s ease-out; | ||||
| } | ||||
|  | ||||
| /* Multi-speaker styles */ | ||||
| .speaker-button { | ||||
|     position: relative; | ||||
|     padding: 8px 16px; | ||||
|     border-radius: 20px; | ||||
|     border: 2px solid; | ||||
|     background-color: white; | ||||
|     font-weight: 500; | ||||
|     transition: all 0.3s ease; | ||||
|     min-width: 120px; | ||||
| } | ||||
|  | ||||
| .speaker-button.active { | ||||
|     color: white !important; | ||||
|     transform: scale(1.05); | ||||
|     box-shadow: 0 2px 8px rgba(0,0,0,0.2); | ||||
| } | ||||
|  | ||||
| .speaker-avatar { | ||||
|     display: inline-flex; | ||||
|     align-items: center; | ||||
|     justify-content: center; | ||||
|     width: 30px; | ||||
|     height: 30px; | ||||
|     border-radius: 50%; | ||||
|     background-color: rgba(255,255,255,0.3); | ||||
|     color: inherit; | ||||
|     font-weight: bold; | ||||
|     font-size: 12px; | ||||
|     margin-right: 8px; | ||||
| } | ||||
|  | ||||
| .speaker-button.active .speaker-avatar { | ||||
|     background-color: rgba(255,255,255,0.3); | ||||
| } | ||||
|  | ||||
| .conversation-entry { | ||||
|     margin-bottom: 16px; | ||||
|     padding: 12px; | ||||
|     border-radius: 12px; | ||||
|     background-color: #f8f9fa; | ||||
|     position: relative; | ||||
|     animation: slideIn 0.3s ease-out; | ||||
| } | ||||
|  | ||||
| @keyframes slideIn { | ||||
|     from { | ||||
|         opacity: 0; | ||||
|         transform: translateY(10px); | ||||
|     } | ||||
|     to { | ||||
|         opacity: 1; | ||||
|         transform: translateY(0); | ||||
|     } | ||||
| } | ||||
|  | ||||
| .conversation-speaker { | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     margin-bottom: 8px; | ||||
|     font-weight: 600; | ||||
| } | ||||
|  | ||||
| .conversation-speaker-avatar { | ||||
|     display: inline-flex; | ||||
|     align-items: center; | ||||
|     justify-content: center; | ||||
|     width: 25px; | ||||
|     height: 25px; | ||||
|     border-radius: 50%; | ||||
|     color: white; | ||||
|     font-size: 11px; | ||||
|     margin-right: 8px; | ||||
| } | ||||
|  | ||||
| .conversation-text { | ||||
|     margin-left: 33px; | ||||
|     line-height: 1.5; | ||||
| } | ||||
|  | ||||
| .conversation-time { | ||||
|     font-size: 0.8rem; | ||||
|     color: #6c757d; | ||||
|     margin-left: auto; | ||||
| } | ||||
|  | ||||
| .conversation-translation { | ||||
|     font-style: italic; | ||||
|     opacity: 0.9; | ||||
| } | ||||
|  | ||||
| /* Speaker list responsive */ | ||||
| @media (max-width: 768px) { | ||||
|     .speaker-button { | ||||
|         min-width: 100px; | ||||
|         padding: 6px 12px; | ||||
|         font-size: 0.9rem; | ||||
|     } | ||||
|      | ||||
|     .speaker-avatar { | ||||
|         width: 25px; | ||||
|         height: 25px; | ||||
|         font-size: 10px; | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user