diff --git a/react/features/base/react/components/AbstractContainer.js b/react/features/base/react/components/AbstractContainer.js index 2a78d1282..14f90663d 100644 --- a/react/features/base/react/components/AbstractContainer.js +++ b/react/features/base/react/components/AbstractContainer.js @@ -1,54 +1,71 @@ /* @flow */ -import PropTypes from 'prop-types'; import React, { Component } from 'react'; +/** + * {@code AbstractContainer} component's property types. + */ +export type Props = { + + /** + * An optional accessibility label to apply to the container root. + */ + accessibilityLabel?: string, + + /** + * Whether or not this element is an accessibility element. + */ + accessible?: boolean, + + /** + * React Elements to display within the component. + */ + children: React$Node | Object, + + /** + * The event handler/listener to be invoked when this + * {@code AbstractContainer} is clicked on Web or pressed on React + * Native. If {@code onClick} is defined and {@link touchFeedback} is + * undefined, {@code touchFeedback} is considered defined as + * {@code true}. + */ + onClick?: ?Function, + + /** + * The style (as in stylesheet) to be applied to this + * {@code AbstractContainer}. + */ + style?: Array | Object, + + /** + * If this instance is to provide visual feedback when touched, then + * {@code true}; otherwise, {@code false}. If {@code touchFeedback} is + * undefined and {@link onClick} is defined, {@code touchFeedback} is + * considered defined as {@code true}. + */ + touchFeedback?: ?Function, + + /** + * Color to display when clicked. + */ + underlayColor?: string, + + /** + * If this {@code AbstractContainer} is to be visible, then {@code true} + * or {@code false} if this instance is to be hidden or not rendered at + * all. + */ + visible?: ?boolean +}; + + /** * Abstract (base) class for container of React {@link Component} children with * a style. * * @extends Component */ -export default class AbstractContainer extends Component<*> { - /** - * {@code AbstractContainer} component's property types. - * - * @static - */ - static propTypes = { - children: PropTypes.node, - - /** - * The event handler/listener to be invoked when this - * {@code AbstractContainer} is clicked on Web or pressed on React - * Native. If {@code onClick} is defined and {@link touchFeedback} is - * undefined, {@code touchFeedback} is considered defined as - * {@code true}. - */ - onClick: PropTypes.func, - - /** - * The style (as in stylesheet) to be applied to this - * {@code AbstractContainer}. - */ - style: PropTypes.object, - - /** - * If this instance is to provide visual feedback when touched, then - * {@code true}; otherwise, {@code false}. If {@code touchFeedback} is - * undefined and {@link onClick} is defined, {@code touchFeedback} is - * considered defined as {@code true}. - */ - touchFeedback: PropTypes.bool, - - /** - * If this {@code AbstractContainer} is to be visible, then {@code true} - * or {@code false} if this instance is to be hidden or not rendered at - * all. - */ - visible: PropTypes.bool - }; - +export default class AbstractContainer extends Component

{ /** * Renders this {@code AbstractContainer} as a React {@code Component} of a * specific type. @@ -61,7 +78,7 @@ export default class AbstractContainer extends Component<*> { * @protected * @returns {ReactElement} */ - _render(type, props) { + _render(type, props?: P) { const { children, diff --git a/react/features/base/react/components/native/Container.js b/react/features/base/react/components/native/Container.js index b586e4673..95c7c2080 100644 --- a/react/features/base/react/components/native/Container.js +++ b/react/features/base/react/components/native/Container.js @@ -8,20 +8,14 @@ import { } from 'react-native'; import AbstractContainer from '../AbstractContainer'; +import type { Props } from '../AbstractContainer'; /** * Represents a container of React Native/mobile {@link Component} children. * * @extends AbstractContainer */ -export default class Container extends AbstractContainer { - /** - * {@code Container} component's property types. - * - * @static - */ - static propTypes = AbstractContainer.propTypes; - +export default class Container extends AbstractContainer

{ /** * Implements React's {@link Component#render()}. * diff --git a/react/features/base/react/components/web/Container.js b/react/features/base/react/components/web/Container.js index 721d4b731..7aa5b14ad 100644 --- a/react/features/base/react/components/web/Container.js +++ b/react/features/base/react/components/web/Container.js @@ -1,13 +1,14 @@ /* @flow */ import AbstractContainer from '../AbstractContainer'; +import type { Props } from '../AbstractContainer'; /** * Represents a container of React/Web {@link Component} children with a style. * * @extends AbstractContainer */ -export default class Container extends AbstractContainer { +export default class Container extends AbstractContainer

{ /** * {@code Container} component's property types. * diff --git a/react/features/conference/components/Conference.native.js b/react/features/conference/components/Conference.native.js index 046114088..16c182573 100644 --- a/react/features/conference/components/Conference.native.js +++ b/react/features/conference/components/Conference.native.js @@ -17,12 +17,18 @@ import { import { TestConnectionInfo } from '../../base/testing'; import { createDesiredLocalTracks } from '../../base/tracks'; import { ConferenceNotification } from '../../calendar-sync'; -import { FILMSTRIP_SIZE, Filmstrip, isFilmstripVisible } from '../../filmstrip'; +import { + FILMSTRIP_SIZE, + Filmstrip, + isFilmstripVisible, + TileView +} from '../../filmstrip'; import { LargeVideo } from '../../large-video'; import { CalleeInfoContainer } from '../../invite'; import { NotificationsContainer } from '../../notifications'; import { Captions } from '../../subtitles'; import { setToolboxVisible, Toolbox } from '../../toolbox'; +import { shouldDisplayTileView } from '../../video-layout'; import styles from './styles'; @@ -115,6 +121,13 @@ type Props = { */ _setToolboxVisible: Function, + /** + * Whether or not the layout should change to support tile view mode. + * + * @private + */ + _shouldDisplayTileView: boolean, + /** * The indicator which determines whether the Toolbox is visible. * @@ -252,6 +265,12 @@ class Conference extends Component { * @returns {ReactElement} */ render() { + const { + _connecting, + _reducedUI, + _shouldDisplayTileView + } = this.props; + return ( { {/* * The LargeVideo is the lowermost stacking layer. - */} - + */ + _shouldDisplayTileView + ? + : + } {/* * If there is a ringing call, show the callee's info. */ - this.props._reducedUI || + _reducedUI || } {/* * The activity/loading indicator goes above everything, except * the toolbox/toolbars and the dialogs. */ - this.props._connecting + _connecting && @@ -304,8 +326,9 @@ class Conference extends Component { * name and grouping stem from the fact that these two * React Components depict the videos of the conference's * participants. - */} - + */ + _shouldDisplayTileView ? undefined : + } @@ -548,6 +571,14 @@ function _mapStateToProps(state) { */ _room: room, + /** + * Whether or not the layout should change to support tile view mode. + * + * @private + * @type {boolean} + */ + _shouldDisplayTileView: shouldDisplayTileView(state), + /** * The indicator which determines whether the Toolbox is visible. * diff --git a/react/features/filmstrip/components/native/Thumbnail.js b/react/features/filmstrip/components/native/Thumbnail.js index 04154f592..8bbcee099 100644 --- a/react/features/filmstrip/components/native/Thumbnail.js +++ b/react/features/filmstrip/components/native/Thumbnail.js @@ -1,4 +1,5 @@ -import PropTypes from 'prop-types'; +// @flow + import React, { Component } from 'react'; import { connect } from 'react-redux'; @@ -18,31 +19,67 @@ import { AVATAR_SIZE } from '../styles'; import styles from './styles'; import VideoMutedIndicator from './VideoMutedIndicator'; +/** + * Thumbnail component's property types. + */ +type Props = { + + /** + * The Redux representation of the participant's audio track. + */ + _audioTrack: Object, + + /** + * The Redux representation of the state "features/large-video". + */ + _largeVideo: Object, + + /** + * The Redux representation of the participant's video track. + */ + _videoTrack: Object, + + /** + * If true, tapping on the thumbnail will not pin the participant to large + * video. By default tapping does pin the participant. + */ + disablePin?: boolean, + + /** + * If true, there will be no color overlay (tint) on the thumbnail + * indicating the participant associated with the thumbnail is displayed on + * large video. By default there will be a tint. + */ + disableTint?: boolean, + + /** + * Invoked to trigger state changes in Redux. + */ + dispatch: Dispatch<*>, + + /** + * The Redux representation of the participant to display. + */ + participant: Object, + + /** + * Optional styling to add or override on the Thumbnail component root. + */ + styleOverrides?: Object +}; + /** * React component for video thumbnail. * * @extends Component */ -class Thumbnail extends Component { - /** - * Thumbnail component's property types. - * - * @static - */ - static propTypes = { - _audioTrack: PropTypes.object, - _largeVideo: PropTypes.object, - _videoTrack: PropTypes.object, - dispatch: PropTypes.func, - participant: PropTypes.object - }; - +class Thumbnail extends Component { /** * Initializes new Video Thumbnail component. * * @param {Object} props - Component props. */ - constructor(props) { + constructor(props: Props) { super(props); // Bind event handlers so they are only bound once for every instance. @@ -56,19 +93,14 @@ class Thumbnail extends Component { * @returns {ReactElement} */ render() { - const audioTrack = this.props._audioTrack; - const largeVideo = this.props._largeVideo; - const participant = this.props.participant; - const videoTrack = this.props._videoTrack; - - let style = styles.thumbnail; - - if (participant.pinned) { - style = { - ...style, - ...styles.thumbnailPinned - }; - } + const { + _audioTrack: audioTrack, + _largeVideo: largeVideo, + _videoTrack: videoTrack, + disablePin, + disableTint, + participant + } = this.props; // We don't render audio in any of the following: // 1. The audio (source) is muted. There's no practical reason (that we @@ -85,8 +117,13 @@ class Thumbnail extends Component { return ( + onClick = { disablePin ? undefined : this._onClick } + style = { [ + styles.thumbnail, + participant.pinned && !disablePin + ? styles.thumbnailPinned : null, + this.props.styleOverrides || null + ] }> { renderAudio &&