diff --git a/bigbluebutton-html5/imports/ui/components/audio/audio-controls/container.jsx b/bigbluebutton-html5/imports/ui/components/audio/audio-controls/container.jsx index c59170c9ce6f0289bafe6057bd13a695c46eced6..f179c495848c20fd473f1ef7778210c74b1d7007 100755 --- a/bigbluebutton-html5/imports/ui/components/audio/audio-controls/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/audio/audio-controls/container.jsx @@ -55,8 +55,11 @@ const { } = Service; export default lockContextContainer(withModalMounter(withTracker(({ mountModal, userLocks }) => { - if (Service.isReturningFromBreakoutAudioTransfer()) { - Service.setReturningFromBreakoutAudioTransfer(false); + const { status } = Service.getBreakoutAudioTransferStatus(); + + if (status === AudioManager.BREAKOUT_AUDIO_TRANSFER_STATES.RETURNING) { + Service.setBreakoutAudioTransferStatus(null, + AudioManager.BREAKOUT_AUDIO_TRANSFER_STATES.DISCONNECTED); Service.recoverMicState(); } diff --git a/bigbluebutton-html5/imports/ui/components/audio/service.js b/bigbluebutton-html5/imports/ui/components/audio/service.js index 6d5583150453edc8955a86beb4d29c049f1d8ad6..5bc9b9a97768037c2e53e6afd660de20a4b9cd45 100755 --- a/bigbluebutton-html5/imports/ui/components/audio/service.js +++ b/bigbluebutton-html5/imports/ui/components/audio/service.js @@ -125,10 +125,10 @@ export default { updateAudioConstraints: constraints => AudioManager.updateAudioConstraints(constraints), recoverMicState, - setReturningFromBreakoutAudioTransfer: (value) => { - AudioManager.returningFromBreakoutAudioTransfer = value; - }, - isReturningFromBreakoutAudioTransfer: - () => AudioManager.returningFromBreakoutAudioTransfer, isReconnecting: () => AudioManager.isReconnecting, + setBreakoutAudioTransferStatus: + (breakoutId, status) => AudioManager + .setBreakoutAudioTransferStatus(breakoutId, status), + getBreakoutAudioTransferStatus: () => AudioManager + .getBreakoutAudioTransferStatus(), }; diff --git a/bigbluebutton-html5/imports/ui/components/breakout-room/component.jsx b/bigbluebutton-html5/imports/ui/components/breakout-room/component.jsx index bdb8898a575b466a0720b4496bbde62780ecb8b3..c77e05d39832b6a2e5db63f1d11fe73cef3879f0 100644 --- a/bigbluebutton-html5/imports/ui/components/breakout-room/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/breakout-room/component.jsx @@ -6,6 +6,7 @@ import { Session } from 'meteor/session'; import logger from '/imports/startup/client/logger'; import { styles } from './styles'; import BreakoutRoomContainer from './breakout-remaining-time/container'; +import AudioManager from '/imports/ui/services/audio-manager'; const intlMessages = defineMessages({ breakoutTitle: { @@ -101,6 +102,7 @@ class BreakoutRoom extends PureComponent { breakoutRoomUser, breakoutRooms, closeBreakoutPanel, + setBreakoutAudioTransferStatus, isMicrophoneUser, isReconnecting, } = this.props; @@ -125,6 +127,8 @@ class BreakoutRoom extends PureComponent { if (joinedAudioOnly && (!isMicrophoneUser || isReconnecting)) { this.clearJoinedAudioOnly(); + setBreakoutAudioTransferStatus('', + AudioManager.BREAKOUT_AUDIO_TRANSFER_STATES.DISCONNECTED); } } @@ -173,21 +177,32 @@ class BreakoutRoom extends PureComponent { intl, isUserInBreakoutRoom, exitAudio, - setReturningFromBreakoutAudioTransfer, + setBreakoutAudioTransferStatus, + getBreakoutAudioTransferStatus, } = this.props; const { joinedAudioOnly, - breakoutId: stateBreakoutId, + breakoutId: _stateBreakoutId, requestedBreakoutId, waiting, } = this.state; + const { + breakoutMeetingId: currentAudioTransferBreakoutId, + status, + } = getBreakoutAudioTransferStatus(); + + const isInBreakoutAudioTransfer = status + === AudioManager.BREAKOUT_AUDIO_TRANSFER_STATES.CONNECTED; + + const stateBreakoutId = _stateBreakoutId || currentAudioTransferBreakoutId; const moderatorJoinedAudio = isMicrophoneUser && amIModerator; const disable = waiting && requestedBreakoutId !== breakoutId; - const audioAction = joinedAudioOnly + const audioAction = joinedAudioOnly || isInBreakoutAudioTransfer ? () => { - setReturningFromBreakoutAudioTransfer(true); + setBreakoutAudioTransferStatus(breakoutId, + AudioManager.BREAKOUT_AUDIO_TRANSFER_STATES.RETURNING); this.returnBackToMeeeting(breakoutId); return logger.debug({ logCode: 'breakoutroom_return_main_audio', @@ -195,6 +210,8 @@ class BreakoutRoom extends PureComponent { }, 'Returning to main audio (breakout room audio closed)'); } : () => { + setBreakoutAudioTransferStatus(breakoutId, + AudioManager.BREAKOUT_AUDIO_TRANSFER_STATES.CONNECTED); this.transferUserToBreakoutRoom(breakoutId); return logger.debug({ logCode: 'breakoutroom_join_audio_from_main_room', @@ -234,9 +251,10 @@ class BreakoutRoom extends PureComponent { ( <Button label={ - stateBreakoutId === breakoutId && joinedAudioOnly - ? intl.formatMessage(intlMessages.breakoutReturnAudio) - : intl.formatMessage(intlMessages.breakoutJoinAudio) + stateBreakoutId === breakoutId + && (joinedAudioOnly || isInBreakoutAudioTransfer) + ? intl.formatMessage(intlMessages.breakoutReturnAudio) + : intl.formatMessage(intlMessages.breakoutJoinAudio) } className={styles.button} disabled={stateBreakoutId !== breakoutId && joinedAudioOnly} diff --git a/bigbluebutton-html5/imports/ui/components/breakout-room/container.jsx b/bigbluebutton-html5/imports/ui/components/breakout-room/container.jsx index f092a239a79af991125593d57d06ae6596095c86..d4f1e30915711f96d8eb7062f202adb185253b6e 100644 --- a/bigbluebutton-html5/imports/ui/components/breakout-room/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/breakout-room/container.jsx @@ -26,7 +26,10 @@ export default withTracker((props) => { const isMicrophoneUser = AudioService.isConnected() && !AudioService.isListenOnly(); const isMeteorConnected = Meteor.status().connected; const isReconnecting = AudioService.isReconnecting(); - const { setReturningFromBreakoutAudioTransfer } = AudioService; + const { + setBreakoutAudioTransferStatus, + getBreakoutAudioTransferStatus, + } = AudioService; return { ...props, @@ -43,7 +46,8 @@ export default withTracker((props) => { isMeteorConnected, isUserInBreakoutRoom, exitAudio: () => AudioManager.exitAudio(), - setReturningFromBreakoutAudioTransfer, isReconnecting, + setBreakoutAudioTransferStatus, + getBreakoutAudioTransferStatus, }; })(BreakoutContainer); diff --git a/bigbluebutton-html5/imports/ui/services/audio-manager/index.js b/bigbluebutton-html5/imports/ui/services/audio-manager/index.js index 23c2b4e8bd57f0e6d9190e9e3eacd9eb87289c65..91042209a7a5340311fd67193fe5907cd4ca3ee5 100755 --- a/bigbluebutton-html5/imports/ui/services/audio-manager/index.js +++ b/bigbluebutton-html5/imports/ui/services/audio-manager/index.js @@ -30,6 +30,12 @@ const CALL_STATES = { AUTOPLAY_BLOCKED: 'autoplayBlocked', }; +const BREAKOUT_AUDIO_TRANSFER_STATES = { + CONNECTED: 'connected', + DISCONNECTED: 'disconnected', + RETURNING: 'returning', +}; + class AudioManager { constructor() { this._inputDevice = { @@ -37,7 +43,10 @@ class AudioManager { tracker: new Tracker.Dependency(), }; - this._returningFromBreakoutAudioTransfer = false; + this._breakoutAudioTransferStatus = { + status: BREAKOUT_AUDIO_TRANSFER_STATES.DISCONNECTED, + breakoutMeetingId: null, + }; this.defineProperties({ isMuted: false, @@ -59,6 +68,8 @@ class AudioManager { this.failedMediaElements = []; this.handlePlayElementFailed = this.handlePlayElementFailed.bind(this); this.monitor = this.monitor.bind(this); + + this.BREAKOUT_AUDIO_TRANSFER_STATES = BREAKOUT_AUDIO_TRANSFER_STATES; } init(userData, audioEventHandler) { @@ -534,12 +545,29 @@ class AudioManager { ? this.bridge.inputDeviceId : DEFAULT_INPUT_DEVICE_ID; } - get returningFromBreakoutAudioTransfer() { - return this._returningFromBreakoutAudioTransfer; + /** + * Sets the current status for breakout audio transfer + * @param {String} breakoutMeetingId The id of the current breakout + * audio transfer. + * @param {String} status The status to be set for + * audio transfer. Valid values + * are 'connected', 'disconnected' + * and 'returning' + */ + setBreakoutAudioTransferStatus(breakoutMeetingId, status) { + const data = this._breakoutAudioTransferStatus; + + if (typeof breakoutMeetingId === 'string') { + data.breakoutMeetingId = breakoutMeetingId; + } + + if (typeof status === 'string') { + data.status = status; + } } - set returningFromBreakoutAudioTransfer(value) { - this._returningFromBreakoutAudioTransfer = value; + getBreakoutAudioTransferStatus() { + return this._breakoutAudioTransferStatus; } set userData(value) {