Merge branch 'video-fadein-fix' of https://github.com/isymchych/jitsi-meet into jitsi-meet-new

This commit is contained in:
damencho 2016-01-25 15:35:40 -06:00
commit e707eb9a79
4 changed files with 127 additions and 86 deletions

View File

@ -1,7 +1,8 @@
/* global Strophe, APP, MD5, config, interfaceConfig */ /* global MD5, config, interfaceConfig */
var users = {};
var Avatar = { let users = {};
export default {
/** /**
* Sets the user's avatar in the settings menu(if local user), contact list * Sets the user's avatar in the settings menu(if local user), contact list
@ -16,48 +17,46 @@ var Avatar = {
} }
users[id] = email; users[id] = email;
} }
var avatarUrl = this.getAvatarUrl(id);
}, },
/** /**
* Returns the URL of the image for the avatar of a particular user, * Returns the URL of the image for the avatar of a particular user,
+ identified by its jid * identified by its id.
* @param jid * @param {string} userId user id
*/ */
getAvatarUrl: function (jid) { getAvatarUrl: function (userId) {
if (config.disableThirdPartyRequests) { if (config.disableThirdPartyRequests) {
return 'images/avatar2.png'; return 'images/avatar2.png';
} else { }
if (!jid) {
console.error("Get avatar - jid is undefined"); if (!userId) {
console.error("Get avatar - id is undefined");
return null; return null;
} }
var id = users[jid];
let avatarId = users[userId];
// If the ID looks like an email, we'll use gravatar. // If the ID looks like an email, we'll use gravatar.
// Otherwise, it's a random avatar, and we'll use the configured // Otherwise, it's a random avatar, and we'll use the configured
// URL. // URL.
var random = !id || id.indexOf('@') < 0; let random = !avatarId || avatarId.indexOf('@') < 0;
if (!id) { if (!avatarId) {
console.warn( console.warn(
"No avatar stored yet for " + jid + " - using JID as ID"); `No avatar stored yet for ${userId} - using ID as avatar ID`);
id = jid; avatarId = userId;
} }
id = MD5.hexdigest(id.trim().toLowerCase()); avatarId = MD5.hexdigest(avatarId.trim().toLowerCase());
// Default to using gravatar. // Default to using gravatar.
var urlPref = 'https://www.gravatar.com/avatar/'; let urlPref = 'https://www.gravatar.com/avatar/';
var urlSuf = "?d=wavatar&size=100"; let urlSuf = "?d=wavatar&size=100";
if (random && interfaceConfig.RANDOM_AVATAR_URL_PREFIX) { if (random && interfaceConfig.RANDOM_AVATAR_URL_PREFIX) {
urlPref = interfaceConfig.RANDOM_AVATAR_URL_PREFIX; urlPref = interfaceConfig.RANDOM_AVATAR_URL_PREFIX;
urlSuf = interfaceConfig.RANDOM_AVATAR_URL_SUFFIX; urlSuf = interfaceConfig.RANDOM_AVATAR_URL_SUFFIX;
} }
return urlPref + id + urlSuf; return urlPref + avatarId + urlSuf;
}
} }
}; };
module.exports = Avatar;

View File

