UNPKG

@elevenlabs/react-native

Version:

ElevenLabs React Native SDK for Conversational AI

101 lines (87 loc) 3.02 kB
import { useState, useEffect, useCallback, useRef } from "react"; import { AudioSession } from "@livekit/react-native"; import type { LocalParticipant } from "livekit-client"; import type { ConversationStatus, Callbacks } from "../types"; export const useLiveKitRoom = ( callbacksRef: { current: Callbacks }, setStatus: (status: ConversationStatus) => void, conversationId: string, status: ConversationStatus, textOnly: boolean = false ) => { const [roomConnected, setRoomConnected] = useState(false); const [localParticipant, setLocalParticipant] = useState<LocalParticipant | null>(null); const hasCalledOnConnectRef = useRef(false); const audioSessionActiveRef = useRef(false); // Reset room state when conversationId changes (new session starting) useEffect(() => { if (conversationId) { setRoomConnected(false); setLocalParticipant(null); hasCalledOnConnectRef.current = false; } }, [conversationId]); useEffect(() => { const shouldHaveAudio = !textOnly && !!conversationId; if (shouldHaveAudio && !audioSessionActiveRef.current) { audioSessionActiveRef.current = true; AudioSession.startAudioSession(); } else if (!shouldHaveAudio && audioSessionActiveRef.current) { audioSessionActiveRef.current = false; AudioSession.stopAudioSession(); } return () => { if (audioSessionActiveRef.current) { audioSessionActiveRef.current = false; AudioSession.stopAudioSession(); } }; }, [textOnly, conversationId]); // Fire onConnect when both participant and room are fully ready useEffect(() => { if (localParticipant && roomConnected && !hasCalledOnConnectRef.current) { hasCalledOnConnectRef.current = true; callbacksRef.current.onConnect?.({ conversationId }); } }, [localParticipant, roomConnected, conversationId, callbacksRef]); const handleParticipantReady = useCallback( (participant: LocalParticipant) => { if (localParticipant) { return; } setLocalParticipant(participant); setStatus("connected"); }, [localParticipant, setStatus] ); const handleConnected = useCallback(() => { setRoomConnected(true); }, []); const handleDisconnected = useCallback(() => { // If already disconnected, endSession already handled the disconnect callback if (status === "disconnected") { return; } setRoomConnected(false); setStatus("disconnected"); setLocalParticipant(null); hasCalledOnConnectRef.current = false; callbacksRef.current.onDisconnect?.({ reason: "user" }); }, [callbacksRef, setStatus, status]); const handleError = useCallback( (error: Error) => { console.error("LiveKit error:", error); callbacksRef.current.onError?.(error.message, undefined); }, [callbacksRef] ); return { roomConnected, localParticipant, handleParticipantReady, handleConnected, handleDisconnected, handleError, }; };