diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b36fd16ab6..21468ab587 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -11,7 +11,7 @@ stages: # define which docker image to use for builds default: - image: gitlab.senfcall.de:5050/senfcall-public/docker-bbb-build:v2021-10-25 + image: gitlab.senfcall.de:5050/senfcall-public/docker-bbb-build:v2021-11-01 # This stage uses git to find out since when each package has been unmodified. # it then checks an API endpoint on the package server to find out for which of diff --git a/bbb-common-web/src/main/java/org/bigbluebutton/api/ApiParams.java b/bbb-common-web/src/main/java/org/bigbluebutton/api/ApiParams.java index ece74cd415..1dabda6d15 100755 --- a/bbb-common-web/src/main/java/org/bigbluebutton/api/ApiParams.java +++ b/bbb-common-web/src/main/java/org/bigbluebutton/api/ApiParams.java @@ -60,6 +60,7 @@ public class ApiParams { public static final String WEBCAMS_ONLY_FOR_MODERATOR = "webcamsOnlyForModerator"; public static final String WELCOME = "welcome"; public static final String HTML5_INSTANCE_ID = "html5InstanceId"; + public static final String ROLE = "role"; public static final String BREAKOUT_ROOMS_ENABLED = "breakoutRoomsEnabled"; public static final String BREAKOUT_ROOMS_RECORD = "breakoutRoomsRecord"; diff --git a/bbb-common-web/src/main/java/org/bigbluebutton/api/MeetingService.java b/bbb-common-web/src/main/java/org/bigbluebutton/api/MeetingService.java index f40faacc63..fa8b4f3fea 100755 --- a/bbb-common-web/src/main/java/org/bigbluebutton/api/MeetingService.java +++ b/bbb-common-web/src/main/java/org/bigbluebutton/api/MeetingService.java @@ -74,6 +74,10 @@ import org.slf4j.LoggerFactory; import com.google.gson.Gson; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.InputStream; + public class MeetingService implements MessageListener { private static Logger log = LoggerFactory.getLogger(MeetingService.class); @@ -1189,6 +1193,13 @@ public class MeetingService implements MessageListener { log.info("Starting Meeting Service."); try { processMessage = true; + Process p = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", "cat /etc/bigbluebutton/bigbluebutton-release | cut -d '=' -f2"}); + + BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())); + + String apiVersionFromFile = reader.readLine(); + + paramsProcessorUtil.setBbbVersion(apiVersionFromFile); Runnable messageReceiver = new Runnable() { public void run() { while (processMessage) { diff --git a/bbb-common-web/src/main/java/org/bigbluebutton/api/ParamsProcessorUtil.java b/bbb-common-web/src/main/java/org/bigbluebutton/api/ParamsProcessorUtil.java index e5349f2940..5f93d090cb 100755 --- a/bbb-common-web/src/main/java/org/bigbluebutton/api/ParamsProcessorUtil.java +++ b/bbb-common-web/src/main/java/org/bigbluebutton/api/ParamsProcessorUtil.java @@ -108,31 +108,34 @@ public class ParamsProcessorUtil { private Long maxPresentationFileUpload = 30000000L; // 30MB private Integer clientLogoutTimerInMinutes = 0; - private Integer meetingExpireIfNoUserJoinedInMinutes = 5; - private Integer meetingExpireWhenLastUserLeftInMinutes = 1; - private Integer userInactivityInspectTimerInMinutes = 120; - private Integer userInactivityThresholdInMinutes = 30; + private Integer meetingExpireIfNoUserJoinedInMinutes = 5; + private Integer meetingExpireWhenLastUserLeftInMinutes = 1; + private Integer userInactivityInspectTimerInMinutes = 120; + private Integer userInactivityThresholdInMinutes = 30; private Integer userActivitySignResponseDelayInMinutes = 5; private Boolean defaultAllowDuplicateExtUserid = true; - private Boolean defaultEndWhenNoModerator = false; - private Integer defaultEndWhenNoModeratorDelayInMinutes = 1; - private Integer defaultHtml5InstanceId = 1; + private Boolean defaultEndWhenNoModerator = false; + private Integer defaultEndWhenNoModeratorDelayInMinutes = 1; + private Integer defaultHtml5InstanceId = 1; - private String formatConfNum(String s) { - if (s.length() > 5) { - /* Reverse conference number. - * Put a whitespace every third char. - * Reverse it again to display it correctly. - * Trim leading whitespaces. - * */ - String confNumReversed = new StringBuilder(s).reverse().toString(); - String confNumSplit = confNumReversed.replaceAll("(.{3})", "$1 "); - String confNumL = new StringBuilder(confNumSplit).reverse().toString().trim(); - return confNumL; - } + private String bbbVersion = ""; + private Boolean allowRevealOfBBBVersion = false; - return s; - } + private String formatConfNum(String s) { + if (s.length() > 5) { + /* Reverse conference number. + * Put a whitespace every third char. + * Reverse it again to display it correctly. + * Trim leading whitespaces. + * */ + String confNumReversed = new StringBuilder(s).reverse().toString(); + String confNumSplit = confNumReversed.replaceAll("(.{3})", "$1 "); + String confNumL = new StringBuilder(confNumSplit).reverse().toString().trim(); + return confNumL; + } + + return s; + } private String substituteKeywords(String message, String dialNumber, String telVoice, String meetingName) { String welcomeMessage = message; @@ -659,6 +662,14 @@ public class ParamsProcessorUtil { } } + public String getBbbVersion() { + return bbbVersion; + } + + public Boolean getAllowRevealOfBBBVersion() { + return allowRevealOfBBBVersion; + } + public String processWelcomeMessage(String message, Boolean isBreakout) { String welcomeMessage = message; if (StringUtils.isEmpty(message)) { @@ -1174,8 +1185,16 @@ public class ParamsProcessorUtil { this.defaultEndWhenNoModerator = val; } - public void setEndWhenNoModeratorDelayInMinutes(Integer value) { - this.defaultEndWhenNoModeratorDelayInMinutes = value; - } + public void setEndWhenNoModeratorDelayInMinutes(Integer value) { + this.defaultEndWhenNoModeratorDelayInMinutes = value; + } + + public void setBbbVersion(String version) { + this.bbbVersion = this.allowRevealOfBBBVersion ? version : ""; + } + + public void setAllowRevealOfBBBVersion(Boolean allowVersion) { + this.allowRevealOfBBBVersion = allowVersion; + } } diff --git a/bbb-common-web/src/main/java/org/bigbluebutton/api/model/request/JoinMeeting.java b/bbb-common-web/src/main/java/org/bigbluebutton/api/model/request/JoinMeeting.java index 1390dbe0c0..c9273f9b7c 100755 --- a/bbb-common-web/src/main/java/org/bigbluebutton/api/model/request/JoinMeeting.java +++ b/bbb-common-web/src/main/java/org/bigbluebutton/api/model/request/JoinMeeting.java @@ -14,7 +14,8 @@ public class JoinMeeting extends RequestWithChecksum { PASSWORD("password"), GUEST("guest"), AUTH("auth"), - CREATE_TIME("createTime"); + CREATE_TIME("createTime"), + ROLE("role"); private final String value; @@ -49,6 +50,8 @@ public class JoinMeeting extends RequestWithChecksum { private String createTimeString; private Long createTime; + private String role; + public JoinMeeting(Checksum checksum) { super(checksum); } @@ -115,6 +118,14 @@ public class JoinMeeting extends RequestWithChecksum { this.createTime = createTime; } + public String getRole() { + return role; + } + + public void setRole(String role) { + this.role = role; + } + @Override public void populateFromParamsMap(Map params) { if(params.containsKey(Params.MEETING_ID.getValue())) { @@ -127,6 +138,7 @@ public class JoinMeeting extends RequestWithChecksum { if(params.containsKey(Params.GUEST.getValue())) setGuestString(params.get(Params.GUEST.getValue())[0]); if(params.containsKey(Params.AUTH.getValue())) setAuthString(params.get(Params.AUTH.getValue())[0]); if(params.containsKey(Params.CREATE_TIME.getValue())) setCreateTimeString(params.get(Params.CREATE_TIME.getValue())[0]); + if(params.containsKey(Params.ROLE.getValue())) setRole(params.get(Params.ROLE.getValue())[0]); } @Override diff --git a/bbb-common-web/src/main/java/org/bigbluebutton/api/util/ResponseBuilder.java b/bbb-common-web/src/main/java/org/bigbluebutton/api/util/ResponseBuilder.java index f25e4df954..ca5c1d6ba1 100755 --- a/bbb-common-web/src/main/java/org/bigbluebutton/api/util/ResponseBuilder.java +++ b/bbb-common-web/src/main/java/org/bigbluebutton/api/util/ResponseBuilder.java @@ -52,12 +52,13 @@ public class ResponseBuilder { return new Date(timestamp).toString(); } - public String buildMeetingVersion(String version, String returnCode) { + public String buildMeetingVersion(String apiVersion, String bbbVersion, String returnCode) { StringWriter xmlText = new StringWriter(); Map data = new HashMap(); data.put("returnCode", returnCode); - data.put("version", version); + data.put("apiVersion", apiVersion); + data.put("bbbVersion", bbbVersion); processData(getTemplate("api-version.ftlx"), data, xmlText); diff --git a/bigbluebutton-html5/.meteor/packages b/bigbluebutton-html5/.meteor/packages index 6205ce29a0..191153ece5 100644 --- a/bigbluebutton-html5/.meteor/packages +++ b/bigbluebutton-html5/.meteor/packages @@ -5,16 +5,16 @@ meteor-base@1.5.1 mobile-experience@1.1.0 -mongo@1.12.0 +mongo@1.13.0 reactive-var@1.0.11 -standard-minifier-css@1.7.3 -standard-minifier-js@2.6.1 +standard-minifier-css@1.7.4 +standard-minifier-js@2.7.1 es5-shim@4.8.0 -ecmascript@0.15.3 +ecmascript@0.16.0 shell-server@0.5.0 -static-html +static-html@1.3.2 react-meteor-data http@1.4.2 session@1.2.0 diff --git a/bigbluebutton-html5/.meteor/release b/bigbluebutton-html5/.meteor/release index 13010aa285..55995295e6 100644 --- a/bigbluebutton-html5/.meteor/release +++ b/bigbluebutton-html5/.meteor/release @@ -1 +1 @@ -METEOR@2.3.6 +METEOR@2.5 diff --git a/bigbluebutton-html5/.meteor/versions b/bigbluebutton-html5/.meteor/versions index 10334b0a2f..5d42d8bc1a 100644 --- a/bigbluebutton-html5/.meteor/versions +++ b/bigbluebutton-html5/.meteor/versions @@ -1,5 +1,5 @@ allow-deny@1.1.0 -autoupdate@1.7.0 +autoupdate@1.8.0 babel-compiler@7.7.0 babel-runtime@1.5.0 base64@1.0.12 @@ -8,20 +8,20 @@ blaze-tools@1.1.2 boilerplate-generator@1.7.1 caching-compiler@1.2.2 caching-html-compiler@1.2.1 -callback-hook@1.3.1 +callback-hook@1.4.0 cfs:reactive-list@0.0.9 check@1.3.1 ddp@1.4.0 ddp-client@2.5.0 ddp-common@1.4.0 -ddp-server@2.4.1 +ddp-server@2.5.0 deps@1.0.12 diff-sequence@1.1.1 -dynamic-import@0.7.1 -ecmascript@0.15.3 -ecmascript-runtime@0.7.0 -ecmascript-runtime-client@0.11.1 -ecmascript-runtime-server@0.10.1 +dynamic-import@0.7.2 +ecmascript@0.16.0 +ecmascript-runtime@0.8.0 +ecmascript-runtime-client@0.12.1 +ecmascript-runtime-server@0.11.0 ejson@1.1.1 es5-shim@4.8.0 fetch@0.1.1 @@ -34,21 +34,21 @@ id-map@1.1.1 inter-process-messaging@0.1.1 launch-screen@1.3.0 lmieulet:meteor-coverage@3.2.0 -logging@1.2.0 -meteor@1.9.3 +logging@1.3.1 +meteor@1.10.0 meteor-base@1.5.1 meteortesting:browser-tests@1.3.4 meteortesting:mocha@2.0.2 meteortesting:mocha-core@8.0.1 -minifier-css@1.5.4 -minifier-js@2.6.1 +minifier-css@1.6.0 +minifier-js@2.7.1 minimongo@1.7.0 mobile-experience@1.1.0 mobile-status-bar@1.1.0 -modern-browsers@0.1.5 -modules@0.16.0 +modern-browsers@0.1.7 +modules@0.17.0 modules-runtime@0.12.0 -mongo@1.12.0 +mongo@1.13.0 mongo-decimal@0.1.2 mongo-dev-server@1.1.0 mongo-id@1.0.8 @@ -57,7 +57,7 @@ npm-mongo@3.9.1 ordered-dict@1.1.0 promise@0.12.0 random@1.2.0 -react-fast-refresh@0.1.1 +react-fast-refresh@0.2.0 react-meteor-data@0.2.16 reactive-dict@1.3.0 reactive-var@1.0.11 @@ -69,13 +69,13 @@ session@1.2.0 shell-server@0.5.0 socket-stream-client@0.4.0 spacebars-compiler@1.3.0 -standard-minifier-css@1.7.3 -standard-minifier-js@2.6.1 +standard-minifier-css@1.7.4 +standard-minifier-js@2.7.1 static-html@1.3.2 templating-tools@1.2.1 tmeasday:check-npm-versions@0.3.2 tracker@1.2.0 underscore@1.0.10 url@1.3.2 -webapp@1.11.1 +webapp@1.13.0 webapp-hashing@1.1.0 diff --git a/bigbluebutton-html5/deploy_to_usr_share.sh b/bigbluebutton-html5/deploy_to_usr_share.sh index 4f90a1fbf6..af5f6bc4df 100755 --- a/bigbluebutton-html5/deploy_to_usr_share.sh +++ b/bigbluebutton-html5/deploy_to_usr_share.sh @@ -1,4 +1,4 @@ -#!/bin/sh -e +#!/bin/sh -ex # Please check bigbluebutton/bigbluebutton-html5/dev_local_deployment/README.md @@ -22,21 +22,18 @@ if [ -d "node_modules" ]; then rm -r node_modules/ fi meteor reset -meteor npm install --production - +meteor npm ci --production sudo chmod 777 /usr/share/meteor -METEOR_DISABLE_OPTIMISTIC_CACHING=1 meteor build $UPPER_DESTINATION_DIR --architecture os.linux.x86_64 --allow-superuser +METEOR_DISABLE_OPTIMISTIC_CACHING=1 meteor build $UPPER_DESTINATION_DIR --architecture os.linux.x86_64 --allow-superuser --directory sudo chown -R meteor:meteor "$UPPER_DESTINATION_DIR"/ echo 'stage3' -tar -xzf $UPPER_DESTINATION_DIR/bigbluebutton-html5.tar.gz -C $UPPER_DESTINATION_DIR - - cd "$DESTINATION_DIR"/programs/server/ || exit -sudo npm i --production +sudo npm i + echo "deployed to $DESTINATION_DIR/programs/server\n\n\n" echo "writing $DESTINATION_DIR/mongod_start_pre.sh" diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/presentation-options/component.jsx b/bigbluebutton-html5/imports/ui/components/actions-bar/presentation-options/component.jsx index b47a4730c7..717acb4d35 100755 --- a/bigbluebutton-html5/imports/ui/components/actions-bar/presentation-options/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/actions-bar/presentation-options/component.jsx @@ -50,6 +50,7 @@ const PresentationOptionsContainer = ({ return ( { }; const createMessage = (name, message) => ( -
-

