import React, { useState, useEffect } from 'react';
import { View, TouchableOpacity, Text, StyleSheet, SafeAreaView } from 'react-native';
import { CometChatCalls } from '@cometchat/calls-sdk-react-native';
interface CustomControlPanelProps {
isAudioOnly?: boolean;
}
function CustomControlPanel({ isAudioOnly = false }: CustomControlPanelProps) {
const [isAudioMuted, setIsAudioMuted] = useState(false);
const [isVideoMuted, setIsVideoMuted] = useState(false);
const [isHandRaised, setIsHandRaised] = useState(false);
const [isRecording, setIsRecording] = useState(false);
const [currentLayout, setCurrentLayout] = useState<'TILE' | 'SIDEBAR' | 'SPOTLIGHT'>('TILE');
useEffect(() => {
// Listen for media events
const unsubscribeAudioMuted = CometChatCalls.addEventListener(
'onAudioMuted',
() => setIsAudioMuted(true)
);
const unsubscribeAudioUnmuted = CometChatCalls.addEventListener(
'onAudioUnMuted',
() => setIsAudioMuted(false)
);
const unsubscribeVideoPaused = CometChatCalls.addEventListener(
'onVideoPaused',
() => setIsVideoMuted(true)
);
const unsubscribeVideoResumed = CometChatCalls.addEventListener(
'onVideoResumed',
() => setIsVideoMuted(false)
);
const unsubscribeRecordingStarted = CometChatCalls.addEventListener(
'onRecordingStarted',
() => setIsRecording(true)
);
const unsubscribeRecordingStopped = CometChatCalls.addEventListener(
'onRecordingStopped',
() => setIsRecording(false)
);
const unsubscribeLayoutChanged = CometChatCalls.addEventListener(
'onCallLayoutChanged',
(layout: 'TILE' | 'SIDEBAR' | 'SPOTLIGHT') => setCurrentLayout(layout)
);
return () => {
unsubscribeAudioMuted();
unsubscribeAudioUnmuted();
unsubscribeVideoPaused();
unsubscribeVideoResumed();
unsubscribeRecordingStarted();
unsubscribeRecordingStopped();
unsubscribeLayoutChanged();
};
}, []);
const toggleAudio = () => {
if (isAudioMuted) {
CometChatCalls.unMuteAudio();
} else {
CometChatCalls.muteAudio();
}
};
const toggleVideo = () => {
if (isVideoMuted) {
CometChatCalls.resumeVideo();
} else {
CometChatCalls.pauseVideo();
}
};
const toggleHand = () => {
if (isHandRaised) {
CometChatCalls.lowerHand();
setIsHandRaised(false);
} else {
CometChatCalls.raiseHand();
setIsHandRaised(true);
}
};
const toggleRecording = () => {
if (isRecording) {
CometChatCalls.stopRecording();
} else {
CometChatCalls.startRecording();
}
};
const cycleLayout = () => {
const layouts: Array<'TILE' | 'SIDEBAR' | 'SPOTLIGHT'> = ['TILE', 'SIDEBAR', 'SPOTLIGHT'];
const currentIndex = layouts.indexOf(currentLayout);
const nextLayout = layouts[(currentIndex + 1) % layouts.length];
CometChatCalls.setLayout(nextLayout);
};
const handleEndCall = () => {
CometChatCalls.leaveSession();
};
return (
<SafeAreaView style={styles.container}>
<View style={styles.controlRow}>
{/* Audio Toggle */}
<TouchableOpacity
style={[styles.controlButton, isAudioMuted && styles.activeButton]}
onPress={toggleAudio}
>
<Text style={styles.buttonIcon}>{isAudioMuted ? '🔇' : '🎤'}</Text>
<Text style={styles.buttonLabel}>
{isAudioMuted ? 'Unmute' : 'Mute'}
</Text>
</TouchableOpacity>
{/* Video Toggle (only for video calls) */}
{!isAudioOnly && (
<TouchableOpacity
style={[styles.controlButton, isVideoMuted && styles.activeButton]}
onPress={toggleVideo}
>
<Text style={styles.buttonIcon}>{isVideoMuted ? '📷' : '🎥'}</Text>
<Text style={styles.buttonLabel}>
{isVideoMuted ? 'Show' : 'Hide'}
</Text>
</TouchableOpacity>
)}
{/* Switch Camera (only for video calls) */}
{!isAudioOnly && (
<TouchableOpacity
style={styles.controlButton}
onPress={() => CometChatCalls.switchCamera()}
>
<Text style={styles.buttonIcon}>🔄</Text>
<Text style={styles.buttonLabel}>Flip</Text>
</TouchableOpacity>
)}
{/* Raise Hand */}
<TouchableOpacity
style={[styles.controlButton, isHandRaised && styles.handRaisedButton]}
onPress={toggleHand}
>
<Text style={styles.buttonIcon}>{isHandRaised ? '✋' : '🤚'}</Text>
<Text style={styles.buttonLabel}>
{isHandRaised ? 'Lower' : 'Raise'}
</Text>
</TouchableOpacity>
</View>
<View style={styles.controlRow}>
{/* Layout Toggle */}
<TouchableOpacity style={styles.controlButton} onPress={cycleLayout}>
<Text style={styles.buttonIcon}>📐</Text>
<Text style={styles.buttonLabel}>{currentLayout}</Text>
</TouchableOpacity>
{/* Recording */}
<TouchableOpacity
style={[styles.controlButton, isRecording && styles.recordingButton]}
onPress={toggleRecording}
>
<Text style={styles.buttonIcon}>{isRecording ? '⏹️' : '⏺️'}</Text>
<Text style={styles.buttonLabel}>
{isRecording ? 'Stop' : 'Record'}
</Text>
</TouchableOpacity>
{/* End Call */}
<TouchableOpacity
style={[styles.controlButton, styles.endCallButton]}
onPress={handleEndCall}
>
<Text style={styles.buttonIcon}>📞</Text>
<Text style={styles.buttonLabel}>End</Text>
</TouchableOpacity>
</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
position: 'absolute',
bottom: 0,
left: 0,
right: 0,
backgroundColor: 'rgba(0, 0, 0, 0.8)',
paddingVertical: 16,
paddingHorizontal: 8,
},
controlRow: {
flexDirection: 'row',
justifyContent: 'center',
marginBottom: 12,
gap: 12,
},
controlButton: {
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#333',
width: 64,
height: 64,
borderRadius: 32,
},
activeButton: {
backgroundColor: '#6851D6',
},
handRaisedButton: {
backgroundColor: '#f59e0b',
},
recordingButton: {
backgroundColor: '#ef4444',
},
endCallButton: {
backgroundColor: '#dc2626',
},
buttonIcon: {
fontSize: 24,
},
buttonLabel: {
color: '#fff',
fontSize: 10,
marginTop: 4,
},
});
export default CustomControlPanel;