diff --git a/bigbluebutton-html5/Gruntfile.js b/bigbluebutton-html5/Gruntfile.js index 97d77c742a..4ba47feb5e 100755 --- a/bigbluebutton-html5/Gruntfile.js +++ b/bigbluebutton-html5/Gruntfile.js @@ -14,7 +14,7 @@ module.exports = function (grunt) { tasks: ['force:jscs:check'], options: { event: ['all'], - spawn: true + spawn: true, }, }, }, @@ -28,7 +28,7 @@ module.exports = function (grunt) { esnext: true, }, }, - fix: { + autofix: { src: ['**/*.js', '**/*.jsx'], options: { config: '.jscsrc', @@ -51,13 +51,11 @@ module.exports = function (grunt) { limit: 3, }, meteor_watch: { - tasks: ['shell:start_meteor', 'watch'] + tasks: ['shell:start_meteor', 'watch'], }, - } + }, }); - grunt.loadNpmTasks('grunt-contrib-jshint'); - grunt.loadNpmTasks('grunt-coffeelint'); grunt.loadNpmTasks('grunt-jscs'); grunt.loadNpmTasks('grunt-force-task'); grunt.loadNpmTasks('grunt-contrib-watch'); diff --git a/bigbluebutton-html5/client/MainContainer.jsx b/bigbluebutton-html5/client/MainContainer.jsx index 3f627d2c95..bd2d3ac9cb 100755 --- a/bigbluebutton-html5/client/MainContainer.jsx +++ b/bigbluebutton-html5/client/MainContainer.jsx @@ -5,20 +5,21 @@ import {Chat} from '/imports/ui/chat/Chat.jsx'; MainContainer = React.createClass({ handleShield() { - $(".tooltip").hide(); + $('.tooltip').hide(); toggleShield(); return closeMenus(); }, + render() { return ( -
-
-
-
- - -
+
+
+
+
+ + +
); - } + }, }); diff --git a/bigbluebutton-html5/client/globals.js b/bigbluebutton-html5/client/globals.js index 29eca7f824..7ddded1d08 100755 --- a/bigbluebutton-html5/client/globals.js +++ b/bigbluebutton-html5/client/globals.js @@ -119,7 +119,6 @@ Handlebars.registerHelper('isCurrentUser', userId => { return userId === null || userId === ((ref = BBB.getCurrentUser()) != null ? ref.userId : void 0); }); - //Retreives a username for a private chat tab from the database if it exists Handlebars.registerHelper('privateChatName', () => { let obj, ref; @@ -139,7 +138,7 @@ Handlebars.registerHelper('isCurrentUserSharingVideo', () => { return BBB.amISharingVideo(); }); -Handlebars.registerHelper("isCurrentUserPresenter", () => { +Handlebars.registerHelper('isCurrentUserPresenter', () => { return BBB.isUserPresenter(getInSession('userId')); }); @@ -194,7 +193,7 @@ Handlebars.registerHelper('messageFontSize', () => { }); //#TODO REMOVE -Handlebars.registerHelper("pointerLocation", () => { +Handlebars.registerHelper('pointerLocation', () => { let currentPresentation, currentSlideDoc, pointer, presentationId, ref; currentPresentation = Meteor.Presentations.findOne({ 'presentation.current': true, @@ -235,19 +234,19 @@ Handlebars.registerHelper('containerPosition', section => { Template.registerHelper('emojiIcons', function () { return [ { name: 'sad', icon: 'sad-face', title: '' }, - { name: 'happy', icon: 'happy-face', title: ''}, - { name: 'confused', icon: 'confused-face', title: ''}, - { name: 'neutral', icon: 'neutral-face', title: ''}, - { name: 'away', icon: 'clock', title: ''}, - { name: 'raiseHand', icon: 'hand', title: 'Lower your Hand'} + { name: 'happy', icon: 'happy-face', title: '' }, + { name: 'confused', icon: 'confused-face', title: '' }, + { name: 'neutral', icon: 'neutral-face', title: '' }, + { name: 'away', icon: 'clock', title: '' }, + { name: 'raiseHand', icon: 'hand', title: 'Lower your Hand' }, ]; }); // scale the whiteboard to adapt to the resized window -this.scaleWhiteboard = function(whiteboardPaperModel) { +this.scaleWhiteboard = function (whiteboardPaperModel) { let adjustedDimensions; adjustedDimensions = scaleSlide(getInSession('slideOriginalWidth'), getInSession('slideOriginalHeight')); - if(typeof whiteboardPaperModel !== "undefined" && whiteboardPaperModel !== null) { + if (typeof whiteboardPaperModel !== 'undefined' && whiteboardPaperModel !== null) { whiteboardPaperModel.scale(adjustedDimensions.width, adjustedDimensions.height); } /* if(callback) { diff --git a/bigbluebutton-html5/client/main.jsx b/bigbluebutton-html5/client/main.jsx index 3410fb7637..5d93dad744 100755 --- a/bigbluebutton-html5/client/main.jsx +++ b/bigbluebutton-html5/client/main.jsx @@ -13,12 +13,14 @@ import '/imports/ui/stylesheets/whiteboard.less'; let loadLib; // Helper to load javascript libraries from the BBB server -loadLib = function(libname) { +loadLib = function (libname) { let retryMessageCallback, successCallback; - successCallback = function() {}; - retryMessageCallback = function(param) { - return console.log("Failed to load library", param); + successCallback = function () {}; + + retryMessageCallback = function (param) { + return console.log('Failed to load library', param); }; + return Meteor.Loader.loadJs(`${window.location.origin}/client/lib/${libname}`, successCallback, 10000).fail(retryMessageCallback); }; @@ -35,7 +37,7 @@ Meteor.startup(() => { set(key, value) { Session.set.apply(this, arguments); amplify.store.sessionStorage(key, value); - } + }, }); }); @@ -45,17 +47,18 @@ Template.menu.events({ toggleSettingsMenu(); return $('.slideButton').blur(); }, + 'click .toggleChatButton'(event) { return toggleChatbar(); - } + }, }); -Template.main.rendered = function() { - ReactDOM.render(, document.getElementById("main")); +Template.main.rendered = function () { + ReactDOM.render(, document.getElementById('main')); ReactDOM.render(, document.getElementById('user-contents')); let lastOrientationWasLandscape; - $("#dialog").dialog({ + $('#dialog').dialog({ modal: true, draggable: false, resizable: false, @@ -64,42 +67,45 @@ Template.main.rendered = function() { buttons: [ { text: 'Yes', - click: function() { - userLogout(BBB.getMeetingId(), getInSession("userId"), true); - return $(this).dialog("close"); + click: function () { + userLogout(BBB.getMeetingId(), getInSession('userId'), true); + return $(this).dialog('close'); }, - "class": 'btn btn-xs btn-primary active' + + class: 'btn btn-xs btn-primary active', }, { text: 'No', - click: function() { - $(this).dialog("close"); - return $(".tooltip").hide(); + click: function () { + $(this).dialog('close'); + return $('.tooltip').hide(); }, - "class": 'btn btn-xs btn-default' - } + + class: 'btn btn-xs btn-default', + }, ], open(event, ui) { return $('.ui-widget-overlay').bind('click', () => { - if(isMobile()) { - return $("#dialog").dialog('close'); + if (isMobile()) { + return $('#dialog').dialog('close'); } }); }, + position: { my: 'right top', at: 'right bottom', - of: '.signOutIcon' - } + of: '.signOutIcon', + }, }); lastOrientationWasLandscape = isLandscape(); $(window).resize(() => { $('#dialog').dialog('close'); // when the orientation switches call the handler - if(isLandscape() && !lastOrientationWasLandscape) { + if (isLandscape() && !lastOrientationWasLandscape) { orientationBecameLandscape(); return lastOrientationWasLandscape = true; - } else if(isPortrait() && lastOrientationWasLandscape) { + } else if (isPortrait() && lastOrientationWasLandscape) { orientationBecamePortrait(); return lastOrientationWasLandscape = false; } @@ -107,14 +113,14 @@ Template.main.rendered = function() { $('#shield').click(() => { return toggleSlidingMenu(); }); - if(Meteor.config.app.autoJoinAudio) { - if(Meteor.config.app.skipCheck) { + if (Meteor.config.app.autoJoinAudio) { + if (Meteor.config.app.skipCheck) { return joinVoiceCall(this, { - isListenOnly: Meteor.config.app.listenOnly + isListenOnly: Meteor.config.app.listenOnly, }); } else { - $("#settingsModal").foundation('reveal', 'open'); - if(Meteor.config.app.listenOnly) { + $('#settingsModal').foundation('reveal', 'open'); + if (Meteor.config.app.listenOnly) { return $('#joinMicrophone').prop('disabled', true); } } @@ -124,29 +130,30 @@ Template.main.rendered = function() { Template.main.gestures({ 'panstart #container'(event, template) { let initTransformValue, menuPanned, panIsValid, screenWidth; - if(isPortraitMobile() && isPanHorizontal(event)) { + if (isPortraitMobile() && isPanHorizontal(event)) { panIsValid = getInSession('panIsValid'); initTransformValue = getInSession('initTransform'); menuPanned = getInSession('menuPanned'); screenWidth = $('#container').width(); setInSession('panStarted', true); - if(panIsValid && menuPanned === 'left' && initTransformValue + event.deltaX >= 0 && initTransformValue + event.deltaX <= $('.left-drawer').width()) { + if (panIsValid && menuPanned === 'left' && initTransformValue + event.deltaX >= 0 && initTransformValue + event.deltaX <= $('.left-drawer').width()) { return $('.left-drawer').css('transform', `translateX(${initTransformValue + event.deltaX}px)`); - } else if(panIsValid && menuPanned === 'right' && initTransformValue + event.deltaX >= screenWidth - $('.right-drawer').width() && initTransformValue + event.deltaX <= screenWidth) { + } else if (panIsValid && menuPanned === 'right' && initTransformValue + event.deltaX >= screenWidth - $('.right-drawer').width() && initTransformValue + event.deltaX <= screenWidth) { return $('.right-drawer').css('transform', `translateX(${initTransformValue + event.deltaX}px)`); } } }, + 'panend #container'(event, template) { let leftDrawerWidth, menuPanned, panIsValid, screenWidth; - if(isPortraitMobile()) { + if (isPortraitMobile()) { panIsValid = getInSession('panIsValid'); menuPanned = getInSession('menuPanned'); leftDrawerWidth = $('.left-drawer').width(); screenWidth = $('#container').width(); setInSession('panStarted', false); - if(panIsValid && menuPanned === 'left' && $('.left-drawer').css('transform') !== 'none') { - if(parseInt($('.left-drawer').css('transform').split(',')[4]) < leftDrawerWidth / 2) { + if (panIsValid && menuPanned === 'left' && $('.left-drawer').css('transform') !== 'none') { + if (parseInt($('.left-drawer').css('transform').split(',')[4]) < leftDrawerWidth / 2) { $('.shield').removeClass('animatedShield'); $('.shield').css('opacity', ''); $('.left-drawer').removeClass('menuOut'); @@ -161,8 +168,9 @@ Template.main.gestures({ $('.toggleUserlistButton').addClass('menuToggledOn'); } } - if(panIsValid && menuPanned === 'right' && parseInt($('.right-drawer').css('transform').split(',')[4]) !== leftDrawerWidth) { - if(parseInt($('.right-drawer').css('transform').split(',')[4]) > screenWidth - $('.right-drawer').width() / 2) { + + if (panIsValid && menuPanned === 'right' && parseInt($('.right-drawer').css('transform').split(',')[4]) !== leftDrawerWidth) { + if (parseInt($('.right-drawer').css('transform').split(',')[4]) > screenWidth - $('.right-drawer').width() / 2) { $('.shield').removeClass('animatedShield'); $('.shield').css('opacity', ''); $('.right-drawer').css('transform', `translateX(${screenWidth}px)`); @@ -178,70 +186,76 @@ Template.main.gestures({ $('.toggleMenuButton').addClass('menuToggledOn'); } } + $('.left-drawer').addClass('userlistMenu'); $('.userlistMenu').removeClass('left-drawer'); $('.right-drawer').addClass('settingsMenu'); return $('.settingsMenu').removeClass('right-drawer'); } }, + 'panright #container, panleft #container'(event, template) { let initTransformValue, leftDrawerWidth, menuPanned, panIsValid, rightDrawerWidth, screenWidth; - if(isPortraitMobile() && isPanHorizontal(event)) { + if (isPortraitMobile() && isPanHorizontal(event)) { // panright/panleft is always triggered once right before panstart - if(!getInSession('panStarted')) { + if (!getInSession('panStarted')) { // opening the left-hand menu - if(event.type === 'panright' && event.center.x <= $('#container').width() * 0.1) { + if (event.type === 'panright' && event.center.x <= $('#container').width() * 0.1) { setInSession('panIsValid', true); setInSession('menuPanned', 'left'); // closing the left-hand menu - } else if(event.type === 'panleft' && event.center.x < $('#container').width() * 0.9) { + } else if (event.type === 'panleft' && event.center.x < $('#container').width() * 0.9) { setInSession('panIsValid', true); setInSession('menuPanned', 'left'); // opening the right-hand menu - } else if(event.type === 'panleft' && event.center.x >= $('#container').width() * 0.9) { + } else if (event.type === 'panleft' && event.center.x >= $('#container').width() * 0.9) { setInSession('panIsValid', true); setInSession('menuPanned', 'right'); // closing the right-hand menu - } else if(event.type === 'panright' && event.center.x > $('#container').width() * 0.1) { + } else if (event.type === 'panright' && event.center.x > $('#container').width() * 0.1) { setInSession('panIsValid', true); setInSession('menuPanned', 'right'); } else { setInSession('panIsValid', false); } + setInSession('eventType', event.type); - if(getInSession('menuPanned') === 'left') { - if($('.userlistMenu').css('transform') !== 'none') { // menu is already transformed + if (getInSession('menuPanned') === 'left') { + if ($('.userlistMenu').css('transform') !== 'none') { // menu is already transformed setInSession( 'initTransform', parseInt($('.userlistMenu').css('transform').split(',')[4]) ); // translateX value - } else if($('.userlistMenu').hasClass('menuOut')) { + } else if ($('.userlistMenu').hasClass('menuOut')) { setInSession('initTransform', $('.userlistMenu').width()); } else { setInSession('initTransform', 0); } + $('.userlistMenu').addClass('left-drawer'); $('.left-drawer').removeClass('userlistMenu'); - } else if(getInSession('menuPanned') === 'right') { - if($('.settingsMenu').css('transform') !== 'none') { // menu is already transformed + } else if (getInSession('menuPanned') === 'right') { + if ($('.settingsMenu').css('transform') !== 'none') { // menu is already transformed setInSession( 'initTransform', parseInt($('.settingsMenu').css('transform').split(',')[4]) ); // translateX value - } else if($('.settingsMenu').hasClass('menuOut')) { + } else if ($('.settingsMenu').hasClass('menuOut')) { setInSession('initTransform', $('.settingsMenu').width()); } else { setInSession('initTransform', 0); } + $('.settingsMenu').addClass('right-drawer'); $('.right-drawer').removeClass('settingsMenu'); } } + initTransformValue = getInSession('initTransform'); panIsValid = getInSession('panIsValid'); menuPanned = getInSession('menuPanned'); @@ -250,35 +264,39 @@ Template.main.gestures({ screenWidth = $('#container').width(); // moving the left-hand menu - if(panIsValid && + if (panIsValid && menuPanned === 'left' && initTransformValue + event.deltaX >= 0 && initTransformValue + event.deltaX <= leftDrawerWidth) { - if($('.settingsMenu').hasClass('menuOut')) { + if ($('.settingsMenu').hasClass('menuOut')) { toggleSettingsMenu(); } + $('.left-drawer').css('transform', `translateX(${initTransformValue + event.deltaX}px)`); - if(!getInSession('panStarted')) { + if (!getInSession('panStarted')) { $('.shield').addClass('animatedShield'); } + return $('.shield').css('opacity', 0.5 * (initTransformValue + event.deltaX) / leftDrawerWidth); - } else if(panIsValid && + } else if (panIsValid && menuPanned === 'right' && initTransformValue + event.deltaX >= screenWidth - rightDrawerWidth && initTransformValue + event.deltaX <= screenWidth) { // moving the right-hand menu - if($('.userlistMenu').hasClass('menuOut')) { + if ($('.userlistMenu').hasClass('menuOut')) { toggleUserlistMenu(); } + $('.right-drawer').css('transform', `translateX(${initTransformValue + event.deltaX}px)`); - if(!getInSession('panStarted')) { + if (!getInSession('panStarted')) { $('.shield').addClass('animatedShield'); } + return $('.shield').css('opacity', 0.5 * (screenWidth - initTransformValue - event.deltaX) / rightDrawerWidth); } } - } + }, }); -Template.makeButton.rendered = function() { +Template.makeButton.rendered = function () { return $('button[rel=tooltip]').tooltip(); }; diff --git a/bigbluebutton-html5/imports/ui/EmojiIcon.jsx b/bigbluebutton-html5/imports/ui/EmojiIcon.jsx index 264019b199..08681f4cd5 100755 --- a/bigbluebutton-html5/imports/ui/EmojiIcon.jsx +++ b/bigbluebutton-html5/imports/ui/EmojiIcon.jsx @@ -13,10 +13,9 @@ export let EmojiIcon = React.createClass({ }, renderIcon() { - if(this.props.iconName === 'raiseHand') { + if (this.props.iconName === 'raiseHand') { return (); - } - else if(this.props.iconName === 'happy') { + } else if (this.props.iconName === 'happy') { return ( @@ -24,9 +23,8 @@ export let EmojiIcon = React.createClass({ - ) - } - else if(this.props.iconName === 'neutral') { + ); + } else if (this.props.iconName === 'neutral') { return ( @@ -34,9 +32,8 @@ export let EmojiIcon = React.createClass({ - ) - } - else if(this.props.iconName === 'confused') { + ); + } else if (this.props.iconName === 'confused') { return ( @@ -44,9 +41,8 @@ export let EmojiIcon = React.createClass({ - ) - } - else if(this.props.iconName === 'sad') { + ); + } else if (this.props.iconName === 'sad') { return ( @@ -54,24 +50,22 @@ export let EmojiIcon = React.createClass({ - ) - } - else if(this.props.iconName === 'away') { + ); + } else if (this.props.iconName === 'away') { return ( - ) - } - else if(this.props.iconName === 'plus') { + ); + } else if (this.props.iconName === 'plus') { return ( - ) + ); } }, }); diff --git a/bigbluebutton-html5/imports/ui/chat/Chat.jsx b/bigbluebutton-html5/imports/ui/chat/Chat.jsx index 9069846135..9bdc48cbc2 100755 --- a/bigbluebutton-html5/imports/ui/chat/Chat.jsx +++ b/bigbluebutton-html5/imports/ui/chat/Chat.jsx @@ -8,22 +8,23 @@ export let Chat = React.createClass({ getMeteorData() { let chatMessages, privateChatName, chattingWith, user, messageFontSize, temp, user_exists; - messageFontSize = { fontSize: getInSession("messageFontSize") + 'px' }; + messageFontSize = { fontSize: getInSession('messageFontSize') + 'px' }; chattingWith = getInSession('inChatWith'); - if(chattingWith === 'PUBLIC_CHAT') { // find all public and system messages - chatMessages = Meteor.Chat.find({ 'message.chat_type': { $in: ["SYSTEM_MESSAGE", "PUBLIC_CHAT"] }}, - { sort: { 'message.from_time': 1 }}).fetch(); + if (chattingWith === 'PUBLIC_CHAT') { // find all public and system messages + chatMessages = Meteor.Chat.find({ 'message.chat_type': { $in: ['SYSTEM_MESSAGE', 'PUBLIC_CHAT'] } }, + { sort: { 'message.from_time': 1 } }).fetch(); } else { - chatMessages = Meteor.Chat.find({ 'message.chat_type': 'PRIVATE_CHAT', $or: [{ 'message.to_userid': chattingWith }, - { 'message.from_userid': chattingWith }]}).fetch(); - } + chatMessages = Meteor.Chat.find({ 'message.chat_type': 'PRIVATE_CHAT', $or: [{ 'message.to_userid': chattingWith }, + { 'message.from_userid': chattingWith }, ], }).fetch(); + } + user = Meteor.Users.findOne({ userId: chattingWith }); - if(user != null) { + if (user != null) { privateChatName = user.user.name; } - if(getInSession('inChatWith') === "PUBLIC_CHAT" || Meteor.Users.findOne({ - userId: getInSession('inChatWith') + if (getInSession('inChatWith') === 'PUBLIC_CHAT' || Meteor.Users.findOne({ + userId: getInSession('inChatWith'), }) != null) { user_exists = true; } else { @@ -34,48 +35,51 @@ export let Chat = React.createClass({ chatMessages: chatMessages, privateChatName: privateChatName, messageFontSize: messageFontSize, - user_exists: user_exists - }; + user_exists: user_exists, + }; }, - detectUnreadChat: function() { + detectUnreadChat: function () { //if the current tab is not the same as the tab we just published in return Meteor.Chat.find({}).observe({ added: (_this => { - return function(chatMessage) { + return function (chatMessage) { let findDestinationTab; - findDestinationTab = function() { + findDestinationTab = function () { let ref, ref1; - if(((ref = chatMessage.message) != null ? ref.chat_type : void 0) === "PUBLIC_CHAT") { - return "PUBLIC_CHAT"; + if (((ref = chatMessage.message) != null ? ref.chat_type : void 0) === 'PUBLIC_CHAT') { + return 'PUBLIC_CHAT'; } else { return (ref1 = chatMessage.message) != null ? ref1.from_userid : void 0; } }; + return Tracker.autorun(comp => { let destinationTab, tabsTime; tabsTime = getInSession('userListRenderedTime'); - if((tabsTime != null) && chatMessage.message.from_userid !== "SYSTEM_MESSAGE" && chatMessage.message.from_time - tabsTime > 0) { + if ((tabsTime != null) && chatMessage.message.from_userid !== 'SYSTEM_MESSAGE' && chatMessage.message.from_time - tabsTime > 0) { populateNotifications(chatMessage); // check if we need to show a new notification destinationTab = findDestinationTab(); - if(destinationTab !== getInSession("inChatWith")) { + if (destinationTab !== getInSession('inChatWith')) { setInSession('chats', getInSession('chats').map(tab => { - if(tab.userId === destinationTab) { + if (tab.userId === destinationTab) { tab.gotMail = true; tab.number++; } + return tab; })); } } + return comp.stop(); }); }; - })(this) + })(this), }); }, - componentDidMount: function(){ + componentDidMount: function () { this.detectUnreadChat(); }, @@ -83,17 +87,18 @@ export let Chat = React.createClass({ let deleted, i, j, len; len = msgs != null ? msgs.length : void 0; // get length of messages i = 0; - while(i < len) { // Must be a do while, for loop compiles and stores the length of array which can change inside the loop! - if(msgs[i].message.from_userid !== 'System') { // skip system messages + while (i < len) { // Must be a do while, for loop compiles and stores the length of array which can change inside the loop! + if (msgs[i].message.from_userid !== 'System') { // skip system messages j = i + 1; // Start looking at messages right after the current one - while(j < len) { + while (j < len) { deleted = false; - if(msgs[j].message.from_userid !== 'System') { // Ignore system messages + if (msgs[j].message.from_userid !== 'System') { // Ignore system messages // Check if the time discrepancy between the two messages exceeds window for grouping - if((parseFloat(msgs[j].message.from_time) - parseFloat(msgs[i].message.from_time)) >= 60000) { // 60 seconds/1 minute + if ((parseFloat(msgs[j].message.from_time) - parseFloat(msgs[i].message.from_time)) >= 60000) { // 60 seconds/1 minute break; // Messages are too far between, so them seperated and stop joining here } - if(msgs[i].message.from_userid === msgs[j].message.from_userid) { // Both messages are from the same user + + if (msgs[i].message.from_userid === msgs[j].message.from_userid) { // Both messages are from the same user // insert a '\r' carriage return character between messages to put them on a new line msgs[i].message.message += `${CARRIAGE_RETURN}${msgs[j].message.message}`; // Combine the messages msgs.splice(j, 1); // Delete the message from the collection @@ -104,44 +109,47 @@ export let Chat = React.createClass({ } else { break; // This is the break point in the chat, don't merge } + len = msgs.length; - if(!deleted) { + if (!deleted) { ++j; } } } + ++i; len = msgs.length; } + return msgs; }, - inPrivateChat(){ + inPrivateChat() { return (getInSession('inChatWith') !== 'PUBLIC_CHAT'); }, - render(){ + render() { return ( -
-
- {this.inPrivateChat() ? +
+
+ {this.inPrivateChat() ? - : null } -
-
    + : null } +
    +
      {this.getCombinedMessagesForChat(this.data.chatMessages).map((message) => - )} - {this.data.user_exists ? null :
    • The user has left
    • } -
    -
    -
