UNPKG

@cometchat/chat-uikit-react-native

Version:

Ready-to-use Chat UI Components for React Native

193 lines 9.32 kB
import { CometChat } from "@cometchat/chat-sdk-react-native"; import React, { useEffect, useMemo, useRef, useState } from "react"; import { Modal, SafeAreaView, Text, TouchableOpacity, View } from "react-native"; import { MessageCategoryConstants, MessageTypeConstants, } from "../../shared/constants/UIKitConstants"; import { CometChatUIEventHandler } from "../../shared/events/CometChatUIEventHandler/CometChatUIEventHandler"; import { CometChatSoundManager, localize } from "../../shared/resources"; import { CometChatAvatar } from "../../shared/views"; import { CallUIEvents } from "../CallEvents"; import { CallingPackage } from "../CallingPackage"; import { CometChatOngoingCall } from "../CometChatOngoingCall"; import { useTheme } from "../../theme"; import { Icon } from "../../shared/icons/Icon"; import { deepMerge } from "../../shared/helper/helperFunctions"; const listenerId = "callListener_" + new Date().getTime(); const CometChatCalls = CallingPackage.CometChatCalls; /** * CometChatOutgoingCall component. * * This component handles the UI for an outgoing call by playing sound, * rendering call details and providing an end call action. It listens to call events * to update the UI based on the call's state. * * @param {CometChatOutgoingCallInterface} props - Component configuration props. * @returns {JSX.Element} The rendered outgoing call UI. */ export const CometChatOutgoingCall = (props) => { const { call, customSoundForCalls, disableSoundForCalls, onEndCallButtonPressed, callSettingsBuilder, style, TitleView, SubtitleView, AvatarView, EndCallView, onError, } = props; // State to track whether the call is connected. const [isCallConnected, setCallConnected] = useState(false); // Controls visibility of this modal. const [isModalVisible, setModalVisible] = useState(true); const ongoingCall = useRef(undefined); const callSessionId = useRef(undefined); const callListener = useRef(null); const callSettings = useRef(null); const isCallEnded = useRef(undefined); const theme = useTheme(); // Merge default and custom styles for the outgoing call. const outgoingCallStyle = useMemo(() => { return deepMerge(theme.outgoingCallStyle, style ?? {}); }, [theme.outgoingCallStyle, style]); function checkIfDefaultCall(call) { return call.getCategory() === MessageCategoryConstants.call; } /** * Ends the call if required by checking if it is a default call. */ const endCallIfRequired = () => { if (call && checkIfDefaultCall(call)) { CometChat.endCall(call.getSessionId()) .then(() => { call.setStatus("ended"); if (!isCallEnded.current) { CometChatUIEventHandler.emitCallEvent(CallUIEvents.ccCallEnded, { call }); } isCallEnded.current = true; }) .catch((err) => { console.log("Error", err); onError && onError(err); }); } }; // Set up listeners, call settings, and sound for the outgoing call. useEffect(() => { if (call && (call["status"] === "ongoing" || (call.getCategory() === CometChat.CATEGORY_CUSTOM && call.getType() === MessageTypeConstants.meeting))) { ongoingCall.current = call; if (call.getType() == MessageTypeConstants.meeting) { callSessionId.current = call.getCustomData()?.sessionId; } if (call.getCategory() === MessageCategoryConstants.call) { callSessionId.current = call["sessionId"]; } setCallConnected(true); } if (!disableSoundForCalls && call?.getType() !== MessageTypeConstants.meeting) { if (customSoundForCalls) { CometChatSoundManager.play("outgoingCall", customSoundForCalls); } else { CometChatSoundManager.play("outgoingCall"); } } // Add call listener to handle outgoing call acceptance and rejection. CometChat.addCallListener(listenerId, new CometChat.CallListener({ onOutgoingCallAccepted: (acceptedCall) => { CometChatSoundManager.pause(); ongoingCall.current = acceptedCall; callSessionId.current = acceptedCall["sessionId"]; setCallConnected(true); }, onOutgoingCallRejected: () => { CometChatSoundManager.pause(); ongoingCall.current = undefined; callSessionId.current = undefined; setCallConnected(false); }, })); // Listen for call failure events. CometChatUIEventHandler.addCallListener(listenerId, { ccCallFailed: (error) => { setCallConnected(false); onError && onError(error); }, }); // Create an ongoing call listener to manage call events. callListener.current = new CometChatCalls.OngoingCallListener({ onCallEnded: () => { CometChatCalls.endSession(); if (checkIfDefaultCall(call)) { CometChat.clearActiveCall(); setCallConnected(false); call.setStatus("ended"); if (!isCallEnded.current) { CometChatUIEventHandler.emitCallEvent(CallUIEvents.ccCallEnded, { call }); } isCallEnded.current = true; } }, onCallEndButtonPressed: () => { if (!checkIfDefaultCall(call)) { setCallConnected(false); call.setStatus("ended"); if (!isCallEnded.current) { CometChatUIEventHandler.emitCallEvent(CallUIEvents.ccCallEnded, { call }); } isCallEnded.current = true; } else { endCallIfRequired(); } }, onUserJoined: (user) => { console.log("user joined:", user); }, onUserLeft: (user) => { endCallIfRequired(); }, onError: (error) => { CometChatUIEventHandler.emitCallEvent(CallUIEvents.ccCallFailed, { error }); }, }); // Determine call type (audio or meeting) and initialize call settings. const callType = call?.getType() === MessageTypeConstants.meeting ? call["customData"]?.["callType"] : call.getType(); callSettings.current = callSettingsBuilder?.setCallEventListener(callListener.current) ?? new CometChatCalls.CallSettingsBuilder() .enableDefaultLayout(true) .setCallEventListener(callListener.current) .setIsAudioOnlyCall(callType === "audio"); // Cleanup on unmount. return () => { if (!disableSoundForCalls) { CometChatSoundManager.pause(); } CometChat.removeCallListener(listenerId); }; }, []); /** * Handles closing the modal (via hardware back button on Android or a custom button). * This is where you can call onEndCallButtonPressed or do any other cleanup. */ const handleModalClose = () => { if (onEndCallButtonPressed) { onEndCallButtonPressed(call); } // Hide the modal – onDismiss fires after the animation completes setModalVisible(false); }; const callReceiverName = call?.getReceiver?.().getName?.() ?? "Unknown"; return (<Modal transparent animationType="fade" visible={isModalVisible} onRequestClose={handleModalClose}> <SafeAreaView style={{ flex: 1 }}> {isCallConnected ? (<CometChatOngoingCall sessionID={callSessionId.current} callSettingsBuilder={callSettings.current}/>) : (<View style={outgoingCallStyle.containerStyle}> {TitleView ? (TitleView(call)) : (<Text style={outgoingCallStyle.titleTextStyle}>{callReceiverName}</Text>)} {SubtitleView ? (SubtitleView(call)) : (<Text style={outgoingCallStyle.subtitleTextStyle}>{localize("CALLING")}</Text>)} {AvatarView ? (AvatarView(call)) : (<CometChatAvatar name={callReceiverName} image={{ uri: call?.getReceiverType?.() === "user" ? call?.getReceiver?.()?.getAvatar() : call?.getReceiver?.()?.getIcon(), }} style={outgoingCallStyle.avatarStyle}/>)} {EndCallView ? (EndCallView(call)) : (<TouchableOpacity style={outgoingCallStyle.endCallButtonStyle} onPress={handleModalClose}> <Icon name="call-end-fill" size={32} height={outgoingCallStyle.endCallIconStyle.height} width={outgoingCallStyle.endCallIconStyle.width} color={outgoingCallStyle.endCallIconStyle.tintColor} imageStyle={outgoingCallStyle.endCallIconStyle}/> </TouchableOpacity>)} </View>)} </SafeAreaView> </Modal>); }; //# sourceMappingURL=CometChatOutgoingCall.js.map