[OPENMEETINGS-2000] more work on user settings
diff --git a/openmeetings-web/src/main/front/chat/src/chat.js b/openmeetings-web/src/main/front/chat/src/chat.js
index 99ea213..7486543 100644
--- a/openmeetings-web/src/main/front/chat/src/chat.js
+++ b/openmeetings-web/src/main/front/chat/src/chat.js
@@ -37,17 +37,20 @@
 			muted: false
 			, sendOn: DEF_SEND
 		};
+		Settings.save(s)
 	}
 	muted = s.chat.muted === true;
 	sendOn = s.chat.sendOn === SEND_ENTER ? SEND_ENTER : SEND_CTRL;
 	return s;
 }
-function _updateAudioBtn(btn) {
+function _updateAudioBtn() {
+	const btn = $('#chat .audio');
 	btn.removeClass('sound' + (muted ? '' : '-mute')).addClass('sound' + (muted ? '-mute' : ''))
 			.attr('title', btn.data(muted ? 'sound-enabled' : 'sound-muted'));
 }
-function _updateSendBtn(btn) {
-	const ctrl = sendOn === SEND_CTRL;
+function _updateSendBtn() {
+	const btn = $('#chat .send-btn')
+		, ctrl = sendOn === SEND_CTRL;
 	if (ctrl) {
 		btn.addClass('send-ctrl');
 		editor.off('keydown', _sendOnEnter).keydown('Ctrl+return', _sendOnEnter);
@@ -89,19 +92,19 @@
 	const sbtn = $('#chat .send-btn');
 	{ //scope
 		_load();
-		_updateAudioBtn(a);
-		_updateSendBtn(sbtn)
+		_updateAudioBtn();
+		_updateSendBtn()
 	}
 	a.off().click(function() {
 		const s = _load();
 		muted = s.chat.muted = !s.chat.muted;
-		_updateAudioBtn(a);
+		_updateAudioBtn();
 		Settings.save(s);
 	});
 	sbtn.off().click(function() {
 		const s = _load();
 		sendOn = s.chat.sendOn = s.chat.sendOn !== SEND_CTRL ? SEND_CTRL : SEND_ENTER;
-		_updateSendBtn(sbtn);
+		_updateSendBtn();
 		Settings.save(s);
 	});
 	$('#chat #hyperlink').parent().find('button').off().click(function() {
@@ -518,7 +521,10 @@
 });
 
 module.exports = {
-	reinit: _reinit
+	SEND_ENTER: SEND_ENTER
+	, SEND_CTRL: SEND_CTRL
+
+	, reinit: _reinit
 	, removeTab: _removeTab
 	, addTab: _addTab
 	, addMessage: _addMessage
@@ -532,6 +538,11 @@
 	, toggle: _toggle
 	, setRoomMode: _setRoomMode
 	, clean: _clean
+	, reload: () => {
+		_load();
+		_updateAudioBtn();
+		_updateSendBtn();
+	}
 	, validate: function() {
 		return !!editor && editor.text().trim().length > 0;
 	}
diff --git a/openmeetings-web/src/main/front/room/src/index.js b/openmeetings-web/src/main/front/room/src/index.js
index fc210b9..a3b511f 100644
--- a/openmeetings-web/src/main/front/room/src/index.js
+++ b/openmeetings-web/src/main/front/room/src/index.js
@@ -18,4 +18,5 @@
 	, Sharer: require('./sharer')
 	, Room: require('./room')
 	, Activities: require('./activities')
+	, UserSettings: require('./user-settings')
 });
diff --git a/openmeetings-web/src/main/front/room/src/user-settings.js b/openmeetings-web/src/main/front/room/src/user-settings.js
new file mode 100644
index 0000000..372deed
--- /dev/null
+++ b/openmeetings-web/src/main/front/room/src/user-settings.js
@@ -0,0 +1,63 @@
+/* Licensed under the Apache License, Version 2.0 (the "License") http://www.apache.org/licenses/LICENSE-2.0 */
+
+function __initMuteOthers() {
+	let s = VideoSettings.load();
+	$('#muteOthersAsk')
+		.prop('checked', s.video.confirmMuteOthers)
+		.off().click(function() {
+			s = VideoSettings.load();
+			s.video.confirmMuteOthers = !$('#muteOthersAsk').prop('checked');
+			VideoSettings.save();
+		});
+}
+function __initChat() {
+	let s = Settings.load();
+	$('#chatNotify')
+		.prop('checked', s.chat.muted)
+		.off().click(function() {
+			s = Settings.load();
+			s.chat.muted = !$('#chatNotify').prop('checked');
+			Settings.save(s);
+			Chat.reload();
+		});
+	$('#sendOnCtrlEnter')
+		.prop('checked', s.chat.sendOn === Chat.SEND_CTRL)
+		.off().click(function() {
+			s = Settings.load();
+			s.chat.sendOn = $('#sendOnCtrlEnter').prop('checked') ? Chat.SEND_CTRL : Chat.SEND_ENTER;
+			Settings.save(s);
+			Chat.reload();
+		});
+}
+function __initVideo() {
+	let s = VideoSettings.load()
+		, resolutions = $('#video-settings .cam-resolution').clone();
+	if (typeof(s.fixed) === 'undefined') {
+		s.fixed = {
+			enabled: false
+			, width: 120
+			, height: 90
+		};
+		VideoSettings.save()
+	}
+	$('#video-sizes-container').html('')
+		.append(resolutions);
+	$('#sendOnCtrlEnter')
+		.prop('checked', s.fixed.enabled)
+		.off().click(function() {
+			s = Settings.load();
+			s.chat.sendOn = $('#sendOnCtrlEnter').prop('checked') ? Chat.SEND_CTRL : Chat.SEND_ENTER;
+			Settings.save(s);
+			Chat.reload();
+		});
+}
+function _open() {
+	__initMuteOthers();
+	__initChat();
+	__initVideo();
+	$('#room-local-settings').modal('show');
+}
+
+module.exports = {
+	open: _open
+};
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.html b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.html
index 6cc6111..1b12ee5 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.html
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.html
@@ -81,6 +81,18 @@
 							<input type="checkbox" class="custom-control-input" id="chatNotify">
 							<label class="custom-control-label" for="chatNotify"><wicket:message key="sound.enable"/></label>
 						</div>
+						<div class="custom-control custom-checkbox col-10">
+							<input type="checkbox" class="custom-control-input" id="sendOnCtrlEnter">
+							<label class="custom-control-label" for="sendOnCtrlEnter"><wicket:message key="send.on.ctrl.enter"/></label>
+						</div>
+					</div>
+					<h5 class="mt-2">Video</h5> <!-- FIXME TODO localize -->
+					<div class="row justify-content-end">
+						<div class="custom-control custom-checkbox col-10">
+							<input type="checkbox" class="custom-control-input" id="fixedVideoPod">
+							<label class="custom-control-label" for="fixedVideoPod">Fixed video pod size</label>
+						</div>
+						<div id="video-sizes-container col-10"></div>
 					</div>
 				</div>
 			</div>
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/menu/ActionsSubMenu.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/menu/ActionsSubMenu.java
index c35c099..8ec7507 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/menu/ActionsSubMenu.java
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/menu/ActionsSubMenu.java
@@ -153,7 +153,7 @@
 				attributes.getAjaxCallListeners().add(new IAjaxCallListener() {
 					@Override
 					public CharSequence getPrecondition(Component component) {
-						return "$('#room-local-settings').modal('show'); return false;";
+						return "UserSettings.open(); return false;";
 					}
 				});
 			}
diff --git a/openmeetings-web/src/main/webapp/css/raw-general.css b/openmeetings-web/src/main/webapp/css/raw-general.css
index 1140cc8..e05380f 100644
--- a/openmeetings-web/src/main/webapp/css/raw-general.css
+++ b/openmeetings-web/src/main/webapp/css/raw-general.css
@@ -735,10 +735,6 @@
 .abstractWizard input[type=checkbox], .abstractWizard input[type=radio] {
 	width: auto;
 }
-.invitation .message {
-	width: 280px;
-	height: 70px;
-}
 .img-upload .btn.btn-file {
 	width: 120px;
 	padding: 0;