feat(connection-indicator): convert to react

- Create a new ConnectionIndicator component for displaying an
  icon for connection quality and for triggering a popover. The
  popover handling has been left in ConnectionIndicator for now,
  which follows the existing implementation.
- Remove the unused method "connectionIndicatorShowMore"
- Change the implementation of existing methods that update the
  connection indicator to call the same method which will rerender
  the indicator completely.
pull/1710/head jitsi-meet_2193
Leonard Kim 8 years ago committed by hristoterezov
parent 35f79dd2b4
commit 4ce5888b4c
  1. 23
      css/_videolayout_default.scss
  2. 5
      modules/UI/UI.js
  3. 273
      modules/UI/videolayout/ConnectionIndicator.js
  4. 10
      modules/UI/videolayout/LocalVideo.js
  5. 30
      modules/UI/videolayout/RemoteVideo.js
  6. 105
      modules/UI/videolayout/SmallVideo.js
  7. 22
      modules/UI/videolayout/VideoLayout.js
  8. 284
      react/features/connection-indicator/components/ConnectionIndicator.js
  9. 1
      react/features/connection-indicator/components/index.js
  10. 1
      react/features/connection-indicator/index.js
  11. 6
      react/features/filmstrip/components/Filmstrip.web.js

@ -58,14 +58,27 @@
padding: $toolbarPadding;
padding-bottom: 0;
.connection-indicator-container,
.connection-indicator,
span.indicator {
margin-right: em(5, 8);
}
span.indicator {
display: none;
&:last-child {
margin-right: 0;
}
}
.connection-indicator,
span.indicator {
position: relative;
font-size: 8px;
text-align: center;
line-height: $thumbnailIndicatorSize;
display: none;
padding: 0;
margin-right: em(5, 8);
float: left;
@include circle($thumbnailIndicatorSize);
box-sizing: border-box;
@ -74,10 +87,6 @@
color: $thumbnailPictogramColor;
border: $thumbnailIndicatorBorder solid $thumbnailPictogramColor;
&:last-child {
margin-right: 0;
}
.indicatoricon {
@include absoluteAligning();
}
@ -297,7 +306,7 @@
background: $raiseHandBg;
}
#connectionindicator {
.connection-indicator {
background: $connectionIndicatorBg;
}

