diff --git a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/bus/ReceivedJsonMsgHdlrActor.scala b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/bus/ReceivedJsonMsgHdlrActor.scala
index d3c3523499f1ce3a915d10bb4450cdf0c5f4c278..e4fac4ee47cce79b91ecdeda420fc8f99d64d4cc 100755
--- a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/bus/ReceivedJsonMsgHdlrActor.scala
+++ b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/bus/ReceivedJsonMsgHdlrActor.scala
@@ -67,6 +67,10 @@ class ReceivedJsonMsgHdlrActor(val msgFromAkkaAppsEventBus: MsgFromAkkaAppsEvent
         route[CheckAlivePongSysMsg](envelope, jsonNode)
       case UserEmojiChangedEvtMsg.NAME =>
         route[UserEmojiChangedEvtMsg](envelope, jsonNode)
+      case PresenterUnassignedEvtMsg.NAME =>
+        route[PresenterUnassignedEvtMsg](envelope, jsonNode)
+      case PresenterAssignedEvtMsg.NAME =>
+        route[PresenterAssignedEvtMsg](envelope, jsonNode)
       case UserJoinedMeetingEvtMsg.NAME =>
         route[UserJoinedMeetingEvtMsg](envelope, jsonNode)
       case UserLeftMeetingEvtMsg.NAME =>
diff --git a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/meeting/OldMeetingMsgHdlrActor.scala b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/meeting/OldMeetingMsgHdlrActor.scala
index 69083fb43661231062c42d6416bd89b3dec616b9..0c8148fe1620a63d02eeae2e8d00274c8e5284b7 100755
--- a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/meeting/OldMeetingMsgHdlrActor.scala
+++ b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/meeting/OldMeetingMsgHdlrActor.scala
@@ -26,6 +26,8 @@ class OldMeetingMsgHdlrActor(val olgMsgGW: OldMessageReceivedGW)
       case m: MeetingDestroyedEvtMsg => handleMeetingDestroyedEvtMsg(m)
       case m: CheckAlivePongSysMsg => handleCheckAlivePongSysMsg(m)
       case m: UserEmojiChangedEvtMsg => handleUserEmojiChangedEvtMsg(m)
+      case m: PresenterUnassignedEvtMsg => handlePresenterUnassignedEvtMsg(m)
+      case m: PresenterAssignedEvtMsg => handlePresenterAssignedEvtMsg(m)
       case m: UserJoinedMeetingEvtMsg => handleUserJoinedMeetingEvtMsg(m)
       case m: UserLeftMeetingEvtMsg => handleUserLeftMeetingEvtMsg(m)
       case m: UserJoinedVoiceConfToClientEvtMsg => handleUserJoinedVoiceConfToClientEvtMsg(m)
@@ -76,6 +78,14 @@ class OldMeetingMsgHdlrActor(val olgMsgGW: OldMessageReceivedGW)
 
   }
 
+  def handlePresenterUnassignedEvtMsg(msg: PresenterUnassignedEvtMsg): Unit = {
+    olgMsgGW.handle(new UserStatusChanged(msg.header.meetingId, msg.body.intId, "presenter", "false"))
+  }
+
+  def handlePresenterAssignedEvtMsg(msg: PresenterAssignedEvtMsg): Unit = {
+    olgMsgGW.handle(new UserStatusChanged(msg.header.meetingId, msg.body.presenterId, "presenter", "true"))
+  }
+
   def handleUserEmojiChangedEvtMsg(msg: UserEmojiChangedEvtMsg): Unit = {
   //listener.handle(new UserStatusChanged(meetingId, userid, status, value))
   }
diff --git a/bigbluebutton-client/branding/default/style/css/V2Theme.css b/bigbluebutton-client/branding/default/style/css/V2Theme.css
index 72420e9da87306c377e789183ec1e266ad3f196b..2336294da2ee38df1d6c791cd1159383e4bbdabe 100755
--- a/bigbluebutton-client/branding/default/style/css/V2Theme.css
+++ b/bigbluebutton-client/branding/default/style/css/V2Theme.css
@@ -250,6 +250,16 @@ phonecomponents|MuteMeButton {
 	iconColorDown   : #FFFFFF;
 }
 
