Browse Source

Move all MUC joining logic to the model

JC Brand 6 years ago
parent
commit
7e515dd4b1
3 changed files with 63 additions and 123 deletions
  1. 11 11
      spec/muc.js
  2. 13 74
      src/converse-muc-views.js
  3. 39 38
      src/headless/converse-muc.js

+ 11 - 11
spec/muc.js

@@ -307,7 +307,7 @@
                 _converse.connection._dataRecv(test_utils.createRequest(features_stanza));
 
                 const view = _converse.chatboxviews.get('lounge@localhost');
-                spyOn(view, 'join').and.callThrough();
+                spyOn(view.model, 'join').and.callThrough();
 
                 /* <iq to="myroom@conference.chat.example.org"
                  *     from="jordie.langen@chat.example.org/converse.js-11659299"
@@ -344,7 +344,7 @@
                 const input = await test_utils.waitUntil(() => view.el.querySelector('input[name="nick"]'));
                 input.value = 'nicky';
                 view.el.querySelector('input[type=submit]').click();
-                expect(view.join).toHaveBeenCalled();
+                expect(view.model.join).toHaveBeenCalled();
 
                 // The user has just entered the room (because join was called)
                 // and receives their own presence from the server.
@@ -359,7 +359,7 @@
                  *    </x>
                  *  </presence>
                  */
