import React, { useState, useEffect } from 'react';
import { View, TouchableOpacity, Text, StyleSheet, Modal, FlatList } from 'react-native';
import { CometChatCalls } from '@cometchat/calls-sdk-react-native';
type AudioMode = 'SPEAKER' | 'EARPIECE' | 'BLUETOOTH' | 'HEADPHONES';
interface AudioModeOption {
type: AudioMode;
label: string;
icon: string;
}
const audioModeOptions: AudioModeOption[] = [
{ type: 'SPEAKER', label: 'Speaker', icon: '🔊' },
{ type: 'EARPIECE', label: 'Earpiece', icon: '📱' },
{ type: 'BLUETOOTH', label: 'Bluetooth', icon: '🎧' },
{ type: 'HEADPHONES', label: 'Headphones', icon: '🎵' },
];
function AudioModeSelector() {
const [currentMode, setCurrentMode] = useState<AudioMode>('SPEAKER');
const [availableModes, setAvailableModes] = useState<AudioMode[]>(['SPEAKER', 'EARPIECE']);
const [modalVisible, setModalVisible] = useState(false);
useEffect(() => {
const unsubscribe = CometChatCalls.addEventListener(
'onAudioModeChanged',
(mode: AudioMode) => {
setCurrentMode(mode);
}
);
return () => unsubscribe();
}, []);
const selectMode = (mode: AudioMode) => {
// The SDK handles audio mode switching through the UI
// This is for display purposes
setCurrentMode(mode);
setModalVisible(false);
};
const getCurrentModeOption = () => {
return audioModeOptions.find((opt) => opt.type === currentMode) || audioModeOptions[0];
};
const renderModeOption = ({ item }: { item: AudioModeOption }) => {
const isAvailable = availableModes.includes(item.type);
const isSelected = currentMode === item.type;
return (
<TouchableOpacity
style={[
styles.modeOption,
isSelected && styles.selectedOption,
!isAvailable && styles.disabledOption,
]}
onPress={() => isAvailable && selectMode(item.type)}
disabled={!isAvailable}
>
<Text style={styles.modeIcon}>{item.icon}</Text>
<Text
style={[
styles.modeLabel,
isSelected && styles.selectedLabel,
!isAvailable && styles.disabledLabel,
]}
>
{item.label}
</Text>
{isSelected && <Text style={styles.checkmark}>✓</Text>}
</TouchableOpacity>
);
};
return (
<View>
<TouchableOpacity
style={styles.button}
onPress={() => setModalVisible(true)}
>
<Text style={styles.buttonIcon}>{getCurrentModeOption().icon}</Text>
<Text style={styles.buttonText}>{getCurrentModeOption().label}</Text>
</TouchableOpacity>
<Modal
visible={modalVisible}
transparent
animationType="slide"
onRequestClose={() => setModalVisible(false)}
>
<View style={styles.modalOverlay}>
<View style={styles.modalContent}>
<Text style={styles.modalTitle}>Audio Output</Text>
<FlatList
data={audioModeOptions}
keyExtractor={(item) => item.type}
renderItem={renderModeOption}
/>
<TouchableOpacity
style={styles.closeButton}
onPress={() => setModalVisible(false)}
>
<Text style={styles.closeButtonText}>Close</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
</View>
);
}
const styles = StyleSheet.create({
button: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#333',
paddingHorizontal: 16,
paddingVertical: 12,
borderRadius: 8,
gap: 8,
},
buttonIcon: {
fontSize: 18,
},
buttonText: {
color: '#fff',
fontSize: 14,
fontWeight: '600',
},
modalOverlay: {
flex: 1,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
justifyContent: 'flex-end',
},
modalContent: {
backgroundColor: '#1a1a1a',
borderTopLeftRadius: 20,
borderTopRightRadius: 20,
padding: 20,
},
modalTitle: {
color: '#fff',
fontSize: 18,
fontWeight: '600',
marginBottom: 16,
textAlign: 'center',
},
modeOption: {
flexDirection: 'row',
alignItems: 'center',
padding: 16,
borderRadius: 8,
marginBottom: 8,
backgroundColor: '#333',
},
selectedOption: {
backgroundColor: '#6851D6',
},
disabledOption: {
opacity: 0.5,
},
modeIcon: {
fontSize: 24,
marginRight: 12,
},
modeLabel: {
flex: 1,
color: '#fff',
fontSize: 16,
},
selectedLabel: {
fontWeight: '600',
},
disabledLabel: {
color: '#666',
},
checkmark: {
color: '#fff',
fontSize: 18,
},
closeButton: {
marginTop: 16,
padding: 16,
alignItems: 'center',
},
closeButtonText: {
color: '#6851D6',
fontSize: 16,
fontWeight: '600',
},
});
export default AudioModeSelector;