-
-
-
-
-
-
-
-
+
+
-
-
diff --git a/interface_config.js b/interface_config.js
index cedf08cf5..48d29b7d3 100644
--- a/interface_config.js
+++ b/interface_config.js
@@ -16,6 +16,7 @@ var interfaceConfig = {
INVITATION_POWERED_BY: true,
// the toolbar buttons line is intentionally left in one line, to be able
// to easily override values or remove them using regex
+ MAIN_TOOLBAR_BUTTONS: ['microphone', 'camera', 'desktop', 'fullscreen', 'hangup'], // jshint ignore:line
TOOLBAR_BUTTONS: ['authentication', 'microphone', 'camera', 'desktop', 'recording', 'security', 'invite', 'chat', 'etherpad', 'sharedvideo', 'fullscreen', 'sip', 'dialpad', 'settings', 'hangup', 'filmstrip', 'contacts'], // jshint ignore:line
// Determines how the video would fit the screen. 'both' would fit the whole
// screen, 'height' would fit the original video height to the height of the
diff --git a/lang/main.json b/lang/main.json
index 05d279f43..c60efe018 100644
--- a/lang/main.json
+++ b/lang/main.json
@@ -1,5 +1,5 @@
{
- "contactlist": "On Call (__participants__)",
+ "contactlist": "ON CALL (__participants__)",
"connectionsettings": "Connection Settings",
"poweredby": "powered by",
"downloadlogs": "Download logs",
@@ -109,17 +109,27 @@
},
"settings":
{
- "title": "Settings",
+ "title": "SETTINGS",
"update": "Update",
"name": "Name",
- "startAudioMuted": "Start without audio",
- "startVideoMuted": "Start without video",
+ "startAudioMuted": "Everyone starts muted",
+ "startVideoMuted": "Everyone starts hidden",
"selectCamera": "Select camera",
"selectMic": "Select microphone",
"selectAudioOutput": "Select audio output",
- "followMe": "Enable follow me",
+ "followMe": "Everyone follows me",
"noDevice": "None",
- "noPermission": "Permission to use device is not granted"
+ "noPermission": "Permission to use device is not granted",
+ "cameraAndMic": "Camera and microphone",
+ "moderator": "MODERATOR",
+ "password": "SET PASSWORD",
+ "audioVideo": "AUDIO / VIDEO",
+ "setPasswordLabel": "Lock your room with a password."
+ },
+ "profile": {
+ "title": "PROFILE",
+ "setDisplayNameLabel": "Set your display name",
+ "setEmailLabel": "Set your gravatar email"
},
"videothumbnail":
{
@@ -221,18 +231,18 @@
"Remove": "Remove",
"passwordMsg": "Set a password to lock your room",
"Invite": "Invite",
- "shareLink": "Share this link with everyone you want to invite",
+ "shareLink": "Copy and share this link",
"settings1": "Configure your conference",
"settings2": "Participants join muted",
"settings3": "Require nicknames
Set a password to lock your room:",
- "yourPassword": "your password",
+ "yourPassword": "Enter new password",
"Back": "Back",
"serviceUnavailable": "Service unavailable",
"gracefulShutdown": "Our service is currently down for maintenance. Please try again later.",
"Yes": "Yes",
"reservationError": "Reservation system error",
"reservationErrorMsg": "Error code: __code__, message: __msg__",
- "password": "password",
+ "password": "Enter password",
"userPassword": "user password",
"token": "token",
"tokenAuthFailed": "Failed to authenticate with XMPP server: invalid token",
diff --git a/modules/UI/UI.js b/modules/UI/UI.js
index 17cc317ae..b705a0334 100644
--- a/modules/UI/UI.js
+++ b/modules/UI/UI.js
@@ -19,6 +19,7 @@ import GumPermissionsOverlay from './gum_overlay/UserMediaPermissionsGuidanceOve
import VideoLayout from "./videolayout/VideoLayout";
import FilmStrip from "./videolayout/FilmStrip";
import SettingsMenu from "./side_pannels/settings/SettingsMenu";
+import Profile from "./side_pannels/profile/Profile";
import Settings from "./../settings/Settings";
import { reload } from '../util/helpers';
import RingOverlay from "./ring_overlay/RingOverlay";
@@ -140,7 +141,7 @@ function setupToolbars() {
* (a.k.a. presentation mode in Chrome).
* @see https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API
*/
-function toggleFullScreen () {
+UI.toggleFullScreen = function() {
// alternative standard method
let isNotFullScreen = !document.fullscreenElement &&
!document.mozFullScreenElement && // current working methods
@@ -169,7 +170,7 @@ function toggleFullScreen () {
document.webkitExitFullscreen();
}
}
-}
+};
/**
* Notify user that server has shut down.
@@ -251,7 +252,7 @@ UI.changeDisplayName = function (id, displayName) {
VideoLayout.onDisplayNameChanged(id, displayName);
if (APP.conference.isLocalId(id) || id === 'localVideoContainer') {
- SettingsMenu.changeDisplayName(displayName);
+ Profile.changeDisplayName(displayName);
Chat.setChatConversationMode(!!displayName);
}
};
@@ -355,16 +356,20 @@ function registerListeners() {
}
});
- UI.addListener(UIEvents.FULLSCREEN_TOGGLE, toggleFullScreen);
+ UI.addListener(UIEvents.FULLSCREEN_TOGGLE, UI.toggleFullScreen);
UI.addListener(UIEvents.TOGGLE_CHAT, UI.toggleChat);
UI.addListener(UIEvents.TOGGLE_SETTINGS, function () {
- SideContainerToggler.toggle("settings_container");
+ UI.toggleSidePanel("settings_container");
});
UI.addListener(UIEvents.TOGGLE_CONTACT_LIST, UI.toggleContactList);
+ UI.addListener( UIEvents.TOGGLE_PROFILE, function() {
+ UI.toggleSidePanel("profile_container");
+ });
+
UI.addListener(UIEvents.TOGGLE_FILM_STRIP, UI.handleToggleFilmStrip);
UI.addListener(UIEvents.FOLLOW_ME_ENABLED, function (isEnabled) {
@@ -379,6 +384,7 @@ function registerListeners() {
function bindEvents() {
function onResize() {
SideContainerToggler.resize();
+ VideoLayout.resizeVideoArea();
}
// Resize and reposition videos in full screen mode.
@@ -499,6 +505,7 @@ UI.start = function () {
};
SettingsMenu.init(eventEmitter);
+ Profile.init(eventEmitter);
}
if(APP.tokenData.callee) {
@@ -716,16 +723,26 @@ UI.isFilmStripVisible = function () {
* Toggles chat panel.
*/
UI.toggleChat = function () {
- SideContainerToggler.toggle("chat_container");
+ UI.toggleSidePanel("chat_container");
};
/**
* Toggles contact list panel.
*/
UI.toggleContactList = function () {
- SideContainerToggler.toggle("contacts_container");
+ UI.toggleSidePanel("contacts_container");
};
+/**
+ * Toggles the given side panel.
+ *
+ * @param {String} sidePanelId the identifier of the side panel to toggle
+ */
+UI.toggleSidePanel = function (sidePanelId) {
+ SideContainerToggler.toggle(sidePanelId);
+};
+
+
/**
* Handle new user display name.
*/
@@ -817,6 +834,16 @@ UI.removeListener = function (type, listener) {
eventEmitter.removeListener(type, listener);
};
+/**
+ * Emits the event of given type by specifying the parameters in options.
+ *
+ * @param type the type of the event we're emitting
+ * @param options the parameters for the event
+ */
+UI.emitEvent = function (type, options) {
+ eventEmitter.emit(type, options);
+};
+
UI.clickOnVideo = function (videoNumber) {
var remoteVideos = $(".videocontainer:not(#mixedstream)");
if (remoteVideos.length > videoNumber) {
@@ -843,7 +870,7 @@ function changeAvatar(id, avatarUrl) {
VideoLayout.changeUserAvatar(id, avatarUrl);
ContactList.changeUserAvatar(id, avatarUrl);
if (APP.conference.isLocalId(id)) {
- SettingsMenu.changeAvatar(avatarUrl);
+ Profile.changeAvatar(avatarUrl);
}
}
diff --git a/modules/UI/side_pannels/profile/Profile.js b/modules/UI/side_pannels/profile/Profile.js
new file mode 100644
index 000000000..cbd4aeeae
--- /dev/null
+++ b/modules/UI/side_pannels/profile/Profile.js
@@ -0,0 +1,61 @@
+/* global APP, $, JitsiMeetJS */
+import UIUtil from "../../util/UIUtil";
+import UIEvents from "../../../../service/UI/UIEvents";
+import languages from "../../../../service/translation/languages";
+import Settings from '../../../settings/Settings';
+
+export default {
+ init (emitter) {
+ // DISPLAY NAME
+ function updateDisplayName () {
+ emitter.emit(UIEvents.NICKNAME_CHANGED, $('#setDisplayName').val());
+ }
+
+ $('#setDisplayName')
+ .val(Settings.getDisplayName())
+ .keyup(function (event) {
+ if (event.keyCode === 13) { // enter
+ updateDisplayName();
+ }
+ })
+ .focusout(updateDisplayName);
+
+
+ // EMAIL
+ function updateEmail () {
+ emitter.emit(UIEvents.EMAIL_CHANGED, $('#setEmail').val());
+ }
+
+ $('#setEmail')
+ .val(Settings.getEmail())
+ .keyup(function (event) {
+ if (event.keyCode === 13) { // enter
+ updateEmail();
+ }
+ }).focusout(updateEmail);
+ },
+
+ /**
+ * Check if settings menu is visible or not.
+ * @returns {boolean}
+ */
+ isVisible () {
+ return UIUtil.isVisible(document.getElementById("profile_container"));
+ },
+
+ /**
+ * Change user display name in the settings menu.
+ * @param {string} newDisplayName
+ */
+ changeDisplayName (newDisplayName) {
+ $('#setDisplayName').val(newDisplayName);
+ },
+
+ /**
+ * Change user avatar in the settings menu.
+ * @param {string} avatarUrl url of the new avatar
+ */
+ changeAvatar (avatarUrl) {
+ $('#avatar').attr('src', avatarUrl);
+ }
+};
\ No newline at end of file
diff --git a/modules/UI/side_pannels/settings/SettingsDialog.js b/modules/UI/side_pannels/settings/SettingsDialog.js
new file mode 100644
index 000000000..6ebf5004a
--- /dev/null
+++ b/modules/UI/side_pannels/settings/SettingsDialog.js
@@ -0,0 +1,288 @@
+/* global APP, $, JitsiMeetJS */
+import UIUtil from "../../util/UIUtil";
+import UIEvents from "../../../../service/UI/UIEvents";
+import languages from "../../../../service/translation/languages";
+import Settings from '../../../settings/Settings';
+import mediaDeviceHelper from '../../../devices/mediaDeviceHelper';
+
+const RTCUIUtils = JitsiMeetJS.util.RTCUIHelper;
+
+var constructAudioIndicatorHtml = function() {
+ return '
'
+ + ''
+ + ''
+ + ''
+ + ''
+ + ''
+ + ''
+ + ''
+ + ''
+ + ''
+ + ''
+ + '';
+};
+
+var constructMediaSettingsHtml = function() {
+ return '
'
+ + '
'
+ //+ constructAudioIndicatorHtml()
+ + '
'
+ + ''
+ + ' '
+ + ''
+ + ''
+ + ' '
+ + ''
+ + ''
+ + ' '
+ + ''
+ + '
'
+ + '
';
+};
+
+/**
+ * The callback function corresponding to the openSettingsWindow parameter.
+ *
+ * @type {function}
+ */
+var settingsWindowCallback = null;
+
+/**
+ * Defines all methods in connection to the Settings dialog.
+ */
+var SettingsDialog = {
+ init(eventEmitter) {
+ this.eventEmitter = eventEmitter;
+ },
+
+ /**
+ * Generate html select options for available physical devices.
+ * @param {{ deviceId, label }[]} items available devices
+ * @param {string} [selectedId] id of selected device
+ * @param {boolean} permissionGranted if permission to use selected device
+ * type is granted
+ * @returns {string}
+ */
+ _generateDevicesOptions(items, selectedId, permissionGranted) {
+ if (!permissionGranted && items.length) {
+ return '
';
+ }
+
+ var options = items.map(function (item) {
+ let attrs = {
+ value: item.deviceId
+ };
+
+ if (item.deviceId === selectedId) {
+ attrs.selected = 'selected';
+ }
+
+ let attrsStr = UIUtil.attrsToString(attrs);
+ return `
`;
+ });
+
+ if (!items.length) {
+ options.unshift('
');
+ }
+
+ return options.join('');
+ },
+
+ _onLoadMediaSettings() {
+ let localVideoPreview = document.getElementById("localVideoPreview");
+ RTCUIUtils.setAutoPlay(localVideoPreview, true);
+ RTCUIUtils.setVolume(localVideoPreview, 0);
+
+ let localVideo = APP.conference.getVideoStream();
+ if (localVideo)
+ localVideoPreview = localVideo.attach(localVideoPreview);
+
+ this.eventEmitter.addListener(UIEvents.VIDEO_STREAM_CHANGED,
+ function(newStream)
+ {
+ newStream.attach(localVideoPreview);
+ });
+
+ // DEVICES LIST
+ JitsiMeetJS.mediaDevices.isDeviceListAvailable()
+ .then((isDeviceListAvailable) => {
+ if (isDeviceListAvailable &&
+ JitsiMeetJS.mediaDevices.isDeviceChangeAvailable()) {
+
+ this._initializeDeviceSelectionSettings();
+ }
+ });
+
+ APP.UI.eventEmitter.addListener(UIEvents.DEVICE_LIST_CHANGED,
+ (devices) => {
+ this._changeDevicesList(devices);
+ });
+ },
+
+ /**
+ * Initializes the device list with the current available media devices
+ * and attaches all listeners needed for device change user
+ * event handling.
+ */
+ _initializeDeviceSelectionSettings() {
+ this._changeDevicesList(mediaDeviceHelper.getCurrentMediaDevices());
+
+ $('#selectCamera').change(function () {
+ let cameraDeviceId = $(this).val();
+ if (cameraDeviceId !== Settings.getCameraDeviceId()) {
+ this.eventEmitter
+ .emit(UIEvents.VIDEO_DEVICE_CHANGED, cameraDeviceId);
+ }
+ });
+ $('#selectMic').change(function () {
+ let micDeviceId = $(this).val();
+ if (micDeviceId !== Settings.getMicDeviceId()) {
+ this.eventEmitter
+ .emit(UIEvents.AUDIO_DEVICE_CHANGED, micDeviceId);
+ }
+ });
+ $('#selectAudioOutput').change(function () {
+ let audioOutputDeviceId = $(this).val();
+ if (audioOutputDeviceId !== Settings.getAudioOutputDeviceId()) {
+ this.eventEmitter.emit(
+ UIEvents.AUDIO_OUTPUT_DEVICE_CHANGED, audioOutputDeviceId);
+ }
+ });
+ },
+
+ /**
+ * Sets microphone's