-                var presence = $pres({
+                const presence = $pres({
                         to:'dummy@localhost/resource',
                         from:'lounge@localhost/thirdwitch',
                         id:'5025e055-036c-4bc5-a227-706e7e352053'
@@ -1752,7 +1752,7 @@
                 _converse.connection._dataRecv(test_utils.createRequest(features_stanza));
 
                 const view = _converse.chatboxviews.get('lounge@localhost');
-                spyOn(view, 'join').and.callThrough();
+                spyOn(view.model, 'join').and.callThrough();
 
                 /* <iq from='hag66@shakespeare.lit/pda'
                  *     id='getnick1'
@@ -1795,7 +1795,7 @@
                 .c('identity', {'category': 'conference', 'name': 'thirdwitch', 'type': 'text'});
                 _converse.connection._dataRecv(test_utils.createRequest(stanza));
 
-                expect(view.join).toHaveBeenCalled();
+                expect(view.model.join).toHaveBeenCalled();
 
                 // The user has just entered the groupchat (because join was called)
                 // and receives their own presence from the server.
@@ -3617,11 +3617,11 @@
                     .toBe('This groupchat requires a password');
 
                 // Let's submit the form
-                spyOn(view, 'join');
+                spyOn(view.model, 'join');
                 const input_el = view.el.querySelector('[name="password"]');
                 input_el.value = 'secret';
                 view.el.querySelector('input[type=submit]').click();
-                expect(view.join).toHaveBeenCalledWith('dummy', 'secret');
+                expect(view.model.join).toHaveBeenCalledWith('dummy', 'secret');
                 done();
             }));
 
@@ -3734,12 +3734,12 @@
 
                 const view = _converse.chatboxviews.get(groupchat_jid);
                 spyOn(view, 'showErrorMessage').and.callThrough();
-                spyOn(view, 'join').and.callThrough();
+                spyOn(view.model, 'join').and.callThrough();
 
                 // Simulate repeatedly that there's already someone in the groupchat
                 // with that nickname
                 _converse.connection._dataRecv(test_utils.createRequest(presence));
-                expect(view.join).toHaveBeenCalledWith('dummy-2');
+                expect(view.model.join).toHaveBeenCalledWith('dummy-2');
 
                 attrs.from = `${groupchat_jid}/dummy-2`;
                 attrs.id = u.getUniqueId();
@@ -3749,7 +3749,7 @@
                         .c('conflict').attrs({xmlns:'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree;
                 _converse.connection._dataRecv(test_utils.createRequest(presence));
 
-                expect(view.join).toHaveBeenCalledWith('dummy-3');
+                expect(view.model.join).toHaveBeenCalledWith('dummy-3');
 
                 attrs.from = `${groupchat_jid}/dummy-3`;
                 attrs.id = new Date().getTime();
@@ -3758,7 +3758,7 @@
                     .c('error').attrs({'by': groupchat_jid, 'type': 'cancel'})
                         .c('conflict').attrs({'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree;
                 _converse.connection._dataRecv(test_utils.createRequest(presence));
-                expect(view.join).toHaveBeenCalledWith('dummy-4');
+                expect(view.model.join).toHaveBeenCalledWith('dummy-4');
                 done();
             }));
 

+ 13 - 74
src/converse-muc-views.js

@@ -544,7 +544,7 @@ converse.plugins.add('converse-muc-views', {
                 this.model.messages.on('reset', () => (this.content.innerHTML = ''));
 
                 this.model.on('change:affiliation', this.renderHeading, this);
-                this.model.on('change:connection_status', this.afterConnected, this);
+                this.model.on('change:connection_status', this.onConnectionStatusChanged, this);
                 this.model.on('change:hidden_occupants', this.updateOccupantsToggle, this);
                 this.model.on('change:jid', this.renderHeading, this);
                 this.model.on('change:name', this.renderHeading, this);
@@ -580,7 +580,7 @@ converse.plugins.add('converse-muc-views', {
                         // is a hanging chatbox (i.e. not in the collection anymore).
                         return;
                     }
-                    this.populateAndJoin();
+                    this.model.join();
                 }
                 /**
                  * Triggered once a groupchat has been opened
@@ -747,7 +747,7 @@ converse.plugins.add('converse-muc-views', {
                 /* Override from converse-chatview, specifically to avoid
                  * the 'active' chat state from being sent out prematurely.
                  *
-                 * This is instead done in `afterConnected` below.
+                 * This is instead done in `onConnectionStatusChanged` below.
                  */
                 if (u.isPersistableModel(this.model)) {
                     this.model.clearUnreadMsgCounter();
@@ -768,10 +768,13 @@ converse.plugins.add('converse-muc-views', {
                 this.afterShown();
             },
 
-            afterConnected () {
-                if (this.model.get('connection_status') === converse.ROOMSTATUS.CONNECTING) {
+            onConnectionStatusChanged () {
+                const conn_status = this.model.get('connection_status');
+                if (conn_status === converse.ROOMSTATUS.NICKNAME_REQUIRED) {
+                    this.renderNicknameForm();
+                } else if (conn_status === converse.ROOMSTATUS.CONNECTING) {
                     this.showSpinner();
-                } else if (this.model.get('connection_status') === converse.ROOMSTATUS.ENTERED) {
+                } else if (conn_status === converse.ROOMSTATUS.ENTERED) {
                     this.hideSpinner();
                     this.setChatState(_converse.ACTIVE);
                     this.scrollDown();
@@ -1193,28 +1196,6 @@ converse.plugins.add('converse-muc-views', {
                 }
             },
 
-            populateAndJoin () {
-                this.model.occupants.fetchMembers();
-                this.join();
-            },
-
-            /**
-             * Join the groupchat.
-             * @private
-             * @method _converse.ChatRoomView#join
-             * @param { String } nick - The user's nickname
-             * @param { String } password - Optional password, if required by the groupchat
-             */
-            join (nick, password) {
-                if (!nick && !this.model.get('nick')) {
-                    this.checkForReservedNick();
-                    return this;
-                }
-                this.showSpinner();
-                this.model.join(nick, password);
-                return this;
-            },
-
             /**
              * Renders a form given an IQ stanza containing the current
              * groupchat configuration.
@@ -1273,34 +1254,6 @@ converse.plugins.add('converse-muc-views', {
                 }
             },
 
-            checkForReservedNick () {
-                /* User service-discovery to ask the XMPP server whether
-                 * this user has a reserved nickname for this groupchat.
-                 * If so, we'll use that, otherwise we render the nickname form.
-                 */
-                this.showSpinner();
-                this.model.checkForReservedNick()
-                    .then(this.onReservedNickFound.bind(this))
-                    .catch(this.onReservedNickNotFound.bind(this));
-            },
-
-            onReservedNickFound (iq) {
-                if (this.model.get('nick')) {
-                    this.join();
-                } else {
-                    this.onReservedNickNotFound();
-                }
-            },
-
-            onReservedNickNotFound (message) {
-                const nick = _converse.getDefaultMUCNickname();
-                if (nick) {
-                    this.join(nick);
-                } else {
-                    this.renderNicknameForm(message);
-                }
-            },
-
             onNicknameClash (presence) {
                 /* When the nickname is already taken, we either render a
                  * form for the user to choose a new nickname, or we
@@ -1313,11 +1266,11 @@ converse.plugins.add('converse-muc-views', {
                 if (_converse.muc_nickname_from_jid) {
                     const nick = presence.getAttribute('from').split('/')[1];
                     if (nick === _converse.getDefaultMUCNickname()) {
-                        this.join(nick + '-2');
+                        this.model.join(nick + '-2');
                     } else {
                         const del= nick.lastIndexOf("-");
                         const num = nick.substring(del+1, nick.length);
-                        this.join(nick.substring(0, del+1) + String(Number(num)+1));
+                        this.model.join(nick.substring(0, del+1) + String(Number(num)+1));
                     }
                 } else {
                     this.renderNicknameForm(
@@ -1930,7 +1883,7 @@ converse.plugins.add('converse-muc-views', {
             submitPassword (ev) {
                 ev.preventDefault();
                 const password = this.el.querySelector('input[type=password]').value;
-                this.chatroomview.join(this.chatroomview.model.get('nick'), password);
+                this.chatroomview.model.join(this.chatroomview.model.get('nick'), password);
                 this.model.set('validation_message', null);
             }
         });
@@ -1968,7 +1921,7 @@ converse.plugins.add('converse-muc-views', {
                 const nick_el = ev.target.nick;
                 const nick = nick_el.value.trim();
                 if (nick) {
-                    this.chatroomview.join(nick);
+                    this.chatroomview.model.join(nick);
                     this.model.set({
                         'validation_message': null,
                         'nickname': nick
@@ -2243,20 +2196,6 @@ converse.plugins.add('converse-muc-views', {
             fetchAndSetMUCDomain(view);
             view.model.on('change:connected', _.partial(fetchAndSetMUCDomain, view));
         });
-
-        function reconnectToChatRooms () {
-            /* Upon a reconnection event from converse, join again
-             * all the open groupchats.
-             */
-            _converse.chatboxviews.each(view => {
-                if (view.model.get('type') === _converse.CHATROOMS_TYPE) {
-                    view.model.save('connection_status', converse.ROOMSTATUS.DISCONNECTED);
-                    view.model.registerHandlers();
-                    view.populateAndJoin();
-                }
-            });
-        }
-        _converse.api.listen.on('reconnected', reconnectToChatRooms);
         /************************ END Event Handlers ************************/
 
 

+ 39 - 38
src/headless/converse-muc.js

@@ -226,6 +226,7 @@ converse.plugins.add('converse-muc', {
                         !this.get('reserved_nick') &&
                         await _converse.api.disco.supports(Strophe.NS.MUC_REGISTER, this.get('jid'))) {
 
+                    this.occupants.fetchMembers();
                     this.registerNickname()
                 }
             },
@@ -320,10 +321,11 @@ converse.plugins.add('converse-muc', {
              * @param { String } nick - The user's nickname
              * @param { String } password - Optional password, if required by the groupchat.
              */
-            join (nick, password) {
-                nick = nick ? nick : this.get('nick');
+            async join (nick, password) {
+                nick = nick ? nick : await this.getNickname();
                 if (!nick) {
-                    throw new TypeError('join: You need to provide a valid nickname');
+                    u.safeSave(this, {'connection_status': converse.ROOMSTATUS.NICKNAME_REQUIRED});
+                    return this;
                 }
                 if (this.get('connection_status') === converse.ROOMSTATUS.ENTERED) {
                     // We have restored a groupchat from session storage,
@@ -843,15 +845,29 @@ converse.plugins.add('converse-muc', {
                     .catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
             },
 
+            async getNickname () {
+                let nick = this.get('nick');
+                if (!nick) {
+                    try {
+                        nick = await this.getReservedNick();
+                        this.save({'reserved_nick': nick, 'nick': nick}, {'silent': true});
+                    } catch (e) {
+                        nick = _converse.getDefaultMUCNickname();
+                        this.save({'nick': nick}, {'silent': true});
+                    }
+                }
+                return nick;
+            },
+
             /**
              * Use service-discovery to ask the XMPP server whether
              * this user has a reserved nickname for this groupchat.
              * If so, we'll use that, otherwise we render the nickname form.
              * @private
-             * @method _converse.ChatRoom#checkForReservedNick
-             * @returns { promise } A promise which resolves with the response IQ
+             * @method _converse.ChatRoom#getReservedNick
+             * @returns { promise } A promise which resolves with the reserved nick or null
              */
-            async checkForReservedNick () {
+            async getReservedNick () {
                 const iq = await _converse.api.sendIQ(
                     $iq({
                         'to': this.get('jid'),
@@ -862,13 +878,8 @@ converse.plugins.add('converse-muc', {
                         'node': 'x-roomuser-item'
                     })
                 );
-                const identity_el = iq.querySelector('query[node="x-roomuser-item"] identity'),
-                      nick = identity_el ? identity_el.getAttribute('name') : null;
-                this.save({
-                    'reserved_nick': nick,
-                    'nick': nick
-                }, {'silent': true});
-                return iq;
+                const identity_el = iq.querySelector('query[node="x-roomuser-item"] identity');
+                return identity_el ? identity_el.getAttribute('name') : null;
             },
 
             async registerNickname () {
@@ -1417,14 +1428,8 @@ converse.plugins.add('converse-muc', {
             }
             if (result === true) {
                 const chatroom = openChatRoom(room_jid, {'password': x_el.getAttribute('password') });
-
                 if (chatroom.get('connection_status') === converse.ROOMSTATUS.DISCONNECTED) {
-                    // XXX: Leaky abstraction from views here
-                    if (_converse.chatboxviews) {
-                        _converse.chatboxviews.get(room_jid).join();
-                    } else {
-                        _converse.chatboxes.get(room_jid).join();
-                    }
+                    _converse.chatboxes.get(room_jid).join();
                 }
             }
         };
@@ -1497,24 +1502,6 @@ converse.plugins.add('converse-muc', {
             });
         }
 
-        function fetchRegistrationForm (room_jid, user_jid) {
-            _converse.api.sendIQ(
-                $iq({
-                    'from': user_jid,
-                    'to': room_jid,
-                    'type': 'get'
-                }).c('query', {'xmlns': Strophe.NS.REGISTER})
-            ).then(iq => {
-
-            }).catch(iq => {
-                if (sizzle('item-not-found[xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"]', iq).length) {
-                    this.feedback.set('error', __('Error: the groupchat %1$s does not exist.', this.model.getDisplayName()));
-                } else if (sizzle('not-allowed[xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"]').length) {
-                    this.feedback.set('error', __("Sorry, you're not allowed to register in this groupchat"));
-                }
-            });
-        }
-
 
         /************************ BEGIN Event Handlers ************************/
         _converse.api.listen.on('addClientFeatures', () => {
@@ -1539,6 +1526,20 @@ converse.plugins.add('converse-muc', {
                 }
             });
         });
+
+        function reconnectToChatRooms () {
+            /* Upon a reconnection event from converse, join again
+             * all the open groupchats.
+             */
+            _converse.chatboxes.each(model => {
+                if (model.get('type') === _converse.CHATROOMS_TYPE) {
+                    model.save('connection_status', converse.ROOMSTATUS.DISCONNECTED);
+                    model.registerHandlers();
+                    model.join();
+                }
+            });
+        }
+        _converse.api.listen.on('reconnected', reconnectToChatRooms);
         /************************ END Event Handlers ************************/