{this.renderNavBar()}
{this.renderMedia()}
{this.renderActionsBar()}
diff --git a/bigbluebutton-html5/imports/ui/components/app/styles.scss b/bigbluebutton-html5/imports/ui/components/app/styles.scss
index 012a51c504..e06813053d 100755
--- a/bigbluebutton-html5/imports/ui/components/app/styles.scss
+++ b/bigbluebutton-html5/imports/ui/components/app/styles.scss
@@ -9,6 +9,7 @@
--bars-padding: calc(var(--lg-padding-x) - .45rem); // -.45 so user-list and chat title is aligned with the presentation title
--userlist-handle-width: 5px; // 5px so user-list and chat resize handle render as the same size
--poll-pane-min-width: 20em;
+ --panel-margin-left: 0.1em;
}
.main {
@@ -57,7 +58,7 @@
}
}
-.content {
+.content, .noPanelContent {
@extend %full-page;
order: 3;
@@ -89,13 +90,16 @@
}
}
+.content{
+ margin-left: var(--panel-margin-left);
+}
.userList {
@extend %full-page;
@extend %text-elipsis;
z-index: 2;
- overflow: visible;
+ overflow: visible;
order: 1;
@include mq($small-only) {
@@ -177,7 +181,7 @@
order: 2;
flex-direction: row;
position: relative;
-
+ margin-left: var(--panel-margin-right);
@include mq($portrait) {
flex-direction: column;
}
diff --git a/bigbluebutton-html5/imports/ui/components/chat/service.js b/bigbluebutton-html5/imports/ui/components/chat/service.js
index 2dcf0e5dd8..70c6c3b152 100755
--- a/bigbluebutton-html5/imports/ui/components/chat/service.js
+++ b/bigbluebutton-html5/imports/ui/components/chat/service.js
@@ -18,6 +18,7 @@ const PUBLIC_CHAT_ID = CHAT_CONFIG.public_id;
const PUBLIC_GROUP_CHAT_ID = CHAT_CONFIG.public_group_id;
const PRIVATE_CHAT_TYPE = CHAT_CONFIG.type_private;
const PUBLIC_CHAT_USER_ID = CHAT_CONFIG.system_userid;
+const PUBLIC_CHAT_CLEAR = CHAT_CONFIG.system_messages_keys.chat_clear;
const ScrollCollection = new Mongo.Collection(null);
@@ -248,8 +249,27 @@ const htmlDecode = (input) => {
};
// Export the chat as [Hour:Min] user: message
-const exportChat = messageList => (
- messageList.map((message) => {
+const exportChat = (messageList) => {
+ const { welcomeProp } = getMeeting();
+ const { logTime } = getUser(Auth.userID);
+ const { welcomeMsg } = welcomeProp;
+
+ const clearMessage = messageList.filter(message => message.message === PUBLIC_CHAT_CLEAR);
+
+ const hasClearMessage = clearMessage.length;
+
+ if (!hasClearMessage || (hasClearMessage && clearMessage[0].timestamp < logTime)) {
+ messageList.push({
+ timestamp: logTime,
+ message: welcomeMsg,
+ type: SYSTEM_CHAT_TYPE,
+ sender: PUBLIC_CHAT_USER_ID,
+ });
+ }
+
+ messageList.sort((a, b) => a.timestamp - b.timestamp);
+
+ return messageList.map((message) => {
const date = new Date(message.timestamp);
const hour = date.getHours().toString().padStart(2, 0);
const min = date.getMinutes().toString().padStart(2, 0);
@@ -259,8 +279,8 @@ const exportChat = messageList => (
}
const userName = message.sender === PUBLIC_CHAT_USER_ID ? '' : `${getUser(message.sender).name} :`;
return `${hourMin} ${userName} ${htmlDecode(message.message)}`;
- }).join('\n')
-);
+ }).join('\n');
+};
const setNotified = (chatType, item) => {
const notified = Storage.getItem('notified');
diff --git a/bigbluebutton-html5/imports/ui/components/media/container.jsx b/bigbluebutton-html5/imports/ui/components/media/container.jsx
index 142205160b..eb6ca0ce21 100755
--- a/bigbluebutton-html5/imports/ui/components/media/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/media/container.jsx
@@ -7,7 +7,6 @@ import { notify } from '/imports/ui/services/notification';
import VideoService from '/imports/ui/components/video-provider/service';
import getFromUserSettings from '/imports/ui/services/users-settings';
import { withModalMounter } from '/imports/ui/components/modal/service';
-import VideoPreviewContainer from '/imports/ui/components/video-preview/container';
import Media from './component';
import MediaService, { getSwapLayout } from './service';
import PresentationPodsContainer from '../presentation-pod/container';
@@ -80,8 +79,9 @@ class MediaContainer extends Component {
const chromeErrorElement = (
@@ -99,7 +99,7 @@ class MediaContainer extends Component {
}
}
-export default withModalMounter(withTracker(({ mountModal }) => {
+export default withModalMounter(withTracker(() => {
const { dataSaving } = Settings;
const { viewParticipantsWebcams, viewScreenshare } = dataSaving;
@@ -118,7 +118,7 @@ export default withModalMounter(withTracker(({ mountModal }) => {
}
const usersVideo = VideoService.getAllUsersVideo();
- if (MediaService.shouldShowOverlay() && usersVideo.length) {
+ if (MediaService.shouldShowOverlay() && usersVideo.length && viewParticipantsWebcams) {
data.floatingOverlay = usersVideo.length < 2;
data.hideOverlay = usersVideo.length === 0;
}
diff --git a/bigbluebutton-html5/imports/ui/components/settings/component.jsx b/bigbluebutton-html5/imports/ui/components/settings/component.jsx
index 7f7e6a3f7d..fd0dc75ec8 100644
--- a/bigbluebutton-html5/imports/ui/components/settings/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/settings/component.jsx
@@ -1,10 +1,12 @@
import React, { Component } from 'react';
import Modal from '/imports/ui/components/modal/fullscreen/component';
-import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
+import {
+ Tab, Tabs, TabList, TabPanel,
+} from 'react-tabs';
import { defineMessages, injectIntl, intlShape } from 'react-intl';
import ClosedCaptions from '/imports/ui/components/settings/submenus/closed-captions/component';
import DataSaving from '/imports/ui/components/settings/submenus/data-saving/component';
-import Application from '/imports/ui/components/settings/submenus/application/container';
+import Application from '/imports/ui/components/settings/submenus/application/component';
import _ from 'lodash';
import PropTypes from 'prop-types';
@@ -61,20 +63,43 @@ const intlMessages = defineMessages({
const propTypes = {
intl: intlShape.isRequired,
- dataSaving: PropTypes.object.isRequired,
- application: PropTypes.object.isRequired,
- cc: PropTypes.object.isRequired,
- participants: PropTypes.object.isRequired,
+ dataSaving: PropTypes.shape({
+ viewParticipantsWebcams: PropTypes.bool,
+ viewScreenshare: PropTypes.bool,
+ }).isRequired,
+ application: PropTypes.shape({
+ chatAudioAlerts: PropTypes.bool,
+ chatPushAlerts: PropTypes.bool,
+ fallbackLocale: PropTypes.string,
+ fontSize: PropTypes.string,
+ locale: PropTypes.string,
+ }).isRequired,
+ cc: PropTypes.shape({
+ backgroundColor: PropTypes.string,
+ enabled: PropTypes.bool,
+ fontColor: PropTypes.string,
+ fontFamily: PropTypes.string,
+ fontSize: PropTypes.string,
+ takeOwnership: PropTypes.bool,
+ }).isRequired,
+ participants: PropTypes.shape({
+ layout: PropTypes.bool,
+ lockAll: PropTypes.bool,
+ microphone: PropTypes.bool,
+ muteAll: PropTypes.bool,
+ privateChat: PropTypes.bool,
+ publicChat: PropTypes.bool,
+ }).isRequired,
updateSettings: PropTypes.func.isRequired,
- availableLocales: PropTypes.object.isRequired,
+ availableLocales: PropTypes.objectOf(PropTypes.array).isRequired,
mountModal: PropTypes.func.isRequired,
- locales: PropTypes.array.isRequired,
};
class Settings extends Component {
static setHtmlFontSize(size) {
document.getElementsByTagName('html')[0].style.fontSize = size;
}
+
constructor(props) {
super(props);
@@ -104,7 +129,8 @@ class Settings extends Component {
}
componentWillMount() {
- this.props.availableLocales.then((locales) => {
+ const { availableLocales } = this.props;
+ availableLocales.then((locales) => {
this.setState({ availableLocales: locales });
});
}
@@ -123,12 +149,17 @@ class Settings extends Component {
renderModalContent() {
const { intl } = this.props;
-
+ const {
+ selectedTab,
+ availableLocales,
+ current,
+ locales,
+ } = this.state;
return (
@@ -170,9 +201,9 @@ class Settings extends Component {
{/* */}
@@ -183,14 +214,14 @@ class Settings extends Component {
{/* */}
@@ -205,18 +236,22 @@ class Settings extends Component {
);
}
+
render() {
const {
intl,
mountModal,
} = this.props;
-
+ const {
+ current,
+ saved,
+ } = this.state;
return (
{
- this.updateSettings(this.state.current);
+ this.updateSettings(current);
// router.push(location.pathname); // TODO 4767
/* We need to use mountModal(null) here to prevent submenu state updates,
* from re-opening the modal.
@@ -228,7 +263,7 @@ class Settings extends Component {
}}
dismiss={{
callback: () => {
- Settings.setHtmlFontSize(this.state.saved.application.fontSize);
+ Settings.setHtmlFontSize(saved.application.fontSize);
mountModal(null);
},
label: intl.formatMessage(intlMessages.CancelLabel),
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 9605cf4f5d..04cea4df29 100644
--- a/bigbluebutton-html5/imports/ui/components/settings/submenus/application/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/settings/submenus/application/component.jsx
@@ -1,13 +1,12 @@
import React from 'react';
-import Button from '/imports/ui/components/button/component';
import cx from 'classnames';
+import Button from '/imports/ui/components/button/component';
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;
const intlMessages = defineMessages({
applicationSectionTitle: {
@@ -61,6 +60,10 @@ const intlMessages = defineMessages({
});
class ApplicationMenu extends BaseMenu {
+ static setHtmlFontSize(size) {
+ document.getElementsByTagName('html')[0].style.fontSize = size;
+ }
+
constructor(props) {
super(props);
@@ -69,41 +72,66 @@ class ApplicationMenu extends BaseMenu {
settings: props.settings,
isLargestFontSize: false,
isSmallestFontSize: false,
+ fontSizes: [
+ '12px',
+ '14px',
+ '16px',
+ '18px',
+ '20px',
+ ],
};
}
+ componentDidMount() {
+ this.setInitialFontSize();
+ }
+
+ setInitialFontSize() {
+ const { fontSizes } = this.state;
+ const clientFont = document.getElementsByTagName('html')[0].style.fontSize;
+ const hasFont = fontSizes.includes(clientFont);
+ if (!hasFont) {
+ fontSizes.push(clientFont);
+ fontSizes.sort();
+ }
+ const fontIndex = fontSizes.indexOf(clientFont);
+ this.changeFontSize(clientFont);
+ this.setState({
+ isSmallestFontSize: fontIndex <= MIN_FONTSIZE,
+ isLargestFontSize: fontIndex >= (fontSizes.length - 1),
+ fontSizes,
+ });
+ }
+
handleUpdateFontSize(size) {
const obj = this.state;
obj.settings.fontSize = size;
this.handleUpdateSettings(this.state.settingsName, obj.settings);
}
- setHtmlFontSize(size) {
- document.getElementsByTagName('html')[0].style.fontSize = size;
- }
-
changeFontSize(size) {
const obj = this.state;
obj.settings.fontSize = size;
this.setState(obj, () => {
- this.setHtmlFontSize(this.state.settings.fontSize);
+ ApplicationMenu.setHtmlFontSize(this.state.settings.fontSize);
this.handleUpdateFontSize(this.state.settings.fontSize);
});
}
handleIncreaseFontSize() {
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 availableFontSizes = this.state.fontSizes;
+ const maxFontSize = availableFontSizes.length - 1;
+ const canIncreaseFontSize = availableFontSizes.indexOf(currentFontSize) < maxFontSize;
+ const fs = canIncreaseFontSize ? availableFontSizes.indexOf(currentFontSize) + 1 : maxFontSize;
this.changeFontSize(availableFontSizes[fs]);
- if (fs === MAX_FONTSIZE) this.setState({ isLargestFontSize: true });
+ if (fs === maxFontSize) this.setState({ isLargestFontSize: true });
this.setState({ isSmallestFontSize: false });
}
handleDecreaseFontSize() {
const currentFontSize = this.state.settings.fontSize;
- const availableFontSizes = this.props.fontSizes;
+ const availableFontSizes = this.state.fontSizes;
const canDecreaseFontSize = availableFontSizes.indexOf(currentFontSize) > MIN_FONTSIZE;
const fs = canDecreaseFontSize ? availableFontSizes.indexOf(currentFontSize) - 1 : MIN_FONTSIZE;
this.changeFontSize(availableFontSizes[fs]);
diff --git a/bigbluebutton-html5/imports/ui/components/settings/submenus/application/container.jsx b/bigbluebutton-html5/imports/ui/components/settings/submenus/application/container.jsx
deleted file mode 100644
index b9011514dd..0000000000
--- a/bigbluebutton-html5/imports/ui/components/settings/submenus/application/container.jsx
+++ /dev/null
@@ -1,20 +0,0 @@
-import React from 'react';
-import { withTracker } from 'meteor/react-meteor-data';
-import Application from './component';
-
-
-const ApplicationContainer = ({ children, ...props }) => (
-
- {children}
-
-);
-
-export default withTracker(() => ({
- fontSizes: [
- '12px',
- '14px',
- '16px',
- '18px',
- '20px',
- ],
-}))(ApplicationContainer);
diff --git a/bigbluebutton-html5/private/config/settings.yml b/bigbluebutton-html5/private/config/settings.yml
index 7af5f976c8..a0658e3d6c 100755
--- a/bigbluebutton-html5/private/config/settings.yml
+++ b/bigbluebutton-html5/private/config/settings.yml
@@ -1,7 +1,7 @@
public:
app:
- mobileFont: 16
- desktopFont: 14
+ mobileFontSize: 16px
+ desktopFontSize: 14px
audioChatNotification: false
autoJoin: true
showParticipantsOnLogin: true
@@ -20,7 +20,6 @@ public:
application:
chatAudioAlerts: false
chatPushAlerts: false
- fontSize: 16px
fallbackLocale: en
audio:
inputDeviceId: undefined
diff --git a/bigbluebutton-html5/private/locales/en.json b/bigbluebutton-html5/private/locales/en.json
index 253ab9b93c..46ed71f02d 100755
--- a/bigbluebutton-html5/private/locales/en.json
+++ b/bigbluebutton-html5/private/locales/en.json
@@ -431,7 +431,7 @@
"app.sfu.noAvailableCodec2203": "Error 2203: Server could not find an appropriate codec",
"app.meeting.endNotification.ok.label": "OK",
"app.whiteboard.toolbar.tools": "Tools",
- "app.whiteboard.toolbar.tools.hand": "Hand",
+ "app.whiteboard.toolbar.tools.hand": "Pan",
"app.whiteboard.toolbar.tools.pencil": "Pencil",
"app.whiteboard.toolbar.tools.rectangle": "Rectangle",
"app.whiteboard.toolbar.tools.triangle": "Triangle",
@@ -456,8 +456,8 @@
"app.whiteboard.toolbar.color.silver": "Silver",
"app.whiteboard.toolbar.undo": "Undo annotation",
"app.whiteboard.toolbar.clear": "Clear all annotations",
- "app.whiteboard.toolbar.multiUserOn": "Turn multi-user mode on",
- "app.whiteboard.toolbar.multiUserOff": "Turn multi-user mode off",
+ "app.whiteboard.toolbar.multiUserOn": "Turn multi-user whiteboard on",
+ "app.whiteboard.toolbar.multiUserOff": "Turn multi-user whiteboard off",
"app.whiteboard.toolbar.fontSize": "Font Size List",
"app.feedback.title": "You have logged out of the conference",
"app.feedback.subtitle": "We'd love to hear about your experience with BigBlueButton (optional)",