UNPKG

@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
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