Browse Source

muc: Store `connection_status` in session storage

Otherwise we might run into a situation where a very old,
cached MUC that's being restored has `connection_status` set to ENTERED
(and the user happens to be in the MUC via another client)
and then restores cached messages without taking
`clear_messages_on_reconnection` into account.
JC Brand 5 years ago
parent
commit
0dc3c9937c
3 changed files with 53 additions and 42 deletions
  1. 12 11
      src/converse-muc-views.js
  2. 1 1
      src/headless/converse-mam.js
  3. 40 30
      src/headless/converse-muc.js

+ 12 - 11
src/converse-muc-views.js

@@ -664,7 +664,7 @@ converse.plugins.add('converse-muc-views', {
                 });
                 });
 
 
                 this.listenTo(this.model, 'change', this.renderHeading);
                 this.listenTo(this.model, 'change', this.renderHeading);
-                this.listenTo(this.model, 'change:connection_status', this.onConnectionStatusChanged);
+                this.listenTo(this.model.session, 'change:connection_status', this.onConnectionStatusChanged);
                 this.listenTo(this.model, 'change:hidden_occupants', this.updateOccupantsToggle);
                 this.listenTo(this.model, 'change:hidden_occupants', this.updateOccupantsToggle);
                 this.listenTo(this.model, 'change:subject', this.setChatRoomSubject);
                 this.listenTo(this.model, 'change:subject', this.setChatRoomSubject);
                 this.listenTo(this.model, 'configurationNeeded', this.getAndRenderConfigurationForm);
                 this.listenTo(this.model, 'configurationNeeded', this.getAndRenderConfigurationForm);
