import React, { useState, useEffect, useCallback } from 'react';
import { View, Text, TouchableOpacity, StyleSheet, Modal } from 'react-native';
import { CometChat } from '@cometchat/chat-sdk-react-native';
import { CometChatCalls } from '@cometchat/calls-sdk-react-native';
interface Call {
getSessionId: () => string;
getType: () => string;
getSender: () => { getName: () => string };
}
function CallManager({ children }: { children: React.ReactNode }) {
const [incomingCall, setIncomingCall] = useState<Call | null>(null);
const [activeCall, setActiveCall] = useState<{
token: string;
settings: any;
} | null>(null);
useEffect(() => {
const listenerId = 'call_manager_listener';
CometChat.addCallListener(
listenerId,
new CometChat.CallListener({
onIncomingCallReceived: (call: Call) => {
setIncomingCall(call);
},
onOutgoingCallAccepted: async (call: Call) => {
await startSession(call);
},
onOutgoingCallRejected: () => {
setActiveCall(null);
},
onIncomingCallCancelled: () => {
setIncomingCall(null);
},
onCallEndedMessageReceived: () => {
setActiveCall(null);
setIncomingCall(null);
},
})
);
return () => {
CometChat.removeCallListener(listenerId);
};
}, []);
const startSession = async (call: Call) => {
try {
const sessionId = call.getSessionId();
const { token } = await CometChatCalls.generateToken(sessionId);
const isAudioOnly = call.getType() === CometChat.CALL_TYPE.AUDIO;
const settings = new CometChatCalls.CallSettingsBuilder()
.setIsAudioOnlyCall(isAudioOnly)
.setCallEventListener(new CometChatCalls.OngoingCallListener({
onCallEnded: () => {
setActiveCall(null);
},
}))
.build();
setActiveCall({ token, settings });
setIncomingCall(null);
} catch (error) {
console.error('Error starting session:', error);
}
};
const handleAccept = async () => {
if (!incomingCall) return;
try {
const call = await CometChat.acceptCall(incomingCall.getSessionId());
await startSession(call);
} catch (error) {
console.error('Error accepting call:', error);
}
};
const handleReject = async () => {
if (!incomingCall) return;
try {
await CometChat.rejectCall(
incomingCall.getSessionId(),
CometChat.CALL_STATUS.REJECTED
);
setIncomingCall(null);
} catch (error) {
console.error('Error rejecting call:', error);
}
};
const handleEndCall = async () => {
if (!activeCall) return;
CometChatCalls.leaveSession();
setActiveCall(null);
};
return (
<View style={styles.container}>
{children}
{/* Incoming Call Modal */}
<Modal visible={!!incomingCall} transparent animationType="slide">
<View style={styles.modalOverlay}>
<View style={styles.incomingCallCard}>
<Text style={styles.callerName}>
{incomingCall?.getSender().getName()}
</Text>
<Text style={styles.callType}>
Incoming {incomingCall?.getType()} call
</Text>
<View style={styles.callActions}>
<TouchableOpacity
style={[styles.callButton, styles.rejectButton]}
onPress={handleReject}
>
<Text style={styles.buttonText}>Decline</Text>
</TouchableOpacity>
<TouchableOpacity
style={[styles.callButton, styles.acceptButton]}
onPress={handleAccept}
>
<Text style={styles.buttonText}>Accept</Text>
</TouchableOpacity>
</View>
</View>
</View>
</Modal>
{/* Active Call */}
{activeCall && (
<Modal visible={true} animationType="slide">
<View style={styles.callContainer}>
<CometChatCalls.Component
callToken={activeCall.token}
callSettings={activeCall.settings}
/>
</View>
</Modal>
)}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
modalOverlay: {
flex: 1,
backgroundColor: 'rgba(0, 0, 0, 0.8)',
justifyContent: 'center',
alignItems: 'center',
},
incomingCallCard: {
backgroundColor: '#1a1a1a',
borderRadius: 20,
padding: 30,
alignItems: 'center',
width: '80%',
},
callerName: {
color: '#fff',
fontSize: 24,
fontWeight: '600',
marginBottom: 8,
},
callType: {
color: '#999',
fontSize: 16,
marginBottom: 30,
},
callActions: {
flexDirection: 'row',
gap: 20,
},
callButton: {
paddingHorizontal: 30,
paddingVertical: 15,
borderRadius: 30,
},
rejectButton: {
backgroundColor: '#ff4444',
},
acceptButton: {
backgroundColor: '#22c55e',
},
buttonText: {
color: '#fff',
fontSize: 16,
fontWeight: '600',
},
callContainer: {
flex: 1,
backgroundColor: '#000',
},
});
export default CallManager;