From e16566de9dde5fcacd8ff2d0d23d223f08036c6c Mon Sep 17 00:00:00 2001
From: Mario Jr <mariogasparoni@gmail.com>
Date: Thu, 4 Mar 2021 11:59:32 -0300
Subject: [PATCH] Recover mute state for moderator when returning from
 breakout's audio transfer

Fixes #11489
---
 .../audio/audio-controls/container.jsx        | 33 +++++++++++--------
 .../imports/ui/components/audio/service.js    |  6 ++++
 .../ui/components/breakout-room/component.jsx |  2 ++
 .../ui/components/breakout-room/container.jsx |  2 ++
 .../ui/services/audio-manager/index.js        | 10 ++++++
 5 files changed, 40 insertions(+), 13 deletions(-)

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 04161e8635..c59170c9ce 100755
--- a/bigbluebutton-html5/imports/ui/components/audio/audio-controls/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/audio/audio-controls/container.jsx
@@ -54,16 +54,23 @@ const {
   joinListenOnly,
 } = Service;
 
-export default lockContextContainer(withModalMounter(withTracker(({ mountModal, userLocks }) => ({
-  processToggleMuteFromOutside: arg => processToggleMuteFromOutside(arg),
-  showMute: isConnected() && !isListenOnly() && !isEchoTest() && !userLocks.userMic,
-  muted: isConnected() && !isListenOnly() && isMuted(),
-  inAudio: isConnected() && !isEchoTest(),
-  listenOnly: isConnected() && isListenOnly(),
-  disable: isConnecting() || isHangingUp() || !Meteor.status().connected,
-  talking: isTalking() && !isMuted(),
-  isVoiceUser: isVoiceUser(),
-  handleToggleMuteMicrophone: () => toggleMuteMicrophone(),
-  handleJoinAudio: () => (isConnected() ? joinListenOnly() : mountModal(<AudioModalContainer />)),
-  handleLeaveAudio,
-}))(AudioControlsContainer)));
+export default lockContextContainer(withModalMounter(withTracker(({ mountModal, userLocks }) => {
+  if (Service.isReturningFromBreakoutAudioTransfer()) {
+    Service.setReturningFromBreakoutAudioTransfer(false);
+    Service.recoverMicState();
+  }
+
+  return ({
+    processToggleMuteFromOutside: arg => processToggleMuteFromOutside(arg),
+    showMute: isConnected() && !isListenOnly() && !isEchoTest() && !userLocks.userMic,
+    muted: isConnected() && !isListenOnly() && isMuted(),
+    inAudio: isConnected() && !isEchoTest(),
+    listenOnly: isConnected() && isListenOnly(),
+    disable: isConnecting() || isHangingUp() || !Meteor.status().connected,
+    talking: isTalking() && !isMuted(),
+    isVoiceUser: isVoiceUser(),
+    handleToggleMuteMicrophone: () => toggleMuteMicrophone(),
+    handleJoinAudio: () => (isConnected() ? joinListenOnly() : mountModal(<AudioModalContainer />)),
+    handleLeaveAudio,
+  })
+})(AudioControlsContainer)));
diff --git a/bigbluebutton-html5/imports/ui/components/audio/service.js b/bigbluebutton-html5/imports/ui/components/audio/service.js
index 2848ec87c0..eab4d128bd 100755
--- a/bigbluebutton-html5/imports/ui/components/audio/service.js
+++ b/bigbluebutton-html5/imports/ui/components/audio/service.js
@@ -124,4 +124,10 @@ export default {
   playAlertSound: url => AudioManager.playAlertSound(url),
   updateAudioConstraints:
     constraints => AudioManager.updateAudioConstraints(constraints),
+  recoverMicState,
+  setReturningFromBreakoutAudioTransfer: (value) => {
+    AudioManager.returningFromBreakoutAudioTransfer = value;
+  },
+  isReturningFromBreakoutAudioTransfer:
+    () => AudioManager.returningFromBreakoutAudioTransfer,
 };
diff --git a/bigbluebutton-html5/imports/ui/components/breakout-room/component.jsx b/bigbluebutton-html5/imports/ui/components/breakout-room/component.jsx
index 775da15279..c075d762d1 100644
--- a/bigbluebutton-html5/imports/ui/components/breakout-room/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/breakout-room/component.jsx
@@ -162,6 +162,7 @@ class BreakoutRoom extends PureComponent {
       intl,
       isUserInBreakoutRoom,
       exitAudio,
+      setReturningFromBreakoutAudioTransfer,
     } = this.props;
 
     const {
@@ -175,6 +176,7 @@ class BreakoutRoom extends PureComponent {
     const disable = waiting && requestedBreakoutId !== breakoutId;
     const audioAction = joinedAudioOnly
       ? () => {
+        setReturningFromBreakoutAudioTransfer(true);
         this.returnBackToMeeeting(breakoutId);
         return logger.debug({
           logCode: 'breakoutroom_return_main_audio',
diff --git a/bigbluebutton-html5/imports/ui/components/breakout-room/container.jsx b/bigbluebutton-html5/imports/ui/components/breakout-room/container.jsx
index 4cc8d07884..a118057d34 100644
--- a/bigbluebutton-html5/imports/ui/components/breakout-room/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/breakout-room/container.jsx
@@ -25,6 +25,7 @@ export default withTracker((props) => {
   const breakoutRooms = findBreakouts();
   const isMicrophoneUser = AudioService.isConnected() && !AudioService.isListenOnly();
   const isMeteorConnected = Meteor.status().connected;
+  const { setReturningFromBreakoutAudioTransfer } = AudioService;
 
   return {
     ...props,
@@ -41,5 +42,6 @@ export default withTracker((props) => {
     isMeteorConnected,
     isUserInBreakoutRoom,
     exitAudio: () => AudioManager.exitAudio(),
+    setReturningFromBreakoutAudioTransfer,
   };
 })(BreakoutContainer);
diff --git a/bigbluebutton-html5/imports/ui/services/audio-manager/index.js b/bigbluebutton-html5/imports/ui/services/audio-manager/index.js
index 5027304d4a..5213040d90 100755
--- a/bigbluebutton-html5/imports/ui/services/audio-manager/index.js
+++ b/bigbluebutton-html5/imports/ui/services/audio-manager/index.js
@@ -37,6 +37,8 @@ class AudioManager {
       tracker: new Tracker.Dependency(),
     };
 
+    this._returningFromBreakoutAudioTransfer = false;
+
     this.defineProperties({
       isMuted: false,
       isConnected: false,
@@ -523,6 +525,14 @@ class AudioManager {
       ? this.bridge.inputDeviceId : DEFAULT_INPUT_DEVICE_ID;
   }
 
+  get returningFromBreakoutAudioTransfer() {
+    return this._returningFromBreakoutAudioTransfer;
+  }
+
+  set returningFromBreakoutAudioTransfer(value) {
+    this._returningFromBreakoutAudioTransfer = value;
+  }
+
   set userData(value) {
     this._userData = value;
   }
-- 
GitLab