diff --git a/bigbluebutton-html5/imports/api/group-chat-msg/server/handlers/userTyping.js b/bigbluebutton-html5/imports/api/group-chat-msg/server/handlers/userTyping.js
index 24456ec5476f88cf4525128a1bcd502bd2fae506..e90006a4d2d0a97ac793698e0751c5d16db03f34 100644
--- a/bigbluebutton-html5/imports/api/group-chat-msg/server/handlers/userTyping.js
+++ b/bigbluebutton-html5/imports/api/group-chat-msg/server/handlers/userTyping.js
@@ -1,5 +1,4 @@
 import { check } from 'meteor/check';
-import { UsersTyping } from '/imports/api/group-chat-msg';
 import startTyping from '../modifiers/startTyping';
 
 export default function handleUserTyping({ body }, meetingId) {
diff --git a/bigbluebutton-html5/imports/api/group-chat-msg/server/publishers.js b/bigbluebutton-html5/imports/api/group-chat-msg/server/publishers.js
index 3b22d84ddfb66293825f636ead554d03da391bee..0f29669348112ed3a1622bea42bac1c609f8e5f8 100644
--- a/bigbluebutton-html5/imports/api/group-chat-msg/server/publishers.js
+++ b/bigbluebutton-html5/imports/api/group-chat-msg/server/publishers.js
@@ -35,7 +35,9 @@ function usersTyping() {
     return UsersTyping.find({ meetingId: '' });
   }
 
-  const { meetingId } = extractCredentials(this.userId);
+  const { meetingId, requesterUserId } = extractCredentials(this.userId);
+
+  Logger.debug(`Publishing users-typing for ${meetingId} ${requesterUserId}`);
 
   return UsersTyping.find({ meetingId });
 }
diff --git a/bigbluebutton-html5/imports/startup/client/base.jsx b/bigbluebutton-html5/imports/startup/client/base.jsx
index 75a33c421526df038b704e34e9d405dadb357652..93fdded2b27c690c9b3b89f51b5e69eac42a6661 100755
--- a/bigbluebutton-html5/imports/startup/client/base.jsx
+++ b/bigbluebutton-html5/imports/startup/client/base.jsx
@@ -21,7 +21,9 @@ import { notify } from '/imports/ui/services/notification';
 import deviceInfo from '/imports/utils/deviceInfo';
 import getFromUserSettings from '/imports/ui/services/users-settings';
 
-const CHAT_ENABLED = Meteor.settings.public.chat.enabled;
+const CHAT_CONFIG = Meteor.settings.public.chat;
+const CHAT_ENABLED = CHAT_CONFIG.enabled;
+const PUBLIC_CHAT_ID = CHAT_CONFIG.public_id;
 
 const BREAKOUT_END_NOTIFY_DELAY = 50;
 
