Web Filmstrip & LargeVideo React Components

We've had Filmstrip & LargeVideo React Components on mobile/React Native
from the start. We didn't have them on Web (because the rewrite in React
is not complete yet). However, that led to differences in the React
Component Conference on Web and mobile. In an effort to get closer to
merging the React Component Conference on Web and mobile, introduce the
React Components Filmstrip & LargeVideo on Web even if a minimal
render-only form at this time.
This commit is contained in:
Lyubo Marinov 2017-05-24 12:01:46 -05:00
parent 66ababc6c8
commit b7c4ebba84
7 changed files with 173 additions and 104 deletions

View File

@ -6,6 +6,7 @@ import { DialogContainer } from '../../base/dialog';
import { Container } from '../../base/react';
import { Filmstrip } from '../../filmstrip';
import { LargeVideo } from '../../large-video';
import { OverlayContainer } from '../../overlay';
import { setToolboxVisible, Toolbox } from '../../toolbox';
import { styles } from './styles';
@ -130,12 +131,33 @@ class Conference extends Component {
style = { styles.conference }
touchFeedback = { false }>
{/*
* The LargeVideo is the lowermost stacking layer.
*/}
<LargeVideo />
<Toolbox />
{/*
* The Filmstrip is in a stacking layer above the LargeVideo.
* The LargeVideo and the Filmstrip form what the Web/React app
* calls "videospace". Presumably, the name and grouping stem
* from the fact that these two React Components depict the
* videos of the conference's participants.
*/}
<Filmstrip />
{/*
* The Toolbox is in a stacking layer above the Filmstrip.
*/}
<Toolbox />
{/*
* The dialogs and overlays are in the topmost stacking layers.
* Generally, the dialogs and overlays should not be visible at
* the same time so it is not really defined which one is above
* the other.
*/}
<DialogContainer />
<OverlayContainer />
</Container>
);
}

View File

@ -5,12 +5,11 @@ import { connect as reactReduxConnect } from 'react-redux';
import { connect, disconnect } from '../../base/connection';
import { DialogContainer } from '../../base/dialog';
import { Watermarks } from '../../base/react';
import { Filmstrip } from '../../filmstrip';
import { LargeVideo } from '../../large-video';
import { OverlayContainer } from '../../overlay';
import { Toolbox } from '../../toolbox';
import { HideNotificationBarStyle } from '../../unsupported-browser';
import { VideoStatusLabel } from '../../video-status-label';
import '../../filmstrip';
declare var $: Function;
declare var APP: Object;
@ -68,114 +67,28 @@ class Conference extends Component {
render() {
return (
<div id = 'videoconference_page'>
<Toolbox />
<div id = 'videospace'>
<div
className = 'videocontainer'
id = 'largeVideoContainer'>
<div id = 'sharedVideo'>
<div id = 'sharedVideoIFrame' />
</div>
<div id = 'etherpad' />
<LargeVideo />
<Watermarks />
<Filmstrip />
</div>
<div id = 'dominantSpeaker'>
<div className = 'dynamic-shadow' />
<img
id = 'dominantSpeakerAvatar'
src = '' />
</div>
<span id = 'remoteConnectionMessage' />
<div id = 'largeVideoWrapper'>
<video
autoPlay = { true }
id = 'largeVideo'
muted = 'true' />
</div>
<span id = 'localConnectionMessage' />
<VideoStatusLabel />
<span
className
= 'video-state-indicator centeredVideoLabel'
id = 'recordingLabel'>
<span id = 'recordingLabelText' />
<img
className = 'recordingSpinner'
id = 'recordingSpinner'
src = 'images/spin.svg' />
</span>
</div>
{ this._renderFilmstrip() }
</div>
<Toolbox />
<DialogContainer />
<OverlayContainer />
{/*
* Temasys automatically injects a notification bar, if
* necessary, displayed at the top of the page notifying that
* WebRTC is not installed or supported. We do not need/want
* the notification bar in question because we have whole pages
* dedicated to the respective scenarios.
*/}
<HideNotificationBarStyle />
</div>
);
}
/**
* Creates a React Element for displaying filmstrip videos.
*
* @private
* @returns {ReactElement}
*/
_renderFilmstrip() {
return (
<div className = 'filmstrip'>
<div
className = 'filmstrip__videos'
id = 'remoteVideos'>
<div
className = 'filmstrip__videos'
id = 'filmstripLocalVideo'>
<span
className = 'videocontainer'
id = 'localVideoContainer'>
<div className = 'videocontainer__background' />
<span id = 'localVideoWrapper' />
<audio
autoPlay = { true }
id = 'localAudio'
muted = { true } />
<div className = 'videocontainer__toolbar' />
<div className = 'videocontainer__toptoolbar' />
<div
className
= 'videocontainer__hoverOverlay' />
</span>
</div>
<div
className = 'filmstrip__videos'
id = 'filmstripRemoteVideos'>
{
/*
This extra video container is needed for
scrolling thumbnails in firefox, otherwise the
flex thumbnails resize instead of causing
overflow.
*/
}
<div
className = 'remote-videos-container'
id = 'filmstripRemoteVideosContainer' />
</div>
<audio
id = 'userJoined'
preload = 'auto'
src = 'sounds/joined.wav' />
<audio
id = 'userLeft'
preload = 'auto'
src = 'sounds/left.wav' />
</div>
</div>
);
}
}
export default reactReduxConnect()(Conference);

