diff --git a/css/_videolayout_default.scss b/css/_videolayout_default.scss
index e2dfca1d8..6bea52c76 100644
--- a/css/_videolayout_default.scss
+++ b/css/_videolayout_default.scss
@@ -85,7 +85,7 @@
position: relative;
width: 100%;
height: 100%;
- display: none;
+ visibility: hidden;
background: rgba(0,0,0,.6);
z-index: 2;
}
diff --git a/modules/UI/util/JitsiPopover.js b/modules/UI/util/JitsiPopover.js
index f49c4ea50..26608ca8d 100644
--- a/modules/UI/util/JitsiPopover.js
+++ b/modules/UI/util/JitsiPopover.js
@@ -98,14 +98,27 @@ var JitsiPopover = (function () {
var self = this;
$(".jitsipopover").on("mouseenter", function () {
self.popoverIsHovered = true;
+ if(typeof self.onHoverPopover === "function") {
+ self.onHoverPopover(self.popoverIsHovered);
+ }
}).on("mouseleave", function () {
self.popoverIsHovered = false;
self.hide();
+ if(typeof self.onHoverPopover === "function") {
+ self.onHoverPopover(self.popoverIsHovered);
+ }
});
this.refreshPosition();
};
+ /**
+ * Adds a hover listener to the popover.
+ */
+ JitsiPopover.prototype.addOnHoverPopover = function (listener) {
+ this.onHoverPopover = listener;
+ };
+
/**
* Refreshes the position of the popover.
*/
diff --git a/modules/UI/videolayout/ConnectionIndicator.js b/modules/UI/videolayout/ConnectionIndicator.js
index 7ecd83ec9..d73be9c7f 100644
--- a/modules/UI/videolayout/ConnectionIndicator.js
+++ b/modules/UI/videolayout/ConnectionIndicator.js
@@ -439,4 +439,11 @@ ConnectionIndicator.prototype.updateResolutionIndicator = function () {
}
};
+/**
+ * Adds a hover listener to the popover.
+ */
+ConnectionIndicator.prototype.addPopoverHoverListener = function (listener) {
+ this.popover.addOnHoverPopover(listener);
+};
+
export default ConnectionIndicator;
diff --git a/modules/UI/videolayout/LocalVideo.js b/modules/UI/videolayout/LocalVideo.js
index 021f026b6..ff1c9ca22 100644
--- a/modules/UI/videolayout/LocalVideo.js
+++ b/modules/UI/videolayout/LocalVideo.js
@@ -11,6 +11,7 @@ function LocalVideo(VideoLayout, emitter) {
this.videoSpanId = "localVideoContainer";
this.container = $("#localVideoContainer").get(0);
this.localVideoId = null;
+ this.createConnectionIndicator();
this.bindHoverHandler();
if(config.enableLocalVideoFlip)
this._buildContextMenu();
@@ -28,7 +29,6 @@ function LocalVideo(VideoLayout, emitter) {
// Set default display name.
this.setDisplayName();
- this.createConnectionIndicator();
this.addAudioLevelIndicator();
}
diff --git a/modules/UI/videolayout/SmallVideo.js b/modules/UI/videolayout/SmallVideo.js
index c919c5f64..e1f1357e3 100644
--- a/modules/UI/videolayout/SmallVideo.js
+++ b/modules/UI/videolayout/SmallVideo.js
@@ -21,11 +21,27 @@ const DISPLAY_VIDEO = 0;
const DISPLAY_AVATAR = 1;
/**
* 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}
* @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) {
this.isAudioMuted = false;
@@ -34,6 +50,7 @@ function SmallVideo(VideoLayout) {
this.videoStream = null;
this.audioStream = null;
this.VideoLayout = VideoLayout;
+ this.videoIsHovered = false;
}
/**
@@ -144,30 +161,26 @@ SmallVideo.getStreamElementID = function (stream) {
};
/**
- * Configures hoverIn/hoverOut handlers.
+ * Configures hoverIn/hoverOut handlers. Depends on connection indicator.
*/
SmallVideo.prototype.bindHoverHandler = function () {
// Add hover handler
$(this.container).hover(
() => {
- if (!this.VideoLayout.isCurrentlyOnLarge(this.id)) {
- $('#' + this.videoSpanId + ' .videocontainer__overlay')
- .removeClass("hide")
- .addClass("show-inline");
- UIUtil.setVisibility(this.$displayName(), true);
- }
+ this.videoIsHovered = true;
+ this.updateView();
},
() => {
- $('#' + this.videoSpanId + ' .videocontainer__overlay')
- .removeClass("show-inline")
- .addClass("hide");
- // If the video has been "pinned" by the user we want to
- // keep the display name on place.
- if (!this.VideoLayout.isLargeVideoVisible() ||
- !this.VideoLayout.isCurrentlyOnLarge(this.id))
- UIUtil.setVisibility(this.$displayName(), false);
+ this.videoIsHovered = false;
+ this.updateView();
}
);
+ if (this.connectionIndicator) {
+ this.connectionIndicator.addPopoverHoverListener(
+ () => {
+ this.updateView();
+ });
+ }
};
/**
@@ -433,19 +446,34 @@ SmallVideo.prototype.isVideoPlayable = function() {
* Determines what should be display on the thumbnail.
*
* @return {number} one of DISPLAY_VIDEO,DISPLAY_AVATAR
- * or DISPLAY_BLACKNESS.
+ * or DISPLAY_BLACKNESS_WITH_NAME.
*/
SmallVideo.prototype.selectDisplayMode = function() {
// Display name is always and only displayed when user is on the stage
if (this.isCurrentlyOnLargeVideo()) {
- return DISPLAY_BLACKNESS;
+ return DISPLAY_BLACKNESS_WITH_NAME;
} 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 {
- 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.popover.popoverIsHovered;
+};
+
/**
* Hides or shows the user's avatar.
* This update assumes that large video had been updated and we will
@@ -469,13 +497,23 @@ SmallVideo.prototype.updateView = function () {
let displayMode = this.selectDisplayMode();
// Show/hide video.
UIUtil.setVisibility( this.selectVideoElement(),
- displayMode === DISPLAY_VIDEO);
+ (displayMode === DISPLAY_VIDEO
+ || displayMode === DISPLAY_VIDEO_WITH_NAME));
// Show/hide the avatar.
UIUtil.setVisibility( this.$avatar(),
- displayMode === DISPLAY_AVATAR);
+ (displayMode === DISPLAY_AVATAR
+ || displayMode === DISPLAY_AVATAR_WITH_NAME));
// Show/hide the display name.
UIUtil.setVisibility( this.$displayName(),
- displayMode === DISPLAY_BLACKNESS);
+ (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__overlay'),
+ (displayMode === DISPLAY_AVATAR_WITH_NAME
+ || displayMode === DISPLAY_VIDEO_WITH_NAME));
};
SmallVideo.prototype.avatarChanged = function (avatarUrl) {