@@ -356,7 +358,7 @@ const BaseContainer = withTracker(() => {
     Session.set('openPanel', 'userlist');
     if (CHAT_ENABLED) {
       Session.set('openPanel', 'chat');
-      Session.set('idChatOpen', '');
+      Session.set('idChatOpen', PUBLIC_CHAT_ID);
     }
   } else {
     Session.set('openPanel', '');
diff --git a/bigbluebutton-html5/imports/ui/components/authenticated-handler/component.jsx b/bigbluebutton-html5/imports/ui/components/authenticated-handler/component.jsx
index dd9a8e82e6216fd92e3331cb6a2c7e4f32c4bf23..d61e337e7c7c3f2b6aff526ce5cef995cc487741 100644
--- a/bigbluebutton-html5/imports/ui/components/authenticated-handler/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/authenticated-handler/component.jsx
@@ -5,8 +5,6 @@ import Auth from '/imports/ui/services/auth';
 import LoadingScreen from '/imports/ui/components/loading-screen/component';
 
 const STATUS_CONNECTING = 'connecting';
-const CHAT_CONFIG = Meteor.settings.public.chat;
-const PUBLIC_CHAT_ID = CHAT_CONFIG.public_id;
 
 class AuthenticatedHandler extends Component {
   static setError(codeError) {
@@ -85,10 +83,9 @@ class AuthenticatedHandler extends Component {
       authenticated,
     } = this.state;
 
-    Session.set('isChatOpen', false);
-    Session.set('idChatOpen', PUBLIC_CHAT_ID);
     Session.set('isMeetingEnded', false);
     Session.set('isPollOpen', false);
+    // TODO: breakoutRoomIsOpen doesn't seem used
     Session.set('breakoutRoomIsOpen', false);
 
     return authenticated
diff --git a/bigbluebutton-html5/imports/ui/components/chat/alert/container.jsx b/bigbluebutton-html5/imports/ui/components/chat/alert/container.jsx
index 3c15dcd777c164e1d819ef0b76e25f419f2db40e..6091d870b6fd8d288493c00c7052709599d842f0 100755
--- a/bigbluebutton-html5/imports/ui/components/chat/alert/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/chat/alert/container.jsx
@@ -14,12 +14,23 @@ export default withTracker(() => {
   const AppSettings = Settings.application;
   const activeChats = UserListService.getActiveChats();
   const { loginTime } = Users.findOne({ userId: Auth.userID }, { fields: { loginTime: 1 } });
+
+  const openPanel = Session.get('openPanel');
+  let idChatOpen = Session.get('idChatOpen');
+
+  // Currently the panel can switch from the chat panel to something else and the idChatOpen won't
+  // always reset. A better solution would be to make the openPanel Session variable an
+  // Object { panelType: <String>, panelOptions: <Object> } and then get rid of idChatOpen
+  if (openPanel !== 'chat') {
+    idChatOpen = '';
+  }
+
   return {
     audioAlertDisabled: !AppSettings.chatAudioAlerts,
     pushAlertDisabled: !AppSettings.chatPushAlerts,
     activeChats,
     publicUserId: Meteor.settings.public.chat.public_group_id,
     joinTimestamp: loginTime,
-    idChatOpen: Session.get('idChatOpen'),
+    idChatOpen,
   };
 })(memo(ChatAlertContainer));
diff --git a/bigbluebutton-html5/imports/ui/components/chat/container.jsx b/bigbluebutton-html5/imports/ui/components/chat/container.jsx
index a790298ddc1fada14d76b9336652c005b368b504..01f35774cb1bff023ec69017c3814fe200281abe 100755
--- a/bigbluebutton-html5/imports/ui/components/chat/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/chat/container.jsx
@@ -38,7 +38,15 @@ class ChatContainer extends PureComponent {
   }
 
   render() {
-    const { children } = this.props;
+    const {
+      children,
+      unmounting,
+    } = this.props;
+
+    if (unmounting === true) {
+      return null;
+    }
+
     return (
       <Chat {...this.props}>
         {children}
@@ -48,7 +56,7 @@ class ChatContainer extends PureComponent {
 }
 
 export default injectIntl(withTracker(({ intl }) => {
-  const chatID = Session.get('idChatOpen') || PUBLIC_CHAT_KEY;
+  const chatID = Session.get('idChatOpen');
   let messages = [];
   let isChatLocked = ChatService.isChatLocked(chatID);
   let title = intl.formatMessage(intlMessages.titlePublic);
@@ -105,7 +113,7 @@ export default injectIntl(withTracker(({ intl }) => {
       .concat(messagesAfterWelcomeMsg);
 
     messages = messagesFormated.sort((a, b) => (a.time - b.time));
-  } else {
+  } else if (chatID) {
     messages = ChatService.getPrivateGroupMessages();
 
     const receiverUser = ChatService.getUser(chatID);
@@ -131,6 +139,11 @@ export default injectIntl(withTracker(({ intl }) => {
       messages.push(messagePartnerLoggedOut);
       isChatLocked = true;
     }
+  } else {
+    // No chatID is set so the panel is closed, about to close, or wasn't opened correctly
+    return {
+      unmounting: true,
+    };
   }
 
   messages = messages.map((message) => {
diff --git a/bigbluebutton-html5/imports/ui/components/chat/service.js b/bigbluebutton-html5/imports/ui/components/chat/service.js
index 64cb0ea5317abc7865756f7e9efc825783646188..db41aeabdaa1b694aecb33bb7d7b67195f7afc19 100755
--- a/bigbluebutton-html5/imports/ui/components/chat/service.js
+++ b/bigbluebutton-html5/imports/ui/components/chat/service.js
@@ -169,7 +169,7 @@ const lastReadMessageTime = (receiverID) => {
 };
 
 const sendGroupMessage = (message) => {
-  const chatID = Session.get('idChatOpen') || PUBLIC_CHAT_ID;
+  const chatID = Session.get('idChatOpen');
   const isPublicChat = chatID === PUBLIC_CHAT_ID;
 
   let destinationChatId = PUBLIC_GROUP_CHAT_ID;
@@ -220,7 +220,7 @@ const updateScrollPosition = position => ScrollCollection.upsert(
 );
 
 const updateUnreadMessage = (timestamp) => {
-  const chatID = Session.get('idChatOpen') || PUBLIC_CHAT_ID;
+  const chatID = Session.get('idChatOpen');
   const isPublic = chatID === PUBLIC_CHAT_ID;
   const chatType = isPublic ? PUBLIC_GROUP_CHAT_ID : chatID;
   return UnreadMessages.update(chatType, timestamp);