@ -665,11 +665,6 @@ UI.getRemoteVideoType = function (jid) {
return VideoLayout.getRemoteVideoType(jid);
};
UI.connectionIndicatorShowMore = function(id) {
VideoLayout.showMore(id);
return false;
};
// FIXME check if someone user this
UI.showLoginPopup = function(callback) {
logger.log('password is required');

@ -1,273 +0,0 @@
/* global $, interfaceConfig, JitsiMeetJS */
/* jshint -W101 */
/* eslint-disable no-unused-vars */
import React from 'react';
import ReactDOM from 'react-dom';
import { ConnectionStatsTable } from '../../../react/features/connection-stats';
/* eslint-enable no-unused-vars */
import JitsiPopover from "../util/JitsiPopover";
import UIUtil from "../util/UIUtil";
const ParticipantConnectionStatus
= JitsiMeetJS.constants.participantConnectionStatus;
/**
* Maps a connection quality value (in percent) to the width of the "full" icon.
*/
const qualityToWidth = [
// Full (5 bars)
{percent: 80, width: "100%"},
// 4 bars
{percent: 60, width: "80%"},
// 3 bars
{percent: 40, width: "55%"},
// 2 bars
{percent: 20, width: "40%"},
// 1 bar
{percent: 0, width: "20%"}
// Note: we never show 0 bars.
];
/**
* Constructs new connection indicator.
* @param videoContainer the video container associated with the indicator.
* @param videoId the identifier of the video
* @constructor
*/
function ConnectionIndicator(videoContainer, videoId) {
this.videoContainer = videoContainer;
this.bandwidth = null;
this.packetLoss = null;
this.bitrate = null;
this.showMoreValue = false;
this.resolution = null;
this.transport = [];
this.framerate = null;
this.popover = null;
this.id = videoId;
this.create();
this.isLocalVideo
= this.videoContainer.videoSpanId === 'localVideoContainer';
this.showMore = this.showMore.bind(this);
}
/**
* Generates the html content.
* @returns {string} the html content.
*/
ConnectionIndicator.prototype.generateText = function () {
/* jshint ignore:start */
return (
<ConnectionStatsTable
bandwidth = { this.bandwidth }
bitrate = { this.bitrate }
isLocalVideo = { this.isLocalVideo }
framerate = { this.framerate }
onShowMore = { this.showMore }
packetLoss = { this.packetLoss}
resolution = { this.resolution }
shouldShowMore = { this.showMoreValue }
transport = { this.transport } />
);
/* jshint ignore:end */
};
/**
* Shows or hide the additional information.
*/
ConnectionIndicator.prototype.showMore = function () {
this.showMoreValue = !this.showMoreValue;
this.updatePopoverData();
};
function createIcon(classes, iconClass) {
var icon = document.createElement("span");
for(var i in classes) {
icon.classList.add(classes[i]);
}
icon.appendChild(
document.createElement("i")).classList.add(iconClass);
return icon;
}
/**
* Creates the indicator
*/
ConnectionIndicator.prototype.create = function () {
let indicatorId = 'connectionindicator';
let element = UIUtil.getVideoThumbnailIndicatorSpan({
videoSpanId: this.videoContainer.videoSpanId,
indicatorId
});
element.classList.add('show');
this.connectionIndicatorContainer = element;
let popoverContent = (
`<div class="connection-info" data-i18n="${indicatorId}.na"></div>`
);
this.popover = new JitsiPopover($(element), {
content: popoverContent,
skin: "black",
position: interfaceConfig.VERTICAL_FILMSTRIP ? 'left' : 'top'
});
// override popover show method to make sure we will update the content
// before showing the popover
var origShowFunc = this.popover.show;
this.popover.show = function () {
// update content by forcing it, to finish even if popover
// is not visible
this.updatePopoverData(true);
// call the original show, passing its actual this
origShowFunc.call(this.popover);
}.bind(this);
let connectionIconContainer = document.createElement('div');
connectionIconContainer.className = 'connection indicatoricon';
this.emptyIcon = connectionIconContainer.appendChild(
createIcon(["connection_empty"], "icon-connection"));
this.fullIcon = connectionIconContainer.appendChild(
createIcon(["connection_full"], "icon-connection"));
this.interruptedIndicator = connectionIconContainer.appendChild(
createIcon(["connection_lost"],"icon-connection-lost"));
this.ninjaIndicator = connectionIconContainer.appendChild(
createIcon(["connection_ninja"],"icon-ninja"));
$(this.interruptedIndicator).hide();
$(this.ninjaIndicator).hide();
this.connectionIndicatorContainer.appendChild(connectionIconContainer);
};
/**
* Removes the indicator
*/
ConnectionIndicator.prototype.remove = function() {
if (this.connectionIndicatorContainer.parentNode) {
this.connectionIndicatorContainer.parentNode.removeChild(
this.connectionIndicatorContainer);
}
this.popover.forceHide();
};
/**
* Updates the UI which displays or not a warning about user's connectivity
* problems.
*
* @param {ParticipantConnectionStatus} connectionStatus
*/
ConnectionIndicator.prototype.updateConnectionStatusIndicator
= function (connectionStatus) {
this.connectionStatus = connectionStatus;
if (connectionStatus === ParticipantConnectionStatus.INTERRUPTED) {
$(this.interruptedIndicator).show();
$(this.emptyIcon).hide();
$(this.fullIcon).hide();
$(this.ninjaIndicator).hide();
} else if (connectionStatus === ParticipantConnectionStatus.INACTIVE) {
$(this.interruptedIndicator).hide();
$(this.emptyIcon).hide();
$(this.fullIcon).hide();
$(this.ninjaIndicator).show();
} else {
$(this.interruptedIndicator).hide();
$(this.emptyIcon).show();
$(this.fullIcon).show();
$(this.ninjaIndicator).hide();
}
};
/**
* Updates the data of the indicator
* @param percent the percent of connection quality
* @param object the statistics data.
*/
ConnectionIndicator.prototype.updateConnectionQuality =
function (percent, object) {
if (!percent) {
this.connectionIndicatorContainer.style.display = "none";
this.popover.forceHide();
return;
} else {
if(this.connectionIndicatorContainer.style.display == "none") {
this.connectionIndicatorContainer.style.display = "block";
}
}
if (object) {
this.bandwidth = object.bandwidth;
this.bitrate = object.bitrate;
this.packetLoss = object.packetLoss;
this.transport = object.transport;
if (object.resolution) {
this.resolution = object.resolution;
}
if (object.framerate)
this.framerate = object.framerate;
}
let width = qualityToWidth.find(x => percent >= x.percent);
this.fullIcon.style.width = width.width;
this.updatePopoverData();
};
/**
* Updates the resolution
* @param resolution the new resolution
*/
ConnectionIndicator.prototype.updateResolution = function (resolution) {
this.resolution = resolution;
this.updatePopoverData();
};
/**
* Updates the framerate
* @param framerate the new resolution
*/
ConnectionIndicator.prototype.updateFramerate = function (framerate) {
this.framerate = framerate;
this.updatePopoverData();
};
/**
* Updates the content of the popover if its visible
* @param force to work even if popover is not visible
*/
ConnectionIndicator.prototype.updatePopoverData = function (force) {
// generate content, translate it and add it to document only if
// popover is visible or we force to do so.
if(this.popover.popoverShown || force) {
this.popover.updateContent(this.generateText());
}
};
/**
* Hides the popover
*/
ConnectionIndicator.prototype.hide = function () {
this.popover.forceHide();
};
/**
* Hides the indicator
*/
ConnectionIndicator.prototype.hideIndicator = function () {
this.connectionIndicatorContainer.style.display = "none";
if(this.popover)
this.popover.forceHide();
};
/**
* Adds a hover listener to the popover.
*/
ConnectionIndicator.prototype.addPopoverHoverListener = function (listener) {
this.popover.addOnHoverPopover(listener);
};
export default ConnectionIndicator;

@ -1,7 +1,6 @@
/* global $, config, interfaceConfig, APP, JitsiMeetJS */
const logger = require("jitsi-meet-logger").getLogger(__filename);
import ConnectionIndicator from "./ConnectionIndicator";
import UIUtil from "../util/UIUtil";
import UIEvents from "../../../service/UI/UIEvents";
import SmallVideo from "./SmallVideo";
@ -13,7 +12,6 @@ function LocalVideo(VideoLayout, emitter) {
this.videoSpanId = "localVideoContainer";
this.container = $("#localVideoContainer").get(0);
this.localVideoId = null;
this.createConnectionIndicator();
this.bindHoverHandler();
if(config.enableLocalVideoFlip)
this._buildContextMenu();
@ -32,6 +30,7 @@ function LocalVideo(VideoLayout, emitter) {
this.setDisplayName();
this.addAudioLevelIndicator();
this.updateConnectionIndicator();
}
LocalVideo.prototype = Object.create(SmallVideo.prototype);
@ -148,13 +147,6 @@ LocalVideo.prototype.setDisplayName = function(displayName) {
}
};
LocalVideo.prototype.createConnectionIndicator = function() {
if(this.connectionIndicator)
return;
this.connectionIndicator = new ConnectionIndicator(this, null);
};
LocalVideo.prototype.changeVideo = function (stream) {
this.videoStream = stream;

@ -15,7 +15,6 @@ import {
const logger = require("jitsi-meet-logger").getLogger(__filename);
import ConnectionIndicator from './ConnectionIndicator';
import SmallVideo from "./SmallVideo";
import UIUtils from "../util/UIUtil";
@ -48,7 +47,7 @@ function RemoteVideo(user, VideoLayout, emitter) {
this.hasRemoteVideoMenu = false;
this._supportsRemoteControl = false;
this.addRemoteVideoContainer();
this.connectionIndicator = new ConnectionIndicator(this, this.id);
this.updateConnectionIndicator();
this.setDisplayName();
this.bindHoverHandler();
this.flipX = false;
@ -497,10 +496,7 @@ RemoteVideo.prototype.updateConnectionStatusIndicator = function () {
// FIXME rename 'mutedWhileDisconnected' to 'mutedWhileNotRendering'
// Update 'mutedWhileDisconnected' flag
this._figureOutMutedWhileDisconnected();
if(this.connectionIndicator) {
this.connectionIndicator.updateConnectionStatusIndicator(
connectionStatus);
}
this.updateConnectionStatus(connectionStatus);
const isInterrupted
= connectionStatus === ParticipantConnectionStatus.INTERRUPTED;
@ -621,9 +617,7 @@ RemoteVideo.prototype.addRemoteStreamElement = function (stream) {
};
RemoteVideo.prototype.updateResolution = function (resolution) {
if (this.connectionIndicator) {
this.connectionIndicator.updateResolution(resolution);
}
this.updateConnectionIndicator({ resolution });
};
/**
@ -631,19 +625,7 @@ RemoteVideo.prototype.updateResolution = function (resolution) {
* @param framerate the value to update
*/
RemoteVideo.prototype.updateFramerate = function (framerate) {
if (this.connectionIndicator) {
this.connectionIndicator.updateFramerate(framerate);
}
};
RemoteVideo.prototype.removeConnectionIndicator = function () {
if (this.connectionIndicator)
this.connectionIndicator.remove();
};
RemoteVideo.prototype.hideConnectionIndicator = function () {
if (this.connectionIndicator)
this.connectionIndicator.hide();
this.updateConnectionIndicator({ framerate });
};
/**
@ -713,6 +695,10 @@ RemoteVideo.createContainer = function (spanId) {
indicatorBar.className = "videocontainer__toptoolbar";
container.appendChild(indicatorBar);
const connectionIndicatorContainer = document.createElement('span');
connectionIndicatorContainer.className = 'connection-indicator-container';
indicatorBar.appendChild(connectionIndicatorContainer);
let toolbar = document.createElement('div');
toolbar.className = "videocontainer__toolbar";
container.appendChild(toolbar);

@ -6,6 +6,9 @@ import ReactDOM from 'react-dom';
import { AudioLevelIndicator }
from '../../../react/features/audio-level-indicator';
import {
ConnectionIndicator
} from '../../../react/features/connection-indicator';
/* eslint-enable no-unused-vars */
const logger = require("jitsi-meet-logger").getLogger(__filename);
@ -64,6 +67,28 @@ function SmallVideo(VideoLayout) {
this.hideDisplayName = false;
// we can stop updating the thumbnail
this.disableUpdateView = false;
/**
* Statistics to display within the connection indicator. With new updates,
* only changed values are updated through assignment to a new reference.
*
* @private
* @type {object}
*/
this._cachedConnectionStats = {};
/**
* Whether or not the ConnectionIndicator's popover is hovered. Modifies
* how the video overlays display based on hover state.
*
* @private
* @type {boolean}
*/
this._popoverIsHovered = false;
// Bind event handlers so they are only bound once for every instance.
this._onPopoverHover = this._onPopoverHover.bind(this);
this.updateView = this.updateView.bind(this);
}
/**
@ -194,12 +219,6 @@ SmallVideo.prototype.bindHoverHandler = function () {
this.updateView();
}
);
if (this.connectionIndicator) {
this.connectionIndicator.addPopoverHoverListener(
() => {
this.updateView();
});
}
};
/**
@ -208,16 +227,34 @@ SmallVideo.prototype.bindHoverHandler = function () {
* @param percent the percent for connection quality
* @param object the data
*/
SmallVideo.prototype.updateStatsIndicator = function (percent, object) {
if(this.connectionIndicator)
this.connectionIndicator.updateConnectionQuality(percent, object);
SmallVideo.prototype.updateConnectionStats = function (percent, object) {
const newStats = Object.assign({}, object, { percent });
this.updateConnectionIndicator(newStats);
};
SmallVideo.prototype.hideIndicator = function () {
if(this.connectionIndicator)
this.connectionIndicator.hideIndicator();
/**
* Unmounts the ConnectionIndicator component.
* @returns {void}
*/
SmallVideo.prototype.removeConnectionIndicator = function () {
const connectionIndicatorContainer
= this.container.querySelector('.connection-indicator-container');
if (connectionIndicatorContainer) {
ReactDOM.unmountComponentAtNode(connectionIndicatorContainer);
}
};
/**
* Updates the connectionStatus stat which displays in the ConnectionIndicator.
* @returns {void}
*/
SmallVideo.prototype.updateConnectionStatus = function (connectionStatus) {
this.updateConnectionIndicator({ connectionStatus });
};
/**
* Shows / hides the audio muted indicator over small videos.
@ -524,9 +561,7 @@ SmallVideo.prototype.selectDisplayMode = function() {
* @private
*/
SmallVideo.prototype._isHovered = function () {
return this.videoIsHovered
|| (this.connectionIndicator
&& this.connectionIndicator.popover.popoverIsHovered);
return this.videoIsHovered || this._popoverIsHovered;
};
/**
@ -700,4 +735,44 @@ SmallVideo.prototype.initBrowserSpecificProperties = function() {
}
};
/**
* Creates or updates the connection indicator. Updates the previously known
* statistics about the participant's connection.
*
* @param {Object} newStats - New statistics to merge with previously known
* statistics about the participant's connection.
* @returns {void}
*/
SmallVideo.prototype.updateConnectionIndicator = function (newStats = {}) {
this._cachedConnectionStats
= Object.assign({}, this._cachedConnectionStats, newStats);
const connectionIndicatorContainer
= this.container.querySelector('.connection-indicator-container');
/* jshint ignore:start */
ReactDOM.render(
<ConnectionIndicator
isLocalVideo = { this.isLocal }
onHover = { this._onPopoverHover }
showMoreLink = { this.isLocal }
stats = { this._cachedConnectionStats } />,
connectionIndicatorContainer
);
/* jshint ignore:end */
};
/**
* Updates the current state of the connection indicator popover being hovered.
* If hovered, display the small video as if it is hovered.
*
* @param {boolean} popoverIsHovered - Whether or not the mouse cursor is
* currently over the connection indicator popover.
* @returns {void}
*/
SmallVideo.prototype._onPopoverHover = function (popoverIsHovered) {
this._popoverIsHovered = popoverIsHovered;
this.updateView();
};
export default SmallVideo;

@ -570,8 +570,7 @@ var VideoLayout = {
? ParticipantConnectionStatus.INTERRUPTED
: ParticipantConnectionStatus.ACTIVE;
localVideoThumbnail
.connectionIndicator.updateConnectionStatusIndicator(status);
localVideoThumbnail.updateConnectionStatus(status);
},
/**
@ -779,7 +778,7 @@ var VideoLayout = {
// Why library internal objects are passed as event's args ?
object.resolution = resolution[APP.conference.getMyUserId()];
object.framerate = framerate[APP.conference.getMyUserId()];
localVideoThumbnail.updateStatsIndicator(percent, object);
localVideoThumbnail.updateConnectionStats(percent, object);
Object.keys(resolution).forEach(function (id) {
if (APP.conference.isLocalId(id)) {
@ -817,7 +816,7 @@ var VideoLayout = {
updateConnectionStats (id, percent, object) {
let remoteVideo = remoteVideos[id];
if (remoteVideo) {
remoteVideo.updateStatsIndicator(percent, object);
remoteVideo.updateConnectionStats(percent, object);
}
},
@ -828,7 +827,7 @@ var VideoLayout = {
hideConnectionIndicator (id) {
let remoteVideo = remoteVideos[id];
if (remoteVideo)
remoteVideo.hideConnectionIndicator();
remoteVideo.removeConnectionIndicator();
},
/**
@ -894,19 +893,6 @@ var VideoLayout = {
}
},
showMore (id) {
if (id === 'local') {
localVideoThumbnail.connectionIndicator.showMore();
} else {
let remoteVideo = remoteVideos[id];
if (remoteVideo) {
remoteVideo.connectionIndicator.showMore();
} else {
logger.info("Error - no remote video for id: " + id);
}
}
},
/**
* Resizes the video area.
*

@ -0,0 +1,284 @@
import React, { Component } from 'react';
import JitsiPopover from '../../../../modules/UI/util/JitsiPopover';
import { JitsiParticipantConnectionStatus } from '../../base/lib-jitsi-meet';
import { ConnectionStatsTable } from '../../connection-stats';
declare var $: Object;
declare var interfaceConfig: Object;
// Converts the percent for connection quality into a string recognized for CSS.
const QUALITY_TO_WIDTH = [
// Full (5 bars)
{
percent: 80,
width: '100%'
},
// 4 bars
{
percent: 60,
width: '80%'
},
// 3 bars
{
percent: 40,
width: '55%'
},
// 2 bars
{
percent: 20,
width: '40%'
},
// 1 bar
{
percent: 0,
width: '20%'
}
// Note: we never show 0 bars.
];
/**
* Implements a React {@link Component} which displays the current connection
* quality percentage and has a popover to show more detailed connection stats.
*
* @extends {Component}
*/
class ConnectionIndicator extends Component {
/**
* {@code ConnectionIndicator} component's property types.
*
* @static
*/
static propTypes = {
/**
* Whether or not the displays stats are for local video.
*/
isLocalVideo: React.PropTypes.bool,
/**
* The callback to invoke when the hover state over the popover changes.
*/
onHover: React.PropTypes.func,
/**
* Whether or not the popover should display a link that can toggle
* a more detailed view of the stats.
*/
showMoreLink: React.PropTypes.bool,
/**
* An object that contains statistics related to connection quality.
*
* {
* bandwidth: Object,
* bitrate: Object,
* connectionStatus: String,
* framerate: Object,
* packetLoss: Object,
* percent: Number,
* resolution: Object,
* transport: Array
* }
*/
stats: React.PropTypes.object,
/**
* Invoked to obtain translated strings.
*/
t: React.PropTypes.func
};
/**
* Initializes a new {@code ConnectionIndicator} instance.
*
* @param {Object} props - The read-only properties with which the new
* instance is to be initialized.
*/
constructor(props) {
super(props);
/**
* The internal reference to topmost DOM/HTML element backing the React
* {@code Component}. Accessed directly for associating an element as
* the trigger for a popover.
*
* @private
* @type {HTMLDivElement}
*/
this._rootElement = null;
this.state = {
/**
* Whether or not the popover content should display additional
* statistics.
*
* @type {boolean}
*/
showMoreStats: false
};
// Bind event handlers so they are only bound once for every instance.
this._onToggleShowMore = this._onToggleShowMore.bind(this);
this._setRootElement = this._setRootElement.bind(this);
}
/**
* Creates a popover instance to display when the component is hovered.
*
* @inheritdoc
* returns {void}
*/
componentDidMount() {
this.popover = new JitsiPopover($(this._rootElement), {
content: this._renderStatisticsTable(),
skin: 'black',
position: interfaceConfig.VERTICAL_FILMSTRIP ? 'left' : 'top'
});
this.popover.addOnHoverPopover(this.props.onHover);
}
/**
* Updates the contents of the popover. This is done manually because the
* popover is not a React Component yet and so is not automatiucally aware
* of changed data.
*
* @inheritdoc
* returns {void}
*/
componentDidUpdate() {
this.popover.updateContent(this._renderStatisticsTable());
}
/**
* Cleans up any popover instance that is linked to the component.
*
* @inheritdoc
* returns {void}
*/
componentWillUnmount() {
this.popover.forceHide();
this.popover.remove();
}
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
* @returns {ReactElement}
*/
render() {
return (
<div
className = 'connection-indicator indicator'
ref = { this._setRootElement }>
<div className = 'connection indicatoricon'>
{ this._renderIcon() }
</div>
</div>
);
}
/**
* Callback to invoke when the show more link in the popover content is
* clicked. Sets the state which will determine if the popover should show
* additional statistics about the connection.
*
* @returns {void}
*/
_onToggleShowMore() {
this.setState({ showMoreStats: !this.state.showMoreStats });
}
/**
* Creates a ReactElement for displaying an icon that represents the current
* connection quality.
*
* @returns {ReactElement}
*/
_renderIcon() {
switch (this.props.stats.connectionStatus) {
case JitsiParticipantConnectionStatus.INTERRUPTED:
return (
<span className = 'connection_lost'>
<i className = 'icon-connection-lost' />
</span>
);
case JitsiParticipantConnectionStatus.INACTIVE:
return (
<span className = 'connection_ninja'>
<i className = 'icon-ninja' />
</span>
);
default: {
const { percent } = this.props.stats;
const width = QUALITY_TO_WIDTH.find(x => percent >= x.percent);
const iconWidth = width && width.width
? { width: width && width.width } : {};
return [
<span
className = 'connection_empty'
key = 'icon-empty'>
<i className = 'icon-connection' />
</span>,
<span
className = 'connection_full'
key = 'icon-full'
style = { iconWidth }>
<i className = 'icon-connection' />
</span>
];
}
}
}
/**
* Creates a {@code ConnectionStatisticsTable} instance.
*
* @returns {ReactElement}
*/
_renderStatisticsTable() {
const {
bandwidth,
bitrate,
framerate,
packetLoss,
resolution,
transport
} = this.props.stats;
return (
<ConnectionStatsTable
bandwidth = { bandwidth }
bitrate = { bitrate }
framerate = { framerate }
isLocalVideo = { this.props.isLocalVideo }
onShowMore = { this._onToggleShowMore }
packetLoss = { packetLoss }
resolution = { resolution }
shouldShowMore = { this.state.showMoreStats }
transport = { transport } />
);
}
/**
* Sets an internal reference to the component's root element.
*
* @param {Object} element - The highest DOM element in the component.
* @private
* @returns {void}
*/
_setRootElement(element) {
this._rootElement = element;
}
}
export default ConnectionIndicator;

@ -0,0 +1 @@
export { default as ConnectionIndicator } from './ConnectionIndicator';

@ -0,0 +1 @@
export * from './components';

@ -34,7 +34,11 @@ export default class Filmstrip extends Component {
id = 'localAudio'
muted = { true } />
<div className = 'videocontainer__toolbar' />
<div className = 'videocontainer__toptoolbar' />
<div className = 'videocontainer__toptoolbar'>
<span
className
= 'connection-indicator-container' />
</div>
<div className = 'videocontainer__hoverOverlay' />
</span>
</div>

Loading…
Cancel
Save