diff --git a/react/features/base/react/components/native/TintedView.js b/react/features/base/react/components/native/TintedView.js new file mode 100644 index 0000000000..8a5bbbb017 --- /dev/null +++ b/react/features/base/react/components/native/TintedView.js @@ -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 { + /** + * 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 ( + + { this.props.children } + + ); + } +} diff --git a/react/features/base/react/components/native/index.js b/react/features/base/react/components/native/index.js index 97d794000a..b6f177d7f9 100644 --- a/react/features/base/react/components/native/index.js +++ b/react/features/base/react/components/native/index.js @@ -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'; diff --git a/react/features/conference/components/Conference.native.js b/react/features/conference/components/Conference.native.js index 41be3a3da4..049b5aa0b1 100644 --- a/react/features/conference/components/Conference.native.js +++ b/react/features/conference/components/Conference.native.js @@ -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 { * the toolbox/toolbars and the dialogs. */ this.props._connecting - && + && - + } diff --git a/react/features/conference/components/styles.js b/react/features/conference/components/styles.js index 7c02a2973e..f667ef3eb1 100644 --- a/react/features/conference/components/styles.js +++ b/react/features/conference/components/styles.js @@ -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 diff --git a/react/features/welcome/components/LocalVideoTrackUnderlay.native.js b/react/features/welcome/components/LocalVideoTrackUnderlay.native.js index 264c0db2e6..84b54fe665 100644 --- a/react/features/welcome/components/LocalVideoTrackUnderlay.native.js +++ b/react/features/welcome/components/LocalVideoTrackUnderlay.native.js @@ -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 ( - + { this.props.children } - + ); } diff --git a/react/features/welcome/components/styles.js b/react/features/welcome/components/styles.js index 11fce40a0d..fead989096 100644 --- a/react/features/welcome/components/styles.js +++ b/react/features/welcome/components/styles.js @@ -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',