@100mslive/react-native-room-kit
Version:
100ms Room Kit provides simple & easy to use UI components to build Live Streaming & Video Conferencing experiences in your apps.
257 lines (252 loc) • 10 kB
JavaScript
import React, { useRef, useState, useImperativeHandle } from 'react';
import { View, FlatList, StyleSheet, Platform } from 'react-native';
import { useDispatch, useSelector } from 'react-redux';
import { useSafeAreaFrame } from 'react-native-safe-area-context';
import { DefaultModal } from './DefaultModal';
import { SaveScreenshot } from './Modals';
import { TilesContainer } from './TilesContainer';
import { MiniView } from './MiniView';
import { PaginationDots } from './PaginationDots';
import { setGridViewActivePage } from '../redux/actions';
import { Tile } from './Tile';
import { useIsLandscapeOrientation } from '../utils/dimension';
import { WhiteboardContainer } from './WhiteboardContainer';
const FLATLIST_VIEWABILITY_CONFIG = {
waitForInteraction: true,
itemVisiblePercentThreshold: 80
};
export const GridView = /*#__PURE__*/React.forwardRef(({
pairedPeers,
onPeerTileMorePress
}, ref) => {
const [screenshotData, setScreenshotData] = useState(null);
const hmsViewRefs = useRef({});
const regularTilesFlatlistRef = useRef(null);
const screenshareTilesFlatlistRef = useRef(null);
const [insetTileBoundingBox, setInsetTileBoundingBox] = useState({
width: null,
height: null
});
const screenshareTilesAvailable = useSelector(state => state.app.screensharePeerTrackNodes.length > 0);
const whiteboardActive = useSelector(state => !!state.hmsStates.whiteboard);
const regularTilesAvailable = pairedPeers.length > 0;
const isLandscapeOrientation = useIsLandscapeOrientation();
// On Orientation change, scroll to first page of list
React.useEffect(() => {
if (screenshareTilesAvailable) {
var _screenshareTilesFlat;
(_screenshareTilesFlat = screenshareTilesFlatlistRef.current) === null || _screenshareTilesFlat === void 0 || _screenshareTilesFlat.scrollToOffset({
offset: 0,
animated: false
});
}
}, [screenshareTilesAvailable, isLandscapeOrientation]);
// On Orientation change, scroll to first page of list
React.useEffect(() => {
if (regularTilesAvailable) {
var _regularTilesFlatlist;
(_regularTilesFlatlist = regularTilesFlatlistRef.current) === null || _regularTilesFlatlist === void 0 || _regularTilesFlatlist.scrollToOffset({
offset: 0,
animated: false
});
}
}, [regularTilesAvailable, isLandscapeOrientation]);
const miniviewPeerTrackNodeExists = useSelector(state => !!state.app.miniviewPeerTrackNode);
// We are setting `captureViewScreenshot` method on ref passed to GridView component
// `captureViewScreenshot` method can be called to with PeerTrackNode to capture the HmsView Snapshot
useImperativeHandle(ref, () => ({
captureViewScreenshot: node => {
var _hmsViewRef$capture;
// getting HmsView ref for the passed PeerTrackNode
const hmsViewRef = hmsViewRefs.current[node.id];
// If HmsView is not rendered on Tile, then HmsView ref will be `undefined`
if (!hmsViewRef) {
console.warn(`HmsViewRef for "${node.id}" is not available!`);
return;
}
// Calling `capture` method on HmsView ref
(_hmsViewRef$capture = hmsViewRef.capture) === null || _hmsViewRef$capture === void 0 || _hmsViewRef$capture.call(hmsViewRef).then(imageBase64 => {
console.log('HmsView Capture Success');
// Saving data needed to show captured snapshot in "Save Snapshot" Modal
setScreenshotData({
peer: node.peer,
source: {
uri: `data:image/png;base64,${imageBase64}`
}
});
}).catch(error => console.warn('HmsView Capture Error: ', error));
},
getRegularTilesFlatlistRef: () => {
return regularTilesFlatlistRef;
},
getScreenshareTilesFlatlistRef: () => {
return screenshareTilesFlatlistRef;
}
}), []);
const setHmsViewRefs = React.useCallback((viewId, ref) => {
hmsViewRefs.current[viewId] = ref;
}, []);
const _handleLayoutChange = React.useCallback(({
nativeEvent
}) => {
setInsetTileBoundingBox({
width: nativeEvent.layout.width,
height: nativeEvent.layout.height
});
}, []);
return /*#__PURE__*/React.createElement(View, {
style: [styles.container]
}, /*#__PURE__*/React.createElement(View, {
onLayout: _handleLayoutChange,
style: styles.measureLayoutView
}), screenshareTilesAvailable ? /*#__PURE__*/React.createElement(ScreenshareTiles, {
ref: screenshareTilesFlatlistRef,
setHmsViewRefs: setHmsViewRefs,
onPeerTileMorePress: onPeerTileMorePress
}) : whiteboardActive ? /*#__PURE__*/React.createElement(WhiteboardContainer, null) : null, (whiteboardActive || screenshareTilesAvailable) && isLandscapeOrientation ? null : /*#__PURE__*/React.createElement(RegularTiles, {
ref: regularTilesFlatlistRef,
pairedPeers: pairedPeers,
setHmsViewRefs: setHmsViewRefs,
onPeerTileMorePress: onPeerTileMorePress
}), pairedPeers.length > 0 && miniviewPeerTrackNodeExists ? /*#__PURE__*/React.createElement(MiniView, {
boundingBoxWidth: insetTileBoundingBox.width,
boundingBoxHeight: insetTileBoundingBox.height,
onMoreOptionsPress: onPeerTileMorePress
}) : null, /*#__PURE__*/React.createElement(DefaultModal, {
modalPosiion: "center",
modalVisible: !!screenshotData,
setModalVisible: () => setScreenshotData(null)
}, /*#__PURE__*/React.createElement(SaveScreenshot, {
imageSource: screenshotData === null || screenshotData === void 0 ? void 0 : screenshotData.source,
cancelModal: () => setScreenshotData(null)
})));
});
GridView.displayName = 'GridView';
const styles = StyleSheet.create({
container: {
flex: 1,
position: 'relative'
},
measureLayoutView: {
position: 'absolute',
width: '100%',
height: '100%'
}
});
const RegularTiles = /*#__PURE__*/React.forwardRef(({
pairedPeers,
onPeerTileMorePress,
setHmsViewRefs
}, flatlistRef) => {
const dispatch = useDispatch();
const {
height: safeHeight
} = useSafeAreaFrame();
const screenshareTilesOrWhiteboardActive = useSelector(state => state.app.screensharePeerTrackNodes.length > 0 || !!state.hmsStates.whiteboard);
const activeIndex = useSelector(state => state.app.gridViewActivePage);
const isLandscapeOrientation = useIsLandscapeOrientation();
const _keyExtractor = React.useCallback(item => {
var _item$;
return (_item$ = item[0]) === null || _item$ === void 0 ? void 0 : _item$.id;
}, []);
const _handleViewableItemsChanged = React.useCallback(info => {
const firstViewable = info.viewableItems[0];
if (firstViewable !== null && firstViewable !== void 0 && firstViewable.isViewable && typeof firstViewable.index === 'number') {
dispatch(setGridViewActivePage(firstViewable.index));
}
}, []);
const _renderItem = React.useCallback(({
item
}) => {
return /*#__PURE__*/React.createElement(TilesContainer, {
onPeerTileMorePress: onPeerTileMorePress,
peerTrackNodes: item,
setHmsViewRefs: setHmsViewRefs
});
}, [onPeerTileMorePress, setHmsViewRefs]);
return /*#__PURE__*/React.createElement(View, {
style: {
flex: screenshareTilesOrWhiteboardActive ? undefined : 1
}
}, /*#__PURE__*/React.createElement(FlatList, {
ref: flatlistRef,
horizontal: true,
style: Platform.OS === 'ios' ? {
maxHeight: safeHeight - (isLandscapeOrientation ? 0 : 16)
} : null,
data: pairedPeers,
initialNumToRender: 1,
maxToRenderPerBatch: 1,
windowSize: 2,
pagingEnabled: true,
showsHorizontalScrollIndicator: false,
renderItem: _renderItem,
numColumns: 1,
keyExtractor: _keyExtractor,
onViewableItemsChanged: _handleViewableItemsChanged,
viewabilityConfig: FLATLIST_VIEWABILITY_CONFIG
}), pairedPeers.length > 1 ? /*#__PURE__*/React.createElement(PaginationDots, {
list: pairedPeers,
activeIndex: activeIndex,
style: screenshareTilesOrWhiteboardActive || isLandscapeOrientation ? {
marginVertical: isLandscapeOrientation ? 4 : 8
} : null
}) : null);
});
const ScreenshareTiles = /*#__PURE__*/React.forwardRef(({
onPeerTileMorePress,
setHmsViewRefs
}, flatlistRef) => {
const {
width: safeWidth
} = useSafeAreaFrame();
const isLandscapeOrientation = useIsLandscapeOrientation();
const [activePage, setActivePage] = useState(0);
const screensharePeerTrackNodes = useSelector(state => state.app.screensharePeerTrackNodes);
const _keyExtractor = React.useCallback(item => item.id, []);
const _handleViewableItemsChanged = React.useCallback(info => {
const firstViewable = info.viewableItems[0];
if (firstViewable !== null && firstViewable !== void 0 && firstViewable.isViewable && typeof firstViewable.index === 'number') {
setActivePage(firstViewable.index);
}
}, []);
const tileWidth = safeWidth;
const _renderItem = React.useCallback(({
item
}) => {
return /*#__PURE__*/React.createElement(Tile, {
height: '100%',
width: tileWidth,
peerTrackNode: item,
onPeerTileMorePress: onPeerTileMorePress,
setHmsViewRefs: setHmsViewRefs
});
}, [tileWidth, onPeerTileMorePress, setHmsViewRefs]);
return /*#__PURE__*/React.createElement(View, {
style: {
flex: 1,
marginBottom: 4
}
}, /*#__PURE__*/React.createElement(FlatList, {
ref: flatlistRef,
horizontal: true,
data: screensharePeerTrackNodes,
initialNumToRender: 1,
maxToRenderPerBatch: 1,
windowSize: 2,
pagingEnabled: true,
showsHorizontalScrollIndicator: false,
renderItem: _renderItem,
numColumns: 1,
keyExtractor: _keyExtractor,
onViewableItemsChanged: _handleViewableItemsChanged,
viewabilityConfig: FLATLIST_VIEWABILITY_CONFIG
}), screensharePeerTrackNodes.length > 1 ? /*#__PURE__*/React.createElement(PaginationDots, {
list: screensharePeerTrackNodes,
activeIndex: activePage,
style: {
marginVertical: isLandscapeOrientation ? 4 : 8
}
}) : null);
});
//# sourceMappingURL=GridView.js.map