diff --git a/css/_font.scss b/css/_font.scss
index 9844e7e51..b5c519b67 100644
--- a/css/_font.scss
+++ b/css/_font.scss
@@ -16,7 +16,7 @@
font-weight: normal;
font-variant: normal;
text-transform: none;
- line-height: 0.75em;
+ line-height: 1.22em;
font-size: 1.22em;
/* Better Font Rendering =========== */
diff --git a/css/_mixins.scss b/css/_mixins.scss
index 43aec2431..1ff283e51 100644
--- a/css/_mixins.scss
+++ b/css/_mixins.scss
@@ -36,6 +36,19 @@
}
}
+@mixin circle($diameter) {
+ width: $diameter;
+ height: $diameter;
+ border-radius: 50%;
+}
+
+@mixin absoluteAligning($sizeX, $sizeY) {
+ top: 50%;
+ left: 50%;
+ position: absolute;
+ @include transform(translate(-#{$sizeX / 2}, -#{$sizeY / 2}))
+}
+
@mixin transform($func) {
-moz-transform: $func;
-ms-transform: $func;
diff --git a/css/_variables.scss b/css/_variables.scss
index 7ccfc269e..a2f3f9416 100644
--- a/css/_variables.scss
+++ b/css/_variables.scss
@@ -10,6 +10,11 @@ $hangupFontSize: 2em;
*/
$defaultToolbarSize: 50px;
+// Video layout.
+$thumbnailIndicatorSize: 23px;
+$thumbnailIndicatorBorder: 0px;
+$thumbnailVideoMargin: 2px;
+
/**
* Color variables.
*/
@@ -17,13 +22,29 @@ $defaultColor: #F1F1F1;
$defaultSemiDarkColor: #ACACAC;
$defaultDarkColor: #4F4F4F;
$defaultBackground: #474747;
+
+// Toolbar
$toolbarSelectBackground: rgba(0, 0, 0, .6);
+
+// Main controls
$inputBackground: rgba(132, 132, 132, .5);
$inputSemiBackground: rgba(132, 132, 132, .8);
$inputLightBackground: #EBEBEB;
$inputBorderColor: #EBEBEB;
$buttonBackground: #44A5FF;
+// Video layout.
+$videoThumbnailHovered: #44A5FF;
+$videoThumbnailSelected: #165ecc;
+$participantNameColor: #fff;
+$thumbnailPictogramColor: #fff;
+$dominantSpeakerBg: #165ecc;
+$raiseHandBg: #D6D61E;
+
+$rateStarDefault: #ccc;
+$rateStarActivity: #165ecc;
+$rateStarLabelColor: #333;
+
/**
* Misc.
*/
@@ -34,8 +55,4 @@ $defaultWatermarkLink: '../images/watermark.png';
* Z-indexes. TODO: Replace this by a function.
*/
$toolbarZ: 900;
-$overlayZ: 800;
-
-$rateStarDefault: #ccc;
-$rateStarActivity: #f6c342;
-$rateStarLabelColor: #333;
+$overlayZ: 800;
\ No newline at end of file
diff --git a/css/_videolayout_default.scss b/css/_videolayout_default.scss
index 102253886..2e64daa42 100644
--- a/css/_videolayout_default.scss
+++ b/css/_videolayout_default.scss
@@ -13,17 +13,17 @@
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
- flex-direction: row;
+ flex-direction: row-reverse;
flex-wrap: nowrap;
- justify-content: flex-end;
+ justify-content: flex-start;
position:absolute;
text-align:right;
height:196px;
- padding: 18px;
+ padding: 10px 10px 10px 5px;
bottom: 0;
left: 0;
- right: 20px;
+ right: 0;
width:auto;
border:1px solid transparent;
z-index: 5;
@@ -43,10 +43,23 @@
#remoteVideos .videocontainer {
display: none;
+ position: relative;
background-color: black;
background-size: contain;
border-radius:1px;
- border: 1px solid #212425;
+ margin: 0 $thumbnailVideoMargin;
+ border: 1px solid $defaultDarkColor;
+}
+
+.videocontainer__toolbar {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ z-index: 1;
+ width: 100%;
+ height: 25px;
+ max-height: 100%;
+ background-color: rgba(0, 0, 0, 0.5);
}
#remoteVideos .videocontainer.videoContainerFocused {
@@ -58,18 +71,13 @@
-webkit-animation-iteration-count: 1;
}
-#remoteVideos .videocontainer:hover {
- border: 1px solid #c1c1c1;
-}
-
#remoteVideos .videocontainer.videoContainerFocused {
- box-shadow: inset 0 0 28px #006d91;
- border: 1px solid #006d91;
+ border: 1px solid $videoThumbnailSelected;
}
+#remoteVideos .videocontainer:hover,
#remoteVideos .videocontainer.videoContainerFocused:hover {
- box-shadow: inset 0 0 5px #c1c1c1, 0 0 10px #c1c1c1, inset 0 0 60px #006d91;
- border: 1px solid #c1c1c1;
+ border: 1px solid $videoThumbnailHovered;
}
#localVideoWrapper {
@@ -145,11 +153,11 @@
#remoteVideos .videocontainer>div.remotevideomenu {
position: absolute;
color: #FFFFFF;
- top: 0;
- left: 0;
+ bottom: 0;
+ right: 0;
padding: 5px 0px;
width: 25px;
- font-size: 11pt;
+ font-size: 9pt;
text-shadow: 0px 1px 0px rgba(255,255,255,.3), 0px -1px 0px rgba(0,0,0,.7);
border: 0px;
z-index: 2;
@@ -166,22 +174,28 @@
.videocontainer>span.displayname,
.videocontainer>input.displayname {
- display: none;
+ display: inline-block;
position: absolute;
- color: #FFFFFF;
- background: rgba(0,0,0,.7);
+ bottom: 4px;
+ left: 25%;
+ color: $participantNameColor;
text-align: center;
text-overflow: ellipsis;
- width: 70%;
- height: 20%;
- left: 15%;
- top: 40%;
- padding: 5px;
- font-size: 11pt;
+ width: 50%;
+ font-size: 12px;
+ font-weight: 100;
+ letter-spacing: 1px;
overflow: hidden;
white-space: nowrap;
z-index: 2;
- border-radius:3px;
+}
+
+.videocontainer>input.displayname {
+ outline: none;
+ border: none;
+ background: none;
+ box-shadow: none;
+ padding: 0;
}
.videocontainer>span.status {
@@ -291,7 +305,8 @@
display: inline-block;
position: absolute;
color: #FFFFFF;
- top: 0;
+ bottom: 0;
+ left: 0;
padding: 8px 5px;
width: 25px;
font-size: 8pt;
@@ -305,8 +320,7 @@
display: inline-block;
position: absolute;
color: #FFFFFF;
- top: 0;
- right: 0;
+ bottom: 0;
padding: 8px 5px;
width: 25px;
font-size: 8pt;
@@ -316,24 +330,30 @@
}
.videocontainer>span.indicator {
- bottom: 0px;
+ position: absolute;
+ top: 0px;
left: 0px;
- width: 25px;
- height: 25px;
+ @include circle($thumbnailIndicatorSize);
+ box-sizing: border-box;
+ line-height: $thumbnailIndicatorSize - 2*$thumbnailIndicatorBorder;
z-index: 3;
text-align: center;
- border-radius: 50%;
- background: #21B9FC;
- margin: 5px;
+ background: $dominantSpeakerBg;
+ margin: 7px;
display: inline-block;
- position: absolute;
- color: #FFFFFF;
- font-size: 11pt;
- border: 0px;
+ color: $thumbnailPictogramColor;
+ font-size: 8pt;
+ border: $thumbnailIndicatorBorder solid $thumbnailPictogramColor;
+}
+
+.videocontainer>#raisehandindicator {
+ background: $raiseHandBg;
}
#indicatoricon {
- padding-top: 5px;
+ width: $thumbnailIndicatorSize - 2*$thumbnailIndicatorBorder;
+ height: $thumbnailIndicatorSize - 2*$thumbnailIndicatorBorder;
+ line-height: $thumbnailIndicatorSize - 2*$thumbnailIndicatorBorder;
}
#reloadPresentation {
@@ -395,10 +415,8 @@
}
.userAvatar {
- height: 100%;
- position: absolute;
- left: 0;
- border-radius: 2px;
+ @include circle(60px);
+ @include absoluteAligning(60px, 60px);
}
.sharedVideoAvatar {
diff --git a/index.html b/index.html
index 725aaa65b..8a31ba044 100644
--- a/index.html
+++ b/index.html
@@ -238,12 +238,13 @@
-
+
+
diff --git a/interface_config.js b/interface_config.js
index 9780d27f2..b96556fc6 100644
--- a/interface_config.js
+++ b/interface_config.js
@@ -34,5 +34,9 @@ var interfaceConfig = {
filmStripOnly: false,
RANDOM_AVATAR_URL_PREFIX: false,
RANDOM_AVATAR_URL_SUFFIX: false,
- FILM_STRIP_MAX_HEIGHT: 120
-};
\ No newline at end of file
+ FILM_STRIP_MAX_HEIGHT: 120,
+ LOCAL_THUMBNAIL_RATIO_WIDTH: 16,
+ LOCAL_THUMBNAIL_RATIO_HEIGHT: 9,
+ REMOTE_THUMBNAIL_RATIO_WIDTH: 1,
+ REMOTE_THUMBNAIL_RATIO_HEIGHT: 1
+};
diff --git a/modules/UI/Feedback.js b/modules/UI/Feedback.js
index 708b762c3..2338721f4 100644
--- a/modules/UI/Feedback.js
+++ b/modules/UI/Feedback.js
@@ -1,5 +1,6 @@
/* global $, APP, config, interfaceConfig, JitsiMeetJS */
import UIEvents from "../../service/UI/UIEvents";
+import UIUtil from "./util/UIUtil";
/**
* Constructs the html for the overall feedback window.
diff --git a/modules/UI/audio_levels/AudioLevels.js b/modules/UI/audio_levels/AudioLevels.js
index 642ddc925..dc188c48c 100644
--- a/modules/UI/audio_levels/AudioLevels.js
+++ b/modules/UI/audio_levels/AudioLevels.js
@@ -10,7 +10,7 @@ let ASDrawContext = null;
let audioLevelCanvasCache = {};
let dominantSpeakerAudioElement = null;
-function initDominantSpeakerAudioLevels(dominantSpeakerAvatarSize) {
+function _initDominantSpeakerAudioLevels(dominantSpeakerAvatarSize) {
let ASRadius = dominantSpeakerAvatarSize / 2;
let ASCenter = (dominantSpeakerAvatarSize + ASRadius) / 2;
@@ -28,7 +28,9 @@ function initDominantSpeakerAudioLevels(dominantSpeakerAvatarSize) {
/**
* Resizes the given audio level canvas to match the given thumbnail size.
*/
-function resizeAudioLevelCanvas(audioLevelCanvas, thumbnailWidth, thumbnailHeight) {
+function _resizeAudioLevelCanvas( audioLevelCanvas,
+ thumbnailWidth,
+ thumbnailHeight) {
audioLevelCanvas.width = thumbnailWidth + interfaceConfig.CANVAS_EXTRA;
audioLevelCanvas.height = thumbnailHeight + interfaceConfig.CANVAS_EXTRA;
}
@@ -138,18 +140,18 @@ const AudioLevels = {
dominantSpeakerAudioElement.height = dominantSpeakerHeight;
let dominantSpeakerAvatar = $("#dominantSpeakerAvatar");
- initDominantSpeakerAudioLevels(dominantSpeakerAvatar.width());
+ _initDominantSpeakerAudioLevels(dominantSpeakerAvatar.width());
},
/**
* Updates the audio level canvas for the given id. If the canvas
* didn't exist we create it.
*/
- updateAudioLevelCanvas (id, thumbWidth, thumbHeight) {
- let videoSpanId = 'localVideoContainer';
- if (id) {
- videoSpanId = `participant_${id}`;
- }
+ createAudioLevelCanvas (id, thumbWidth, thumbHeight) {
+
+ let videoSpanId = (id === "local")
+ ? "localVideoContainer"
+ : `participant_${id}`;
let videoSpan = document.getElementById(videoSpanId);
@@ -172,13 +174,13 @@ const AudioLevels = {
= `-${interfaceConfig.CANVAS_EXTRA/2}px`;
audioLevelCanvas.style.left
= `-${interfaceConfig.CANVAS_EXTRA/2}px`;
- resizeAudioLevelCanvas(audioLevelCanvas, thumbWidth, thumbHeight);
+ _resizeAudioLevelCanvas(audioLevelCanvas, thumbWidth, thumbHeight);
videoSpan.appendChild(audioLevelCanvas);
} else {
audioLevelCanvas = audioLevelCanvas.get(0);
- resizeAudioLevelCanvas(audioLevelCanvas, thumbWidth, thumbHeight);
+ _resizeAudioLevelCanvas(audioLevelCanvas, thumbWidth, thumbHeight);
}
},
@@ -242,19 +244,29 @@ const AudioLevels = {
ASDrawContext.fill();
},
- updateCanvasSize (thumbWidth, thumbHeight) {
- let canvasWidth = thumbWidth + interfaceConfig.CANVAS_EXTRA;
- let canvasHeight = thumbHeight + interfaceConfig.CANVAS_EXTRA;
+ updateCanvasSize (localVideo, remoteVideo) {
+ let localCanvasWidth
+ = localVideo.thumbWidth + interfaceConfig.CANVAS_EXTRA;
+ let localCanvasHeight
+ = localVideo.thumbHeight + interfaceConfig.CANVAS_EXTRA;
+ let remoteCanvasWidth
+ = remoteVideo.thumbWidth + interfaceConfig.CANVAS_EXTRA;
+ let remoteCanvasHeight
+ = remoteVideo.thumbHeight + interfaceConfig.CANVAS_EXTRA;
- FilmStrip.getThumbs().children('canvas').each(function () {
- $(this).attr('width', canvasWidth);
- $(this).attr('height', canvasHeight);
+ let { remoteThumbs, localThumb } = FilmStrip.getThumbs();
+
+ remoteThumbs.children('canvas').each(function () {
+ $(this).attr('width', remoteCanvasWidth);
+ $(this).attr('height', remoteCanvasHeight);
});
- Object.keys(audioLevelCanvasCache).forEach(function (id) {
- audioLevelCanvasCache[id].width = canvasWidth;
- audioLevelCanvasCache[id].height = canvasHeight;
- });
+ if(localThumb) {
+ localThumb.children('canvas').each(function () {
+ $(this).attr('width', localCanvasWidth);
+ $(this).attr('height', localCanvasHeight);
+ });
+ }
}
};
diff --git a/modules/UI/toolbars/Toolbar.js b/modules/UI/toolbars/Toolbar.js
index 876b6f108..01a36dc39 100644
--- a/modules/UI/toolbars/Toolbar.js
+++ b/modules/UI/toolbars/Toolbar.js
@@ -7,7 +7,6 @@ import SideContainerToggler from "../side_pannels/SideContainerToggler";
let roomUrl = null;
let emitter = null;
-
/**
* Opens the invite link dialog.
*/
@@ -766,4 +765,4 @@ const Toolbar = {
}
};
-export default Toolbar;
+export default Toolbar;
\ No newline at end of file
diff --git a/modules/UI/videolayout/FilmStrip.js b/modules/UI/videolayout/FilmStrip.js
index db74044f0..125d7c7fa 100644
--- a/modules/UI/videolayout/FilmStrip.js
+++ b/modules/UI/videolayout/FilmStrip.js
@@ -3,8 +3,6 @@
import UIEvents from "../../../service/UI/UIEvents";
import UIUtil from "../util/UIUtil";
-const thumbAspectRatio = 1 / 1;
-
const FilmStrip = {
/**
*
@@ -66,13 +64,52 @@ const FilmStrip = {
- parseInt(this.filmStrip.css('paddingRight'), 10);
},
- /**
- * Calculates the thumbnail size.
- */
- calculateThumbnailSize () {
- let availableHeight = interfaceConfig.FILM_STRIP_MAX_HEIGHT;
+ calculateThumbnailSize() {
+ let availableSizes = this.calculateAvailableSize();
+ let width = availableSizes.availableWidth;
+ let height = availableSizes.availableHeight;
- let numvids = this.getThumbs(true).length;
+ return this.calculateThumbnailSizeFromAvailable(width, height);
+ },
+
+ /**
+ * Normalizes local and remote thumbnail ratios
+ */
+ normalizeThumbnailRatio () {
+ let remoteHeightRatio = interfaceConfig.REMOTE_THUMBNAIL_RATIO_HEIGHT;
+ let remoteWidthRatio = interfaceConfig.REMOTE_THUMBNAIL_RATIO_WIDTH;
+
+ let localHeightRatio = interfaceConfig.LOCAL_THUMBNAIL_RATIO_HEIGHT;
+ let localWidthRatio = interfaceConfig.LOCAL_THUMBNAIL_RATIO_WIDTH;
+
+ let commonHeightRatio = remoteHeightRatio * localHeightRatio;
+
+ let localRatioCoefficient = localWidthRatio / localHeightRatio;
+ let remoteRatioCoefficient = remoteWidthRatio / remoteHeightRatio;
+
+ remoteWidthRatio = commonHeightRatio * remoteRatioCoefficient;
+ remoteHeightRatio = commonHeightRatio;
+
+ localWidthRatio = commonHeightRatio * localRatioCoefficient;
+ localHeightRatio = commonHeightRatio;
+
+ let localRatio = {
+ widthRatio: localWidthRatio,
+ heightRatio: localHeightRatio
+ };
+
+ let remoteRatio = {
+ widthRatio: remoteWidthRatio,
+ heightRatio: remoteHeightRatio
+ };
+
+ return { localRatio, remoteRatio };
+ },
+
+ calculateAvailableSize() {
+ let availableHeight = interfaceConfig.FILM_STRIP_MAX_HEIGHT;
+ let thumbs = this.getThumbs(true);
+ let numvids = thumbs.remoteThumbs.length;
let localVideoContainer = $("#localVideoContainer");
@@ -92,11 +129,10 @@ const FilmStrip = {
let availableWidth = videoAreaAvailableWidth;
- // If the number of videos is 0 or undefined we don't need to calculate
- // further.
- if (numvids)
+ // If local thumb is not hidden
+ if(thumbs.localThumb) {
availableWidth = Math.floor(
- (videoAreaAvailableWidth - numvids * (
+ (videoAreaAvailableWidth - (
UIUtil.parseCssInt(
localVideoContainer.css('borderLeftWidth'), 10)
+ UIUtil.parseCssInt(
@@ -109,36 +145,90 @@ const FilmStrip = {
localVideoContainer.css('marginLeft'), 10)
+ UIUtil.parseCssInt(
localVideoContainer.css('marginRight'), 10)))
- / numvids);
+ );
+ }
+
+ // If the number of videos is 0 or undefined we don't need to calculate
+ // further.
+ if (numvids) {
+ let remoteVideoContainer = thumbs.remoteThumbs.eq(0);
+ availableWidth = Math.floor(
+ (videoAreaAvailableWidth - numvids * (
+ UIUtil.parseCssInt(
+ remoteVideoContainer.css('borderLeftWidth'), 10)
+ + UIUtil.parseCssInt(
+ remoteVideoContainer.css('borderRightWidth'), 10)
+ + UIUtil.parseCssInt(
+ remoteVideoContainer.css('paddingLeft'), 10)
+ + UIUtil.parseCssInt(
+ remoteVideoContainer.css('paddingRight'), 10)
+ + UIUtil.parseCssInt(
+ remoteVideoContainer.css('marginLeft'), 10)
+ + UIUtil.parseCssInt(
+ remoteVideoContainer.css('marginRight'), 10)))
+ );
+ }
let maxHeight
// If the MAX_HEIGHT property hasn't been specified
// we have the static value.
- = Math.min( interfaceConfig.FILM_STRIP_MAX_HEIGHT || 120,
- availableHeight);
+ = Math.min(interfaceConfig.FILM_STRIP_MAX_HEIGHT || 120,
+ availableHeight);
availableHeight
- = Math.min( maxHeight, window.innerHeight - 18);
+ = Math.min(maxHeight, window.innerHeight - 18);
- if (availableHeight < availableWidth) {
- availableWidth = availableHeight;
+ return { availableWidth, availableHeight };
+ },
+
+ calculateThumbnailSizeFromAvailable(availableWidth, availableHeight) {
+ let { localRatio, remoteRatio } = this.normalizeThumbnailRatio();
+ let { remoteThumbs } = this.getThumbs(true);
+ let remoteProportion = remoteRatio.widthRatio * remoteThumbs.length;
+ let widthProportion = remoteProportion + localRatio.widthRatio;
+
+ let heightUnit = availableHeight / localRatio.heightRatio;
+ let widthUnit = availableWidth / widthProportion;
+
+ if (heightUnit < widthUnit) {
+ widthUnit = heightUnit;
}
else
- availableHeight = availableWidth;
+ heightUnit = widthUnit;
+
+ let localVideo = {
+ thumbWidth: widthUnit * localRatio.widthRatio,
+ thumbHeight: heightUnit * localRatio.heightRatio
+ };
+ let remoteVideo = {
+ thumbWidth: widthUnit * remoteRatio.widthRatio,
+ thumbHeight: widthUnit * remoteRatio.heightRatio
+ };
return {
- thumbWidth: availableWidth,
- thumbHeight: availableHeight
+ localVideo,
+ remoteVideo
};
},
- resizeThumbnails (thumbWidth, thumbHeight,
+ resizeThumbnails (local, remote,
animate = false, forceUpdate = false) {
return new Promise(resolve => {
- this.getThumbs(!forceUpdate).animate({
- height: thumbHeight,
- width: thumbWidth
+ let thumbs = this.getThumbs(!forceUpdate);
+
+ thumbs.localThumb.animate({
+ height: local.thumbHeight,
+ width: local.thumbWidth
+ }, {
+ queue: false,
+ duration: animate ? 500 : 0,
+ complete: resolve
+ });
+
+ thumbs.remoteThumbs.animate({
+ height: remote.thumbHeight,
+ width: remote.thumbWidth
}, {
queue: false,
duration: animate ? 500 : 0,
@@ -147,7 +237,7 @@ const FilmStrip = {
this.filmStrip.animate({
// adds 2 px because of small video 1px border
- height: thumbHeight + 2
+ height: remote.thumbHeight + 2
}, {
queue: false,
duration: animate ? 500 : 0
@@ -165,13 +255,19 @@ const FilmStrip = {
selector += ':visible';
}
+ let localThumb = $("#localVideoContainer");
+ let remoteThumbs = this.filmStrip.children(selector)
+ .not("#localVideoContainer");
+
// Exclude the local video container if it has been hidden.
- if ($("#localVideoContainer").hasClass("hidden"))
- return this.filmStrip.children(selector)
- .not("#localVideoContainer");
- else
- return this.filmStrip.children(selector);
- }
+ if (localThumb.hasClass("hidden")) {
+ return { remoteThumbs };
+ } else {
+ return { remoteThumbs, localThumb };
+ }
+
+ },
+
};
export default FilmStrip;
diff --git a/modules/UI/videolayout/LocalVideo.js b/modules/UI/videolayout/LocalVideo.js
index b245ee8e6..a368fcc8c 100644
--- a/modules/UI/videolayout/LocalVideo.js
+++ b/modules/UI/videolayout/LocalVideo.js
@@ -11,7 +11,6 @@ function LocalVideo(VideoLayout, emitter) {
this.videoSpanId = "localVideoContainer";
this.container = $("#localVideoContainer").get(0);
this.localVideoId = null;
- this.bindHoverHandler();
if(config.enableLocalVideoFlip)
this._buildContextMenu();
this.isLocal = true;
@@ -44,7 +43,7 @@ function createEditDisplayNameButton() {
editButton.className = 'displayname';
UIUtil.setTooltip(editButton,
"videothumbnail.editnickname",
- "top");
+ "left");
editButton.innerHTML = '';
return editButton;
@@ -72,7 +71,7 @@ LocalVideo.prototype.setDisplayName = function(displayName, key) {
if (displayName && displayName.length > 0) {
meHTML = APP.translation.generateTranslationHTML("me");
$('#localDisplayName').html(
- UIUtil.escapeHtml(displayName) + ' (' + meHTML + ')'
+ `${UIUtil.escapeHtml(displayName)} (${meHTML})`
);
} else {
$('#localDisplayName').html(defaultLocalDisplayName);
@@ -80,11 +79,9 @@ LocalVideo.prototype.setDisplayName = function(displayName, key) {
}
this.updateView();
} else {
- var editButton = createEditDisplayNameButton();
-
nameSpan = document.createElement('span');
nameSpan.className = 'displayname';
- $('#' + this.videoSpanId)[0].appendChild(nameSpan);
+ document.getElementById(this.videoSpanId).appendChild(nameSpan);
if (displayName && displayName.length > 0) {
@@ -97,7 +94,6 @@ LocalVideo.prototype.setDisplayName = function(displayName, key) {
nameSpan.id = 'localDisplayName';
- this.container.appendChild(editButton);
//translates popover of edit button
APP.translation.translateElement($("a.displayname"));
@@ -124,21 +120,23 @@ LocalVideo.prototype.setDisplayName = function(displayName, key) {
var self = this;
$('#localVideoContainer .displayname')
.bind("click", function (e) {
+ let $editDisplayName = $('#editDisplayName');
+ let $localDisplayName = $('#localDisplayName');
- var editDisplayName = $('#editDisplayName');
e.preventDefault();
e.stopPropagation();
- $('#localDisplayName').hide();
- editDisplayName.show();
- editDisplayName.focus();
- editDisplayName.select();
+ $localDisplayName.hide();
+ $editDisplayName.show();
+ $editDisplayName.focus();
+ $editDisplayName.select();
- editDisplayName.one("focusout", function (e) {
+ $editDisplayName.one("focusout", function (e) {
self.emitter.emit(UIEvents.NICKNAME_CHANGED, this.value);
- $('#editDisplayName').hide();
+ $editDisplayName.hide();
+ $localDisplayName.show();
});
- editDisplayName.on('keydown', function (e) {
+ $editDisplayName.on('keydown', function (e) {
if (e.keyCode === 13) {
e.preventDefault();
$('#editDisplayName').hide();
diff --git a/modules/UI/videolayout/RemoteVideo.js b/modules/UI/videolayout/RemoteVideo.js
index badd626f7..dc6d68118 100644
--- a/modules/UI/videolayout/RemoteVideo.js
+++ b/modules/UI/videolayout/RemoteVideo.js
@@ -17,7 +17,6 @@ function RemoteVideo(id, VideoLayout, emitter) {
this.addRemoteVideoContainer();
this.connectionIndicator = new ConnectionIndicator(this, id);
this.setDisplayName();
- this.bindHoverHandler();
this.flipX = false;
this.isLocal = false;
this.isMuted = false;
@@ -34,8 +33,10 @@ RemoteVideo.prototype.addRemoteVideoContainer = function() {
if (APP.conference.isModerator) {
this.addRemoteVideoMenu();
}
- let {thumbWidth, thumbHeight} = this.VideoLayout.resizeThumbnails();
- AudioLevels.updateAudioLevelCanvas(this.id, thumbWidth, thumbHeight);
+
+ let { remoteVideo } = this.VideoLayout.resizeThumbnails();
+ let { thumbHeight, thumbWidth } = remoteVideo;
+ AudioLevels.createAudioLevelCanvas(this.id, thumbWidth, thumbHeight);
return this.container;
};
@@ -427,12 +428,16 @@ RemoteVideo.prototype.removeRemoteVideoMenu = function() {
};
RemoteVideo.createContainer = function (spanId) {
- var container = document.createElement('span');
+ let container = document.createElement('span');
container.id = spanId;
container.className = 'videocontainer';
+
+ let toolbar = document.createElement('div');
+ toolbar.className = "videocontainer__toolbar";
+ container.appendChild(toolbar);
+
var remotes = document.getElementById('remoteVideos');
return remotes.appendChild(container);
};
-
export default RemoteVideo;
diff --git a/modules/UI/videolayout/SmallVideo.js b/modules/UI/videolayout/SmallVideo.js
index cf42a16dc..b905b6eb8 100644
--- a/modules/UI/videolayout/SmallVideo.js
+++ b/modules/UI/videolayout/SmallVideo.js
@@ -171,26 +171,6 @@ SmallVideo.getStreamElementID = function (stream) {
return (isVideo ? 'remoteVideo_' : 'remoteAudio_') + stream.getId();
};
-/**
- * Configures hoverIn/hoverOut handlers.
- */
-SmallVideo.prototype.bindHoverHandler = function () {
- // Add hover handler
- var self = this;
- $(this.container).hover(
- function () {
- self.showDisplayName(true);
- },
- function () {
- // If the video has been "pinned" by the user we want to
- // keep the display name on place.
- if (!self.VideoLayout.isLargeVideoVisible() ||
- !self.VideoLayout.isCurrentlyOnLarge(self.id))
- self.showDisplayName(false);
- }
- );
-};
-
/**
* Updates the data for the indicator
* @param id the id of the indicator
@@ -219,6 +199,7 @@ SmallVideo.prototype.showAudioIndicator = function(isMuted) {
if (audioMutedSpan.length > 0) {
audioMutedSpan.popover('hide');
audioMutedSpan.remove();
+ this.updateIconPositions();
}
}
else {
@@ -230,12 +211,14 @@ SmallVideo.prototype.showAudioIndicator = function(isMuted) {
"top");
this.container.appendChild(audioMutedSpan);
- APP.translation.translateElement($('#' + this.videoSpanId + " > span"));
+ APP.translation
+ .translateElement($('#' + this.videoSpanId + " > span"));
var mutedIndicator = document.createElement('i');
mutedIndicator.className = 'icon-mic-disabled';
audioMutedSpan.appendChild(mutedIndicator);
}
+
this.updateIconPositions();
}
this.isMuted = isMuted;
@@ -254,6 +237,7 @@ SmallVideo.prototype.setMutedView = function(isMuted) {
if (isMuted === false) {
if (videoMutedSpan.length > 0) {
videoMutedSpan.remove();
+ this.updateIconPositions();
}
}
else {
@@ -270,7 +254,8 @@ SmallVideo.prototype.setMutedView = function(isMuted) {
"top");
videoMutedSpan.appendChild(mutedIndicator);
//translate texts for muted indicator
- APP.translation.translateElement($('#' + this.videoSpanId + " > span > i"));
+ APP.translation
+ .translateElement($('#' + this.videoSpanId + " > span > i"));
}
this.updateIconPositions();
@@ -278,13 +263,18 @@ SmallVideo.prototype.setMutedView = function(isMuted) {
};
SmallVideo.prototype.updateIconPositions = function () {
- var audioMutedSpan = $('#' + this.videoSpanId + '>span.audioMuted');
- var connectionIndicator = $('#' + this.videoSpanId + '>div.connectionindicator');
- var videoMutedSpan = $('#' + this.videoSpanId + '>span.videoMuted');
+ let audioMutedSpan = $('#' + this.videoSpanId + '>span.audioMuted');
+ let videoMutedSpan = $('#' + this.videoSpanId + '>span.videoMuted');
+ audioMutedSpan.css({left: "0px"});
+ videoMutedSpan.css({left: (audioMutedSpan.length > 0? 25 : 0) + "px"});
+
+ var connectionIndicator
+ = $('#' + this.videoSpanId + '>div.connectionindicator');
if(connectionIndicator.length > 0 &&
connectionIndicator[0].style.display != "none") {
audioMutedSpan.css({right: "23px"});
- videoMutedSpan.css({right: ((audioMutedSpan.length > 0? 23 : 0) + 30) + "px"});
+ videoMutedSpan.css({right:
+ ((audioMutedSpan.length > 0? 23 : 0) + 30) + "px"});
} else {
audioMutedSpan.css({right: "0px"});
videoMutedSpan.css({right: (audioMutedSpan.length > 0? 30 : 0) + "px"});
@@ -317,7 +307,8 @@ SmallVideo.prototype.createModeratorIndicatorElement = function () {
"top");
//translates text in focus indicators
- APP.translation.translateElement($('#' + this.videoSpanId + ' .focusindicator'));
+ APP.translation
+ .translateElement($('#' + this.videoSpanId + ' .focusindicator'));
};
/**
@@ -406,8 +397,6 @@ SmallVideo.prototype.updateView = function () {
setVisibility(video, showVideo);
}
setVisibility(avatar, showAvatar);
-
- this.showDisplayName(!showVideo && !showAvatar);
};
SmallVideo.prototype.avatarChanged = function (avatarUrl) {
@@ -465,9 +454,8 @@ SmallVideo.prototype.showRaisedHandIndicator = function (show) {
var indicatorSpanId = "raisehandindicator";
var indicatorSpan = this.getIndicatorSpan(indicatorSpanId);
- indicatorSpan.style.background = "#D6D61E";
indicatorSpan.innerHTML
- = "";
+ = "";
// adds a tooltip
UIUtil.setTooltip(indicatorSpan, "raisedHand", "left");
diff --git a/modules/UI/videolayout/VideoLayout.js b/modules/UI/videolayout/VideoLayout.js
index d574265ab..118c2d87f 100644
--- a/modules/UI/videolayout/VideoLayout.js
+++ b/modules/UI/videolayout/VideoLayout.js
@@ -105,8 +105,9 @@ var VideoLayout = {
localVideoThumbnail.setVideoType(VIDEO_CONTAINER_TYPE);
// if we do not resize the thumbs here, if there is no video device
// the local video thumb maybe one pixel
- let {thumbWidth, thumbHeight} = this.resizeThumbnails(false, true);
- AudioLevels.updateAudioLevelCanvas(null, thumbWidth, thumbHeight);
+ let { localVideo } = this.resizeThumbnails(false, true);
+ AudioLevels.createAudioLevelCanvas(
+ "local", localVideo.thumbWidth, localVideo.thumbHeight);
emitter.addListener(UIEvents.CONTACT_CLICKED, onContactClicked);
this.lastNCount = config.channelLastN;
@@ -254,7 +255,8 @@ var VideoLayout = {
electLastVisibleVideo () {
// pick the last visible video in the row
// if nobody else is left, this picks the local video
- let thumbs = FilmStrip.getThumbs(true).filter('[id!="mixedstream"]');
+ let remoteThumbs = FilmStrip.getThumbs(true).remoteThumbs;
+ let thumbs = remoteThumbs.filter('[id!="mixedstream"]');
let lastVisible = thumbs.filter(':visible:last');
if (lastVisible.length) {
@@ -268,7 +270,7 @@ var VideoLayout = {
}
console.info("Last visible video no longer exists");
- thumbs = FilmStrip.getThumbs();
+ thumbs = FilmStrip.getThumbs().remoteThumbs;
if (thumbs.length) {
let id = getPeerContainerResourceId(thumbs[0]);
if (remoteVideos[id]) {
@@ -401,7 +403,7 @@ var VideoLayout = {
// In case this is not currently in the last n we don't show it.
if (localLastNCount && localLastNCount > 0 &&
- FilmStrip.getThumbs().length >= localLastNCount + 2) {
+ FilmStrip.getThumbs().remoteThumbs.length >= localLastNCount + 2) {
remoteVideo.showPeerContainer('hide');
} else {
VideoLayout.resizeThumbnails(false, true);
@@ -486,19 +488,19 @@ var VideoLayout = {
forceUpdate = false,
onComplete = null) {
- let {thumbWidth, thumbHeight}
+ let { localVideo, remoteVideo }
= FilmStrip.calculateThumbnailSize();
- $('.userAvatar').css('left', (thumbWidth - thumbHeight) / 2);
+ let {thumbWidth, thumbHeight} = remoteVideo;
- FilmStrip.resizeThumbnails(thumbWidth, thumbHeight,
+ FilmStrip.resizeThumbnails(localVideo, remoteVideo,
animate, forceUpdate)
.then(function () {
- AudioLevels.updateCanvasSize(thumbWidth, thumbHeight);
+ AudioLevels.updateCanvasSize(localVideo, remoteVideo);
if (onComplete && typeof onComplete === "function")
onComplete();
- });
- return {thumbWidth, thumbHeight};
+ });
+ return { localVideo, remoteVideo };
},
/**
@@ -656,7 +658,7 @@ var VideoLayout = {
var updateLargeVideo = false;
// Handle LastN/local LastN changes.
- FilmStrip.getThumbs().each(( index, element ) => {
+ FilmStrip.getThumbs().remoteThumbs.each(( index, element ) => {
var resourceJid = getPeerContainerResourceId(element);
var smallVideo = remoteVideos[resourceJid];
diff --git a/package.json b/package.json
index c744fc911..1a6cfa30a 100644
--- a/package.json
+++ b/package.json
@@ -21,18 +21,18 @@
"bootstrap": "3.1.1",
"events": "*",
"i18next-client": "1.7.7",
- "jquery": "~2.1.1",
"jQuery-Impromptu": "git+https://github.com/trentrichardson/jQuery-Impromptu.git#v6.0.0",
- "lib-jitsi-meet": "git+https://github.com/jitsi/lib-jitsi-meet.git",
+ "jquery": "~2.1.1",
"jquery-contextmenu": "*",
"jquery-ui": "1.10.5",
"jssha": "1.5.0",
+ "jws": "*",
+ "lib-jitsi-meet": "git+https://github.com/jitsi/lib-jitsi-meet.git",
+ "postis": "^2.2.0",
"retry": "0.6.1",
"strophe": "^1.2.2",
"strophejs-plugins": "^0.0.6",
- "toastr": "^2.0.3",
- "postis": "^2.2.0",
- "jws": "*"
+ "toastr": "^2.0.3"
},
"devDependencies": {
"babel-polyfill": "*",