jiti-meet/react/features/filmstrip/components/native/TileView.js

282 lines
7.7 KiB
JavaScript
Raw Normal View History

// @flow
import React, { PureComponent } from 'react';
import {
FlatList,
TouchableWithoutFeedback,
View
} from 'react-native';
2019-03-19 15:42:25 +00:00
import type { Dispatch } from 'redux';
feat: Participants optimisations (#9515) * fix(participants): Change from array to Map * fix(unload): optimise * feat: Introduces new states for e2ee feature. Stores everyoneSupportsE2EE and everyoneEnabledE2EE to minimize looping through participants list. squash: Uses participants map and go over the elements only once. * feat: Optimizes isEveryoneModerator to do less frequent checks in all participants. * fix: Drops deep equal from participants pane and uses the map. * fix(SharedVideo): isVideoPlaying * fix(participants): Optimise isEveryoneModerator * fix(e2e): Optimise everyoneEnabledE2EE * fix: JS errors. * ref(participants): remove getParticipants * fix(participants): Prepare for PR. * fix: Changes participants pane to be component. The functional component was always rendered: `prev props: {} !== {} :next props`. * feat: Optimization to skip participants list on pane closed. * fix: The participants list shows and the local participant. * fix: Fix wrong action name for av-moderation. * fix: Minimizes the number of render calls of av moderation notification. * fix: Fix iterating over remote participants. * fix: Fixes lint error. * fix: Reflects participant updates for av-moderation. * fix(ParticipantPane): to work with IDs. * fix(av-moderation): on PARTCIPANT_UPDATE * fix(ParticipantPane): close delay. * fix: address code review comments * fix(API): mute-everyone * fix: bugs * fix(Thumbnail): on mobile. * fix(ParticipantPane): Close context menu on click. * fix: Handles few error when local participant is undefined. * feat: Hides AV moderation if not supported. * fix: Show mute all video. * fix: Fixes updating participant for av moderation. Co-authored-by: damencho <damencho@jitsi.org>
2021-07-09 12:36:19 +00:00
import { getLocalParticipant, getParticipantCountWithFake } from '../../../base/participants';
2019-03-21 16:38:29 +00:00
import { connect } from '../../../base/redux';
import { setVisibleRemoteParticipants } from '../../actions.web';
import Thumbnail from './Thumbnail';
import styles from './styles';
/**
* The type of the React {@link Component} props of {@link TileView}.
*/
type Props = {
/**
* Application's aspect ratio.
*/
_aspectRatio: Symbol,
/**
* The number of columns.
*/
_columns: number,
/**
* Application's viewport height.
*/
_height: number,
/**
feat: Participants optimisations (#9515) * fix(participants): Change from array to Map * fix(unload): optimise * feat: Introduces new states for e2ee feature. Stores everyoneSupportsE2EE and everyoneEnabledE2EE to minimize looping through participants list. squash: Uses participants map and go over the elements only once. * feat: Optimizes isEveryoneModerator to do less frequent checks in all participants. * fix: Drops deep equal from participants pane and uses the map. * fix(SharedVideo): isVideoPlaying * fix(participants): Optimise isEveryoneModerator * fix(e2e): Optimise everyoneEnabledE2EE * fix: JS errors. * ref(participants): remove getParticipants * fix(participants): Prepare for PR. * fix: Changes participants pane to be component. The functional component was always rendered: `prev props: {} !== {} :next props`. * feat: Optimization to skip participants list on pane closed. * fix: The participants list shows and the local participant. * fix: Fix wrong action name for av-moderation. * fix: Minimizes the number of render calls of av moderation notification. * fix: Fix iterating over remote participants. * fix: Fixes lint error. * fix: Reflects participant updates for av-moderation. * fix(ParticipantPane): to work with IDs. * fix(av-moderation): on PARTCIPANT_UPDATE * fix(ParticipantPane): close delay. * fix: address code review comments * fix(API): mute-everyone * fix: bugs * fix(Thumbnail): on mobile. * fix(ParticipantPane): Close context menu on click. * fix: Handles few error when local participant is undefined. * feat: Hides AV moderation if not supported. * fix: Show mute all video. * fix: Fixes updating participant for av moderation. Co-authored-by: damencho <damencho@jitsi.org>
2021-07-09 12:36:19 +00:00
* The local participant.
*/
feat: Participants optimisations (#9515) * fix(participants): Change from array to Map * fix(unload): optimise * feat: Introduces new states for e2ee feature. Stores everyoneSupportsE2EE and everyoneEnabledE2EE to minimize looping through participants list. squash: Uses participants map and go over the elements only once. * feat: Optimizes isEveryoneModerator to do less frequent checks in all participants. * fix: Drops deep equal from participants pane and uses the map. * fix(SharedVideo): isVideoPlaying * fix(participants): Optimise isEveryoneModerator * fix(e2e): Optimise everyoneEnabledE2EE * fix: JS errors. * ref(participants): remove getParticipants * fix(participants): Prepare for PR. * fix: Changes participants pane to be component. The functional component was always rendered: `prev props: {} !== {} :next props`. * feat: Optimization to skip participants list on pane closed. * fix: The participants list shows and the local participant. * fix: Fix wrong action name for av-moderation. * fix: Minimizes the number of render calls of av moderation notification. * fix: Fix iterating over remote participants. * fix: Fixes lint error. * fix: Reflects participant updates for av-moderation. * fix(ParticipantPane): to work with IDs. * fix(av-moderation): on PARTCIPANT_UPDATE * fix(ParticipantPane): close delay. * fix: address code review comments * fix(API): mute-everyone * fix: bugs * fix(Thumbnail): on mobile. * fix(ParticipantPane): Close context menu on click. * fix: Handles few error when local participant is undefined. * feat: Hides AV moderation if not supported. * fix: Show mute all video. * fix: Fixes updating participant for av moderation. Co-authored-by: damencho <damencho@jitsi.org>
2021-07-09 12:36:19 +00:00
_localParticipant: Object,
/**
* The number of participants in the conference.
*/
_participantCount: number,
/**
* An array with the IDs of the remote participants in the conference.
*/
_remoteParticipants: Array<string>,
/**
* The thumbnail height.
*/
_thumbnailHeight: number,
/**
* Application's viewport height.
*/
_width: number,
/**
* Invoked to update the receiver video quality.
*/
dispatch: Dispatch<any>,
/**
* Callback to invoke when tile view is tapped.
*/
onClick: Function
};
/**
* An empty array. The purpose of the constant is to use the same reference every time we need an empty array.
* This will prevent unnecessary re-renders.
*/
const EMPTY_ARRAY = [];
/**
* Implements a React {@link PureComponent} which displays thumbnails in a two
* dimensional grid.
*
2021-11-04 21:10:43 +00:00
* @augments PureComponent
*/
class TileView extends PureComponent<Props> {
/**
2021-08-30 14:50:24 +00:00
* The styles for the content container of the FlatList.
*/
2021-08-30 14:50:24 +00:00
_contentContainerStyles: Object;
/**
* The styles for the FlatList.
*/
_flatListStyles: Object;
/**
2021-08-30 14:50:24 +00:00
* The FlatList's viewabilityConfig.
*/
2021-08-30 14:50:24 +00:00
_viewabilityConfig: Object;
/**
* Creates new TileView component.
*
* @param {Props} props - The props of the component.
*/
constructor(props: Props) {
super(props);
this._keyExtractor = this._keyExtractor.bind(this);
this._onViewableItemsChanged = this._onViewableItemsChanged.bind(this);
this._renderThumbnail = this._renderThumbnail.bind(this);
this._viewabilityConfig = {
itemVisiblePercentThreshold: 30,
minimumViewTime: 500
};
this._flatListStyles = {
...styles.flatListTileView
};
this._contentContainerStyles = {
...styles.contentContainer
};
}
_keyExtractor: string => string;
/**
* Returns a key for a passed item of the list.
*
* @param {string} item - The user ID.
* @returns {string} - The user ID.
*/
_keyExtractor(item) {
return item;
}
_onViewableItemsChanged: Object => void;
/**
* A handler for visible items changes.
*
* @param {Object} data - The visible items data.
* @param {Array<Object>} data.viewableItems - The visible items array.
* @returns {void}
*/
_onViewableItemsChanged({ viewableItems = [] }: { viewableItems: Array<Object> }) {
if (viewableItems[0]?.index === 0) {
// Skip the local thumbnail.
viewableItems.shift();
}
if (viewableItems.length === 0) {
// User might be fast-scrolling, it will stabilize.
return;
}
// We are off by one in the remote participants array.
const startIndex = viewableItems[0].index - 1;
const endIndex = viewableItems[viewableItems.length - 1].index - 1;
this.props.dispatch(setVisibleRemoteParticipants(startIndex, endIndex));
}
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
* @returns {ReactElement}
*/
render() {
const { _columns, _height, _thumbnailHeight, _width, onClick } = this.props;
const participants = this._getSortedParticipants();
const initialRowsToRender = Math.ceil(_height / (_thumbnailHeight + (2 * styles.thumbnail.margin)));
if (this._flatListStyles.minHeight !== _height || this._flatListStyles.minWidth !== _width) {
this._flatListStyles = {
...styles.flatListTileView,
minHeight: _height,
minWidth: _width
};
}
if (this._contentContainerStyles.minHeight !== _height || this._contentContainerStyles.minWidth !== _width) {
this._contentContainerStyles = {
...styles.contentContainer,
minHeight: _height,
minWidth: _width
};
}
return (
<TouchableWithoutFeedback onPress = { onClick }>
<View style = { styles.flatListContainer }>
<FlatList
bounces = { false }
contentContainerStyle = { this._contentContainerStyles }
data = { participants }
horizontal = { false }
initialNumToRender = { initialRowsToRender }
key = { _columns }
keyExtractor = { this._keyExtractor }
numColumns = { _columns }
onViewableItemsChanged = { this._onViewableItemsChanged }
renderItem = { this._renderThumbnail }
showsHorizontalScrollIndicator = { false }
showsVerticalScrollIndicator = { false }
style = { this._flatListStyles }
viewabilityConfig = { this._viewabilityConfig }
windowSize = { 2 } />
</View>
</TouchableWithoutFeedback>
);
}
/**
* Returns all participants with the local participant at the end.
*
* @private
* @returns {Participant[]}
*/
_getSortedParticipants() {
feat: Participants optimisations (#9515) * fix(participants): Change from array to Map * fix(unload): optimise * feat: Introduces new states for e2ee feature. Stores everyoneSupportsE2EE and everyoneEnabledE2EE to minimize looping through participants list. squash: Uses participants map and go over the elements only once. * feat: Optimizes isEveryoneModerator to do less frequent checks in all participants. * fix: Drops deep equal from participants pane and uses the map. * fix(SharedVideo): isVideoPlaying * fix(participants): Optimise isEveryoneModerator * fix(e2e): Optimise everyoneEnabledE2EE * fix: JS errors. * ref(participants): remove getParticipants * fix(participants): Prepare for PR. * fix: Changes participants pane to be component. The functional component was always rendered: `prev props: {} !== {} :next props`. * feat: Optimization to skip participants list on pane closed. * fix: The participants list shows and the local participant. * fix: Fix wrong action name for av-moderation. * fix: Minimizes the number of render calls of av moderation notification. * fix: Fix iterating over remote participants. * fix: Fixes lint error. * fix: Reflects participant updates for av-moderation. * fix(ParticipantPane): to work with IDs. * fix(av-moderation): on PARTCIPANT_UPDATE * fix(ParticipantPane): close delay. * fix: address code review comments * fix(API): mute-everyone * fix: bugs * fix(Thumbnail): on mobile. * fix(ParticipantPane): Close context menu on click. * fix: Handles few error when local participant is undefined. * feat: Hides AV moderation if not supported. * fix: Show mute all video. * fix: Fixes updating participant for av moderation. Co-authored-by: damencho <damencho@jitsi.org>
2021-07-09 12:36:19 +00:00
const { _localParticipant, _remoteParticipants } = this.props;
if (!_localParticipant) {
return EMPTY_ARRAY;
}
return [ _localParticipant?.id, ..._remoteParticipants ];
}
_renderThumbnail: Object => Object;
/**
* Creates React Element to display each participant in a thumbnail.
*
* @private
* @returns {ReactElement}
*/
_renderThumbnail({ item/* , index , separators */ }) {
const { _thumbnailHeight } = this.props;
return (
<Thumbnail
disableTint = { true }
height = { _thumbnailHeight }
key = { item }
participantID = { item }
renderDisplayName = { true }
tileView = { true } />)
;
}
}
/**
* Maps (parts of) the redux state to the associated {@code TileView}'s props.
*
* @param {Object} state - The redux state.
* @private
* @returns {Props}
*/
function _mapStateToProps(state) {
const responsiveUi = state['features/base/responsive-ui'];
const { remoteParticipants, tileViewDimensions } = state['features/filmstrip'];
const { height } = tileViewDimensions.thumbnailSize;
const { columns } = tileViewDimensions;
return {
_aspectRatio: responsiveUi.aspectRatio,
_columns: columns,
_height: responsiveUi.clientHeight,
feat: Participants optimisations (#9515) * fix(participants): Change from array to Map * fix(unload): optimise * feat: Introduces new states for e2ee feature. Stores everyoneSupportsE2EE and everyoneEnabledE2EE to minimize looping through participants list. squash: Uses participants map and go over the elements only once. * feat: Optimizes isEveryoneModerator to do less frequent checks in all participants. * fix: Drops deep equal from participants pane and uses the map. * fix(SharedVideo): isVideoPlaying * fix(participants): Optimise isEveryoneModerator * fix(e2e): Optimise everyoneEnabledE2EE * fix: JS errors. * ref(participants): remove getParticipants * fix(participants): Prepare for PR. * fix: Changes participants pane to be component. The functional component was always rendered: `prev props: {} !== {} :next props`. * feat: Optimization to skip participants list on pane closed. * fix: The participants list shows and the local participant. * fix: Fix wrong action name for av-moderation. * fix: Minimizes the number of render calls of av moderation notification. * fix: Fix iterating over remote participants. * fix: Fixes lint error. * fix: Reflects participant updates for av-moderation. * fix(ParticipantPane): to work with IDs. * fix(av-moderation): on PARTCIPANT_UPDATE * fix(ParticipantPane): close delay. * fix: address code review comments * fix(API): mute-everyone * fix: bugs * fix(Thumbnail): on mobile. * fix(ParticipantPane): Close context menu on click. * fix: Handles few error when local participant is undefined. * feat: Hides AV moderation if not supported. * fix: Show mute all video. * fix: Fixes updating participant for av moderation. Co-authored-by: damencho <damencho@jitsi.org>
2021-07-09 12:36:19 +00:00
_localParticipant: getLocalParticipant(state),
_participantCount: getParticipantCountWithFake(state),
_remoteParticipants: remoteParticipants,
_thumbnailHeight: height,
_width: responsiveUi.clientWidth
};
}
export default connect(_mapStateToProps)(TileView);