[RN] Dynamically adjust LargeView's Avatar to available size

When in PiP mode the LargeView will not be large enough to hold the avatar (for
those interested in the details, our avatar's size is 200, and in PiP mode the
app is resized to about 150).

In order to solve it, this PR refactors how the avatar style is passed along,
reducing it to a single "size" prop. With this only prop, the Avatar compononent
will compute the width, height and borderRadius, plus deal with some Android
shenanigans.

In addition, the LargeView component now uses DimensionsDetector to check its
own size and adjust the size prop passed to the Avatar component as needed.
This commit is contained in:
Saúl Ibarra Corretgé
2018-02-05 11:57:40 +01:00
committed by Lyubo Marinov
parent 4fb37c38eb
commit 1419247801
7 changed files with 135 additions and 59 deletions

View File

@@ -1,12 +1,42 @@
/* @flow */
// @flow
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { ParticipantView } from '../../base/participants';
import { DimensionsDetector } from '../../base/responsive-ui';
import styles from './styles';
import styles, { AVATAR_SIZE } from './styles';
type Props = {
/**
* The ID of the participant (to be) depicted by LargeVideo.
*
* @private
*/
_participantId: string
};
type State = {
/**
* Size for the Avatar. It will be dynamically adjusted based on the
* available size.
*/
avatarSize: number,
/**
* Whether the connectivity indicator will be shown or not. It will be true
* by default, but it may be turned off if there is not enough space.
*/
useConnectivityInfoLabel: boolean
};
const DEFAULT_STATE = {
avatarSize: AVATAR_SIZE,
useConnectivityInfoLabel: true
};
/**
* Implements a React {@link Component} which represents the large video (a.k.a.
@@ -14,21 +44,52 @@ import styles from './styles';
*
* @extends Component
*/
class LargeVideo extends Component<*> {
/**
* LargeVideo component's property types.
*
* @static
*/
static propTypes = {
/**
* The ID of the participant (to be) depicted by LargeVideo.
*
* @private
*/
_participantId: PropTypes.string
class LargeVideo extends Component<Props, State> {
state = {
...DEFAULT_STATE
};
/** Initializes a new {@code LargeVideo} instance.
*
* @param {Object} props - The read-only properties with which the new
* instance is to be initialized.
*/
constructor(props) {
super(props);
this._onDimensionsChanged = this._onDimensionsChanged.bind(this);
}
_onDimensionsChanged: (width: number, height: number) => void;
/**
* Handle this component's dimension changes. In case we deem it's too
* small, the connectivity indicator won't be rendered and the avatar
* will occupy the entirety of the available screen state.
*
* @param {number} width - The component's current width.
* @param {number} height - The component's current height.
* @private
* @returns {void}
*/
_onDimensionsChanged(width: number, height: number) {
// Get the size, rounded to the nearest even number.
const size = 2 * Math.round(Math.min(height, width) / 2);
let newState;
if (size < AVATAR_SIZE * 1.5) {
newState = {
avatarSize: size - 15, // Leave some margin.
useConnectivityInfoLabel: false
};
} else {
newState = DEFAULT_STATE;
}
this.setState(newState);
}
/**
* Implements React's {@link Component#render()}.
*
@@ -36,13 +97,21 @@ class LargeVideo extends Component<*> {
* @returns {ReactElement}
*/
render() {
const {
avatarSize,
useConnectivityInfoLabel
} = this.state;
return (
<ParticipantView
avatarStyle = { styles.avatar }
participantId = { this.props._participantId }
style = { styles.largeVideo }
useConnectivityInfoLabel = { true }
zOrder = { 0 } />
<DimensionsDetector
onDimensionsChanged = { this._onDimensionsChanged } >
<ParticipantView
avatarSize = { avatarSize }
participantId = { this.props._participantId }
style = { styles.largeVideo }
useConnectivityInfoLabel = { useConnectivityInfoLabel }
zOrder = { 0 } />
</DimensionsDetector>
);
}
}

View File

@@ -1,18 +1,11 @@
import { ColorPalette, createStyleSheet } from '../../base/styles';
export default createStyleSheet({
/**
* The style of the avatar of the participant displayed in largeVideo. It's
* an addition to the default style of Avatar.
*/
avatar: {
alignSelf: 'center',
borderRadius: 100,
flex: 0,
height: 200,
width: 200
},
/**
* Size for the Avatar.
*/
export const AVATAR_SIZE = 200;
export default createStyleSheet({
/**
* Large video container style.
*/