UNPKG

@revrag-ai/embed-react-native

Version:

A powerful React Native library for integrating AI-powered voice agents into mobile applications. Features real-time voice communication, intelligent speech processing, customizable UI components, and comprehensive event handling for building conversation

127 lines (117 loc) 3.79 kB
"use strict"; import { AudioSession, LiveKitRoom } from '@livekit/react-native'; import { useEffect, useRef, useState } from 'react'; // export interface VoiceProps { // url: string; // token: string; // onDisconnected: (data: string) => void; // onConnected: (data: string) => void; // } import { jsx as _jsx } from "react/jsx-runtime"; // Track audio session state globally to prevent multiple starts/stops let audioSessionActive = false; let audioSessionStarting = false; let audioSessionStopping = false; // Track connection to prevent unmounting while connected let activeConnectionToken = null; const Voice = props => { const { url, token, onDisconnected, onConnected, roomRef } = props; const [audioSessionStarted, setAudioSessionStarted] = useState(audioSessionActive); const mountedRef = useRef(true); const connectedRef = useRef(false); // Start audio session safely - prevent multiple simultaneous starts const startAudioSession = async () => { if (audioSessionActive || audioSessionStarting) { console.log('Audio session already active or starting, skipping'); return; } try { audioSessionStarting = true; console.log('Starting audio session'); await AudioSession.startAudioSession(); audioSessionActive = true; if (mountedRef.current) { setAudioSessionStarted(true); } } catch (err) { console.error('Failed to start audio session:', err); } finally { audioSessionStarting = false; } }; // Stop audio session safely - prevent multiple simultaneous stops const stopAudioSession = async () => { if (!audioSessionActive || audioSessionStopping) { console.log('Audio session already inactive or stopping, skipping'); return; } try { audioSessionStopping = true; console.log('Stopping audio session'); await AudioSession.stopAudioSession(); audioSessionActive = false; } catch (err) { console.error('Failed to stop audio session:', err); } finally { audioSessionStopping = false; } }; // Setup audio session useEffect(() => { mountedRef.current = true; startAudioSession(); return () => { mountedRef.current = false; // IMPORTANT: Don't stop the audio session on unmount if there might be an active call // This prevents audio session start/stop loops when components remount if (roomRef.current?.state !== 'connected' && !connectedRef.current) { stopAudioSession(); } else { console.log('Skipping audio session stop because room is still connected'); } }; }, []); // Track connection state changes to avoid unmounting while connected useEffect(() => { if (token) { activeConnectionToken = token; } return () => { // Only clear token when unmounting with this specific token if (activeConnectionToken === token) { activeConnectionToken = null; } }; }, [token]); // Only render LiveKitRoom when audio session is ready if (!audioSessionStarted) { return null; } // IMPORTANT: Never return empty fragment when connected! // Instead, always render the LiveKitRoom component to maintain the connection return /*#__PURE__*/_jsx(LiveKitRoom, { serverUrl: url, token: token, screen: false, audio: true, onConnected: () => { console.log('LiveKitRoom connected'); connectedRef.current = true; onConnected('connected'); }, room: roomRef.current || undefined, onDisconnected: () => { console.log('LiveKitRoom disconnected'); connectedRef.current = false; onDisconnected('disconnected'); } }); }; export default Voice; //# sourceMappingURL=EmbedVoice.js.map