+ )} + {this.data.user_exists ? null :
  • The user has left
  • } + +
    +
    {this.data.user_exists ? -
    - +
    +
    - : null } + : null }
    ); - } + }, }); diff --git a/bigbluebutton-html5/imports/ui/chat/ChatInputControls.jsx b/bigbluebutton-html5/imports/ui/chat/ChatInputControls.jsx index 863fe1d142..7ef61b6de5 100755 --- a/bigbluebutton-html5/imports/ui/chat/ChatInputControls.jsx +++ b/bigbluebutton-html5/imports/ui/chat/ChatInputControls.jsx @@ -2,27 +2,30 @@ import React from 'react'; export let ChatInputControls = React.createClass({ //#TODO MessageFontSize dynamic change - componentDidMount: function() { + componentDidMount: function () { $('.panel-footer').resizable({ - handles: 'n', - minHeight: 70, - resize(event, ui) { + handles: 'n', + minHeight: 70, + resize(event, ui) { let ref; - if($('.panel-footer').css('top') === '0px') { + if ($('.panel-footer').css('top') === '0px') { $('.panel-footer').height(70); // prevents the element from shrinking vertically for 1-2 px } else { $('.panel-footer').css('top', `${parseInt($('.panel-footer').css('top'))}${1}px`); } + $('#chatbody').height($('#chat').height() - $('.panel-footer').height() - 45); return $('#chatbody').scrollTop((ref = $('#chatbody')[0]) != null ? ref.scrollHeight : void 0); }, - start(event, ui) { + + start(event, ui) { $('#newMessageInput').css('overflow', ''); return $('.panel-footer').resizable('option', 'maxHeight', Math.max($('.panel-footer').height(), $('#chat').height() / 2)); }, - stop(event, ui) { + + stop(event, ui) { return setInSession('chatInputMinHeight', $('.panel-footer').height() + 1); - } + }, }); $('#newMessageInput').on('keydown paste cut', () => { @@ -31,30 +34,33 @@ export let ChatInputControls = React.createClass({ }, 0); }); }, - sendMessage: function() { + + sendMessage: function () { let chattingWith, color, message, ref, toUsername; message = linkify($('#newMessageInput').val()); // get the message from the input box - if(!((message != null ? message.length : void 0) > 0 && (/\S/.test(message)))) { // check the message has content and it is not whitespace + if (!((message != null ? message.length : void 0) > 0 && (/\S/.test(message)))) { // check the message has content and it is not whitespace return; // do nothing if invalid message } - color = "0x000000"; //"0x#{getInSession("messageColor")}" - if((chattingWith = getInSession('inChatWith')) !== "PUBLIC_CHAT") { + + color = '0x000000'; //"0x#{getInSession("messageColor")}" + if ((chattingWith = getInSession('inChatWith')) !== 'PUBLIC_CHAT') { toUsername = (ref = Meteor.Users.findOne({ - userId: chattingWith + userId: chattingWith, })) != null ? ref.user.name : void 0; - BBB.sendPrivateChatMessage(color, "en", message, chattingWith, toUsername); + BBB.sendPrivateChatMessage(color, 'en', message, chattingWith, toUsername); } else { - BBB.sendPublicChatMessage(color, "en", message); + BBB.sendPublicChatMessage(color, 'en', message); } + return $('#newMessageInput').val(''); // Clear message box }, - adjustChatInputHeight: function() { + adjustChatInputHeight: function () { let projectedHeight, ref; - if(isLandscape()) { + if (isLandscape()) { $('#newMessageInput').css('height', 'auto'); projectedHeight = $('#newMessageInput')[0].scrollHeight + 23; - if(projectedHeight !== $('.panel-footer').height() && projectedHeight >= getInSession('chatInputMinHeight')) { + if (projectedHeight !== $('.panel-footer').height() && projectedHeight >= getInSession('chatInputMinHeight')) { $('#newMessageInput').css('overflow', 'hidden'); // prevents a scroll bar // resizes the chat input area @@ -67,83 +73,86 @@ export let ChatInputControls = React.createClass({ $('#chatbody').height($('#chat').height() - projectedHeight - 45); $('#chatbody').scrollTop((ref = $('#chatbody')[0]) != null ? ref.scrollHeight : void 0); } + return $('#newMessageInput').css('height', ''); - } else if(isPortrait()) { + } else if (isPortrait()) { $('.panel-footer').attr('style', ''); $('#chatbody').attr('style', ''); return $('#newMessageInput').attr('style', ''); } }, - handleClick: function() { + handleClick: function () { $('#sendMessageButton').blur(); this.sendMessage(); return this.adjustChatInputHeight(); }, // user pressed a button inside the chatbox - keyPressedHandler: function(event) { + keyPressedHandler: function (event) { let key; key = event.charCode ? event.charCode : (event.keyCode ? event.keyCode : 0); - if(event.shiftKey && (key === 13)) { + if (event.shiftKey && (key === 13)) { event.preventDefault(); + // append a '\r' carriage return character to the input box dropping the cursor to a new line - document.getElementById("newMessageInput").value += CARRIAGE_RETURN; // Change newline character + document.getElementById('newMessageInput').value += CARRIAGE_RETURN; // Change newline character return; } - if(key === 13) { // Check for pressing enter to submit message + + if (key === 13) { // Check for pressing enter to submit message event.preventDefault(); this.sendMessage(); - $('#newMessageInput').val(""); + $('#newMessageInput').val(''); return false; } }, - publicChatDisabled: function() { + publicChatDisabled: function () { let presenter, publicChatIsDisabled, ref, ref1, ref2, userIsLocked; userIsLocked = (ref = Meteor.Users.findOne({ - userId: getInSession('userId') + userId: getInSession('userId'), })) != null ? ref.user.locked : void 0; publicChatIsDisabled = (ref1 = Meteor.Meetings.findOne({})) != null ? ref1.roomLockSettings.disablePublicChat : void 0; presenter = (ref2 = Meteor.Users.findOne({ - userId: getInSession('userId') + userId: getInSession('userId'), })) != null ? ref2.user.presenter : void 0; return userIsLocked && publicChatIsDisabled && !presenter; }, - privateChatDisabled: function() { + privateChatDisabled: function () { let presenter, privateChatIsDisabled, ref, ref1, ref2, userIsLocked; userIsLocked = (ref = Meteor.Users.findOne({ - userId: getInSession('userId') + userId: getInSession('userId'), })) != null ? ref.user.locked : void 0; privateChatIsDisabled = (ref1 = Meteor.Meetings.findOne({})) != null ? ref1.roomLockSettings.disablePrivateChat : void 0; presenter = (ref2 = Meteor.Users.findOne({ - userId: getInSession('userId') + userId: getInSession('userId'), })) != null ? ref2.user.presenter : void 0; return userIsLocked && privateChatIsDisabled && !presenter; }, - getInputControls: function() { - if(this.props.inPrivateChat && this.privateChatDisabled() || !this.props.inPrivateChat && this.publicChatDisabled()){ + getInputControls: function () { + if (this.props.inPrivateChat && this.privateChatDisabled() || !this.props.inPrivateChat && this.publicChatDisabled()) { return ( - ); } else { return ( -
    - - +
    + +
    ); } }, - render(){ + render() { return ( -
    - { this.getInputControls() } +
    + { this.getInputControls() }
    ); - } + }, }); diff --git a/bigbluebutton-html5/imports/ui/chat/ChatMessage.jsx b/bigbluebutton-html5/imports/ui/chat/ChatMessage.jsx index 376be50c17..83353be83e 100755 --- a/bigbluebutton-html5/imports/ui/chat/ChatMessage.jsx +++ b/bigbluebutton-html5/imports/ui/chat/ChatMessage.jsx @@ -1,99 +1,102 @@ import React from 'react'; -export let ChatMessage = React.createClass({ - sanitizeAndFormat: function(str) { +export let ChatMessage = React.createClass({ + sanitizeAndFormat: function (str) { let res; - if(typeof str === 'string') { // First, replace replace all tags with the ascii equivalent (excluding those involved in anchor tags) + if (typeof str === 'string') { // First, replace replace all tags with the ascii equivalent (excluding those involved in anchor tags) res = str.replace(/&/g, '&').replace(/<(?![au\/])/g, '<').replace(/\/([^au])>/g, '$1>').replace(/([^=])"(?!>)/g, '$1"'); res = this.toClickable(res); return res = this.activateBreakLines(res); } }, - toClickable: function(str) { + toClickable: function (str) { let res; - if(typeof str === 'string') { + if (typeof str === 'string') { res = str.replace(/ - {this.toClockTime(this.props.message.message.from_time)} - + + {this.toClockTime(this.props.message.message.from_time)} + ); } else { return ( - + ); } }, - render(){ + render() { var messageColor = { color: colourToHex(this.props.message.message.from_color) }; - var floatLeft = {float: 'left'}; - function createMarkup(str) { return {__html: str}; }; + var floatLeft = { float: 'left' }; + function createMarkup(str) { return { __html: str }; }; + return ( -
  • - +
  • + {this.props.message.message.from_username ? - - {this.props.message.message.from_username} + + {this.props.message.message.from_username} - : null } - - {this.getTime()} -
    -
    -
    - {this.autoscroll()} + : null } +
    + {this.getTime()} +
    +
    +
    + {this.autoscroll()}
  • ); - } + }, }); diff --git a/bigbluebutton-html5/imports/ui/chat/PrivateChatToolBar.jsx b/bigbluebutton-html5/imports/ui/chat/PrivateChatToolBar.jsx index 9946b19cd4..34bbc480f7 100755 --- a/bigbluebutton-html5/imports/ui/chat/PrivateChatToolBar.jsx +++ b/bigbluebutton-html5/imports/ui/chat/PrivateChatToolBar.jsx @@ -2,25 +2,25 @@ import React from 'react'; import { Button } from '../shared/Button.jsx'; export let PrivateChatToolBar = React.createClass({ - componentDidMount: function() { - if(isLandscape() || isPortrait()) { - return $("#newMessageInput").focus(); + componentDidMount: function () { + if (isLandscape() || isPortrait()) { + return $('#newMessageInput').focus(); } }, - handleClick: function() { - console.log("I'm in the handleClick function"); + handleClick: function () { setInSession('inChatWith', 'PUBLIC_CHAT'); return setInSession('chats', getInSession('chats').map(chat => { - if(chat.userId === "PUBLIC_CHAT") { + if (chat.userId === 'PUBLIC_CHAT') { chat.gotMail = false; chat.number = 0; } + $('.ui-tooltip').hide(); return chat; })); }, - render(){ + render() { return (
    ); - } + }, }); diff --git a/bigbluebutton-html5/imports/ui/main/Header.jsx b/bigbluebutton-html5/imports/ui/main/Header.jsx index 16df2c6693..77b03816d2 100755 --- a/bigbluebutton-html5/imports/ui/main/Header.jsx +++ b/bigbluebutton-html5/imports/ui/main/Header.jsx @@ -6,7 +6,7 @@ export let Header = React.createClass({ getMeteorData() { let in_audio, whiteboard_title, in_listen_only, is_muted, is_talking; in_audio = BBB.amIInAudio(); - whiteboard_title = BBB.currentPresentationName() || "No active presentation"; + whiteboard_title = BBB.currentPresentationName() || 'No active presentation'; in_listen_only = BBB.amIListenOnlyAudio(); is_muted = BBB.amIMuted(); is_talking = BBB.amITalking(); @@ -22,72 +22,76 @@ export let Header = React.createClass({ handleLeaveAudioButton(event) { return exitVoiceCall(event); }, + handleMuteButton(event) { - $(".tooltip").hide(); + $('.tooltip').hide(); return toggleMic(this); }, handleToggleUserlistButton(event) { - if(isLandscape() || isLandscapeMobile()) { + if (isLandscape() || isLandscapeMobile()) { return toggleUsersList(); } else { - if($('.settingsMenu').hasClass('menuOut')) { + if ($('.settingsMenu').hasClass('menuOut')) { toggleSettingsMenu(); } else { toggleShield(); } + return toggleUserlistMenu(); } }, + handleToggleMenuButton(event) { - if($('.userlistMenu').hasClass('menuOut')) { + if ($('.userlistMenu').hasClass('menuOut')) { toggleUserlistMenu(); } else { toggleShield(); } + $('.toggleMenuButton').blur(); return toggleSettingsMenu(); }, - + handleSettingsButton(event) { - return $("#settingsModal").foundation('reveal', 'open'); + return $('#settingsModal').foundation('reveal', 'open'); }, handleSignOutButton(event) { $('.signOutIcon').blur(); - return $("#logoutModal").foundation('reveal', 'open'); + return $('#logoutModal').foundation('reveal', 'open'); }, render() { return ( -
    - : null } - - {this.data.whiteboard_title} - - -
    + : null } + + {this.data.whiteboard_title} + + +
    -
    + - ) - } + ); + }, }); diff --git a/bigbluebutton-html5/imports/ui/userlist/UserListItem.jsx b/bigbluebutton-html5/imports/ui/userlist/UserListItem.jsx index 2788c6156b..1a83d2a9bd 100755 --- a/bigbluebutton-html5/imports/ui/userlist/UserListItem.jsx +++ b/bigbluebutton-html5/imports/ui/userlist/UserListItem.jsx @@ -43,7 +43,7 @@ export let UserListItem = React.createClass({ const user = this.props.user; let statusIcons = []; - if(user.emoji !== 'none' && !user.isPresenter) { + if (user.emoji !== 'none' && !user.isPresenter) { statusIcons.push(( )); diff --git a/bigbluebutton-html5/imports/ui/whiteboard/EmojiContainer.jsx b/bigbluebutton-html5/imports/ui/whiteboard/EmojiContainer.jsx index f9577f907a..6a778c8107 100755 --- a/bigbluebutton-html5/imports/ui/whiteboard/EmojiContainer.jsx +++ b/bigbluebutton-html5/imports/ui/whiteboard/EmojiContainer.jsx @@ -2,23 +2,24 @@ import React from 'react'; import classNames from 'classnames'; import { Button } from '../shared/Button.jsx'; -export let EmojiContainer = React.createClass ({ +export let EmojiContainer = React.createClass({ mixins: [ReactMeteorData], getMeteorData() { let user, emoji_status, current_presentation; user = BBB.getCurrentUser(); - if(user != null) { + if (user != null) { emoji_status = user.user.emoji_status; } else { - emoji_status = "none"; + emoji_status = 'none'; } + current_presentation = Meteor.Presentations.findOne({ - 'presentation.current': true + 'presentation.current': true, }); current_presentation ? current_presentation = true : current_presentation = false; return { emoji_status: emoji_status, - current_presentation: current_presentation + current_presentation: current_presentation, }; }, @@ -28,17 +29,17 @@ export let EmojiContainer = React.createClass ({ emojiIcons() { return [ - { name: 'sad', icon: 'sad-face', title: ''}, - { name: 'happy', icon: 'happy-face', title: ''}, - { name: 'confused', icon: 'confused-face', title: ''}, - { name: 'neutral', icon: 'neutral-face', title: ''}, - { name: 'away', icon: 'clock', title: ''}, - { name: 'raiseHand', icon: 'hand', title: 'Lower your Hand'} + { name: 'sad', icon: 'sad-face', title: '' }, + { name: 'happy', icon: 'happy-face', title: '' }, + { name: 'confused', icon: 'confused-face', title: '' }, + { name: 'neutral', icon: 'neutral-face', title: '' }, + { name: 'away', icon: 'clock', title: '' }, + { name: 'raiseHand', icon: 'hand', title: 'Lower your Hand' }, ]; }, handleInactive(name, event) { - if($(event.target).css('opacity') === '1') { + if ($(event.target).css('opacity') === '1') { BBB.setEmojiStatus( BBB.getMeetingId(), getInSession('userId'), @@ -52,13 +53,13 @@ export let EmojiContainer = React.createClass ({ }, handleActive(event) { - if($('.activeEmojiButton').css('opacity') === '1') { + if ($('.activeEmojiButton').css('opacity') === '1') { BBB.setEmojiStatus( BBB.getMeetingId(), getInSession('userId'), getInSession('userId'), getInSession('authToken'), - "none" + 'none' ); $('.FABTriggerButton').blur(); return toggleEmojisFAB(); @@ -72,14 +73,14 @@ export let EmojiContainer = React.createClass ({ render() { return ( -
    -
    ); - } + }, }); diff --git a/bigbluebutton-html5/imports/ui/whiteboard/EmojisSVG.jsx b/bigbluebutton-html5/imports/ui/whiteboard/EmojisSVG.jsx index 0eb5185e01..905371a141 100755 --- a/bigbluebutton-html5/imports/ui/whiteboard/EmojisSVG.jsx +++ b/bigbluebutton-html5/imports/ui/whiteboard/EmojisSVG.jsx @@ -1,65 +1,59 @@ import React from 'react'; -export let EmojisSVG = React.createClass ({ +export let EmojisSVG = React.createClass({ render() { - if(this.props.emoji == "happy-face") { - return ( - - - - - + if (this.props.emoji == 'happy-face') { + return ( + + + + + ); - } - else if(this.props.emoji == "neutral-face") { + } else if (this.props.emoji == 'neutral-face') { return ( - - - - - + + + + + ); - } - else if(this.props.emoji == "confused-face") { - return( - - - - - - - ); - } - else if(this.props.emoji == "sad-face") { - return( - - - - - - - ); - } - else if(this.props.emoji == "clock") { + } else if (this.props.emoji == 'confused-face') { return ( - - - - + + + + + + + ); + } else if (this.props.emoji == 'sad-face') { + return ( + + + + + + + ); + } else if (this.props.emoji == 'clock') { + return ( + + + + ); - } - else if(this.props.emoji == "hand") { + } else if (this.props.emoji == 'hand') { return ( - - + + ); - } - else { + } else { console.log("This shouldn't be happening"); - return ( ); + return (); } - } + }, }); diff --git a/bigbluebutton-html5/imports/ui/whiteboard/Polling.jsx b/bigbluebutton-html5/imports/ui/whiteboard/Polling.jsx index 7a08a23bf0..13fdbb001e 100755 --- a/bigbluebutton-html5/imports/ui/whiteboard/Polling.jsx +++ b/bigbluebutton-html5/imports/ui/whiteboard/Polling.jsx @@ -8,47 +8,48 @@ export let Polling = React.createClass({ let poll; poll = BBB.getCurrentPoll(getInSession('userId')); return { - poll: poll + poll: poll, }; }, - - componentDidMount: function() { + + componentDidMount: function () { return scaleWhiteboard(); }, - componentWillUnmount: function() { + componentWillUnmount: function () { setTimeout(scaleWhiteboard, 0); }, getStyledAnswers(poll) { - let number, buttonStyle, answers; - if(poll != null) { + let number, buttonStyle, answers; + if (poll != null) { number = poll.poll_info.poll.answers.length; buttonStyle = { width: 'calc(75%/' + number + ')', marginLeft: 'calc(25%/' + number * 2 + ')', - marginRight: 'calc(25%/ ' + number * 2 + ')' + marginRight: 'calc(25%/ ' + number * 2 + ')', }; answers = poll.poll_info.poll.answers; - for(j = 0; j < number; j++) { + for (j = 0; j < number; j++) { answers[j].style = buttonStyle; } - return answers; + + return answers; } }, - handleClick: function(label, answer) { + handleClick: function (label, answer) { return BBB.sendPollResponseMessage(label, answer); }, - render(){ + render() { return ( -
    +
    {this.data.poll ? this.getStyledAnswers(this.data.poll).map((question) =>
    - ) - } + ); + }, }); diff --git a/bigbluebutton-html5/imports/ui/whiteboard/PresentationList.jsx b/bigbluebutton-html5/imports/ui/whiteboard/PresentationList.jsx index 8534088b79..66a9d7436c 100755 --- a/bigbluebutton-html5/imports/ui/whiteboard/PresentationList.jsx +++ b/bigbluebutton-html5/imports/ui/whiteboard/PresentationList.jsx @@ -2,44 +2,44 @@ import React from 'react'; import classNames from 'classnames'; export let PresentationList = React.createClass({ - handleShow(name){ + handleShow(name) { return console.info('Should show the file `' + name + '`'); }, - handleDelete(name){ + handleDelete(name) { return console.info('Should delete the file `' + name + '`'); }, render() { - return( -
      + return ( +
        {this.props.files ? this.props.files.map((file) => -
      • - - {file.name} - - - {file.percUploaded} - +
      • + + {file.name} + + + {file.percUploaded} +
      • ) - : null } - + : null } + {this.props.presentations ? this.props.presentations.map((presentation) => -
      • - - {presentation.name} - - +
      • + + {presentation.name} + + {presentation.current ? null : - } - - + } + +
      • ) - : null } + : null }
      ); - } + }, }); diff --git a/bigbluebutton-html5/imports/ui/whiteboard/Slide.jsx b/bigbluebutton-html5/imports/ui/whiteboard/Slide.jsx index 5351b37f70..81a48d0cc5 100755 --- a/bigbluebutton-html5/imports/ui/whiteboard/Slide.jsx +++ b/bigbluebutton-html5/imports/ui/whiteboard/Slide.jsx @@ -1,19 +1,19 @@ import React from 'react'; -this.scaleSlide = function(originalWidth, originalHeight) { +this.scaleSlide = function (originalWidth, originalHeight) { let adjustedHeight, adjustedWidth, boardHeight, boardWidth; // set the size of the whiteboard space (frame) where the slide will be displayed - if(window.matchMedia('(orientation: landscape)').matches) { + if (window.matchMedia('(orientation: landscape)').matches) { // for landscape orientation we want "fit to height" so that we can // minimize the empty space above and below the slide (for best readability) - boardWidth = $("#whiteboard-container").width(); - boardHeight = $("#whiteboard-container").height(); + boardWidth = $('#whiteboard-container').width(); + boardHeight = $('#whiteboard-container').height(); } else { // for portrait orientation we want "fit to width" so that we can // minimize the empty space on the sides of the slide (for best readability) - boardWidth = $("#whiteboard-container").width(); - boardHeight = 1.4 * $("#whiteboard-container").width(); + boardWidth = $('#whiteboard-container').width(); + boardHeight = 1.4 * $('#whiteboard-container').width(); } // this is the best fitting pair @@ -21,7 +21,7 @@ this.scaleSlide = function(originalWidth, originalHeight) { adjustedHeight = null; // the slide image is in portrait orientation - if(originalWidth <= originalHeight) { + if (originalWidth <= originalHeight) { adjustedWidth = boardHeight * originalWidth / originalHeight; if (boardWidth < adjustedWidth) { adjustedHeight = boardHeight * boardWidth / adjustedWidth; @@ -40,11 +40,12 @@ this.scaleSlide = function(originalWidth, originalHeight) { adjustedWidth = boardWidth; } } + return { width: adjustedWidth, height: adjustedHeight, boardWidth: boardWidth, - boardHeight: boardHeight + boardHeight: boardHeight, }; }; @@ -54,9 +55,9 @@ export let Slide = React.createClass({ let currentSlide, shapes, pointer; currentSlide = BBB.getCurrentSlide(); - if(currentSlide != null) { + if (currentSlide != null) { shapes = Meteor.Shapes.find({ - whiteboardId: currentSlide.slide.id + whiteboardId: currentSlide.slide.id, }).fetch(); } @@ -66,25 +67,27 @@ export let Slide = React.createClass({ }; }, - componentDidMount: function() { + componentDidMount: function () { //console.log('componentDidMount'); this.reactOnSlideChange(); }, - componentWillUpdate: function() { - if(typeof this.whiteboardPaperModel !== "undefined" && this.whiteboardPaperModel !== null) { + componentWillUpdate: function () { + if (typeof this.whiteboardPaperModel !== 'undefined' && this.whiteboardPaperModel !== null) { wpm = this.whiteboardPaperModel; wpm.clearShapes(); + //this.manuallyDisplayShapes(); } + //console.log('componentWillUpdate'); }, - componentDidUpdate: function() { + componentDidUpdate: function () { //console.log('componentDidUpdate'); - if(this.data.current_slide){ + if (this.data.current_slide) { this.reactOnSlideChange(); - if(this.data.shapes){ + if (this.data.shapes) { this.data.shapes.map((shape) => this.renderShape(shape)); } @@ -93,16 +96,16 @@ export let Slide = React.createClass({ } }, - componentWillUnmount: function() { + componentWillUnmount: function () { //console.log('componentWillUnmount'); }, - createWhiteboardPaper: function(callback) { + createWhiteboardPaper: function (callback) { this.whiteboardPaperModel = new Meteor.WhiteboardPaperModel('whiteboard-paper'); return callback(this.whiteboardPaperModel); }, - displaySlide: function(wpm) { + displaySlide: function (wpm) { let adjustedDimensions, currentSlide, ref; currentSlide = BBB.getCurrentSlide(); wpm.create(); @@ -118,102 +121,113 @@ export let Slide = React.createClass({ clearSlide() { let ref; + //clear the slide - if(typeof this.whiteboardPaperModel !== "undefined" && this.whiteboardPaperModel !== null) { + if (typeof this.whiteboardPaperModel !== 'undefined' && this.whiteboardPaperModel !== null) { this.whiteboardPaperModel.removeAllImagesFromPaper(); } + //hide the cursor - return typeof this.whiteboardPaperModel !== "undefined" && this.whiteboardPaperModel !== null ? (ref = this.whiteboardPaperModel.cursor) != null ? ref.remove() : void 0 : void 0; + return typeof this.whiteboardPaperModel !== 'undefined' && this.whiteboardPaperModel !== null ? (ref = this.whiteboardPaperModel.cursor) != null ? ref.remove() : void 0 : void 0; }, - manuallyDisplayShapes: function() { + manuallyDisplayShapes: function () { let currentSlide, i, j, len, len1, num, ref, ref1, ref2, results, s, shapeInfo, shapeType, shapes, wpm; - if(Meteor.WhiteboardCleanStatus.findOne({ - in_progress: true + if (Meteor.WhiteboardCleanStatus.findOne({ + in_progress: true, }) != null) { return; } + currentSlide = BBB.getCurrentSlide(); wpm = this.whiteboardPaperModel; shapes = Meteor.Shapes.find({ - whiteboardId: currentSlide != null ? (ref = currentSlide.slide) != null ? ref.id : void 0 : void 0 + whiteboardId: currentSlide != null ? (ref = currentSlide.slide) != null ? ref.id : void 0 : void 0, }).fetch(); results = []; - for(i = 0, len1 = shapes.length; i < len1; i++) { + for (i = 0, len1 = shapes.length; i < len1; i++) { s = shapes[i]; shapeInfo = ((ref1 = s.shape) != null ? ref1.shape : void 0) || (s != null ? s.shape : void 0); shapeType = shapeInfo != null ? shapeInfo.type : void 0; - if(shapeType !== "text") { + if (shapeType !== 'text') { len = shapeInfo.points.length; - for(num = j = 0, ref2 = len; 0 <= ref2 ? j <= ref2 : j >= ref2; num = 0 <= ref2 ? ++j : --j) { // the coordinates must be in the range 0 to 1 - if(shapeInfo != null) { + for (num = j = 0, ref2 = len; 0 <= ref2 ? j <= ref2 : j >= ref2; num = 0 <= ref2 ? ++j : --j) { // the coordinates must be in the range 0 to 1 + if (shapeInfo != null) { shapeInfo.points[num] = (shapeInfo != null ? shapeInfo.points[num] : void 0) / 100; } } } - if(wpm != null) { + + if (wpm != null) { wpm.makeShape(shapeType, shapeInfo); } + results.push(wpm != null ? wpm.updateShape(shapeType, shapeInfo) : void 0); } + return results; }, - reactOnSlideChange: function() { + reactOnSlideChange: function () { var _this = this; var currentSlide, pic, ref; - currentSlide = BBB.getCurrentSlide("slide.rendered"); + currentSlide = BBB.getCurrentSlide('slide.rendered'); pic = new Image(); - pic.onload = function() { + pic.onload = function () { var ref; setInSession('slideOriginalWidth', this.width); setInSession('slideOriginalHeight', this.height); - $(window).resize(function() { + $(window).resize(function () { if (!$('.panel-footer').hasClass('ui-resizable-resizing')) { scaleWhiteboard(_this.whiteboardPaperModel); } }); + if ((currentSlide != null ? (ref = currentSlide.slide) != null ? ref.img_uri : void 0 : void 0) != null) { - return _this.createWhiteboardPaper(function(wpm) { + return _this.createWhiteboardPaper(function (wpm) { return _this.displaySlide(wpm); }); } }; + pic.src = currentSlide != null ? (ref = currentSlide.slide) != null ? ref.img_uri : void 0 : void 0; - return ""; + return ''; }, updatePointerLocation(pointer) { - if(typeof this.whiteboardPaperModel !== "undefined" && this.whiteboardPaperModel !== null) { + if (typeof this.whiteboardPaperModel !== 'undefined' && this.whiteboardPaperModel !== null) { this.whiteboardPaperModel.moveCursor(pointer.x, pointer.y); } }, renderShape(data) { let i, len, num, ref, ref1, shapeInfo, shapeType, wpm; + // @data is the shape object coming from the {{#each}} in the html file shapeInfo = ((ref = data.shape) != null ? ref.shape : void 0) || data.shape; shapeType = shapeInfo != null ? shapeInfo.type : void 0; - if(shapeType !== "text") { + if (shapeType !== 'text') { len = shapeInfo.points.length; for (num = i = 0, ref1 = len; 0 <= ref1 ? i <= ref1 : i >= ref1; num = 0 <= ref1 ? ++i : --i) { // the coordinates must be in the range 0 to 1 shapeInfo.points[num] = shapeInfo.points[num] / 100; } } - if(typeof this.whiteboardPaperModel !== "undefined" && this.whiteboardPaperModel !== null) { + + if (typeof this.whiteboardPaperModel !== 'undefined' && this.whiteboardPaperModel !== null) { wpm = this.whiteboardPaperModel; - if(wpm != null) { + if (wpm != null) { wpm.makeShape(shapeType, shapeInfo); } + return wpm != null ? wpm.updateShape(shapeType, shapeInfo) : void 0; } }, render() { return ( -
      +
      ); - } + }, }); diff --git a/bigbluebutton-html5/imports/ui/whiteboard/UploaderControls.jsx b/bigbluebutton-html5/imports/ui/whiteboard/UploaderControls.jsx index 1c4badaf5e..1174e9d2e0 100755 --- a/bigbluebutton-html5/imports/ui/whiteboard/UploaderControls.jsx +++ b/bigbluebutton-html5/imports/ui/whiteboard/UploaderControls.jsx @@ -3,8 +3,8 @@ import classNames from 'classnames'; import { Button } from '../shared/Button.jsx'; import { PresentationList } from './PresentationList.jsx'; -export let UploaderControls = React.createClass ({ - getDefaultProps: function() { +export let UploaderControls = React.createClass({ + getDefaultProps: function () { return { isOpen: new ReactiveVar(false), files: new ReactiveList({ @@ -13,25 +13,25 @@ export let UploaderControls = React.createClass ({ let ref, ref1; return (ref = a.isUploading === b.isUploading) != null ? ref : { 0: (ref1 = a.isUploading) != null ? ref1 : -{ - 1: 1 - } + 1: 1, + }, }; - } + }, }), }; }, - + mixins: [ReactMeteorData], getMeteorData() { let presentations; presentations = Meteor.Presentations.find({}, { sort: { 'presentation.current': -1, - 'presentation.name': 1 + 'presentation.name': 1, }, fields: { - 'presentation': 1 - } + presentation: 1, + }, }).fetch(); return { @@ -39,32 +39,35 @@ export let UploaderControls = React.createClass ({ }; }, - fakeUpload (file, list) { + fakeUpload(file, list) { return setTimeout((() => { file.uploadedSize = file.uploadedSize + (Math.floor(Math.random() * file.size + file.uploadedSize) / 10); - file.percUploaded = Math.round((file.uploadedSize / file.size) * 100) + "%"; + file.percUploaded = Math.round((file.uploadedSize / file.size) * 100) + '%'; if (!(file.size > file.uploadedSize)) { file.uploadedSize = file.size; file.isUploading = false; } + list.update(file.name, file); this.forceUpdate(); - if(file.isUploading === true) { + if (file.isUploading === true) { return this.fakeUpload(file, list); } else { list.remove(file.name); // TODO: Here we should remove and update te presentation on mongo this.forceUpdate(); - return + return; } }), 200); }, - + isOpen() { - return this.props.isOpen.get() ? "is-open" : "" + return this.props.isOpen.get() ? 'is-open' : ''; }, + files() { return this.props.files ? this.props.files.fetch() : null; }, + presentations() { return this.data.presentations.map(x => { return x.presentation; @@ -78,7 +81,7 @@ export let UploaderControls = React.createClass ({ return _.each(files, file => { file.isUploading = true; file.uploadedSize = 0; - file.percUploaded = "0"; + file.percUploaded = '0'; this.props.files.insert(file.name, file); return this.fakeUpload(file, this.props.files); }); @@ -106,23 +109,23 @@ export let UploaderControls = React.createClass ({ render() { return ( -
      -
      - -
      - - - Drop files here
      or click to upload
      -
      -
      -
      +
      - ) - } + ); + }, }); diff --git a/bigbluebutton-html5/imports/ui/whiteboard/Whiteboard.jsx b/bigbluebutton-html5/imports/ui/whiteboard/Whiteboard.jsx index 9408a12f5d..0627e3b15d 100755 --- a/bigbluebutton-html5/imports/ui/whiteboard/Whiteboard.jsx +++ b/bigbluebutton-html5/imports/ui/whiteboard/Whiteboard.jsx @@ -6,33 +6,33 @@ import { Polling } from './Polling.jsx'; import { Button } from '../shared/Button.jsx'; import { WhiteboardControls } from './WhiteboardControls.jsx'; - export let Whiteboard = React.createClass({ mixins: [ReactMeteorData], getMeteorData() { let poll_started, is_presenter, is_mobile, whiteboard_size; - if(BBB.isPollGoing(getInSession('userId'))) { + if (BBB.isPollGoing(getInSession('userId'))) { poll_started = true; } else { poll_started = false; } - if(BBB.isUserPresenter(getInSession('userId'))) { + if (BBB.isUserPresenter(getInSession('userId'))) { is_presenter = true; } else { is_presenter = false; } is_mobile = isMobile(); - if(BBB.isUserPresenter(getInSession('userId'))) { + if (BBB.isUserPresenter(getInSession('userId'))) { whiteboard_size = 'presenter-whiteboard'; } else { - if(BBB.isPollGoing(getInSession('userId'))) { - whiteboard_size = 'poll-whiteboard'; - } else { - whiteboard_size = 'viewer-whiteboard'; + if (BBB.isPollGoing(getInSession('userId'))) { + whiteboard_size = 'poll-whiteboard'; + } else { + whiteboard_size = 'viewer-whiteboard'; + } } - } + return { whiteboard_size: whiteboard_size, is_mobile: is_mobile, @@ -42,7 +42,7 @@ export let Whiteboard = React.createClass({ }, isPollStarted() { - if(BBB.isPollGoing(getInSession('userId'))) { + if (BBB.isPollGoing(getInSession('userId'))) { return true; } else { return false; @@ -56,17 +56,19 @@ export let Whiteboard = React.createClass({ resize() { return adjustChatInputHeight(); }, + start() { - if($('#chat').width() / $('#panels').width() > 0.2) { // chat shrinking can't make it smaller than one fifth of the whiteboard-chat area + if ($('#chat').width() / $('#panels').width() > 0.2) { // chat shrinking can't make it smaller than one fifth of the whiteboard-chat area return $('#whiteboard').resizable('option', 'maxWidth', $('#panels').width() - 200); // gives the chat enough space (200px) } else { return $('#whiteboard').resizable('option', 'maxWidth', $('#whiteboard').width()); } }, + stop() { $('#whiteboard').css('width', `${100 * $('#whiteboard').width() / $('#panels').width()}%`); // transforms width to % return $('#whiteboard').resizable('option', 'maxWidth', null); - } + }, }); // whiteboard element needs to be available @@ -74,23 +76,23 @@ export let Whiteboard = React.createClass({ return $(document).foundation(); // initialize foundation javascript }, - + handleWhiteboardFullScreen() { return enterWhiteboardFullscreen(); }, handleExitFullScreen() { - if(document.exitFullscreen) { + if (document.exitFullscreen) { return document.exitFullscreen(); - } else if(document.mozCancelFullScreen) { + } else if (document.mozCancelFullScreen) { return document.mozCancelFullScreen(); - } else if(document.webkitExitFullscreen) { + } else if (document.webkitExitFullscreen) { return document.webkitExitFullscreen(); } }, isFullScreen() { - if($( ".fullscreenButton" ).hasClass( "exitFullscreenButton" )) { + if ($('.fullscreenButton').hasClass('exitFullscreenButton')) { return true; } else { return false; @@ -99,23 +101,23 @@ export let Whiteboard = React.createClass({ render() { return ( -
      -
      - - +
      +
      + + {this.data.is_mobile ?
      -
      + : null } +
      +
      {this.data.is_presenter ? - : null } + : null } {this.data.poll_started ? - : null } -
      + : null } +
      ); - } + }, }); diff --git a/bigbluebutton-html5/imports/ui/whiteboard/WhiteboardControls.jsx b/bigbluebutton-html5/imports/ui/whiteboard/WhiteboardControls.jsx index 19576aafea..24cdced41a 100755 --- a/bigbluebutton-html5/imports/ui/whiteboard/WhiteboardControls.jsx +++ b/bigbluebutton-html5/imports/ui/whiteboard/WhiteboardControls.jsx @@ -2,32 +2,33 @@ import React from 'react'; import { Button } from '../shared/Button.jsx'; import { UploaderControls } from './UploaderControls.jsx'; - -export let WhiteboardControls = React.createClass ({ +export let WhiteboardControls = React.createClass({ mixins: [ReactMeteorData], getMeteorData() { let currentPresentation, currentSlide, currentSlideNum, ref, ref1, totalSlideNum; currentSlideNum = 0; totalSlideNum = 0; currentPresentation = Meteor.Presentations.findOne({ - 'presentation.current': true + 'presentation.current': true, }); - if(currentPresentation != null) { + if (currentPresentation != null) { currentSlide = Meteor.Slides.findOne({ - 'presentationId': currentPresentation.presentation.id, - 'slide.current': true - }) - if(currentSlide != null) { + presentationId: currentPresentation.presentation.id, + 'slide.current': true, + }); + if (currentSlide != null) { currentSlideNum = currentSlide.slide.num; } - totalSlides = Meteor.Slides.find({ 'presentationId': currentPresentation.presentation.id }); - if(totalSlides != null) { + + totalSlides = Meteor.Slides.find({ presentationId: currentPresentation.presentation.id }); + if (totalSlides != null) { totalSlideNum = totalSlides.count(); } } + return { currentSlideNum: currentSlideNum, - totalSlideNum: totalSlideNum + totalSlideNum: totalSlideNum, }; }, @@ -35,7 +36,7 @@ export let WhiteboardControls = React.createClass ({ setTimeout(scaleWhiteboard, 0); }, - componentWillUnmount () { + componentWillUnmount() { setTimeout(scaleWhiteboard, 0); }, @@ -49,26 +50,26 @@ export let WhiteboardControls = React.createClass ({ render() { return ( -
      -
      +
      +
      {/* TODO: Adjust the presenter uploader for mobile views on iOS devices you cant upload PDFs, only images from camera/gallery */ - !isMobile() ? + !isMobile() ? - : null } -
      -
      -
      -
      -
      -
      -
      + : null } +
      +
      +
      +
      +
      +
      +
      - ) - } + ); + }, }); diff --git a/bigbluebutton-html5/server/collection_methods/shapes.js b/bigbluebutton-html5/server/collection_methods/shapes.js index 0a23864594..d2cfeb417c 100755 --- a/bigbluebutton-html5/server/collection_methods/shapes.js +++ b/bigbluebutton-html5/server/collection_methods/shapes.js @@ -45,20 +45,20 @@ this.addShapeToCollection = function (meetingId, whiteboardId, shapeObject) { // the mouse button was released - the drawing is complete // TODO: pencil messages currently don't send draw_end and are labeled all as DRAW_START - } else if(shapeObject != null && (shapeObject.status === "DRAW_START" || shapeObject.status === "DRAW_UPDATE" || shapeObject.status === "DRAW_END")) { - shape = Meteor.Shapes.findOne({ - "shape.id": shapeObject.shape.id + } else if (shapeObject != null && (shapeObject.status === 'DRAW_START' || shapeObject.status === 'DRAW_UPDATE' || shapeObject.status === 'DRAW_END')) { + shape = Meteor.Shapes.findOne({ + 'shape.id': shapeObject.shape.id, }); - if(shape != null) { - return id = Meteor.Shapes.update({ - "shape.id": shapeObject.shape.id + if (shape != null) { + return id = Meteor.Shapes.update({ + 'shape.id': shapeObject.shape.id, }, { $set: { - "shape.shape.points": shapeObject.shape.points - } + 'shape.shape.points': shapeObject.shape.points, + }, }); - } else { - entry = { + } else { + entry = { meetingId: meetingId, whiteboardId: whiteboardId, shape: { @@ -83,8 +83,8 @@ this.addShapeToCollection = function (meetingId, whiteboardId, shapeObject) { }, }; return id = Meteor.Shapes.insert(entry); - } } + } }; this.removeAllShapesFromSlide = function (meetingId, whiteboardId) { diff --git a/bigbluebutton-html5/server/redispubsub.js b/bigbluebutton-html5/server/redispubsub.js index 7c9b0b4c78..9429d8ba87 100755 --- a/bigbluebutton-html5/server/redispubsub.js +++ b/bigbluebutton-html5/server/redispubsub.js @@ -65,8 +65,8 @@ Meteor.RedisPubSub = (function () { let eventName, message, messagesWeIgnore; message = JSON.parse(jsonMsg); eventName = message.header.name; - messagesWeIgnore = ["BbbPubSubPongMessage", "bbb_apps_is_alive_message", "broadcast_layout_message"]; - if(indexOf.call(messagesWeIgnore, eventName) < 0) { + messagesWeIgnore = ['BbbPubSubPongMessage', 'bbb_apps_is_alive_message', 'broadcast_layout_message']; + if (indexOf.call(messagesWeIgnore, eventName) < 0) { // Uncomment for DEVELOPMENT purposes only // Otherwise dynamic shapes' updates will slow down significantly // Meteor.log.info(`Q ${eventName} ${Meteor.myQueue.total()}`); diff --git a/bigbluebutton-html5/server/server.js b/bigbluebutton-html5/server/server.js index 776b1698ab..4d45a0cff2 100755 --- a/bigbluebutton-html5/server/server.js +++ b/bigbluebutton-html5/server/server.js @@ -45,6 +45,7 @@ Meteor.startup(() => { return ''; } }; + // Uncomment for DEVELOPMENT purposes only // Otherwise dynamic shapes' updates will slow down significantly //Meteor.log.info(`in callback after handleRedisMessage ${eventName}. ${lengthString()}`); @@ -107,7 +108,8 @@ Meteor.startup(() => { Meteor.log.error('ERROR!! No header or payload'); callback(); } - if(eventName, indexOf.call(notLoggedEventTypes, eventName) < 0) { + + if (eventName, indexOf.call(notLoggedEventTypes, eventName) < 0) { // Uncomment for DEVELOPMENT purposes only // Otherwise dynamic shapes' updates will slow down significantly /* @@ -659,7 +661,7 @@ Meteor.startup(() => { if (indexOf.call(notLoggedEventTypes, eventName) < 0) { Meteor.log.info(`WARNING!!! THE JSON MESSAGE WAS NOT OF TYPE SUPPORTED BY THIS APPLICATION ${eventName} - {JSON.stringify(message)}` ); + {JSON.stringify(message)}`); } return callback();