[RN] Add TintedView component

It's designed to cover a container and give it a "tint" by using a color and
opacity.
This commit is contained in:
Saúl Ibarra Corretgé 2017-12-14 16:04:35 +01:00 committed by Paweł Domas
parent 9a3f98a4a0
commit ac09233558
6 changed files with 148 additions and 46 deletions

View File

@ -0,0 +1,140 @@
// @flow
import React, { Component } from 'react';
import { View } from 'react-native';
import { ColorPalette } from '../../../styles';
/**
* Base style for the {@code TintedView} component.
*/
const BASE_STYLE = {
alignItems: 'center',
bottom: 0,
justifyContent: 'center',
left: 0,
position: 'absolute',
right: 0,
top: 0
};
/**
* {@code TintedView}'s React {@code Component} prop types.
*/
type Props = {
/**
* The children components of this component.
*/
children?: React$Node,
/**
* Color used as the background of the view. Defaults to
*/
color: string,
/**
* Opacity for the
*/
opacity: number,
/**
* Style to override the base style.
*/
style: Object
};
/**
* {@code TintedView}'s React {@code Component} state.
*/
type State = {
/**
* The style of {@code TintedView} which is a combination of its default
* style, the consumer-specified style.
*/
style: Object
};
/**
* Implements a component aimed at covering another view and tinting it with
* the given color and opacity.
*/
export default class TintedView extends Component<Props, State> {
/**
* Default values for the component's props.
*/
static defaultProps = {
color: ColorPalette.appBackground,
opacity: 0.8,
style: {}
};
/**
* Initializes a new {@code TintedView} instance.
*
* @param {Object} props - The read-only React {@code Component} props with
* which the new instance is to be initialized.
*/
constructor(props: Object) {
super(props);
this.componentWillReceiveProps(props);
}
/**
* Notifies this mounted React {@code Component} that it will receive new
* props. Forks (in Facebook/React speak) the prop {@code style} because its
* value is to be combined with the default style.
*
* @inheritdoc
* @param {Object} nextProps - The read-only React {@code Component} props
* that this instance will receive.
* @returns {void}
*/
componentWillReceiveProps(nextProps: Object) {
// style
const prevColor = this.props && this.props.color;
const prevOpacity = this.props && this.props.opacity;
const prevStyle = this.props && this.props.style;
const nextColor = nextProps && nextProps.color;
const nextOpacity = nextProps && nextProps.opacity;
const nextStyle = nextProps && nextProps.style;
const assignState = !this.state;
if (prevColor !== nextColor || prevOpacity !== nextOpacity
|| prevStyle !== nextStyle || assignState) {
const nextState = {
style: {
...BASE_STYLE,
...nextStyle,
backgroundColor: nextColor,
opacity: nextOpacity
}
};
if (assignState) {
// eslint-disable-next-line react/no-direct-mutation-state
this.state = nextState;
} else {
this.setState(nextState);
}
}
}
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
* @returns {ReactElement}
*/
render() {
return (
<View style = { this.state.style }>
{ this.props.children }
</View>
);
}
}

View File

@ -1,4 +1,5 @@
export { default as Container } from './Container';
export { default as Link } from './Link';
export { default as LoadingIndicator } from './LoadingIndicator';
export { default as TintedView } from './TintedView';
export { default as Text } from './Text';

View File

@ -10,7 +10,7 @@ import { appNavigate } from '../../app';
import { connect, disconnect } from '../../base/connection';
import { DialogContainer } from '../../base/dialog';
import { CalleeInfoContainer } from '../../base/jwt';
import { Container, LoadingIndicator } from '../../base/react';
import { Container, LoadingIndicator, TintedView } from '../../base/react';
import { createDesiredLocalTracks } from '../../base/tracks';
import { Filmstrip } from '../../filmstrip';
import { LargeVideo } from '../../large-video';
@ -200,9 +200,9 @@ class Conference extends Component<Props> {
* the toolbox/toolbars and the dialogs.
*/
this.props._connecting
&& <View style = { styles.connectingIndicator }>
&& <TintedView>
<LoadingIndicator />
</View>
</TintedView>
}
<View style = { styles.toolboxAndFilmstripContainer } >

View File

@ -18,29 +18,6 @@ export default createStyleSheet({
flex: 1
}),
/**
* The style of the View rendered while the conference is being connected
* (i.e. the XMPP connection is being established and the MUC is being
* joined).
*/
connectingIndicator: {
alignItems: 'center',
bottom: 0,
justifyContent: 'center',
left: 0,
position: 'absolute',
right: 0,
top: 0,
// Because the background of LargeVideo varies wildly (e.g. the
// participant's video or avatar), the LoadingIndicator may be difficult
// to see. Reduce the variance of the background of LargeVideo and,
// thus, increase the visibility of LoadingIndicator by introducing
// contrast and translucency.
backgroundColor: ColorPalette.appBackground,
opacity: 0.5
},
/**
* The style of the {@link View} which expands over the whole
* {@link Conference} area and splits it between the {@link Filmstrip} and

View File

@ -6,6 +6,7 @@ import { View } from 'react-native';
import { connect } from 'react-redux';
import { VideoTrack } from '../../base/media';
import { TintedView } from '../../base/react';
import { getLocalVideoTrack } from '../../base/tracks';
import styles from './styles';
@ -91,9 +92,9 @@ class LocalVideoTrackUnderlay extends Component<*, *> {
return (
<View style = { this.state.style }>
<VideoTrack videoTrack = { this.props._localVideoTrack } />
<View style = { styles.localVideoTrackOverlay }>
<TintedView>
{ this.props.children }
</View>
</TintedView>
</View>
);
}

View File

@ -65,24 +65,6 @@ export default createStyleSheet({
margin: BoxModel.margin
},
/**
* The style of the {@code View} displayed over the local video by
* {@code LocalVideoTrackUnderlay}. The latter is thought of as the
* background (content). The former is thought of as the foreground
* (content).
*/
localVideoTrackOverlay: {
backgroundColor: 'transparent',
bottom: 0,
flex: 1,
flexDirection: 'column',
justifyContent: 'center',
left: 0,
position: 'absolute',
right: 0,
top: 0
},
/**
* The style of the top-level container/{@code View} of
* {@code LocalVideoTrackUnderlay}.
@ -97,6 +79,7 @@ export default createStyleSheet({
* Container for room name input box and 'join' button.
*/
roomContainer: {
alignSelf: 'stretch',
flex: 1,
flexDirection: 'column',
justifyContent: 'center',