[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:
parent
9a3f98a4a0
commit
ac09233558
|
@ -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>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
|
|
|
@ -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 } >
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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',
|
||||
|
|
Loading…
Reference in New Issue