mediasfu-reactnative-expo
Version:
mediasfu-reactnative-expo – Expo-managed React Native WebRTC SDK for video conferencing, webinars, live streaming, broadcast, screen sharing, whiteboard, chat, recording, live subtitles, translation, and AI agent rooms on iOS, Android, and web. Prebuilt r
192 lines • 6.61 kB
JavaScript
// MainContainerComponent.tsx
import React, { useEffect, useState } from 'react';
import { View, StyleSheet, Dimensions, } from 'react-native';
/**
* MainContainerComponent - Top-level responsive layout container
*
* MainContainerComponent is a React Native component that provides the primary
* layout container for the entire meeting interface. It automatically responds
* to window size changes and calculates dimensions based on fractional values,
* enabling consistent layouts across different screen sizes and orientations.
*
* **Key Features:**
* - Responsive dimension calculation based on window size
* - Fractional width/height support (e.g., 0.9 = 90% of window)
* - Automatic recalculation on window resize/rotation
* - Configurable margins and padding
* - Custom background color support
* - Advanced render override hooks
*
* **UI Customization:**
* This component can be replaced via `uiOverrides.mainContainerComponent` to
* provide a completely custom top-level layout container.
*
* @component
* @param {MainContainerComponentOptions} props - Configuration options for the main container
*
* @returns {JSX.Element} Rendered responsive main container
*
* @example
* // Basic usage - Full-screen container
* import React from 'react';
* import { MainContainerComponent } from 'mediasfu-reactnative-expo';
* import { Text } from 'react-native';
*
* function MeetingApp() {
* return (
* <MainContainerComponent backgroundColor="#000000">
* <Text style={{ color: 'white' }}>Meeting Content</Text>
* </MainContainerComponent>
* );
* }
*
* @example
* // With fractional dimensions and margins
* <MainContainerComponent
* backgroundColor="#1a1a1a"
* containerWidthFraction={0.95}
* containerHeightFraction={0.9}
* marginLeft={20}
* marginRight={20}
* marginTop={10}
* marginBottom={10}
* padding={15}
* >
* <MeetingLayout />
* </MainContainerComponent>
*
* @example
* // With custom content renderer (add header/footer)
* <MainContainerComponent
* backgroundColor="white"
* renderContent={({ defaultContent, dimensions }) => (
* <>
* <View style={{ height: 60, backgroundColor: '#007bff' }}>
* <Text>Meeting Header</Text>
* </View>
* {defaultContent}
* <View style={{ height: 40, backgroundColor: '#f0f0f0' }}>
* <Text>Footer - {dimensions.width}x{dimensions.height}</Text>
* </View>
* </>
* )}
* >
* <MeetingContent />
* </MainContainerComponent>
*
* @example
* // Using uiOverrides for complete container replacement
* import { MyCustomMainContainer } from './MyCustomMainContainer';
*
* const sessionConfig = {
* credentials: { apiKey: 'your-api-key' },
* uiOverrides: {
* mainContainerComponent: {
* component: MyCustomMainContainer,
* injectedProps: {
* theme: 'dark',
* showGrid: true,
* },
* },
* },
* };
*
* // MyCustomMainContainer.tsx
* export const MyCustomMainContainer = (props: MainContainerComponentOptions & { theme: string; showGrid: boolean }) => {
* return (
* <View style={{
* flex: 1,
* backgroundColor: props.theme === 'dark' ? '#000' : '#fff',
* borderWidth: props.showGrid ? 1 : 0,
* }}>
* {props.children}
* </View>
* );
* };
*/
const MainContainerComponent = ({ backgroundColor = 'transparent', children, containerWidthFraction = 1, containerHeightFraction = 1, marginLeft = 0, marginRight = 0, marginTop = 0, marginBottom = 0, padding = 0, style, renderContent, renderContainer, }) => {
// State to store calculated aspect styles
const [aspectStyles, setAspectStyles] = useState({
height: Math.floor(containerHeightFraction * Dimensions.get('window').height),
width: Math.floor(containerWidthFraction * Dimensions.get('window').width),
maxHeight: Math.floor(containerHeightFraction * Dimensions.get('window').height),
maxWidth: Math.floor(containerWidthFraction * Dimensions.get('window').width),
});
useEffect(() => {
const updateAspectStyles = ({ window }) => {
const windowHeight = window.height;
const windowWidth = window.width;
setAspectStyles({
height: Math.floor(containerHeightFraction * windowHeight),
width: Math.floor(containerWidthFraction * windowWidth),
maxHeight: Math.floor(containerHeightFraction * windowHeight),
maxWidth: Math.floor(containerWidthFraction * windowWidth),
});
};
// Initial setup
const { width, height } = Dimensions.get('window');
updateAspectStyles({
window: {
width, height, scale: 1, fontScale: 1,
},
screen: {
width, height, scale: 1, fontScale: 1,
},
});
// Subscribe to dimension changes
const subscription = Dimensions.addEventListener('change', updateAspectStyles);
return () => {
// Cleanup listener on component unmount
if (subscription && typeof subscription.remove === 'function') {
subscription.remove();
}
else {
// For older React Native versions
subscription.remove();
}
};
}, [
containerHeightFraction,
containerWidthFraction,
]);
const dimensions = {
width: aspectStyles.width,
height: aspectStyles.height,
};
const defaultContent = children;
const content = renderContent
? renderContent({ defaultContent, dimensions })
: defaultContent;
const defaultContainer = (<View style={[
styles.container,
{
backgroundColor,
marginLeft,
marginRight,
marginTop,
marginBottom,
padding,
height: aspectStyles.height,
width: aspectStyles.width,
maxHeight: aspectStyles.maxHeight,
maxWidth: aspectStyles.maxWidth,
},
style,
]}>
{content}
</View>);
return renderContainer
? renderContainer({ defaultContainer, dimensions })
: defaultContainer;
};
export default MainContainerComponent;
/**
* Stylesheet for the MainContainerComponent.
*/
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 0,
},
});
//# sourceMappingURL=MainContainerComponent.js.map