diff --git a/config.js b/config.js
index 4dda7b85f..9d6fb6a1e 100644
--- a/config.js
+++ b/config.js
@@ -70,4 +70,5 @@ var config = {
'During that time service will not be available. ' +
'Apologise for inconvenience.',*/
disableThirdPartyRequests: false,
+ minHDResolution: 540
};
diff --git a/css/main.css b/css/main.css
index 5a937025f..d2b7d1c41 100644
--- a/css/main.css
+++ b/css/main.css
@@ -9,7 +9,7 @@ html, body{
color: #424242;
font-family:'Helvetica Neue', Helvetica, sans-serif;
font-weight: 400;
- background: #000000;
+ background: #4E4E4E;
overflow: hidden;
}
@@ -38,16 +38,6 @@ html, body{
position: relative;
}
-#toolbar a.button::after {
- content: '';
- display: inline-block;
- position: absolute;
- left: 40px;
- width: 1px;
- height: 20px;
- background: #373737;
-}
-
#toolbar a.button:last-child::after {
content: none;
}
@@ -57,7 +47,7 @@ html, body{
position: relative;
color: #FFFFFF;
top: 0;
- padding: 10px 0;
+ padding: 9px 0;
width: 38px;
cursor: pointer;
text-align: center;
@@ -109,7 +99,7 @@ html, body{
height: 13px;
line-height: 13px;
font-weight: bold;
- border-radius: 2px;
+ border-radius: 1px;
font-size: 11px;
text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black;
}
@@ -144,10 +134,8 @@ a.bottomToolbarButton:hover {
top: 0px;
cursor: pointer;
background: rgba(255, 255, 255, 0.1);
- border-radius: 6px;
- background-clip: padding-box;
- -webkit-border-radius: 6px;
- -webkit-background-clip: padding-box;
+ border-radius: 1px;
+ -webkit-border-radius: 1px;
}
.no-fa-video-camera, .fa-microphone-slash {
@@ -210,7 +198,7 @@ button {
height: 35px;
padding: 0 1em 0 2em;
position: relative;
- border-radius: 3px;
+ border-radius: 1px;
font-weight: bold;
color: #fff;
line-height: 35px;
@@ -272,10 +260,9 @@ div.feedbackButton:hover {
margin-right: 5px;
bottom: 40px;
width: 29px;
- border-radius: 6px;
+ border-radius: 1px;
color: #FFF;
- border: 1px solid rgba(256, 256, 256, 0.2);
- background: rgba(0,0,0,0.8);
+ background: rgba(0,0,0,0.5);
z-index: 6; /*+1 from #remoteVideos*/
}
@@ -349,7 +336,7 @@ div.feedbackButton:hover {
}
#toast-container.notification-bottom-right {
- bottom: 120px;
+ bottom: 140px;
right: 5px;
}
diff --git a/css/popup_menu.css b/css/popup_menu.css
index 300d95f4b..041e04229 100644
--- a/css/popup_menu.css
+++ b/css/popup_menu.css
@@ -13,7 +13,7 @@ ul.popupmenu {
width: 100px;
background-color: rgba(0,0,0,0.9);
border: 1px solid rgba(256, 256, 256, 0.2);
- border-radius:8px;
+ border-radius:3px;
}
ul.popupmenu:after {
@@ -31,7 +31,7 @@ ul.popupmenu li {
ul.popupmenu li:hover {
background-color: rgba(256, 256, 256, .2);
- border-radius:6px;
+ border-radius:3px;
}
/*Link Appearance*/
diff --git a/css/videolayout_default.css b/css/videolayout_default.css
index 73668cf56..e87860a8a 100644
--- a/css/videolayout_default.css
+++ b/css/videolayout_default.css
@@ -21,6 +21,7 @@
z-index: 5;
transition: bottom 2s;
overflow: visible !important;
+ font-size: 0pt; /*!!!Removes the gap between the local video container and the remote videos.*/
}
#remotevideos.hidden {
@@ -37,12 +38,12 @@
display: none;
background-color: black;
background-size: contain;
- border-radius:8px;
- border: 2px solid #212425;
- margin-right: 3px;
+ border-radius:1px;
+ border: 1px solid #212425;
+ /*margin-right: 1px;*/
}
-#remoteVideos .videocontainer:hover,
+/*#remoteVideos .videocontainer:hover,*/
#remoteVideos .videocontainer.videoContainerFocused {
cursor: hand;
/* transform:scale(1.08, 1.08);
@@ -56,25 +57,21 @@
}
#remoteVideos .videocontainer:hover {
- box-shadow: inset 0 0 10px #FFFFFF, 0 0 10px #FFFFFF;
- border: 2px solid #FFFFFF;
+ border: 1px solid #c1c1c1;
}
#remoteVideos .videocontainer.videoContainerFocused {
box-shadow: inset 0 0 28px #006d91;
- border: 2px solid #006d91;
+ border: 1px solid #006d91;
}
#remoteVideos .videocontainer.videoContainerFocused:hover {
- box-shadow: inset 0 0 5px #FFFFFF, 0 0 10px #FFFFFF, inset 0 0 60px #006d91;
- border: 2px solid #FFFFFF;
+ box-shadow: inset 0 0 5px #c1c1c1, 0 0 10px #c1c1c1, inset 0 0 60px #006d91;
+ border: 1px solid #c1c1c1;
}
#localVideoWrapper {
display:inline-block;
- -webkit-mask-box-image: url(../images/videomask.svg);
- border-radius:4px !important;
- border: 0px !important;
}
/* With TemasysWebRTC plugin element is used
@@ -82,7 +79,8 @@
#remoteVideos .videocontainer>video,
#remoteVideos .videocontainer>object {
cursor: hand;
- border-radius:4px;
+ border-radius:1px;
+ object-fit: cover;
}
.flipVideoX {
@@ -95,7 +93,8 @@
#localVideoWrapper>video,
#localVideoWrapper>object {
cursor: hand;
- border-radius:4px !important;
+ border-radius:1px !important;
+ object-fit: cover;
}
#largeVideo,
@@ -175,7 +174,7 @@
overflow: hidden;
white-space: nowrap;
z-index: 2;
- border-radius:20px;
+ border-radius:3px;
}
.videocontainer>span.status {
@@ -194,7 +193,7 @@
overflow: hidden;
white-space: nowrap;
z-index: 2;
- border-radius:20px;
+ border-radius:3px;
}
.connectionindicator
@@ -368,9 +367,8 @@
padding-right:2px;
height:38px;
width:auto;
- background-color: rgba(0,0,0,0.8);
- border: 1px solid rgba(256, 256, 256, 0.2);
- border-radius: 6px;
+ background-color: rgba(0,0,0,0.5);
+ border-radius: 1px;
pointer-events: auto;
}
@@ -393,14 +391,14 @@
display: inline-block;
position: absolute;
z-index: 0;
- border-radius:10px;
+ border-radius:1px;
pointer-events: none;
}
#dominantSpeaker {
visibility: hidden;
- width: 150px;
- height: 150px;
+ width: 300px;
+ height: 300px;
margin: auto;
overflow: hidden;
position: relative;
@@ -419,21 +417,22 @@
}
#dominantSpeakerAvatar {
- width: 100px;
- height: 100px;
- top: 25px;
+ width: 200px;
+ height: 200px;
+ top: 50px;
margin: auto;
position: relative;
- border-radius: 50px;
+ border-radius: 100px;
z-index: 3;
visibility: inherit;
+ background-color: #000000;
}
.userAvatar {
height: 100%;
position: absolute;
- left: 35px;
- border-radius: 200px;
+ left: 0;
+ border-radius: 2px;
}
.noMic {
@@ -485,4 +484,15 @@
0px 1px 1px rgba(0,0,0,0.3),
1px 0px 1px rgba(0,0,0,0.3),
0px 0px 1px rgba(0,0,0,0.3);
+}
+
+#videoResolutionLabel {
+ display: none;
+ position: absolute;
+ top: 5px;
+ right: 5px;
+ background: rgba(0,0,0,.5);
+ padding: 10px;
+ color: rgba(255,255,255,.5);
+ z-index: 10000;
}
\ No newline at end of file
diff --git a/css/welcome_page.css b/css/welcome_page.css
index 3b3c54796..84435dc3c 100644
--- a/css/welcome_page.css
+++ b/css/welcome_page.css
@@ -42,11 +42,11 @@
}
#enter_room_form {
- border-radius: 10px;
+ border-radius: 1px;
background-color: #FFFFFF;
border: none;
- -moz-border-radius: 10px;
- -webkit-border-radius: 10px;
+ -moz-border-radius: 1px;
+ -webkit-border-radius: 1px;
-webkit-appearance: none;
height: 55px;
box-shadow: none;
@@ -82,8 +82,8 @@
width: 73px;
height: 45px;
background-color: #16a8fe;
- moz-border-radius: 10px;
- -webkit-border-radius: 10px;
+ moz-border-radius: 1px;
+ -webkit-border-radius: 1px;
color: #ffffff;
font-weight: 600;
border: none;
diff --git a/index.html b/index.html
index 4154cbdc5..ce8268e2b 100644
--- a/index.html
+++ b/index.html
@@ -151,6 +151,7 @@
+ HD
diff --git a/interface_config.js b/interface_config.js
index 7101d6d05..23668d8cc 100644
--- a/interface_config.js
+++ b/interface_config.js
@@ -1,6 +1,6 @@
var interfaceConfig = {
CANVAS_EXTRA: 104,
- CANVAS_RADIUS: 7,
+ CANVAS_RADIUS: 0,
SHADOW_COLOR: '#ffffff',
INITIAL_TOOLBAR_TIMEOUT: 20000,
TOOLBAR_TIMEOUT: 4000,
@@ -14,7 +14,6 @@ var interfaceConfig = {
GENERATE_ROOMNAMES_ON_WELCOME_PAGE: true,
APP_NAME: "Jitsi Meet",
INVITATION_POWERED_BY: true,
- DOMINANT_SPEAKER_AVATAR_SIZE: 100,
TOOLBAR_BUTTONS: ['authentication', 'microphone', 'camera', 'desktop',
'recording', 'security', 'invite', 'chat', 'etherpad',
'fullscreen', 'sip', 'dialpad', 'settings', 'hangup', 'filmstrip',
@@ -30,5 +29,5 @@ var interfaceConfig = {
filmStripOnly: false,
RANDOM_AVATAR_URL_PREFIX: false,
RANDOM_AVATAR_URL_SUFFIX: false,
- FILM_STRIP_MAX_HEIGHT: 160
+ FILM_STRIP_MAX_HEIGHT: 120
};
diff --git a/modules/UI/audio_levels/AudioLevels.js b/modules/UI/audio_levels/AudioLevels.js
index 7e1bc68dd..68568710d 100644
--- a/modules/UI/audio_levels/AudioLevels.js
+++ b/modules/UI/audio_levels/AudioLevels.js
@@ -8,13 +8,16 @@ const LOCAL_LEVEL = 'local';
let ASDrawContext = null;
let audioLevelCanvasCache = {};
+let dominantSpeakerAudioElement = null;
-function initDominantSpeakerAudioLevels() {
- let ASRadius = interfaceConfig.DOMINANT_SPEAKER_AVATAR_SIZE / 2;
- let ASCenter = (interfaceConfig.DOMINANT_SPEAKER_AVATAR_SIZE + ASRadius) / 2;
+function initDominantSpeakerAudioLevels(dominantSpeakerAvatarSize) {
+ let ASRadius = dominantSpeakerAvatarSize / 2;
+ let ASCenter = (dominantSpeakerAvatarSize + ASRadius) / 2;
// Draw a circle.
+ ASDrawContext.beginPath();
ASDrawContext.arc(ASCenter, ASCenter, ASRadius, 0, 2 * Math.PI);
+ ASDrawContext.closePath();
// Add a shadow around the circle
ASDrawContext.shadowColor = interfaceConfig.SHADOW_COLOR;
@@ -90,14 +93,14 @@ function getShadowLevel (audioLevel) {
let shadowLevel = 0;
if (audioLevel <= 0.3) {
- shadowLevel
- = Math.round(interfaceConfig.CANVAS_EXTRA/2*(audioLevel/0.3));
+ shadowLevel = Math.round(
+ interfaceConfig.CANVAS_EXTRA/2*(audioLevel/0.3));
} else if (audioLevel <= 0.6) {
- shadowLevel
- = Math.round(interfaceConfig.CANVAS_EXTRA/2*((audioLevel - 0.3) / 0.3));
+ shadowLevel = Math.round(
+ interfaceConfig.CANVAS_EXTRA/2*((audioLevel - 0.3) / 0.3));
} else {
- shadowLevel
- = Math.round(interfaceConfig.CANVAS_EXTRA/2*((audioLevel - 0.6) / 0.4));
+ shadowLevel = Math.round(
+ interfaceConfig.CANVAS_EXTRA/2*((audioLevel - 0.6) / 0.4));
}
return shadowLevel;
@@ -124,8 +127,18 @@ function getVideoSpanId(id) {
const AudioLevels = {
init () {
- ASDrawContext = $('#dominantSpeakerAudioLevel')[0].getContext('2d');
- initDominantSpeakerAudioLevels();
+ dominantSpeakerAudioElement = $('#dominantSpeakerAudioLevel')[0];
+ ASDrawContext = dominantSpeakerAudioElement.getContext('2d');
+
+ let parentContainer = $("#dominantSpeaker");
+ let dominantSpeakerWidth = parentContainer.width();
+ let dominantSpeakerHeight = parentContainer.height();
+
+ dominantSpeakerAudioElement.width = dominantSpeakerWidth;
+ dominantSpeakerAudioElement.height = dominantSpeakerHeight;
+
+ let dominantSpeakerAvatar = $("#dominantSpeakerAvatar");
+ initDominantSpeakerAudioLevels(dominantSpeakerAvatar.width());
},
/**
@@ -155,8 +168,10 @@ const AudioLevels = {
audioLevelCanvas = document.createElement('canvas');
audioLevelCanvas.className = "audiolevel";
- audioLevelCanvas.style.bottom = `-${interfaceConfig.CANVAS_EXTRA/2}px`;
- audioLevelCanvas.style.left = `-${interfaceConfig.CANVAS_EXTRA/2}px`;
+ audioLevelCanvas.style.bottom
+ = `-${interfaceConfig.CANVAS_EXTRA/2}px`;
+ audioLevelCanvas.style.left
+ = `-${interfaceConfig.CANVAS_EXTRA/2}px`;
resizeAudioLevelCanvas(audioLevelCanvas, thumbWidth, thumbHeight);
videoSpan.appendChild(audioLevelCanvas);
@@ -213,7 +228,10 @@ const AudioLevels = {
return;
}
- ASDrawContext.clearRect(0, 0, 300, 300);
+ ASDrawContext.clearRect(0, 0,
+ dominantSpeakerAudioElement.width,
+ dominantSpeakerAudioElement.height);
+
if (!audioLevel) {
return;
}
diff --git a/modules/UI/avatar/Avatar.js b/modules/UI/avatar/Avatar.js
index 31b489d43..7fbadd444 100644
--- a/modules/UI/avatar/Avatar.js
+++ b/modules/UI/avatar/Avatar.js
@@ -44,18 +44,26 @@ export default {
if (!avatarId) {
console.warn(
`No avatar stored yet for ${userId} - using ID as avatar ID`);
+ console.log("USER ID ", userId);
avatarId = userId;
}
avatarId = MD5.hexdigest(avatarId.trim().toLowerCase());
- // Default to using gravatar.
- let urlPref = 'https://www.gravatar.com/avatar/';
- let urlSuf = "?d=wavatar&size=100";
- if (random && interfaceConfig.RANDOM_AVATAR_URL_PREFIX) {
+ let urlPref = null;
+ let urlSuf = null;
+ if (!random) {
+ urlPref = 'https://www.gravatar.com/avatar/';
+ urlSuf = "?d=wavatar&size=200";
+ }
+ else if (random && interfaceConfig.RANDOM_AVATAR_URL_PREFIX) {
urlPref = interfaceConfig.RANDOM_AVATAR_URL_PREFIX;
urlSuf = interfaceConfig.RANDOM_AVATAR_URL_SUFFIX;
}
+ else {
+ urlPref = 'https://robohash.org/';
+ urlSuf = ".png?size=200x200";
+ }
return urlPref + avatarId + urlSuf;
}
diff --git a/modules/UI/videolayout/ConnectionIndicator.js b/modules/UI/videolayout/ConnectionIndicator.js
index 642dc9754..40bb85363 100644
--- a/modules/UI/videolayout/ConnectionIndicator.js
+++ b/modules/UI/videolayout/ConnectionIndicator.js
@@ -1,6 +1,7 @@
-/* global APP, $ */
+/* global APP, $, config */
/* jshint -W101 */
import JitsiPopover from "../util/JitsiPopover";
+import VideoLayout from "./VideoLayout";
/**
* Constructs new connection indicator.
@@ -14,6 +15,7 @@ function ConnectionIndicator(videoContainer, id) {
this.bitrate = null;
this.showMoreValue = false;
this.resolution = null;
+ this.isResolutionHD = null;
this.transport = [];
this.popover = null;
this.id = id;
@@ -292,7 +294,6 @@ ConnectionIndicator.prototype.remove = function() {
*/
ConnectionIndicator.prototype.updateConnectionQuality =
function (percent, object) {
-
if (percent === null) {
this.connectionIndicatorContainer.style.display = "none";
this.popover.forceHide();
@@ -316,6 +317,10 @@ ConnectionIndicator.prototype.updateConnectionQuality =
ConnectionIndicator.connectionQualityValues[quality];
}
}
+ if (object.isResolutionHD) {
+ this.isResolutionHD = object.isResolutionHD;
+ }
+ this.updateResolutionIndicator();
this.updatePopoverData();
};
@@ -325,6 +330,7 @@ ConnectionIndicator.prototype.updateConnectionQuality =
*/
ConnectionIndicator.prototype.updateResolution = function (resolution) {
this.resolution = resolution;
+ this.updateResolutionIndicator();
this.updatePopoverData();
};
@@ -354,4 +360,29 @@ ConnectionIndicator.prototype.hideIndicator = function () {
this.popover.forceHide();
};
+/**
+ * Updates the resolution indicator.
+ */
+ConnectionIndicator.prototype.updateResolutionIndicator = function () {
+
+ if (this.id !== null
+ && VideoLayout.isCurrentlyOnLarge(this.id)) {
+
+ let showResolutionLabel = false;
+
+ if (this.isResolutionHD !== null)
+ showResolutionLabel = this.isResolutionHD;
+ else if (this.resolution !== null) {
+ let resolutions = this.resolution || {};
+ Object.keys(resolutions).map(function (ssrc) {
+ let {width, height} = resolutions[ssrc];
+ if (height >= config.minHDResolution)
+ showResolutionLabel = true;
+ });
+ }
+
+ VideoLayout.updateResolutionLabel(showResolutionLabel);
+ }
+};
+
export default ConnectionIndicator;
diff --git a/modules/UI/videolayout/FilmStrip.js b/modules/UI/videolayout/FilmStrip.js
index 2e0a8ce50..19539f752 100644
--- a/modules/UI/videolayout/FilmStrip.js
+++ b/modules/UI/videolayout/FilmStrip.js
@@ -2,7 +2,7 @@
import UIUtil from "../util/UIUtil";
-const thumbAspectRatio = 16.0 / 9.0;
+const thumbAspectRatio = 1 / 1;
const FilmStrip = {
init () {
@@ -44,11 +44,7 @@ const FilmStrip = {
* that we want to take into account when calculating the film strip width.
*/
calculateThumbnailSize (isSideBarVisible) {
- // Calculate the available height, which is the inner window height
- // minus 39px for the header minus 2px for the delimiter lines on the
- // top and bottom of the large video, minus the 36px space inside the
- // remoteVideos container used for highlighting shadow.
- let availableHeight = 100;
+ let availableHeight = interfaceConfig.FILM_STRIP_MAX_HEIGHT;
let numvids = this.getThumbs(true).length;
@@ -80,17 +76,17 @@ const FilmStrip = {
let maxHeight
// If the MAX_HEIGHT property hasn't been specified
// we have the static value.
- = Math.min( interfaceConfig.FILM_STRIP_MAX_HEIGHT || 160,
+ = Math.min( interfaceConfig.FILM_STRIP_MAX_HEIGHT || 120,
availableHeight);
availableHeight
- = Math.min( maxHeight,
- availableWidth / thumbAspectRatio,
- window.innerHeight - 18);
+ = Math.min( maxHeight, window.innerHeight - 18);
- if (availableHeight < availableWidth / thumbAspectRatio) {
- availableWidth = Math.floor(availableHeight * thumbAspectRatio);
+ if (availableHeight < availableWidth) {
+ availableWidth = availableHeight;
}
+ else
+ availableHeight = availableWidth;
return {
thumbWidth: availableWidth,
diff --git a/modules/UI/videolayout/LargeVideo.js b/modules/UI/videolayout/LargeVideo.js
index 494062af9..b01b275da 100644
--- a/modules/UI/videolayout/LargeVideo.js
+++ b/modules/UI/videolayout/LargeVideo.js
@@ -8,7 +8,6 @@ import FilmStrip from './FilmStrip';
import Avatar from "../avatar/Avatar";
import {createDeferred} from '../../util/helpers';
-const avatarSize = interfaceConfig.DOMINANT_SPEAKER_AVATAR_SIZE;
const FADE_DURATION_MS = 300;
/**
@@ -175,6 +174,8 @@ class VideoContainer extends LargeContainer {
this.$avatar = $('#dominantSpeaker');
this.$wrapper = $('#largeVideoWrapper');
+ this.avatarHeight = $("#dominantSpeakerAvatar").height();
+
// This does not work with Temasys plugin - has to be a property to be
// copied between new