UNPKG

mediasfu-reactnative

Version:
378 lines (377 loc) 14.8 kB
import React, { useState, useEffect } from 'react'; import { Modal, View, Text, Pressable, StyleSheet, Dimensions, Switch, TextInput, ScrollView, } from 'react-native'; import FontAwesome from 'react-native-vector-icons/FontAwesome'; import RNPickerSelect from 'react-native-picker-select'; import { getModalPosition } from '../../methods/utils/getModalPosition'; import { modifyCoHostSettings } from '../../methods/coHostMethods/modifyCoHostSettings'; /** * CoHostModal component allows users to manage co-host settings in a virtual event. * * This component renders a modal interface where users can assign a new co-host from the list of participants, * set responsibilities, and save the updated settings. It leverages a Socket instance for real-time updates * and offers customizable modal position and styling options. * * @component * @param {boolean} isCoHostModalVisible - Flag to control the visibility of the modal. * @param {() => void} onCoHostClose - Callback to close the modal. * @param {Function} [onModifyEventSettings=modifyCoHostSettings] - Callback to handle changes to event settings, defaulting to `modifyCoHostSettings`. * @param {string} [currentCohost='No coHost'] - Name of the current co-host. * @param {Participant[]} participants - List of event participants. * @param {CoHostResponsibility[]} coHostResponsibility - List of co-host responsibilities and their statuses. * @param {string} [position='topRight'] - Screen position of the modal. * @param {string} [backgroundColor='#83c0e9'] - Background color for the modal. * @param {string} roomName - Room identifier for the event. * @param {ShowAlert} [showAlert] - Function to display alerts. * @param {Function} updateCoHostResponsibility - Function to update co-host responsibility statuses. * @param {Function} updateCoHost - Function to set a new co-host. * @param {Function} updateIsCoHostModalVisible - Function to toggle modal visibility. * @param {Socket} socket - Socket instance for real-time communication. * * @returns {JSX.Element} The CoHostModal component. * * @example * ```tsx * import React from 'react'; * import { CoHostModal } from 'mediasfu-reactnative'; * import { io } from 'socket.io-client'; * * function App() { * const socket = io('http://localhost:3000'); * * return ( * <CoHostModal * isCoHostModalVisible={true} * onCoHostClose={() => console.log('Modal closed')} * currentCohost="John Doe" * participants={[ * { name: 'John Doe', islevel: '1' }, * { name: 'Jane Doe', islevel: '0' } * ]} * coHostResponsibility={[ * { name: 'manageParticipants', value: true, dedicated: false } * ]} * position="topRight" * backgroundColor="#83c0e9" * roomName="Room 1" * showAlert={({ message, type }) => console.log(message, type)} * updateCoHostResponsibility={(responsibilities) => console.log(responsibilities)} * updateCoHost={(coHost) => console.log(coHost)} * updateIsCoHostModalVisible={(visible) => console.log(visible)} * socket={socket} * /> * ); * } * * export default App; * ``` */ const CoHostModal = ({ isCoHostModalVisible, onCoHostClose, onModifyEventSettings = modifyCoHostSettings, currentCohost = 'No coHost', participants, coHostResponsibility, position = 'topRight', backgroundColor = '#83c0e9', roomName, showAlert, updateCoHostResponsibility, updateCoHost, updateIsCoHostModalVisible, socket, }) => { const [selectedCohost, setSelectedCohost] = useState(currentCohost); const [coHostResponsibilityCopy, setCoHostResponsibilityCopy] = useState([...coHostResponsibility]); const [coHostResponsibilityCopyAlt, setCoHostResponsibilityCopyAlt] = useState([...coHostResponsibility]); const initialResponsibilities = coHostResponsibilityCopyAlt.reduce((acc, item) => { const str2 = item.name.charAt(0).toUpperCase() + item.name.slice(1); const keyed = `manage${str2}`; acc[keyed] = item.value; acc[`dedicateTo${keyed}`] = item.dedicated; return acc; }, {}); const [responsibilities, setResponsibilities] = useState(initialResponsibilities); const responsibilityItems = [ { name: 'manageParticipants', label: 'Manage Participants' }, { name: 'manageMedia', label: 'Manage Media' }, { name: 'manageWaiting', label: 'Manage Waiting Room' }, { name: 'manageChat', label: 'Manage Chat' }, ]; // Filter out the current co-host from the list of participants and any participant with islevel '2' const filteredParticipants = participants === null || participants === void 0 ? void 0 : participants.filter((participant) => participant.name !== currentCohost && participant.islevel !== '2'); const handleToggleSwitch = (responsibility) => { setResponsibilities((prevResponsibilities) => (Object.assign(Object.assign({}, prevResponsibilities), { [responsibility]: !prevResponsibilities[responsibility] }))); // Update the coHostResponsibilityCopy if (responsibility.startsWith('dedicateTo')) { const responsibilityName = responsibility .replace('dedicateTomanage', '') .toLowerCase(); const responsibilityItem = coHostResponsibilityCopy.find((item) => item.name === responsibilityName); if (responsibilityItem) { responsibilityItem.dedicated = !responsibilityItem.dedicated; setCoHostResponsibilityCopy([...coHostResponsibilityCopy]); } } else if (responsibility.startsWith('manage')) { const responsibilityName = responsibility .replace('manage', '') .toLowerCase(); const responsibilityItem = coHostResponsibilityCopy.find((item) => item.name === responsibilityName); if (responsibilityItem) { responsibilityItem.value = !responsibilityItem.value; setCoHostResponsibilityCopy([...coHostResponsibilityCopy]); } } }; const screenWidth = Dimensions.get('window').width; let modalWidth = 0.8 * screenWidth; if (modalWidth > 400) { modalWidth = 400; } useEffect(() => { const populateResponsibilities = () => { setCoHostResponsibilityCopyAlt([...coHostResponsibility]); setCoHostResponsibilityCopy([...coHostResponsibility]); const responsibilities = coHostResponsibilityCopyAlt.reduce((acc, item) => { const str2 = item.name.charAt(0).toUpperCase() + item.name.slice(1); const keyed = `manage${str2}`; acc[keyed] = item.value; acc[`dedicateTo${keyed}`] = item.dedicated; return acc; }, {}); setResponsibilities(responsibilities); }; if (isCoHostModalVisible) { populateResponsibilities(); } }, [isCoHostModalVisible, coHostResponsibility]); const handleSave = () => { onModifyEventSettings({ roomName: roomName, showAlert: showAlert, selectedParticipant: selectedCohost, coHost: currentCohost, coHostResponsibility: coHostResponsibilityCopy, updateCoHostResponsibility: updateCoHostResponsibility, updateCoHost: updateCoHost, updateIsCoHostModalVisible: updateIsCoHostModalVisible, socket: socket, }); }; return (<Modal transparent animationType="slide" visible={isCoHostModalVisible} onRequestClose={onCoHostClose}> <View style={[styles.modalContainer, getModalPosition({ position })]}> <View style={[ styles.modalContent, { width: modalWidth, backgroundColor: backgroundColor }, ]}> <ScrollView> <View style={styles.modalHeader}> <Text style={styles.modalTitle}>Manage Co-Host</Text> <Pressable onPress={onCoHostClose} style={styles.btnCloseSettings}> <FontAwesome name="times" style={styles.icon}/> </Pressable> </View> <View style={styles.hr}/> <View style={styles.modalBody}> <View style={styles.formGroup}> <Text style={[styles.label, { fontWeight: 'bold' }]}> Current Co-host: </Text> <TextInput style={[styles.input, styles.disabledInput]} value={currentCohost} editable={false}/> </View> <View style={styles.sep}/> <View style={styles.formGroup}> <Text style={[styles.label, { fontWeight: 'bold' }]}> Select New Co-host: </Text> <RNPickerSelect style={pickerSelectStyles} value={selectedCohost} onValueChange={(value) => setSelectedCohost(value)} items={filteredParticipants ? filteredParticipants.map((participant) => ({ label: participant.name, value: participant.name, })) : []} placeholder={{ label: 'Select a participant', value: '' }} useNativeAndroidPickerStyle={false}/> </View> <View style={styles.sep}/> <View style={styles.row}> <View style={styles.col5}> <Text style={[styles.label, { fontWeight: 'bold' }]}> Responsibility </Text> </View> <View style={styles.col3}> <Text style={[styles.label, { fontWeight: 'bold' }]}> Select </Text> </View> <View style={styles.col4}> <Text style={[styles.label, { fontWeight: 'bold' }]}> Dedicated </Text> </View> </View> {responsibilityItems.map((item) => (<View style={styles.row} key={item.name}> <View style={styles.col5}> <Text style={styles.label}>{item.label}</Text> </View> <View style={styles.col3}> <Switch trackColor={{ false: '#767577', true: '#81b0ff' }} thumbColor={responsibilities[item.name] ? '#f5dd4b' : '#f4f3f4'} ios_backgroundColor="#3e3e3e" onValueChange={() => handleToggleSwitch(item.name)} value={responsibilities[item.name]}/> </View> <View style={styles.col4}> <Switch trackColor={{ false: '#767577', true: '#81b0ff' }} thumbColor={responsibilities[item.name] && responsibilities[`dedicateTo${item.name}`] ? '#f5dd4b' : '#f4f3f4'} ios_backgroundColor="#3e3e3e" onValueChange={() => handleToggleSwitch(`dedicateTo${item.name}`)} value={responsibilities[`dedicateTo${item.name}`] && responsibilities[item.name]} disabled={!responsibilities[item.name]}/> </View> </View>))} </View> <View style={styles.modalFooter}> <Pressable onPress={handleSave} style={styles.btnApplySettings}> <Text style={styles.btnText}>Save</Text> </Pressable> </View> </ScrollView> </View> </View> </Modal>); }; export default CoHostModal; const styles = StyleSheet.create({ modalContainer: { flex: 1, justifyContent: 'flex-end', alignItems: 'flex-end', zIndex: 9, elevation: 9, }, modalContent: { height: '65%', backgroundColor: '#83c0e9', borderRadius: 0, padding: 20, maxHeight: '65%', maxWidth: '70%', zIndex: 9, elevation: 9, }, modalHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 15, }, modalTitle: { fontSize: 18, fontWeight: 'bold', color: 'black', }, text: { color: 'black', }, btnCloseSettings: { padding: 5, }, modalBody: { flex: 1, }, formCheckGroup: { marginBottom: 10, }, formCheck: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10, }, sep: { height: 1, backgroundColor: '#ffffff', marginVertical: 2, }, hr: { height: 1, backgroundColor: 'black', marginVertical: 5, }, input: { fontSize: 14, paddingVertical: 4, paddingHorizontal: 8, borderWidth: 1, borderColor: 'gray', borderRadius: 4, color: 'black', paddingRight: 20, backgroundColor: 'white', }, disabledInput: { backgroundColor: '#f2f2f2', }, formGroup: { marginBottom: 10, }, label: { fontSize: 14, color: 'black', marginBottom: 5, }, modalFooter: { marginTop: 10, flexDirection: 'row', justifyContent: 'flex-end', }, btnApplySettings: { flex: 1, padding: 5, borderRadius: 5, justifyContent: 'center', alignItems: 'center', backgroundColor: 'black', }, btnText: { color: 'white', fontSize: 14, }, icon: { fontSize: 24, color: 'black', }, row: { flexDirection: 'row', marginBottom: 10, }, col5: { flex: 5, }, col3: { flex: 3, alignItems: 'center', }, col4: { flex: 4, alignItems: 'center', }, }); const pickerSelectStyles = StyleSheet.create({ inputIOS: { fontSize: 14, paddingVertical: 12, paddingHorizontal: 10, borderWidth: 1, borderColor: 'gray', borderRadius: 4, color: 'black', paddingRight: 30, backgroundColor: 'white', }, inputAndroid: { fontSize: 14, paddingHorizontal: 10, paddingVertical: 8, borderWidth: 0.5, borderColor: 'purple', borderRadius: 8, color: 'black', paddingRight: 30, backgroundColor: 'white', }, inputWeb: { fontSize: 14, paddingHorizontal: 5, paddingVertical: 1, borderWidth: 0.5, borderColor: 'purple', borderRadius: 8, color: 'black', paddingRight: 30, // To ensure the text is never behind the icon backgroundColor: 'white', marginBottom: 10, }, }); //# sourceMappingURL=CoHostModal.js.map