abstract out remoteVideos management

This commit is contained in:
isymchych 2015-12-30 12:55:51 +02:00
parent 3400925f99
commit b375b14696
9 changed files with 131 additions and 99 deletions

View File

@ -88,7 +88,7 @@ function setupChat() {
function setupToolbars() {
Toolbar.init(eventEmitter);
Toolbar.setupButtonsFromConfig();
BottomToolbar.init(eventEmitter);
BottomToolbar.setupListeners(eventEmitter);
}
/**
@ -246,6 +246,8 @@ UI.start = function () {
registerListeners();
BottomToolbar.init();
VideoLayout.init(eventEmitter);
if (!interfaceConfig.filmStripOnly) {
VideoLayout.initLargeVideo(PanelToggler.isVisible());
@ -277,8 +279,7 @@ UI.start = function () {
$("#header").css("display", "none");
$("#bottomToolbar").css("display", "none");
$("#downloadlog").css("display", "none");
$("#remoteVideos").css("padding", "0px 0px 18px 0px");
$("#remoteVideos").css("right", "0px");
BottomToolbar.setupFilmStripOnly();
messageHandler.disableNotifications();
$('body').popover("disable");
JitsiPopover.enabled = false;

View File

@ -2,6 +2,7 @@
/* jshint -W101 */
import CanvasUtil from './CanvasUtils';
import BottomToolbar from '../toolbars/BottomToolbar';
const LOCAL_LEVEL = 'local';
@ -126,7 +127,7 @@ const AudioLevels = {
* Updates the audio level canvas for the given id. If the canvas
* didn't exist we create it.
*/
updateAudioLevelCanvas (id, VideoLayout) {
updateAudioLevelCanvas (id, thumbWidth, thumbHeight) {
let videoSpanId = 'localVideoContainer';
if (id) {
videoSpanId = `participant_${id}`;
@ -145,24 +146,19 @@ const AudioLevels = {
let audioLevelCanvas = $(`#${videoSpanId}>canvas`);
let videoSpaceWidth = $('#remoteVideos').width();
let thumbnailSize = VideoLayout.calculateThumbnailSize(videoSpaceWidth);
let thumbnailWidth = thumbnailSize[0];
let thumbnailHeight = thumbnailSize[1];
if (!audioLevelCanvas || audioLevelCanvas.length === 0) {
audioLevelCanvas = document.createElement('canvas');
audioLevelCanvas.className = "audiolevel";
audioLevelCanvas.style.bottom = `-${interfaceConfig.CANVAS_EXTRA/2}px`;
audioLevelCanvas.style.left = `-${interfaceConfig.CANVAS_EXTRA/2}px`;
resizeAudioLevelCanvas(audioLevelCanvas, thumbnailWidth, thumbnailHeight);
resizeAudioLevelCanvas(audioLevelCanvas, thumbWidth, thumbHeight);
videoSpan.appendChild(audioLevelCanvas);
} else {
audioLevelCanvas = audioLevelCanvas.get(0);
resizeAudioLevelCanvas(audioLevelCanvas, thumbnailWidth, thumbnailHeight);
resizeAudioLevelCanvas(audioLevelCanvas, thumbWidth, thumbHeight);
}
},
@ -223,31 +219,16 @@ const AudioLevels = {
ASDrawContext.fill();
},
/**
* Indicates that the remote video has been resized.
*/
onRemoteVideoResized (width, height) {
let resized = false;
updateCanvasSize (thumbWidth, thumbHeight) {
let canvasWidth = thumbWidth + interfaceConfig.CANVAS_EXTRA;
let canvasHeight = thumbHeight + interfaceConfig.CANVAS_EXTRA;
$('#remoteVideos>span>canvas').each(function() {
let canvas = $(this).get(0);
if (canvas.width !== width + interfaceConfig.CANVAS_EXTRA) {
canvas.width = width + interfaceConfig.CANVAS_EXTRA;
resized = true;
}
BottomToolbar.getThumbs().children('canvas').width(canvasWidth).height(canvasHeight);
if (canvas.height !== height + interfaceConfig.CANVAS_EXTRA) {
canvas.height = height + interfaceConfig.CANVAS_EXTRA;
resized = true;
}
Object.keys(audioLevelCanvasCache).forEach(function (id) {
audioLevelCanvasCache[id].width = canvasWidth;
audioLevelCanvasCache[id].height = canvasHeight;
});
if (resized) {
Object.keys(audioLevelCanvasCache).forEach(function (id) {
audioLevelCanvasCache[id].width = width + interfaceConfig.CANVAS_EXTRA;
audioLevelCanvasCache[id].height = height + interfaceConfig.CANVAS_EXTRA;
});
}
}
};

View File

@ -4,6 +4,7 @@ import VideoLayout from "../videolayout/VideoLayout";
import LargeContainer from '../videolayout/LargeContainer';
import UIUtil from "../util/UIUtil";
import SidePanelToggler from "../side_pannels/SidePanelToggler";
import BottomToolbar from '../toolbars/BottomToolbar';
const options = $.param({
showControns: true,
@ -88,9 +89,7 @@ class Etherpad extends LargeContainer {
}
resize (containerWidth, containerHeight, animate) {
let remoteVideos = $('#remoteVideos');
let height = containerHeight - remoteVideos.outerHeight();
let height = containerHeight - BottomToolbar.getFilmStripHeight();
let width = containerWidth;
$(this.iframe).width(width).height(height);

View File

@ -9,6 +9,7 @@ import UIEvents from '../../../service/UI/UIEvents';
import messageHandler from '../util/MessageHandler';
import ToolbarToggler from "../toolbars/ToolbarToggler";
import SidePanelToggler from "../side_pannels/SidePanelToggler";
import BottomToolbar from '../toolbars/BottomToolbar';
const defaultPreziLink = "http://prezi.com/wz7vhjycl7e6/my-prezi";
const alphanumRegex = /^[a-z0-9-_\/&\?=;]+$/i;
@ -244,8 +245,7 @@ class PreziContainer extends LargeContainer {
}
resize (containerWidth, containerHeight) {
let remoteVideos = $('#remoteVideos');
let height = containerHeight - remoteVideos.outerHeight();
let height = containerHeight - BottomToolbar.getFilmStripHeight();
let width = containerWidth;

View File

@ -10,7 +10,12 @@ const defaultBottomToolbarButtons = {
};
const BottomToolbar = {
init (emitter) {
init () {
this.filmStrip = $('#remoteVideos');
this.toolbar = $('#bottomToolbar');
},
setupListeners (emitter) {
UIUtil.hideDisabledButtons(defaultBottomToolbarButtons);
const buttonHandlers = {
@ -34,14 +39,69 @@ const BottomToolbar = {
},
toggleFilmStrip () {
$("#remoteVideos").toggleClass("hidden");
this.filmStrip.toggleClass("hidden");
},
onRemoteVideoResized (width, height) {
let toolbar = $('#bottomToolbar');
let bottom = (height - toolbar.outerHeight())/2 + 18;
isFilmStripVisible () {
return !this.filmStrip.hasClass('hidden');
},
toolbar.css({bottom});
setupFilmStripOnly () {
this.filmStrip.css({
padding: "0px 0px 18px 0px",
right: 0
});
},
getFilmStripHeight () {
if (this.isFilmStripVisible()) {
return this.filmStrip.outerHeight();
} else {
return 0;
}
},
getFilmStripWidth () {
return this.filmStrip.width();
},
resizeThumbnails (thumbWidth, thumbHeight, animate = false) {
return new Promise(resolve => {
this.filmStrip.animate({
// adds 2 px because of small video 1px border
height: thumbHeight + 2
}, {
queue: false,
duration: animate ? 500 : 0
});
this.getThumbs().animate({
height: thumbHeight,
width: thumbWidth
}, {
queue: false,
duration: animate ? 500 : 0,
complete: resolve
});
if (!animate) {
resolve();
}
});
},
resizeToolbar (thumbWidth, thumbHeight) {
let bottom = (thumbHeight - this.toolbar.outerHeight())/2 + 18;
this.toolbar.css({bottom});
},
getThumbs (visible = false) {
let selector = 'span';
if (visible) {
selector += ':visible';
}
return this.filmStrip.children(selector);
}
};

View File

@ -1,6 +1,7 @@
/* global APP, config, $, interfaceConfig */
import UIUtil from '../util/UIUtil';
import BottomToolbar from './BottomToolbar';
let toolbarTimeoutObject;
let toolbarTimeout = interfaceConfig.INITIAL_TOOLBAR_TIMEOUT;
@ -47,7 +48,7 @@ function hideToolbar() {
} else {
header.hide("slide", { direction: "up", duration: 300});
$('#subject').animate({top: "-=40"}, 300);
if ($("#remoteVideos").hasClass("hidden")) {
if (!BottomToolbar.isFilmStripVisible()) {
bottomToolbar.hide(
"slide", {direction: "right", duration: 300}
);

View File

@ -4,6 +4,7 @@
import UIUtil from "../util/UIUtil";
import UIEvents from "../../../service/UI/UIEvents";
import LargeContainer from './LargeContainer';
import BottomToolbar from '../toolbars/BottomToolbar';
const RTCBrowserType = require("../../RTC/RTCBrowserType");
@ -34,10 +35,7 @@ function getDesktopVideoSize(videoWidth,
let availableWidth = Math.max(videoWidth, videoSpaceWidth);
let availableHeight = Math.max(videoHeight, videoSpaceHeight);
let filmstrip = $("#remoteVideos");
if (!filmstrip.hasClass("hidden"))
videoSpaceHeight -= filmstrip.outerHeight();
videoSpaceHeight -= BottomToolbar.getFilmStripHeight();
if (availableWidth / aspectRatio >= videoSpaceHeight) {
availableHeight = videoSpaceHeight;

View File

@ -34,7 +34,8 @@ RemoteVideo.prototype.addRemoteVideoContainer = function() {
if (APP.conference.isModerator) {
this.addRemoteVideoMenu();
}
AudioLevels.updateAudioLevelCanvas(this.id, this.VideoLayout);
let {thumbWidth, thumbHeight} = this.VideoLayout.calculateThumbnailSize();
AudioLevels.updateAudioLevelCanvas(this.id, thumbWidth, thumbHeight);
return this.container;
};

View File

@ -34,6 +34,8 @@ var eventEmitter = null;
*/
var focusedVideoResourceJid = null;
const thumbAspectRatio = 16.0 / 9.0;
/**
* On contact list item clicked.
*/
@ -153,7 +155,8 @@ var VideoLayout = {
let localId = APP.conference.localId;
this.onVideoTypeChanged(localId, stream.getType());
AudioLevels.updateAudioLevelCanvas(null, VideoLayout);
let {thumbWidth, thumbHeight} = this.calculateThumbnailSize();
AudioLevels.updateAudioLevelCanvas(null, thumbWidth, thumbHeight);
localVideoThumbnail.changeVideo(stream);
@ -215,9 +218,11 @@ var VideoLayout = {
electLastVisibleVideo () {
// pick the last visible video in the row
// if nobody else is left, this picks the local video
let pick = $('#remoteVideos>span[id!="mixedstream"]:visible:last');
if (pick.length) {
let id = getPeerContainerResourceId(pick[0]);
let thumbs = BottomToolbar.getThumbs(true).filter('id!="mixedstream"');
let lastVisible = thumbs.filter(':visible:last');
if (lastVisible.length) {
let id = getPeerContainerResourceId(lastVisible[0]);
if (remoteVideos[id]) {
console.info("electLastVisibleVideo: " + id);
return id;
@ -227,9 +232,9 @@ var VideoLayout = {
}
console.info("Last visible video no longer exists");
pick = $('#remoteVideos>span[id!="mixedstream"]');
if (pick.length) {
let id = getPeerContainerResourceId(pick[0]);
thumbs = BottomToolbar.getThumbs();
if (thumbs.length) {
let id = getPeerContainerResourceId(thumbs[0]);
if (remoteVideos[id]) {
console.info("electLastVisibleVideo: " + id);
return id;
@ -332,7 +337,7 @@ var VideoLayout = {
// In case this is not currently in the last n we don't show it.
if (localLastNCount && localLastNCount > 0 &&
$('#remoteVideos>span').length >= localLastNCount + 2) {
BottomToolbar.getThumbs().length >= localLastNCount + 2) {
remoteVideo.showPeerContainer('hide');
} else {
VideoLayout.resizeThumbnails();
@ -419,67 +424,53 @@ var VideoLayout = {
* Resizes thumbnails.
*/
resizeThumbnails (animate = false) {
let videoSpaceWidth = $('#remoteVideos').width();
let {thumbWidth, thumbHeight} = this.calculateThumbnailSize();
let [width, height] = this.calculateThumbnailSize(videoSpaceWidth);
$('.userAvatar').css('left', (thumbWidth - thumbHeight) / 2);
$('.userAvatar').css('left', (width - height) / 2);
$('#remoteVideos').animate({
// adds 2 px because of small video 1px border
height: height + 2
}, {
queue: false,
duration: animate ? 500 : 0
});
$('#remoteVideos>span').animate({
height, width
}, {
queue: false,
duration: animate ? 500 : 0,
complete: function () {
BottomToolbar.onRemoteVideoResized(width, height);
AudioLevels.onRemoteVideoResized(width, height);
}
BottomToolbar.resizeThumbnails(thumbWidth, thumbHeight, animate).then(function () {
BottomToolbar.resizeToolbar(thumbWidth, thumbHeight);
AudioLevels.updateCanvasSize(thumbWidth, thumbHeight);
});
},
/**
* Calculates the thumbnail size.
*
* @param videoSpaceWidth the width of the video space
*/
calculateThumbnailSize (videoSpaceWidth) {
calculateThumbnailSize () {
let videoSpaceWidth = BottomToolbar.getFilmStripWidth();
// 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.
var availableHeight = 100;
let availableHeight = 100;
var numvids = $('#remoteVideos>span:visible').length;
let numvids = BottomToolbar.getThumbs().length;
if (localLastNCount && localLastNCount > 0) {
numvids = Math.min(localLastNCount + 1, numvids);
}
// Remove the 3px borders arround videos and border around the remote
// videos area and the 4 pixels between the local video and the others
//TODO: Find out where the 4 pixels come from and remove them
var availableWinWidth = videoSpaceWidth - 2 * 3 * numvids - 70 - 4;
// Remove the 3px borders arround videos and border around the remote
// videos area and the 4 pixels between the local video and the others
//TODO: Find out where the 4 pixels come from and remove them
let availableWinWidth = videoSpaceWidth - 2 * 3 * numvids - 70 - 4;
var availableWidth = availableWinWidth / numvids;
var aspectRatio = 16.0 / 9.0;
var maxHeight = Math.min(160, availableHeight);
availableHeight
= Math.min( maxHeight,
availableWidth / aspectRatio,
window.innerHeight - 18);
let availableWidth = availableWinWidth / numvids;
let maxHeight = Math.min(160, availableHeight);
availableHeight
= Math.min( maxHeight,
availableWidth / thumbAspectRatio,
window.innerHeight - 18);
if (availableHeight < availableWidth / aspectRatio) {
availableWidth = Math.floor(availableHeight * aspectRatio);
}
if (availableHeight < availableWidth / thumbAspectRatio) {
availableWidth = Math.floor(availableHeight * thumbAspectRatio);
}
return [availableWidth, availableHeight];
return {
thumbWidth: availableWidth,
thumbHeight: availableHeight
};
},
/**
@ -623,7 +614,7 @@ var VideoLayout = {
var updateLargeVideo = false;
// Handle LastN/local LastN changes.
$('#remoteVideos>span').each(function( index, element ) {
BottomToolbar.getThumbs().each(function( index, element ) {
var resourceJid = getPeerContainerResourceId(element);
// We do not want to process any logic for our own(local) video