diff --git a/bigbluebutton-html5/imports/api/meetings/server/eventHandlers.js b/bigbluebutton-html5/imports/api/meetings/server/eventHandlers.js index e0fbf321e6238fae0561b83a2556e5d4e06c2109..5e82844e77a41e5146ae54c67a4e900658fac6e0 100644 --- a/bigbluebutton-html5/imports/api/meetings/server/eventHandlers.js +++ b/bigbluebutton-html5/imports/api/meetings/server/eventHandlers.js @@ -7,6 +7,7 @@ import handleMeetingLocksChange from './handlers/meetingLockChange'; import handleUserLockChange from './handlers/userLockChange'; import handleRecordingStatusChange from './handlers/recordingStatusChange'; import handleRecordingTimerChange from './handlers/recordingTimerChange'; +import handleTimeRemainingUpdate from './handlers/timeRemainingUpdate'; import handleChangeWebcamOnlyModerator from './handlers/webcamOnlyModerator'; RedisPubSub.on('MeetingCreatedEvtMsg', handleMeetingCreation); @@ -18,3 +19,4 @@ RedisPubSub.on('UserLockedInMeetingEvtMsg', handleUserLockChange); RedisPubSub.on('RecordingStatusChangedEvtMsg', handleRecordingStatusChange); RedisPubSub.on('UpdateRecordingTimerEvtMsg', handleRecordingTimerChange); RedisPubSub.on('WebcamsOnlyForModeratorChangedEvtMsg', handleChangeWebcamOnlyModerator); +RedisPubSub.on('MeetingTimeRemainingUpdateEvtMsg', handleTimeRemainingUpdate); diff --git a/bigbluebutton-html5/imports/api/meetings/server/handlers/meetingCreation.js b/bigbluebutton-html5/imports/api/meetings/server/handlers/meetingCreation.js index c0fe2430c4ddfe5caf55f01166ac827538666e75..024bf29a26ba8d2e1925c8f6d7d12342687a97d6 100644 --- a/bigbluebutton-html5/imports/api/meetings/server/handlers/meetingCreation.js +++ b/bigbluebutton-html5/imports/api/meetings/server/handlers/meetingCreation.js @@ -3,6 +3,8 @@ import addMeeting from '../modifiers/addMeeting'; export default function handleMeetingCreation({ body }) { const meeting = body.props; + const durationInSecods = (meeting.durationProps.duration * 60); + meeting.durationProps.timeRemaining = durationInSecods; check(meeting, Object); return addMeeting(meeting); diff --git a/bigbluebutton-html5/imports/api/meetings/server/handlers/timeRemainingUpdate.js b/bigbluebutton-html5/imports/api/meetings/server/handlers/timeRemainingUpdate.js new file mode 100644 index 0000000000000000000000000000000000000000..619b52d74a33756cc1580c593ea3233f841f98f0 --- /dev/null +++ b/bigbluebutton-html5/imports/api/meetings/server/handlers/timeRemainingUpdate.js @@ -0,0 +1,30 @@ +import { check } from 'meteor/check'; +import Meetings from '/imports/api/meetings'; +import Logger from '/imports/startup/server/logger'; + +export default function handleTimeRemainingUpdate({ body }, meetingId) { + check(meetingId, String); + + check(body, { + timeLeftInSec: Number, + }); + const { timeLeftInSec } = body; + + const selector = { + meetingId, + }; + + const modifier = { + $set: { + 'durationProps.timeRemaining': timeLeftInSec, + }, + }; + + const cb = (err) => { + if (err) { + Logger.error(`Changing recording time: ${err}`); + } + }; + + return Meetings.upsert(selector, modifier, cb); +} diff --git a/bigbluebutton-html5/imports/api/meetings/server/modifiers/addMeeting.js b/bigbluebutton-html5/imports/api/meetings/server/modifiers/addMeeting.js index f8011fd0d32225429338b6252eefd78af4307bc8..ba0bf11748d28f3c41431aec6bfbc7313184bf5d 100644 --- a/bigbluebutton-html5/imports/api/meetings/server/modifiers/addMeeting.js +++ b/bigbluebutton-html5/imports/api/meetings/server/modifiers/addMeeting.js @@ -36,6 +36,7 @@ export default function addMeeting(meeting) { userInactivityInspectTimerInMinutes: Number, userInactivityThresholdInMinutes: Number, userActivitySignResponseDelayInMinutes: Number, + timeRemaining: Number, }, welcomeProp: { welcomeMsg: String, diff --git a/bigbluebutton-html5/imports/ui/components/breakout-room/breakout-remaining-time/container.jsx b/bigbluebutton-html5/imports/ui/components/breakout-room/breakout-remaining-time/container.jsx index 422ce26f2ae11fdfd3b3c20e94d9db511b7a0764..bcbb2cacc88da92a881a97b025e9486032de3fec 100644 --- a/bigbluebutton-html5/imports/ui/components/breakout-room/breakout-remaining-time/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/breakout-room/breakout-remaining-time/container.jsx @@ -77,7 +77,9 @@ const startCounter = (sec, set, get, interval) => { }; -export default injectIntl(withTracker(({ breakoutRoom, intl, messageDuration }) => { +export default injectIntl(withTracker(({ + breakoutRoom, intl, messageDuration, timeEndedMessage, +}) => { const data = {}; if (breakoutRoom) { const roomRemainingTime = breakoutRoom.timeRemaining; @@ -94,13 +96,13 @@ export default injectIntl(withTracker(({ breakoutRoom, intl, messageDuration }) clearInterval(timeRemainingInterval); } - if (timeRemaining) { + if (timeRemaining >= 0) { if (timeRemaining > 0) { const time = getTimeRemaining(); data.message = intl.formatMessage(messageDuration, { 0: humanizeSeconds(time) }); } else { clearInterval(timeRemainingInterval); - data.message = intl.formatMessage(intlMessages.breakoutWillClose); + data.message = intl.formatMessage(timeEndedMessage || intlMessages.breakoutWillClose); } } else if (breakoutRoom) { data.message = intl.formatMessage(intlMessages.calculatingBreakoutTimeRemaining); diff --git a/bigbluebutton-html5/imports/ui/components/notifications-bar/component.jsx b/bigbluebutton-html5/imports/ui/components/notifications-bar/component.jsx index 3ed8f4afef2ecc69440aea6a2234fe8506d739a1..c833284b0ab6def4904582b79f6b6abe68cd84f1 100644 --- a/bigbluebutton-html5/imports/ui/components/notifications-bar/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/notifications-bar/component.jsx @@ -9,7 +9,6 @@ const COLORS = [ ]; const propTypes = { - children: PropTypes.string.isRequired, color: PropTypes.oneOf(COLORS), }; @@ -18,14 +17,14 @@ const defaultProps = { }; const NotificationsBar = (props) => { - const { color } = props; + const { color, children } = props; return ( <div role="alert" className={cx(styles.notificationsBar, styles[color])} > - {props.children} + {children} </div> ); }; diff --git a/bigbluebutton-html5/imports/ui/components/notifications-bar/container.jsx b/bigbluebutton-html5/imports/ui/components/notifications-bar/container.jsx index 063e720d58965837a24f241a2d4fbcf54dc65e12..b47463231debaace78d196f8e87f6cb597d4ec8f 100644 --- a/bigbluebutton-html5/imports/ui/components/notifications-bar/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/notifications-bar/container.jsx @@ -4,8 +4,10 @@ import React from 'react'; import { defineMessages, injectIntl } from 'react-intl'; import _ from 'lodash'; import Auth from '/imports/ui/services/auth'; +import Meetings from '/imports/api/meetings'; import humanizeSeconds from '/imports/utils/humanizeSeconds'; import NavBarService from '../nav-bar/service'; +import BreakoutRemainingTime from '/imports/ui/components/breakout-room/breakout-remaining-time/container'; import NotificationsBar from './component'; @@ -43,6 +45,14 @@ const intlMessages = defineMessages({ id: 'app.calculatingBreakoutTimeRemaining', description: 'Message that tells that the remaining time is being calculated', }, + meetingTimeRemaining: { + id: 'app.meeting.meetingTimeRemaining', + description: 'Message that tells how much time is remaining for the meeting', + }, + meetingWillClose: { + id: 'app.meeting.meetingTimeHasEnded', + description: 'Message that tells time has ended and meeting will close', + }, }); const NotificationsBarContainer = (props) => { @@ -60,22 +70,14 @@ const NotificationsBarContainer = (props) => { }; let retrySeconds = 0; -let timeRemaining = 0; const retrySecondsDep = new Tracker.Dependency(); -const timeRemainingDep = new Tracker.Dependency(); let retryInterval = null; -let timeRemainingInterval = null; const getRetrySeconds = () => { retrySecondsDep.depend(); return retrySeconds; }; -const getTimeRemaining = () => { - timeRemainingDep.depend(); - return timeRemaining; -}; - const setRetrySeconds = (sec = 0) => { if (sec !== retrySeconds) { retrySeconds = sec; @@ -83,13 +85,6 @@ const setRetrySeconds = (sec = 0) => { } }; -const setTimeRemaining = (sec = 0) => { - if (sec !== timeRemaining) { - timeRemaining = sec; - timeRemainingDep.changed(); - } -}; - const startCounter = (sec, set, get, interval) => { clearInterval(interval); set(sec); @@ -137,37 +132,36 @@ export default injectIntl(withTracker(({ intl }) => { const currentBreakout = breakouts.find(b => b.breakoutId === meetingId); if (currentBreakout) { - const roomRemainingTime = currentBreakout.timeRemaining; - - if (!timeRemainingInterval && roomRemainingTime) { - timeRemainingInterval = startCounter( - roomRemainingTime, - setTimeRemaining, - getTimeRemaining, - timeRemainingInterval, - ); - } - } else if (timeRemainingInterval) { - clearInterval(timeRemainingInterval); + data.message = ( + <BreakoutRemainingTime + breakoutRoom={currentBreakout} + messageDuration={intlMessages.breakoutTimeRemaining} + timeEndedMessage={intlMessages.breakoutWillClose} + /> + ); } + } - timeRemaining = getTimeRemaining(); - if (timeRemaining) { - if (timeRemaining > 0) { - data.message = intl.formatMessage( - intlMessages.breakoutTimeRemaining, - { 0: humanizeSeconds(timeRemaining) }, - ); - } else { - clearInterval(timeRemainingInterval); - data.message = intl.formatMessage(intlMessages.breakoutWillClose); - } - } else if (currentBreakout) { - data.message = intl.formatMessage(intlMessages.calculatingBreakoutTimeRemaining); + const Meeting = Meetings.findOne({ meetingId: Auth.meetingID }); + + if (Meeting) { + const { timeRemaining } = Meeting.durationProps; + const { isBreakout } = Meeting.meetingProp; + const underThirtyMin = timeRemaining && timeRemaining <= (30 * 60); + + if (underThirtyMin && !isBreakout) { + data.message = ( + <BreakoutRemainingTime + breakoutRoom={Meeting.durationProps} + messageDuration={intlMessages.meetingTimeRemaining} + timeEndedMessage={intlMessages.meetingWillClose} + /> + ); } } + data.color = 'primary'; return data; })(NotificationsBarContainer)); diff --git a/bigbluebutton-html5/private/locales/en.json b/bigbluebutton-html5/private/locales/en.json index 93c91b147b31556fe037d69f046b127176f4c759..c5237c604c4e1e2e720eb4711acf51512d699519 100755 --- a/bigbluebutton-html5/private/locales/en.json +++ b/bigbluebutton-html5/private/locales/en.json @@ -59,6 +59,8 @@ "app.media.screenshare.end": "Screenshare has ended", "app.media.screenshare.safariNotSupported": "Screenshare is currently not supported by Safari. Please, use Firefox or Google Chrome.", "app.meeting.ended": "This session has ended", + "app.meeting.meetingTimeRemaining": "Meeting time remaining: {0}", + "app.meeting.meetingTimeHasEnded": "Time ended. Meeting will close soon", "app.meeting.endedMessage": "You will be forwarded back to the home screen", "app.presentation.presentationToolbar.prevSlideLabel": "Previous slide", "app.presentation.presentationToolbar.prevSlideDesc": "Change the presentation to the previous slide",