mediasfu-reactnative
Version:
MediaSFU Prebuilt React Native SDK
181 lines • 6.44 kB
JavaScript
// FlexibleVideo.tsx
import React, { useEffect, useState } from 'react';
import { View, StyleSheet } from 'react-native';
/**
* FlexibleVideo is a React Native component that renders a flexible video grid with optional screenboard overlay
* and annotation capabilities.
*
* This component arranges components in a grid layout with specified rows and columns. It supports custom item
* dimensions, optional screenboard overlay, and video stream annotation.
*
* @component
* @param {FlexibleVideoOptions} props - Options to configure the FlexibleVideo component.
* @param {number} props.customWidth - Width of each grid item.
* @param {number} props.customHeight - Height of each grid item.
* @param {number} props.rows - Number of rows in the grid.
* @param {number} props.columns - Number of columns in the grid.
* @param {React.ReactNode[]} props.componentsToRender - Components or elements to display in the grid.
* @param {boolean} [props.showAspect=false] - Controls whether the aspect ratio is enforced.
* @param {string} [props.backgroundColor='transparent'] - Background color for each grid item.
* @param {React.ReactNode} [props.Screenboard] - Overlay component for the video grid.
* @param {boolean} [props.annotateScreenStream=false] - Enables screen stream annotation.
* @param {MediaStream} [props.localStreamScreen] - Media stream for local screen annotation.
*
* @returns {JSX.Element} The rendered FlexibleVideo component.
*
* @example
* ```tsx
* import React from 'react';
* import { FlexibleVideo } from 'mediasfu-reactnative';
*
* function App() {
* const videoComponents = [
* <RTCView streamURL="stream1" />,
* <RTCView streamURL="stream2" />,
* ];
*
* return (
* <FlexibleVideo
* customWidth={200}
* customHeight={150}
* rows={2}
* columns={2}
* componentsToRender={videoComponents}
* showAspect={true}
* backgroundColor="black"
* Screenboard={<Text>Overlay Component</Text>}
* annotateScreenStream={true}
* localStreamScreen={myLocalStream}
* />
* );
* }
*
* export default App;
* ```
*/
const FlexibleVideo = ({ customWidth, customHeight, rows, columns, componentsToRender, showAspect = false, backgroundColor = 'transparent', Screenboard, annotateScreenStream = false, localStreamScreen, }) => {
const [key, setKey] = useState(0);
const [cardWidth, setCardWidth] = useState(customWidth);
const [cardHeight, setCardHeight] = useState(customHeight);
const [, setCardTop] = useState(0);
const [cardLeft, setCardLeft] = useState(0);
const [canvasLeft, setCanvasLeft] = useState(0);
useEffect(() => {
setKey((prevKey) => prevKey + 1);
}, [columns]);
useEffect(() => {
if (annotateScreenStream && localStreamScreen) {
const videoTrack = localStreamScreen.getVideoTracks()[0];
const videoSettings = videoTrack.getSettings();
const videoHeight = videoSettings.height || customHeight;
const videoWidth = videoSettings.width || customWidth;
setCardWidth(videoWidth);
setCardHeight(videoHeight);
setCardTop(Math.floor((customHeight - videoHeight) / 2));
setCardLeft(Math.floor((customWidth - videoWidth) / 2));
setCanvasLeft(cardLeft < 0 ? cardLeft : 0);
}
else {
setCardWidth(customWidth);
setCardHeight(customHeight);
setCardTop(0);
setCardLeft(0);
setCanvasLeft(0);
}
}, [
customWidth,
customHeight,
localStreamScreen,
annotateScreenStream,
cardLeft,
]);
/**
* Renders the grid layout based on the number of rows and columns.
*
* @returns {React.ReactNode[]} Array of React elements representing the grid.
*/
const renderGrid = () => {
const grid = [];
for (let row = 0; row < rows; row++) {
const rowComponents = [];
for (let col = 0; col < columns; col++) {
const index = row * columns + col;
const component = componentsToRender[index];
rowComponents.push(<View key={col} style={[
styles.gridItem,
{
width: cardWidth,
height: cardHeight,
backgroundColor,
margin: 1,
padding: 0,
borderRadius: 0,
left: cardLeft,
},
]}>
{component}
</View>);
}
grid.push(<View key={row} style={styles.rowContainer}>
{rowComponents}
</View>);
}
return grid;
};
return (<View key={key} style={[
styles.gridContainer,
{
padding: 0,
flex: 1,
margin: 0,
position: 'relative',
display: showAspect ? 'flex' : 'none',
maxWidth: customWidth,
overflow: 'hidden',
left: cardLeft > 0 ? cardLeft : 0,
},
]}>
{renderGrid()}
{Screenboard && (<View style={[
styles.screenboardOverlay,
{
top: 0,
left: canvasLeft,
width: cardWidth,
height: cardHeight,
backgroundColor: 'rgba(0, 0, 0, 0.005)',
zIndex: 2,
},
]}>
{Screenboard}
</View>)}
</View>);
};
export default FlexibleVideo;
/**
* Stylesheet for the FlexibleVideo component.
*/
const styles = StyleSheet.create({
gridContainer: {
// Additional container styles can be added here if needed
},
rowContainer: {
flexDirection: 'row',
},
gridItem: {
flex: 1,
margin: 1,
padding: 0,
borderRadius: 0,
},
screenboardOverlay: {
position: 'absolute',
top: 0,
left: 0,
// width and height are set dynamically via inline styles
backgroundColor: 'rgba(0, 0, 0, 0.005)',
zIndex: 2,
// Additional overlay styles can be added here
},
});
//# sourceMappingURL=FlexibleVideo.js.map