Skip to content

Commit

Permalink
feat(rn) start listening for stats on the Thumbnail
Browse files Browse the repository at this point in the history
  • Loading branch information
tmoldovan8x8 committed Jan 18, 2022
1 parent 2dfd164 commit cfc4efb
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 13 deletions.
80 changes: 77 additions & 3 deletions react/features/filmstrip/components/native/Thumbnail.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { connect } from '../../../base/redux';
import { StyleType } from '../../../base/styles';
import { getTrackByMediaTypeAndParticipant } from '../../../base/tracks';
import { ConnectionIndicator } from '../../../connection-indicator';
import statsEmitter from '../../../connection-indicator/statsEmitter';
import { DisplayNameLabel } from '../../../display-name';
import {
showConnectionStatus,
Expand Down Expand Up @@ -144,10 +145,17 @@ type Props = {
tileView?: boolean
};

/**
* The type of the React {@code Component} state of {@link Thumbnail}.
*/
type State = {
stats: Object
}

/**
* React component for video thumbnail.
*/
class Thumbnail extends PureComponent<Props> {
class Thumbnail extends PureComponent<Props, State> {

/**
* Creates new Thumbnail component.
Expand All @@ -160,6 +168,48 @@ class Thumbnail extends PureComponent<Props> {

this._onClick = this._onClick.bind(this);
this._onThumbnailLongPress = this._onThumbnailLongPress.bind(this);
this._onStatsUpdated = this._onStatsUpdated.bind(this);

this.state = {
stats: {}
};
}

/**
* Starts listening for stat updates.
*
* @inheritdoc
* returns {void}
*/
componentDidMount() {
statsEmitter.subscribeToClientStats(
this.props.participantID, this._onStatsUpdated);
}

/**
* Updates which user's stats are being listened to.
*
* @inheritdoc
* returns {void}
*/
componentDidUpdate(prevProps: Props) {
if (prevProps.participantID !== this.props.participantID) {
prevProps.participantID && statsEmitter.unsubscribeToClientStats(
prevProps.participantID, this._onStatsUpdated);
this.props.participantID && statsEmitter.subscribeToClientStats(
this.props.participantID, this._onStatsUpdated);
}
}

/**
* Stop listening for stat updates.
*
* @inheritdoc
* returns {void}
*/
componentWillUnmount() {
this.props.participantID && statsEmitter.unsubscribeToClientStats(
this.props.participantID, this._onStatsUpdated);
}

_onClick: () => void;
Expand Down Expand Up @@ -188,20 +238,44 @@ class Thumbnail extends PureComponent<Props> {
*/
_onThumbnailLongPress() {
const { _participantId, _local, _isFakeParticipant, _localVideoOwner, dispatch } = this.props;
const { stats } = this.state;

if (_isFakeParticipant && _localVideoOwner) {
dispatch(showSharedVideoMenu(_participantId));
}

if (!_isFakeParticipant) {
if (_local) {
dispatch(showConnectionStatus(_participantId));
dispatch(showConnectionStatus({
initialStats: stats,
participantId: _participantId
}));
} else {
dispatch(showContextMenuDetails(_participantId));
dispatch(showContextMenuDetails({
initialStats: stats,
participantId: _participantId
}));
}
}
}

_onStatsUpdated: Object => void;

/**
* Callback invoked when new connection stats associated with the passed in
* user ID are available. Will update the component's display of current
* statistics.
*
* @param {Object} stats - Connection stats from the library.
* @private
* @returns {void}
*/
_onStatsUpdated(stats = {}) {
this.setState({
stats
});
}

/**
* Renders the indicators for the thumbnail.
*
Expand Down
8 changes: 4 additions & 4 deletions react/features/participants-pane/actions.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ export function showContextMenuReject(participant: Object) {
* @param {string} participantID - The selected meeting participant id.
* @returns {Function}
*/
export function showConnectionStatus(participantID: string) {
return openDialog(ConnectionStatusComponent, { participantID });
export function showConnectionStatus(options) {
return openDialog(ConnectionStatusComponent, options);
}

/**
Expand All @@ -39,8 +39,8 @@ export function showConnectionStatus(participantID: string) {
* @param {string} participantId - The ID of the selected meeting participant.
* @returns {Function}
*/
export function showContextMenuDetails(participantId: string) {
return openDialog(RemoteVideoMenu, { participantId });
export function showContextMenuDetails(options) {
return openDialog(RemoteVideoMenu, options);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,9 @@ class MeetingParticipantItem extends PureComponent<Props> {
dispatch(showSharedVideoMenu(_participantID));
} else if (!_isFakeParticipant) {
if (_local) {
dispatch(showConnectionStatus(_participantID));
dispatch(showConnectionStatus({ participantId: _participantID }));
} else {
dispatch(showContextMenuDetails(_participantID));
dispatch(showContextMenuDetails({ participantId: _participantID }));
}
} // else no-op
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ export type Props = AbstractButtonProps & {
*/
dispatch: Function,

/**
* Connection stats passed from the previous component.
*/
initialStats: Object,

/**
* The ID of the participant that this button is supposed to pin.
*/
Expand All @@ -40,9 +45,10 @@ class ConnectionStatusButton extends AbstractButton<Props, *> {
* @returns {void}
*/
_handleClick() {
const { dispatch, participantID } = this.props;
const { dispatch, participantID, initialStats } = this.props;

dispatch(openDialog(ConnectionStatusComponent, {
initialStats,
participantID
}));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ export type Props = {
*/
dispatch: Function,

/**
* Connection stats passed from the previous component.
*/
initialStats: Object,

/**
* The ID of the participant that this button is supposed to pin.
*/
Expand Down Expand Up @@ -114,6 +119,8 @@ class ConnectionStatusComponent extends Component<Props, State> {
codecString: 'N/A',
connectionString: 'N/A'
};

this.state = this._buildState(this.props.initialStats);
}

/**
Expand Down Expand Up @@ -228,6 +235,17 @@ class ConnectionStatusComponent extends Component<Props, State> {
}
}

/**
* Stop listening for stat updates.
*
* @inheritdoc
* returns {void}
*/
componentWillUnmount() {
statsEmitter.unsubscribeToClientStats(
this.props.participantID, this._onStatsUpdated);
}

_onStatsUpdated: Object => void;

/**
Expand All @@ -252,7 +270,7 @@ class ConnectionStatusComponent extends Component<Props, State> {
* @private
* @returns {State}
*/
_buildState(stats) {
_buildState(stats = {}) {
const { download: downloadBitrate, upload: uploadBitrate } = this._extractBitrate(stats) ?? {};

const { download: downloadPacketLost, upload: uploadPacketLost } = this._extractPacketLost(stats) ?? {};
Expand Down
13 changes: 11 additions & 2 deletions react/features/video-menu/components/native/RemoteVideoMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ type Props = {
*/
_disableGrantModerator: Boolean,

/**
* Connection stats passed from the previous component.
*/
_initialStats: Object,

/**
* True if the menu is currently open, false otherwise.
*/
Expand Down Expand Up @@ -130,6 +135,7 @@ class RemoteVideoMenu extends PureComponent<Props> {
_disableKick,
_disableRemoteMute,
_disableGrantModerator,
_initialStats,
_isParticipantAvailable,
_rooms,
_currentRoomId,
Expand Down Expand Up @@ -157,7 +163,9 @@ class RemoteVideoMenu extends PureComponent<Props> {
{ !_disableGrantModerator && <GrantModeratorButton { ...buttonProps } /> }
<PinButton { ...buttonProps } />
<PrivateMessageButton { ...buttonProps } />
<ConnectionStatusButton { ...buttonProps } />
<ConnectionStatusButton
initialStats = { _initialStats }
{ ...buttonProps } />
{_rooms.length > 1 && <>
<Divider style = { styles.divider } />
<View style = { styles.contextMenuItem }>
Expand Down Expand Up @@ -229,7 +237,7 @@ class RemoteVideoMenu extends PureComponent<Props> {
*/
function _mapStateToProps(state, ownProps) {
const kickOutEnabled = getFeatureFlag(state, KICK_OUT_ENABLED, true);
const { participantId } = ownProps;
const { initialStats, participantId } = ownProps;
const { remoteVideoMenu = {}, disableRemoteMute } = state['features/base/config'];
const isParticipantAvailable = getParticipantById(state, participantId);
let { disableKick } = remoteVideoMenu;
Expand All @@ -243,6 +251,7 @@ function _mapStateToProps(state, ownProps) {
_currentRoomId,
_disableKick: Boolean(disableKick),
_disableRemoteMute: Boolean(disableRemoteMute),
_initialStats: initialStats,
_isOpen: isDialogOpen(state, RemoteVideoMenu_),
_isParticipantAvailable: Boolean(isParticipantAvailable),
_participantDisplayName: getParticipantDisplayName(state, participantId),
Expand Down

0 comments on commit cfc4efb

Please sign in to comment.