Merge pull request #1071 from jitsi/ongoing-work-video-thumbnails
Ongoing work video thumbnails
This commit is contained in:
commit
2fe69d409b
|
@ -1279,10 +1279,6 @@ export default {
|
||||||
APP.UI.updateRecordingState(status);
|
APP.UI.updateRecordingState(status);
|
||||||
});
|
});
|
||||||
|
|
||||||
room.on(ConferenceEvents.USER_STATUS_CHANGED, function (id, status) {
|
|
||||||
APP.UI.updateUserStatus(id, status);
|
|
||||||
});
|
|
||||||
|
|
||||||
room.on(ConferenceEvents.KICKED, () => {
|
room.on(ConferenceEvents.KICKED, () => {
|
||||||
APP.UI.hideStats();
|
APP.UI.hideStats();
|
||||||
APP.UI.notifyKicked();
|
APP.UI.notifyKicked();
|
||||||
|
|
|
@ -50,6 +50,15 @@
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Absolute position the element at the top left corner
|
||||||
|
**/
|
||||||
|
@mixin topLeft() {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
@mixin absoluteAligning($sizeX, $sizeY) {
|
@mixin absoluteAligning($sizeX, $sizeY) {
|
||||||
top: 50%;
|
top: 50%;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
|
|
|
@ -11,10 +11,10 @@ $hangupFontSize: 2em;
|
||||||
$defaultToolbarSize: 50px;
|
$defaultToolbarSize: 50px;
|
||||||
|
|
||||||
// Video layout.
|
// Video layout.
|
||||||
$thumbnailIndicatorSize: 23px;
|
$thumbnailToolbarHeight: 22px;
|
||||||
$thumbnailIndicatorBorder: 0px;
|
$thumbnailIndicatorBorder: 0px;
|
||||||
|
$thumbnailIndicatorSize: $thumbnailToolbarHeight;
|
||||||
$thumbnailVideoMargin: 2px;
|
$thumbnailVideoMargin: 2px;
|
||||||
$thumbnailToolbarHeight: 25px;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Color variables.
|
* Color variables.
|
||||||
|
@ -46,6 +46,7 @@ $thumbnailPictogramColor: #fff;
|
||||||
$dominantSpeakerBg: #165ecc;
|
$dominantSpeakerBg: #165ecc;
|
||||||
$raiseHandBg: #D6D61E;
|
$raiseHandBg: #D6D61E;
|
||||||
$audioLevelBg: #44A5FF;
|
$audioLevelBg: #44A5FF;
|
||||||
|
$connectionIndicatorBg: #165ecc;
|
||||||
$audioLevelShadow: rgba(9, 36, 77, 0.9);
|
$audioLevelShadow: rgba(9, 36, 77, 0.9);
|
||||||
$videoStateIndicatorColor: $defaultColor;
|
$videoStateIndicatorColor: $defaultColor;
|
||||||
$videoStateIndicatorBackground: $toolbarBackground;
|
$videoStateIndicatorBackground: $toolbarBackground;
|
||||||
|
|
|
@ -58,17 +58,36 @@
|
||||||
/**
|
/**
|
||||||
* The toolbar of the video thumbnail.
|
* The toolbar of the video thumbnail.
|
||||||
*/
|
*/
|
||||||
.videocontainer__toolbar {
|
.videocontainer__toolbar,
|
||||||
|
.videocontainer__toptoolbar {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
left: 0;
|
||||||
z-index: 1;
|
z-index: 3;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
box-sizing: border-box; // Includes the padding in the 100% width.
|
box-sizing: border-box; // Includes the padding in the 100% width.
|
||||||
height: $thumbnailToolbarHeight;
|
}
|
||||||
max-height: 100%;
|
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
.videocontainer__toolbar {
|
||||||
|
bottom: 0;
|
||||||
padding: 0 5px 0 5px;
|
padding: 0 5px 0 5px;
|
||||||
|
height: $thumbnailToolbarHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
.videocontainer__toptoolbar {
|
||||||
|
$toolbarPadding: 5px;
|
||||||
|
top: 0;
|
||||||
|
padding: $toolbarPadding;
|
||||||
|
padding-bottom: 0;
|
||||||
|
height: $thumbnailIndicatorSize + $toolbarPadding;
|
||||||
|
}
|
||||||
|
|
||||||
|
.videocontainer__hoverOverlay {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
visibility: hidden;
|
||||||
|
background: rgba(0,0,0,.6);
|
||||||
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
#remoteVideos .videocontainer.videoContainerFocused,
|
#remoteVideos .videocontainer.videoContainerFocused,
|
||||||
|
@ -176,8 +195,10 @@
|
||||||
.videocontainer .editdisplayname {
|
.videocontainer .editdisplayname {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 30%;
|
left: 10%;
|
||||||
width: 40%;
|
width: 80%;
|
||||||
|
top: 50%;
|
||||||
|
@include transform(translateY(-40%));
|
||||||
color: $participantNameColor;
|
color: $participantNameColor;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
@ -200,72 +221,10 @@
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.videocontainer>span.status {
|
|
||||||
display: inline-block;
|
|
||||||
position: absolute;
|
|
||||||
color: #FFFFFF;
|
|
||||||
background: rgba(0,0,0,.7);
|
|
||||||
text-align: center;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
width: 70%;
|
|
||||||
height: 15%;
|
|
||||||
left: 15%;
|
|
||||||
bottom: 2%;
|
|
||||||
padding: 5px;
|
|
||||||
font-size: 10pt;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
z-index: 2;
|
|
||||||
border-radius:3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.connectionindicator
|
|
||||||
{
|
|
||||||
display: inline-block;
|
|
||||||
position: absolute;
|
|
||||||
top: 7px;
|
|
||||||
right: 0;
|
|
||||||
padding: 0px 5px;
|
|
||||||
z-index: 3;
|
|
||||||
width: 18px;
|
|
||||||
height: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.connection.connection_empty
|
|
||||||
{
|
|
||||||
color: #8B8B8B;/*#FFFFFF*/
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.connection.connection_lost
|
|
||||||
{
|
|
||||||
color: #8B8B8B;
|
|
||||||
overflow: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
.connection.connection_full
|
|
||||||
{
|
|
||||||
color: #FFFFFF;/*#15A1ED*/
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.connection
|
|
||||||
{
|
|
||||||
position: absolute;
|
|
||||||
left: 0px;
|
|
||||||
top: 0px;
|
|
||||||
font-size: 8pt;
|
|
||||||
border: 0px;
|
|
||||||
width: 18px;
|
|
||||||
height: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#localVideoContainer>span.status:hover,
|
|
||||||
#localVideoContainer .displayname:hover {
|
#localVideoContainer .displayname:hover {
|
||||||
cursor: text;
|
cursor: text;
|
||||||
}
|
}
|
||||||
|
|
||||||
.videocontainer>span.status,
|
|
||||||
.videocontainer .displayname {
|
.videocontainer .displayname {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
@ -278,7 +237,6 @@
|
||||||
pointer-events: auto !important;
|
pointer-events: auto !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.videocontainer>a.status,
|
|
||||||
.videocontainer>a.displayname {
|
.videocontainer>a.displayname {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -323,25 +281,92 @@
|
||||||
margin: 0px 0px 0px 5px;
|
margin: 0px 0px 0px 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.videocontainer>span.indicator {
|
#raisehandindicator {
|
||||||
position: absolute;
|
background: $raiseHandBg;
|
||||||
top: 0px;
|
|
||||||
left: 0px;
|
|
||||||
@include circle($thumbnailIndicatorSize);
|
|
||||||
box-sizing: border-box;
|
|
||||||
line-height: $thumbnailIndicatorSize - 2*$thumbnailIndicatorBorder;
|
|
||||||
z-index: 3;
|
|
||||||
text-align: center;
|
|
||||||
background: $dominantSpeakerBg;
|
|
||||||
margin: 7px;
|
|
||||||
display: inline-block;
|
|
||||||
color: $thumbnailPictogramColor;
|
|
||||||
font-size: 8pt;
|
|
||||||
border: $thumbnailIndicatorBorder solid $thumbnailPictogramColor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.videocontainer>#raisehandindicator {
|
#connectionindicator {
|
||||||
background: $raiseHandBg;
|
background: $connectionIndicatorBg;
|
||||||
|
}
|
||||||
|
|
||||||
|
.videocontainer__toptoolbar span.indicator {
|
||||||
|
position: relative;
|
||||||
|
font-size: 8pt;
|
||||||
|
text-align: center;
|
||||||
|
line-height: $thumbnailToolbarHeight;
|
||||||
|
display: none;
|
||||||
|
padding: 0;
|
||||||
|
margin-right: 5px;
|
||||||
|
float: left;
|
||||||
|
@include circle($thumbnailIndicatorSize);
|
||||||
|
box-sizing: border-box;
|
||||||
|
z-index: 3;
|
||||||
|
background: $dominantSpeakerBg;
|
||||||
|
color: $thumbnailPictogramColor;
|
||||||
|
border: $thumbnailIndicatorBorder solid $thumbnailPictogramColor;
|
||||||
|
|
||||||
|
.indicatoricon {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 0;
|
||||||
|
@include transform(translateY(-50%));
|
||||||
|
width: $thumbnailIndicatorSize - 2 * $thumbnailIndicatorBorder;
|
||||||
|
height: $thumbnailIndicatorSize - 2 * $thumbnailIndicatorBorder;
|
||||||
|
line-height: $thumbnailIndicatorSize - 2 * $thumbnailIndicatorBorder;
|
||||||
|
}
|
||||||
|
|
||||||
|
.connection {
|
||||||
|
position: relative;
|
||||||
|
margin: 0 auto;
|
||||||
|
width: 12px;
|
||||||
|
height: 8px;
|
||||||
|
|
||||||
|
&_empty
|
||||||
|
{
|
||||||
|
@include topLeft();
|
||||||
|
max-width: 12px;
|
||||||
|
width: 12px;
|
||||||
|
color: #8B8B8B;/*#FFFFFF*/
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_lost
|
||||||
|
{
|
||||||
|
@include topLeft();
|
||||||
|
max-width: 12px;
|
||||||
|
width: 12px;
|
||||||
|
color: #8B8B8B;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_full
|
||||||
|
{
|
||||||
|
@include topLeft();
|
||||||
|
max-width: 12px;
|
||||||
|
width: 12px;
|
||||||
|
color: #FFFFFF;/*#15A1ED*/
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-connection,
|
||||||
|
.icon-connection-lost {
|
||||||
|
font-size: 6pt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.remotevideomenu
|
||||||
|
{
|
||||||
|
display: inline-block;
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
right: 0;
|
||||||
|
margin: 7px;
|
||||||
|
z-index: 3;
|
||||||
|
width: 18px;
|
||||||
|
height: 13px;
|
||||||
|
color: #FFF;
|
||||||
|
font-size: 8pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -384,12 +409,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#indicatoricon {
|
|
||||||
width: $thumbnailIndicatorSize - 2*$thumbnailIndicatorBorder;
|
|
||||||
height: $thumbnailIndicatorSize - 2*$thumbnailIndicatorBorder;
|
|
||||||
line-height: $thumbnailIndicatorSize - 2*$thumbnailIndicatorBorder;
|
|
||||||
}
|
|
||||||
|
|
||||||
#reloadPresentation {
|
#reloadPresentation {
|
||||||
display: none;
|
display: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
|
@ -254,6 +254,8 @@
|
||||||
</span>
|
</span>
|
||||||
<audio id="localAudio" autoplay muted></audio>
|
<audio id="localAudio" autoplay muted></audio>
|
||||||
<div class="videocontainer__toolbar"></div>
|
<div class="videocontainer__toolbar"></div>
|
||||||
|
<div class="videocontainer__toptoolbar"></div>
|
||||||
|
<div class="videocontainer__hoverOverlay"></div>
|
||||||
</span>
|
</span>
|
||||||
<audio id="userJoined" src="sounds/joined.wav" preload="auto"></audio>
|
<audio id="userJoined" src="sounds/joined.wav" preload="auto"></audio>
|
||||||
<audio id="userLeft" src="sounds/left.wav" preload="auto"></audio>
|
<audio id="userLeft" src="sounds/left.wav" preload="auto"></audio>
|
||||||
|
|
|
@ -609,10 +609,6 @@ UI.removeUser = function (id, displayName) {
|
||||||
VideoLayout.removeParticipantContainer(id);
|
VideoLayout.removeParticipantContainer(id);
|
||||||
};
|
};
|
||||||
|
|
||||||
UI.updateUserStatus = function (id, status) {
|
|
||||||
VideoLayout.setPresenceStatus(id, status);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update videotype for specified user.
|
* Update videotype for specified user.
|
||||||
* @param {string} id user id
|
* @param {string} id user id
|
||||||
|
|
|
@ -625,7 +625,7 @@ function SharedVideoThumb (url)
|
||||||
this.videoSpanId = "sharedVideoContainer";
|
this.videoSpanId = "sharedVideoContainer";
|
||||||
this.container = this.createContainer(this.videoSpanId);
|
this.container = this.createContainer(this.videoSpanId);
|
||||||
this.container.onclick = this.videoClick.bind(this);
|
this.container.onclick = this.videoClick.bind(this);
|
||||||
|
this.bindHoverHandler();
|
||||||
SmallVideo.call(this, VideoLayout);
|
SmallVideo.call(this, VideoLayout);
|
||||||
this.isVideoMuted = true;
|
this.isVideoMuted = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,14 +98,27 @@ var JitsiPopover = (function () {
|
||||||
var self = this;
|
var self = this;
|
||||||
$(".jitsipopover").on("mouseenter", function () {
|
$(".jitsipopover").on("mouseenter", function () {
|
||||||
self.popoverIsHovered = true;
|
self.popoverIsHovered = true;
|
||||||
|
if(typeof self.onHoverPopover === "function") {
|
||||||
|
self.onHoverPopover(self.popoverIsHovered);
|
||||||
|
}
|
||||||
}).on("mouseleave", function () {
|
}).on("mouseleave", function () {
|
||||||
self.popoverIsHovered = false;
|
self.popoverIsHovered = false;
|
||||||
self.hide();
|
self.hide();
|
||||||
|
if(typeof self.onHoverPopover === "function") {
|
||||||
|
self.onHoverPopover(self.popoverIsHovered);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.refreshPosition();
|
this.refreshPosition();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a hover listener to the popover.
|
||||||
|
*/
|
||||||
|
JitsiPopover.prototype.addOnHoverPopover = function (listener) {
|
||||||
|
this.onHoverPopover = listener;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refreshes the position of the popover.
|
* Refreshes the position of the popover.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -136,7 +136,7 @@ const TOOLTIP_POSITIONS = {
|
||||||
element.setAttribute('data-i18n', '[content]' + key);
|
element.setAttribute('data-i18n', '[content]' + key);
|
||||||
|
|
||||||
APP.translation.translateElement($(element));
|
APP.translation.translateElement($(element));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -237,6 +237,18 @@ const TOOLTIP_POSITIONS = {
|
||||||
$("#"+id).addClass("hide");
|
$("#"+id).addClass("hide");
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows / hides the element with the given jQuery selector.
|
||||||
|
*
|
||||||
|
* @param {jQuery} selector the jQuery selector of the element to show/hide
|
||||||
|
* @param {boolean} isVisible
|
||||||
|
*/
|
||||||
|
setVisibility(selector, isVisible) {
|
||||||
|
if (selector && selector.length > 0) {
|
||||||
|
selector.css("visibility", isVisible ? "visible" : "hidden");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
hideDisabledButtons: function (mappings) {
|
hideDisabledButtons: function (mappings) {
|
||||||
var selector = Object.keys(mappings)
|
var selector = Object.keys(mappings)
|
||||||
.map(function (buttonName) {
|
.map(function (buttonName) {
|
||||||
|
@ -376,6 +388,49 @@ const TOOLTIP_POSITIONS = {
|
||||||
"cursor": "default"
|
"cursor": "default"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an "indicator" span for a video thumbnail.
|
||||||
|
* If element doesn't exist then creates it and appends
|
||||||
|
* video span container.
|
||||||
|
*
|
||||||
|
* @param {object} opts
|
||||||
|
* @param opts.indicatorId {String} - identificator of indicator
|
||||||
|
* @param opts.videoSpanId {String} - identificator of video span
|
||||||
|
* @param opts.content {String} HTML content of indicator
|
||||||
|
* @param opts.tooltip {String} - tooltip key for translation
|
||||||
|
*
|
||||||
|
* @returns {HTMLSpanElement} indicatorSpan
|
||||||
|
*/
|
||||||
|
getVideoThumbnailIndicatorSpan(opts = {}) {
|
||||||
|
let indicatorId = opts.indicatorId;
|
||||||
|
let videoSpanId = opts.videoSpanId;
|
||||||
|
let indicators = $(`#${videoSpanId} [id="${indicatorId}"]`);
|
||||||
|
let indicatorSpan;
|
||||||
|
|
||||||
|
if (indicators.length <= 0) {
|
||||||
|
indicatorSpan = document.createElement('span');
|
||||||
|
indicatorSpan.className = 'indicator';
|
||||||
|
indicatorSpan.id = indicatorId;
|
||||||
|
|
||||||
|
if(opts.content) {
|
||||||
|
indicatorSpan.innerHTML = opts.content;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.tooltip) {
|
||||||
|
this.setTooltip(indicatorSpan, opts.tooltip, "top");
|
||||||
|
APP.translation.translateElement($(indicatorSpan));
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById(videoSpanId)
|
||||||
|
.querySelector('.videocontainer__toptoolbar')
|
||||||
|
.appendChild(indicatorSpan);
|
||||||
|
} else {
|
||||||
|
indicatorSpan = indicators[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return indicatorSpan;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2,13 +2,15 @@
|
||||||
/* jshint -W101 */
|
/* jshint -W101 */
|
||||||
import JitsiPopover from "../util/JitsiPopover";
|
import JitsiPopover from "../util/JitsiPopover";
|
||||||
import VideoLayout from "./VideoLayout";
|
import VideoLayout from "./VideoLayout";
|
||||||
|
import UIUtil from "../util/UIUtil";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs new connection indicator.
|
* Constructs new connection indicator.
|
||||||
* @param videoContainer the video container associated with the indicator.
|
* @param videoContainer the video container associated with the indicator.
|
||||||
|
* @param videoId the identifier of the video
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
function ConnectionIndicator(videoContainer, id) {
|
function ConnectionIndicator(videoContainer, videoId) {
|
||||||
this.videoContainer = videoContainer;
|
this.videoContainer = videoContainer;
|
||||||
this.bandwidth = null;
|
this.bandwidth = null;
|
||||||
this.packetLoss = null;
|
this.packetLoss = null;
|
||||||
|
@ -18,7 +20,7 @@ function ConnectionIndicator(videoContainer, id) {
|
||||||
this.isResolutionHD = null;
|
this.isResolutionHD = null;
|
||||||
this.transport = [];
|
this.transport = [];
|
||||||
this.popover = null;
|
this.popover = null;
|
||||||
this.id = id;
|
this.id = videoId;
|
||||||
this.create();
|
this.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,12 +34,12 @@ function ConnectionIndicator(videoContainer, id) {
|
||||||
* 0: string}}
|
* 0: string}}
|
||||||
*/
|
*/
|
||||||
ConnectionIndicator.connectionQualityValues = {
|
ConnectionIndicator.connectionQualityValues = {
|
||||||
98: "18px", //full
|
98: "100%", //full
|
||||||
81: "15px",//4 bars
|
81: "80%",//4 bars
|
||||||
64: "11px",//3 bars
|
64: "55%",//3 bars
|
||||||
47: "7px",//2 bars
|
47: "40%",//2 bars
|
||||||
30: "3px",//1 bar
|
30: "20%",//1 bar
|
||||||
0: "0px"//empty
|
0: "0"//empty
|
||||||
};
|
};
|
||||||
|
|
||||||
ConnectionIndicator.getIP = function(value) {
|
ConnectionIndicator.getIP = function(value) {
|
||||||
|
@ -259,18 +261,22 @@ function createIcon(classes, iconClass) {
|
||||||
* Creates the indicator
|
* Creates the indicator
|
||||||
*/
|
*/
|
||||||
ConnectionIndicator.prototype.create = function () {
|
ConnectionIndicator.prototype.create = function () {
|
||||||
this.connectionIndicatorContainer = document.createElement("div");
|
let indicatorId = 'connectionindicator';
|
||||||
this.connectionIndicatorContainer.className = "connectionindicator";
|
let element = UIUtil.getVideoThumbnailIndicatorSpan({
|
||||||
this.connectionIndicatorContainer.style.display = "none";
|
videoSpanId: this.videoContainer.videoSpanId,
|
||||||
this.videoContainer.container.appendChild(
|
indicatorId
|
||||||
this.connectionIndicatorContainer);
|
});
|
||||||
this.popover = new JitsiPopover(
|
element.classList.add('show');
|
||||||
$("#" + this.videoContainer.videoSpanId + " > .connectionindicator"), {
|
this.connectionIndicatorContainer = element;
|
||||||
content: "<div class=\"connection-info\" " +
|
|
||||||
"data-i18n='connectionindicator.na'></div>",
|
let popoverContent = (
|
||||||
skin: "black",
|
`<div class="connection-info" data-i18n="${indicatorId}.na"></div>`
|
||||||
onBeforePosition: el => APP.translation.translateElement(el)
|
);
|
||||||
});
|
this.popover = new JitsiPopover($(element), {
|
||||||
|
content: popoverContent,
|
||||||
|
skin: "black",
|
||||||
|
onBeforePosition: el => APP.translation.translateElement(el)
|
||||||
|
});
|
||||||
|
|
||||||
// override popover show method to make sure we will update the content
|
// override popover show method to make sure we will update the content
|
||||||
// before showing the popover
|
// before showing the popover
|
||||||
|
@ -283,13 +289,19 @@ ConnectionIndicator.prototype.create = function () {
|
||||||
origShowFunc.call(this.popover);
|
origShowFunc.call(this.popover);
|
||||||
}.bind(this);
|
}.bind(this);
|
||||||
|
|
||||||
this.emptyIcon = this.connectionIndicatorContainer.appendChild(
|
let connectionIconContainer = document.createElement('div');
|
||||||
createIcon(["connection", "connection_empty"], "icon-connection"));
|
connectionIconContainer.className = 'connection indicatoricon';
|
||||||
this.fullIcon = this.connectionIndicatorContainer.appendChild(
|
|
||||||
createIcon(["connection", "connection_full"], "icon-connection"));
|
|
||||||
this.interruptedIndicator = this.connectionIndicatorContainer.appendChild(
|
this.emptyIcon = connectionIconContainer.appendChild(
|
||||||
createIcon(["connection", "connection_lost"],"icon-connection-lost"));
|
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.interruptedIndicator).hide();
|
$(this.interruptedIndicator).hide();
|
||||||
|
this.connectionIndicatorContainer.appendChild(connectionIconContainer);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -320,7 +332,6 @@ ConnectionIndicator.prototype.updateConnectionStatusIndicator
|
||||||
$(this.interruptedIndicator).show();
|
$(this.interruptedIndicator).show();
|
||||||
$(this.emptyIcon).hide();
|
$(this.emptyIcon).hide();
|
||||||
$(this.fullIcon).hide();
|
$(this.fullIcon).hide();
|
||||||
this.updateConnectionQuality(0 /* zero bars */);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -427,4 +438,11 @@ ConnectionIndicator.prototype.updateResolutionIndicator = function () {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a hover listener to the popover.
|
||||||
|
*/
|
||||||
|
ConnectionIndicator.prototype.addPopoverHoverListener = function (listener) {
|
||||||
|
this.popover.addOnHoverPopover(listener);
|
||||||
|
};
|
||||||
|
|
||||||
export default ConnectionIndicator;
|
export default ConnectionIndicator;
|
||||||
|
|
|
@ -11,6 +11,8 @@ function LocalVideo(VideoLayout, emitter) {
|
||||||
this.videoSpanId = "localVideoContainer";
|
this.videoSpanId = "localVideoContainer";
|
||||||
this.container = $("#localVideoContainer").get(0);
|
this.container = $("#localVideoContainer").get(0);
|
||||||
this.localVideoId = null;
|
this.localVideoId = null;
|
||||||
|
this.createConnectionIndicator();
|
||||||
|
this.bindHoverHandler();
|
||||||
if(config.enableLocalVideoFlip)
|
if(config.enableLocalVideoFlip)
|
||||||
this._buildContextMenu();
|
this._buildContextMenu();
|
||||||
this.isLocal = true;
|
this.isLocal = true;
|
||||||
|
@ -27,7 +29,6 @@ function LocalVideo(VideoLayout, emitter) {
|
||||||
// Set default display name.
|
// Set default display name.
|
||||||
this.setDisplayName();
|
this.setDisplayName();
|
||||||
|
|
||||||
this.createConnectionIndicator();
|
|
||||||
this.addAudioLevelIndicator();
|
this.addAudioLevelIndicator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +71,6 @@ LocalVideo.prototype.setDisplayName = function(displayName) {
|
||||||
nameSpan = document.createElement('span');
|
nameSpan = document.createElement('span');
|
||||||
nameSpan.className = 'displayname';
|
nameSpan.className = 'displayname';
|
||||||
document.getElementById(this.videoSpanId)
|
document.getElementById(this.videoSpanId)
|
||||||
.querySelector('.videocontainer__toolbar')
|
|
||||||
.appendChild(nameSpan);
|
.appendChild(nameSpan);
|
||||||
|
|
||||||
|
|
||||||
|
@ -104,7 +104,6 @@ LocalVideo.prototype.setDisplayName = function(displayName) {
|
||||||
APP.translation.translateElement($(editableText));
|
APP.translation.translateElement($(editableText));
|
||||||
|
|
||||||
this.container
|
this.container
|
||||||
.querySelector('.videocontainer__toolbar')
|
|
||||||
.appendChild(editableText);
|
.appendChild(editableText);
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
@ -115,7 +114,7 @@ LocalVideo.prototype.setDisplayName = function(displayName) {
|
||||||
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
$localDisplayName.hide();
|
UIUtil.setVisibility($localDisplayName, false);
|
||||||
$editDisplayName.show();
|
$editDisplayName.show();
|
||||||
$editDisplayName.focus();
|
$editDisplayName.focus();
|
||||||
$editDisplayName.select();
|
$editDisplayName.select();
|
||||||
|
@ -123,7 +122,7 @@ LocalVideo.prototype.setDisplayName = function(displayName) {
|
||||||
$editDisplayName.one("focusout", function () {
|
$editDisplayName.one("focusout", function () {
|
||||||
self.emitter.emit(UIEvents.NICKNAME_CHANGED, this.value);
|
self.emitter.emit(UIEvents.NICKNAME_CHANGED, this.value);
|
||||||
$editDisplayName.hide();
|
$editDisplayName.hide();
|
||||||
$localDisplayName.show();
|
UIUtil.setVisibility($localDisplayName, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
$editDisplayName.on('keydown', function (e) {
|
$editDisplayName.on('keydown', function (e) {
|
||||||
|
|
|
@ -31,6 +31,7 @@ function RemoteVideo(user, VideoLayout, emitter) {
|
||||||
this.addRemoteVideoContainer();
|
this.addRemoteVideoContainer();
|
||||||
this.connectionIndicator = new ConnectionIndicator(this, this.id);
|
this.connectionIndicator = new ConnectionIndicator(this, this.id);
|
||||||
this.setDisplayName();
|
this.setDisplayName();
|
||||||
|
this.bindHoverHandler();
|
||||||
this.flipX = false;
|
this.flipX = false;
|
||||||
this.isLocal = false;
|
this.isLocal = false;
|
||||||
/**
|
/**
|
||||||
|
@ -233,11 +234,9 @@ if (!interfaceConfig.filmStripOnly) {
|
||||||
RemoteVideo.prototype.addRemoteVideoMenu = function () {
|
RemoteVideo.prototype.addRemoteVideoMenu = function () {
|
||||||
|
|
||||||
var spanElement = document.createElement('span');
|
var spanElement = document.createElement('span');
|
||||||
spanElement.className = 'remotevideomenu toolbar-icon right';
|
spanElement.className = 'remotevideomenu';
|
||||||
|
|
||||||
this.container
|
this.container.appendChild(spanElement);
|
||||||
.querySelector('.videocontainer__toolbar')
|
|
||||||
.appendChild(spanElement);
|
|
||||||
|
|
||||||
var menuElement = document.createElement('i');
|
var menuElement = document.createElement('i');
|
||||||
menuElement.className = 'icon-menu-up';
|
menuElement.className = 'icon-menu-up';
|
||||||
|
@ -512,9 +511,10 @@ RemoteVideo.prototype.hideConnectionIndicator = function () {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the display name for the given video span id.
|
* Sets the display name for the given video span id.
|
||||||
|
*
|
||||||
|
* @param displayName the display name to set
|
||||||
*/
|
*/
|
||||||
RemoteVideo.prototype.setDisplayName = function(displayName, key) {
|
RemoteVideo.prototype.setDisplayName = function(displayName) {
|
||||||
|
|
||||||
if (!this.container) {
|
if (!this.container) {
|
||||||
console.warn( "Unable to set displayName - " + this.videoSpanId +
|
console.warn( "Unable to set displayName - " + this.videoSpanId +
|
||||||
" does not exist");
|
" does not exist");
|
||||||
|
@ -530,10 +530,6 @@ RemoteVideo.prototype.setDisplayName = function(displayName, key) {
|
||||||
if (displaynameSpan.text() !== displayName)
|
if (displaynameSpan.text() !== displayName)
|
||||||
displaynameSpan.text(displayName);
|
displaynameSpan.text(displayName);
|
||||||
}
|
}
|
||||||
else if (key && key.length > 0) {
|
|
||||||
var nameHtml = APP.translation.generateTranslationHTML(key);
|
|
||||||
$('#' + this.videoSpanId + '_name').html(nameHtml);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
$('#' + this.videoSpanId + '_name').text(
|
$('#' + this.videoSpanId + '_name').text(
|
||||||
interfaceConfig.DEFAULT_REMOTE_DISPLAY_NAME);
|
interfaceConfig.DEFAULT_REMOTE_DISPLAY_NAME);
|
||||||
|
@ -541,7 +537,6 @@ RemoteVideo.prototype.setDisplayName = function(displayName, key) {
|
||||||
nameSpan = document.createElement('span');
|
nameSpan = document.createElement('span');
|
||||||
nameSpan.className = 'displayname';
|
nameSpan.className = 'displayname';
|
||||||
$('#' + this.videoSpanId)[0]
|
$('#' + this.videoSpanId)[0]
|
||||||
.querySelector('.videocontainer__toolbar')
|
|
||||||
.appendChild(nameSpan);
|
.appendChild(nameSpan);
|
||||||
|
|
||||||
if (displayName && displayName.length > 0) {
|
if (displayName && displayName.length > 0) {
|
||||||
|
@ -573,10 +568,18 @@ RemoteVideo.createContainer = function (spanId) {
|
||||||
container.id = spanId;
|
container.id = spanId;
|
||||||
container.className = 'videocontainer';
|
container.className = 'videocontainer';
|
||||||
|
|
||||||
|
let indicatorBar = document.createElement('div');
|
||||||
|
indicatorBar.className = "videocontainer__toptoolbar";
|
||||||
|
container.appendChild(indicatorBar);
|
||||||
|
|
||||||
let toolbar = document.createElement('div');
|
let toolbar = document.createElement('div');
|
||||||
toolbar.className = "videocontainer__toolbar";
|
toolbar.className = "videocontainer__toolbar";
|
||||||
container.appendChild(toolbar);
|
container.appendChild(toolbar);
|
||||||
|
|
||||||
|
let overlay = document.createElement('div');
|
||||||
|
overlay.className = "videocontainer__hoverOverlay";
|
||||||
|
container.appendChild(overlay);
|
||||||
|
|
||||||
var remotes = document.getElementById('remoteVideos');
|
var remotes = document.getElementById('remoteVideos');
|
||||||
return remotes.appendChild(container);
|
return remotes.appendChild(container);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* global $, APP, JitsiMeetJS, interfaceConfig */
|
/* global $, JitsiMeetJS, interfaceConfig */
|
||||||
import Avatar from "../avatar/Avatar";
|
import Avatar from "../avatar/Avatar";
|
||||||
import UIUtil from "../util/UIUtil";
|
import UIUtil from "../util/UIUtil";
|
||||||
import UIEvents from "../../../service/UI/UIEvents";
|
import UIEvents from "../../../service/UI/UIEvents";
|
||||||
|
@ -21,11 +21,27 @@ const DISPLAY_VIDEO = 0;
|
||||||
const DISPLAY_AVATAR = 1;
|
const DISPLAY_AVATAR = 1;
|
||||||
/**
|
/**
|
||||||
* Display mode constant used when neither video nor avatar is being displayed
|
* Display mode constant used when neither video nor avatar is being displayed
|
||||||
* on the small video.
|
* on the small video. And we just show the display name.
|
||||||
* @type {number}
|
* @type {number}
|
||||||
* @constant
|
* @constant
|
||||||
*/
|
*/
|
||||||
const DISPLAY_BLACKNESS = 2;
|
const DISPLAY_BLACKNESS_WITH_NAME = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display mode constant used when video is displayed and display name
|
||||||
|
* at the same time.
|
||||||
|
* @type {number}
|
||||||
|
* @constant
|
||||||
|
*/
|
||||||
|
const DISPLAY_VIDEO_WITH_NAME = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display mode constant used when neither video nor avatar is being displayed
|
||||||
|
* on the small video. And we just show the display name.
|
||||||
|
* @type {number}
|
||||||
|
* @constant
|
||||||
|
*/
|
||||||
|
const DISPLAY_AVATAR_WITH_NAME = 4;
|
||||||
|
|
||||||
function SmallVideo(VideoLayout) {
|
function SmallVideo(VideoLayout) {
|
||||||
this.isAudioMuted = false;
|
this.isAudioMuted = false;
|
||||||
|
@ -34,12 +50,7 @@ function SmallVideo(VideoLayout) {
|
||||||
this.videoStream = null;
|
this.videoStream = null;
|
||||||
this.audioStream = null;
|
this.audioStream = null;
|
||||||
this.VideoLayout = VideoLayout;
|
this.VideoLayout = VideoLayout;
|
||||||
}
|
this.videoIsHovered = false;
|
||||||
|
|
||||||
function setVisibility(selector, show) {
|
|
||||||
if (selector && selector.length > 0) {
|
|
||||||
selector.css("visibility", show ? "visible" : "hidden");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -60,18 +71,6 @@ SmallVideo.prototype.isVisible = function () {
|
||||||
return $('#' + this.videoSpanId).is(':visible');
|
return $('#' + this.videoSpanId).is(':visible');
|
||||||
};
|
};
|
||||||
|
|
||||||
SmallVideo.prototype.showDisplayName = function(isShow) {
|
|
||||||
var nameSpan = $('#' + this.videoSpanId + ' .displayname').get(0);
|
|
||||||
if (isShow) {
|
|
||||||
if (nameSpan && nameSpan.innerHTML && nameSpan.innerHTML.length)
|
|
||||||
nameSpan.setAttribute("style", "display:inline-block;");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (nameSpan)
|
|
||||||
nameSpan.setAttribute("style", "display:none;");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables / disables the device availability icons for this small video.
|
* Enables / disables the device availability icons for this small video.
|
||||||
* @param {enable} set to {true} to enable and {false} to disable
|
* @param {enable} set to {true} to enable and {false} to disable
|
||||||
|
@ -132,37 +131,6 @@ SmallVideo.prototype.getVideoType = function () {
|
||||||
return this.videoType;
|
return this.videoType;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows the presence status message for the given video.
|
|
||||||
*/
|
|
||||||
SmallVideo.prototype.setPresenceStatus = function (statusMsg) {
|
|
||||||
if (!this.container) {
|
|
||||||
// No container
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var statusSpan = $('#' + this.videoSpanId + '>span.status');
|
|
||||||
if (!statusSpan.length) {
|
|
||||||
//Add status span
|
|
||||||
statusSpan = document.createElement('span');
|
|
||||||
statusSpan.className = 'status';
|
|
||||||
statusSpan.id = this.videoSpanId + '_status';
|
|
||||||
$('#' + this.videoSpanId)[0].appendChild(statusSpan);
|
|
||||||
|
|
||||||
statusSpan = $('#' + this.videoSpanId + '>span.status');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Display status
|
|
||||||
if (statusMsg && statusMsg.length) {
|
|
||||||
$('#' + this.videoSpanId + '_status').text(statusMsg);
|
|
||||||
statusSpan.get(0).setAttribute("style", "display:inline-block;");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Hide
|
|
||||||
statusSpan.get(0).setAttribute("style", "display:none;");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an audio or video element for a particular MediaStream.
|
* Creates an audio or video element for a particular MediaStream.
|
||||||
*/
|
*/
|
||||||
|
@ -192,6 +160,29 @@ SmallVideo.getStreamElementID = function (stream) {
|
||||||
return (isVideo ? 'remoteVideo_' : 'remoteAudio_') + stream.getId();
|
return (isVideo ? 'remoteVideo_' : 'remoteAudio_') + stream.getId();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures hoverIn/hoverOut handlers. Depends on connection indicator.
|
||||||
|
*/
|
||||||
|
SmallVideo.prototype.bindHoverHandler = function () {
|
||||||
|
// Add hover handler
|
||||||
|
$(this.container).hover(
|
||||||
|
() => {
|
||||||
|
this.videoIsHovered = true;
|
||||||
|
this.updateView();
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
this.videoIsHovered = false;
|
||||||
|
this.updateView();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (this.connectionIndicator) {
|
||||||
|
this.connectionIndicator.addPopoverHoverListener(
|
||||||
|
() => {
|
||||||
|
this.updateView();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the data for the indicator
|
* Updates the data for the indicator
|
||||||
* @param id the id of the indicator
|
* @param id the id of the indicator
|
||||||
|
@ -395,6 +386,16 @@ SmallVideo.prototype.$avatar = function () {
|
||||||
return $('#' + this.videoSpanId + ' .userAvatar');
|
return $('#' + this.videoSpanId + ' .userAvatar');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the display name element, which appears on the video thumbnail.
|
||||||
|
*
|
||||||
|
* @return {jQuery} a jQuery selector pointing to the display name element of
|
||||||
|
* the video thumbnail
|
||||||
|
*/
|
||||||
|
SmallVideo.prototype.$displayName = function () {
|
||||||
|
return $('#' + this.videoSpanId + ' .displayname');
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables / disables the css responsible for focusing/pinning a video
|
* Enables / disables the css responsible for focusing/pinning a video
|
||||||
* thumbnail.
|
* thumbnail.
|
||||||
|
@ -445,19 +446,35 @@ SmallVideo.prototype.isVideoPlayable = function() {
|
||||||
* Determines what should be display on the thumbnail.
|
* Determines what should be display on the thumbnail.
|
||||||
*
|
*
|
||||||
* @return {number} one of <tt>DISPLAY_VIDEO</tt>,<tt>DISPLAY_AVATAR</tt>
|
* @return {number} one of <tt>DISPLAY_VIDEO</tt>,<tt>DISPLAY_AVATAR</tt>
|
||||||
* or <tt>DISPLAY_BLACKNESS</tt>.
|
* or <tt>DISPLAY_BLACKNESS_WITH_NAME</tt>.
|
||||||
*/
|
*/
|
||||||
SmallVideo.prototype.selectDisplayMode = function() {
|
SmallVideo.prototype.selectDisplayMode = function() {
|
||||||
// Display name is always and only displayed when user is on the stage
|
// Display name is always and only displayed when user is on the stage
|
||||||
if (this.isCurrentlyOnLargeVideo()) {
|
if (this.isCurrentlyOnLargeVideo()) {
|
||||||
return DISPLAY_BLACKNESS;
|
return DISPLAY_BLACKNESS_WITH_NAME;
|
||||||
} else if (this.isVideoPlayable() && this.selectVideoElement().length) {
|
} else if (this.isVideoPlayable() && this.selectVideoElement().length) {
|
||||||
return DISPLAY_VIDEO;
|
// check hovering and change state to video with name
|
||||||
|
return this._isHovered() ?
|
||||||
|
DISPLAY_VIDEO_WITH_NAME : DISPLAY_VIDEO;
|
||||||
} else {
|
} else {
|
||||||
return DISPLAY_AVATAR;
|
// check hovering and change state to avatar with name
|
||||||
|
return this._isHovered() ?
|
||||||
|
DISPLAY_AVATAR_WITH_NAME : DISPLAY_AVATAR;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether current video is considered hovered. Currently it is hovered
|
||||||
|
* if the mouse is over the video, or if the connection
|
||||||
|
* indicator is shown(hovered).
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
SmallVideo.prototype._isHovered = function () {
|
||||||
|
return this.videoIsHovered
|
||||||
|
|| (this.connectionIndicator
|
||||||
|
&& this.connectionIndicator.popover.popoverIsHovered);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hides or shows the user's avatar.
|
* Hides or shows the user's avatar.
|
||||||
* This update assumes that large video had been updated and we will
|
* This update assumes that large video had been updated and we will
|
||||||
|
@ -479,10 +496,25 @@ SmallVideo.prototype.updateView = function () {
|
||||||
|
|
||||||
// Determine whether video, avatar or blackness should be displayed
|
// Determine whether video, avatar or blackness should be displayed
|
||||||
let displayMode = this.selectDisplayMode();
|
let displayMode = this.selectDisplayMode();
|
||||||
// Show/hide video
|
// Show/hide video.
|
||||||
setVisibility(this.selectVideoElement(), displayMode === DISPLAY_VIDEO);
|
UIUtil.setVisibility( this.selectVideoElement(),
|
||||||
// Show/hide the avatar
|
(displayMode === DISPLAY_VIDEO
|
||||||
setVisibility(this.$avatar(), displayMode === DISPLAY_AVATAR);
|
|| displayMode === DISPLAY_VIDEO_WITH_NAME));
|
||||||
|
// Show/hide the avatar.
|
||||||
|
UIUtil.setVisibility( this.$avatar(),
|
||||||
|
(displayMode === DISPLAY_AVATAR
|
||||||
|
|| displayMode === DISPLAY_AVATAR_WITH_NAME));
|
||||||
|
// Show/hide the display name.
|
||||||
|
UIUtil.setVisibility( this.$displayName(),
|
||||||
|
(displayMode === DISPLAY_BLACKNESS_WITH_NAME
|
||||||
|
|| displayMode === DISPLAY_VIDEO_WITH_NAME
|
||||||
|
|| displayMode === DISPLAY_AVATAR_WITH_NAME));
|
||||||
|
// show hide overlay when there is a video or avatar under
|
||||||
|
// the display name
|
||||||
|
UIUtil.setVisibility( $('#' + this.videoSpanId
|
||||||
|
+ ' .videocontainer__hoverOverlay'),
|
||||||
|
(displayMode === DISPLAY_AVATAR_WITH_NAME
|
||||||
|
|| displayMode === DISPLAY_VIDEO_WITH_NAME));
|
||||||
};
|
};
|
||||||
|
|
||||||
SmallVideo.prototype.avatarChanged = function (avatarUrl) {
|
SmallVideo.prototype.avatarChanged = function (avatarUrl) {
|
||||||
|
@ -519,13 +551,21 @@ SmallVideo.prototype.showDominantSpeakerIndicator = function (show) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var indicatorSpan = this.getIndicatorSpan({
|
let indicatorSpanId = "dominantspeakerindicator";
|
||||||
id: 'dominantspeakerindicator',
|
let content = `<i id="indicatoricon"
|
||||||
content: '<i id="indicatoricon" class="fa fa-bullhorn"></i>',
|
' class="indicatoricon fa fa-bullhorn"></i>`;
|
||||||
|
let indicatorSpan = UIUtil.getVideoThumbnailIndicatorSpan({
|
||||||
|
videoSpanId: this.videoSpanId,
|
||||||
|
indicatorId: indicatorSpanId,
|
||||||
|
content,
|
||||||
tooltip: 'speaker'
|
tooltip: 'speaker'
|
||||||
});
|
});
|
||||||
|
|
||||||
indicatorSpan.style.display = show ? "" : "none";
|
if (show) {
|
||||||
|
indicatorSpan.classList.add('show');
|
||||||
|
} else {
|
||||||
|
indicatorSpan.classList.remove('show');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -539,43 +579,21 @@ SmallVideo.prototype.showRaisedHandIndicator = function (show) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var indicatorSpan = this.getIndicatorSpan({
|
let indicatorSpanId = "raisehandindicator";
|
||||||
id: 'raisehandindicator',
|
let content = `<i id="indicatoricon"
|
||||||
content: '<i id="indicatoricon" class="icon-raised-hand"></i>',
|
class="icon-raised-hand indicatoricon"></i>`;
|
||||||
|
let indicatorSpan = UIUtil.getVideoThumbnailIndicatorSpan({
|
||||||
|
indicatorId: indicatorSpanId,
|
||||||
|
videoSpanId: this.videoSpanId,
|
||||||
|
content,
|
||||||
tooltip: 'raisedHand'
|
tooltip: 'raisedHand'
|
||||||
});
|
});
|
||||||
|
|
||||||
indicatorSpan.style.display = show ? "" : "none";
|
if (show) {
|
||||||
};
|
indicatorSpan.classList.add('show');
|
||||||
|
} else {
|
||||||
/**
|
indicatorSpan.classList.remove('show');
|
||||||
* Gets (creating if necessary) the "indicator" span for this SmallVideo.
|
|
||||||
*
|
|
||||||
* @param options.id {String} element ID
|
|
||||||
* @param options.content {String} HTML content of the indicator
|
|
||||||
* @param options.tooltip {String} The key that should be passed to tooltip
|
|
||||||
*
|
|
||||||
* @returns {HTMLElement} DOM represention of the indicator
|
|
||||||
*/
|
|
||||||
SmallVideo.prototype.getIndicatorSpan = function(options) {
|
|
||||||
var indicator = this.container.querySelector('#' + options.id);
|
|
||||||
|
|
||||||
if (indicator) {
|
|
||||||
return indicator;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
indicator = document.createElement('span');
|
|
||||||
indicator.className = 'indicator';
|
|
||||||
indicator.id = options.id;
|
|
||||||
|
|
||||||
indicator.innerHTML = options.content;
|
|
||||||
|
|
||||||
UIUtil.setTooltip(indicator, options.tooltip, "top");
|
|
||||||
APP.translation.translateElement($(indicator));
|
|
||||||
|
|
||||||
this.container.appendChild(indicator);
|
|
||||||
|
|
||||||
return indicator;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -449,15 +449,6 @@ var VideoLayout = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows the presence status message for the given video.
|
|
||||||
*/
|
|
||||||
setPresenceStatus (id, statusMsg) {
|
|
||||||
let remoteVideo = remoteVideos[id];
|
|
||||||
if (remoteVideo)
|
|
||||||
remoteVideo.setPresenceStatus(statusMsg);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows a visual indicator for the moderator of the conference.
|
* Shows a visual indicator for the moderator of the conference.
|
||||||
* On local or remote participants.
|
* On local or remote participants.
|
||||||
|
|
Loading…
Reference in New Issue