From 14192478010334a5d900643f0141817a8f1e4242 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Mon, 5 Feb 2018 11:57:40 +0100 Subject: [PATCH] [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. --- .../participants/components/Avatar.native.js | 22 +++- .../components/ParticipantView.native.js | 10 +- .../base/participants/components/styles.js | 8 ++ .../filmstrip/components/Thumbnail.js | 4 +- react/features/filmstrip/components/styles.js | 20 +--- .../components/LargeVideo.native.js | 113 ++++++++++++++---- .../features/large-video/components/styles.js | 17 +-- 7 files changed, 135 insertions(+), 59 deletions(-) diff --git a/react/features/base/participants/components/Avatar.native.js b/react/features/base/participants/components/Avatar.native.js index f34cafbe0..ebc5363e5 100644 --- a/react/features/base/participants/components/Avatar.native.js +++ b/react/features/base/participants/components/Avatar.native.js @@ -6,6 +6,8 @@ import { CachedImage, ImageCache } from '../../../mobile/image-cache'; import { Platform } from '../../react'; import { ColorPalette } from '../../styles'; +import styles from './styles'; + /** * The default image/source to be used in case none is specified or the * specified one fails to load. @@ -32,10 +34,9 @@ export default class Avatar extends Component { */ static propTypes = { /** - * The optional style to add to the {@link Avatar} in order to customize - * its base look (and feel). + * The size for the {@link Avatar}. */ - style: PropTypes.object, + size: PropTypes.number, /** * The URI of the {@link Avatar}. @@ -216,7 +217,7 @@ export default class Avatar extends Component { /* eslint-enable no-unused-vars */ - style, + size, ...props } = this.props; const { @@ -224,6 +225,19 @@ export default class Avatar extends Component { source } = this.state; + // Compute the base style + const style = { + ...styles.avatar, + + // XXX Workaround for Android: for radii < 80 the border radius + // doesn't work properly, but applying a radius twice as big + // seems to do the trick. + borderRadius: size / 2 < 80 + ? Platform.OS === 'android' ? size * 2 : size / 2 : size / 2, + height: size, + width: size + }; + // If we're rendering the _DEFAULT_SOURCE, then we want to do some // additional fu like having automagical colors generated per // participant, transparency to make the intermediate state while diff --git a/react/features/base/participants/components/ParticipantView.native.js b/react/features/base/participants/components/ParticipantView.native.js index 300ecf07d..565106b1f 100644 --- a/react/features/base/participants/components/ParticipantView.native.js +++ b/react/features/base/participants/components/ParticipantView.native.js @@ -73,9 +73,9 @@ class ParticipantView extends Component { _videoTrack: PropTypes.object, /** - * The style, if any, of the avatar in addition to the default style. + * The avatar size. */ - avatarStyle: PropTypes.object, + avatarSize: PropTypes.number, /** * The ID of the participant (to be) depicted by ParticipantView. @@ -145,7 +145,7 @@ class ParticipantView extends Component { } const { - avatarStyle, + avatarSize, _participantName: displayName, t } = this.props; @@ -154,7 +154,7 @@ class ParticipantView extends Component { // view and one for the thumbnail. Some of these don't apply to both. const containerStyle = { ...styles.connectionInfoContainer, - width: avatarStyle.width * 1.5 + width: avatarSize * 1.5 }; return ( @@ -230,7 +230,7 @@ class ParticipantView extends Component { // rendered. && _toBoolean(this.props.showAvatar, true) && } { useTint diff --git a/react/features/base/participants/components/styles.js b/react/features/base/participants/components/styles.js index a90731a00..2e27fc2a1 100644 --- a/react/features/base/participants/components/styles.js +++ b/react/features/base/participants/components/styles.js @@ -4,6 +4,14 @@ import { BoxModel, ColorPalette, createStyleSheet } from '../../styles'; * The styles of the feature base/participants. */ export default createStyleSheet({ + /** + * The style of the avatar of the participant. + */ + avatar: { + alignSelf: 'center', + flex: 0 + }, + /** * Style for the text rendered when there is a connectivity problem. */ diff --git a/react/features/filmstrip/components/Thumbnail.js b/react/features/filmstrip/components/Thumbnail.js index 8ed2dd1d7..cd4fcb85e 100644 --- a/react/features/filmstrip/components/Thumbnail.js +++ b/react/features/filmstrip/components/Thumbnail.js @@ -19,6 +19,8 @@ import { VideoMutedIndicator } from './_'; +import { AVATAR_SIZE } from './styles'; + /** * React component for video thumbnail. * @extends Component @@ -94,7 +96,7 @@ class Thumbnail extends Component { = { audioTrack.jitsiTrack.getOriginalStream() } /> } { - /** - * 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 { + 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 ( - + + + ); } } diff --git a/react/features/large-video/components/styles.js b/react/features/large-video/components/styles.js index a3ac55547..a7da3ce92 100644 --- a/react/features/large-video/components/styles.js +++ b/react/features/large-video/components/styles.js @@ -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. */