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

View File

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

View File

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

View File

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

View File

@ -10,7 +10,12 @@ const defaultBottomToolbarButtons = {
}; };
const BottomToolbar = { const BottomToolbar = {
init (emitter) { init () {
this.filmStrip = $('#remoteVideos');
this.toolbar = $('#bottomToolbar');
},
setupListeners (emitter) {
UIUtil.hideDisabledButtons(defaultBottomToolbarButtons); UIUtil.hideDisabledButtons(defaultBottomToolbarButtons);
const buttonHandlers = { const buttonHandlers = {
@ -34,14 +39,69 @@ const BottomToolbar = {
}, },
toggleFilmStrip () { toggleFilmStrip () {
$("#remoteVideos").toggleClass("hidden"); this.filmStrip.toggleClass("hidden");
}, },
onRemoteVideoResized (width, height) { isFilmStripVisible () {
let toolbar = $('#bottomToolbar'); return !this.filmStrip.hasClass('hidden');
let bottom = (height - toolbar.outerHeight())/2 + 18; },
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 */ /* global APP, config, $, interfaceConfig */
import UIUtil from '../util/UIUtil'; import UIUtil from '../util/UIUtil';
import BottomToolbar from './BottomToolbar';
let toolbarTimeoutObject; let toolbarTimeoutObject;
let toolbarTimeout = interfaceConfig.INITIAL_TOOLBAR_TIMEOUT; let toolbarTimeout = interfaceConfig.INITIAL_TOOLBAR_TIMEOUT;
@ -47,7 +48,7 @@ function hideToolbar() {
} else { } else {
header.hide("slide", { direction: "up", duration: 300}); header.hide("slide", { direction: "up", duration: 300});
$('#subject').animate({top: "-=40"}, 300); $('#subject').animate({top: "-=40"}, 300);
if ($("#remoteVideos").hasClass("hidden")) { if (!BottomToolbar.isFilmStripVisible()) {
bottomToolbar.hide( bottomToolbar.hide(
"slide", {direction: "right", duration: 300} "slide", {direction: "right", duration: 300}
); );

View File

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

View File

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

View File

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