@@ -704,7 +704,7 @@ converse.plugins.add('converse-muc-views', {
                 this.renderChatArea();
                 this.renderChatArea();
                 this.renderBottomPanel();
                 this.renderBottomPanel();
                 if (!_converse.muc_show_logs_before_join) {
                 if (!_converse.muc_show_logs_before_join) {
-                    this.model.get('connection_status') !== converse.ROOMSTATUS.ENTERED && this.showSpinner();
+                    this.model.session.get('connection_status') !== converse.ROOMSTATUS.ENTERED && this.showSpinner();
                 }
                 }
                 if (!this.model.get('hidden')) {
                 if (!this.model.get('hidden')) {
                     this.show();
                     this.show();
@@ -723,7 +723,7 @@ converse.plugins.add('converse-muc-views', {
 
 
             renderBottomPanel () {
             renderBottomPanel () {
                 const container = this.el.querySelector('.bottom-panel');
                 const container = this.el.querySelector('.bottom-panel');
-                const entered = this.model.get('connection_status') === converse.ROOMSTATUS.ENTERED;
+                const entered = this.model.session.get('connection_status') === converse.ROOMSTATUS.ENTERED;
                 const can_edit = entered && !(this.model.features.get('moderated') && this.model.getOwnRole() === 'visitor');
                 const can_edit = entered && !(this.model.features.get('moderated') && this.model.getOwnRole() === 'visitor');
                 container.innerHTML = tpl_chatroom_bottom_panel({__, can_edit, entered});
                 container.innerHTML = tpl_chatroom_bottom_panel({__, can_edit, entered});
                 if (entered && can_edit) {
                 if (entered && can_edit) {
@@ -1127,7 +1127,7 @@ converse.plugins.add('converse-muc-views', {
             },
             },
 
 
             onConnectionStatusChanged () {
             onConnectionStatusChanged () {
-                const conn_status = this.model.get('connection_status');
+                const conn_status = this.model.session.get('connection_status');
                 if (conn_status === converse.ROOMSTATUS.NICKNAME_REQUIRED) {
                 if (conn_status === converse.ROOMSTATUS.NICKNAME_REQUIRED) {
                     this.renderNicknameForm();
                     this.renderNicknameForm();
                 } else if (conn_status === converse.ROOMSTATUS.PASSWORD_REQUIRED) {
                 } else if (conn_status === converse.ROOMSTATUS.PASSWORD_REQUIRED) {
@@ -1562,7 +1562,7 @@ converse.plugins.add('converse-muc-views', {
                     const container = this.el.querySelector('.chatroom-body');
                     const container = this.el.querySelector('.chatroom-body');
                     container.insertAdjacentHTML('beforeend', html);
                     container.insertAdjacentHTML('beforeend', html);
                 }
                 }
-                u.safeSave(this.model, {'connection_status': converse.ROOMSTATUS.NICKNAME_REQUIRED});
+                u.safeSave(this.model.session, {'connection_status': converse.ROOMSTATUS.NICKNAME_REQUIRED});
             },
             },
 
 
             closeForm () {
             closeForm () {
@@ -1623,7 +1623,7 @@ converse.plugins.add('converse-muc-views', {
                     this.password_form.model.set('validation_message', message);
                     this.password_form.model.set('validation_message', message);
                 }
                 }
                 u.showElement(this.password_form.el);
                 u.showElement(this.password_form.el);
-                this.model.save('connection_status', converse.ROOMSTATUS.PASSWORD_REQUIRED);
+                this.model.session.save('connection_status', converse.ROOMSTATUS.PASSWORD_REQUIRED);
             },
             },
 
 
             showDestroyedMessage () {
             showDestroyedMessage () {
@@ -1734,7 +1734,7 @@ converse.plugins.add('converse-muc-views', {
             },
             },
 
 
             onOccupantRemoved (occupant) {
             onOccupantRemoved (occupant) {
-                if (this.model.get('connection_status') ===  converse.ROOMSTATUS.ENTERED &&
+                if (this.model.session.get('connection_status') ===  converse.ROOMSTATUS.ENTERED &&
                         occupant.get('show') === 'online') {
                         occupant.get('show') === 'online') {
                     this.showLeaveNotification(occupant);
                     this.showLeaveNotification(occupant);
                 }
                 }
@@ -1784,7 +1784,7 @@ converse.plugins.add('converse-muc-views', {
 
 
             showJoinNotification (occupant) {
             showJoinNotification (occupant) {
                 if (!_converse.muc_show_join_leave ||
                 if (!_converse.muc_show_join_leave ||
-                        this.model.get('connection_status') !==  converse.ROOMSTATUS.ENTERED) {
+                        this.model.session.get('connection_status') !==  converse.ROOMSTATUS.ENTERED) {
                     return;
                     return;
                 }
                 }
                 const nick = occupant.get('nick'),
                 const nick = occupant.get('nick'),
@@ -1899,11 +1899,12 @@ converse.plugins.add('converse-muc-views', {
              * @method _converse.ChatRoomView#renderAfterTransition
              * @method _converse.ChatRoomView#renderAfterTransition
              */
              */
             renderAfterTransition () {
             renderAfterTransition () {
-                if (this.model.get('connection_status') == converse.ROOMSTATUS.NICKNAME_REQUIRED) {
+                const conn_status = this.model.session.get('connection_status')
+                if (conn_status == converse.ROOMSTATUS.NICKNAME_REQUIRED) {
                     this.renderNicknameForm();
                     this.renderNicknameForm();
-                } else if (this.model.get('connection_status') == converse.ROOMSTATUS.PASSWORD_REQUIRED) {
+                } else if (conn_status == converse.ROOMSTATUS.PASSWORD_REQUIRED) {
                     this.renderPasswordForm();
                     this.renderPasswordForm();
-                } else if (this.model.get('connection_status') == converse.ROOMSTATUS.ENTERED) {
+                } else if (conn_status == converse.ROOMSTATUS.ENTERED) {
                     this.hideChatRoomContents();
                     this.hideChatRoomContents();
                     u.showElement(this.el.querySelector('.chat-area'));
                     u.showElement(this.el.querySelector('.chat-area'));
                     u.showElement(this.el.querySelector('.occupants'));
                     u.showElement(this.el.querySelector('.occupants'));

+ 1 - 1
src/headless/converse-mam.js

@@ -220,7 +220,7 @@ converse.plugins.add('converse-mam', {
         function preMUCJoinMAMFetch (room) {
         function preMUCJoinMAMFetch (room) {
             if (!_converse.muc_show_logs_before_join ||
             if (!_converse.muc_show_logs_before_join ||
                     !room.features.get('mam_enabled') ||
                     !room.features.get('mam_enabled') ||
-                    room.get('connection_status') !== converse.ROOMSTATUS.ENTERED ||
+                    room.session.get('connection_status') !== converse.ROOMSTATUS.ENTERED ||
                     room.get('prejoin_mam_fetched')) {
                     room.get('prejoin_mam_fetched')) {
                 return;
                 return;
             }
             }

+ 40 - 30
src/headless/converse-muc.js

@@ -299,6 +299,15 @@ converse.plugins.add('converse-muc', {
         });
         });
 
 
 
 
+        const MUCSession = Backbone.Model.extend({
+            defaults () {
+                return {
+                    'connection_status': converse.ROOMSTATUS.DISCONNECTED
+                }
+            }
+        });
+
+
         /**
         /**
          * Collection which stores MUC messages
          * Collection which stores MUC messages
          * @class
          * @class
@@ -334,7 +343,6 @@ converse.plugins.add('converse-muc', {
 
 
                     'bookmarked': false,
                     'bookmarked': false,
                     'chat_state': undefined,
                     'chat_state': undefined,
-                    'connection_status': converse.ROOMSTATUS.DISCONNECTED,
                     'description': '',
                     'description': '',
                     'hidden': ['mobile', 'fullscreen'].includes(_converse.view_mode),
                     'hidden': ['mobile', 'fullscreen'].includes(_converse.view_mode),
                     'message_type': 'groupchat',
                     'message_type': 'groupchat',
@@ -349,12 +357,18 @@ converse.plugins.add('converse-muc', {
 
 
             async initialize() {
             async initialize() {
                 this.initialized = u.getResolveablePromise();
                 this.initialized = u.getResolveablePromise();
+
+                const id = `muc.session-${this.get('jid')}`;
+                this.session = new MUCSession({id});
+                this.session.browserStorage = _converse.createStore(id, "session");
+                await new Promise(r => this.session.fetch({'success': r, 'error': r}));
+
                 this.setVCard();
                 this.setVCard();
                 this.set('box_id', `box-${btoa(this.get('jid'))}`);
                 this.set('box_id', `box-${btoa(this.get('jid'))}`);
 
 
                 this.initFeatures(); // sendChatState depends on this.features
                 this.initFeatures(); // sendChatState depends on this.features
                 this.on('change:chat_state', this.sendChatState, this);
                 this.on('change:chat_state', this.sendChatState, this);
-                this.on('change:connection_status', this.onConnectionStatusChanged, this);
+                this.session.on('change:connection_status', this.onConnectionStatusChanged, this);
 
 
                 this.initMessages();
                 this.initMessages();
                 this.initOccupants();
                 this.initOccupants();
@@ -382,7 +396,7 @@ converse.plugins.add('converse-muc', {
              * @returns { Boolean } Returns `true` if we're still joined, otherwise returns `false`.
              * @returns { Boolean } Returns `true` if we're still joined, otherwise returns `false`.
              */
              */
             async restoreFromCache () {
             async restoreFromCache () {
-                if (this.get('connection_status') === converse.ROOMSTATUS.ENTERED && await this.isJoined()) {
+                if (this.session.get('connection_status') === converse.ROOMSTATUS.ENTERED && await this.isJoined()) {
                     // We've restored the room from cache and we're still joined.
                     // We've restored the room from cache and we're still joined.
                     await new Promise(resolve => this.features.fetch({'success': resolve, 'error': resolve}));
                     await new Promise(resolve => this.features.fetch({'success': resolve, 'error': resolve}));
                     await this.fetchOccupants();
                     await this.fetchOccupants();
@@ -402,7 +416,7 @@ converse.plugins.add('converse-muc', {
              * @param { String } [password] - Optional password, if required by the groupchat.
              * @param { String } [password] - Optional password, if required by the groupchat.
              */
              */
             async join (nick, password) {
             async join (nick, password) {
-                if (this.get('connection_status') === converse.ROOMSTATUS.ENTERED) {
+                if (this.session.get('connection_status') === converse.ROOMSTATUS.ENTERED) {
                     // We have restored a groupchat from session storage,
                     // We have restored a groupchat from session storage,
                     // so we don't send out a presence stanza again.
                     // so we don't send out a presence stanza again.
                     return this;
                     return this;
@@ -410,7 +424,7 @@ converse.plugins.add('converse-muc', {
                 await this.refreshRoomFeatures();
                 await this.refreshRoomFeatures();
                 nick = await this.getAndPersistNickname(nick);
                 nick = await this.getAndPersistNickname(nick);
                 if (!nick) {
                 if (!nick) {
-                    u.safeSave(this, {'connection_status': converse.ROOMSTATUS.NICKNAME_REQUIRED});
+                    u.safeSave(this.session, {'connection_status': converse.ROOMSTATUS.NICKNAME_REQUIRED});
                     if (_converse.muc_show_logs_before_join) {
                     if (_converse.muc_show_logs_before_join) {
                         await this.fetchMessages();
                         await this.fetchMessages();
                     }
                     }
@@ -425,13 +439,13 @@ converse.plugins.add('converse-muc', {
                 if (password) {
                 if (password) {
                     stanza.cnode(Strophe.xmlElement("password", [], password));
                     stanza.cnode(Strophe.xmlElement("password", [], password));
                 }
                 }
-                this.save('connection_status', converse.ROOMSTATUS.CONNECTING);
+                this.session.save('connection_status', converse.ROOMSTATUS.CONNECTING);
                 _converse.api.send(stanza);
                 _converse.api.send(stanza);
                 return this;
                 return this;
             },
             },
 
 
             async clearCache () {
             async clearCache () {
-                this.save('connection_status', converse.ROOMSTATUS.DISCONNECTED);
+                this.session.save('connection_status', converse.ROOMSTATUS.DISCONNECTED);
                 if (this.occupants.length) {
                 if (this.occupants.length) {
                     // Remove non-members when reconnecting
                     // Remove non-members when reconnecting
                     this.occupants.filter(o => !o.isMember()).forEach(o => o.destroy());
                     this.occupants.filter(o => !o.isMember()).forEach(o => o.destroy());
@@ -455,7 +469,7 @@ converse.plugins.add('converse-muc', {
             },
             },
 
 
             async onConnectionStatusChanged () {
             async onConnectionStatusChanged () {
-                if (this.get('connection_status') === converse.ROOMSTATUS.ENTERED) {
+                if (this.session.get('connection_status') === converse.ROOMSTATUS.ENTERED) {
                     if (_converse.muc_fetch_members) {
                     if (_converse.muc_fetch_members) {
                         await this.occupants.fetchMembers();
                         await this.occupants.fetchMembers();
                     }
                     }
@@ -716,7 +730,7 @@ converse.plugins.add('converse-muc', {
                 if (_converse.api.connection.connected()) {
                 if (_converse.api.connection.connected()) {
                     this.sendUnavailablePresence(exit_msg);
                     this.sendUnavailablePresence(exit_msg);
                 }
                 }
-                u.safeSave(this, {'connection_status': converse.ROOMSTATUS.DISCONNECTED});
+                u.safeSave(this.session, {'connection_status': converse.ROOMSTATUS.DISCONNECTED});
                 this.removeHandlers();
                 this.removeHandlers();
             },
             },
 
 
@@ -855,7 +869,7 @@ converse.plugins.add('converse-muc', {
             sendChatState () {
             sendChatState () {
                 if (!_converse.send_chat_state_notifications ||
                 if (!_converse.send_chat_state_notifications ||
                         !this.get('chat_state') ||
                         !this.get('chat_state') ||
-                        this.get('connection_status') !== converse.ROOMSTATUS.ENTERED ||
+                        this.session.get('connection_status') !== converse.ROOMSTATUS.ENTERED ||
                         this.features.get('moderated') && this.getOwnRole() === 'visitor') {
                         this.features.get('moderated') && this.getOwnRole() === 'visitor') {
                     return;
                     return;
                 }
                 }
@@ -1739,7 +1753,7 @@ converse.plugins.add('converse-muc', {
             handleModifyError(pres) {
             handleModifyError(pres) {
                 const text = get(pres.querySelector('error text'), 'textContent');
                 const text = get(pres.querySelector('error text'), 'textContent');
                 if (text) {
                 if (text) {
-                    if (this.get('connection_status') === converse.ROOMSTATUS.CONNECTING) {
+                    if (this.session.get('connection_status') === converse.ROOMSTATUS.CONNECTING) {
                         this.setDisconnectionMessage(text);
                         this.setDisconnectionMessage(text);
                     } else {
                     } else {
                         const attrs = {
                         const attrs = {
@@ -1835,11 +1849,11 @@ converse.plugins.add('converse-muc', {
 
 
             setDisconnectionMessage (message, reason, actor) {
             setDisconnectionMessage (message, reason, actor) {
                 this.save({
                 this.save({
-                    'connection_status': converse.ROOMSTATUS.DISCONNECTED,
                     'disconnection_message': message,
                     'disconnection_message': message,
                     'disconnection_reason': reason,
                     'disconnection_reason': reason,
                     'disconnection_actor': actor
                     'disconnection_actor': actor
                 });
                 });
+                this.session.save({'connection_status': converse.ROOMSTATUS.DISCONNECTED});
             },
             },
 
 
 
 
@@ -1857,9 +1871,10 @@ converse.plugins.add('converse-muc', {
                     this.save({
                     this.save({
                         'nickname_validation_message': __(
                         'nickname_validation_message': __(
                             "The nickname you chose is reserved or "+
                             "The nickname you chose is reserved or "+
-                            "currently in use, please choose a different one."),
-                        'connection_status': converse.ROOMSTATUS.NICKNAME_REQUIRED
+                            "currently in use, please choose a different one."
+                        )
                     });
                     });
+                    this.session.save({'connection_status': converse.ROOMSTATUS.NICKNAME_REQUIRED});
                 }
                 }
             },
             },
 
 
@@ -1880,10 +1895,8 @@ converse.plugins.add('converse-muc', {
                     this.handleModifyError(stanza);
                     this.handleModifyError(stanza);
                 } else if (error_type === 'auth') {
                 } else if (error_type === 'auth') {
                     if (sizzle(`not-authorized[xmlns="${Strophe.NS.STANZAS}"]`, error).length) {
                     if (sizzle(`not-authorized[xmlns="${Strophe.NS.STANZAS}"]`, error).length) {
-                        this.save({
-                            'password_validation_message': reason || __("Password incorrect"),
-                            'connection_status': converse.ROOMSTATUS.PASSWORD_REQUIRED
-                        });
+                        this.save({'password_validation_message': reason || __("Password incorrect")});
+                        this.session.save({'connection_status': converse.ROOMSTATUS.PASSWORD_REQUIRED});
                     }
                     }
                     if (error.querySelector('registration-required')) {
                     if (error.querySelector('registration-required')) {
                         const message = __('You are not on the member list of this groupchat.');
                         const message = __('You are not on the member list of this groupchat.');
@@ -1903,11 +1916,8 @@ converse.plugins.add('converse-muc', {
                         const moved_jid = get(sizzle(`gone[xmlns="${Strophe.NS.STANZAS}"]`, error).pop(), 'textContent')
                         const moved_jid = get(sizzle(`gone[xmlns="${Strophe.NS.STANZAS}"]`, error).pop(), 'textContent')
                             .replace(/^xmpp:/, '')
                             .replace(/^xmpp:/, '')
                             .replace(/\?join$/, '');
                             .replace(/\?join$/, '');
-                        this.save({
-                            'connection_status': converse.ROOMSTATUS.DESTROYED,
-                            'destroyed_reason': reason,
-                            'moved_jid': moved_jid
-                        });
+                        this.save({ moved_jid, 'destroyed_reason': reason});
+                        this.session.save({'connection_status': converse.ROOMSTATUS.DESTROYED});
                     } else if (error.querySelector('conflict')) {
                     } else if (error.querySelector('conflict')) {
                         this.onNicknameClash(stanza);
                         this.onNicknameClash(stanza);
                     } else if (error.querySelector('item-not-found')) {
                     } else if (error.querySelector('item-not-found')) {
@@ -1939,8 +1949,8 @@ converse.plugins.add('converse-muc', {
                 if (stanza.querySelector("status[code='110']")) {
                 if (stanza.querySelector("status[code='110']")) {
                     this.onOwnPresence(stanza);
                     this.onOwnPresence(stanza);
                     if (this.getOwnRole() !== 'none' &&
                     if (this.getOwnRole() !== 'none' &&
-                            this.get('connection_status') === converse.ROOMSTATUS.CONNECTING) {
-                        this.save('connection_status', converse.ROOMSTATUS.CONNECTED);
+                            this.session.get('connection_status') === converse.ROOMSTATUS.CONNECTING) {
+                        this.session.save('connection_status', converse.ROOMSTATUS.CONNECTED);
                     }
                     }
                 } else {
                 } else {
                     this.updateOccupantsOnPresence(stanza);
                     this.updateOccupantsOnPresence(stanza);
@@ -1964,7 +1974,7 @@ converse.plugins.add('converse-muc', {
              */
              */
             onOwnPresence (stanza) {
             onOwnPresence (stanza) {
                 if (stanza.getAttribute('type') !== 'unavailable') {
                 if (stanza.getAttribute('type') !== 'unavailable') {
-                    this.save('connection_status', converse.ROOMSTATUS.ENTERED);
+                    this.session.save('connection_status', converse.ROOMSTATUS.ENTERED);
                 }
                 }
                 this.updateOccupantsOnPresence(stanza);
                 this.updateOccupantsOnPresence(stanza);
 
 
@@ -2003,7 +2013,7 @@ converse.plugins.add('converse-muc', {
                         }
                         }
                     }
                     }
                 }
                 }
-                this.save({'connection_status': converse.ROOMSTATUS.ENTERED});
+                this.session.save({'connection_status': converse.ROOMSTATUS.ENTERED});
             },
             },
 
 
             /**
             /**
@@ -2224,7 +2234,7 @@ converse.plugins.add('converse-muc', {
             }
             }
             if (result === true) {
             if (result === true) {
                 const chatroom = await openChatRoom(room_jid, {'password': x_el.getAttribute('password') });
                 const chatroom = await openChatRoom(room_jid, {'password': x_el.getAttribute('password') });
-                if (chatroom.get('connection_status') === converse.ROOMSTATUS.DISCONNECTED) {
+                if (chatroom.session.get('connection_status') === converse.ROOMSTATUS.DISCONNECTED) {
                     _converse.chatboxes.get(room_jid).rejoin();
                     _converse.chatboxes.get(room_jid).rejoin();
                 }
                 }
             }
             }
@@ -2288,7 +2298,7 @@ converse.plugins.add('converse-muc', {
         /************************ BEGIN Event Handlers ************************/
         /************************ BEGIN Event Handlers ************************/
         _converse.api.listen.on('beforeTearDown', () => {
         _converse.api.listen.on('beforeTearDown', () => {
             const groupchats = _converse.chatboxes.where({'type': _converse.CHATROOMS_TYPE});
             const groupchats = _converse.chatboxes.where({'type': _converse.CHATROOMS_TYPE});
-            groupchats.forEach(gc => u.safeSave(gc, {'connection_status': converse.ROOMSTATUS.DISCONNECTED}));
+            groupchats.forEach(muc => u.safeSave(muc.session, {'connection_status': converse.ROOMSTATUS.DISCONNECTED}));
         });
         });
 
 
         _converse.api.listen.on('windowStateChanged', onWindowStateChanged);
         _converse.api.listen.on('windowStateChanged', onWindowStateChanged);
@@ -2311,7 +2321,7 @@ converse.plugins.add('converse-muc', {
              */
              */
             return _converse.chatboxes
             return _converse.chatboxes
                 .filter(m => (m.get('type') === _converse.CHATROOMS_TYPE))
                 .filter(m => (m.get('type') === _converse.CHATROOMS_TYPE))
-                .forEach(m => m.save({'connection_status': converse.ROOMSTATUS.DISCONNECTED}));
+                .forEach(m => m.session.save({'connection_status': converse.ROOMSTATUS.DISCONNECTED}));
         }
         }
         _converse.api.listen.on('disconnected', disconnectChatRooms);
         _converse.api.listen.on('disconnected', disconnectChatRooms);