+.mainActionButton, .cameraDisplaySettingsWindowStartBtn {
+	borderThickness   : 0;
+	color             : #FFFFFF;
+	fillColorUp       : #1070D7;
+	fillColorOver     : #0A5EAC;
+	fillColorDown     : #1070D7;
+	textRollOverColor : #FFFFFF;
+	textSelectedColor : #FFFFFF;
+}
+
 .voiceConfDefaultButtonStyle {
 	icon         : Embed(source="assets/swf/v2_skin.swf", symbol="Icon_Audio");
 	disabledIcon : Embed(source="assets/swf/v2_skin.swf", symbol="Icon_Audio_Disabled");
@@ -1227,6 +1237,12 @@ mx|Panel {
 	color : #2A2D33;
 }
 
+.pollVoteLabel {
+	textAlign  : center;
+	fontSize   : 16;
+	fontWeight : bold;
+}
+
 .presentationFilesList {
 	paddingBottom : 5;
 	paddingLeft   : 5;
@@ -1289,6 +1305,19 @@ poll|PollResultsModal {
 	fontSize : 14;
 }
 
+.pollHintBoxStyle {
+	horizontalAlign : center;
+	verticalAlign   : middle;
+	backgroundColor : #CDD4DB;
+	paddingLeft     : 10;
+	paddingRight    : 10;
+}
+
+.pollHintTextStyle {
+	textAlign  : center;
+	fontWeight : bold;
+}
+
 /*
 //------------------------------
 //  ProgressBar
@@ -1678,7 +1707,7 @@ videoconf|UserGraphicHolder {
 }
 
 .cameraDisplaySettingsWindowStartBtn {
-	icon         : Embed(source="assets/swf/v2_skin.swf", symbol="Icon_Webcam");
+	icon         : Embed(source="assets/swf/v2_skin.swf", symbol="Icon_Webcam_On");
 	disabledIcon : Embed(source="assets/swf/v2_skin.swf", symbol="Icon_Webcam_Disabled");
 }
 
diff --git a/bigbluebutton-client/build.xml b/bigbluebutton-client/build.xml
index 0f3c3e15495dd06837046c690a570f915c06eb15..49afe82cf197a7a0e7d9255be4b33bade178157e 100755
--- a/bigbluebutton-client/build.xml
+++ b/bigbluebutton-client/build.xml
@@ -126,6 +126,10 @@
 		</sequential>
 	</target>
 
+	<target name="locale">
+		<compileLocale locale="${LOCALE}" />
+	</target>
+
 	<target name="localize">
 		<compileLocale locale="${LOCALE}" />
 	</target>
diff --git a/bigbluebutton-client/locale/en_US/bbbResources.properties b/bigbluebutton-client/locale/en_US/bbbResources.properties
index e85a5449b1807d6811371b859a67ecbe74d24bbb..798b33cd7963d34ba27bffd7ef468c4240505352 100755
--- a/bigbluebutton-client/locale/en_US/bbbResources.properties
+++ b/bigbluebutton-client/locale/en_US/bbbResources.properties
@@ -246,6 +246,7 @@ bbb.presentation.fitToWidth.toolTip = Fit Presentation To Width
 bbb.presentation.fitToPage.toolTip = Fit Presentation To Page
 bbb.presentation.uploadPresBtn.toolTip = Upload Presentation
 bbb.presentation.downloadPresBtn.toolTip = Download Presentations
+bbb.presentation.poll.response = Response to poll
 bbb.presentation.backBtn.toolTip = Previous slide
 bbb.presentation.btnSlideNum.accessibilityName = Slide {0} of {1}
 bbb.presentation.btnSlideNum.toolTip = Select a slide
@@ -755,6 +756,7 @@ bbb.polling.publishButton.label = Publish
 bbb.polling.closeButton.label = Close
 bbb.polling.customPollOption.label = Custom Poll...
 bbb.polling.pollModal.title = Live Poll Results
+bbb.polling.pollModal.hint = Leave this window open to allow students to respond to the poll. Selecting the Publish or Close button will end the poll.
 bbb.polling.customChoices.title = Enter Polling Choices
 bbb.polling.respondersLabel.novotes = Waiting for responses
 bbb.polling.respondersLabel.text = {0} Users Responded
@@ -815,6 +817,7 @@ bbb.lockSettings.lockOnJoin=Lock On Join
 
 bbb.users.breakout.breakoutRooms = Breakout Rooms
 bbb.users.breakout.updateBreakoutRooms = Update Breakout Rooms
+bbb.users.breakout.timerForRoom.toolTip = Time left for this breakout room
 bbb.users.breakout.timer.toolTip = Time left for breakout rooms
 bbb.users.breakout.calculatingRemainingTime = Calculating remaining time...
 bbb.users.breakout.closing = Closing
diff --git a/bigbluebutton-client/locale/zh_TW/bbbResources.properties b/bigbluebutton-client/locale/zh_TW/bbbResources.properties
index 24b91e29afe53b83fc19b667d65ebf4696a4f64d..1db7f5d3e27d087bddaf2f25c729b1067e58a58d 100644
--- a/bigbluebutton-client/locale/zh_TW/bbbResources.properties
+++ b/bigbluebutton-client/locale/zh_TW/bbbResources.properties
@@ -645,7 +645,7 @@ bbb.shortcuthelp.dropdown.users = 用戶相關快捷鍵
 bbb.shortcuthelp.dropdown.caption = Closed Caption shortcuts
 bbb.shortcuthelp.browserWarning.text = The full list of shortcuts are only supported in Internet Explorer.
 bbb.shortcuthelp.headers.shortcut = 快捷鍵
-bbb.shortcuthelp.headers.function = 功能\
+bbb.shortcuthelp.headers.function = 功能
 
 bbb.shortcutkey.general.minimize = 189
 bbb.shortcutkey.general.minimize.function = 最小化當前視窗
diff --git a/bigbluebutton-client/resources/config.xml.template b/bigbluebutton-client/resources/config.xml.template
index a0881070970d58d3671b0f6781a82fabacad7b2a..80dfc6256446995c4b788d7079ecafbbe94bd9f0 100755
--- a/bigbluebutton-client/resources/config.xml.template
+++ b/bigbluebutton-client/resources/config.xml.template
@@ -40,6 +40,7 @@
 			enableEmojiStatus="true"
 			enableSettingsButton="true"
 			enableGuestUI="false"
+			moderatorUnmute="true"
 			baseTabIndex="301"
 		/>
 
diff --git a/bigbluebutton-client/resources/prod/BigBlueButton.html b/bigbluebutton-client/resources/prod/BigBlueButton.html
index bc6a6c37ee7f7ebcd84f37dd211d4b29e93fa1a6..15a8c952d1c11d41806e92b88b59900173be631d 100755
--- a/bigbluebutton-client/resources/prod/BigBlueButton.html
+++ b/bigbluebutton-client/resources/prod/BigBlueButton.html
@@ -164,7 +164,7 @@
     </script>
     <script type="text/javascript">
       window.onload = function() {
-        var checkRequest = $.ajax({
+        let checkRequest = $.ajax({
            dataType: 'json',
            url: '/html5client/check'
         });
@@ -178,35 +178,8 @@
       };
 
       function html5() {
-        // no Flash detected on the client
-        var originalPath, enterRequest, authToken, meetingId, userId;
-        originalPath = document.location.pathname;
-
-        // use the enter api to detect the meetingid, userid and authToken
-        // and reuse them to join via the HTML5 client
-        enterRequest = $.ajax({
-           dataType: 'json',
-           url: '/bigbluebutton/api/enter' + document.location.search
-        });
-
-        enterRequest.done(function(enterData) {
-          meetingId = enterData.response.meetingID;
-          userId = enterData.response.externUserID;
-          authToken = enterData.response.authToken;
-
-          if ((meetingId != null) && (userId != null) && (authToken != null)) {
-            // redirect to the html5 client with the received info
-            // format <IP>/html5client/<meetingId>/<userId>/<authToken>
-            document.location.pathname = "/html5client/join/"+meetingId+"/"+userId+"/"+authToken;
-          } else {
-            // go back to the redirection page
-            document.location.pathname = originalPath;
-          }
-        });
-
-        enterRequest.fail(function(enterData, textStatus, errorThrown){
-          BBBLog.debug("Enter request failed");
-        });
+        // Navigate to HTML5 login
+        document.location.pathname = "/html5client/join";
       }
     </script>
   </head>
diff --git a/bigbluebutton-client/src/org/bigbluebutton/core/model/users/VoiceUsers2x.as b/bigbluebutton-client/src/org/bigbluebutton/core/model/users/VoiceUsers2x.as
index 514a75d6e1bd8520ac182c57311a457b3c8b268d..a16e6241eedd95f452036b72fc28d27f3105985d 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/core/model/users/VoiceUsers2x.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/core/model/users/VoiceUsers2x.as
@@ -7,8 +7,14 @@ package org.bigbluebutton.core.model.users
     
     private var _users:ArrayCollection = new ArrayCollection();
     
-    public function add(user: VoiceUser2x):void {
-      _users.addItem(user);
+    public function add(nuser: VoiceUser2x):void {
+      var index:int = getIndex(nuser.intId);
+      if (index != -1) {
+        // replace this user with the new user
+        _users.setItemAt(nuser, index);
+      } else {
+        _users.addItem(nuser);
+      }
     }
     
     public function remove(userId: String):VoiceUser2x {
@@ -59,7 +65,7 @@ package org.bigbluebutton.core.model.users
       
       return -1;
     }
-       
+    
     public function getVoiceOnlyUsers():Array {
       var temp: Array = new Array();
       for (var i:int = 0; i < _users.length; i++) {
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/model/options/HelpOptions.as b/bigbluebutton-client/src/org/bigbluebutton/main/model/options/HelpOptions.as
old mode 100644
new mode 100755
index 9bb905e61bbbf2adcc10e021de0b2b15d9fbb959..fd76e5b72b8d0474e647aedea3051a4c00f3ae0f
--- a/bigbluebutton-client/src/org/bigbluebutton/main/model/options/HelpOptions.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/model/options/HelpOptions.as
@@ -22,7 +22,7 @@ package org.bigbluebutton.main.model.options {
 	public class HelpOptions extends Options {
 
 		[Bindable]
-		public var url:String = "";
+		public var url:String = "http://www.bigbluebutton.org/content/videos";
 
 		public function HelpOptions() {
 			name = "help";
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/views/BBBSettings.mxml b/bigbluebutton-client/src/org/bigbluebutton/main/views/BBBSettings.mxml
index 3fb67b2d8389383e7263e09c8c38d5ac5ed9bef2..ef9fc85597cad67749505ce61f05ce6a43d2827e 100644
--- a/bigbluebutton-client/src/org/bigbluebutton/main/views/BBBSettings.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/views/BBBSettings.mxml
@@ -54,7 +54,7 @@
 	<mx:VBox id="addedComponents" paddingTop="12" height="100%" />
 
 	<mx:ControlBar width="100%" horizontalAlign="right">
-		<mx:Button id="okBtn" label="{ResourceUtil.getInstance().getString('bbb.settings.ok')}" click="onOkClicked()"/>
+		<mx:Button id="okBtn" styleName="mainActionButton" label="{ResourceUtil.getInstance().getString('bbb.settings.ok')}" click="onOkClicked()"/>
 		<mx:Button id="cancelBtn" label="{ResourceUtil.getInstance().getString('bbb.settings.cancel')}" click="onCancelClicked()"/>
 	</mx:ControlBar>
 </mx:TitleWindow>
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/views/FlashMicSettings.mxml b/bigbluebutton-client/src/org/bigbluebutton/main/views/FlashMicSettings.mxml
old mode 100644
new mode 100755
index 33699919a028ad68c4be3a19ece89d47b8b75099..f9b180daa6514a71a2a836310ac903babb6ab473
--- a/bigbluebutton-client/src/org/bigbluebutton/main/views/FlashMicSettings.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/views/FlashMicSettings.mxml
@@ -290,13 +290,10 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 				var currentSlider:Slider=Slider(event.currentTarget);
 				mic.gain = currentSlider.value
 			}
-			
-			private var DEFAULT_HELP_URL:String = "http://www.bigbluebutton.org/content/videos";			
       
 			private function onHelpButtonClicked():void {
 				var helpOptions : HelpOptions = Options.getOptions(HelpOptions) as HelpOptions;
-				DEFAULT_HELP_URL =  helpOptions.url;
-				navigateToURL(new URLRequest(DEFAULT_HELP_URL));
+				navigateToURL(new URLRequest(helpOptions.url));
 			}
      
       private function yesButtonClicked():void {
@@ -388,6 +385,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 									  styleName="micSettingsWindowSpeakIntoMicLabelStyle" />
 				<mx:Button id="yesButton" label="{ResourceUtil.getInstance().getString('bbb.micSettings.echoTestAudioYes')}" 
 						   click="yesButtonClicked()"
+						   styleName="mainActionButton"
 						   toolTip=""/>
 				<mx:Button id="noButton" label="{ResourceUtil.getInstance().getString('bbb.micSettings.echoTestAudioNo')}" 
 						   click="noButtonClicked()" 
@@ -438,6 +436,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
         <mx:HBox width="100%" horizontalAlign="right" horizontalGap="18" paddingTop="10">
           <mx:Button id="echoTestButton" label="{ResourceUtil.getInstance().getString('bbb.micSettings.nextButton')}" 
                  click="echoTestButtonClickHandler()"
+				 styleName="mainActionButton"
                  toolTip="{ResourceUtil.getInstance().getString('bbb.micSettings.nextButton.toolTip')}"/>
           <mx:Button id="playButton" label="{ResourceUtil.getInstance().getString('bbb.micSettings.playSound')}" 
                  click="playButtonClickHandler()" toggle="true"
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/views/LockSettings.mxml b/bigbluebutton-client/src/org/bigbluebutton/main/views/LockSettings.mxml
index 5c71250e4f27fe0e113785e2d0ebc43fac9864ac..cba5732e212519d275465df4cc0a217e15491978 100644
--- a/bigbluebutton-client/src/org/bigbluebutton/main/views/LockSettings.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/views/LockSettings.mxml
@@ -141,7 +141,8 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 		</mx:HBox>
 		
 		<mx:HBox width="100%" horizontalAlign="right" horizontalGap="18" paddingTop="20">
-			<mx:Button id="saveBtn" label="{ResourceUtil.getInstance().getString('bbb.lockSettings.save')}" 
+			<mx:Button id="saveBtn" label="{ResourceUtil.getInstance().getString('bbb.lockSettings.save')}"
+					   styleName="mainActionButton"
 					   click="onSaveClicked()"
 					   toolTip="{ResourceUtil.getInstance().getString('bbb.lockSettings.save.tooltip')}"/>
 			
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/views/LoggedOutWindow.mxml b/bigbluebutton-client/src/org/bigbluebutton/main/views/LoggedOutWindow.mxml
index 0fbf395e636970c051ac7b421b832631dd28983b..82d3ae20890b63350c07da17290c672329793505 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/main/views/LoggedOutWindow.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/views/LoggedOutWindow.mxml
@@ -132,6 +132,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 	</fx:Script>
 	<mx:VBox width="100%" height="100%" horizontalAlign="center">
 		<mx:Text text="{message}" textAlign="center"/>
-		<mx:Button id="okBtn" label="{ResourceUtil.getInstance().getString('bbb.logout.button.label')}" click="callSignOut()"/>
+		<mx:Button id="okBtn" styleName="mainActionButton" label="{ResourceUtil.getInstance().getString('bbb.logout.button.label')}" click="callSignOut()"/>
 	</mx:VBox>
 </mx:TitleWindow> 
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/views/MainApplicationShell.mxml b/bigbluebutton-client/src/org/bigbluebutton/main/views/MainApplicationShell.mxml
index 2383fdee806a0c1d7a766a442c7bd4c667097c9c..1937c3316856163391d0784e88882a375bc59c64 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/main/views/MainApplicationShell.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/views/MainApplicationShell.mxml
@@ -808,7 +808,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 
 			private function updateToolbarHeight():void {
 				if (toolbarHeight != 0) {
-					toolbarHeight = Math.max(DEFAULT_TOOLBAR_HEIGHT, toolbar.logo.height + toolbar.quickLinks.includeInLayout ? toolbar.quickLinks.height : 0 + 10);
+					toolbarHeight = Math.max(DEFAULT_TOOLBAR_HEIGHT, toolbar.logo.height + toolbar.quickLinks.includeInLayout ? toolbar.quickLinks.height : 0);
 					if (UsersUtil.isBreakout()) {
 						toolbarHeight += toolbar.breakoutRibbon.height;
 					}
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/views/MainToolbar.mxml b/bigbluebutton-client/src/org/bigbluebutton/main/views/MainToolbar.mxml
index f0ecb8e80fd0425245f1186973b0ba2baeb9559c..f939574e9649e32d20de1b5da79741da5641a9ca 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/main/views/MainToolbar.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/views/MainToolbar.mxml
@@ -89,6 +89,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 			import org.bigbluebutton.main.events.SuccessfulLoginEvent;
 			import org.bigbluebutton.main.model.NetworkStatsData;
 			import org.bigbluebutton.main.model.options.BrandingOptions;
+			import org.bigbluebutton.main.model.options.HelpOptions;
 			import org.bigbluebutton.main.model.options.LayoutOptions;
 			import org.bigbluebutton.main.model.options.ShortcutKeysOptions;
 			import org.bigbluebutton.main.model.users.events.ChangeMyRole;
@@ -98,8 +99,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 			import org.bigbluebutton.util.i18n.ResourceUtil;
 
 			private static const LOGGER:ILogger = getClassLogger(MainToolbar);
-
-			private var DEFAULT_HELP_URL:String = "http://www.bigbluebutton.org/content/videos";
 			
 			public static const ALIGN_RIGHT:String ="ALIGN_RIGHT";
 			public static const ALIGN_LEFT:String = "ALIGN_LEFT";
@@ -289,7 +288,8 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 			}
 			
 			private function onHelpButtonClicked():void {
-				navigateToURL(new URLRequest(DEFAULT_HELP_URL))
+				var helpOptions:HelpOptions = Options.getOptions(HelpOptions) as HelpOptions;
+				navigateToURL(new URLRequest(helpOptions.url));
 			}
 			
 			private function handleEndMeetingEvent(event:BBBEvent):void {
@@ -542,7 +542,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 			<mx:Label text="|" visible="{timeRemaining.visible}" includeInLayout="{timeRemaining.visible}"/>
 			<mx:Label id="timeRemaining" visible="false" includeInLayout="{timeRemaining.visible}"
 					  text="{ResourceUtil.getInstance().getString('bbb.users.breakout.calculatingRemainingTime')}"
-					  toolTip="{ResourceUtil.getInstance().getString('bbb.users.breakout.timer.toolTip')}"/>
+					  toolTip="{ResourceUtil.getInstance().getString('bbb.users.breakout.timerForRoom.toolTip')}"/>
 		</mx:HBox>
 		<!-- Top bar -->
 		<mx:HBox id="topBox" width="100%" verticalAlign="middle" horizontalScrollPolicy="off" styleName="topBoxStyle">
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/views/OldLocaleWarnWindow.mxml b/bigbluebutton-client/src/org/bigbluebutton/main/views/OldLocaleWarnWindow.mxml
index 7bbaebd0912ffce272a27b1890b457dcd7a8960a..dad78b7929ad187b032b837c9864763d9c63a353 100644
--- a/bigbluebutton-client/src/org/bigbluebutton/main/views/OldLocaleWarnWindow.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/views/OldLocaleWarnWindow.mxml
@@ -1,86 +1,86 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
-
-BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
-
-Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
-
-This program is free software; you can redistribute it and/or modify it under the
-terms of the GNU Lesser General Public License as published by the Free Software
-Foundation; either version 3.0 of the License, or (at your option) any later
-version.
-
-BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License along
-with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
-
--->
-
-<mx:TitleWindow xmlns:mx="library://ns.adobe.com/flex/mx"
-				xmlns:fx="http://ns.adobe.com/mxml/2009"
-    title="{windowTitle}" showCloseButton="false" creationComplete="init()"
-    x="168" y="86" layout="vertical" width="400" height="150" horizontalAlign="center">
-	<fx:Script>
-		<![CDATA[
-			import org.as3commons.logging.api.ILogger;
-			import org.as3commons.logging.api.getClassLogger;
-			import org.bigbluebutton.core.BBB;
-			import org.bigbluebutton.core.PopUpUtil;
-			import org.bigbluebutton.util.i18n.ResourceUtil;
-
-			private static const LOGGER:ILogger = getClassLogger(OldLocaleWarnWindow);      
-			private const windowTitleDefault:String = "Warning: Old Language Version";
-			private const reminder1Default:String = "You have an old language translation of BigBlueButton.";
-			private const reminder2Default:String = "Please clear your browser cache and try again.";
-
-			[Bindable] private var windowTitle:String;
-			[Bindable] private var oldLocalesReminder1:String;
-			[Bindable] private var oldLocalesReminder2:String;
-
-			private function init():void {
-				addEventListener(Event.CLOSE, onUserLoggedOutWindowClose);
-				
-				var locWindowTitle:String = ResourceUtil.getInstance().getString('bbb.oldlocalewindow.windowTitle');
-				if ((locWindowTitle == null) || (locWindowTitle == "")) windowTitle = windowTitleDefault;
-				else windowTitle = locWindowTitle;
-				
-				var reminder1:String = ResourceUtil.getInstance().getString('bbb.oldlocalewindow.reminder1');
-				if ((reminder1 == null) || (reminder1 == "")) oldLocalesReminder1 = reminder1Default;
-				else oldLocalesReminder1 = reminder1;
-				
-				var reminder2:String = ResourceUtil.getInstance().getString('bbb.oldlocalewindow.reminder2');
-				if ((reminder2 == null) || (reminder2 == "")) oldLocalesReminder2 = reminder2Default;
-				else oldLocalesReminder2 = reminder2;
-			}
-
-            private function redirect():void {
-                var logoutURL:String = BBB.getLogoutURL();
-                var request:URLRequest = new URLRequest(logoutURL);
-                LOGGER.debug("Log out url: " + logoutURL);
-                request.method = URLRequestMethod.GET;
-                var urlLoader:URLLoader = new URLLoader();
-                urlLoader.addEventListener(Event.COMPLETE, handleComplete);
-                urlLoader.load(request);
-            }
-
-			private function handleComplete(e:Event):void {	
-				var request:URLRequest = new URLRequest(BBB.getLogoutURL());
-				navigateToURL(request, '_self');
-				PopUpUtil.removePopUp(this);				
-			}
-			
-            private function onUserLoggedOutWindowClose(e:Event):void {
-            	PopUpUtil.removePopUp(this);
-            }
-			
-		]]>
-	</fx:Script>
-	<mx:Label text="{oldLocalesReminder1}"/>
-	<mx:Label text="{oldLocalesReminder2}"/>
-	<mx:Button id="okBtn" label="OK" click="redirect()"/>
-
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+
+BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+
+Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+
+This program is free software; you can redistribute it and/or modify it under the
+terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 3.0 of the License, or (at your option) any later
+version.
+
+BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+
+-->
+
+<mx:TitleWindow xmlns:mx="library://ns.adobe.com/flex/mx"
+				xmlns:fx="http://ns.adobe.com/mxml/2009"
+    title="{windowTitle}" showCloseButton="false" creationComplete="init()"
+    x="168" y="86" layout="vertical" width="400" height="150" horizontalAlign="center">
+	<fx:Script>
+		<![CDATA[
+			import org.as3commons.logging.api.ILogger;
+			import org.as3commons.logging.api.getClassLogger;
+			import org.bigbluebutton.core.BBB;
+			import org.bigbluebutton.core.PopUpUtil;
+			import org.bigbluebutton.util.i18n.ResourceUtil;
+
+			private static const LOGGER:ILogger = getClassLogger(OldLocaleWarnWindow);      
+			private const windowTitleDefault:String = "Warning: Old Language Version";
+			private const reminder1Default:String = "You have an old language translation of BigBlueButton.";
+			private const reminder2Default:String = "Please clear your browser cache and try again.";
+
+			[Bindable] private var windowTitle:String;
+			[Bindable] private var oldLocalesReminder1:String;
+			[Bindable] private var oldLocalesReminder2:String;
+
+			private function init():void {
+				addEventListener(Event.CLOSE, onUserLoggedOutWindowClose);
+				
+				var locWindowTitle:String = ResourceUtil.getInstance().getString('bbb.oldlocalewindow.windowTitle');
+				if ((locWindowTitle == null) || (locWindowTitle == "")) windowTitle = windowTitleDefault;
+				else windowTitle = locWindowTitle;
+				
+				var reminder1:String = ResourceUtil.getInstance().getString('bbb.oldlocalewindow.reminder1');
+				if ((reminder1 == null) || (reminder1 == "")) oldLocalesReminder1 = reminder1Default;
+				else oldLocalesReminder1 = reminder1;
+				
+				var reminder2:String = ResourceUtil.getInstance().getString('bbb.oldlocalewindow.reminder2');
+				if ((reminder2 == null) || (reminder2 == "")) oldLocalesReminder2 = reminder2Default;
+				else oldLocalesReminder2 = reminder2;
+			}
+
+            private function redirect():void {
+                var logoutURL:String = BBB.getLogoutURL();
+                var request:URLRequest = new URLRequest(logoutURL);
+                LOGGER.debug("Log out url: " + logoutURL);
+                request.method = URLRequestMethod.GET;
+                var urlLoader:URLLoader = new URLLoader();
+                urlLoader.addEventListener(Event.COMPLETE, handleComplete);
+                urlLoader.load(request);
+            }
+
+			private function handleComplete(e:Event):void {	
+				var request:URLRequest = new URLRequest(BBB.getLogoutURL());
+				navigateToURL(request, '_self');
+				PopUpUtil.removePopUp(this);				
+			}
+			
+            private function onUserLoggedOutWindowClose(e:Event):void {
+            	PopUpUtil.removePopUp(this);
+            }
+			
+		]]>
+	</fx:Script>
+	<mx:Label text="{oldLocalesReminder1}"/>
+	<mx:Label text="{oldLocalesReminder2}"/>
+	<mx:Button id="okBtn" styleName="mainActionButton" label="OK" click="redirect()"/>
+
 </mx:TitleWindow>
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/views/WebRTCEchoTest.mxml b/bigbluebutton-client/src/org/bigbluebutton/main/views/WebRTCEchoTest.mxml
index 84c08ffce026db3fc35a669ee1d3963a77cae4f5..87f69ff8a22bba353570f058119c8a8bbf408a83 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/main/views/WebRTCEchoTest.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/views/WebRTCEchoTest.mxml
@@ -58,7 +58,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 			import org.bigbluebutton.util.i18n.ResourceUtil;
 
 			private static const LOGGER:ILogger = getClassLogger(WebRTCEchoTest);      
-			private static var DEFAULT_HELP_URL:String = "http://www.bigbluebutton.org/content/videos";
 
 			private static const TIMEOUT:Number = 60;
 			private static const CANCEL_BUTTON:Number = 55;
@@ -243,8 +242,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 			
 			private function onHelpButtonClicked():void {
 				var helpOptions : HelpOptions = Options.getOptions(HelpOptions) as HelpOptions;
-				DEFAULT_HELP_URL =  helpOptions.url;
-				navigateToURL(new URLRequest(DEFAULT_HELP_URL));
+				navigateToURL(new URLRequest(helpOptions.url));
 			}
 			
 			
@@ -308,11 +306,12 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 									  text="{ResourceUtil.getInstance().getString('bbb.micSettings.echoTestMicPrompt')}"
 									  styleName="micSettingsWindowSpeakIntoMicLabelStyle" />
 				<mx:Button id="yesButton" label="{ResourceUtil.getInstance().getString('bbb.micSettings.echoTestAudioYes')}"
-						   click="yesButtonClicked()" 
+						   click="yesButtonClicked()"
+						   styleName="mainActionButton"
 						   toolTip=""/>
-				<mx:Button id="noButton" 
-						   label="{ResourceUtil.getInstance().getString('bbb.micSettings.echoTestAudioNo')}" 
-						   click="noButtonClicked()" 
+				<mx:Button id="noButton"
+						   label="{ResourceUtil.getInstance().getString('bbb.micSettings.echoTestAudioNo')}"
+						   click="noButtonClicked()"
 						   toolTip=""/>
 			</mx:HBox>
 		</mx:VBox>
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/polling/views/PollChoicesModal.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/polling/views/PollChoicesModal.mxml
index 78ad3fc08cd94dfa7d3c15cc0a1d139bde308cdd..816fc93020d6a6336ae25863ee02e9d24d29510e 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/polling/views/PollChoicesModal.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/polling/views/PollChoicesModal.mxml
@@ -89,6 +89,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 	
 	<mx:HBox width="100%" horizontalGap="10" horizontalAlign="right">
 		<mx:Button id="publishButton" click="publishButton_clickHandler(event)"
+				   styleName="mainActionButton"
 				   label="{ResourceUtil.getInstance().getString('bbb.polling.startButton.label')}"/>
 		<mx:Button id="closeButton" click="onCloseClicked()"
 				   label="{ResourceUtil.getInstance().getString('bbb.polling.closeButton.label')}"/>
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/polling/views/PollResultsModal.as b/bigbluebutton-client/src/org/bigbluebutton/modules/polling/views/PollResultsModal.as
index f5af7d9c0ee2e6d9d89205c4ee23540338be7d1b..d17267aa69c3efc3bdf44da5bb5f4e8c4e0fd49e 100644
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/polling/views/PollResultsModal.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/polling/views/PollResultsModal.as
@@ -7,6 +7,7 @@ package org.bigbluebutton.modules.polling.views
 	import flash.events.TimerEvent;
 	import flash.utils.Timer;
 	
+	import mx.containers.Box;
 	import mx.containers.HBox;
 	import mx.containers.TitleWindow;
 	import mx.controls.Button;
@@ -50,6 +51,17 @@ package org.bigbluebutton.modules.polling.views
 			modalTitle.maxWidth = 300;
 			addChild(modalTitle);
 			
+			var hintBox : Box = new Box();
+			hintBox.percentWidth = 100;
+			hintBox.styleName = "pollHintBoxStyle";
+			addChild(hintBox);
+			
+			var hintText : AdvancedLabel = new AdvancedLabel();
+			hintText.percentWidth = 100;
+			hintText.styleName = "pollHintTextStyle";
+			hintText.text = ResourceUtil.getInstance().getString('bbb.polling.pollModal.hint');
+			hintBox.addChild(hintText);
+
 			var hrule:HRule = new HRule();
 			hrule.percentWidth = 100;
 			addChild(hrule);
@@ -89,6 +101,7 @@ package org.bigbluebutton.modules.polling.views
 			
 			_publishBtn = new Button();
 			_publishBtn.label = ResourceUtil.getInstance().getString('bbb.polling.publishButton.label');
+			_publishBtn.styleName = "mainActionButton";
 			_publishBtn.addEventListener(MouseEvent.CLICK, handlePublishClick);
 			botBox.addChild(_publishBtn);
 			_closeBtn = new Button();
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/present/ui/views/PresentationWindow.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/present/ui/views/PresentationWindow.mxml
index e698f608a40391017484fbb6a5b9ec917bd142c7..808fa663963574b3dac9ff3b39320cbf93024dd5 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/present/ui/views/PresentationWindow.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/present/ui/views/PresentationWindow.mxml
@@ -70,6 +70,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 			import mx.collections.ArrayCollection;
 			import mx.controls.Menu;
 			import mx.events.MenuEvent;
+			import mx.managers.PopUpManager;
 			
 			import flashx.textLayout.formats.Direction;
 			
@@ -694,6 +695,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 					if (pollResultsPopUp) {
 						pollResultsPopUp.setPoll(e.poll);
 					}
+					PopUpManager.centerPopUp(pollResultsPopUp);
 				} else {
 					//switch to vote state
 					setControlBarState("vote");
@@ -871,6 +873,9 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 					   toolTip="{ResourceUtil.getInstance().getString('bbb.presentation.fitToPage.toolTip')}" 
 					   click="onFitToPage(true)"/>
 		</mx:HBox>
-		<mx:HBox id="pollVoteBox" width="100%" height="100%" visible="false" includeInLayout="false" horizontalAlign="center" verticalAlign="middle"/>
+		<mx:VBox width="100%" height="100%" visible="{pollVoteBox.visible}" includeInLayout="{pollVoteBox.includeInLayout}" horizontalAlign="center">
+			<mx:Label id="pollVoteLabel" styleName="pollVoteLabel" text="{ResourceUtil.getInstance().getString('bbb.presentation.poll.response')}"/>
+			<mx:HBox id="pollVoteBox" width="100%" height="100%" visible="false" includeInLayout="false" horizontalAlign="center" verticalAlign="middle"/>	
+		</mx:VBox>
 	</mx:ControlBar>
 </pres:CustomMdiWindow>
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/view/components/ScreensharePublishWindow.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/view/components/ScreensharePublishWindow.mxml
index cc627779d0576a9e2c0c0e4dd19069304e64a743..52461fc6ae8fd5b5b4b945fe08193bf2f9e4ebe9 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/view/components/ScreensharePublishWindow.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/view/components/ScreensharePublishWindow.mxml
@@ -619,8 +619,8 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
         <mx:ComboBox id="shareTypeCombo" dataProvider="{shareTypeProvider}" />
       </mx:HBox>
     <mx:Spacer width="80%" />
-    <mx:Button id="startBtn" click="onStartButtonClick()" label="{ResourceUtil.getInstance().getString('bbb.screensharePublish.startButton.label')}" />
+    <mx:Button id="startBtn" styleName="mainActionButton" click="onStartButtonClick()" label="{ResourceUtil.getInstance().getString('bbb.screensharePublish.startButton.label')}" />
     <mx:Button id="cancelBtn" click="closeWindow()" label="{ResourceUtil.getInstance().getString('bbb.screensharePublish.cancelButton.label')}" />
-    <mx:Button id="stopBtn" visible="false" includeInLayout="false" click="close()" label="{ResourceUtil.getInstance().getString('bbb.screensharePublish.stopButton.label')}" />
+    <mx:Button id="stopBtn" styleName="mainActionButton" visible="false" includeInLayout="false" click="close()" label="{ResourceUtil.getInstance().getString('bbb.screensharePublish.stopButton.label')}" />
   </mx:ControlBar>
 </common:CustomMdiWindow>
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/users/model/UsersOptions.as b/bigbluebutton-client/src/org/bigbluebutton/modules/users/model/UsersOptions.as
index cdfa54a4459669f95c145425107249e0a697a158..1cb05e10695062781c94dd642fd569c7b59bd2df 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/users/model/UsersOptions.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/users/model/UsersOptions.as
@@ -33,7 +33,10 @@ package org.bigbluebutton.modules.users.model {
 
 		[Bindable]
 		public var enableSettingsButton:Boolean = true;
-		
+
+		[Bindable]
+		public var moderatorUnmute:Boolean = true;
+
 		[Bindable]
 		public var enableGuestUI:Boolean = false;
 
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/users/views/BreakoutRoomSettings.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/users/views/BreakoutRoomSettings.mxml
index 32ec37d7f1faa723a510e9eb7ed23da849c4e736..0062d520004bf22948b8c1aee5c5377920bab3a4 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/users/views/BreakoutRoomSettings.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/users/views/BreakoutRoomSettings.mxml
@@ -314,6 +314,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
         
         <mx:HBox width="100%" horizontalAlign="right" verticalGap="15">
             <mx:Button id="startButton"
+					   styleName="mainActionButton"
                        click="this.mode == 'create' ? createBreakoutRooms() : inviteUsersToBreakoutRooms()"/>
             <mx:Button label="{ResourceUtil.getInstance().getString('bbb.users.breakout.close')}" click="onCloseClicked()"/>
         </mx:HBox>
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/users/views/MediaItemRenderer.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/users/views/MediaItemRenderer.mxml
index 51fb279705019af138123d80d55634dc3aa8b447..f5ca881c0e039e0eaab078fa62a504cfda2d36a6 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/users/views/MediaItemRenderer.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/users/views/MediaItemRenderer.mxml
@@ -68,22 +68,22 @@
 			
 			private var options:UsersOptions;
 			private var myMenu:Menu = null;
-			
-      private function onCreationComplete():void{
-        refreshRole(UsersUtil.amIModerator());
-        
-        this.addEventListener(FlexEvent.DATA_CHANGE, dataChangeHandler);
-        
-        BindingUtils.bindSetter(updateButtons, listenOnlyInd, "visible");
-        BindingUtils.bindSetter(updateButtons, voiceJoinedInd, "visible");
-        BindingUtils.bindSetter(updateButtons, muteInd, "visible");
-        BindingUtils.bindSetter(updateButtons, userLockedInd, "visible");
-        BindingUtils.bindSetter(updateButtons, hasStreamInd, "visible");
-        BindingUtils.bindSetter(updateButtons, viewingStreamInd, "visible");
-        
-        options = Options.getOptions(UsersOptions) as UsersOptions;
-      }
-			
+
+			private function onCreationComplete():void {
+				options = Options.getOptions(UsersOptions) as UsersOptions;
+
+				refreshRole(UsersUtil.amIModerator());
+
+				this.addEventListener(FlexEvent.DATA_CHANGE, dataChangeHandler);
+
+				BindingUtils.bindSetter(updateButtons, listenOnlyInd, "visible");
+				BindingUtils.bindSetter(updateButtons, voiceJoinedInd, "visible");
+				BindingUtils.bindSetter(updateButtons, muteInd, "visible");
+				BindingUtils.bindSetter(updateButtons, userLockedInd, "visible");
+				BindingUtils.bindSetter(updateButtons, hasStreamInd, "visible");
+				BindingUtils.bindSetter(updateButtons, viewingStreamInd, "visible");
+			}
+
 			private function dataChangeHandler(e:Event):void {
 				//rest rolledOver when the data changes because onRollOut wont be called if the row moves
 				if (data != null) {
@@ -171,29 +171,29 @@
 				e.internalUserID = data.userId;
 				dispatchEvent(e);
 			}
-			
+
 			private function updateButtons(voiceMuted:Boolean = false):void {
 				// reset the mute image filter so the talking indicator doesn't stick
 				muteImg.filters = null;
-				
+
 				var ls:LockSettingsVO = UsersUtil.getLockSettings();
-				
+
 				if (data != null) {
 					settingsBtn.visible = rolledOver && !data.me && !UsersUtil.isBreakout();
-					
-					if (!data.inVoiceConf) {
-							muteImg.visible = false;
-							muteImg.includeInLayout = false;
-							muteBtn.visible = false;
-							muteBtn.includeInLayout = true;
+
+					if ( !data.inVoiceConf || ( options.moderatorUnmute == false && UsersUtil.amIModerator() && !UsersUtil.isMe(data.userId) ) ) {
+						muteImg.visible = false;
+						muteImg.includeInLayout = false;
+						muteBtn.visible = false;
+						muteBtn.includeInLayout = true;
 					} else {
-            if (data.listenOnly) {
-              muteImg.source = getStyle("iconSound");
-              muteImg.visible = true;
-              muteImg.includeInLayout = true;
-              muteBtn.visible = false;
-              muteBtn.includeInLayout = false;             
-            } else if (data.locked && ls.getDisableMic()) {
+						if (data.listenOnly) {
+							muteImg.source = getStyle("iconSound");
+							muteImg.visible = true;
+							muteImg.includeInLayout = true;
+							muteBtn.visible = false;
+							muteBtn.includeInLayout = false;
+						} else if (data.locked && ls.getDisableMic()) {
 							muteImg.visible = true;
 							muteImg.includeInLayout = true;
 							muteBtn.visible = false;
@@ -205,20 +205,20 @@
 							muteBtn.includeInLayout = rolledOver;
 							muteBtn.enabled = true;
 
-							if(data.talking && !rolledOver){
+							if (data.talking && !rolledOver) {
 								muteImg.filters = [new GlowFilter(getStyle("glowFilterColor"), 1, 6, 6, 2, BitmapFilterQuality.HIGH, false, false)];
-							}else{
+							} else {
 								muteImg.filters = [];
 							}
 						}
 					}
-					
-					if (data.role == Role.MODERATOR){
+
+					if (data.role == Role.MODERATOR) {
 						lockImg.visible = false;
 						lockImg.includeInLayout = true;
 						lockBtn.visible = false;
 						lockBtn.includeInLayout = false;
-					} else if(moderator && ls.isAnythingLocked()) {
+					} else if (moderator && ls.isAnythingLocked()) {
 						lockImg.visible = !rolledOver;
 						lockImg.includeInLayout = !rolledOver;
 						lockBtn.visible = rolledOver;
@@ -230,7 +230,7 @@
 						lockBtn.visible = false;
 						lockBtn.includeInLayout = false;
 					}
-					
+
 					if (data.hasStream) {
 						// if it's myself or if I'm watching all the streams from the given user, then don't activate the button
 						if (data.me || data.isViewingAllStreams()) {
@@ -253,20 +253,19 @@
 
 					if (!rolledOver) {
 						if (data.inVoiceConf) {
-              if (data.listenOnly) {
-                muteImg.source = getStyle("iconSound");
-              } else if (data.muted) {
-                muteImg.source = getStyle("iconAudioMuted");
-              } else {
-                muteImg.source = getStyle("iconAudio");
-              }
+							if (data.listenOnly) {
+								muteImg.source = getStyle("iconSound");
+							} else if (data.muted) {
+								muteImg.source = getStyle("iconAudioMuted");
+							} else {
+								muteImg.source = getStyle("iconAudio");
+							}
 						}
-						
-						
-						if ( data.locked && !data.presenter && ls.isAnythingLocked() ) {
+
+
+						if (data.locked && !data.presenter && ls.isAnythingLocked()) {
 							lockImg.source = getStyle("iconLock");
-						}
-						else {
+						} else {
 							lockImg.source = null;
 						}
 					} else {
@@ -274,7 +273,7 @@
 							muteBtn.setStyle("icon", getStyle("iconAudio"));
 						else
 							muteBtn.setStyle("icon", getStyle("iconAudioMuted"));
-						
+
 						if (data.locked == rolledOverLock)
 							lockBtn.setStyle("icon", getStyle("iconUnlock"));
 						else
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/users/views/UsersWindow.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/users/views/UsersWindow.mxml
index c1aa784e4c28438b8ba7573ff12afa22ccac9a63..83a32b116251dad95afa4f504f6629a5c806f956 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/users/views/UsersWindow.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/users/views/UsersWindow.mxml
@@ -384,13 +384,15 @@ $Id: $
         paramsMenuData = [];
         paramsMenuData.push({label: ResourceUtil.getInstance().getString('bbb.users.settings.clearAllStatus'), icon: getStyle('iconClearStatus'), handler: resetEmojiStatuses});
         
-        if (!roomMuted) {
-          paramsMenuData.push({label: ResourceUtil.getInstance().getString('bbb.users.settings.muteAll'), icon: getStyle('iconAudioMuted'), handler: muteAll});
-          var presenter:User2x = UsersUtil.getPresenter();
-          if (presenter != null)
-            paramsMenuData.push({label: ResourceUtil.getInstance().getString('bbb.users.settings.muteAllExcept') + ": " + presenter.name, icon: getStyle('iconAudioMuted'), handler: muteAlmostAll});
-        } else
-          paramsMenuData.push({label: ResourceUtil.getInstance().getString('bbb.users.settings.unmuteAll'), icon: getStyle('iconAudio'), handler: muteAll});
+		if (partOptions.moderatorUnmute == true) {
+	      if (!roomMuted) {
+	        paramsMenuData.push({label: ResourceUtil.getInstance().getString('bbb.users.settings.muteAll'), icon: getStyle('iconAudioMuted'), handler: muteAll});
+	        var presenter:User2x = UsersUtil.getPresenter();
+	        if (presenter != null)
+	          paramsMenuData.push({label: ResourceUtil.getInstance().getString('bbb.users.settings.muteAllExcept') + ": " + presenter.name, icon: getStyle('iconAudioMuted'), handler: muteAlmostAll});
+	      } else
+	        paramsMenuData.push({label: ResourceUtil.getInstance().getString('bbb.users.settings.unmuteAll'), icon: getStyle('iconAudio'), handler: muteAll});
+		}
         
         paramsMenuData.push({label: ResourceUtil.getInstance().getString('bbb.users.settings.lockSettings'), icon: getStyle('iconLock'), handler: lockSettings});
         if (breakoutOptions.enabled && amIModerator && !UsersUtil.isBreakout()) {
diff --git a/bigbluebutton-html5/client/stylesheets/bbb-icons.css b/bigbluebutton-html5/client/stylesheets/bbb-icons.css
index 5e8b131cc437e9096b4663bd255d3adaecd0f435..efda7c393348ed712996ee5a1b21ec0d2bc671a2 100755
--- a/bigbluebutton-html5/client/stylesheets/bbb-icons.css
+++ b/bigbluebutton-html5/client/stylesheets/bbb-icons.css
@@ -1,32 +1,32 @@
 @font-face {
-    font-family: 'bbb-icons';
-    src: url('/fonts/BbbIcons/bbb-icons.eot?j1ntjp');
-    src: url('/fonts/BbbIcons/bbb-icons.eot?j1ntjp#iefix') format('embedded-opentype'),
-         url('/fonts/BbbIcons/bbb-icons.ttf?j1ntjp') format('truetype'),
-         url('/fonts/BbbIcons/bbb-icons.woff?j1ntjp') format('woff'),
-         url('/fonts/BbbIcons/bbb-icons.svg?j1ntjp#bbb-icons') format('svg');
-    font-weight: normal;
-    font-style: normal;
+  font-family: 'bbb-icons';
+  src: url('/fonts/BbbIcons/bbb-icons.eot?j1ntjp');
+  src: url('/fonts/BbbIcons/bbb-icons.eot?j1ntjp#iefix') format('embedded-opentype'),
+       url('/fonts/BbbIcons/bbb-icons.ttf?j1ntjp') format('truetype'),
+       url('/fonts/BbbIcons/bbb-icons.woff?j1ntjp') format('woff'),
+       url('/fonts/BbbIcons/bbb-icons.svg?j1ntjp#bbb-icons') format('svg');
+  font-weight: normal;
+  font-style: normal;
 }
 
 [class^="icon-bbb-"], [class*=" icon-bbb-"] {
-    /* use !important to prevent issues with browser extensions that change fonts */
-    font-family: 'bbb-icons' !important;
-    speak: none;
-    position: relative;
-    /*top: 1px;*/
-    display: inline-block;
-    font-style: normal;
-    font-weight: 400;
-    line-height: 1;
-    -webkit-font-smoothing: antialiased;
-    width: 1.28571429em;
-    text-align: center;
-    vertical-align: middle;
+  /* use !important to prevent issues with browser extensions that change fonts */
+  font-family: 'bbb-icons' !important;
+  speak: none;
+  position: relative;
+  /*top: 1px;*/
+  display: inline-block;
+  font-style: normal;
+  font-weight: 400;
+  line-height: 1;
+  -webkit-font-smoothing: antialiased;
+  width: 1.28571429em;
+  text-align: center;
+  vertical-align: middle;
 
-    /* Better Font Rendering =========== */
-    -webkit-font-smoothing: antialiased;
-    -moz-osx-font-smoothing: grayscale;
+  /* Better Font Rendering =========== */
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
 }
 
 .icon-bbb-mute:before {
@@ -45,7 +45,7 @@
   content: "\e92a";
 }
 .icon-bbb-exit_fullscreen:before {
-    content: "\e935";
+  content: "\e935";
 }
 .icon-bbb-settings:before {
   content: "\e92b";
@@ -95,8 +95,13 @@
 .icon-bbb-video:before {
   content: "\e930";
 }
+.icon-bbb-elipsis:before {
+  content: "\e902";
+}
 .icon-bbb-more:before {
   content: "\e902";
+  display: inline-block;
+  transform: rotate(90deg);
 }
 .icon-bbb-promote:before {
   content: "\e903";
diff --git a/bigbluebutton-html5/imports/api/2.0/annotations/server/methods/sendAnnotation.js b/bigbluebutton-html5/imports/api/2.0/annotations/server/methods/sendAnnotation.js
index 2a56cdfc19aa40d3b4695245a89d89cd4df73f91..0a6fb16c2778324220857a4e8c56ea6c1b3efd8d 100644
--- a/bigbluebutton-html5/imports/api/2.0/annotations/server/methods/sendAnnotation.js
+++ b/bigbluebutton-html5/imports/api/2.0/annotations/server/methods/sendAnnotation.js
@@ -6,7 +6,9 @@ import { check } from 'meteor/check';
 import Annotations from '/imports/api/2.0/annotations';
 
 function isLastMessage(annotation, userId) {
-  if (annotation.status === 'DRAW_END') {
+  const DRAW_END = Meteor.settings.public.whiteboard.annotations.status.end;
+
+  if (annotation.status === DRAW_END) {
     const selector = {
       id: annotation.id,
       userId,
diff --git a/bigbluebutton-html5/imports/api/2.0/audio/client/manager/index.js b/bigbluebutton-html5/imports/api/2.0/audio/client/manager/index.js
index 81e9d19ea6ed5d01793291918005fe92e91973ed..621f720136696728c28e9ec1fa5308dc1bf3d67d 100644
--- a/bigbluebutton-html5/imports/api/2.0/audio/client/manager/index.js
+++ b/bigbluebutton-html5/imports/api/2.0/audio/client/manager/index.js
@@ -213,7 +213,11 @@ class AudioManager {
       }
       resolve({
         stunServers: stunServers.map(server => server.url),
-        turnServers: turnServers.map(server => server.url),
+        turnServers: turnServers.map(server => ({
+          urls: server.url,
+          username: server.username,
+          password: server.password,
+        })),
       });
     });
     return promise;
diff --git a/bigbluebutton-html5/imports/api/2.0/meetings/server/modifiers/changeLockSettings.js b/bigbluebutton-html5/imports/api/2.0/meetings/server/modifiers/changeLockSettings.js
index 49fb1b5bc911ef896d37918c859fd680885c13da..dcbdf772546a01ca6dc85f66a519a2c9560f0e5f 100644
--- a/bigbluebutton-html5/imports/api/2.0/meetings/server/modifiers/changeLockSettings.js
+++ b/bigbluebutton-html5/imports/api/2.0/meetings/server/modifiers/changeLockSettings.js
@@ -30,9 +30,11 @@ export default function changeLockSettings(meetingId, payload) {
       return Logger.error(`Changing meeting={${meetingId}} lock settings: ${err}`);
     }
 
-    if (numChanged) {
-      return Logger.error(`Changed meeting={${meetingId}} updated lock settings`);
+    if (!numChanged) {
+      return Logger.info(`meeting={${meetingId}} lock settings were not updated`);
     }
+
+    return Logger.info(`Changed meeting={${meetingId}} updated lock settings`);
   };
 
   return Meetings.upsert(selector, modifier, cb);
diff --git a/bigbluebutton-html5/imports/api/2.0/meetings/server/modifiers/changeUserLock.js b/bigbluebutton-html5/imports/api/2.0/meetings/server/modifiers/changeUserLock.js
index ebb0647db9b8dea6e3cfb27b3d308806af194db1..f9cd16a5ab0d57b7d31ae6367b3114a78771591d 100644
--- a/bigbluebutton-html5/imports/api/2.0/meetings/server/modifiers/changeUserLock.js
+++ b/bigbluebutton-html5/imports/api/2.0/meetings/server/modifiers/changeUserLock.js
@@ -10,20 +10,28 @@ export default function changeUserLock(meetingId, payload) {
     lockedBy: String,
   });
 
+  const { userId, locked, lockedBy } = payload;
+
   const selector = {
-    userId: payload.userId,
+    userId,
   };
 
   const modifier = {
     $set: {
-      locked: payload.locked,
+      locked,
     },
   };
 
-  const cb = (err) => {
+  const cb = (err, numChanged) => {
     if (err) {
       return Logger.error(`Changing user lock setting: ${err}`);
     }
+
+    if (!numChanged) {
+      return Logger.info(`User's userId=${userId} lock status wasn't updated`);
+    }
+
+    return Logger.info(`User's userId=${userId} lock status was changed to: ${locked} by user userId=${lockedBy}`);
   };
 
   return Users.upsert(selector, modifier, cb);
diff --git a/bigbluebutton-html5/imports/api/2.0/presentations/server/handlers/presentationConversionUpdate.js b/bigbluebutton-html5/imports/api/2.0/presentations/server/handlers/presentationConversionUpdate.js
old mode 100755
new mode 100644
diff --git a/bigbluebutton-html5/imports/api/2.0/presentations/server/methods/removePresentation.js b/bigbluebutton-html5/imports/api/2.0/presentations/server/methods/removePresentation.js
old mode 100755
new mode 100644
diff --git a/bigbluebutton-html5/imports/api/2.0/presentations/server/methods/setPresentation.js b/bigbluebutton-html5/imports/api/2.0/presentations/server/methods/setPresentation.js
old mode 100755
new mode 100644
diff --git a/bigbluebutton-html5/imports/api/2.0/slides/server/modifiers/addSlide.js b/bigbluebutton-html5/imports/api/2.0/slides/server/modifiers/addSlide.js
index be19f2a06e76a0b1601d8e93aa5fcf38804dcce6..e28f6e79aa5ff5334fdabeddd6b4c6bb494089c1 100644
--- a/bigbluebutton-html5/imports/api/2.0/slides/server/modifiers/addSlide.js
+++ b/bigbluebutton-html5/imports/api/2.0/slides/server/modifiers/addSlide.js
@@ -93,6 +93,14 @@ export default function addSlide(meetingId, presentationId, slide) {
 
   return fetchImageSizes(imageUri)
     .then(({ width, height }) => {
+      // there is a rare case when for a very long not-active meeting
+      // the presentation files just disappear
+      // in that case just set the whole calculatedData to undefined
+      if (!width && !height) {
+        modifier.$set.calculatedData = undefined;
+        return Slides.upsert(selector, modifier, cb);
+      }
+
       // pre-calculating the width, height, and vieBox coordinates / dimensions
       // to unload the client-side
       const slideData = {
diff --git a/bigbluebutton-html5/imports/api/2.0/slides/server/modifiers/resizeSlide.js b/bigbluebutton-html5/imports/api/2.0/slides/server/modifiers/resizeSlide.js
index 0ad0eca27f2424db207f557bb1726e8c1d370ad0..ad00b543067d6d309509c2c9379f111aa443a72f 100644
--- a/bigbluebutton-html5/imports/api/2.0/slides/server/modifiers/resizeSlide.js
+++ b/bigbluebutton-html5/imports/api/2.0/slides/server/modifiers/resizeSlide.js
@@ -27,19 +27,19 @@ export default function resizeSlide(meetingId, slide) {
   // fetching the current slide data
   // and pre-calculating the width, height, and vieBox coordinates / sizes
   // to reduce the client-side load
-  const _slide = Slides.findOne(selector);
+  const Slide = Slides.findOne(selector);
   const slideData = {
-    width: _slide.calculatedData.width,
-    height: _slide.calculatedData.height,
+    width: Slide.calculatedData.width,
+    height: Slide.calculatedData.height,
     xOffset,
     yOffset,
     widthRatio,
     heightRatio,
   };
   const calculatedData = calculateSlideData(slideData);
-  calculatedData.imageUri = _slide.calculatedData.imageUri;
-  calculatedData.width = _slide.calculatedData.width;
-  calculatedData.height = _slide.calculatedData.height;
+  calculatedData.imageUri = Slide.calculatedData.imageUri;
+  calculatedData.width = Slide.calculatedData.width;
+  calculatedData.height = Slide.calculatedData.height;
   modifier.$set.calculatedData = calculatedData;
 
   const cb = (err, numChanged) => {
diff --git a/bigbluebutton-html5/imports/api/2.0/users/server/eventHandlers.js b/bigbluebutton-html5/imports/api/2.0/users/server/eventHandlers.js
old mode 100755
new mode 100644
diff --git a/bigbluebutton-html5/imports/api/2.0/users/server/handlers/changeRole.js b/bigbluebutton-html5/imports/api/2.0/users/server/handlers/changeRole.js
old mode 100755
new mode 100644
index 711e25bbeb6dbf553ed020e8ec8bf3f70dedf93e..5b0638cd2f0d763973a8ea6038a1acaf8d5803b7
--- a/bigbluebutton-html5/imports/api/2.0/users/server/handlers/changeRole.js
+++ b/bigbluebutton-html5/imports/api/2.0/users/server/handlers/changeRole.js
@@ -1,36 +1,9 @@
-import Logger from '/imports/startup/server/logger';
 import { check } from 'meteor/check';
-import Users from '/imports/api/2.0/users';
+import changeRole from '../modifiers/changeRole';
 
-export default function handleChangeRole({body}, meetingId) {
-
-  const { userId, role, changedBy } = body;
-
-  check(userId, String);
-  check(role, String);
-  check(changedBy, String);
-
-  const selector = {
-    meetingId,
-    userId,
-  };
-
-  const modifier = {
-    $set: {
-      role,
-    },
-  };
-
-  const cb = (err, numChanged) => {
-    if (err) {
-      return Logger.error(`Changed user role: ${err}`);
-    }
-
-    if (numChanged) {
-      return Logger.info(`Changed user role ${role} id=${userId} meeting=${meetingId} by changedBy=${changedBy}`);
-    }
-  };
-
-  return Users.update(selector, modifier, cb);
+export default function handleChangeRole(payload, meetingId) {
+  check(payload.body, Object);
+  check(meetingId, String);
 
+  changeRole(payload, meetingId);
 }
diff --git a/bigbluebutton-html5/imports/api/2.0/users/server/methods.js b/bigbluebutton-html5/imports/api/2.0/users/server/methods.js
old mode 100755
new mode 100644
diff --git a/bigbluebutton-html5/imports/api/2.0/users/server/methods/changeRole.js b/bigbluebutton-html5/imports/api/2.0/users/server/methods/changeRole.js
old mode 100755
new mode 100644
index 74591ce9dc3cf556e0faf2520068f40e37aacb7c..5e40381a504b0c612a6ffc9fff610758dd07ec34
--- a/bigbluebutton-html5/imports/api/2.0/users/server/methods/changeRole.js
+++ b/bigbluebutton-html5/imports/api/2.0/users/server/methods/changeRole.js
@@ -26,12 +26,6 @@ export default function changeRole(credentials, userId, role) {
       'user-not-found', `You need a valid user to be able to set '${role}'`);
   }
 
-  const header = {
-    name: EVENT_NAME,
-    meetingId,
-    userId,
-  };
-
   const payload = {
     userId,
     role,
@@ -40,5 +34,5 @@ export default function changeRole(credentials, userId, role) {
 
   Logger.verbose(`User '${userId}' setted as '${role} role by '${requesterUserId}' from meeting '${meetingId}'`);
 
-  return RedisPubSub.publish(CHANNEL, EVENT_NAME, meetingId, payload, header);
+  return RedisPubSub.publishUserMessage(CHANNEL, EVENT_NAME, meetingId, requesterUserId, payload);
 }
diff --git a/bigbluebutton-html5/imports/api/2.0/users/server/modifiers/changeRole.js b/bigbluebutton-html5/imports/api/2.0/users/server/modifiers/changeRole.js
new file mode 100644
index 0000000000000000000000000000000000000000..01518275a665c5161bd8ac6e1c71d6ccf2e46943
--- /dev/null
+++ b/bigbluebutton-html5/imports/api/2.0/users/server/modifiers/changeRole.js
@@ -0,0 +1,34 @@
+import Logger from '/imports/startup/server/logger';
+import Users from '/imports/api/2.0/users';
+
+export default function changeRole({ body }, meetingId) {
+  const { userId, role, changedBy } = body;
+
+  const selector = {
+    meetingId,
+    userId,
+  };
+
+  const modifier = {
+    $set: {
+      role,
+    },
+    $push: {
+      roles: (role === 'MODERATOR' ? 'moderator' : 'viewer'),
+    },
+  };
+
+  const cb = (err, numChanged) => {
+    if (err) {
+      return Logger.error(`Changed user role: ${err}`);
+    }
+
+    if (numChanged) {
+      return Logger.info(`Changed user role ${role} id=${userId} meeting=${meetingId} by changedBy=${changedBy}`);
+    }
+
+    return null;
+  };
+
+  return Users.update(selector, modifier, cb);
+}
diff --git a/bigbluebutton-html5/imports/api/acl/Acl.js b/bigbluebutton-html5/imports/api/acl/Acl.js
index 208b29c48ed0b8bd9f5279d03b6bb1c7cbb05229..f031a2a3e6c82e710e78b568933efdb89aba1b09 100644
--- a/bigbluebutton-html5/imports/api/acl/Acl.js
+++ b/bigbluebutton-html5/imports/api/acl/Acl.js
@@ -1,8 +1,9 @@
+
+import { Meteor } from 'meteor/meteor';
 import { check } from 'meteor/check';
 import deepMerge from '/imports/utils/deepMerge';
 
-export class Acl {
-
+export default class Acl {
   constructor(config, Users) {
     this.Users = Users;
     this.config = config;
@@ -12,11 +13,22 @@ export class Acl {
     check(permission, String);
     const permissions = this.getPermissions(credentials);
 
-    if (permissions) {
-      return this.fetchPermission(permission, permissions);
-    }
+    return this.checkToken(credentials) && this.fetchPermission(permission, permissions);
+  }
 
-    return false;
+  checkToken(credentials) {
+    // skip token check in client `can` calls since we dont have the authToken in the collection
+    if (!Meteor.isServer) return true;
+
+    const { meetingId, requesterUserId: userId, requesterToken: authToken } = credentials;
+
+    const User = this.Users.findOne({
+      meetingId,
+      userId,
+      authToken,
+    });
+
+    return !!User; // if he found a user means the meeting/user/token is valid
   }
 
   fetchPermission(permission, permissions) {
diff --git a/bigbluebutton-html5/imports/startup/acl.js b/bigbluebutton-html5/imports/startup/acl.js
index 693f0b22126b7d78e4409016ab405b5baef516b9..cfee53ae5ab51c613b82b458b1b95a4b8d6b6910 100644
--- a/bigbluebutton-html5/imports/startup/acl.js
+++ b/bigbluebutton-html5/imports/startup/acl.js
@@ -1,6 +1,6 @@
 import { Meteor } from 'meteor/meteor';
 import Users from '/imports/api/2.0/users';
-import { Acl } from '/imports/api/acl/Acl';
+import Acl from '/imports/api/acl/Acl';
 
 const AclSingleton = new Acl();
 
diff --git a/bigbluebutton-html5/imports/startup/server/index.js b/bigbluebutton-html5/imports/startup/server/index.js
index 869fffc72aa6dae48b345c2a4bb91fe4be1b07c4..b1aa6ff9bd87ca13e7ab4ac1787426230f265fc2 100644
--- a/bigbluebutton-html5/imports/startup/server/index.js
+++ b/bigbluebutton-html5/imports/startup/server/index.js
@@ -21,7 +21,7 @@ WebApp.connectHandlers.use('/check', (req, res, next) => {
 
 WebApp.connectHandlers.use('/locale', (req, res) => {
   const APP_CONFIG = Meteor.settings.public.app;
-  const defaultLocale = APP_CONFIG.defaultLocale;
+  const defaultLocale = APP_CONFIG.defaultSettings.application.locale;
   const localeRegion = req.query.locale.split('-');
   let messages = {};
   const locales = [defaultLocale, localeRegion[0]];
diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/emoji-menu/component.jsx b/bigbluebutton-html5/imports/ui/components/actions-bar/emoji-menu/component.jsx
index ac4833c1ae8829757b1badca5c9934b8b18d7415..efd132d6fe463d2f0875d770f5ef650130a7518b 100644
--- a/bigbluebutton-html5/imports/ui/components/actions-bar/emoji-menu/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/actions-bar/emoji-menu/component.jsx
@@ -1,4 +1,4 @@
-import React, { Component } from 'react';
+import React from 'react';
 import PropTypes from 'prop-types';
 import { defineMessages, injectIntl } from 'react-intl';
 
@@ -10,129 +10,7 @@ import DropdownList from '/imports/ui/components/dropdown/list/component';
 import DropdownListItem from '/imports/ui/components/dropdown/list/item/component';
 import DropdownListSeparator from '/imports/ui/components/dropdown/list/separator/component';
 
-const propTypes = {
-  // Emoji status of the current user
-  userEmojiStatus: PropTypes.string.isRequired,
-  actions: PropTypes.object.isRequired,
-};
-
-class EmojiMenu extends Component {
-  constructor(props) {
-    super(props);
-  }
-
-  render() {
-    const {
-     userEmojiStatus,
-     actions,
-     intl,
-   } = this.props;
-
-    return (
-      <Dropdown autoFocus>
-        <DropdownTrigger tabIndex={0}>
-          <Button
-            role="button"
-            label={intl.formatMessage(intlMessages.statusTriggerLabel)}
-            aria-label={intl.formatMessage(intlMessages.changeStatusLabel)}
-            aria-describedby="currentStatus"
-            icon="hand"
-            ghost={false}
-            circle
-            hideLabel={false}
-            color="primary"
-            size="lg"
-
-            // FIXME: Without onClick react proptypes keep warning
-            // even after the DropdownTrigger inject an onClick handler
-            onClick={() => null}
-          >
-            <div id="currentStatus" hidden>
-              {
-                intl.formatMessage(intlMessages.currentStatusDesc, { 0: userEmojiStatus })
-              }
-            </div>
-          </Button>
-        </DropdownTrigger>
-        <DropdownContent placement="top left">
-          <DropdownList>
-            <DropdownListItem
-              icon="hand"
-              label={intl.formatMessage(intlMessages.raiseLabel)}
-              description={intl.formatMessage(intlMessages.raiseDesc)}
-              onClick={() => actions.setEmojiHandler('raiseHand')}
-              tabIndex={-1}
-            />
-            <DropdownListItem
-              icon="happy"
-              label={intl.formatMessage(intlMessages.happyLabel)}
-              description={intl.formatMessage(intlMessages.happyDesc)}
-              onClick={() => actions.setEmojiHandler('happy')}
-              tabIndex={-1}
-            />
-            <DropdownListItem
-              icon="undecided"
-              label={intl.formatMessage(intlMessages.undecidedLabel)}
-              description={intl.formatMessage(intlMessages.undecidedDesc)}
-              onClick={() => actions.setEmojiHandler('neutral')}
-              tabIndex={-1}
-            />
-            <DropdownListItem
-              icon="sad"
-              label={intl.formatMessage(intlMessages.sadLabel)}
-              description={intl.formatMessage(intlMessages.sadDesc)}
-              onClick={() => actions.setEmojiHandler('sad')}
-              tabIndex={-1}
-            />
-            <DropdownListItem
-              icon="confused"
-              label={intl.formatMessage(intlMessages.confusedLabel)}
-              description={intl.formatMessage(intlMessages.confusedDesc)}
-              onClick={() => actions.setEmojiHandler('confused')}
-              tabIndex={-1}
-            />
-            <DropdownListItem
-              icon="time"
-              label={intl.formatMessage(intlMessages.awayLabel)}
-              description={intl.formatMessage(intlMessages.awayDesc)}
-              onClick={() => actions.setEmojiHandler('away')}
-              tabIndex={-1}
-            />
-            <DropdownListItem
-              icon="thumbs_up"
-              label={intl.formatMessage(intlMessages.thumbsUpLabel)}
-              description={intl.formatMessage(intlMessages.thumbsUpDesc)}
-              onClick={() => actions.setEmojiHandler('thumbsUp')}
-              tabIndex={-1}
-            />
-            <DropdownListItem
-              icon="thumbs_down"
-              label={intl.formatMessage(intlMessages.thumbsDownLabel)}
-              description={intl.formatMessage(intlMessages.thumbsDownDesc)}
-              onClick={() => actions.setEmojiHandler('thumbsDown')}
-              tabIndex={-1}
-            />
-            <DropdownListItem
-              icon="applause"
-              label={intl.formatMessage(intlMessages.applauseLabel)}
-              description={intl.formatMessage(intlMessages.applauseDesc)}
-              onClick={() => actions.setEmojiHandler('applause')}
-              tabIndex={-1}
-            />
-            <DropdownListSeparator />
-            <DropdownListItem
-              icon="clear_status"
-              label={intl.formatMessage(intlMessages.clearLabel)}
-              description={intl.formatMessage(intlMessages.clearDesc)}
-              onClick={() => actions.setEmojiHandler('none')}
-              tabIndex={-1}
-            />
-          </DropdownList>
-        </DropdownContent>
-      </Dropdown>
-    );
-  }
-}
+import { EMOJI_NORMALIZE } from '/imports/utils/statuses';
 
 const intlMessages = defineMessages({
   statusTriggerLabel: {
@@ -229,5 +107,118 @@ const intlMessages = defineMessages({
   },
 });
 
+const propTypes = {
+  // Emoji status of the current user
+  userEmojiStatus: PropTypes.string.isRequired,
+  actions: PropTypes.object.isRequired,
+};
+
+const EmojiMenu = ({
+ userEmojiStatus,
+ actions,
+ intl,
+}) => (
+  <Dropdown autoFocus>
+    <DropdownTrigger tabIndex={0}>
+      <Button
+        role="button"
+        label={intl.formatMessage(intlMessages.statusTriggerLabel)}
+        aria-label={intl.formatMessage(intlMessages.changeStatusLabel)}
+        aria-describedby="currentStatus"
+        icon={userEmojiStatus in EMOJI_NORMALIZE ?
+          EMOJI_NORMALIZE[userEmojiStatus] : 'hand'}
+        ghost={false}
+        circle
+        hideLabel={false}
+        color="primary"
+        size="lg"
+
+        // FIXME: Without onClick react proptypes keep warning
+        // even after the DropdownTrigger inject an onClick handler
+        onClick={() => null}
+      >
+        <div id="currentStatus" hidden>
+          { intl.formatMessage(intlMessages.currentStatusDesc, { 0: userEmojiStatus }) }
+        </div>
+      </Button>
+    </DropdownTrigger>
+    <DropdownContent placement="top left">
+      <DropdownList>
+        <DropdownListItem
+          icon="hand"
+          label={intl.formatMessage(intlMessages.raiseLabel)}
+          description={intl.formatMessage(intlMessages.raiseDesc)}
+          onClick={() => actions.setEmojiHandler('raiseHand')}
+          tabIndex={-1}
+        />
+        <DropdownListItem
+          icon="happy"
+          label={intl.formatMessage(intlMessages.happyLabel)}
+          description={intl.formatMessage(intlMessages.happyDesc)}
+          onClick={() => actions.setEmojiHandler('happy')}
+          tabIndex={-1}
+        />
+        <DropdownListItem
+          icon="undecided"
+          label={intl.formatMessage(intlMessages.undecidedLabel)}
+          description={intl.formatMessage(intlMessages.undecidedDesc)}
+          onClick={() => actions.setEmojiHandler('neutral')}
+          tabIndex={-1}
+        />
+        <DropdownListItem
+          icon="sad"
+          label={intl.formatMessage(intlMessages.sadLabel)}
+          description={intl.formatMessage(intlMessages.sadDesc)}
+          onClick={() => actions.setEmojiHandler('sad')}
+          tabIndex={-1}
+        />
+        <DropdownListItem
+          icon="confused"
+          label={intl.formatMessage(intlMessages.confusedLabel)}
+          description={intl.formatMessage(intlMessages.confusedDesc)}
+          onClick={() => actions.setEmojiHandler('confused')}
+          tabIndex={-1}
+        />
+        <DropdownListItem
+          icon="time"
+          label={intl.formatMessage(intlMessages.awayLabel)}
+          description={intl.formatMessage(intlMessages.awayDesc)}
+          onClick={() => actions.setEmojiHandler('away')}
+          tabIndex={-1}
+        />
+        <DropdownListItem
+          icon="thumbs_up"
+          label={intl.formatMessage(intlMessages.thumbsUpLabel)}
+          description={intl.formatMessage(intlMessages.thumbsUpDesc)}
+          onClick={() => actions.setEmojiHandler('thumbsUp')}
+          tabIndex={-1}
+        />
+        <DropdownListItem
+          icon="thumbs_down"
+          label={intl.formatMessage(intlMessages.thumbsDownLabel)}
+          description={intl.formatMessage(intlMessages.thumbsDownDesc)}
+          onClick={() => actions.setEmojiHandler('thumbsDown')}
+          tabIndex={-1}
+        />
+        <DropdownListItem
+          icon="applause"
+          label={intl.formatMessage(intlMessages.applauseLabel)}
+          description={intl.formatMessage(intlMessages.applauseDesc)}
+          onClick={() => actions.setEmojiHandler('applause')}
+          tabIndex={-1}
+        />
+        <DropdownListSeparator />
+        <DropdownListItem
+          icon="clear_status"
+          label={intl.formatMessage(intlMessages.clearLabel)}
+          description={intl.formatMessage(intlMessages.clearDesc)}
+          onClick={() => actions.setEmojiHandler('none')}
+          tabIndex={-1}
+        />
+      </DropdownList>
+    </DropdownContent>
+  </Dropdown>
+);
+
 EmojiMenu.propTypes = propTypes;
 export default injectIntl(EmojiMenu);
diff --git a/bigbluebutton-html5/imports/ui/components/app/container.jsx b/bigbluebutton-html5/imports/ui/components/app/container.jsx
index 709d37304763f93e155a03f620ed202f1651e5cb..4813274ec076f96d6ca1b2c0f2701057c92a6c16 100644
--- a/bigbluebutton-html5/imports/ui/components/app/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/app/container.jsx
@@ -2,7 +2,7 @@ import React, { cloneElement } from 'react';
 import { createContainer } from 'meteor/react-meteor-data';
 import { withRouter } from 'react-router';
 import { defineMessages, injectIntl } from 'react-intl';
-
+import PropTypes from 'prop-types';
 import Auth from '/imports/ui/services/auth';
 import Users from '/imports/api/2.0/users';
 import Breakouts from '/imports/api/2.0/breakouts';
@@ -13,6 +13,7 @@ import ClosedCaptionsContainer from '/imports/ui/components/closed-captions/cont
 import {
   getFontSize,
   getCaptionsStatus,
+  meetingIsBreakout,
 } from './service';
 
 import { withModalMounter } from '../modal/service';
@@ -22,6 +23,14 @@ import NavBarContainer from '../nav-bar/container';
 import ActionsBarContainer from '../actions-bar/container';
 import MediaContainer from '../media/container';
 
+const propTypes = {
+  navbar: PropTypes.node,
+  actionsbar: PropTypes.node,
+  media: PropTypes.node,
+  location: PropTypes.object.isRequired,
+  children: PropTypes.node.isRequired,
+};
+
 const defaultProps = {
   navbar: <NavBarContainer />,
   actionsbar: <ActionsBarContainer />,
@@ -45,10 +54,22 @@ const intlMessages = defineMessages({
 
 const AppContainer = (props) => {
   // inject location on the navbar container
-  const navbarWithLocation = cloneElement(props.navbar, { location: props.location });
+  const {
+    navbar,
+    actionsbar,
+    media,
+    ...otherProps
+  } = props;
+
+  const navbarWithLocation = cloneElement(navbar, { location: props.location });
 
   return (
-    <App {...props} navbar={navbarWithLocation}>
+    <App
+      navbar={navbarWithLocation}
+      actionsbar={actionsbar}
+      media={media}
+      {...otherProps}
+    >
       {props.children}
     </App>
   );
@@ -83,7 +104,9 @@ export default withRouter(injectIntl(withModalMounter(createContainer((
   // forcelly logged out when the meeting is ended
   Meetings.find({ meetingId: Auth.meetingID }).observeChanges({
     removed() {
-      sendToError(410, intl.formatMessage(intlMessages.endMeetingMessage));
+      if (!meetingIsBreakout) {
+        sendToError(410, intl.formatMessage(intlMessages.endMeetingMessage));
+      }
     },
   });
 
@@ -101,3 +124,4 @@ export default withRouter(injectIntl(withModalMounter(createContainer((
 }, AppContainer))));
 
 AppContainer.defaultProps = defaultProps;
+AppContainer.propTypes = propTypes;
diff --git a/bigbluebutton-html5/imports/ui/components/button/styles.scss b/bigbluebutton-html5/imports/ui/components/button/styles.scss
index f25bf612ef695c5024225866bd0a243f3e05180d..c10260a0a9d692ca892889de8fa09bf2827f85e4 100644
--- a/bigbluebutton-html5/imports/ui/components/button/styles.scss
+++ b/bigbluebutton-html5/imports/ui/components/button/styles.scss
@@ -46,6 +46,7 @@ $btn-jumbo-padding: $jumbo-padding-y $jumbo-padding-x;
   vertical-align: middle;
   cursor: pointer;
   user-select: none;
+  transition: all .2s ease-in-out;
 
   &:hover,
   &:focus {
@@ -99,7 +100,6 @@ $btn-jumbo-padding: $jumbo-padding-y $jumbo-padding-x;
     opacity: .85;
     display: block;
     margin-top: $btn-spacing;
-    font-size: 90%;
     color: #fff;
     font-weight: normal;
     line-height: 1.5;
diff --git a/bigbluebutton-html5/imports/ui/components/chat/chat-dropdown/component.jsx b/bigbluebutton-html5/imports/ui/components/chat/chat-dropdown/component.jsx
index 87c94d86fa9e83d1e17e15af1c5feb80854d7bcc..894ec742b1b63a6e38625575567840ad315f9048 100644
--- a/bigbluebutton-html5/imports/ui/components/chat/chat-dropdown/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/chat/chat-dropdown/component.jsx
@@ -4,7 +4,7 @@ import cx from 'classnames';
 import { withModalMounter } from '/imports/ui/components/modal/service';
 import Clipboard from 'clipboard';
 import _ from 'lodash';
-import Button from '/imports/ui/components/button/component';
+import Icon from '/imports/ui/components/icon/component';
 import Dropdown from '/imports/ui/components/dropdown/component';
 import DropdownTrigger from '/imports/ui/components/dropdown/trigger/component';
 import DropdownContent from '/imports/ui/components/dropdown/content/component';
@@ -118,17 +118,12 @@ class ChatDropdown extends Component {
         onShow={this.onActionsShow}
         onHide={this.onActionsHide}
       >
-        <DropdownTrigger tabIndex={0}>
-          <Button
-            label={intl.formatMessage(intlMessages.options)}
-            icon="more"
-            circle
-            hideLabel
-            className={cx(styles.btn, styles.btnSettings)}
-            // FIXME: Without onClick react proptypes keep warning
-            // even after the DropdownTrigger inject an onClick handler
-            onClick={() => null}
-          />
+        <DropdownTrigger
+          tabIndex={0}
+          ariaLabel={intl.formatMessage(intlMessages.options)}
+          className={styles.btn}
+        >
+          <Icon iconName="more" />
         </DropdownTrigger>
         <DropdownContent placement="bottom right">
           <DropdownList>
diff --git a/bigbluebutton-html5/imports/ui/components/chat/chat-dropdown/styles.scss b/bigbluebutton-html5/imports/ui/components/chat/chat-dropdown/styles.scss
index 020412197717d4e7be0b66a512b1c7d76e6ac9ef..d45076abba5c8f1576b77289aaf34479039fb0a6 100644
--- a/bigbluebutton-html5/imports/ui/components/chat/chat-dropdown/styles.scss
+++ b/bigbluebutton-html5/imports/ui/components/chat/chat-dropdown/styles.scss
@@ -2,18 +2,5 @@
 
 .btn {
   flex: 0 0;
-  margin-left: $sm-padding-x / 2;
-
-  i{
-  color: black !important;
-  }
-
-  &:hover,
-  &:focus {
-    span {
-      background-color: transparent !important;
-      color: $color-white !important;
-      opacity: .75;
-    }
-  }
+  margin-top: auto;
 }
diff --git a/bigbluebutton-html5/imports/ui/components/chat/component.jsx b/bigbluebutton-html5/imports/ui/components/chat/component.jsx
index 6bb60620934b3e95fe0df71cebe70c20547a9e74..e40eb35f60c80bc7966fee4022b418ac88fb461c 100644
--- a/bigbluebutton-html5/imports/ui/components/chat/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/chat/component.jsx
@@ -1,6 +1,8 @@
-import React, { Component } from 'react';
+import React from 'react';
+import PropTypes from 'prop-types';
 import { Link } from 'react-router';
 import { defineMessages, injectIntl } from 'react-intl';
+import injectWbResizeEvent from '/imports/ui/components/presentation/resize-wrapper/component';
 import styles from './styles';
 import MessageForm from './message-form/component';
 import MessageList from './message-list/component';
@@ -20,86 +22,102 @@ const intlMessages = defineMessages({
   },
 });
 
-class Chat extends Component {
-  constructor(props) {
-    super(props);
-  }
+const Chat = (props) => {
+  const {
+    chatID,
+    chatName,
+    title,
+    messages,
+    scrollPosition,
+    hasUnreadMessages,
+    lastReadMessageTime,
+    partnerIsLoggedOut,
+    isChatLocked,
+    minMessageLength,
+    maxMessageLength,
+    actions,
+    intl,
+  } = props;
 
-  componentDidMount() {
-    // to let the whiteboard know that the presentation area's size has changed
-    window.dispatchEvent(new Event('resize'));
-  }
-
-  componentWillUnmount() {
-    // to let the whiteboard know that the presentation area's size has changed
-    window.dispatchEvent(new Event('resize'));
-  }
-
-  render() {
-    const {
-      chatID,
-      chatName,
-      title,
-      messages,
-      scrollPosition,
-      hasUnreadMessages,
-      lastReadMessageTime,
-      partnerIsLoggedOut,
-      isChatLocked,
-      minMessageLength,
-      maxMessageLength,
-      actions,
-      intl,
-    } = this.props;
-
-    return (
-      <div className={styles.chat}>
-        <header className={styles.header}>
-          <div className={styles.title}>
+  return (
+    <div className={styles.chat}>
+      <header className={styles.header}>
+        <div className={styles.title}>
+          <Link
+            to="/users"
+            role="button"
+            aria-label={intl.formatMessage(intlMessages.hideChatLabel, { 0: title })}
+          >
+            <Icon iconName="left_arrow" /> {title}
+          </Link>
+        </div>
+        {
+          chatID !== 'public' ?
             <Link
               to="/users"
               role="button"
-              aria-label={intl.formatMessage(intlMessages.hideChatLabel, { 0: title })}
+              className={styles.closeIcon}
+              aria-label={intl.formatMessage(intlMessages.closeChatLabel, { 0: title })}
             >
-              <Icon iconName="left_arrow" /> {title}
-            </Link>
-          </div>
-          {
-            chatID !== 'public' ?
-              <Link
-                to="/users"
-                role="button"
-                className={styles.closeIcon}
-                aria-label={intl.formatMessage(intlMessages.closeChatLabel, { 0: title })}
-              >
-                <Icon iconName="close" onClick={() => actions.handleClosePrivateChat(chatID)} />
-              </Link> :
-              <ChatDropdown />
-          }
-        </header>
-        <MessageList
-          chatId={chatID}
-          messages={messages}
-          id={ELEMENT_ID}
-          scrollPosition={scrollPosition}
-          hasUnreadMessages={hasUnreadMessages}
-          handleScrollUpdate={actions.handleScrollUpdate}
-          handleReadMessage={actions.handleReadMessage}
-          lastReadMessageTime={lastReadMessageTime}
-          partnerIsLoggedOut={partnerIsLoggedOut}
-        />
-        <MessageForm
-          disabled={isChatLocked}
-          chatAreaId={ELEMENT_ID}
-          chatTitle={title}
-          chatName={chatName}
-          minMessageLength={minMessageLength}
-          maxMessageLength={maxMessageLength}
-          handleSendMessage={actions.handleSendMessage}
-        />
-      </div>
-    );
-  }
-}
+              <Icon iconName="close" onClick={() => actions.handleClosePrivateChat(chatID)} />
+            </Link> :
+            <ChatDropdown />
+        }
+      </header>
+      <MessageList
+        chatId={chatID}
+        messages={messages}
+        id={ELEMENT_ID}
+        scrollPosition={scrollPosition}
+        hasUnreadMessages={hasUnreadMessages}
+        handleScrollUpdate={actions.handleScrollUpdate}
+        handleReadMessage={actions.handleReadMessage}
+        lastReadMessageTime={lastReadMessageTime}
+        partnerIsLoggedOut={partnerIsLoggedOut}
+      />
+      <MessageForm
+        disabled={isChatLocked}
+        chatAreaId={ELEMENT_ID}
+        chatTitle={title}
+        chatName={chatName}
+        minMessageLength={minMessageLength}
+        maxMessageLength={maxMessageLength}
+        handleSendMessage={actions.handleSendMessage}
+      />
+    </div>
+  );
+};
+
+export default injectWbResizeEvent(injectIntl(Chat));
 
-export default injectIntl(Chat);
+Chat.propTypes = {
+  chatID: PropTypes.string.isRequired,
+  chatName: PropTypes.string.isRequired,
+  title: PropTypes.string.isRequired,
+  messages: PropTypes.arrayOf(
+    PropTypes.objectOf(
+      PropTypes.oneOfType([
+        PropTypes.array,
+        PropTypes.string,
+        PropTypes.number,
+        PropTypes.object,
+      ]),
+    ).isRequired,
+  ).isRequired,
+  scrollPosition: PropTypes.number,
+  hasUnreadMessages: PropTypes.bool.isRequired,
+  lastReadMessageTime: PropTypes.number.isRequired,
+  partnerIsLoggedOut: PropTypes.bool.isRequired,
+  isChatLocked: PropTypes.bool.isRequired,
+  minMessageLength: PropTypes.number.isRequired,
+  maxMessageLength: PropTypes.number.isRequired,
+  actions: PropTypes.shape({
+    handleClosePrivateChat: PropTypes.func.isRequired,
+    handleReadMessage: PropTypes.func.isRequired,
+    handleScrollUpdate: PropTypes.func.isRequired,
+    handleSendMessage: PropTypes.func.isRequired,
+  }).isRequired,
+  intl: PropTypes.shape({
+    formatMessage: PropTypes.func.isRequired,
+  }).isRequired,
+};
diff --git a/bigbluebutton-html5/imports/ui/components/chat/message-form/styles.scss b/bigbluebutton-html5/imports/ui/components/chat/message-form/styles.scss
index fc07712b5caa4c3d774c547526c3d27158253dcf..d40826f530dea7235222611fea94b571deacd6c4 100644
--- a/bigbluebutton-html5/imports/ui/components/chat/message-form/styles.scss
+++ b/bigbluebutton-html5/imports/ui/components/chat/message-form/styles.scss
@@ -70,6 +70,11 @@
 
 .sendButton {
   margin-left: $sm-padding-x;
+  align-self: flex-end;
+
+  i {
+    font-size: 115% !important;
+  }
 }
 
 .info {
diff --git a/bigbluebutton-html5/imports/ui/components/chat/message-list/message-list-item/styles.scss b/bigbluebutton-html5/imports/ui/components/chat/message-list/message-list-item/styles.scss
index b68a8d01f19c7de13f5a5437868f2b1c91208c3f..9f6f665d8329aacf411394be0c42f40ac5cb4a56 100644
--- a/bigbluebutton-html5/imports/ui/components/chat/message-list/message-list-item/styles.scss
+++ b/bigbluebutton-html5/imports/ui/components/chat/message-list/message-list-item/styles.scss
@@ -16,13 +16,31 @@
 }
 
 .systemMessage {
-  .item + &,
-  & + .item {
-    margin-bottom: $line-height-computed * 1.5;
+  padding: $line-height-computed 0;
+  border-bottom: 1px solid $color-gray-lighter;
+
+  .item:not(&) + & {
+    border-top: 1px solid $color-gray-lighter;
+  }
+
+  & + & {
+    margin-top: -$line-height-computed;
+  }
+
+  &:last-child {
+    border-bottom: none;
   }
 
   .message {
-    color: $color-heading;
+    color: $color-gray;
+
+
+    // hide the <br> we dont want from the default WelcomeMessage
+    br:first-child,
+    br:last-child,
+    br + br {
+      display: none;
+    }
   }
 }
 
@@ -70,7 +88,6 @@
   display: flex;
   min-width: 0;
   font-weight: 600;
-  color: $color-gray-light;
   text-transform: capitalize;
   font-style: italic;
 
diff --git a/bigbluebutton-html5/imports/ui/components/chat/message-list/styles.scss b/bigbluebutton-html5/imports/ui/components/chat/message-list/styles.scss
index 2cf89614b17b618ba2b32b2db1fd0a8cc1ca96c4..8e4af86678558bb1a5366391693313618bb818c6 100644
--- a/bigbluebutton-html5/imports/ui/components/chat/message-list/styles.scss
+++ b/bigbluebutton-html5/imports/ui/components/chat/message-list/styles.scss
@@ -11,9 +11,11 @@ $padding: $md-padding-x;
   position: relative;
   overflow-x: hidden;
   overflow-y: auto;
+  padding-left: $padding;
+  margin-left: -$padding;
   padding-right: $padding;
-  padding-bottom: $padding;
   margin-right: -$padding;
+  padding-bottom: $padding;
   margin-bottom: -$padding;
 }
 
@@ -29,10 +31,11 @@ $padding: $md-padding-x;
 }
 
 .unreadButton {
-  flex-grow: 0;
   flex-shrink: 0;
-  border-radius: 0;
+  width: 100%;
   text-transform: uppercase;
-  margin-bottom: .5rem;
+  // margin-top: .25rem;
+  margin-bottom: .25rem;
+  background-color: darken($color-white, 5%);
   @extend %text-elipsis;
 }
diff --git a/bigbluebutton-html5/imports/ui/components/closed-captions/component.jsx b/bigbluebutton-html5/imports/ui/components/closed-captions/component.jsx
index 6d16c52d426ef961707153bb21ab0b49817c94dd..9831e593e3acc68327c6fbdc9578f003a3f4f907 100644
--- a/bigbluebutton-html5/imports/ui/components/closed-captions/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/closed-captions/component.jsx
@@ -1,15 +1,29 @@
-import React from 'react';
+import React, { Component } from 'react';
 import PropTypes from 'prop-types';
+import injectWbResizeEvent from '/imports/ui/components/presentation/resize-wrapper/component';
 import styles from './styles.scss';
-import { findDOMNode } from 'react-dom';
 
-export default class ClosedCaptions extends React.Component {
+class ClosedCaptions extends Component {
   constructor(props) {
     super(props);
 
     this.shouldScrollBottom = false;
   }
 
+  componentWillUpdate() {
+    const node = this.refCCScrollArea;
+
+    // number 4 is for the border
+    // offset height includes the border, but scrollheight doesn't
+    this.shouldScrollBottom = (node.scrollTop + node.offsetHeight) - 4 === node.scrollHeight;
+  }
+
+  componentDidUpdate() {
+    if (this.shouldScrollBottom) {
+      this.refCCScrollArea.scrollTop = this.refCCScrollArea.scrollHeight;
+    }
+  }
+
   renderCaptions(caption) {
     const text = caption.captions;
     const captionStyles = {
@@ -29,31 +43,6 @@ export default class ClosedCaptions extends React.Component {
     );
   }
 
-  componentDidMount() {
-    // to let the whiteboard know that the presentation area's size has changed
-    window.dispatchEvent(new Event('resize'));
-  }
-
-  componentWillUnmount() {
-    // to let the whiteboard know that the presentation area's size has changed
-    window.dispatchEvent(new Event('resize'));
-  }
-
-  componentWillUpdate() {
-    const node = findDOMNode(this.ccScrollArea);
-
-    // number 4 is for the border
-    // offset height includes the border, but scrollheight doesn't
-    this.shouldScrollBottom = node.scrollTop + node.offsetHeight - 4 === node.scrollHeight;
-  }
-
-  componentDidUpdate() {
-    if (this.shouldScrollBottom) {
-      const node = findDOMNode(this.ccScrollArea);
-      node.scrollTop = node.scrollHeight;
-    }
-  }
-
   render() {
     const {
       locale,
@@ -64,10 +53,10 @@ export default class ClosedCaptions extends React.Component {
     return (
       <div disabled className={styles.ccbox}>
         <div className={styles.title}>
-          <p> {locale || 'Locale is not selected'} </p>
+          <p> {locale} </p>
         </div>
         <div
-          ref={(ref) => { this.ccScrollArea = ref; }}
+          ref={(ref) => { this.refCCScrollArea = ref; }}
           className={styles.frame}
           style={{ background: backgroundColor }}
         >
@@ -79,3 +68,27 @@ export default class ClosedCaptions extends React.Component {
     );
   }
 }
+
+export default injectWbResizeEvent(ClosedCaptions);
+
+ClosedCaptions.propTypes = {
+  backgroundColor: PropTypes.string.isRequired,
+  captions: PropTypes.arrayOf(
+    PropTypes.shape({
+      ownerId: PropTypes.string.isRequired,
+      captions: PropTypes.arrayOf(
+        PropTypes.shape({
+          captions: PropTypes.string.isRequired,
+        }).isRequired,
+      ).isRequired,
+    }).isRequired,
+  ).isRequired,
+  locale: PropTypes.string.isRequired,
+  fontColor: PropTypes.string.isRequired,
+  fontSize: PropTypes.string.isRequired,
+  fontFamily: PropTypes.string.isRequired,
+};
+
+ClosedCaptions.defaultProps = {
+  locale: 'Locale is not selected',
+};
diff --git a/bigbluebutton-html5/imports/ui/components/closed-captions/container.jsx b/bigbluebutton-html5/imports/ui/components/closed-captions/container.jsx
index a7ba7bf422e0b576938badc91f379c008438a05c..a8da014e7cb5ca165425f3ea9df6c2c6e36bfe18 100644
--- a/bigbluebutton-html5/imports/ui/components/closed-captions/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/closed-captions/container.jsx
@@ -1,21 +1,10 @@
-import React, { Component } from 'react';
-import PropTypes from 'prop-types';
+import React from 'react';
 import { createContainer } from 'meteor/react-meteor-data';
-import ClosedCaptionsService from './service.js';
+import ClosedCaptionsService from './service';
 import ClosedCaptions from './component';
 
-class ClosedCaptionsContainer extends Component {
-  constructor(props) {
-    super(props);
-  }
-
-  render() {
-    return (
-      <ClosedCaptions {...this.props}>
-        {this.props.children}
-      </ClosedCaptions>
-    );
-  }
-}
+const ClosedCaptionsContainer = props => (
+  <ClosedCaptions {...props} />
+ );
 
 export default createContainer(() => ClosedCaptionsService.getCCData(), ClosedCaptionsContainer);
diff --git a/bigbluebutton-html5/imports/ui/components/dropdown/trigger/component.jsx b/bigbluebutton-html5/imports/ui/components/dropdown/trigger/component.jsx
index b2e3b07265ec01eca3b8e6d7a6dec184a3073b8e..a55cb8a379976891038a02d2af3d539ba4038ce9 100644
--- a/bigbluebutton-html5/imports/ui/components/dropdown/trigger/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/dropdown/trigger/component.jsx
@@ -41,16 +41,14 @@ export default class DropdownTrigger extends Component {
   }
 
   render() {
-    const { children, style, className, tabIndex } = this.props;
+    const { children, className, ...restProps } = this.props;
     const TriggerComponent = React.Children.only(children);
 
-    const TriggerComponentBounded = React.cloneElement(children, {
+    const TriggerComponentBounded = React.cloneElement(TriggerComponent, {
+      ...restProps,
       onClick: this.handleClick,
       onKeyDown: this.handleKeyDown,
       'aria-haspopup': true,
-      tabIndex,
-      style,
-
       className: cx(children.props.className, className),
     });
 
diff --git a/bigbluebutton-html5/imports/ui/components/nav-bar/styles.scss b/bigbluebutton-html5/imports/ui/components/nav-bar/styles.scss
index 80aa5ef1338b1816635efaf89fd7f6cc8321d951..48ea6b771e74ff36608a91be320d7eca2e783102 100644
--- a/bigbluebutton-html5/imports/ui/components/nav-bar/styles.scss
+++ b/bigbluebutton-html5/imports/ui/components/nav-bar/styles.scss
@@ -46,11 +46,12 @@
     content: '';
     position: absolute;
     border-radius: 50%;
-    width: 10px;
-    height: 10px;
-    bottom: 0;
-    right: 0;
+    width: 12px;
+    height: 12px;
+    bottom: 2px;
+    right: 3px;
     background-color: $color-danger;
+    border: 2px solid;
   }
 }
 
@@ -73,7 +74,6 @@
 }
 
 .btnSettings {
-  transform: rotate(90deg);
 }
 
 .dropdownBreakout {
diff --git a/bigbluebutton-html5/imports/ui/components/notifications-bar/component.jsx b/bigbluebutton-html5/imports/ui/components/notifications-bar/component.jsx
index 70d3585102ce7f71b49c3b73bf54666579d1541b..378d27ff5d6c29ed3b669376cb597728e617011c 100644
--- a/bigbluebutton-html5/imports/ui/components/notifications-bar/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/notifications-bar/component.jsx
@@ -1,6 +1,7 @@
-import React, { Component } from 'react';
+import React from 'react';
 import PropTypes from 'prop-types';
 import cx from 'classnames';
+import injectWbResizeEvent from '/imports/ui/components/presentation/resize-wrapper/component';
 import styles from './styles.scss';
 
 const COLORS = [
@@ -8,6 +9,7 @@ const COLORS = [
 ];
 
 const propTypes = {
+  children: PropTypes.string.isRequired,
   color: PropTypes.oneOf(COLORS),
 };
 
@@ -15,31 +17,20 @@ const defaultProps = {
   color: 'default',
 };
 
-export default class NotificationsBar extends Component {
-
-  componentDidMount() {
-    // to let the whiteboard know that the presentation area's size has changed
-    window.dispatchEvent(new Event('resize'));
-  }
-
-  componentWillUnmount() {
-    // to let the whiteboard know that the presentation area's size has changed
-    window.dispatchEvent(new Event('resize'));
-  }
-
-  render() {
-    const { color } = this.props;
-
-    return (
-      <div
-        role="alert"
-        className={cx(styles.notificationsBar, styles[color])}
-      >
-        {this.props.children}
-      </div>
-    );
-  }
-}
+const NotificationsBar = (props) => {
+  const { color } = props;
+
+  return (
+    <div
+      role="alert"
+      className={cx(styles.notificationsBar, styles[color])}
+    >
+      {props.children}
+    </div>
+  );
+};
 
 NotificationsBar.propTypes = propTypes;
 NotificationsBar.defaultProps = defaultProps;
+
+export default injectWbResizeEvent(NotificationsBar);
diff --git a/bigbluebutton-html5/imports/ui/components/polling/component.jsx b/bigbluebutton-html5/imports/ui/components/polling/component.jsx
index 99edf9551500a93f8602e32ca9f183ff0acac8ea..97fa2bf55013d83aa87e723f71f1859f79f9f346 100644
--- a/bigbluebutton-html5/imports/ui/components/polling/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/polling/component.jsx
@@ -1,7 +1,9 @@
-import React from 'react';
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
 import Button from '/imports/ui/components/button/component';
-import styles from './styles.scss';
 import { defineMessages, injectIntl } from 'react-intl';
+import injectWbResizeEvent from '/imports/ui/components/presentation/resize-wrapper/component';
+import styles from './styles.scss';
 
 const intlMessages = defineMessages({
   pollingTitleLabel: {
@@ -10,20 +12,7 @@ const intlMessages = defineMessages({
   },
 });
 
-class PollingComponent extends React.Component {
-  constructor(props) {
-    super(props);
-  }
-
-  componentDidMount() {
-    // to let the whiteboard know that the presentation area's size has changed
-    window.dispatchEvent(new Event('resize'));
-  }
-
-  componentWillUnmount() {
-    // to let the whiteboard know that the presentation area's size has changed
-    window.dispatchEvent(new Event('resize'));
-  }
+class PollingComponent extends Component {
 
   getStyles() {
     const number = this.props.poll.answers.length + 1;
@@ -49,9 +38,9 @@ class PollingComponent extends React.Component {
             {intl.formatMessage(intlMessages.pollingTitleLabel)}
           </p>
         </div>
-        {poll.answers.map((pollAnswer, index) =>
+        {poll.answers.map(pollAnswer =>
           (<div
-            key={index}
+            key={pollAnswer.id}
             style={calculatedStyles}
             className={styles.pollButtonWrapper}
           >
@@ -83,4 +72,20 @@ class PollingComponent extends React.Component {
   }
 }
 
-export default injectIntl(PollingComponent);
+export default injectWbResizeEvent(injectIntl(PollingComponent));
+
+PollingComponent.propTypes = {
+  intl: PropTypes.shape({
+    formatMessage: PropTypes.func.isRequired,
+  }).isRequired,
+  handleVote: PropTypes.func.isRequired,
+  poll: PropTypes.shape({
+    pollId: PropTypes.string.isRequired,
+    answers: PropTypes.arrayOf(
+      PropTypes.shape({
+        id: PropTypes.number.isRequired,
+        key: PropTypes.string.isRequired,
+      }).isRequired,
+    ).isRequired,
+  }).isRequired,
+};
diff --git a/bigbluebutton-html5/imports/ui/components/presentation/component.jsx b/bigbluebutton-html5/imports/ui/components/presentation/component.jsx
index e9e5cb35a319d3f397441712b9f3abddb5884f85..a5ea9298fc39db3850200bbb774a9e1b92f32d28 100644
--- a/bigbluebutton-html5/imports/ui/components/presentation/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/presentation/component.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { Component } from 'react';
 import PropTypes from 'prop-types';
 import CSSTransitionGroup from 'react-transition-group/CSSTransitionGroup';
 import WhiteboardOverlayContainer from '/imports/ui/components/whiteboard/whiteboard-overlay/container';
@@ -12,7 +12,7 @@ import Slide from './slide/component';
 import styles from './styles.scss';
 
 
-export default class PresentationArea extends React.Component {
+export default class PresentationArea extends Component {
   constructor() {
     super();
 
@@ -59,7 +59,7 @@ export default class PresentationArea extends React.Component {
       // if a user is a presenter - this means there is a whiteboard toolbar on the right
       // and we have to get the width/height of the refWhiteboardArea
       // (inner hidden div with absolute position)
-      if (this.props.userIsPresenter) {
+      if (this.props.userIsPresenter || this.props.multiUser) {
         clientHeight = refWhiteboardArea.clientHeight;
         clientWidth = refWhiteboardArea.clientWidth;
       }
@@ -132,19 +132,19 @@ export default class PresentationArea extends React.Component {
   // renders the whole presentation area
   renderPresentationArea() {
     // sometimes tomcat publishes the slide url, but the actual file is not accessible (why?)
-    if (this.props.currentSlide &&
-        this.props.currentSlide.calculatedData &&
-        this.props.currentSlide.calculatedData.width &&
-        this.props.currentSlide.calculatedData.height) {
+    if (!this.props.currentSlide ||
+        !this.props.currentSlide.calculatedData) {
+      return null;
+    }
       // to control the size of the svg wrapper manually
       // and adjust cursor's thickness, so that svg didn't scale it automatically
-      const adjustedSizes = this.calculateSize();
+    const adjustedSizes = this.calculateSize();
 
       // a reference to the slide object
-      const slideObj = this.props.currentSlide;
+    const slideObj = this.props.currentSlide;
 
       // retrieving the pre-calculated data from the slide object
-      const {
+    const {
         x,
         y,
         width,
@@ -154,70 +154,68 @@ export default class PresentationArea extends React.Component {
         imageUri,
       } = slideObj.calculatedData;
 
-      return (
-        <div
-          style={{
-            width: adjustedSizes.width,
-            height: adjustedSizes.height,
-            WebkitTransition: 'width 0.2s', /* Safari */
-            transition: 'width 0.2s',
+    return (
+      <div
+        style={{
+          width: adjustedSizes.width,
+          height: adjustedSizes.height,
+          WebkitTransition: 'width 0.2s', /* Safari */
+          transition: 'width 0.2s',
+        }}
+      >
+        <CSSTransitionGroup
+          transitionName={{
+            enter: styles.enter,
+            enterActive: styles.enterActive,
+            appear: styles.appear,
+            appearActive: styles.appearActive,
           }}
+          transitionAppear
+          transitionEnter
+          transitionLeave={false}
+          transitionAppearTimeout={400}
+          transitionEnterTimeout={400}
+          transitionLeaveTimeout={400}
         >
-          <CSSTransitionGroup
-            transitionName={{
-              enter: styles.enter,
-              enterActive: styles.enterActive,
-              appear: styles.appear,
-              appearActive: styles.appearActive,
-            }}
-            transitionAppear
-            transitionEnter
-            transitionLeave={false}
-            transitionAppearTimeout={400}
-            transitionEnterTimeout={400}
-            transitionLeaveTimeout={400}
+          <svg
+            width={width}
+            height={height}
+            ref={(ref) => { if (ref != null) { this.svggroup = ref; } }}
+            viewBox={`${x} ${y} ${viewBoxWidth} ${viewBoxHeight}`}
+            version="1.1"
+            xmlns="http://www.w3.org/2000/svg"
+            className={styles.svgStyles}
+            key={slideObj.id}
           >
-            <svg
-              width={width}
-              height={height}
-              ref={(ref) => { if (ref != null) { this.svggroup = ref; } }}
-              viewBox={`${x} ${y} ${viewBoxWidth} ${viewBoxHeight}`}
-              version="1.1"
-              xmlns="http://www.w3.org/2000/svg"
-              className={styles.svgStyles}
-              key={slideObj.id}
-            >
-              <defs>
-                <clipPath id="viewBox">
-                  <rect x={x} y={y} width="100%" height="100%" fill="none" />
-                </clipPath>
-              </defs>
-              <g clipPath="url(#viewBox)">
-                <Slide
-                  id="slideComponent"
-                  imageUri={imageUri}
-                  svgWidth={width}
-                  svgHeight={height}
-                />
-                <AnnotationGroupContainer
-                  width={width}
-                  height={height}
-                  whiteboardId={slideObj.id}
-                />
-                <CursorWrapperContainer
-                  widthRatio={slideObj.widthRatio}
-                  physicalWidthRatio={adjustedSizes.width / width}
-                  slideWidth={width}
-                  slideHeight={height}
-                />
-              </g>
-              {this.renderOverlays(slideObj, adjustedSizes)}
-            </svg>
-          </CSSTransitionGroup>
-        </div>
-      );
-    }
-    return null;
+            <defs>
+              <clipPath id="viewBox">
+                <rect x={x} y={y} width="100%" height="100%" fill="none" />
+              </clipPath>
+            </defs>
+            <g clipPath="url(#viewBox)">
+              <Slide
+                id="slideComponent"
+                imageUri={imageUri}
+                svgWidth={width}
+                svgHeight={height}
+              />
+              <AnnotationGroupContainer
+                width={width}
+                height={height}
+                whiteboardId={slideObj.id}
+              />
+              <CursorWrapperContainer
+                widthRatio={slideObj.widthRatio}
+                physicalWidthRatio={adjustedSizes.width / width}
+                slideWidth={width}
+                slideHeight={height}
+              />
+            </g>
+            {this.renderOverlays(slideObj, adjustedSizes)}
+          </svg>
+        </CSSTransitionGroup>
+      </div>
+    );
   }
 
   renderOverlays(slideObj, adjustedSizes) {
@@ -271,17 +269,18 @@ export default class PresentationArea extends React.Component {
   }
 
   renderWhiteboardToolbar() {
-    if (this.props.currentSlide) {
-      const adjustedSizes = this.calculateSize();
-
-      return (
-        <WhiteboardToolbarContainer
-          whiteboardId={this.props.currentSlide.id}
-          height={adjustedSizes.height}
-        />
-      );
+    if (!this.props.currentSlide ||
+        !this.props.currentSlide.calculatedData) {
+      return null;
     }
-    return null;
+
+    const adjustedSizes = this.calculateSize();
+    return (
+      <WhiteboardToolbarContainer
+        whiteboardId={this.props.currentSlide.id}
+        height={adjustedSizes.height}
+      />
+    );
   }
 
   render() {
@@ -329,7 +328,7 @@ PresentationArea.propTypes = {
       viewBoxWidth: PropTypes.number.isRequired,
       viewBoxHeight: PropTypes.number.isRequired,
       imageUri: PropTypes.string.isRequired,
-    }).isRequired,
+    }),
   }),
   // current multi-user status
   multiUser: PropTypes.bool.isRequired,
diff --git a/bigbluebutton-html5/imports/ui/components/presentation/container.jsx b/bigbluebutton-html5/imports/ui/components/presentation/container.jsx
index fc3bca1968b8dc286ad7f6da8fc9820abad400b1..a45c819198873819ff534ca223e081c503bd7eac 100644
--- a/bigbluebutton-html5/imports/ui/components/presentation/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/presentation/container.jsx
@@ -3,7 +3,7 @@ import { createContainer } from 'meteor/react-meteor-data';
 import PresentationAreaService from './service';
 import PresentationArea from './component';
 
-const PresentationAreaContainer = ({ ...props }) => (
+const PresentationAreaContainer = props => (
   <PresentationArea {...props} />
 );
 
diff --git a/bigbluebutton-html5/imports/ui/components/presentation/cursor/component.jsx b/bigbluebutton-html5/imports/ui/components/presentation/cursor/component.jsx
index e15af7ab1711270795d2508e37773fd13a95eb53..ada7003b6f496ee917c7f809d4de1b69e4566f83 100644
--- a/bigbluebutton-html5/imports/ui/components/presentation/cursor/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/presentation/cursor/component.jsx
@@ -3,20 +3,18 @@ import PropTypes from 'prop-types';
 
 export default class Cursor extends Component {
 
-  static scale(attribute, propsObj) {
-    const { widthRatio, physicalWidthRatio } = propsObj;
+  static scale(attribute, widthRatio, physicalWidthRatio) {
     return ((attribute * widthRatio) / 100) / physicalWidthRatio;
   }
 
-  static invertScale(attribute, propsObj) {
-    const { widthRatio, physicalWidthRatio } = propsObj;
+  static invertScale(attribute, widthRatio, physicalWidthRatio) {
     return ((attribute * physicalWidthRatio) * 100) / widthRatio;
   }
 
-  static getCursorCoordinates(props) {
+  static getCursorCoordinates(cursorX, cursorY, slideWidth, slideHeight) {
     // main cursor x and y coordinates
-    const x = (props.cursorX / 100) * props.slideWidth;
-    const y = (props.cursorY / 100) * props.slideHeight;
+    const x = (cursorX / 100) * slideWidth;
+    const y = (cursorY / 100) * slideHeight;
 
     return {
       x,
@@ -24,9 +22,7 @@ export default class Cursor extends Component {
     };
   }
 
-  static getFillAndLabel(props) {
-    const { presenter, isMultiUser } = props;
-
+  static getFillAndLabel(presenter, isMultiUser) {
     const obj = {
       fill: 'green',
       displayLabel: false,
@@ -69,15 +65,20 @@ export default class Cursor extends Component {
   }
 
   componentWillMount() {
-    const cursorCoordinate = Cursor.getCursorCoordinates(this.props);
-    const { fill, displayLabel } = Cursor.getFillAndLabel(this.props);
-    const _scaledSizes = Cursor.getScaledSizes(this.props);
+    const { cursorX, cursorY, slideWidth, slideHeight, presenter, isMultiUser } = this.props;
 
     // setting the initial cursor info
-    this.cursorCoordinate = cursorCoordinate;
+    this.scaledSizes = Cursor.getScaledSizes(this.props);
+    this.cursorCoordinate = Cursor.getCursorCoordinates(
+      cursorX,
+      cursorY,
+      slideWidth,
+      slideHeight,
+    );
+
+    const { fill, displayLabel } = Cursor.getFillAndLabel(presenter, isMultiUser);
     this.fill = fill;
     this.displayLabel = displayLabel;
-    this.scaledSizes = _scaledSizes;
   }
 
   componentDidMount() {
@@ -98,7 +99,10 @@ export default class Cursor extends Component {
     } = this.props;
 
     if (presenter !== nextProps.presenter || isMultiUser !== nextProps.isMultiUser) {
-      const { fill, displayLabel } = Cursor.getFillAndLabel(nextProps);
+      const { fill, displayLabel } = Cursor.getFillAndLabel(
+        nextProps.presenter,
+        nextProps.isMultiUser,
+      );
       this.displayLabel = displayLabel;
       this.fill = fill;
     }
@@ -108,12 +112,16 @@ export default class Cursor extends Component {
       ||
         (labelBoxWidth !== nextProps.labelBoxWidth ||
           labelBoxHeight !== nextProps.labelBoxHeight)) {
-      const _scaledSizes = Cursor.getScaledSizes(nextProps);
-      this.scaledSizes = _scaledSizes;
+      this.scaledSizes = Cursor.getScaledSizes(nextProps);
     }
 
     if (cursorX !== nextProps.cursorX || cursorY !== nextProps.cursorY) {
-      const cursorCoordinate = Cursor.getCursorCoordinates(nextProps);
+      const cursorCoordinate = Cursor.getCursorCoordinates(
+        nextProps.cursorX,
+        nextProps.cursorY,
+        nextProps.slideWidth,
+        nextProps.slideHeight,
+      );
       this.cursorCoordinate = cursorCoordinate;
     }
   }
@@ -125,9 +133,10 @@ export default class Cursor extends Component {
 
     if (this.cursorLabelRef) {
       const { width, height } = this.cursorLabelRef.getBBox();
+      const { widthRatio, physicalWidthRatio } = this.props;
 
-      labelBoxWidth = Cursor.invertScale(width, this.props);
-      labelBoxHeight = Cursor.invertScale(height, this.props);
+      labelBoxWidth = Cursor.invertScale(width, widthRatio, physicalWidthRatio);
+      labelBoxHeight = Cursor.invertScale(height, widthRatio, physicalWidthRatio);
 
       // if the width of the text node is bigger than the maxSize - set the width to maxWidth
       if (labelBoxWidth > this.props.cursorLabelBox.maxWidth) {
@@ -235,6 +244,11 @@ Cursor.propTypes = {
   // Slide physical size to original size ratio
   physicalWidthRatio: PropTypes.number.isRequired,
 
+  // Slide width (svg)
+  slideWidth: PropTypes.number.isRequired,
+  // Slide height (svg)
+  slideHeight: PropTypes.number.isRequired,
+
   /**
    * Defines the cursor radius (not scaled)
    * @defaultValue 5
@@ -267,7 +281,6 @@ Cursor.propTypes = {
 
 Cursor.defaultProps = {
   radius: 5,
-
   cursorLabelText: {
     // text Y shift (10 points down)
     textDY: 10,
diff --git a/bigbluebutton-html5/imports/ui/components/presentation/cursor/cursor-wrapper-container/container.jsx b/bigbluebutton-html5/imports/ui/components/presentation/cursor/cursor-wrapper-container/container.jsx
index f766bbc5e98fdc9fee20a1f0f62e141c5e808f53..96c2d724d8f5855605e543878c654de9235881b3 100644
--- a/bigbluebutton-html5/imports/ui/components/presentation/cursor/cursor-wrapper-container/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/presentation/cursor/cursor-wrapper-container/container.jsx
@@ -29,16 +29,14 @@ const CursorWrapperContainer = ({ presenterCursorId, multiUserCursorIds, ...rest
       />
         : null }
 
-    {multiUserCursorIds.length > 0 ?
-          multiUserCursorIds.map(cursorId =>
-            (<CursorContainer
-              key={cursorId._id}
-              cursorId={cursorId._id}
-              presenter={false}
-              {...rest}
-            />),
-          )
-        : null }
+    {multiUserCursorIds.map(cursorId =>
+      (<CursorContainer
+        key={cursorId._id}
+        cursorId={cursorId._id}
+        presenter={false}
+        {...rest}
+      />),
+    )}
   </g>
 );
 
diff --git a/bigbluebutton-html5/imports/ui/components/presentation/cursor/cursor-wrapper-container/service.js b/bigbluebutton-html5/imports/ui/components/presentation/cursor/cursor-wrapper-container/service.js
index 6540751b80e75872322aa61f9d8655dc1383571a..bee7d97f56c35765e8f962c6933d310318fb4f5f 100644
--- a/bigbluebutton-html5/imports/ui/components/presentation/cursor/cursor-wrapper-container/service.js
+++ b/bigbluebutton-html5/imports/ui/components/presentation/cursor/cursor-wrapper-container/service.js
@@ -5,12 +5,7 @@ import Users from '/imports/api/2.0/users';
 
 const getMultiUserStatus = () => {
   const data = WhiteboardMultiUser.findOne({ meetingId: Auth.meetingID });
-
-  if (data) {
-    return data.multiUser;
-  }
-
-  return false;
+  return data ? data.multiUser : false;
 };
 
 const getPresenterCursorId = userId => Cursor.findOne({ userId }, { fields: { _id: 1 } });
@@ -30,18 +25,24 @@ const getCurrentCursorIds = () => {
   // checking whether multiUser mode is on or off
   const isMultiUser = getMultiUserStatus();
 
-  if (isMultiUser && data.presenterCursorId) {
-    // it's a multi-user mode - fetching all the cursors except the presenter's
-    const selector = {
-      _id: {
-        $ne: data.presenterCursorId._id,
-      },
-    };
+  // it's a multi-user mode - fetching all the cursors except the presenter's
+  if (isMultiUser) {
+    let selector = {};
     const filter = {
       fields: {
         _id: 1,
       },
     };
+
+    // if there is a presenter cursor - excluding it from the query
+    if (data.presenterCursorId) {
+      selector = {
+        _id: {
+          $ne: data.presenterCursorId._id,
+        },
+      };
+    }
+
     data.multiUserCursorIds = Cursor.find(selector, filter).fetch();
   } else {
     // it's not multi-user, assigning an empty array
diff --git a/bigbluebutton-html5/imports/ui/components/presentation/presentation-toolbar/component.jsx b/bigbluebutton-html5/imports/ui/components/presentation/presentation-toolbar/component.jsx
index 6e9eab3d1a7784694480110527976c40104725d6..a5412544b0461e8d1b4001653b31d5a4ed6b810b 100644
--- a/bigbluebutton-html5/imports/ui/components/presentation/presentation-toolbar/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/presentation/presentation-toolbar/component.jsx
@@ -1,6 +1,7 @@
 import React, { Component } from 'react';
 import PropTypes from 'prop-types';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
+import injectWbResizeEvent from '/imports/ui/components/presentation/resize-wrapper/component';
 import Button from '/imports/ui/components/button/component';
 import styles from './styles.scss';
 
@@ -137,16 +138,6 @@ class PresentationToolbar extends Component {
     this.handleValuesChange = this.handleValuesChange.bind(this);
   }
 
-  componentDidMount() {
-    // to let the whiteboard know that the presentation area's size has changed
-    window.dispatchEvent(new Event('resize'));
-  }
-
-  componentWillUnmount() {
-    // to let the whiteboard know that the presentation area's size has changed
-    window.dispatchEvent(new Event('resize'));
-  }
-
   handleValuesChange(event) {
     this.setState({ sliderValue: event.target.value });
   }
@@ -279,6 +270,9 @@ PresentationToolbar.propTypes = {
     previousSlideHandler: PropTypes.func.isRequired,
     skipToSlideHandler: PropTypes.func.isRequired,
   }).isRequired,
+  intl: PropTypes.shape({
+    formatMessage: PropTypes.func.isRequired,
+  }).isRequired,
 };
 
-export default injectIntl(PresentationToolbar);
+export default injectWbResizeEvent(injectIntl(PresentationToolbar));
diff --git a/bigbluebutton-html5/imports/ui/components/presentation/presentation-toolbar/container.jsx b/bigbluebutton-html5/imports/ui/components/presentation/presentation-toolbar/container.jsx
index a182e102c51f54dca9546dc801c906caca984d61..e414e27505f36303a80b5aaa1ccbd20d144a81ef 100644
--- a/bigbluebutton-html5/imports/ui/components/presentation/presentation-toolbar/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/presentation/presentation-toolbar/container.jsx
@@ -4,7 +4,7 @@ import { createContainer } from 'meteor/react-meteor-data';
 import PresentationToolbarService from './service';
 import PresentationToolbar from './component';
 
-const PresentationToolbarContainer = ({ ...props }) => {
+const PresentationToolbarContainer = (props) => {
   const {
     currentSlideNum,
     userIsPresenter,
diff --git a/bigbluebutton-html5/imports/ui/components/presentation/presentation-toolbar/service.js b/bigbluebutton-html5/imports/ui/components/presentation/presentation-toolbar/service.js
index 35e0ff64c3be99fb0dd5c2985569b218fc3cd05b..b57d5226df1e96ec46b8eba4a7552e5f0510dc94 100644
--- a/bigbluebutton-html5/imports/ui/components/presentation/presentation-toolbar/service.js
+++ b/bigbluebutton-html5/imports/ui/components/presentation/presentation-toolbar/service.js
@@ -16,10 +16,7 @@ const getSlideData = (params) => {
     userId,
   });
 
-  let userIsPresenter;
-  if (currentUser) {
-    userIsPresenter = currentUser.presenter;
-  }
+  const userIsPresenter = currentUser ? currentUser.presenter : false;
 
   // Get total number of slides in this presentation
   const numberOfSlides = Slides.find({
diff --git a/bigbluebutton-html5/imports/ui/components/presentation/presentation-uploader/component.jsx b/bigbluebutton-html5/imports/ui/components/presentation/presentation-uploader/component.jsx
old mode 100755
new mode 100644
diff --git a/bigbluebutton-html5/imports/ui/components/presentation/presentation-uploader/container.jsx b/bigbluebutton-html5/imports/ui/components/presentation/presentation-uploader/container.jsx
old mode 100755
new mode 100644
diff --git a/bigbluebutton-html5/imports/ui/components/presentation/presentation-uploader/service.js b/bigbluebutton-html5/imports/ui/components/presentation/presentation-uploader/service.js
old mode 100755
new mode 100644
diff --git a/bigbluebutton-html5/imports/ui/components/presentation/presentation-uploader/styles.scss b/bigbluebutton-html5/imports/ui/components/presentation/presentation-uploader/styles.scss
old mode 100755
new mode 100644
diff --git a/bigbluebutton-html5/imports/ui/components/presentation/resize-wrapper/component.jsx b/bigbluebutton-html5/imports/ui/components/presentation/resize-wrapper/component.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..c769c78d17b96ad394cfe25a8336aabe962fd118
--- /dev/null
+++ b/bigbluebutton-html5/imports/ui/components/presentation/resize-wrapper/component.jsx
@@ -0,0 +1,20 @@
+import React, { Component } from 'react';
+
+const injectWbResizeEvent = WrappedComponent =>
+  class Resize extends Component {
+    componentDidMount() {
+      window.dispatchEvent(new Event('resize'));
+    }
+
+    componentWillUnmount() {
+      window.dispatchEvent(new Event('resize'));
+    }
+
+    render() {
+      return (
+        <WrappedComponent {...this.props} />
+      );
+    }
+  };
+
+export default injectWbResizeEvent;
diff --git a/bigbluebutton-html5/imports/ui/components/presentation/service.js b/bigbluebutton-html5/imports/ui/components/presentation/service.js
index 3464eb9c66be028eec916c8260ea00693947632e..d7edc9b7b9f4f276a090c17eedbc779251d8c35f 100644
--- a/bigbluebutton-html5/imports/ui/components/presentation/service.js
+++ b/bigbluebutton-html5/imports/ui/components/presentation/service.js
@@ -34,22 +34,12 @@ const getCurrentSlide = () => {
 
 const isPresenter = () => {
   const currentUser = Users.findOne({ userId: Auth.userID });
-
-  if (currentUser) {
-    return currentUser.presenter;
-  }
-
-  return false;
+  return currentUser ? currentUser.presenter : false;
 };
 
 const getMultiUserStatus = () => {
   const data = WhiteboardMultiUser.findOne({ meetingId: Auth.meetingID });
-
-  if (data) {
-    return data.multiUser;
-  }
-
-  return false;
+  return data ? data.multiUser : false;
 };
 
 export default {
diff --git a/bigbluebutton-html5/imports/ui/components/presentation/slide/component.jsx b/bigbluebutton-html5/imports/ui/components/presentation/slide/component.jsx
index bbbfc28b7839ff5bc3b07687acf5bec6d1bd0225..702977d2d9fa56c9fd1b575c584738ce735439e1 100644
--- a/bigbluebutton-html5/imports/ui/components/presentation/slide/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/presentation/slide/component.jsx
@@ -1,7 +1,7 @@
 import React from 'react';
 import PropTypes from 'prop-types';
 
-const Slide = ({ ...props }) => {
+const Slide = (props) => {
   const { imageUri, svgWidth, svgHeight } = props;
 
   return (
diff --git a/bigbluebutton-html5/imports/ui/components/settings/submenus/application/component.jsx b/bigbluebutton-html5/imports/ui/components/settings/submenus/application/component.jsx
index fda261c824c23b0065afa8b13679f4b3eb73abce..cce5d435ab257f75dfac23870b0feacc2ccc8fc7 100644
--- a/bigbluebutton-html5/imports/ui/components/settings/submenus/application/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/settings/submenus/application/component.jsx
@@ -2,12 +2,12 @@ import React from 'react';
 import Modal from 'react-modal';
 import Icon from '/imports/ui/components/icon/component';
 import Button from '/imports/ui/components/button/component';
-import BaseMenu from '../base/component';
 import ReactDOM from 'react-dom';
 import cx from 'classnames';
-import styles from '../styles.scss';
 import Toggle from '/imports/ui/components/switch/component';
 import { defineMessages, injectIntl } from 'react-intl';
+import BaseMenu from '../base/component';
+import styles from '../styles';
 
 const MIN_FONTSIZE = 0;
 const MAX_FONTSIZE = 4;
@@ -96,7 +96,8 @@ class ApplicationMenu extends BaseMenu {
     const currentFontSize = this.state.settings.fontSize;
     const availableFontSizes = this.props.fontSizes;
     const canIncreaseFontSize = availableFontSizes.indexOf(currentFontSize) < MAX_FONTSIZE;
-    const fs = (canIncreaseFontSize) ? availableFontSizes.indexOf(currentFontSize) + 1 : MAX_FONTSIZE;
+    const fs = (canIncreaseFontSize) ?
+      availableFontSizes.indexOf(currentFontSize) + 1 : MAX_FONTSIZE;
     this.changeFontSize(availableFontSizes[fs]);
   }
 
@@ -104,7 +105,8 @@ class ApplicationMenu extends BaseMenu {
     const currentFontSize = this.state.settings.fontSize;
     const availableFontSizes = this.props.fontSizes;
     const canDecreaseFontSize = availableFontSizes.indexOf(currentFontSize) > MIN_FONTSIZE;
-    const fs = (canDecreaseFontSize) ? availableFontSizes.indexOf(currentFontSize) - 1 : MIN_FONTSIZE;
+    const fs = (canDecreaseFontSize) ?
+      availableFontSizes.indexOf(currentFontSize) - 1 : MIN_FONTSIZE;
     this.changeFontSize(availableFontSizes[fs]);
   }
 
@@ -148,6 +150,7 @@ class ApplicationMenu extends BaseMenu {
               </div>
             </div>
           </div>
+          {/* TODO: Uncomment after the release
           <div className={styles.row}>
             <div className={styles.col}>
               <div className={styles.formElement} >
@@ -167,7 +170,7 @@ class ApplicationMenu extends BaseMenu {
                 />
               </div>
             </div>
-          </div>
+          </div>*/}
           <div className={styles.row}>
             <div className={styles.col}>
               <div className={styles.formElement}>
diff --git a/bigbluebutton-html5/imports/ui/components/user-avatar/styles.scss b/bigbluebutton-html5/imports/ui/components/user-avatar/styles.scss
index 05ae6f536485a942ec7f5fcb7c72336bfe91da7c..c636ab4f96c6dbec45fdf3c9fa89e8ab6350d89b 100644
--- a/bigbluebutton-html5/imports/ui/components/user-avatar/styles.scss
+++ b/bigbluebutton-html5/imports/ui/components/user-avatar/styles.scss
@@ -5,7 +5,7 @@
  */
 $user-avatar-border: $color-gray-light;
 $user-avatar-text: $color-white;
-$user-indicators-offset: -.15rem;
+$user-indicators-offset: -5px;
 $user-indicator-presenter-bg: $color-primary;
 $user-indicator-voice-bg: $color-success;
 $user-indicator-muted-bg: $color-danger;
@@ -20,7 +20,7 @@ $user-list-bg: #F3F6F9;
   text-align: center;
   text-transform: capitalize;
   transition: .3s ease-in-out;
-  font-size: 1rem;
+  font-size: .85rem;
 
   &:after, &:before {
     content: "";
@@ -31,9 +31,9 @@ $user-list-bg: #F3F6F9;
     color: inherit;
     top: auto;
     left: auto;
-    bottom: $user-indicators-offset / 2;
+    bottom: $user-indicators-offset;
     right: $user-indicators-offset;
-    border: 1.25px solid $user-list-bg;
+    border: 1.5px solid $user-list-bg;
     border-radius: 50%;
     background-color: $user-indicator-voice-bg;
     color: $user-avatar-text;
@@ -60,7 +60,7 @@ $user-list-bg: #F3F6F9;
   &:before {
     content: "\00a0\e90b\00a0";
     opacity: 1;
-    top: $user-indicators-offset / 2;
+    top: $user-indicators-offset;
     left: $user-indicators-offset;
     bottom: auto;
     right: auto;
diff --git a/bigbluebutton-html5/imports/ui/components/user-list/chat-list-item/styles.scss b/bigbluebutton-html5/imports/ui/components/user-list/chat-list-item/styles.scss
index a507cf4c17924278f9654f26ed0b52703f03aea8..caac495cda7d2dcabaab84eec44b78531e87fb16 100644
--- a/bigbluebutton-html5/imports/ui/components/user-list/chat-list-item/styles.scss
+++ b/bigbluebutton-html5/imports/ui/components/user-list/chat-list-item/styles.scss
@@ -6,6 +6,7 @@
   cursor: pointer;
   padding: 0;
   text-decoration: none;
+  color: $color-gray-dark;
 }
 
 .chatListItemLink {
diff --git a/bigbluebutton-html5/imports/ui/components/user-list/component.jsx b/bigbluebutton-html5/imports/ui/components/user-list/component.jsx
index 6091961f5cdfbf49715382d701595d5a15371a43..5b4d61c507fa8c0795fd7b01608f9f3cd436bbba 100644
--- a/bigbluebutton-html5/imports/ui/components/user-list/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/user-list/component.jsx
@@ -2,6 +2,8 @@ import React, { Component } from 'react';
 import { injectIntl } from 'react-intl';
 import PropTypes from 'prop-types';
 import { withRouter } from 'react-router';
+
+import injectWbResizeEvent from '/imports/ui/components/presentation/resize-wrapper/component';
 import styles from './styles';
 import UserListHeader from './user-list-header/component';
 import UserContent from './user-list-content/component';
@@ -52,10 +54,10 @@ class UserList extends Component {
   render() {
     return (
       <div className={styles.userList}>
-        <UserListHeader
+        {/* <UserListHeader
           intl={this.props.intl}
           compact={this.state.compact}
-        />
+        /> */}
         {<UserContent
           intl={this.props.intl}
           openChats={this.props.openChats}
@@ -82,4 +84,4 @@ class UserList extends Component {
 UserList.propTypes = propTypes;
 UserList.defaultProps = defaultProps;
 
-export default withRouter(injectIntl(UserList));
+export default withRouter(injectWbResizeEvent(injectIntl(UserList)));
diff --git a/bigbluebutton-html5/imports/ui/components/user-list/container.jsx b/bigbluebutton-html5/imports/ui/components/user-list/container.jsx
old mode 100755
new mode 100644
diff --git a/bigbluebutton-html5/imports/ui/components/user-list/service.js b/bigbluebutton-html5/imports/ui/components/user-list/service.js
old mode 100755
new mode 100644
diff --git a/bigbluebutton-html5/imports/ui/components/user-list/styles.scss b/bigbluebutton-html5/imports/ui/components/user-list/styles.scss
index f40d05a25accc5f7f184809ef7b7b2fcc7a4fbda..b7d24ee75f56d607a8e2bf6d2d52f70a740fefe1 100644
--- a/bigbluebutton-html5/imports/ui/components/user-list/styles.scss
+++ b/bigbluebutton-html5/imports/ui/components/user-list/styles.scss
@@ -61,6 +61,7 @@ $user-icons-color-hover: $color-gray;
   background-color: $user-list-bg;
   color: $user-list-text;
   height: 100vh;
+  padding-top: $md-padding-x;
 }
 
 .lists {
@@ -77,15 +78,6 @@ $user-icons-color-hover: $color-gray;
   flex-shrink: 1;
 }
 
-.smallTitle {
-  font-size: 0.85rem;
-  font-weight: 600;
-  text-transform: uppercase;
-  padding: 0 $sm-padding-x;
-  margin: 0 0 ($lg-padding-x / 2) 0;
-  color: $color-gray-light;
-}
-
 .participants, .messages {
   flex-grow: 0;
   display: flex;
@@ -94,7 +86,6 @@ $user-icons-color-hover: $color-gray;
 }
 
 .messages {
-  margin-bottom: $lg-padding-x;
 }
 
 .participants {
@@ -105,6 +96,15 @@ $user-icons-color-hover: $color-gray;
   overflow-y: auto;
 }
 
+.smallTitle {
+  font-size: 0.85rem;
+  font-weight: 600;
+  text-transform: uppercase;
+  padding: 0 $sm-padding-x;
+  margin: ($md-padding-x / 2) 0 0 0;
+  color: $color-gray-light;
+}
+
 .enter, .appear {
   opacity: 0.01;
 }
diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/styles.scss b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/styles.scss
index 560ffd1881df487299c7229ba00318843e4c0dd9..77695e3c8f347e23390e21a83a19d197307fd201 100644
--- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/styles.scss
+++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/styles.scss
@@ -1,4 +1,5 @@
 @import "/imports/ui/components/user-list/styles.scss";
+@import "/imports/ui/stylesheets/mixins/_scrollable";
 
 .content {
   @extend %flex-column;
@@ -8,4 +9,5 @@
 
 .scrollableList {
   @extend %customListFocus;
-}
\ No newline at end of file
+  @include scrollbox-vertical();
+}
diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-messages/styles.scss b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-messages/styles.scss
index e97a9ea3a9d3fc979cd95dc96abe5d2df8d688ee..3f3cc128b073e709889776ac4cff34d88ec2cf5a 100644
--- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-messages/styles.scss
+++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-messages/styles.scss
@@ -1,12 +1,7 @@
 @import "/imports/ui/components/user-list/styles.scss";
 
 .smallTitle {
-  font-size: 0.85rem;
-  font-weight: 600;
-  text-transform: uppercase;
-  padding: 0 $sm-padding-x;
-  margin: 0 0 ($lg-padding-x / 2) 0;
-  color: $color-gray-light;
+  @extend .smallTitle;
 }
 
 .scrollableList {
@@ -25,4 +20,4 @@
   @extend .lists;
   overflow-x: hidden;
   flex-shrink: 1;
-}
\ No newline at end of file
+}
diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/component.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/component.jsx
index cd458b47d223e2781e6dd5010016e820ae3d68dd..e3100b4bd5af036fdbbb54ac8a079c21498f652e 100644
--- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/component.jsx
@@ -96,16 +96,26 @@ const intlMessages = defineMessages({
 
 class UserParticipants extends Component {
 
+  constructor() {
+    super();
+
+    this.getScrollContainerRef = this.getScrollContainerRef.bind(this);
+  }
+
   componentDidMount() {
     if (!this.props.compact) {
-      this._usersList.addEventListener('keydown',
+      this.refScrollContainer.addEventListener('keydown',
         event => this.props.rovingIndex(event,
-          this._usersList,
-          this._userItems,
+          this.refScrollContainer,
+          this.refScrollItems,
           this.props.users.length));
     }
   }
 
+  getScrollContainerRef() {
+    return this.refScrollContainer;
+  }
+
   render() {
     const {
       users,
@@ -181,7 +191,8 @@ class UserParticipants extends Component {
           className={styles.scrollableList}
           role="tabpanel"
           tabIndex={0}
-          ref={(ref) => { this._usersList = ref; }}
+          refScrollContainer
+          ref={(ref) => { this.refScrollContainer = ref; }}
         >
           <CSSTransitionGroup
             transitionName={listTransition}
@@ -194,7 +205,7 @@ class UserParticipants extends Component {
             component="div"
             className={cx(styles.participantsList, styles.scrollableList)}
           >
-            <div ref={(ref) => { this._userItems = ref; }}>
+            <div ref={(ref) => { this.refScrollItems = ref; }}>
               {
                 users.map(user => (
                   <UserListItem
@@ -208,6 +219,7 @@ class UserParticipants extends Component {
                     getAvailableActions={getAvailableActions}
                     normalizeEmojiName={normalizeEmojiName}
                     isMeetingLocked={isMeetingLocked}
+                    getScrollContainerRef={this.getScrollContainerRef}
                   />
                 ))
               }
diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/component.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/component.jsx
old mode 100755
new mode 100644
index de8a636db6c630b1d81c11a9e5f0273071d6fa41..7310566300424a5fa984fb128afa5171ffd1ac94
--- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/component.jsx
@@ -30,6 +30,7 @@ const propTypes = {
   meeting: PropTypes.shape({}).isRequired,
   isMeetingLocked: PropTypes.func.isRequired,
   normalizeEmojiName: PropTypes.func.isRequired,
+  getScrollContainerRef: PropTypes.func.isRequired,
 };
 
 const defaultProps = {
@@ -105,6 +106,7 @@ class UserListItem extends Component {
       meeting,
       isMeetingLocked,
       normalizeEmojiName,
+      getScrollContainerRef,
     } = this.props;
 
     const actions = this.getUsersActions();
@@ -117,6 +119,7 @@ class UserListItem extends Component {
       actions={actions}
       meeting={meeting}
       isMeetingLocked={isMeetingLocked}
+      getScrollContainerRef={getScrollContainerRef}
     />);
 
     return contents;
diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/user-list-content/component.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/user-list-content/component.jsx
index 184da45328b6c01ae178a86879b4e6d54ef6a52f..9af1a7808be463022222e4aa582b5e3106c32d82 100644
--- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/user-list-content/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/user-list-content/component.jsx
@@ -52,6 +52,7 @@ const propTypes = {
   actions: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
   meeting: PropTypes.shape({}).isRequired,
   isMeetingLocked: PropTypes.func.isRequired,
+  getScrollContainerRef: PropTypes.func.isRequired,
 };
 
 
@@ -90,7 +91,7 @@ class UserListContent extends Component {
 
   onActionsShow() {
     const dropdown = findDOMNode(this.dropdown);
-    const scrollContainer = dropdown.parentElement.parentElement;
+    const scrollContainer = this.props.getScrollContainerRef();
     const dropdownTrigger = dropdown.children[0];
 
     this.setState({
@@ -109,7 +110,8 @@ class UserListContent extends Component {
       dropdownVisible: false,
     });
 
-    findDOMNode(this).parentElement.removeEventListener('scroll', this.handleScroll, false);
+    const scrollContainer = this.props.getScrollContainerRef();
+    scrollContainer.removeEventListener('scroll', this.handleScroll, false);
   }
 
   getDropdownMenuParent() {
@@ -131,7 +133,7 @@ class UserListContent extends Component {
       const dropdownTrigger = dropdown.children[0];
       const dropdownContent = dropdown.children[1];
 
-      const scrollContainer = dropdown.parentElement.parentElement;
+      const scrollContainer = this.props.getScrollContainerRef();
 
       const nextState = {
         dropdownVisible: true,
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-factory/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-factory/component.jsx
index a0fb86b829cbbec866d9664666ef450c2ce7c68e..4de6fad4d8aba6ef7a68c3ba3dbb14a3f7510dd2 100644
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-factory/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-factory/component.jsx
@@ -10,6 +10,9 @@ import Text from '../annotations/text/container';
 import Triangle from '../annotations/triangle/component';
 import Pencil from '../annotations/pencil/component';
 
+const ANNOTATION_CONFIG = Meteor.settings.public.whiteboard.annotations;
+const DRAW_END = ANNOTATION_CONFIG.status.end;
+
 export default class AnnotationFactory extends Component {
 
   static renderStaticAnnotation(annotationInfo, slideWidth, slideHeight, drawObject) {
@@ -44,7 +47,7 @@ export default class AnnotationFactory extends Component {
   renderAnnotation(annotationInfo) {
     const drawObject = this.props.annotationSelector[annotationInfo.annotationType];
 
-    if (annotationInfo.status === 'DRAW_END') {
+    if (annotationInfo.status === DRAW_END) {
       return AnnotationFactory.renderStaticAnnotation(
           annotationInfo,
           this.props.slideWidth,
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-factory/reactive-annotation/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-factory/reactive-annotation/component.jsx
index 1db318f2773b9a6b41418334da6f6040649e6d71..d6a3b60b5d38a90efaf3a0a795f87a17554af1ea 100644
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-factory/reactive-annotation/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-factory/reactive-annotation/component.jsx
@@ -1,7 +1,7 @@
 import React from 'react';
 import PropTypes from 'prop-types';
 
-const ReactiveAnnotation = ({ ...props }) => {
+const ReactiveAnnotation = (props) => {
   const Component = props.drawObject;
 
   return (
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-factory/reactive-annotation/container.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-factory/reactive-annotation/container.jsx
index 7feadea8d72203a6f1d548dd2bbd7f29012506b9..9124ab46ec73e3126a0da66fa889927339c69c9a 100644
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-factory/reactive-annotation/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-factory/reactive-annotation/container.jsx
@@ -4,7 +4,7 @@ import { createContainer } from 'meteor/react-meteor-data';
 import ReactiveAnnotationService from './service';
 import ReactiveAnnotation from './component';
 
-const ReactiveAnnotationContainer = ({ ...props }) => {
+const ReactiveAnnotationContainer = (props) => {
   if (props.annotation) {
     return (
       <ReactiveAnnotation
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-factory/static-annotation/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-factory/static-annotation/component.jsx
index 2e829dc27419e01ca78b1623796c6f743c8e1e37..3211a6caf61339fd0a3e66ad79416aa149b190a2 100644
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-factory/static-annotation/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-factory/static-annotation/component.jsx
@@ -4,7 +4,7 @@ import StaticAnnotationService from './service';
 
 export default class StaticAnnotation extends React.Component {
 
-  // finished Annotations (status == 'DRAW_END' ) should never update
+  // completed annotations should never update
   shouldComponentUpdate() {
     return false;
   }
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-group/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-group/component.jsx
index 34ebb2b4910cc03348ab0890d8f36cc467d5f850..05da443af91a3c5612da535eb9b8bb080d6f6ddc 100644
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-group/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-group/component.jsx
@@ -2,7 +2,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import AnnotationFactory from '../annotation-factory/component';
 
-const AnnotationGroup = ({ ...props }) => (
+const AnnotationGroup = props => (
   <AnnotationFactory
     annotationsInfo={props.annotationsInfo}
     slideWidth={props.slideWidth}
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-group/container.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-group/container.jsx
index 13177654112e9a47702701e5363c75b7376ee627..53f3fecc97d31ccd05f1e58d19f7225bfd7d367c 100644
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-group/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-group/container.jsx
@@ -4,7 +4,7 @@ import { createContainer } from 'meteor/react-meteor-data';
 import AnnotationGroupService from './service';
 import AnnotationGroup from './component';
 
-const AnnotationGroupContainer = ({ ...props }) => (
+const AnnotationGroupContainer = props => (
   <AnnotationGroup
     annotationsInfo={props.annotationsInfo}
     slideWidth={props.width}
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/text/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/text/component.jsx
index da99ab09d7e2b85cf11c4d734e4601b9e3783092..c7c0e963bbe06c6f613fed441993f74f61c7e31b 100644
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/text/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/text/component.jsx
@@ -2,6 +2,8 @@ import React, { Component } from 'react';
 import PropTypes from 'prop-types';
 import AnnotationHelpers from '../helpers';
 
+const DRAW_END = Meteor.settings.public.whiteboard.annotations.status.end;
+
 export default class TextDrawComponent extends Component {
   static getViewerStyles(results) {
     const styles = {
@@ -53,7 +55,7 @@ export default class TextDrawComponent extends Component {
   }
 
   componentDidMount() {
-    if (this.props.isActive && this.props.annotation.status !== 'DRAW_END') {
+    if (this.props.isActive && this.props.annotation.status !== DRAW_END) {
       this.handleFocus();
     }
   }
@@ -177,7 +179,7 @@ export default class TextDrawComponent extends Component {
   render() {
     const results = this.getCoordinates();
 
-    if (this.props.isActive && this.props.annotation.status !== 'DRAW_END') {
+    if (this.props.isActive && this.props.annotation.status !== DRAW_END) {
       return this.renderPresenterTextShape(results);
     }
     return this.renderViewerTextShape(results);
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/text/container.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/text/container.jsx
index 1c3e38f55043d0e1f691ae2b05feb9816797a49a..b58769135eca5a864281be91a64b7fb4885aa9de 100644
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/text/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/text/container.jsx
@@ -3,7 +3,7 @@ import { createContainer } from 'meteor/react-meteor-data';
 import TextShapeService from './service';
 import TextDrawComponent from './component';
 
-const TextDrawContainer = ({ ...props }) => (
+const TextDrawContainer = props => (
   <TextDrawComponent {...props} />
 );
 
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/text/service.js b/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/text/service.js
index 9bad9191b4a239233c47631083298e6192cbb321..0a319b60bda39699f3dc74d76336272625b23a53 100644
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/text/service.js
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/text/service.js
@@ -3,50 +3,37 @@ import Users from '/imports/api/2.0/users';
 import Auth from '/imports/ui/services/auth';
 import WhiteboardMultiUser from '/imports/api/2.0/whiteboard-multi-user/';
 
+const DRAW_SETTINGS = 'drawSettings';
+
 const setTextShapeValue = (text) => {
-  const drawSettings = Storage.getItem('drawSettings');
+  const drawSettings = Storage.getItem(DRAW_SETTINGS);
   if (drawSettings) {
     drawSettings.textShape.textShapeValue = text;
-    Storage.setItem('drawSettings', JSON.stringify(drawSettings));
+    Storage.setItem(DRAW_SETTINGS, drawSettings);
   }
 };
 
 const resetTextShapeActiveId = () => {
-  const drawSettings = Storage.getItem('drawSettings');
+  const drawSettings = Storage.getItem(DRAW_SETTINGS);
   if (drawSettings) {
     drawSettings.textShape.textShapeActiveId = '';
-    Storage.setItem('drawSettings', JSON.stringify(drawSettings));
+    Storage.setItem(DRAW_SETTINGS, drawSettings);
   }
 };
 
 const isPresenter = () => {
   const currentUser = Users.findOne({ userId: Auth.userID });
-
-  if (currentUser) {
-    return currentUser.presenter;
-  }
-
-  return false;
+  return currentUser ? currentUser.presenter : false;
 };
 
 const getMultiUserStatus = () => {
   const data = WhiteboardMultiUser.findOne({ meetingId: Auth.meetingID });
-
-  if (data) {
-    return data.multiUser;
-  }
-
-  return false;
+  return data ? data.multiUser : false;
 };
 
 const activeTextShapeId = () => {
-  const drawSettings = Storage.getItem('drawSettings');
-
-  if (drawSettings) {
-    return drawSettings.textShape.textShapeActiveId;
-  }
-
-  return '';
+  const drawSettings = Storage.getItem(DRAW_SETTINGS);
+  return drawSettings ? drawSettings.textShape.textShapeActiveId : '';
 };
 
 export default {
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/container.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/container.jsx
index 193e7e89022483d58fd29f58232127d48d25bc65..6db90e596807ee7bf6529ab8e974de4a2ffe56b8 100644
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/container.jsx
@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
 import WhiteboardOverlayService from './service';
 import WhiteboardOverlay from './component';
 
-const WhiteboardOverlayContainer = ({ ...props }) => {
+const WhiteboardOverlayContainer = (props) => {
   if (Object.keys(props.drawSettings).length > 0) {
     return (
       <WhiteboardOverlay {...props} />
@@ -23,20 +23,23 @@ export default createContainer(() => ({
 
 
 WhiteboardOverlayContainer.propTypes = {
-  drawSettings: PropTypes.shape({
-    // Annotation color
-    color: PropTypes.number.isRequired,
-    // Annotation thickness (not normalized)
-    thickness: PropTypes.number.isRequired,
-    // The name of the tool currently selected
-    tool: PropTypes.string.isRequired,
-    // Font size for the text shape
-    textFontSize: PropTypes.number.isRequired,
-    // Current active text shape value
-    textShapeValue: PropTypes.string.isRequired,
-    // Text active text shape id
-    textShapeActiveId: PropTypes.string.isRequired,
-  }),
+  drawSettings: PropTypes.oneOfType([
+    PropTypes.shape({
+      // Annotation color
+      color: PropTypes.number.isRequired,
+      // Annotation thickness (not normalized)
+      thickness: PropTypes.number.isRequired,
+      // The name of the tool currently selected
+      tool: PropTypes.string.isRequired,
+      // Font size for the text shape
+      textFontSize: PropTypes.number.isRequired,
+      // Current active text shape value
+      textShapeValue: PropTypes.string.isRequired,
+      // Text active text shape id
+      textShapeActiveId: PropTypes.string.isRequired,
+    }),
+    PropTypes.object.isRequired,
+  ]),
 };
 
 WhiteboardOverlayContainer.defaultProps = {
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/pencil-draw-listener/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/pencil-draw-listener/component.jsx
index 774c7d3415d30c9513557ad3d003fc243d332489..814b5b035a6b96376997c1dd8a2d257590f68fb2 100644
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/pencil-draw-listener/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/pencil-draw-listener/component.jsx
@@ -2,7 +2,11 @@ import React, { Component } from 'react';
 import PropTypes from 'prop-types';
 import styles from '../styles.scss';
 
-const MESSAGE_INTERVAL = 50;
+const ANNOTATION_CONFIG = Meteor.settings.public.whiteboard.annotations;
+const MESSAGE_FREQUENCY = ANNOTATION_CONFIG.message_frequency;
+const DRAW_START = ANNOTATION_CONFIG.status.start;
+const DRAW_UPDATE = ANNOTATION_CONFIG.status.update;
+const DRAW_END = ANNOTATION_CONFIG.status.end;
 
 export default class PencilDrawListener extends Component {
   constructor() {
@@ -55,10 +59,10 @@ export default class PencilDrawListener extends Component {
 
       // sending the first message
       const _points = [transformedSvgPoint.x, transformedSvgPoint.y];
-      this.handleDrawPencil(_points, 'DRAW_START', generateNewShapeId());
+      this.handleDrawPencil(_points, DRAW_START, generateNewShapeId());
 
       // All the DRAW_UPDATE messages will be send on timer by sendCoordinates func
-      this.intervalId = setInterval(this.sendCoordinates, MESSAGE_INTERVAL);
+      this.intervalId = setInterval(this.sendCoordinates, MESSAGE_FREQUENCY);
 
     // if you switch to a different window using Alt+Tab while mouse is down and release it
     // it wont catch mouseUp and will keep tracking the movements. Thus we need this check.
@@ -99,7 +103,7 @@ export default class PencilDrawListener extends Component {
   sendCoordinates() {
     if (this.isDrawing && this.points.length > 0) {
       const { getCurrentShapeId } = this.props.actions;
-      this.handleDrawPencil(this.points, 'DRAW_UPDATE', getCurrentShapeId());
+      this.handleDrawPencil(this.points, DRAW_UPDATE, getCurrentShapeId());
       this.points = [];
     }
   }
@@ -145,7 +149,7 @@ export default class PencilDrawListener extends Component {
 
       this.handleDrawPencil(
         this.points,
-        'DRAW_END',
+        DRAW_END,
         getCurrentShapeId(),
         [Math.round(physicalSlideWidth), Math.round(physicalSlideHeight)],
       );
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/service.js b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/service.js
index 17248925a974f41b1ec1f3f38deae2f88af7dbb0..122f1b6c3a7640417c5e5bd70a46a806cc72d8d1 100644
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/service.js
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/service.js
@@ -2,47 +2,50 @@ import { makeCall } from '/imports/ui/services/api';
 import Storage from '/imports/ui/services/storage/session';
 import Auth from '/imports/ui/services/auth';
 
+const DRAW_SETTINGS = 'drawSettings';
+
 const sendAnnotation = (annotation) => {
   makeCall('sendAnnotation', annotation);
 };
 
 const getWhiteboardToolbarValues = () => {
-  const drawSettings = Storage.getItem('drawSettings');
-  if (drawSettings) {
-    const {
-      whiteboardAnnotationTool,
-      whiteboardAnnotationThickness,
-      whiteboardAnnotationColor,
-      textFontSize,
-      textShape,
-    } = drawSettings;
-
-    return {
-      tool: whiteboardAnnotationTool,
-      thickness: whiteboardAnnotationThickness,
-      color: whiteboardAnnotationColor,
-      textFontSize,
-      textShapeValue: textShape.textShapeValue ? textShape.textShapeValue : '',
-      textShapeActiveId: textShape.textShapeActiveId ? textShape.textShapeActiveId : '',
-    };
+  const drawSettings = Storage.getItem(DRAW_SETTINGS);
+  if (!drawSettings) {
+    return {};
   }
-  return {};
+
+  const {
+    whiteboardAnnotationTool,
+    whiteboardAnnotationThickness,
+    whiteboardAnnotationColor,
+    textFontSize,
+    textShape,
+  } = drawSettings;
+
+  return {
+    tool: whiteboardAnnotationTool,
+    thickness: whiteboardAnnotationThickness,
+    color: whiteboardAnnotationColor,
+    textFontSize,
+    textShapeValue: textShape.textShapeValue ? textShape.textShapeValue : '',
+    textShapeActiveId: textShape.textShapeActiveId ? textShape.textShapeActiveId : '',
+  };
 };
 
 const resetTextShapeSession = () => {
-  const drawSettings = Storage.getItem('drawSettings');
+  const drawSettings = Storage.getItem(DRAW_SETTINGS);
   if (drawSettings) {
     drawSettings.textShape.textShapeValue = '';
     drawSettings.textShape.textShapeActiveId = '';
-    Storage.setItem('drawSettings', JSON.stringify(drawSettings));
+    Storage.setItem(DRAW_SETTINGS, drawSettings);
   }
 };
 
 const setTextShapeActiveId = (id) => {
-  const drawSettings = Storage.getItem('drawSettings');
+  const drawSettings = Storage.getItem(DRAW_SETTINGS);
   if (drawSettings) {
     drawSettings.textShape.textShapeActiveId = id;
-    Storage.setItem('drawSettings', JSON.stringify(drawSettings));
+    Storage.setItem(DRAW_SETTINGS, drawSettings);
   }
 };
 
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/shape-draw-listener/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/shape-draw-listener/component.jsx
index f80c6e3b3a3be4ab98c6caa5beac0179f360c34f..fd8ceaa8b93539c42316cbc18274506c1827af21 100644
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/shape-draw-listener/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/shape-draw-listener/component.jsx
@@ -2,12 +2,17 @@ import React, { Component } from 'react';
 import PropTypes from 'prop-types';
 import styles from '../styles.scss';
 
-const MESSAGE_INTERVAL = 50;
+const ANNOTATION_CONFIG = Meteor.settings.public.whiteboard.annotations;
+const MESSAGE_FREQUENCY = ANNOTATION_CONFIG.message_frequency;
+const DRAW_START = ANNOTATION_CONFIG.status.start;
+const DRAW_UPDATE = ANNOTATION_CONFIG.status.update;
+const DRAW_END = ANNOTATION_CONFIG.status.end;
 
 export default class ShapeDrawListener extends Component {
   constructor(props) {
     super(props);
 
+    // there is no valid defaults for the coordinates, and we wouldn't want them anyway
     this.initialCoordinate = {
       x: undefined,
       y: undefined,
@@ -29,9 +34,9 @@ export default class ShapeDrawListener extends Component {
     // id of the setInterval()
     this.intervalId = 0;
 
-    this.mouseDownHandler = this.mouseDownHandler.bind(this);
-    this.mouseMoveHandler = this.mouseMoveHandler.bind(this);
-    this.mouseUpHandler = this.mouseUpHandler.bind(this);
+    this.handleMouseDown = this.handleMouseDown.bind(this);
+    this.handleMouseMove = this.handleMouseMove.bind(this);
+    this.handleMouseUp = this.handleMouseUp.bind(this);
     this.resetState = this.resetState.bind(this);
     this.sendLastMessage = this.sendLastMessage.bind(this);
     this.sendCoordinates = this.sendCoordinates.bind(this);
@@ -50,15 +55,15 @@ export default class ShapeDrawListener extends Component {
   }
 
   // main mouse down handler
-  mouseDownHandler(event) {
+  handleMouseDown(event) {
     // Sometimes when you Alt+Tab while drawing it can happen that your mouse is up,
     // but the browser didn't catch it. So check it here.
     if (this.isDrawing) {
       return this.sendLastMessage();
     }
 
-    window.addEventListener('mouseup', this.mouseUpHandler);
-    window.addEventListener('mousemove', this.mouseMoveHandler, true);
+    window.addEventListener('mouseup', this.handleMouseUp);
+    window.addEventListener('mousemove', this.handleMouseMove, true);
     this.isDrawing = true;
 
     const {
@@ -77,7 +82,7 @@ export default class ShapeDrawListener extends Component {
     generateNewShapeId();
 
     // setting the initial current status
-    this.currentStatus = 'DRAW_START';
+    this.currentStatus = DRAW_START;
 
     // saving the coordinates for future references
     this.initialCoordinate = {
@@ -91,65 +96,71 @@ export default class ShapeDrawListener extends Component {
     };
 
     // All the messages will be send on timer by sendCoordinates func
-    this.intervalId = setInterval(this.sendCoordinates, MESSAGE_INTERVAL);
+    this.intervalId = setInterval(this.sendCoordinates, MESSAGE_FREQUENCY);
 
     return true;
   }
 
   // main mouse move handler
-  // calls a mouseMove<AnnotationName> handler based on the tool selected
-  mouseMoveHandler(event) {
-    if (this.isDrawing) {
-      const {
-        checkIfOutOfBounds,
-        getTransformedSvgPoint,
-        svgCoordinateToPercentages,
-      } = this.props.actions;
+  handleMouseMove(event) {
+    if (!this.isDrawing) {
+      return;
+    }
 
-      // get the transformed svg coordinate
-      let transformedSvgPoint = getTransformedSvgPoint(event);
+    const {
+      checkIfOutOfBounds,
+      getTransformedSvgPoint,
+      svgCoordinateToPercentages,
+    } = this.props.actions;
 
-      // check if it's out of bounds
-      transformedSvgPoint = checkIfOutOfBounds(transformedSvgPoint);
+    // get the transformed svg coordinate
+    let transformedSvgPoint = getTransformedSvgPoint(event);
 
-      // transforming svg coordinate to percentages relative to the slide width/height
-      transformedSvgPoint = svgCoordinateToPercentages(transformedSvgPoint);
+    // check if it's out of bounds
+    transformedSvgPoint = checkIfOutOfBounds(transformedSvgPoint);
 
-      // saving the last sent coordinate
-      this.currentCoordinate = transformedSvgPoint;
-    }
+    // transforming svg coordinate to percentages relative to the slide width/height
+    transformedSvgPoint = svgCoordinateToPercentages(transformedSvgPoint);
+
+    // saving the last sent coordinate
+    this.currentCoordinate = transformedSvgPoint;
   }
 
   // main mouse up handler
-  mouseUpHandler() {
+  handleMouseUp() {
     this.sendLastMessage();
   }
 
   sendCoordinates() {
     // check the current drawing status
-    if (this.isDrawing) {
-      // check if a current coordinate is not the same as an initial one
-      // it prevents us from drawing dots on random clicks
-      if (this.currentCoordinate.x !== this.initialCoordinate.x ||
-        this.currentCoordinate.y !== this.initialCoordinate.y) {
-        // check if previously sent coordinate is not equal to a current one
-        if (this.currentCoordinate.x !== this.lastSentCoordinate.x ||
-            this.currentCoordinate.y !== this.lastSentCoordinate.y) {
-          const { getCurrentShapeId } = this.props.actions;
-          this.handleDrawCommonAnnotation(
-            this.initialCoordinate,
-            this.currentCoordinate,
-            this.currentStatus,
-            getCurrentShapeId(),
-            this.props.drawSettings.tool,
-          );
-          this.lastSentCoordinate = this.currentCoordinate;
-
-          if (this.currentStatus === 'DRAW_START') {
-            this.currentStatus = 'DRAW_UPDATE';
-          }
-        }
-      }
+    if (!this.isDrawing) {
+      return;
+    }
+    // check if a current coordinate is not the same as an initial one
+    // it prevents us from drawing dots on random clicks
+    if (this.currentCoordinate.x === this.initialCoordinate.x &&
+        this.currentCoordinate.y === this.initialCoordinate.y) {
+      return;
+    }
+
+    // check if previously sent coordinate is not equal to a current one
+    if (this.currentCoordinate.x === this.lastSentCoordinate.x &&
+        this.currentCoordinate.y === this.lastSentCoordinate.y) {
+      return;
+    }
+
+    const { getCurrentShapeId } = this.props.actions;
+    this.handleDrawCommonAnnotation(
+      this.initialCoordinate,
+      this.currentCoordinate,
+      this.currentStatus,
+      getCurrentShapeId(),
+      this.props.drawSettings.tool,
+    );
+    this.lastSentCoordinate = this.currentCoordinate;
+
+    if (this.currentStatus === DRAW_START) {
+      this.currentStatus = DRAW_UPDATE;
     }
   }
 
@@ -160,19 +171,25 @@ export default class ShapeDrawListener extends Component {
 
     if (this.isDrawing) {
       // make sure we are drawing and we have some coordinates sent for this shape before
-      // to prevent sending 'DRAW_END on a random mouse click
+      // to prevent sending DRAW_END on a random mouse click
       if (this.lastSentCoordinate.x && this.lastSentCoordinate.y) {
         const { getCurrentShapeId } = this.props.actions;
-        this.handleDrawCommonAnnotation(this.initialCoordinate, this.currentCoordinate, 'DRAW_END', getCurrentShapeId(), this.props.drawSettings.tool);
+        this.handleDrawCommonAnnotation(
+          this.initialCoordinate,
+          this.currentCoordinate,
+          DRAW_END,
+          getCurrentShapeId(),
+          this.props.drawSettings.tool,
+        );
       }
       this.resetState();
     }
   }
 
   resetState() {
-    // resetting the current state
-    window.removeEventListener('mouseup', this.mouseUpHandler);
-    window.removeEventListener('mousemove', this.mouseMoveHandler, true);
+    // resetting the current drawing state
+    window.removeEventListener('mouseup', this.handleMouseUp);
+    window.removeEventListener('mousemove', this.handleMouseMove, true);
     this.isDrawing = false;
     this.currentStatus = undefined;
     this.initialCoordinate = {
@@ -227,7 +244,7 @@ export default class ShapeDrawListener extends Component {
         role="presentation"
         className={styles[tool]}
         style={{ width: '100%', height: '100%' }}
-        onMouseDown={this.mouseDownHandler}
+        onMouseDown={this.handleMouseDown}
       />
     );
   }
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/text-draw-listener/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/text-draw-listener/component.jsx
index eb4bcb4280748dbd89a851c8e6d3595bbc55a693..bf29ccac2d77482291fe83e5b48af38ac65fc2b2 100644
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/text-draw-listener/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/text-draw-listener/component.jsx
@@ -2,6 +2,11 @@ import React, { Component } from 'react';
 import PropTypes from 'prop-types';
 import styles from '../styles.scss';
 
+const ANNOTATION_CONFIG = Meteor.settings.public.whiteboard.annotations;
+const DRAW_START = ANNOTATION_CONFIG.status.start;
+const DRAW_UPDATE = ANNOTATION_CONFIG.status.update;
+const DRAW_END = ANNOTATION_CONFIG.status.end;
+
 export default class TextDrawListener extends Component {
   constructor() {
     super();
@@ -31,12 +36,12 @@ export default class TextDrawListener extends Component {
     this.currentWidth = undefined;
     this.currentHeight = undefined;
 
-    // current text shape status, it may change between "DRAW_START", "DRAW_UPDATE", "DRAW_END"
+    // current text shape status, it may change between DRAW_START, DRAW_UPDATE, DRAW_END
     this.currentStatus = '';
 
-    this.mouseDownHandler = this.mouseDownHandler.bind(this);
-    this.mouseMoveHandler = this.mouseMoveHandler.bind(this);
-    this.mouseUpHandler = this.mouseUpHandler.bind(this);
+    this.handleMouseDown = this.handleMouseDown.bind(this);
+    this.handleMouseMove = this.handleMouseMove.bind(this);
+    this.handleMouseUp = this.handleMouseUp.bind(this);
     this.resetState = this.resetState.bind(this);
     this.sendLastMessage = this.sendLastMessage.bind(this);
   }
@@ -50,27 +55,29 @@ export default class TextDrawListener extends Component {
   // While the user was drawing it. So we are resetting the state.
   componentWillReceiveProps(nextProps) {
     const { drawSettings } = this.props;
-    const _drawsettings = nextProps.drawSettings;
+    const nextDrawsettings = nextProps.drawSettings;
 
-    if (drawSettings.textShapeActiveId !== '' && _drawsettings.textShapeActiveId === '') {
+    if (drawSettings.textShapeActiveId !== '' && nextDrawsettings.textShapeActiveId === '') {
       this.resetState();
     }
   }
 
   componentDidUpdate(prevProps) {
     const { drawSettings } = this.props;
-    const _drawsettings = prevProps.drawSettings;
-    const _textShapeValue = prevProps.drawSettings.textShapeValue;
+    const prevDrawsettings = prevProps.drawSettings;
+    const prevTextShapeValue = prevProps.drawSettings.textShapeValue;
 
     // Updating the component in cases when:
     // Either color / font-size or text value has changed
     // and excluding the case when the textShapeActiveId changed to ''
-    if ((drawSettings.textFontSize !== _drawsettings.textFontSize ||
-      drawSettings.color !== _drawsettings.color ||
-      drawSettings.textShapeValue !== _textShapeValue) &&
-      drawSettings.textShapeActiveId !== '') {
+    const fontSizeChanged = drawSettings.textFontSize !== prevDrawsettings.textFontSize;
+    const colorChanged = drawSettings.color !== prevDrawsettings.color;
+    const textShapeValueChanged = drawSettings.textShapeValue !== prevTextShapeValue;
+    const textShapeIdNotEmpty = drawSettings.textShapeActiveId !== '';
+
+    if ((fontSizeChanged || colorChanged || textShapeValueChanged) && textShapeIdNotEmpty) {
       const { getCurrentShapeId } = this.props.actions;
-      this.currentStatus = 'DRAW_UPDATE';
+      this.currentStatus = DRAW_UPDATE;
 
       this.handleDrawText(
         { x: this.currentX, y: this.currentY },
@@ -85,8 +92,8 @@ export default class TextDrawListener extends Component {
 
   componentWillUnmount() {
     window.removeEventListener('beforeunload', this.sendLastMessage);
-    window.removeEventListener('mouseup', this.mouseUpHandler);
-    window.removeEventListener('mousemove', this.mouseMoveHandler, true);
+    window.removeEventListener('mouseup', this.handleMouseUp);
+    window.removeEventListener('mousemove', this.handleMouseMove, true);
 
     // sending the last message on componentDidUnmount
     // for example in case when you switched a tool while drawing text shape
@@ -94,30 +101,27 @@ export default class TextDrawListener extends Component {
   }
 
   // main mouse down handler
-  // calls a mouseDown<AnnotationName> handler based on the tool selected
-  mouseDownHandler(event) {
+  handleMouseDown(event) {
     this.mouseDownText(event);
   }
 
   // main mouse up handler
-  // calls a mouseUp<AnnotationName> handler based on the tool selected
-  mouseUpHandler(event) {
-    window.removeEventListener('mouseup', this.mouseUpHandler);
-    window.removeEventListener('mousemove', this.mouseMoveHandler, true);
+  handleMouseUp(event) {
+    window.removeEventListener('mouseup', this.handleMouseUp);
+    window.removeEventListener('mousemove', this.handleMouseMove, true);
     this.mouseUpText(event);
   }
 
   // main mouse move handler
-  // calls a mouseMove<AnnotationName> handler based on the tool selected
-  mouseMoveHandler(event) {
+  handleMouseMove(event) {
     this.mouseMoveText(event);
   }
 
   mouseDownText(event) {
     // if our current drawing state is not drawing the box and not writing the text
     if (!this.state.isDrawing && !this.state.isWritingText) {
-      window.addEventListener('mouseup', this.mouseUpHandler);
-      window.addEventListener('mousemove', this.mouseMoveHandler, true);
+      window.addEventListener('mouseup', this.handleMouseUp);
+      window.addEventListener('mousemove', this.handleMouseMove, true);
 
       // saving initial X and Y coordinates for further displaying of the textarea
       this.initialX = event.nativeEvent.offsetX;
@@ -137,21 +141,23 @@ export default class TextDrawListener extends Component {
   }
 
   sendLastMessage() {
-    if (this.state.isWritingText) {
-      const { getCurrentShapeId } = this.props.actions;
-      this.currentStatus = 'DRAW_END';
+    if (!this.state.isWritingText) {
+      return;
+    }
 
-      this.handleDrawText(
-        { x: this.currentX, y: this.currentY },
-        this.currentWidth,
-        this.currentHeight,
-        this.currentStatus,
-        getCurrentShapeId(),
-        this.props.drawSettings.textShapeValue,
-      );
+    const { getCurrentShapeId } = this.props.actions;
+    this.currentStatus = DRAW_END;
 
-      this.resetState();
-    }
+    this.handleDrawText(
+      { x: this.currentX, y: this.currentY },
+      this.currentWidth,
+      this.currentHeight,
+      this.currentStatus,
+      getCurrentShapeId(),
+      this.props.drawSettings.textShapeValue,
+    );
+
+    this.resetState();
   }
 
   resetState() {
@@ -206,39 +212,41 @@ export default class TextDrawListener extends Component {
 
   mouseUpText() {
     // TODO - find if the size is large enough to display the text area
-    if (this.state.isDrawing && !this.state.isWritingText) {
-      const { generateNewShapeId,
-        getCurrentShapeId,
-        setTextShapeActiveId,
-      } = this.props.actions;
-
-      // coordinates and width/height of the textarea in percentages of the current slide
-      // saving them in the class since they will be used during all updates
-      this.currentX = (this.state.textBoxX / this.props.slideWidth) * 100;
-      this.currentY = (this.state.textBoxY / this.props.slideHeight) * 100;
-      this.currentWidth = (this.state.textBoxWidth / this.props.slideWidth) * 100;
-      this.currentHeight = (this.state.textBoxHeight / this.props.slideHeight) * 100;
-      this.currentStatus = 'DRAW_START';
-      this.handleDrawText(
-        { x: this.currentX, y: this.currentY },
-        this.currentWidth,
-        this.currentHeight,
-        this.currentStatus,
-        generateNewShapeId(),
-        '',
-      );
+    if (!this.state.isDrawing && this.state.isWritingText) {
+      return;
+    }
 
-      setTextShapeActiveId(getCurrentShapeId());
+    const { generateNewShapeId,
+      getCurrentShapeId,
+      setTextShapeActiveId,
+    } = this.props.actions;
+
+    // coordinates and width/height of the textarea in percentages of the current slide
+    // saving them in the class since they will be used during all updates
+    this.currentX = (this.state.textBoxX / this.props.slideWidth) * 100;
+    this.currentY = (this.state.textBoxY / this.props.slideHeight) * 100;
+    this.currentWidth = (this.state.textBoxWidth / this.props.slideWidth) * 100;
+    this.currentHeight = (this.state.textBoxHeight / this.props.slideHeight) * 100;
+    this.currentStatus = DRAW_START;
+    this.handleDrawText(
+      { x: this.currentX, y: this.currentY },
+      this.currentWidth,
+      this.currentHeight,
+      this.currentStatus,
+      generateNewShapeId(),
+      '',
+    );
 
-      this.setState({
-        isWritingText: true,
-        isDrawing: false,
-        textBoxX: undefined,
-        textBoxY: undefined,
-        textBoxWidth: 0,
-        textBoxHeight: 0,
-      });
-    }
+    setTextShapeActiveId(getCurrentShapeId());
+
+    this.setState({
+      isWritingText: true,
+      isDrawing: false,
+      textBoxX: undefined,
+      textBoxY: undefined,
+      textBoxWidth: 0,
+      textBoxHeight: 0,
+    });
   }
 
   handleDrawText(startPoint, width, height, status, id, text) {
@@ -277,7 +285,7 @@ export default class TextDrawListener extends Component {
         role="presentation"
         className={styles.text}
         style={{ width: '100%', height: '100%' }}
-        onMouseDown={this.mouseDownHandler}
+        onMouseDown={this.handleMouseDown}
       >
         {this.state.isDrawing ?
           <svg
@@ -334,7 +342,7 @@ TextDrawListener.propTypes = {
     // Defines a function which generates a new shape id
     generateNewShapeId: PropTypes.func.isRequired,
     // Defines a function which receives a thickness num and normalizes it before we send a message
-    normalizeThickness: PropTypes.func.isRequired,
+    normalizeFont: PropTypes.func.isRequired,
     // Defines a function which we use to publish a message to the server
     sendAnnotation: PropTypes.func.isRequired,
     // Defines a function which resets the current state of the text shape drawing
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/component.jsx
index 7d91bf70c01e0c2db3589749d6165d3e1d54d07b..d9fb758a6831c8503a912a2be7824d930ef6b673 100644
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/component.jsx
@@ -1,29 +1,23 @@
 import React, { Component } from 'react';
 import PropTypes from 'prop-types';
 import cx from 'classnames';
+import { HEXToINTColor, INTToHEXColor } from '/imports/utils/hexInt';
+import injectWbResizeEvent from '/imports/ui/components/presentation/resize-wrapper/component';
 import styles from './styles.scss';
-import WhiteboardToolbarItem from './whiteboard-toolbar-item/component';
+import ToolbarMenuItem from './toolbar-menu-item/component';
+import ToolbarSubmenu from './toolbar-submenu/component';
 
-export default class WhiteboardToolbar extends Component {
+const TRANSITION_DURATION = '0.4s';
+const TOOLBAR_CONFIG = Meteor.settings.public.whiteboard.toolbar;
+const ANNOTATION_COLORS = TOOLBAR_CONFIG.colors;
+const THICKNESS_RADIUSES = TOOLBAR_CONFIG.thickness;
+const FONT_SIZES = TOOLBAR_CONFIG.font_sizes;
+const ANNOTATION_TOOLS = TOOLBAR_CONFIG.tools;
 
-  static HEXToINTColor(hexColor) {
-    const _rrggbb = hexColor.slice(1);
-    const rrggbb = _rrggbb.substr(0, 2) + _rrggbb.substr(2, 2) + _rrggbb.substr(4, 2);
-    return parseInt(rrggbb, 16);
-  }
-
-  static INTToHEXColor(intColor) {
-    let hex;
-    hex = parseInt(intColor, 10).toString(16);
-    while (hex.length < 6) {
-      hex = `0${hex}`;
-    }
+class WhiteboardToolbar extends Component {
 
-    return `#${hex}`;
-  }
-
-  constructor(props) {
-    super(props);
+  constructor() {
+    super();
 
     this.state = {
       // a variable to control which list is currently open
@@ -32,15 +26,15 @@ export default class WhiteboardToolbar extends Component {
       // variables to keep current selected draw settings
       annotationSelected: {
         icon: 'hand',
-        sessionValue: 'hand',
+        value: 'hand',
       },
-      thicknessSelected: 4,
-      colorSelected: '#000000',
-      fontSizeSelected: 20,
+      thicknessSelected: { value: 4 },
+      colorSelected: { value: '#000000' },
+      fontSizeSelected: { value: 20 },
 
       // keeping the previous color and the thickness icon's radius selected for svg animation
-      prevColorSelected: '#000000',
-      prevIconRadius: 4,
+      prevColorSelected: { value: '#000000' },
+      prevThicknessSelected: { value: 4 },
 
       // lists of tools/thickness/colors are not direct children of main toolbar buttons
       // and we want the list to close when onBlur fires at the main toolbar button
@@ -58,12 +52,8 @@ export default class WhiteboardToolbar extends Component {
     this.handleThicknessChange = this.handleThicknessChange.bind(this);
     this.handleFontSizeChange = this.handleFontSizeChange.bind(this);
     this.handleColorChange = this.handleColorChange.bind(this);
-    this.disableOnBlur = this.disableOnBlur.bind(this);
-    this.enableOnBlur = this.enableOnBlur.bind(this);
-    this.renderAnnotationList = this.renderAnnotationList.bind(this);
-    this.renderFontSizeList = this.renderFontSizeList.bind(this);
-    this.renderThicknessList = this.renderThicknessList.bind(this);
-    this.renderColorList = this.renderColorList.bind(this);
+    this.handleMouseEnter = this.handleMouseEnter.bind(this);
+    this.handleMouseLeave = this.handleMouseLeave.bind(this);
   }
 
   componentWillMount() {
@@ -77,10 +67,10 @@ export default class WhiteboardToolbar extends Component {
       // setting default drawing settings if they haven't been set previously
       const { annotationSelected, thicknessSelected, colorSelected, fontSizeSelected } = this.state;
       this.props.actions.setInitialWhiteboardToolbarValues(
-        annotationSelected.sessionValue,
-        thicknessSelected,
-        WhiteboardToolbar.HEXToINTColor(colorSelected),
-        fontSizeSelected,
+        annotationSelected.value,
+        thicknessSelected.value * 2,
+        HEXToINTColor(colorSelected.value),
+        fontSizeSelected.value,
         {
           textShapeValue: '',
           textShapeActiveId: '',
@@ -90,10 +80,7 @@ export default class WhiteboardToolbar extends Component {
   }
 
   componentDidMount() {
-    // to let the whiteboard know that the presentation area's size has changed
-    window.dispatchEvent(new Event('resize'));
-
-    if (this.state.annotationSelected.sessionValue !== 'text') {
+    if (this.state.annotationSelected.value !== 'text') {
       // trigger initial animation on the thickness circle, otherwise it stays at 0
       this.thicknessListIconColor.beginElement();
       this.thicknessListIconRadius.beginElement();
@@ -109,20 +96,15 @@ export default class WhiteboardToolbar extends Component {
     this.animateSvgIcons(prevState);
   }
 
-  componentWillUnmount() {
-    // to let the whiteboard know that the presentation area's size has changed
-    window.dispatchEvent(new Event('resize'));
-  }
-
   setToolbarValues(drawSettings) {
     // divide by 2, since we need the radius for the thickness icon
-    const thicknessSelected = drawSettings.whiteboardAnnotationThickness / 2;
-    const fontSizeSelected = drawSettings.textFontSize;
-    const colorSelected = WhiteboardToolbar.INTToHEXColor(drawSettings.whiteboardAnnotationColor);
+    const thicknessSelected = { value: drawSettings.whiteboardAnnotationThickness / 2 };
+    const fontSizeSelected = { value: drawSettings.textFontSize };
+    const colorSelected = { value: INTToHEXColor(drawSettings.whiteboardAnnotationColor) };
 
     let annotationSelected = {};
     for (let i = 0; i < this.props.annotations.length; i += 1) {
-      if (drawSettings.whiteboardAnnotationTool === this.props.annotations[i].sessionValue) {
+      if (drawSettings.whiteboardAnnotationTool === this.props.annotations[i].value) {
         annotationSelected = this.props.annotations[i];
         break;
       }
@@ -149,19 +131,19 @@ export default class WhiteboardToolbar extends Component {
     */
 
     // 1st case
-    if (this.state.colorSelected !== prevState.colorSelected) {
+    if (this.state.colorSelected.value !== prevState.colorSelected.value) {
       // 1st case b)
-      if (this.state.annotationSelected.sessionValue !== 'text') {
+      if (this.state.annotationSelected.value !== 'text') {
         this.thicknessListIconColor.beginElement();
       }
       // 1st case a)
       this.colorListIconColor.beginElement();
     // 2nd case
-    } else if (this.state.thicknessSelected !== prevState.thicknessSelected) {
+    } else if (this.state.thicknessSelected.value !== prevState.thicknessSelected.value) {
       this.thicknessListIconRadius.beginElement();
       // 3rd case
-    } else if (this.state.annotationSelected.sessionValue !== 'text' &&
-          prevState.annotationSelected.sessionValue === 'text') {
+    } else if (this.state.annotationSelected.value !== 'text' &&
+          prevState.annotationSelected.value === 'text') {
       this.thicknessListIconRadius.beginElement();
       this.thicknessListIconColor.beginElement();
     }
@@ -179,7 +161,7 @@ export default class WhiteboardToolbar extends Component {
   // close a current submenu (fires onBlur only, when you click anywhere on the screen)
   closeSubMenu() {
     // a separate case for the active text shape
-    if (this.state.annotationSelected.sessionValue === 'text' && this.props.textShapeActiveId !== '') {
+    if (this.state.annotationSelected.value === 'text' && this.props.textShapeActiveId !== '') {
       return;
     }
 
@@ -214,33 +196,33 @@ export default class WhiteboardToolbar extends Component {
     };
 
     // to animate thickness icon properly when you switch the tool back from Text
-    if (annotation.sessionValue === 'text') {
-      obj.prevIconRadius = 0;
+    if (annotation.value === 'text') {
+      obj.prevThicknessSelected = { value: 0 };
     }
 
-    this.props.actions.setTool(annotation.sessionValue);
+    this.props.actions.setTool(annotation.value);
     this.setState(obj);
   }
 
   // changes a current selected thickness both in the state and in the session
   // and closes the thickness list
-  handleThicknessChange(thicknessValue) {
-    // thicknessValue * 2 since this is radius, we need to double it
-    this.props.actions.setThickness(thicknessValue * 2);
+  handleThicknessChange(thicknessSelected) {
+    // thickness value * 2 since this is radius, we need to double it
+    this.props.actions.setThickness(thicknessSelected.value * 2);
 
     this.setState({
-      prevIconRadius: this.state.thicknessSelected,
-      thicknessSelected: thicknessValue,
+      prevThicknessSelected: this.state.thicknessSelected,
+      thicknessSelected,
       onBlurEnabled: true,
       currentSubmenuOpen: '',
     });
   }
 
-  handleFontSizeChange(fontSizeValue) {
-    this.props.actions.setFontSize(fontSizeValue);
+  handleFontSizeChange(fontSize) {
+    this.props.actions.setFontSize(fontSize.value);
 
     this.setState({
-      fontSizeSelected: fontSizeValue,
+      fontSizeSelected: fontSize,
       onBlurEnabled: true,
       currentSubmenuOpen: '',
     });
@@ -249,7 +231,7 @@ export default class WhiteboardToolbar extends Component {
   // changes a current selected color both in the state and in the session
   // and closes the color list
   handleColorChange(color) {
-    this.props.actions.setColor(WhiteboardToolbar.HEXToINTColor(color));
+    this.props.actions.setColor(HEXToINTColor(color.value));
 
     this.setState({
       prevColorSelected: this.state.colorSelected,
@@ -260,245 +242,249 @@ export default class WhiteboardToolbar extends Component {
   }
 
   // disabling onBlur flag when mouse is over the items in the lists
-  disableOnBlur() {
+  handleMouseEnter() {
     this.setState({
       onBlurEnabled: false,
     });
   }
 
   // enabling the onBlur flag when the mouse leaving the lists
-  enableOnBlur() {
+  handleMouseLeave() {
     this.setState({
       onBlurEnabled: true,
     });
   }
 
-  renderAnnotationList() {
-    const { annotations } = this.props;
+  renderToolItem() {
+    return (
+      <ToolbarMenuItem
+        label={'Tools'}
+        icon={this.state.annotationSelected.icon}
+        onItemClick={this.displaySubMenu}
+        objectToReturn={'annotationList'}
+        onBlur={this.closeSubMenu}
+        className={cx(styles.toolbarButton, this.state.currentSubmenuOpen === 'annotationList' ? '' : styles.notActive)}
+      >
+        {this.state.currentSubmenuOpen === 'annotationList' ?
+          <ToolbarSubmenu
+            type="annotations"
+            customIcon={false}
+            label="Annotations"
+            onItemClick={this.handleAnnotationChange}
+            objectsToRender={this.props.annotations}
+            objectSelected={this.state.annotationSelected}
+            handleMouseEnter={this.handleMouseEnter}
+            handleMouseLeave={this.handleMouseLeave}
+          />
+        : null }
+      </ToolbarMenuItem>
+    );
+  }
 
+  renderFontItem() {
     return (
-      <div className={cx(styles.annotationList, styles.toolbarList)}>
-        { annotations ? annotations.map(annotation =>
-          (
-            <WhiteboardToolbarItem
-              label={'Annotation'}
-              icon={annotation.icon}
-              onItemClick={this.handleAnnotationChange}
-              objectToReturn={annotation}
-              className={cx(styles.toolbarListButton, this.state.annotationSelected.sessionValue === annotation.sessionValue ? styles.selectedListButton : '')}
-              onMouseEnter={this.disableOnBlur}
-              onMouseLeave={this.enableOnBlur}
-              key={annotation.sessionValue}
-            />
-          ),
-        ) : null}
-      </div>
+      <ToolbarMenuItem
+        label={'Font Size List'}
+        customIcon={this.renderFontItemIcon()}
+        onItemClick={this.displaySubMenu}
+        objectToReturn={'fontSizeList'}
+        onBlur={this.closeSubMenu}
+        className={cx(styles.toolbarButton, this.state.currentSubmenuOpen === 'fontSizeList' ? '' : styles.notActive)}
+      >
+        {this.state.currentSubmenuOpen === 'fontSizeList' ?
+          <ToolbarSubmenu
+            type="font-size"
+            customIcon
+            label="Font Size"
+            onItemClick={this.handleFontSizeChange}
+            objectsToRender={this.props.fontSizes}
+            objectSelected={this.state.fontSizeSelected}
+            handleMouseEnter={this.handleMouseEnter}
+            handleMouseLeave={this.handleMouseLeave}
+          />
+        : null }
+      </ToolbarMenuItem>
     );
   }
 
-  renderFontSizeList() {
-    const { fontSizes } = this.props;
+  renderFontItemIcon() {
+    return (
+      <p
+        className={styles.textThickness}
+        style={{
+          fontSize: this.state.fontSizeSelected.value,
+          color: this.state.colorSelected.value,
+          WebkitTransition: `color ${TRANSITION_DURATION}, font-size ${TRANSITION_DURATION}`, /* Safari */
+          transition: `color ${TRANSITION_DURATION}, font-size ${TRANSITION_DURATION}`,
+        }}
+      >
+        Aa
+      </p>
+    );
+  }
 
+  renderThicknessItem() {
     return (
-      <div className={cx(styles.fontSizeList, styles.toolbarList)}>
-        {fontSizes ? fontSizes.map(fontSizeValue =>
-          (
-            <WhiteboardToolbarItem
-              label={'Font Size'}
-              customIcon={
-                <p className={styles.textThickness} style={{ fontSize: fontSizeValue }}>
-                  Aa
-                </p>
-              }
-              onItemClick={this.handleFontSizeChange}
-              objectToReturn={fontSizeValue}
-              className={cx(styles.toolbarListButton, styles.fontSizeListButton, this.state.fontSizeSelected === fontSizeValue ? styles.selectedListButton : '')}
-              onMouseEnter={this.disableOnBlur}
-              onMouseLeave={this.enableOnBlur}
-              key={fontSizeValue}
-            />
-          ),
-        ) : null}
-      </div>
+      <ToolbarMenuItem
+        label={'Thickness List'}
+        onItemClick={this.displaySubMenu}
+        objectToReturn={'thicknessList'}
+        onBlur={this.closeSubMenu}
+        className={cx(styles.toolbarButton, this.state.currentSubmenuOpen === 'thicknessList' ? '' : styles.notActive)}
+        customIcon={this.renderThicknessItemIcon()}
+      >
+        {this.state.currentSubmenuOpen === 'thicknessList' ?
+          <ToolbarSubmenu
+            type="thickness"
+            customIcon
+            label="Thickness"
+            onItemClick={this.handleThicknessChange}
+            objectsToRender={this.props.thicknessRadiuses}
+            objectSelected={this.state.thicknessSelected}
+            handleMouseEnter={this.handleMouseEnter}
+            handleMouseLeave={this.handleMouseLeave}
+          />
+        : null }
+      </ToolbarMenuItem>
     );
   }
 
-  renderThicknessList() {
-    const { thicknessRadiuses } = this.props;
+  renderThicknessItemIcon() {
+    return (
+      <svg className={styles.customSvgIcon} shapeRendering="geometricPrecision">
+        <circle
+          shapeRendering="geometricPrecision"
+          cx="50%"
+          cy="50%"
+          stroke="black"
+          strokeWidth="1"
+        >
+          <animate
+            ref={(ref) => { this.thicknessListIconColor = ref; }}
+            attributeName="fill"
+            attributeType="XML"
+            from={this.state.prevColorSelected.value}
+            to={this.state.colorSelected.value}
+            begin={'indefinite'}
+            dur={TRANSITION_DURATION}
+            repeatCount="0"
+            fill="freeze"
+          />
+          <animate
+            ref={(ref) => { this.thicknessListIconRadius = ref; }}
+            attributeName="r"
+            attributeType="XML"
+            from={this.state.prevThicknessSelected.value}
+            to={this.state.thicknessSelected.value}
+            begin={'indefinite'}
+            dur={TRANSITION_DURATION}
+            repeatCount="0"
+            fill="freeze"
+          />
+        </circle>
+      </svg>
+    );
+  }
 
+  renderColorItem() {
     return (
-      <div className={cx(styles.thicknessList, styles.toolbarList)}>
-        {thicknessRadiuses ? thicknessRadiuses.map(thicknessRadius =>
-          (
-            <WhiteboardToolbarItem
-              label={'Radius'}
-              customIcon={
-                <svg className={styles.customSvgIcon}>
-                  <circle cx="50%" cy="50%" r={thicknessRadius} fill="#F3F6F9" />
-                </svg>
-              }
-              onItemClick={this.handleThicknessChange}
-              objectToReturn={thicknessRadius}
-              className={cx(styles.toolbarListButton, this.state.thicknessSelected === thicknessRadius ? styles.selectedListButton : '')}
-              onMouseEnter={this.disableOnBlur}
-              onMouseLeave={this.enableOnBlur}
-              key={thicknessRadius}
-            />
-          ),
-        ) : null}
-      </div>
+      <ToolbarMenuItem
+        label={'Color List'}
+        onItemClick={this.displaySubMenu}
+        objectToReturn={'colorList'}
+        onBlur={this.closeSubMenu}
+        className={cx(styles.toolbarButton, this.state.currentSubmenuOpen === 'colorList' ? '' : styles.notActive)}
+        customIcon={this.renderColorItemIcon()}
+      >
+        {this.state.currentSubmenuOpen === 'colorList' ?
+          <ToolbarSubmenu
+            type="color"
+            customIcon
+            label="Color"
+            onItemClick={this.handleColorChange}
+            objectsToRender={this.props.colors}
+            objectSelected={this.state.colorSelected}
+            handleMouseEnter={this.handleMouseEnter}
+            handleMouseLeave={this.handleMouseLeave}
+          />
+        : null }
+      </ToolbarMenuItem>
+    );
+  }
+
+  renderColorItemIcon() {
+    return (
+      <svg className={styles.customSvgIcon}>
+        <rect x="25%" y="25%" width="50%" height="50%" stroke="black" strokeWidth="1">
+          <animate
+            ref={(ref) => { this.colorListIconColor = ref; }}
+            attributeName="fill"
+            attributeType="XML"
+            from={this.state.prevColorSelected.value}
+            to={this.state.colorSelected.value}
+            begin={'indefinite'}
+            dur={TRANSITION_DURATION}
+            repeatCount="0"
+            fill="freeze"
+          />
+        </rect>
+      </svg>
     );
   }
 
-  renderColorList() {
-    const { colors } = this.props;
+  renderUndoItem() {
+    return (
+      <ToolbarMenuItem
+        label={'Undo Annotation'}
+        icon={'undo'}
+        onItemClick={this.handleUndo}
+        className={cx(styles.toolbarButton, styles.notActive)}
+      />
+    );
+  }
 
+  renderClearAllItem() {
     return (
-      <div className={cx(styles.colorList, styles.toolbarList)}>
-        {colors ? colors.map(color =>
-          (
-            <WhiteboardToolbarItem
-              label={'Color'}
-              customIcon={
-                <svg className={styles.customSvgIcon}>
-                  <rect x="20%" y="20%" width="60%" height="60%" fill={color} />
-                </svg>
-              }
-              onItemClick={this.handleColorChange}
-              objectToReturn={color}
-              className={cx(styles.toolbarListButton, this.state.colorSelected === color ? styles.selectedListButton : '')}
-              onMouseEnter={this.disableOnBlur}
-              onMouseLeave={this.enableOnBlur}
-              key={color}
-            />
-          ),
-        ) : null}
-      </div>
+      <ToolbarMenuItem
+        label={'Clear All Annotations'}
+        icon={'circle_close'}
+        onItemClick={this.handleClearAll}
+        className={cx(styles.toolbarButton, styles.notActive)}
+      />
+    );
+  }
+
+  renderMultiUserItem() {
+    const { multiUser } = this.props;
+
+    return (
+      <ToolbarMenuItem
+        label={multiUser ? 'Turn multi-user mode off' : 'Tuen multi-user mode on'}
+        icon={multiUser ? 'multi_whiteboard' : 'whiteboard'}
+        onItemClick={this.handleSwitchWhiteboardMode}
+        className={cx(styles.toolbarButton, styles.notActive)}
+      />
     );
   }
 
   render() {
+    const { annotationSelected } = this.state;
+    const { isPresenter } = this.props;
     return (
       <div className={styles.toolbarContainer} style={{ height: this.props.height }}>
         <div className={styles.toolbarWrapper}>
-          <WhiteboardToolbarItem
-            label={'Tools'}
-            icon={this.state.annotationSelected.icon}
-            onItemClick={this.displaySubMenu}
-            objectToReturn={'annotationList'}
-            onBlur={this.closeSubMenu}
-            className={cx(styles.toolbarButton, this.state.currentSubmenuOpen === 'annotationList' ? '' : styles.notActive)}
-            renderSubMenu={this.state.currentSubmenuOpen === 'annotationList' ? this.renderAnnotationList : null}
-          />
-          {this.state.annotationSelected.sessionValue === 'text' ?
-            <WhiteboardToolbarItem
-              label={'Font Size List'}
-              customIcon={
-                <p
-                  className={styles.textThickness}
-                  style={{
-                    fontSize: this.state.fontSizeSelected,
-                    color: this.state.colorSelected,
-                  }}
-                >
-                  Aa
-                </p>
-              }
-              onItemClick={this.displaySubMenu}
-              objectToReturn={'fontSizeList'}
-              onBlur={this.closeSubMenu}
-              className={cx(styles.toolbarButton, this.state.currentSubmenuOpen === 'fontSizeList' ? '' : styles.notActive)}
-              renderSubMenu={this.state.currentSubmenuOpen === 'fontSizeList' ? this.renderFontSizeList : null}
-            />
+          {this.renderToolItem()}
+          {annotationSelected.value === 'text' ?
+          this.renderFontItem()
           :
-              <WhiteboardToolbarItem
-                label={'Thickness List'}
-                onItemClick={this.displaySubMenu}
-                objectToReturn={'thicknessList'}
-                onBlur={this.closeSubMenu}
-                className={cx(styles.toolbarButton, this.state.currentSubmenuOpen === 'thicknessList' ? '' : styles.notActive)}
-                renderSubMenu={this.state.currentSubmenuOpen === 'thicknessList' ? this.renderThicknessList : null}
-                customIcon={
-                  <svg className={styles.customSvgIcon} shapeRendering="geometricPrecision">
-                    <circle
-                      shapeRendering="geometricPrecision"
-                      cx="50%"
-                      cy="50%"
-                      stroke="black"
-                      strokeWidth="1"
-                    >
-                      <animate
-                        ref={(ref) => { this.thicknessListIconColor = ref; }}
-                        attributeName="fill"
-                        attributeType="XML"
-                        from={this.state.prevColorSelected}
-                        to={this.state.colorSelected}
-                        begin={'indefinite'}
-                        dur="0.4s"
-                        repeatCount="0"
-                        fill="freeze"
-                      />
-                      <animate
-                        ref={(ref) => { this.thicknessListIconRadius = ref; }}
-                        attributeName="r"
-                        attributeType="XML"
-                        from={this.state.prevIconRadius}
-                        to={this.state.thicknessSelected}
-                        begin={'indefinite'}
-                        dur="0.4s"
-                        repeatCount="0"
-                        fill="freeze"
-                      />
-                    </circle>
-                  </svg>
-              }
-              />
-          }
-          <WhiteboardToolbarItem
-            label={'Color List'}
-            onItemClick={this.displaySubMenu}
-            objectToReturn={'colorList'}
-            onBlur={this.closeSubMenu}
-            className={cx(styles.toolbarButton, this.state.currentSubmenuOpen === 'colorList' ? '' : styles.notActive)}
-            renderSubMenu={this.state.currentSubmenuOpen === 'colorList' ? this.renderColorList : null}
-            customIcon={
-              <svg className={styles.customSvgIcon}>
-                <rect x="25%" y="25%" width="50%" height="50%" stroke="black" strokeWidth="1">
-                  <animate
-                    ref={(ref) => { this.colorListIconColor = ref; }}
-                    attributeName="fill"
-                    attributeType="XML"
-                    from={this.state.prevColorSelected}
-                    to={this.state.colorSelected}
-                    begin={'indefinite'}
-                    dur="0.4s"
-                    repeatCount="0"
-                    fill="freeze"
-                  />
-                </rect>
-              </svg>
-              }
-          />
-          <WhiteboardToolbarItem
-            label={'Undo Annotation'}
-            icon={'undo'}
-            onItemClick={this.handleUndo}
-            className={cx(styles.toolbarButton, styles.notActive)}
-          />
-          <WhiteboardToolbarItem
-            label={'Clear All Annotations'}
-            icon={'circle_close'}
-            onItemClick={this.handleClearAll}
-            className={cx(styles.toolbarButton, styles.notActive)}
-          />
-          {this.props.isPresenter ?
-            <WhiteboardToolbarItem
-              label={this.props.multiUser ? 'Turn multi-user mode off' : 'Tuen multi-user mode on'}
-              icon={this.props.multiUser ? 'multi_whiteboard' : 'whiteboard'}
-              onItemClick={this.handleSwitchWhiteboardMode}
-              className={cx(styles.toolbarButton, styles.notActive)}
-            />
-          : null}
+          this.renderThicknessItem()
+        }
+          {this.renderColorItem()}
+          {this.renderUndoItem()}
+          {this.renderClearAllItem()}
+          {isPresenter ?
+          this.renderMultiUserItem()
+        : null }
         </div>
       </div>
     );
@@ -506,21 +492,10 @@ export default class WhiteboardToolbar extends Component {
 }
 
 WhiteboardToolbar.defaultProps = {
-  colors: [
-    '#000000', '#ffffff', '#ff0000', '#ff8800', '#ccff00', '#00ff00',
-    '#00ffff', '#0088ff', '#0000ff', '#8800ff', '#ff00ff', '#c0c0c0',
-  ],
-  thicknessRadiuses: [14, 12, 10, 8, 6, 4, 2],
-  fontSizes: [36, 32, 28, 24, 20, 16],
-  annotations: [
-    { icon: 'text_tool', sessionValue: 'text' },
-    { icon: 'linte_tool', sessionValue: 'line' },
-    { icon: 'circle_tool', sessionValue: 'ellipse' },
-    { icon: 'triangle_tool', sessionValue: 'triangle' },
-    { icon: 'rectangle_tool', sessionValue: 'rectangle' },
-    { icon: 'pen_tool', sessionValue: 'pencil' },
-    { icon: 'hand', sessionValue: 'hand' },
-  ],
+  colors: ANNOTATION_COLORS,
+  thicknessRadiuses: THICKNESS_RADIUSES,
+  fontSizes: FONT_SIZES,
+  annotations: ANNOTATION_TOOLS,
 };
 
 WhiteboardToolbar.propTypes = {
@@ -544,14 +519,27 @@ WhiteboardToolbar.propTypes = {
   annotations: PropTypes.arrayOf(PropTypes.object).isRequired,
 
   // defines an array of font-sizes for the Font-size submenu of the text shape
-  fontSizes: PropTypes.arrayOf(PropTypes.number).isRequired,
+  fontSizes: PropTypes.arrayOf(
+    PropTypes.shape({
+      value: PropTypes.number.isRequired,
+    }).isRequired,
+  ).isRequired,
 
   // defines an array of colors for the toolbar (color submenu)
-  colors: PropTypes.arrayOf(PropTypes.string).isRequired,
-
+  colors: PropTypes.arrayOf(
+    PropTypes.shape({
+      value: PropTypes.string.isRequired,
+    }).isRequired,
+  ).isRequired,
   // defines an array of thickness values for the toolbar and their corresponding session values
-  thicknessRadiuses: PropTypes.arrayOf(PropTypes.number).isRequired,
+  thicknessRadiuses: PropTypes.arrayOf(
+    PropTypes.shape({
+      value: PropTypes.number.isRequired,
+    }).isRequired,
+  ).isRequired,
 
   // defines the physical height of the whiteboard
   height: PropTypes.number.isRequired,
 };
+
+export default injectWbResizeEvent(WhiteboardToolbar);
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/container.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/container.jsx
index b5195c1741e9e461155f66a8aa349f3b8e899b0c..7c48c619b3a9fd8543a9c593e258081dee0e7879 100644
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/container.jsx
@@ -3,12 +3,23 @@ import { createContainer } from 'meteor/react-meteor-data';
 import WhiteboardToolbarService from './service';
 import WhiteboardToolbar from './component';
 
-const WhiteboardToolbarContainer = ({ ...props }) => (
+const WhiteboardToolbarContainer = props => (
   <WhiteboardToolbar {...props} />
   );
 
 export default createContainer(() => ({
-  actions: WhiteboardToolbarService.actions,
+  actions: {
+    undoAnnotation: WhiteboardToolbarService.undoAnnotation,
+    clearWhiteboard: WhiteboardToolbarService.clearWhiteboard,
+    changeWhiteboardMode: WhiteboardToolbarService.changeWhiteboardMode,
+    setInitialWhiteboardToolbarValues: WhiteboardToolbarService.setInitialWhiteboardToolbarValues,
+    getCurrentDrawSettings: WhiteboardToolbarService.getCurrentDrawSettings,
+    setFontSize: WhiteboardToolbarService.setFontSize,
+    setTool: WhiteboardToolbarService.setTool,
+    setThickness: WhiteboardToolbarService.setThickness,
+    setColor: WhiteboardToolbarService.setColor,
+    setTextShapeObject: WhiteboardToolbarService.setTextShapeObject,
+  },
   textShapeActiveId: WhiteboardToolbarService.getTextShapeActiveId(),
   multiUser: WhiteboardToolbarService.getMultiUserStatus(),
   isPresenter: WhiteboardToolbarService.isPresenter(),
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/service.js b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/service.js
index 0cf5ab1c5e2c4b71098226b66ed95833b6dfc835..8f3754216ecf3347974ed0725215fff29e834ba0 100644
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/service.js
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/service.js
@@ -4,107 +4,80 @@ import Users from '/imports/api/2.0/users';
 import Auth from '/imports/ui/services/auth';
 import WhiteboardMultiUser from '/imports/api/2.0/whiteboard-multi-user/';
 
-const actions = {
-  undoAnnotation: (whiteboardId) => {
-    makeCall('undoAnnotation', whiteboardId);
-  },
-
-  clearWhiteboard: (whiteboardId) => {
-    makeCall('clearWhiteboard', whiteboardId);
-  },
-
-  changeWhiteboardMode: (multiUser) => {
-    makeCall('changeWhiteboardAccess', multiUser);
-  },
-
-  setInitialWhiteboardToolbarValues: (tool, thickness, color, fontSize, textShape) => {
-    const _drawSettings = Storage.getItem('drawSettings');
-    if (!_drawSettings) {
-      const drawSettings = {
-        whiteboardAnnotationTool: tool,
-        whiteboardAnnotationThickness: thickness,
-        whiteboardAnnotationColor: color,
-        textFontSize: fontSize,
-        textShape,
-      };
-      Storage.setItem('drawSettings', JSON.stringify(drawSettings));
-    }
-  },
-
-  setTool: (tool) => {
-    const drawSettings = Storage.getItem('drawSettings');
-    if (drawSettings) {
-      drawSettings.whiteboardAnnotationTool = tool;
-      Storage.setItem('drawSettings', JSON.stringify(drawSettings));
-    }
-  },
-
-  setThickness: (thickness) => {
-    const drawSettings = Storage.getItem('drawSettings');
-    if (drawSettings) {
-      drawSettings.whiteboardAnnotationThickness = thickness;
-      Storage.setItem('drawSettings', JSON.stringify(drawSettings));
-    }
-  },
-
-  setColor: (color) => {
-    const drawSettings = Storage.getItem('drawSettings');
-    if (drawSettings) {
-      drawSettings.whiteboardAnnotationColor = color;
-      Storage.setItem('drawSettings', JSON.stringify(drawSettings));
-    }
-  },
-
-  setFontSize: (fontSize) => {
-    const drawSettings = Storage.getItem('drawSettings');
-    if (drawSettings) {
-      drawSettings.textFontSize = fontSize;
-      Storage.setItem('drawSettings', JSON.stringify(drawSettings));
-    }
-  },
-
-  getCurrentDrawSettings: () => Storage.getItem('drawSettings'),
-
-  setTextShapeObject: (textShape) => {
-    const drawSettings = Storage.getItem('drawSettings');
-    if (drawSettings) {
-      drawSettings.textShape = textShape;
-      Storage.setItem('drawSettings', JSON.stringify(drawSettings));
-    }
-  },
-};
+const DRAW_SETTINGS = 'drawSettings';
 
-const getTextShapeActiveId = () => {
-  const drawSettings = Storage.getItem('drawSettings');
+const makeSetter = key => (value) => {
+  const drawSettings = Storage.getItem(DRAW_SETTINGS);
   if (drawSettings) {
-    return drawSettings.textShape.textShapeActiveId;
+    drawSettings[key] = value;
+    Storage.setItem(DRAW_SETTINGS, drawSettings);
   }
+};
 
-  return '';
+const undoAnnotation = (whiteboardId) => {
+  makeCall('undoAnnotation', whiteboardId);
 };
 
-const getMultiUserStatus = () => {
-  const data = WhiteboardMultiUser.findOne({ meetingId: Auth.meetingID });
+const clearWhiteboard = (whiteboardId) => {
+  makeCall('clearWhiteboard', whiteboardId);
+};
 
-  if (data) {
-    return data.multiUser;
+const changeWhiteboardMode = (multiUser) => {
+  makeCall('changeWhiteboardAccess', multiUser);
+};
+
+const setInitialWhiteboardToolbarValues = (tool, thickness, color, fontSize, textShape) => {
+  const _drawSettings = Storage.getItem(DRAW_SETTINGS);
+  if (!_drawSettings) {
+    const drawSettings = {
+      whiteboardAnnotationTool: tool,
+      whiteboardAnnotationThickness: thickness,
+      whiteboardAnnotationColor: color,
+      textFontSize: fontSize,
+      textShape,
+    };
+    Storage.setItem(DRAW_SETTINGS, drawSettings);
   }
+};
+
+const getCurrentDrawSettings = () => Storage.getItem(DRAW_SETTINGS);
+
+const setFontSize = makeSetter('textFontSize');
+
+const setTool = makeSetter('whiteboardAnnotationTool');
 
-  return false;
+const setThickness = makeSetter('whiteboardAnnotationThickness');
+
+const setColor = makeSetter('whiteboardAnnotationColor');
+
+const setTextShapeObject = makeSetter('textShape');
+
+const getTextShapeActiveId = () => {
+  const drawSettings = Storage.getItem(DRAW_SETTINGS);
+  return drawSettings ? drawSettings.textShape.textShapeActiveId : '';
+};
+
+const getMultiUserStatus = () => {
+  const data = WhiteboardMultiUser.findOne({ meetingId: Auth.meetingID });
+  return data ? data.multiUser : false;
 };
 
 const isPresenter = () => {
   const currentUser = Users.findOne({ userId: Auth.userID });
-
-  if (currentUser) {
-    return currentUser.presenter;
-  }
-
-  return false;
+  return currentUser ? currentUser.presenter : false;
 };
 
 export default {
-  actions,
+  undoAnnotation,
+  clearWhiteboard,
+  changeWhiteboardMode,
+  setInitialWhiteboardToolbarValues,
+  getCurrentDrawSettings,
+  setFontSize,
+  setTool,
+  setThickness,
+  setColor,
+  setTextShapeObject,
   getTextShapeActiveId,
   getMultiUserStatus,
   isPresenter,
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/styles.scss b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/styles.scss
index 96f8696499407a2f6ff68a7fc840a05c7b4b4354..1c9b9ad62be9cfc44d7fe26fd8d2f003f653d467 100644
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/styles.scss
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/styles.scss
@@ -91,9 +91,6 @@ $number-of-vertical-main-toolbar-buttons: 5;
   i {
     color: $color-white;
   }
-}
-
-.fontSizeListButton {
   padding: initial;
 }
 
@@ -108,14 +105,11 @@ $number-of-vertical-main-toolbar-buttons: 5;
 }
 
 .textThickness {
-  font-family: "Arial";
+  font-family: Arial, sans-serif;
   font-weight: normal;
   text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black;
   margin: auto;
   color: $color-white;
-
-  //color transiton should match color transition for the svg Color and Thickness icons in the component.jsx
-  transition: color 0.4s, font-size 0.3s;
 }
 
 .annotationList {
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/whiteboard-toolbar-item/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/toolbar-menu-item/component.jsx
similarity index 60%
rename from bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/whiteboard-toolbar-item/component.jsx
rename to bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/toolbar-menu-item/component.jsx
index 62b9f78a74b66e37ea160de6eb4359438e2a470f..bb782817ff3824f4f1c4d27cb5c9cd70db921996 100644
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/whiteboard-toolbar-item/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/toolbar-menu-item/component.jsx
@@ -3,22 +3,19 @@ import PropTypes from 'prop-types';
 import Button from '/imports/ui/components/button/component';
 import styles from '../styles';
 
-export default class WhiteboardToolbarItem extends Component {
+export default class ToolbarMenuItem extends Component {
   constructor() {
     super();
 
-    this._onClick = this._onClick.bind(this);
+    this.handleItemClick = this.handleItemClick.bind(this);
   }
 
-  _onClick() {
+  handleItemClick() {
     const { objectToReturn, onItemClick } = this.props;
     // if there is a submenu name, then pass it to onClick
-    // if not - it's probably "Undo", "Clear All", "Multi-user", etc. No submenu here.
-    if (objectToReturn) {
-      onItemClick(objectToReturn);
-    } else {
-      onItemClick();
-    }
+    // if not - it's probably "Undo", "Clear All", "Multi-user", etc.
+    // in the second case we'll pass undefined and it will work fine anyway
+    onItemClick(objectToReturn);
   }
 
   render() {
@@ -31,42 +28,40 @@ export default class WhiteboardToolbarItem extends Component {
           size={'md'}
           label={this.props.label}
           icon={this.props.icon ? this.props.icon : null}
-          customIcon={this.props.customIcon}
-          onClick={this._onClick}
+          customIcon={this.props.customIcon ? this.props.customIcon : null}
+          onClick={this.handleItemClick}
           onBlur={this.props.onBlur}
           className={this.props.className}
-          onMouseEnter={this.props.onMouseEnter}
-          onMouseLeave={this.props.onMouseLeave}
         />
-        {this.props.renderSubMenu ? this.props.renderSubMenu() : null}
+        {this.props.children}
       </div>
     );
   }
 }
 
-WhiteboardToolbarItem.propTypes = {
+ToolbarMenuItem.propTypes = {
+  // objectToReturn, children and onBlur are passed only with menu items that have submenus
+  // thus they are optional
+  onBlur: PropTypes.func,
+  children: PropTypes.node,
   objectToReturn: PropTypes.oneOfType([
     PropTypes.string,
     PropTypes.object,
     PropTypes.number,
   ]),
   onItemClick: PropTypes.func.isRequired,
+  // we can have either icon from the bigbluebutton-font or our custom svg/html
+  // thus they are optional
   icon: PropTypes.string,
   customIcon: PropTypes.node,
   label: PropTypes.string.isRequired,
-  onBlur: PropTypes.func,
   className: PropTypes.string.isRequired,
-  onMouseEnter: PropTypes.func,
-  onMouseLeave: PropTypes.func,
-  renderSubMenu: PropTypes.func,
 };
 
-WhiteboardToolbarItem.defaultProps = {
+ToolbarMenuItem.defaultProps = {
   objectToReturn: null,
   icon: '',
-  customIcon: (<p />),
+  customIcon: null,
   onBlur: null,
-  onMouseLeave: null,
-  onMouseEnter: null,
-  renderSubMenu: null,
+  children: null,
 };
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/toolbar-submenu-item/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/toolbar-submenu-item/component.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..2ac4c999d8bf26bce8e0e4ccf5382c94a00ce0d7
--- /dev/null
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/toolbar-submenu-item/component.jsx
@@ -0,0 +1,57 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import Button from '/imports/ui/components/button/component';
+import styles from '../styles';
+
+export default class ToolbarSubmenuItem extends Component {
+  constructor() {
+    super();
+
+    this.handleItemClick = this.handleItemClick.bind(this);
+  }
+
+  handleItemClick() {
+    const { objectToReturn, onItemClick } = this.props;
+    // if there is a submenu name, then pass it to onClick
+    // if not - it's probably "Undo", "Clear All", "Multi-user", etc.
+    // in the second case we'll pass undefined and it will work fine anyway
+    onItemClick(objectToReturn);
+  }
+
+  render() {
+    return (
+      <div className={styles.buttonWrapper}>
+        <Button
+          hideLabel
+          role="button"
+          color={'default'}
+          size={'md'}
+          label={this.props.label}
+          icon={this.props.icon}
+          customIcon={this.props.customIcon}
+          onClick={this.handleItemClick}
+          className={this.props.className}
+        />
+      </div>
+    );
+  }
+}
+
+
+ToolbarSubmenuItem.propTypes = {
+  label: PropTypes.string.isRequired,
+  icon: PropTypes.string,
+  customIcon: PropTypes.node,
+  onItemClick: PropTypes.func.isRequired,
+  objectToReturn: PropTypes.oneOfType([
+    PropTypes.string,
+    PropTypes.object,
+    PropTypes.number,
+  ]).isRequired,
+  className: PropTypes.string.isRequired,
+};
+
+ToolbarSubmenuItem.defaultProps = {
+  icon: null,
+  customIcon: null,
+};
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/toolbar-submenu/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/toolbar-submenu/component.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..645a586a1586381e0362de9f66788d37d237c2c5
--- /dev/null
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/toolbar-submenu/component.jsx
@@ -0,0 +1,134 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import cx from 'classnames';
+import styles from '../styles';
+import ToolbarSubmenuItem from '../toolbar-submenu-item/component';
+
+export default class ToolbarSubmenu extends Component {
+  static getCustomIcon(type, obj) {
+    if (type === 'color') {
+      return (
+        <svg className={styles.customSvgIcon}>
+          <rect x="20%" y="20%" width="60%" height="60%" fill={obj.value} />
+        </svg>
+      );
+    } else if (type === 'thickness') {
+      return (
+        <svg className={styles.customSvgIcon}>
+          <circle cx="50%" cy="50%" r={obj.value} fill="#F3F6F9" />
+        </svg>
+      );
+    } else if (type === 'font-size') {
+      return (
+        <p className={styles.textThickness} style={{ fontSize: obj.value }}>
+          Aa
+        </p>
+      );
+    }
+
+    return null;
+  }
+
+  static getWrapperClassNames(type) {
+    if (type === 'color') {
+      return cx(styles.colorList, styles.toolbarList);
+    } else if (type === 'thickness') {
+      return cx(styles.thicknessList, styles.toolbarList);
+    } else if (type === 'font-size') {
+      return cx(styles.fontSizeList, styles.toolbarList);
+    } else if (type === 'annotations') {
+      return cx(styles.annotationList, styles.toolbarList);
+    }
+
+    return null;
+  }
+  constructor() {
+    super();
+
+    this.handleMouseEnter = this.handleMouseEnter.bind(this);
+    this.handleMouseLeave = this.handleMouseLeave.bind(this);
+    this.onItemClick = this.onItemClick.bind(this);
+  }
+
+  onItemClick(objectToReturn) {
+    if (this.props.onItemClick) {
+      this.props.onItemClick(objectToReturn);
+    }
+  }
+
+  handleMouseEnter() {
+    if (this.props.handleMouseEnter) {
+      this.props.handleMouseEnter();
+    }
+  }
+
+  handleMouseLeave() {
+    if (this.props.handleMouseLeave) {
+      this.props.handleMouseLeave();
+    }
+  }
+
+  render() {
+    const { type, objectsToRender, objectSelected, label, customIcon } = this.props;
+
+    return (
+      <div
+        onMouseEnter={this.handleMouseEnter}
+        onMouseLeave={this.handleMouseLeave}
+        className={ToolbarSubmenu.getWrapperClassNames(type)}
+      >
+        {objectsToRender ? objectsToRender.map(obj =>
+          (
+            <ToolbarSubmenuItem
+              label={label}
+              icon={!customIcon ? obj.icon : null}
+              customIcon={customIcon ? ToolbarSubmenu.getCustomIcon(type, obj) : null}
+              onItemClick={this.onItemClick}
+              objectToReturn={obj}
+              className={cx(
+                styles.toolbarListButton,
+                objectSelected.value === obj.value ? styles.selectedListButton : '',
+              )}
+              key={obj.value}
+            />
+          ),
+        ) : null}
+      </div>
+    );
+  }
+}
+
+ToolbarSubmenu.propTypes = {
+  onItemClick: PropTypes.func.isRequired,
+  handleMouseEnter: PropTypes.func.isRequired,
+  handleMouseLeave: PropTypes.func.isRequired,
+  type: PropTypes.string.isRequired,
+  objectsToRender: PropTypes.arrayOf(
+    PropTypes.oneOfType([
+      PropTypes.shape({
+        value: PropTypes.string.isRequired,
+      }),
+      PropTypes.shape({
+        value: PropTypes.number.isRequired,
+      }),
+      PropTypes.shape({
+        value: PropTypes.string.isRequired,
+        icon: PropTypes.string.isRequired,
+      }),
+    ]).isRequired,
+  ).isRequired,
+  objectSelected: PropTypes.oneOfType([
+    PropTypes.shape({
+      value: PropTypes.string.isRequired,
+    }),
+    PropTypes.shape({
+      value: PropTypes.number.isRequired,
+    }),
+    PropTypes.shape({
+      value: PropTypes.string.isRequired,
+      icon: PropTypes.string.isRequired,
+    }),
+  ]).isRequired,
+  label: PropTypes.string.isRequired,
+  customIcon: PropTypes.bool.isRequired,
+};
diff --git a/bigbluebutton-html5/imports/utils/hexInt.js b/bigbluebutton-html5/imports/utils/hexInt.js
new file mode 100644
index 0000000000000000000000000000000000000000..573b50be8673a2dc32a58df644c9345be6c5b747
--- /dev/null
+++ b/bigbluebutton-html5/imports/utils/hexInt.js
@@ -0,0 +1,16 @@
+
+export function HEXToINTColor(hexColor) {
+  const _rrggbb = hexColor.slice(1);
+  const rrggbb = _rrggbb.substr(0, 2) + _rrggbb.substr(2, 2) + _rrggbb.substr(4, 2);
+  return parseInt(rrggbb, 16);
+}
+
+export function INTToHEXColor(intColor) {
+  let hex;
+  hex = parseInt(intColor, 10).toString(16);
+  while (hex.length < 6) {
+    hex = `0${hex}`;
+  }
+
+  return `#${hex}`;
+}
diff --git a/bigbluebutton-html5/private/config/public/app.yaml b/bigbluebutton-html5/private/config/public/app.yaml
index d08eedb4739c09f247ae8f6f7c7f3c8ced31c5b1..910acd7b4a87f58b1ae8067087ceb23e230c95fc 100755
--- a/bigbluebutton-html5/private/config/public/app.yaml
+++ b/bigbluebutton-html5/private/config/public/app.yaml
@@ -13,32 +13,32 @@ app:
   skipCheck: false
 
   # Default global variables
-  appName: "BigBlueButton HTML5 Client"
-  bbbServerVersion: "1.1-beta"
-  copyright: "©2017 BigBlueButton Inc."
-  html5ClientBuild: "HTML5_CLIENT_VERSION"
+  appName: 'BigBlueButton HTML5 Client'
+  bbbServerVersion: '1.1-beta'
+  copyright: '©2017 BigBlueButton Inc.'
+  html5ClientBuild: 'HTML5_CLIENT_VERSION'
   lockOnJoin: true
 
   # Name displayed in the brower URL
   basename: '/html5client'
 
-  defaultLocale: 'en'
   #default settings for session storage
   defaultSettings:
     application:
       chatAudioNotifications: false
       chatPushNotifications: false
-      fontSize: "16px"
+      fontSize: '16px'
+      locale: 'en'
     audio:
       inputDeviceId: undefined
       outputDeviceId: undefined
     video:
       viewParticipantsWebcams: true
     cc:
-      backgroundColor: "#FFFFFF"
-      fontColor: "#000000"
+      backgroundColor: '#FFFFFF'
+      fontColor: '#000000'
       enabled: false
-      fontFamily: "Calibri"
+      fontFamily: 'Calibri'
       fontSize: '16px'
       # locale: undefined
       takeOwnership: false
@@ -53,4 +53,4 @@ app:
 
   # The initial client version has limited moderator capabilities
   # The following flag disables moderator-only features
-  allowHTML5Moderator: false
+  allowHTML5Moderator: true
diff --git a/bigbluebutton-html5/private/config/public/whiteboard.yaml b/bigbluebutton-html5/private/config/public/whiteboard.yaml
new file mode 100755
index 0000000000000000000000000000000000000000..40d6d0eb1ac4fdc589b17a437f3fbea0f78ac4f8
--- /dev/null
+++ b/bigbluebutton-html5/private/config/public/whiteboard.yaml
@@ -0,0 +1,59 @@
+whiteboard:
+  #annotation statuses specific to the each type of annotation
+  annotations:
+    message_frequency: 50
+    status:
+      start: 'DRAW_START'
+      update: 'DRAW_UPDATE'
+      end: 'DRAW_END'
+  toolbar:
+    colors:
+      - value: '#000000'
+      - value: '#ffffff'
+      - value: '#ff0000'
+      - value: '#ff8800'
+      - value: '#ccff00'
+      - value: '#00ff00'
+      - value: '#00ffff'
+      - value: '#0088ff'
+      - value: '#0000ff'
+      - value: '#8800ff'
+      - value: '#ff00ff'
+      - value: '#c0c0c0'
+    thickness:
+      - value: 14
+      - value: 12
+      - value: 10
+      - value: 8
+      - value: 6
+      - value: 4
+      - value: 2
+    font_sizes: 
+      - value: 36
+      - value: 32
+      - value: 28
+      - value: 24
+      - value: 20
+      - value: 16
+    tools:
+      #text
+      - icon: 'text_tool'
+        value: 'text'
+      #line
+      - icon: 'linte_tool'
+        value: 'line'
+      #ellipse
+      - icon: 'circle_tool'
+        value: 'ellipse'
+      #triangle
+      - icon: 'triangle_tool'
+        value: 'triangle'
+      #rectangle
+      - icon: 'rectangle_tool'
+        value: 'rectangle'
+      #pencil
+      - icon: 'pen_tool'
+        value: 'pencil'
+      #pan and zoom hand
+      - icon: 'hand'
+        value: 'hand'
diff --git a/bigbluebutton-html5/private/locales/en.json b/bigbluebutton-html5/private/locales/en.json
index fd57c0ef6249c0e261ee8f0d0ab2dbfb87af93dc..65843bbc87923d1b64f351e86acb67b3463bbdc6 100755
--- a/bigbluebutton-html5/private/locales/en.json
+++ b/bigbluebutton-html5/private/locales/en.json
@@ -34,6 +34,8 @@
     "app.userList.menu.muteUserAudio.label": "Mute user",
     "app.userList.menu.unmuteUserAudio.label": "Unmute user",
     "app.userList.userAriaLabel": "User : {0}  Role: {1}  Person: {2}  Status: {3}",
+    "app.userList.menu.promoteUser.label": "Promote {0} to moderator",
+    "app.userList.menu.demoteUser.label": "Demote {0} to viewer",
     "app.media.label": "Media",
     "app.presentation.presentationToolbar.prevSlideLabel": "Previous slide",
     "app.presentation.presentationToolbar.prevSlideDesc": "Change the presentation to the previous slide",
diff --git a/bigbluebutton-web/grails-app/conf/bigbluebutton.properties b/bigbluebutton-web/grails-app/conf/bigbluebutton.properties
index 6b82969d3573f170e1047e5cc6fee6533409db39..2cb809e165f82385eb00dab17cb51f8a6d5d1f97 100755
--- a/bigbluebutton-web/grails-app/conf/bigbluebutton.properties
+++ b/bigbluebutton-web/grails-app/conf/bigbluebutton.properties
@@ -109,7 +109,7 @@ defaultGuestPolicy=ASK_MODERATOR
 #
 # native2ascii -encoding UTF8 bigbluebutton.properties bigbluebutton.properties
 #
-defaultWelcomeMessage=<br>Welcome to <b>%%CONFNAME%%</b>!<br><br>For help on using BigBlueButton see these (short) <a href="event:http://www.bigbluebutton.org/content/videos"><u>tutorial videos</u></a>.<br><br>To join the audio bridge click the phone button (top center of screen).  Use a headset to avoid causing background noise for others.<br>
+defaultWelcomeMessage=<br>Welcome to <b>%%CONFNAME%%</b>!<br><br>For help on using BigBlueButton see these (short) <a href="event:http://www.bigbluebutton.org/content/videos"><u>tutorial videos</u></a>.<br><br>To join the audio bridge click the phone button.  Use a headset to avoid causing background noise for others.<br>
 defaultWelcomeMessageFooter=This server is running <a href="http://docs.bigbluebutton.org/" target="_blank"><u>BigBlueButton</u></a>.
 
 # Default maximum number of users a meeting can have.