wellnua-lite/contexts/ChatContext.tsx
Sergei 05f872d067 fix: voice session improvements - FAB stop, echo prevention, chat TTS
- FAB button now correctly stops session during speaking/processing states
- Echo prevention: STT stopped during TTS playback, results ignored during speaking
- Chat TTS only speaks when voice session is active (no auto-speak for text chat)
- Session stop now aborts in-flight API requests and prevents race conditions
- STT restarts after TTS with 800ms delay for audio focus release
- Pending interrupt transcript processed after TTS completion
- ChatContext added for message persistence across tab navigation
- VoiceFAB redesigned with state-based animations
- console.error replaced with console.warn across voice pipeline
- no-speech STT errors silenced (normal silence behavior)
2026-01-27 22:59:55 -08:00

52 lines
1.5 KiB
TypeScript

/**
* Chat Context - Persists chat messages across tab navigation
*
* Without this context, messages are lost when switching tabs
* because ChatScreen component unmounts and remounts.
*/
import React, { createContext, useContext, useState, useCallback, ReactNode } from 'react';
import type { Message } from '@/types';
interface ChatContextValue {
messages: Message[];
setMessages: React.Dispatch<React.SetStateAction<Message[]>>;
addMessage: (message: Message) => void;
clearMessages: (initialMessage: Message) => void;
}
const ChatContext = createContext<ChatContextValue | undefined>(undefined);
export function ChatProvider({ children }: { children: ReactNode }) {
const [messages, setMessages] = useState<Message[]>([
{
id: '1',
role: 'assistant',
content: "Hello! I'm Julia, your AI wellness companion.\n\nType a message below to chat with me.",
timestamp: new Date(),
},
]);
const addMessage = useCallback((message: Message) => {
setMessages(prev => [...prev, message]);
}, []);
const clearMessages = useCallback((initialMessage: Message) => {
setMessages([initialMessage]);
}, []);
return (
<ChatContext.Provider value={{ messages, setMessages, addMessage, clearMessages }}>
{children}
</ChatContext.Provider>
);
}
export function useChat() {
const context = useContext(ChatContext);
if (!context) {
throw new Error('useChat must be used within ChatProvider');
}
return context;
}