{name}

-
+ + {name} + { mapContentText(message) .reduce((acc, text) => [...acc, (
), text], []) } -
-
+ + ); return pushAlertEnabled diff --git a/bigbluebutton-html5/imports/ui/components/chat/alert/styles.js b/bigbluebutton-html5/imports/ui/components/chat/alert/styles.js new file mode 100644 index 0000000000..0530edd8bc --- /dev/null +++ b/bigbluebutton-html5/imports/ui/components/chat/alert/styles.js @@ -0,0 +1,45 @@ +import styled from 'styled-components'; +import { colorGrayDark } from '/imports/ui/stylesheets/styled-components/palette'; +import { borderRadius } from '/imports/ui/stylesheets/styled-components/general'; +import { fontSizeSmall } from '/imports/ui/stylesheets/styled-components/typography'; + +const PushMessageContent = styled.div` + margin-top: 1.4rem; + margin-bottom: .4rem; + margin-left: .4rem; + margin-right: .4rem; + background-color: inherit; + width: 98%; +`; + +const UserNameMessage = styled.h3` + margin: 0; + font-size: 80%; + color: ${colorGrayDark}; + font-weight: bold; + background-color: inherit; + position: relative; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + line-height: 1em; + max-height: 1em; +`; + +const ContentMessage = styled.div` + margin-top: ${borderRadius}; + font-size: 80%; + background-color: inherit; + position: relative; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + line-height: ${fontSizeSmall}; + max-height: calc(${fontSizeSmall} * 10); +`; + +export default { + PushMessageContent, + UserNameMessage, + ContentMessage, +}; diff --git a/bigbluebutton-html5/imports/ui/components/chat/chat-dropdown/styles.scss b/bigbluebutton-html5/imports/ui/components/chat/chat-dropdown/styles.scss deleted file mode 100644 index 657d450de0..0000000000 --- a/bigbluebutton-html5/imports/ui/components/chat/chat-dropdown/styles.scss +++ /dev/null @@ -1,30 +0,0 @@ -.btn { - --icon-offset: -.4em; - --square-side-length: 1.56rem; - - z-index: 3; - - flex: 0 0; - margin-top: auto; - - cursor: pointer; - - span:first-child { - width: var(--square-side-length); - height: var(--square-side-length); - } - - - i { - color: var(--color-gray-dark) !important; - top: var(--icon-offset); - left: var(--icon-offset); - } - - &:hover, - &:focus { - > span:first-child { - background-color: transparent !important; - } - } -} diff --git a/bigbluebutton-html5/imports/ui/components/chat/component.jsx b/bigbluebutton-html5/imports/ui/components/chat/component.jsx index 4391bab25a..a75849ad8c 100755 --- a/bigbluebutton-html5/imports/ui/components/chat/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/chat/component.jsx @@ -6,13 +6,14 @@ import Button from '/imports/ui/components/button/component'; import withShortcutHelper from '/imports/ui/components/shortcut-help/service'; import { Meteor } from 'meteor/meteor'; import ChatLogger from '/imports/ui/components/chat/chat-logger/ChatLogger'; -import { styles } from './styles.scss'; +import Styled from './styles'; import MessageFormContainer from './message-form/container'; import TimeWindowList from './time-window-list/container'; import ChatDropdownContainer from './chat-dropdown/container'; import { PANELS, ACTIONS } from '../layout/enums'; import { UserSentMessageCollection } from './service'; import Auth from '/imports/ui/services/auth'; +import browserInfo from '/imports/utils/browserInfo'; const CHAT_CONFIG = Meteor.settings.public.chat; const PUBLIC_CHAT_ID = CHAT_CONFIG.public_id; @@ -55,21 +56,19 @@ const Chat = (props) => { } = props; const userSentMessage = UserSentMessageCollection.findOne({ userId: Auth.userID, sent: true }); + const { isChrome } = browserInfo; const HIDE_CHAT_AK = shortcuts.hideprivatechat; const CLOSE_CHAT_AK = shortcuts.closeprivatechat; ChatLogger.debug('ChatComponent::render', props); return ( -
-
-
-
+ { chatID !== PUBLIC_CHAT_ID ? ( @@ -127,7 +125,7 @@ const Chat = (props) => { /> ) } -
+ { locked={isChatLocked} partnerIsLoggedOut={partnerIsLoggedOut} /> -
+ ); }; diff --git a/bigbluebutton-html5/imports/ui/components/chat/message-form/component.jsx b/bigbluebutton-html5/imports/ui/components/chat/message-form/component.jsx index 419bb6a02c..b39f580306 100755 --- a/bigbluebutton-html5/imports/ui/components/chat/message-form/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/chat/message-form/component.jsx @@ -1,13 +1,10 @@ import React, { PureComponent } from 'react'; import { defineMessages, injectIntl } from 'react-intl'; -import cx from 'classnames'; -import TextareaAutosize from 'react-autosize-textarea'; import deviceInfo from '/imports/utils/deviceInfo'; import PropTypes from 'prop-types'; import _ from 'lodash'; import TypingIndicatorContainer from './typing-indicator/container'; -import { styles } from './styles.scss'; -import Button from '../../button/component'; +import Styled from './styles'; const propTypes = { intl: PropTypes.object.isRequired, @@ -16,7 +13,6 @@ const propTypes = { minMessageLength: PropTypes.number.isRequired, maxMessageLength: PropTypes.number.isRequired, chatTitle: PropTypes.string.isRequired, - className: PropTypes.string, chatAreaId: PropTypes.string.isRequired, handleSendMessage: PropTypes.func.isRequired, UnsentMessagesCollection: PropTypes.objectOf(Object).isRequired, @@ -27,10 +23,6 @@ const propTypes = { startUserTyping: PropTypes.func.isRequired, }; -const defaultProps = { - className: '', -}; - const messages = defineMessages({ submitLabel: { id: 'app.chat.submitLabel', @@ -261,7 +253,6 @@ class MessageForm extends PureComponent { chatTitle, title, disabled, - className, idChatOpen, partnerIsLoggedOut, } = this.props; @@ -269,14 +260,12 @@ class MessageForm extends PureComponent { const { hasErrors, error, message } = this.state; return CHAT_ENABLED ? ( -
{ this.form = ref; }} - className={cx(className, styles.form)} onSubmit={this.handleSubmit} > -
- + { this.textarea = ref; return this.textarea; }} placeholder={intl.formatMessage(messages.inputPlaceholder, { 0: title })} @@ -291,10 +280,9 @@ class MessageForm extends PureComponent { onKeyDown={this.handleMessageKeyDown} async /> -
+ - + ) : null; } } MessageForm.propTypes = propTypes; -MessageForm.defaultProps = defaultProps; export default injectIntl(MessageForm); diff --git a/bigbluebutton-html5/imports/ui/components/chat/message-form/styles.js b/bigbluebutton-html5/imports/ui/components/chat/message-form/styles.js new file mode 100644 index 0000000000..9bba15e9f7 --- /dev/null +++ b/bigbluebutton-html5/imports/ui/components/chat/message-form/styles.js @@ -0,0 +1,92 @@ +import styled from 'styled-components'; +import { + colorBlueLight, + colorText, + colorGrayLighter, + colorPrimary, +} from '/imports/ui/stylesheets/styled-components/palette'; +import { + smPaddingX, + smPaddingY, + borderRadius, + borderSize, +} from '/imports/ui/stylesheets/styled-components/general'; +import { fontSizeBase } from '/imports/ui/stylesheets/styled-components/typography'; +import TextareaAutosize from 'react-autosize-textarea'; +import Button from '/imports/ui/components/button/component'; + +const Form = styled.form` + flex-grow: 0; + flex-shrink: 0; + align-self: flex-end; + width: 100%; + position: relative; + margin-bottom: calc(-1 * ${smPaddingX}); + margin-top: .2rem; +`; + +const Wrapper = styled.div` + display: flex; + flex-direction: row; +`; + +const Input = styled(TextareaAutosize)` + flex: 1; + background: #fff; + background-clip: padding-box; + margin: 0; + color: ${colorText}; + -webkit-appearance: none; + padding: calc(${smPaddingY} * 2.5) calc(${smPaddingX} * 1.25); + resize: none; + transition: none; + border-radius: ${borderRadius}; + font-size: ${fontSizeBase}; + line-height: 1; + min-height: 2.5rem; + max-height: 10rem; + border: 1px solid ${colorGrayLighter}; + box-shadow: 0 0 0 1px ${colorGrayLighter}; + + &:disabled, + &[disabled] { + cursor: not-allowed; + opacity: .75; + background-color: rgba(167,179,189,0.25); + } + + &:focus { + border-radius: ${borderSize}; + box-shadow: 0 0 0 ${borderSize} ${colorBlueLight}, inset 0 0 0 1px ${colorPrimary}; + } + + &:hover, + &:active, + &:focus { + outline: transparent; + outline-style: dotted; + outline-width: ${borderSize}; + } +`; + +const SendButton = styled(Button)` + margin:0 0 0 ${smPaddingX}; + align-self: center; + font-size: 0.9rem; + + [dir="rtl"] & { + margin: 0 ${smPaddingX} 0 0; + -webkit-transform: scale(-1, 1); + -moz-transform: scale(-1, 1); + -ms-transform: scale(-1, 1); + -o-transform: scale(-1, 1); + transform: scale(-1, 1); + } +`; + +export default { + Form, + Wrapper, + Input, + SendButton, +}; diff --git a/bigbluebutton-html5/imports/ui/components/chat/message-form/styles.scss b/bigbluebutton-html5/imports/ui/components/chat/message-form/styles.scss deleted file mode 100755 index a73902da12..0000000000 --- a/bigbluebutton-html5/imports/ui/components/chat/message-form/styles.scss +++ /dev/null @@ -1,182 +0,0 @@ -@import "/imports/ui/stylesheets/mixins/focus"; -@import "/imports/ui/stylesheets/mixins/_indicators"; -@import "/imports/ui/stylesheets/variables/placeholders"; - -:root { - --max-chat-input-msg-height: .93rem; -} - -.form { - flex-grow: 0; - flex-shrink: 0; - align-self: flex-end; - width: 100%; - position: relative; - margin-bottom: calc(-1 * var(--sm-padding-x)); - margin-top: .2rem; -} - -.wrapper { - display: flex; - flex-direction: row; -} - -.actions { - display: flex; - align-items: center; - justify-content: center; - flex-grow: 0; - flex-shrink: 0; - border: var(--border-size) solid var(--color-gray-lighter); - background-color: #fff; - border-radius: var(--border-radius) 0 0 var(--border-radius); - color: var(--color-gray-light); - padding: var(--sm-padding-y) var(--sm-padding-x); - cursor: pointer; - - :global(.animationsEnabled) & { - transition: all .3s; - } - - --bg-faded: rgba(167,179,189,0.25); - - &:hover, - &:focus { - background-color: var(--bg-faded); - } - - &:disabled, - &[disabled] { - cursor: not-allowed; - opacity: .75; - background-color: var(--bg-faded); - } -} - -.input { - @include inputFocus(var(--color-blue-light)); - - flex: 1; - background: #fff; - background-clip: padding-box; - margin: 0; - color: var(--color-text); - -webkit-appearance: none; - padding: calc(var(--sm-padding-y) * 2.5) calc(var(--sm-padding-x) * 1.25); - resize: none; - transition: none; - border-radius: var(--border-radius); - font-size: var(--font-size-base); - line-height: 1; - min-height: 2.5rem; - max-height: 10rem; - border: 1px solid var(--color-gray-lighter); - box-shadow: 0 0 0 1px var(--color-gray-lighter); - - &:disabled, - &[disabled] { - cursor: not-allowed; - opacity: .75; - background-color: rgba(167,179,189,0.25); - } - - &:hover, - &:active, - &:focus { - @extend %highContrastOutline; - } -} - -.sendButton { - margin:0 0 0 var(--sm-padding-x); - align-self: center; - font-size: 0.9rem; - - [dir="rtl"] & { - margin: 0 var(--sm-padding-x) 0 0; - -webkit-transform: scale(-1, 1); - -moz-transform: scale(-1, 1); - -ms-transform: scale(-1, 1); - -o-transform: scale(-1, 1); - transform: scale(-1, 1); - } -} - -.error, -.info { - font-size: calc(var(--font-size-base) * .75); - color: var(--color-gray-dark); - text-align: left; - padding: var(--border-size) 0; - position: relative; -} - -.error, -.info, -.spacer { - height: var(--max-chat-input-msg-height); - max-height: var(--max-chat-input-msg-height); -} - -.coupleTyper, -.singleTyper { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - font-weight: bold; - font-size: var(--font-size-smaller); -} - -.singleTyper { - max-width: 70%; -} - -.coupleTyper { - max-width: 25%; -} - -.typingIndicator { - display: flex; - flex-direction: row; - - > span { - display: block; - margin-right: 0.05rem; - margin-left: 0.05rem; - line-height: var(--font-size-md); - } - - text-align: left; - [dir="rtl"] & { - text-align: right; - } -} - -.error { - color: var(--color-danger); -} - -.connectingAnimation { - margin: auto; - display: inline-block; - width: 1.5em; - - &:after { - overflow: hidden; - display: inline-block; - vertical-align: bottom; - content: "\2026"; /* ascii code for the ellipsis character */ - width: 0; - margin-left: 0.25em; - - :global(.animationsEnabled) & { - animation: ellipsis steps(4, end) 900ms infinite; - } - } -} - -@keyframes ellipsis { - to { - width: 1.5em; - } -} diff --git a/bigbluebutton-html5/imports/ui/components/chat/message-form/typing-indicator/component.jsx b/bigbluebutton-html5/imports/ui/components/chat/message-form/typing-indicator/component.jsx index 08024cbaac..b96a6cfef2 100644 --- a/bigbluebutton-html5/imports/ui/components/chat/message-form/typing-indicator/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/chat/message-form/typing-indicator/component.jsx @@ -3,8 +3,7 @@ import { defineMessages, injectIntl, FormattedMessage, } from 'react-intl'; import PropTypes from 'prop-types'; -import cx from 'classnames'; -import { styles } from '../styles.scss'; +import Styled from './styles'; const propTypes = { intl: PropTypes.object.isRequired, @@ -46,10 +45,10 @@ class TypingIndicator extends PureComponent { id="app.chat.one.typing" description="label used when one user is typing" values={{ - 0: + 0: {`${name}`}   - , + , }} /> ); @@ -63,15 +62,15 @@ class TypingIndicator extends PureComponent { id="app.chat.two.typing" description="label used when two users are typing" values={{ - 0: + 0: {`${name}`}   - , - 1: + , + 1:   {`${name2}`}   - , + , }} /> ); @@ -96,15 +95,14 @@ class TypingIndicator extends PureComponent { const typingElement = indicatorEnabled ? this.renderTypingElement() : null; - const style = {}; - style[styles.error] = !!error; - style[styles.info] = !error; - style[styles.spacer] = !!typingElement; - return ( -
- {error || typingElement} -
+ + {error || typingElement} + ); } } diff --git a/bigbluebutton-html5/imports/ui/components/chat/message-form/typing-indicator/styles.js b/bigbluebutton-html5/imports/ui/components/chat/message-form/typing-indicator/styles.js new file mode 100644 index 0000000000..9eab00f431 --- /dev/null +++ b/bigbluebutton-html5/imports/ui/components/chat/message-form/typing-indicator/styles.js @@ -0,0 +1,74 @@ +import styled from 'styled-components'; +import { colorDanger, colorGrayDark } from '/imports/ui/stylesheets/styled-components/palette'; +import { borderSize } from '/imports/ui/stylesheets/styled-components/general'; +import { fontSizeSmaller, fontSizeMD, fontSizeBase } from '/imports/ui/stylesheets/styled-components/typography'; + +const SingleTyper = styled.span` + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-weight: bold; + font-size: ${fontSizeSmaller}; + max-width: 70%; +`; + +const CoupleTyper = styled.span` + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-weight: bold; + font-size: ${fontSizeSmaller}; + max-width: 25%; +`; + +const TypingIndicator = styled.span` + display: flex; + flex-direction: row; + + > span { + display: block; + margin-right: 0.05rem; + margin-left: 0.05rem; + line-height: ${fontSizeMD}; + } + + text-align: left; + [dir="rtl"] & { + text-align: right; + } +`; + +const TypingIndicatorWrapper = styled.div` + ${({ error }) => error && ` + color: ${colorDanger}; + font-size: calc(${fontSizeBase} * .75); + color: ${colorGrayDark}; + text-align: left; + padding: ${borderSize} 0; + position: relative; + height: .93rem; + max-height: .93rem; + `} + + ${({ info }) => info && ` + font-size: calc(${fontSizeBase} * .75); + color: ${colorGrayDark}; + text-align: left; + padding: ${borderSize} 0; + position: relative; + height: .93rem; + max-height: .93rem; + `} + + ${({ spacer }) => spacer && ` + height: .93rem; + max-height: .93rem; + `} +`; + +export default { + SingleTyper, + CoupleTyper, + TypingIndicator, + TypingIndicatorWrapper, +}; diff --git a/bigbluebutton-html5/imports/ui/components/chat/styles.js b/bigbluebutton-html5/imports/ui/components/chat/styles.js new file mode 100644 index 0000000000..7390f0c1da --- /dev/null +++ b/bigbluebutton-html5/imports/ui/components/chat/styles.js @@ -0,0 +1,92 @@ +import styled from 'styled-components'; +import { + colorWhite, + colorGrayDark, +} from '/imports/ui/stylesheets/styled-components/palette'; +import { smallOnly } from '/imports/ui/stylesheets/styled-components/breakpoints'; +import Button from '/imports/ui/components/button/component'; +import { + mdPaddingX, + mdPaddingY, + pollHeaderOffset, + borderSizeLarge, + borderSize, +} from '/imports/ui/stylesheets/styled-components/general'; +import { DivElipsis } from '/imports/ui/stylesheets/styled-components/placeholders'; + +const Chat = styled.div` + background-color: ${colorWhite}; + padding: ${mdPaddingX} ${mdPaddingY} ${mdPaddingX} ${mdPaddingX}; + + display: flex; + flex-grow: 1; + flex-direction: column; + justify-content: space-around; + overflow: hidden; + height: 100%; + + ${({ isChrome }) => isChrome && ` + transform: translateZ(0); + `} + + @media ${smallOnly} { + transform: none !important; + } +`; + +const Header = styled.header` + position: relative; + top: ${pollHeaderOffset}; + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; +`; + +const Title = styled(DivElipsis)` + flex: 1; + + & > button, button:hover { + max-width: 98%; + } +`; + +const HideChatButton = styled(Button)` + position: relative; + background-color: ${colorWhite}; + display: block; + margin: ${borderSizeLarge}; + margin-bottom: ${borderSize}; + padding-left: 0; + padding-right: inherit; + z-index: 3; + + [dir="rtl"] & { + padding-left: inherit; + padding-right: 0; + } + + & > i { + color: ${colorGrayDark}; + font-size: smaller; + + [dir="rtl"] & { + -webkit-transform: scale(-1, 1); + -moz-transform: scale(-1, 1); + -ms-transform: scale(-1, 1); + -o-transform: scale(-1, 1); + transform: scale(-1, 1); + } + } + + &:hover { + background-color: ${colorWhite}; + } +`; + +export default { + Chat, + Header, + Title, + HideChatButton, +}; diff --git a/bigbluebutton-html5/imports/ui/components/chat/styles.scss b/bigbluebutton-html5/imports/ui/components/chat/styles.scss deleted file mode 100755 index 8ba6e12ac1..0000000000 --- a/bigbluebutton-html5/imports/ui/components/chat/styles.scss +++ /dev/null @@ -1,124 +0,0 @@ -@import "/imports/ui/stylesheets/mixins/focus"; -@import "/imports/ui/stylesheets/variables/breakpoints"; -@import "/imports/ui/stylesheets/variables/placeholders"; - -:root { - --toast-content-width: 98%; - --toast-font-size: 80%; - --toast-content-margin-sm: .4rem; - --toast-content-margin-md: 1.4rem; -} - -@mixin lineClamp($lineHeight: 1em, $lineCount: 1) { - position: relative; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - line-height: $lineHeight; - max-height: calc(#{"$lineHeight * $lineCount"}); -} - -.chat { - background-color: var(--color-white); - padding: - var(--md-padding-x) - var(--md-padding-y) - var(--md-padding-x) - var(--md-padding-x); - - display: flex; - flex-grow: 1; - flex-direction: column; - justify-content: space-around; - overflow: hidden; - height: 100%; - - :global(.browser-chrome) & { - transform: translateZ(0); - } - - @include mq($small-only) { - transform: none !important; - } -} - -.header { - position: relative; - top: var(--poll-header-offset); - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; -} - -.title { - @extend %text-elipsis; - flex: 1; - - & > button, button:hover { - max-width: var(--toast-content-width); - } -} - -.hideBtn { - position: relative; - background-color: var(--color-white); - display: block; - margin: var(--border-size-large); - margin-bottom: var(--border-size); - padding-left: 0; - padding-right: inherit; - z-index: 3; - - [dir="rtl"] & { - padding-left: inherit; - padding-right: 0; - } - - > i { - color: var(--color-gray-dark); - font-size: smaller; - - [dir="rtl"] & { - -webkit-transform: scale(-1, 1); - -moz-transform: scale(-1, 1); - -ms-transform: scale(-1, 1); - -o-transform: scale(-1, 1); - transform: scale(-1, 1); - } - } - - &:hover { - background-color: var(--color-white); - } -} - -.link { - text-decoration: none; - background-color: inherit; -} - -.pushMessageContent { - margin-top: var(--toast-content-margin-md); - margin-bottom: var(--toast-content-margin-sm); - margin-left: var(--toast-content-margin-sm); - margin-right: var(--toast-content-margin-sm); - background-color: inherit; - width: var(--toast-content-width); -} - -.userNameMessage { - margin: 0; - font-size: var(--toast-font-size); - color: var(--color-gray-dark); - font-weight: bold; - background-color: inherit; - @include lineClamp(1em, 1); -} - -.contentMessage { - margin-top: var(--border-radius); - font-size: var(--toast-font-size); - background-color: inherit; - @include lineClamp(var(--font-size-small), 10); -} diff --git a/bigbluebutton-html5/imports/ui/components/chat/time-window-list/component.jsx b/bigbluebutton-html5/imports/ui/components/chat/time-window-list/component.jsx index 1cbdca9f86..752d0579c2 100644 --- a/bigbluebutton-html5/imports/ui/components/chat/time-window-list/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/chat/time-window-list/component.jsx @@ -3,9 +3,8 @@ import { findDOMNode } from 'react-dom'; import PropTypes from 'prop-types'; import { defineMessages, injectIntl } from 'react-intl'; import _ from 'lodash'; -import Button from '/imports/ui/components/button/component'; -import { List, AutoSizer,CellMeasurer, CellMeasurerCache } from 'react-virtualized'; -import { styles } from './styles'; +import { AutoSizer,CellMeasurer, CellMeasurerCache } from 'react-virtualized'; +import Styled from './styles'; import ChatLogger from '/imports/ui/components/chat/chat-logger/ChatLogger'; import TimeWindowChatItem from './time-window-chat-item/container'; @@ -236,9 +235,8 @@ class TimeWindowList extends PureComponent { if (count && userScrolledBack) { return ( - + ); }); @@ -111,14 +103,6 @@ class TalkingIndicator extends PureComponent { const nobodyTalking = Service.nobodyTalking(talkers); - const style = { - [styles.talker]: true, - [styles.spoke]: nobodyTalking, - // [styles.muted]: false, - [styles.mobileHide]: sidebarNavigationIsOpen - && sidebarContentIsOpen, - }; - const { moreThanMaxIndicatorsTalking, moreThanMaxIndicatorsWereTalking } = intlMessages; const ariaLabel = intl.formatMessage(nobodyTalking @@ -127,9 +111,12 @@ class TalkingIndicator extends PureComponent { }); return ( -