View File

@ -1,3 +1,5 @@
/* @flow */
import React, { Component } from 'react';
import { ScrollView } from 'react-native';
import { connect } from 'react-redux';
@ -8,7 +10,8 @@ import Thumbnail from './Thumbnail';
import { styles } from './_';
/**
* React component for filmstrip.
* Implements a React {@link Component} which represents the filmstrip on
* mobile/React Native.
*
* @extends Component
*/
@ -40,6 +43,7 @@ class Filmstrip extends Component {
* Implements React's {@link Component#render()}.
*
* @inheritdoc
* @returns {ReactElement}
*/
render() {
return (

View File

@ -0,0 +1,65 @@
/* @flow */
import React, { Component } from 'react';
/**
* Implements a React {@link Component} which represents the filmstrip on
* Web/React.
*
* @extends Component
*/
export default class Filmstrip extends Component {
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
* @returns {ReactElement}
*/
render() {
return (
<div className = 'filmstrip'>
<div
className = 'filmstrip__videos'
id = 'remoteVideos'>
<div
className = 'filmstrip__videos'
id = 'filmstripLocalVideo'>
<span
className = 'videocontainer'
id = 'localVideoContainer'>
<div className = 'videocontainer__background' />
<span id = 'localVideoWrapper' />
<audio
autoPlay = { true }
id = 'localAudio'
muted = { true } />
<div className = 'videocontainer__toolbar' />
<div className = 'videocontainer__toptoolbar' />
<div className = 'videocontainer__hoverOverlay' />
</span>
</div>
<div
className = 'filmstrip__videos'
id = 'filmstripRemoteVideos'>
{/*
* This extra video container is needed for scrolling
* thumbnails in Firefox; otherwise, the flex
* thumbnails resize instead of causing overflow.
*/}
<div
className = 'remote-videos-container'
id = 'filmstripRemoteVideosContainer' />
</div>
<audio
id = 'userJoined'
preload = 'auto'
src = 'sounds/joined.wav' />
<audio
id = 'userLeft'
preload = 'auto'
src = 'sounds/left.wav' />
</div>
</div>
);
}
}

View File

@ -1,3 +1,5 @@
/* @flow */
import React, { Component } from 'react';
import { connect } from 'react-redux';
@ -6,7 +8,8 @@ import { ParticipantView } from '../../base/participants';
import { styles } from './styles';
/**
* Large video React component.
* Implements a React {@link Component} which represents the large video (a.k.a.
* the conference participant who is on the local stage) on mobile/React Native.
*
* @extends Component
*/

View File

@ -0,0 +1,62 @@
/* @flow */
import React, { Component } from 'react';
import { Watermarks } from '../../base/react';
import { VideoStatusLabel } from '../../video-status-label';
/**
* Implements a React {@link Component} which represents the large video (a.k.a.
* the conference participant who is on the local stage) on Web/React.
*
* @extends Component
*/
export default class LargeVideo extends Component {
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
* @returns {ReactElement}
*/
render() {
return (
<div
className = 'videocontainer'
id = 'largeVideoContainer'>
<div id = 'sharedVideo'>
<div id = 'sharedVideoIFrame' />
</div>
<div id = 'etherpad' />
<Watermarks />
<div id = 'dominantSpeaker'>
<div className = 'dynamic-shadow' />
<img
id = 'dominantSpeakerAvatar'
src = '' />
</div>
<span id = 'remoteConnectionMessage' />
<div id = 'largeVideoWrapper'>
<video
autoPlay = { true }
id = 'largeVideo'
muted = { true } />
</div>
<span id = 'localConnectionMessage' />
<VideoStatusLabel />
<span
className = 'video-state-indicator centeredVideoLabel'
id = 'recordingLabel'>
<span id = 'recordingLabelText' />
<img
className = 'recordingSpinner'
id = 'recordingSpinner'
src = 'images/spin.svg' />
</span>
</div>
);
}
}