import React, { useState, useEffect } from 'react';
import { View, FlatList, Text, TouchableOpacity, StyleSheet } from 'react-native';
import { CometChatCalls } from '@cometchat/calls-sdk-react-native';
interface Participant {
pid: string;
uid: string;
name: string;
avatar?: string;
}
function ParticipantList() {
const [participants, setParticipants] = useState<Participant[]>([]);
const [pinnedId, setPinnedId] = useState<string | null>(null);
useEffect(() => {
const unsubscribeList = CometChatCalls.addEventListener(
'onParticipantListChanged',
(list: Participant[]) => {
setParticipants(list);
}
);
const unsubscribeJoin = CometChatCalls.addEventListener(
'onParticipantJoined',
(participant: Participant) => {
console.log(`${participant.name} joined`);
}
);
const unsubscribeLeave = CometChatCalls.addEventListener(
'onParticipantLeft',
(participant: Participant) => {
console.log(`${participant.name} left`);
// Unpin if the pinned participant left
if (pinnedId === participant.pid) {
setPinnedId(null);
}
}
);
return () => {
unsubscribeList();
unsubscribeJoin();
unsubscribeLeave();
};
}, [pinnedId]);
const handlePin = (participant: Participant) => {
if (pinnedId === participant.pid) {
CometChatCalls.unpinParticipant();
setPinnedId(null);
} else {
CometChatCalls.pinParticipant(participant.pid, 'human');
setPinnedId(participant.pid);
}
};
const handleMute = (participant: Participant) => {
CometChatCalls.muteParticipant(participant.pid);
};
const renderParticipant = ({ item }: { item: Participant }) => (
<View style={styles.participantItem}>
<View style={styles.avatar}>
<Text style={styles.avatarText}>
{item.name.charAt(0).toUpperCase()}
</Text>
</View>
<Text style={styles.name}>{item.name}</Text>
<View style={styles.actions}>
<TouchableOpacity
style={[styles.actionButton, pinnedId === item.pid && styles.activeButton]}
onPress={() => handlePin(item)}
>
<Text style={styles.actionText}>
{pinnedId === item.pid ? 'Unpin' : 'Pin'}
</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.actionButton}
onPress={() => handleMute(item)}
>
<Text style={styles.actionText}>Mute</Text>
</TouchableOpacity>
</View>
</View>
);
return (
<View style={styles.container}>
<Text style={styles.header}>
Participants ({participants.length})
</Text>
<FlatList
data={participants}
keyExtractor={(item) => item.pid}
renderItem={renderParticipant}
ListEmptyComponent={
<Text style={styles.emptyText}>No other participants</Text>
}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#1a1a1a',
},
header: {
color: '#fff',
fontSize: 18,
fontWeight: '600',
padding: 16,
borderBottomWidth: 1,
borderBottomColor: '#333',
},
participantItem: {
flexDirection: 'row',
alignItems: 'center',
padding: 12,
borderBottomWidth: 1,
borderBottomColor: '#333',
},
avatar: {
width: 40,
height: 40,
borderRadius: 20,
backgroundColor: '#6851D6',
justifyContent: 'center',
alignItems: 'center',
},
avatarText: {
color: '#fff',
fontSize: 16,
fontWeight: '600',
},
name: {
flex: 1,
color: '#fff',
fontSize: 16,
marginLeft: 12,
},
actions: {
flexDirection: 'row',
gap: 8,
},
actionButton: {
backgroundColor: '#333',
paddingHorizontal: 12,
paddingVertical: 6,
borderRadius: 4,
},
activeButton: {
backgroundColor: '#6851D6',
},
actionText: {
color: '#fff',
fontSize: 12,
},
emptyText: {
color: '#666',
textAlign: 'center',
padding: 20,
},
});
export default ParticipantList;