@ -6,19 +6,22 @@ import UIEvents from "../../../service/UI/UIEvents";
import LargeContainer from './LargeContainer'; import LargeContainer from './LargeContainer';
import BottomToolbar from '../toolbars/BottomToolbar'; import BottomToolbar from '../toolbars/BottomToolbar';
import Avatar from "../avatar/Avatar"; import Avatar from "../avatar/Avatar";
import {createDeferred} from '../../util/helpers';
const RTCBrowserType = require("../../RTC/RTCBrowserType"); const RTCBrowserType = require("../../RTC/RTCBrowserType");
const avatarSize = interfaceConfig.DOMINANT_SPEAKER_AVATAR_SIZE; const avatarSize = interfaceConfig.DOMINANT_SPEAKER_AVATAR_SIZE;
const FADE_DURATION_MS = 300;
/** /**
* Get stream id. * Get stream id.
* @param {JitsiTrack?} stream * @param {JitsiTrack?} stream
*/ */
function getStreamId(stream) { function getStreamOwnerId(stream) {
if(!stream) if (!stream) {
return; return;
if (stream.isLocal()) { }
if (stream.isLocal()) { // local stream doesn't have method "getParticipantId"
return APP.conference.localId; return APP.conference.localId;
} else { } else {
return stream.getParticipantId(); return stream.getParticipantId();
@ -161,9 +164,7 @@ class VideoContainer extends LargeContainer {
} }
get id () { get id () {
if (this.stream) { return getStreamOwnerId(this.stream);
return getStreamId(this.stream);
}
} }
constructor (onPlay) { constructor (onPlay) {
@ -306,20 +307,20 @@ class VideoContainer extends LargeContainer {
show () { show () {
let $wrapper = this.$wrapper; let $wrapper = this.$wrapper;
return new Promise(function(resolve) { return new Promise(function(resolve) {
$wrapper.fadeIn(300, function () {
$wrapper.css({visibility: 'visible'}); $wrapper.css({visibility: 'visible'});
$wrapper.fadeIn(FADE_DURATION_MS, function () {
$('.watermark').css({visibility: 'visible'}); $('.watermark').css({visibility: 'visible'});
});
resolve(); resolve();
}); });
});
} }
hide () { hide () {
let $wrapper = this.$wrapper; let $wrapper = this.$wrapper;
let id = this.id;
return new Promise(function(resolve) { return new Promise(function(resolve) {
$wrapper.fadeOut(300, function () { $wrapper.fadeOut(id ? FADE_DURATION_MS : 1, function () {
$wrapper.css({visibility: 'hidden'}); $wrapper.css({visibility: 'hidden'});
$('.watermark').css({visibility: 'hidden'}); $('.watermark').css({visibility: 'hidden'});
resolve(); resolve();
@ -397,6 +398,45 @@ export default class LargeVideoManager {
return this.videoContainer.id; return this.videoContainer.id;
} }
scheduleLargeVideoUpdate () {
if (this.updateInProcess || !this.newStreamData) {
return;
}
this.updateInProcess = true;
let container = this.getContainer(this.state);
container.hide().then(() => {
let {id, stream, videoType, resolve} = this.newStreamData;
this.newStreamData = null;
console.info("hover in %s", id);
this.state = VideoContainerType;
this.videoContainer.setStream(stream, videoType);
// change the avatar url on large
this.updateAvatar(Avatar.getAvatarUrl(id));
let isVideoMuted = stream.isMuted();
// show the avatar on large if needed
this.videoContainer.showAvatar(isVideoMuted);
// do not show stream if video is muted
let promise = isVideoMuted ? Promise.resolve() : this.videoContainer.show();
// resolve updateLargeVideo promise after everything is done
promise.then(resolve);
return promise;
}).then(() => {
// after everything is done check again if there are any pending new streams.
this.updateInProcess = false;
this.scheduleLargeVideoUpdate();
});
}
/** /**
* Update large video. * Update large video.
* Switches to large video even if previously other container was visible. * Switches to large video even if previously other container was visible.
@ -404,28 +444,21 @@ export default class LargeVideoManager {
* @param {string?} videoType new video type * @param {string?} videoType new video type
* @returns {Promise} * @returns {Promise}
*/ */
updateLargeVideo (smallVideo, videoType, largeVideoUpdatedCallBack) { updateLargeVideo (stream, videoType) {
let id = getStreamId(smallVideo.stream); let id = getStreamOwnerId(stream);
let container = this.getContainer(this.state); if (this.newStreamData) {
this.newStreamData.reject();
}
container.hide().then(() => { this.newStreamData = createDeferred();
console.info("hover in %s", id); this.newStreamData.id = id;
this.state = VideoContainerType; this.newStreamData.stream = stream;
this.videoContainer.setStream(smallVideo.stream, videoType); this.newStreamData.videoType = videoType;
// change the avatar url on large this.scheduleLargeVideoUpdate();
this.updateAvatar(Avatar.getAvatarUrl(smallVideo.id));
var isVideoMuted = smallVideo.stream.isMuted() return this.newStreamData.promise;
// show the avatar on large if needed
this.videoContainer.showAvatar(isVideoMuted);
if (!isVideoMuted)
this.videoContainer.show();
largeVideoUpdatedCallBack();
});
} }
/** /**
@ -486,7 +519,6 @@ export default class LargeVideoManager {
* @param {boolean} show * @param {boolean} show
*/ */
showAvatar (show) { showAvatar (show) {
show ? this.videoContainer.hide() : this.videoContainer.show();
this.videoContainer.showAvatar(show); this.videoContainer.showAvatar(show);
} }
@ -542,16 +574,11 @@ export default class LargeVideoManager {
return Promise.resolve(); return Promise.resolve();
} }
let container = this.getContainer(type);
if (this.state) {
let oldContainer = this.containers[this.state]; let oldContainer = this.containers[this.state];
if (oldContainer) {
oldContainer.hide(); oldContainer.hide();
}
}
this.state = type; this.state = type;
let container = this.getContainer(type);
return container.show(); return container.show();
} }

View File

@ -990,13 +990,14 @@ var VideoLayout = {
let videoType = this.getRemoteVideoType(id); let videoType = this.getRemoteVideoType(id);
largeVideo.updateLargeVideo( largeVideo.updateLargeVideo(
smallVideo, smallVideo.stream,
videoType, videoType
// LargeVideoUpdatedCallBack ).then(function() {
function() {
// update current small video and the old one // update current small video and the old one
smallVideo.updateView(); smallVideo.updateView();
oldSmallVideo && oldSmallVideo.updateView(); oldSmallVideo && oldSmallVideo.updateView();
}, function () {
// use clicked other video during update, nothing to do.
}); });
} else if (currentId) { } else if (currentId) {

14
modules/util/helpers.js Normal file
View File

@ -0,0 +1,14 @@
/**
* Create deferred object.
* @returns {{promise, resolve, reject}}
*/
export function createDeferred () {
let deferred = {};
deferred.promise = new Promise(function (resolve, reject) {
deferred.resolve = resolve;
deferred.reject = reject;
});
return deferred;
}