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:
parent
66ababc6c8
commit
b7c4ebba84
|
@ -6,6 +6,7 @@ import { DialogContainer } from '../../base/dialog';
|
||||||
import { Container } from '../../base/react';
|
import { Container } from '../../base/react';
|
||||||
import { Filmstrip } from '../../filmstrip';
|
import { Filmstrip } from '../../filmstrip';
|
||||||
import { LargeVideo } from '../../large-video';
|
import { LargeVideo } from '../../large-video';
|
||||||
|
import { OverlayContainer } from '../../overlay';
|
||||||
import { setToolboxVisible, Toolbox } from '../../toolbox';
|
import { setToolboxVisible, Toolbox } from '../../toolbox';
|
||||||
|
|
||||||
import { styles } from './styles';
|
import { styles } from './styles';
|
||||||
|
@ -130,12 +131,33 @@ class Conference extends Component {
|
||||||
style = { styles.conference }
|
style = { styles.conference }
|
||||||
touchFeedback = { false }>
|
touchFeedback = { false }>
|
||||||
|
|
||||||
|
{/*
|
||||||
|
* The LargeVideo is the lowermost stacking layer.
|
||||||
|
*/}
|
||||||
<LargeVideo />
|
<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 />
|
<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 />
|
<DialogContainer />
|
||||||
|
<OverlayContainer />
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,12 +5,11 @@ import { connect as reactReduxConnect } from 'react-redux';
|
||||||
|
|
||||||
import { connect, disconnect } from '../../base/connection';
|
import { connect, disconnect } from '../../base/connection';
|
||||||
import { DialogContainer } from '../../base/dialog';
|
import { DialogContainer } from '../../base/dialog';
|
||||||
import { Watermarks } from '../../base/react';
|
import { Filmstrip } from '../../filmstrip';
|
||||||
|
import { LargeVideo } from '../../large-video';
|
||||||
import { OverlayContainer } from '../../overlay';
|
import { OverlayContainer } from '../../overlay';
|
||||||
import { Toolbox } from '../../toolbox';
|
import { Toolbox } from '../../toolbox';
|
||||||
import { HideNotificationBarStyle } from '../../unsupported-browser';
|
import { HideNotificationBarStyle } from '../../unsupported-browser';
|
||||||
import { VideoStatusLabel } from '../../video-status-label';
|
|
||||||
import '../../filmstrip';
|
|
||||||
|
|
||||||
declare var $: Function;
|
declare var $: Function;
|
||||||
declare var APP: Object;
|
declare var APP: Object;
|
||||||
|
@ -68,114 +67,28 @@ class Conference extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div id = 'videoconference_page'>
|
<div id = 'videoconference_page'>
|
||||||
<Toolbox />
|
|
||||||
|
|
||||||
<div id = 'videospace'>
|
<div id = 'videospace'>
|
||||||
<div
|
<LargeVideo />
|
||||||
className = 'videocontainer'
|
|
||||||
id = 'largeVideoContainer'>
|
|
||||||
<div id = 'sharedVideo'>
|
|
||||||
<div id = 'sharedVideoIFrame' />
|
|
||||||
</div>
|
|
||||||
<div id = 'etherpad' />
|
|
||||||
|
|
||||||
<Watermarks />
|
<Filmstrip />
|
||||||
|
|
||||||
<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>
|
</div>
|
||||||
|
|
||||||
|
<Toolbox />
|
||||||
|
|
||||||
<DialogContainer />
|
<DialogContainer />
|
||||||
<OverlayContainer />
|
<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 />
|
<HideNotificationBarStyle />
|
||||||
</div>
|
</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);
|
export default reactReduxConnect()(Conference);
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* @flow */
|
||||||
|
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { ScrollView } from 'react-native';
|
import { ScrollView } from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
@ -8,7 +10,8 @@ import Thumbnail from './Thumbnail';
|
||||||
import { styles } from './_';
|
import { styles } from './_';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* React component for filmstrip.
|
* Implements a React {@link Component} which represents the filmstrip on
|
||||||
|
* mobile/React Native.
|
||||||
*
|
*
|
||||||
* @extends Component
|
* @extends Component
|
||||||
*/
|
*/
|
||||||
|
@ -40,6 +43,7 @@ class Filmstrip extends Component {
|
||||||
* Implements React's {@link Component#render()}.
|
* Implements React's {@link Component#render()}.
|
||||||
*
|
*
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
|
* @returns {ReactElement}
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* @flow */
|
||||||
|
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
@ -6,7 +8,8 @@ import { ParticipantView } from '../../base/participants';
|
||||||
import { styles } from './styles';
|
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
|
* @extends Component
|
||||||
*/
|
*/
|
|
@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue