Browse Source

Convert a few functions to async/await.

Emmanuel Gil Peyrot 6 years ago
parent
commit
35b7dbe389

+ 15 - 18
src/converse-bookmarks.js

@@ -69,15 +69,14 @@ converse.plugins.add('converse-bookmarks', {
                 close_button.insertAdjacentHTML('afterend', bookmark_button);
             },
 
-            renderHeading () {
+            async renderHeading () {
                 this.__super__.renderHeading.apply(this, arguments);
                 const { _converse } = this.__super__;
                 if (_converse.allow_bookmarks) {
-                    _converse.checkBookmarksSupport().then((supported) => {
-                        if (supported) {
-                            this.renderBookmarkToggle();
-                        }
-                    }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+                    const supported = await _converse.checkBookmarksSupport();
+                    if (supported) {
+                        this.renderBookmarkToggle();
+                    }
                 }
             },
 
@@ -529,21 +528,19 @@ converse.plugins.add('converse-bookmarks', {
             }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
         }
 
-        const initBookmarks = function () {
+        const initBookmarks = async function () {
             if (!_converse.allow_bookmarks) {
                 return;
             }
-            _converse.checkBookmarksSupport().then((supported) => {
-                if (supported) {
-                    _converse.bookmarks = new _converse.Bookmarks();
-                    _converse.bookmarksview = new _converse.BookmarksView({'model': _converse.bookmarks});
-                    _converse.bookmarks.fetchBookmarks()
-                        .catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
-                        .then(() => _converse.emit('bookmarksInitialized'));
-                } else {
-                    _converse.emit('bookmarksInitialized');
-                }
-            });
+            const supported = await _converse.checkBookmarksSupport();
+            if (supported) {
+                _converse.bookmarks = new _converse.Bookmarks();
+                _converse.bookmarksview = new _converse.BookmarksView({'model': _converse.bookmarks});
+                await _converse.bookmarks.fetchBookmarks();
+                _converse.emit('bookmarksInitialized');
+            } else {
+                _converse.emit('bookmarksInitialized');
+            }
         }
 
         u.onMultipleEvents([

+ 20 - 23
src/converse-chatview.js

@@ -229,13 +229,12 @@ converse.plugins.add('converse-chatview', {
                 }
             },
 
-            refreshContact (ev) {
+            async refreshContact (ev) {
                 if (ev && ev.preventDefault) { ev.preventDefault(); }
                 const refresh_icon = this.el.querySelector('.fa-refresh');
                 u.addClass('fa-spin', refresh_icon);
-                _converse.api.vcard.update(this.model.contact.vcard, true)
-                    .then(() => u.removeClass('fa-spin', refresh_icon))
-                    .catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+                await _converse.api.vcard.update(this.model.contact.vcard, true);
+                u.removeClass('fa-spin', refresh_icon);
             },
 
             removeContact (ev) {
@@ -387,17 +386,16 @@ converse.plugins.add('converse-chatview', {
                 this.model.sendFiles(evt.target.files);
             },
 
-            addFileUploadButton (options) {
-                _converse.api.disco.supports(Strophe.NS.HTTPUPLOAD, _converse.domain).then((result) => {
-                    if (result.length) {
-                        this.el.querySelector('.chat-toolbar').insertAdjacentHTML(
-                            'beforeend',
-                            tpl_toolbar_fileupload({'tooltip_upload_file': __('Choose a file to send')}));
-                    }
-                }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+            async addFileUploadButton (options) {
+                const result = await _converse.api.disco.supports(Strophe.NS.HTTPUPLOAD, _converse.domain);
+                if (result.length) {
+                    this.el.querySelector('.chat-toolbar').insertAdjacentHTML(
+                        'beforeend',
+                        tpl_toolbar_fileupload({'tooltip_upload_file': __('Choose a file to send')}));
+                }
             },
 
-            addSpoilerButton (options) {
+            async addSpoilerButton (options) {
                 /* Asynchronously adds a button for writing spoiler
                  * messages, based on whether the contact's client supports
                  * it.
@@ -410,18 +408,17 @@ converse.plugins.add('converse-chatview', {
                 if (_.isEmpty(resources)) {
                     return;
                 }
-                Promise.all(_.map(_.keys(resources), (resource) =>
+                const results = await Promise.all(_.map(_.keys(resources), (resource) =>
                     _converse.api.disco.supports(Strophe.NS.SPOILER, `${contact_jid}/${resource}`)
-                )).then((results) => {
-                    if (_.filter(results, 'length').length) {
-                        const html = tpl_spoiler_button(this.model.toJSON());
-                        if (_converse.visible_toolbar_buttons.emoji) {
-                            this.el.querySelector('.toggle-smiley').insertAdjacentHTML('afterEnd', html);
-                        } else {
-                            this.el.querySelector('.chat-toolbar').insertAdjacentHTML('afterBegin', html);
-                        }
+                ));
+                if (_.filter(results, 'length').length) {
+                    const html = tpl_spoiler_button(this.model.toJSON());
+                    if (_converse.visible_toolbar_buttons.emoji) {
+                        this.el.querySelector('.toggle-smiley').insertAdjacentHTML('afterEnd', html);
+                    } else {
+                        this.el.querySelector('.chat-toolbar').insertAdjacentHTML('afterBegin', html);
                     }
-                }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+                }
             },
 
             insertHeading () {

+ 10 - 11
src/converse-controlbox.js

@@ -154,7 +154,7 @@ converse.plugins.add('converse-controlbox', {
         }
     },
 
-    initialize () {
+    async initialize () {
         /* The initialize function gets called as soon as the plugin is
          * loaded by converse.js's plugin machinery.
          */
@@ -238,14 +238,13 @@ converse.plugins.add('converse-controlbox', {
                 }
             },
 
-            insertRoster () {
+            async insertRoster () {
                 if (_converse.authentication === _converse.ANONYMOUS) {
                     return;
                 }
                 /* Place the rosterview inside the "Contacts" panel. */
-                _converse.api.waitUntil('rosterViewInitialized')
-                    .then(() => this.controlbox_pane.el.insertAdjacentElement('beforeEnd', _converse.rosterview.el))
-                    .catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+                await _converse.api.waitUntil('rosterViewInitialized');
+                this.controlbox_pane.el.insertAdjacentElement('beforeEnd', _converse.rosterview.el);
             },
 
              createBrandHeadingHTML () {
@@ -506,11 +505,10 @@ converse.plugins.add('converse-controlbox', {
                 'href': "#"
             },
 
-            initialize () {
+            async initialize () {
                 _converse.chatboxviews.insertRowColumn(this.render().el);
-                _converse.api.waitUntil('initialized')
-                    .then(this.render.bind(this))
-                    .catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+                await _converse.api.waitUntil('initialized');
+                this.render.bind(this);
             },
 
             render () {
@@ -589,10 +587,11 @@ converse.plugins.add('converse-controlbox', {
             }
         });
 
-        Promise.all([
+        await Promise.all([
             _converse.api.waitUntil('connectionInitialized'),
             _converse.api.waitUntil('chatBoxViewsInitialized')
-        ]).then(_converse.addControlBox).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+        ]);
+        _converse.addControlBox();
 
         _converse.on('chatBoxesFetched', () => {
             const controlbox = _converse.chatboxes.get('controlbox') || _converse.addControlBox();

+ 33 - 38
src/converse-minimize.js

@@ -229,7 +229,7 @@ converse.plugins.add('converse-minimize', {
                 );
             },
 
-            trimChats (newchat) {
+            async trimChats (newchat) {
                 /* This method is called when a newly created chat box will
                  * be shown.
                  *
@@ -250,35 +250,34 @@ converse.plugins.add('converse-minimize', {
                     // fullscreen. In this case we don't trim.
                     return;
                 }
-                _converse.api.waitUntil('minimizedChatsInitialized').then(() => {
-                    const minimized_el = _.get(_converse.minimized_chats, 'el'),
-                          new_id = newchat ? newchat.model.get('id') : null;
-
-                    if (minimized_el) {
-                        const minimized_width = _.includes(this.model.pluck('minimized'), true) ?
-                            u.getOuterWidth(minimized_el, true) : 0;
-
-                        const boxes_width = _.reduce(
-                            this.xget(new_id),
-                            (memo, view) => memo + this.getChatBoxWidth(view),
-                            newchat ? u.getOuterWidth(newchat.el, true) : 0
-                        );
-                        if ((minimized_width + boxes_width) > body_width) {
-                            const oldest_chat = this.getOldestMaximizedChat([new_id]);
-                            if (oldest_chat) {
-                                // We hide the chat immediately, because waiting
-                                // for the event to fire (and letting the
-                                // ChatBoxView hide it then) causes race
-                                // conditions.
-                                const view = this.get(oldest_chat.get('id'));
-                                if (view) {
-                                    view.hide();
-                                }
-                                oldest_chat.minimize();
+                await _converse.api.waitUntil('minimizedChatsInitialized');
+                const minimized_el = _.get(_converse.minimized_chats, 'el'),
+                      new_id = newchat ? newchat.model.get('id') : null;
+
+                if (minimized_el) {
+                    const minimized_width = _.includes(this.model.pluck('minimized'), true) ?
+                        u.getOuterWidth(minimized_el, true) : 0;
+
+                    const boxes_width = _.reduce(
+                        this.xget(new_id),
+                        (memo, view) => memo + this.getChatBoxWidth(view),
+                        newchat ? u.getOuterWidth(newchat.el, true) : 0
+                    );
+                    if ((minimized_width + boxes_width) > body_width) {
+                        const oldest_chat = this.getOldestMaximizedChat([new_id]);
+                        if (oldest_chat) {
+                            // We hide the chat immediately, because waiting
+                            // for the event to fire (and letting the
+                            // ChatBoxView hide it then) causes race
+                            // conditions.
+                            const view = this.get(oldest_chat.get('id'));
+                            if (view) {
+                                view.hide();
                             }
+                            oldest_chat.minimize();
                         }
                     }
-                }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+                }
             },
 
             getOldestMaximizedChat (exclude_ids) {
@@ -300,7 +299,7 @@ converse.plugins.add('converse-minimize', {
     },
 
 
-    initialize () {
+    async initialize () {
         /* The initialize function gets called as soon as the plugin is
          * loaded by Converse.js's plugin machinery.
          */
@@ -510,16 +509,12 @@ converse.plugins.add('converse-minimize', {
             }
         });
 
-        Promise.all([
-            _converse.api.waitUntil('connectionInitialized'),
-            _converse.api.waitUntil('chatBoxViewsInitialized')
-        ]).then(() => {
-            _converse.minimized_chats = new _converse.MinimizedChats({
-                model: _converse.chatboxes
-            });
-            _converse.emit('minimizedChatsInitialized');
-        }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
-
+        await _converse.api.waitUntil('connectionInitialized');
+        await _converse.api.waitUntil('chatBoxViewsInitialized');
+        _converse.minimized_chats = new _converse.MinimizedChats({
+            model: _converse.chatboxes
+        });
+        _converse.emit('minimizedChatsInitialized');
 
         _converse.on('registeredGlobalEventHandlers', function () {
             window.addEventListener("resize", _.debounce(function (ev) {

+ 8 - 9
src/converse-muc-views.js

@@ -248,18 +248,18 @@ converse.plugins.add('converse-muc-views', {
                 }));
         }
 
-        function toggleRoomInfo (ev) {
+        async function toggleRoomInfo (ev) {
             /* Show/hide extra information about a groupchat in a listing. */
             const parent_el = u.ancestor(ev.target, '.room-item'),
                     div_el = parent_el.querySelector('div.room-info');
             if (div_el) {
-                u.slideIn(div_el).then(u.removeElement)
+                await u.slideIn(div_el);
+                u.removeElement();
                 parent_el.querySelector('a.room-info').classList.remove('selected');
             } else {
                 parent_el.insertAdjacentHTML('beforeend', tpl_spinner());
-                _converse.api.disco.info(ev.target.getAttribute('data-room-jid'), null)
-                    .then((stanza) => insertRoomInfo(parent_el, stanza))
-                    .catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
+                const stanza = await _converse.api.disco.info(ev.target.getAttribute('data-room-jid'), null);
+                insertRoomInfo(parent_el, stanza);
             }
         }
 
@@ -1144,7 +1144,7 @@ converse.plugins.add('converse-muc-views', {
                 this.renderAfterTransition();
             },
 
-            getAndRenderConfigurationForm (ev) {
+            async getAndRenderConfigurationForm (ev) {
                 /* Start the process of configuring a groupchat, either by
                  * rendering a configuration form, or by auto-configuring
                  * based on the "roomconfig" data stored on the
@@ -1160,9 +1160,8 @@ converse.plugins.add('converse-muc-views', {
                  *      the settings.
                  */
                 this.showSpinner();
-                this.model.fetchRoomConfiguration()
-                    .then(this.renderConfigurationForm.bind(this))
-                    .catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
+                await this.model.fetchRoomConfiguration();
+                this.renderConfigurationForm();
             },
 
             submitNickname (ev) {

+ 9 - 12
src/converse-oauth.js

@@ -106,17 +106,16 @@ converse.plugins.add("converse-oauth", {
                     }));
             },
 
-            fetchOAuthProfileDataAndLogin () {
-                this.oauth_service.api('me').then((profile) => {
-                    const response = this.oauth_service.getAuthResponse();
-                    _converse.api.user.login({
-                        'jid': `${profile.name}@${this.provider.get('host')}`,
-                        'password': response.access_token
-                    });
+            async fetchOAuthProfileDataAndLogin () {
+                const profile = await this.oauth_service.api('me');
+                const response = this.oauth_service.getAuthResponse();
+                _converse.api.user.login({
+                    'jid': `${profile.name}@${this.provider.get('host')}`,
+                    'password': response.access_token
                 });
             },
 
-            oauthLogin (ev) {
+            async oauthLogin (ev) {
                 ev.preventDefault();
                 const id = ev.target.getAttribute('data-id');
                 this.provider = _converse.oauth_providers.get(id);
@@ -128,10 +127,8 @@ converse.plugins.add("converse-oauth", {
                     'redirect_uri': '/redirect.html'
                 });
 
-                this.oauth_service.login().then(
-                    () => this.fetchOAuthProfileDataAndLogin(),
-                    (error) => _converse.log(error.error_message, Strophe.LogLevel.ERROR)
-                );
+                await this.oauth_service.login();
+                this.fetchOAuthProfileDataAndLogin();
             }
         });
     }

+ 4 - 5
src/converse-rosterview.js

@@ -680,15 +680,14 @@ converse.plugins.add('converse-rosterview', {
                 this.filterOutContacts(this.getFilterMatches(q, type));
             },
 
-            toggle (ev) {
+            async toggle (ev) {
                 if (ev && ev.preventDefault) { ev.preventDefault(); }
                 const icon_el = ev.target.querySelector('.fa');
                 if (_.includes(icon_el.classList, "fa-caret-down")) {
                     this.model.save({state: _converse.CLOSED});
-                    this.collapse().then(() => {
-                        icon_el.classList.remove("fa-caret-down");
-                        icon_el.classList.add("fa-caret-right");
-                    });
+                    await this.collapse();
+                    icon_el.classList.remove("fa-caret-down");
+                    icon_el.classList.add("fa-caret-right");
                 } else {
                     icon_el.classList.remove("fa-caret-right");
                     icon_el.classList.add("fa-caret-down");

+ 49 - 49
src/headless/converse-chatboxes.js

@@ -148,27 +148,29 @@ converse.plugins.add('converse-chatboxes', {
                 });
             },
 
-            getRequestSlotURL () {
-                this.sendSlotRequestStanza().then((stanza) => {
-                    const slot = stanza.querySelector('slot');
-                    if (slot) {
-                        this.save({
-                            'get':  slot.querySelector('get').getAttribute('url'),
-                            'put': slot.querySelector('put').getAttribute('url'),
-                        });
-                    } else {
-                        return this.save({
-                            'type': 'error',
-                            'message': __("Sorry, could not determine file upload URL.")
-                        });
-                    }
-                }).catch((e) => {
+            async getRequestSlotURL () {
+                let stanza;
+                try {
+                    stanza = await this.sendSlotRequestStanza();
+                } catch (e) {
                     _converse.log(e, Strophe.LogLevel.ERROR);
                     return this.save({
                         'type': 'error',
                         'message': __("Sorry, could not determine upload URL.")
                     });
-                });
+                }
+                const slot = stanza.querySelector('slot');
+                if (slot) {
+                    this.save({
+                        'get':  slot.querySelector('get').getAttribute('url'),
+                        'put': slot.querySelector('put').getAttribute('url'),
+                    });
+                } else {
+                    return this.save({
+                        'type': 'error',
+                        'message': __("Sorry, could not determine file upload URL.")
+                    });
+                }
             },
 
             uploadFile () {
@@ -417,39 +419,38 @@ converse.plugins.add('converse-chatboxes', {
             },
 
 
-            sendFiles (files) {
-                _converse.api.disco.supports(Strophe.NS.HTTPUPLOAD, _converse.domain).then((result) => {
-                    const item = result.pop(),
-                          data = item.dataforms.where({'FORM_TYPE': {'value': Strophe.NS.HTTPUPLOAD, 'type': "hidden"}}).pop(),
-                          max_file_size = window.parseInt(_.get(data, 'attributes.max-file-size.value')),
-                          slot_request_url = _.get(item, 'id');
+            async sendFiles (files) {
+                const result = await _converse.api.disco.supports(Strophe.NS.HTTPUPLOAD, _converse.domain);
+                const item = result.pop(),
+                      data = item.dataforms.where({'FORM_TYPE': {'value': Strophe.NS.HTTPUPLOAD, 'type': "hidden"}}).pop(),
+                      max_file_size = window.parseInt(_.get(data, 'attributes.max-file-size.value')),
+                      slot_request_url = _.get(item, 'id');
 
-                    if (!slot_request_url) {
-                        this.messages.create({
-                            'message': __("Sorry, looks like file upload is not supported by your server."),
+                if (!slot_request_url) {
+                    this.messages.create({
+                        'message': __("Sorry, looks like file upload is not supported by your server."),
+                        'type': 'error',
+                    });
+                    return;
+                }
+                _.each(files, (file) => {
+                    if (!window.isNaN(max_file_size) && window.parseInt(file.size) > max_file_size) {
+                        return this.messages.create({
+                            'message': __('The size of your file, %1$s, exceeds the maximum allowed by your server, which is %2$s.',
+                                file.name, filesize(max_file_size)),
                             'type': 'error',
                         });
-                        return;
+                    } else {
+                        this.messages.create(
+                            _.extend(
+                                this.getOutgoingMessageAttributes(), {
+                                'file': file,
+                                'progress': 0,
+                                'slot_request_url': slot_request_url
+                            })
+                        );
                     }
-                    _.each(files, (file) => {
-                        if (!window.isNaN(max_file_size) && window.parseInt(file.size) > max_file_size) {
-                            return this.messages.create({
-                                'message': __('The size of your file, %1$s, exceeds the maximum allowed by your server, which is %2$s.',
-                                    file.name, filesize(max_file_size)),
-                                'type': 'error',
-                            });
-                        } else {
-                            this.messages.create(
-                                _.extend(
-                                    this.getOutgoingMessageAttributes(), {
-                                    'file': file,
-                                    'progress': 0,
-                                    'slot_request_url': slot_request_url
-                                })
-                            );
-                        }
-                    });
-                }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+                });
             },
 
             getReferencesFromStanza (stanza) {
@@ -653,7 +654,7 @@ converse.plugins.add('converse-chatboxes', {
                 }
             },
 
-            onMessage (stanza) {
+            async onMessage (stanza) {
                 /* Handler method for all incoming single-user chat "message"
                  * stanzas.
                  *
@@ -727,9 +728,8 @@ converse.plugins.add('converse-chatboxes', {
                           message = msgid && chatbox.messages.findWhere({msgid});
                     if (!message) {
                         // Only create the message when we're sure it's not a duplicate
-                        chatbox.createMessage(stanza, original_stanza)
-                            .then(msg => chatbox.incrementUnreadMsgCounter(msg))
-                            .catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+                        const msg = await chatbox.createMessage(stanza, original_stanza);
+                        chatbox.incrementUnreadMsgCounter(msg);
                     }
                 }
                 _converse.emit('message', {'stanza': original_stanza, 'chatbox': chatbox});

+ 52 - 60
src/headless/converse-disco.js

@@ -162,13 +162,14 @@ converse.plugins.add('converse-disco', {
                 });
             },
 
-            queryForItems () {
+            async queryForItems () {
                 if (_.isEmpty(this.identities.where({'category': 'server'}))) {
                     // Don't fetch features and items if this is not a
                     // server or a conference component.
                     return;
                 }
-                _converse.api.disco.items(this.get('jid')).then(stanza => this.onDiscoItems(stanza));
+                const stanza = await _converse.api.disco.items(this.get('jid'));
+                this.onDiscoItems(stanza);
             },
 
             onInfo (stanza) {
@@ -268,7 +269,7 @@ converse.plugins.add('converse-disco', {
             _converse.emit('streamFeaturesAdded');
         }
 
-        function initializeDisco () {
+        async function initializeDisco () {
             addClientFeatures();
             _converse.connection.addHandler(onDiscoInfoRequest, Strophe.NS.DISCO_INFO, 'iq', 'get', null, null);
 
@@ -277,14 +278,13 @@ converse.plugins.add('converse-disco', {
                 b64_sha1(`converse.disco-entities-${_converse.bare_jid}`)
             );
 
-            _converse.disco_entities.fetchEntities().then((collection) => {
-                if (collection.length === 0 || !collection.get(_converse.domain)) {
-                    // If we don't have an entity for our own XMPP server,
-                    // create one.
-                    _converse.disco_entities.create({'jid': _converse.domain});
-                }
-                _converse.emit('discoInitialized');
-            }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+            const collection = await _converse.disco_entities.fetchEntities();
+            if (collection.length === 0 || !collection.get(_converse.domain)) {
+                // If we don't have an entity for our own XMPP server,
+                // create one.
+                _converse.disco_entities.create({'jid': _converse.domain});
+            }
+            _converse.emit('discoInitialized');
         }
 
         _converse.api.listen.on('sessionInitialized', initStreamFeatures);
@@ -513,18 +513,16 @@ converse.plugins.add('converse-disco', {
                      * @param {boolean} [create] Whether the entity should be created if it doesn't exist.
                      * @example _converse.api.disco.entities.get(jid);
                      */
-                    'get' (jid, create=false) {
-                        return _converse.api.waitUntil('discoInitialized')
-                        .then(() => {
-                            if (_.isNil(jid)) {
-                                return _converse.disco_entities;
-                            }
-                            const entity = _converse.disco_entities.get(jid);
-                            if (entity || !create) {
-                                return entity;
-                            }
-                            return _converse.disco_entities.create({'jid': jid});
-                        });
+                    async 'get' (jid, create=false) {
+                        await _converse.api.waitUntil('discoInitialized');
+                        if (_.isNil(jid)) {
+                            return _converse.disco_entities;
+                        }
+                        const entity = _converse.disco_entities.get(jid);
+                        if (entity || !create) {
+                            return entity;
+                        }
+                        return _converse.disco_entities.create({'jid': jid});
                     }
                 },
 
@@ -559,20 +557,18 @@ converse.plugins.add('converse-disco', {
                  *     );
                  * });
                  */
-                'supports' (feature, jid) {
+                async 'supports' (feature, jid) {
                     if (_.isNil(jid)) {
                         throw new TypeError('api.disco.supports: You need to provide an entity JID');
                     }
-                    return _converse.api.waitUntil('discoInitialized')
-                    .then(() => _converse.api.disco.entities.get(jid, true))
-                    .then(entity => entity.waitUntilFeaturesDiscovered)
-                    .then(entity => {
-                        const promises = _.concat(
-                            entity.items.map(item => item.hasFeature(feature)),
-                            entity.hasFeature(feature)
-                        );
-                        return Promise.all(promises);
-                    }).then(result => f.filter(f.isObject, result));
+                    await _converse.api.waitUntil('discoInitialized');
+                    let entity = await _converse.api.disco.entities.get(jid, true);
+                    entity = await entity.waitUntilFeaturesDiscovered;
+                    const promises = _.concat(
+                        entity.items.map(item => item.hasFeature(feature)),
+                        entity.hasFeature(feature)
+                    );
+                    return Promise.all(promises);
                 },
 
                 /**
@@ -585,21 +581,18 @@ converse.plugins.add('converse-disco', {
                  * @example
                  * await _converse.api.disco.refreshFeatures('room@conference.example.org');
                  */
-                'refreshFeatures' (jid) {
+                async 'refreshFeatures' (jid) {
                     if (_.isNil(jid)) {
                         throw new TypeError('api.disco.refreshFeatures: You need to provide an entity JID');
                     }
-                    return _converse.api.waitUntil('discoInitialized')
-                        .then(() => _converse.api.disco.entities.get(jid, true))
-                        .then(entity => {
-                            entity.features.reset();
-                            entity.fields.reset();
-                            entity.identities.reset();
-                            entity.waitUntilFeaturesDiscovered = utils.getResolveablePromise()
-                            entity.queryInfo();
-                            return entity.waitUntilFeaturesDiscovered;
-                        })
-                        .catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+                    await _converse.api.waitUntil('discoInitialized');
+                    const entity = await _converse.api.disco.entities.get(jid, true);
+                    entity.features.reset();
+                    entity.fields.reset();
+                    entity.identities.reset();
+                    entity.waitUntilFeaturesDiscovered = utils.getResolveablePromise()
+                    entity.queryInfo();
+                    return entity.waitUntilFeaturesDiscovered;
                 },
 
                 /**
@@ -611,15 +604,14 @@ converse.plugins.add('converse-disco', {
                  * @example
                  * const features = await _converse.api.disco.getFeatures('room@conference.example.org');
                  */
-                'getFeatures' (jid) {
+                async 'getFeatures' (jid) {
                     if (_.isNil(jid)) {
                         throw new TypeError('api.disco.getFeatures: You need to provide an entity JID');
                     }
-                    return _converse.api.waitUntil('discoInitialized')
-                    .then(() => _converse.api.disco.entities.get(jid, true))
-                    .then(entity => entity.waitUntilFeaturesDiscovered)
-                    .then(entity => entity.features)
-                    .catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+                    await _converse.api.waitUntil('discoInitialized');
+                    let entity = await _converse.api.disco.entities.get(jid, true);
+                    entity = await entity.waitUntilFeaturesDiscovered;
+                    return entity.features;
                 },
 
                 /**
@@ -633,15 +625,14 @@ converse.plugins.add('converse-disco', {
                  * @example
                  * const fields = await _converse.api.disco.getFields('room@conference.example.org');
                  */
-                'getFields' (jid) {
+                async 'getFields' (jid) {
                     if (_.isNil(jid)) {
                         throw new TypeError('api.disco.getFields: You need to provide an entity JID');
                     }
-                    return _converse.api.waitUntil('discoInitialized')
-                    .then(() => _converse.api.disco.entities.get(jid, true))
-                    .then(entity => entity.waitUntilFeaturesDiscovered)
-                    .then(entity => entity.fields)
-                    .catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+                    await _converse.api.waitUntil('discoInitialized');
+                    let entity = await _converse.api.disco.entities.get(jid, true);
+                    entity = await entity.waitUntilFeaturesDiscovered;
+                    return entity.fields;
                 },
 
                 /**
@@ -675,8 +666,9 @@ converse.plugins.add('converse-disco', {
                  *     }
                  * ).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
                  */
-                'getIdentity' (category, type, jid) {
-                    return _converse.api.disco.entities.get(jid, true).then(e => e.getIdentity(category, type));
+                async 'getIdentity' (category, type, jid) {
+                    const e = await _converse.api.disco.entities.get(jid, true);
+                    return e.getIdentity(category, type);
                 }
             }
         });

+ 46 - 52
src/headless/converse-muc.js

@@ -109,20 +109,18 @@ converse.plugins.add('converse-muc', {
         _converse.api.promises.add(['roomsAutoJoined']);
 
 
-        function openRoom (jid) {
+        async function openRoom (jid) {
             if (!u.isValidMUCJID(jid)) {
                 return _converse.log(
                     `Invalid JID "${jid}" provided in URL fragment`,
                     Strophe.LogLevel.WARN
                 );
             }
-            const promises = [_converse.api.waitUntil('roomsAutoJoined')]
+            await _converse.api.waitUntil('roomsAutoJoined');
             if (_converse.allow_bookmarks) {
-                promises.push( _converse.api.waitUntil('bookmarksInitialized'));
+                await _converse.api.waitUntil('bookmarksInitialized');
             }
-            Promise.all(promises).then(() => {
-                _converse.api.rooms.open(jid);
-            });
+            _converse.api.rooms.open(jid);
         }
         _converse.router.route('converse/room?jid=:jid', openRoom);
 
@@ -770,7 +768,7 @@ converse.plugins.add('converse-muc', {
                 }
             },
 
-            checkForReservedNick () {
+            async checkForReservedNick () {
                 /* 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.
@@ -779,7 +777,7 @@ converse.plugins.add('converse-muc', {
                  *  (Function) callback: Callback upon succesful IQ response
                  *  (Function) errback: Callback upon error IQ response
                  */
-                return _converse.api.sendIQ(
+                const iq = await _converse.api.sendIQ(
                     $iq({
                         'to': this.get('jid'),
                         'from': _converse.connection.jid,
@@ -788,15 +786,14 @@ converse.plugins.add('converse-muc', {
                         'xmlns': Strophe.NS.DISCO_INFO,
                         'node': 'x-roomuser-item'
                     })
-                ).then(iq => {
-                    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'),
+                      nick = identity_el ? identity_el.getAttribute('name') : null;
+                this.save({
+                    'reserved_nick': nick,
+                    'nick': nick
+                }, {'silent': true});
+                return iq;
             },
 
             async registerNickname () {
@@ -947,7 +944,7 @@ converse.plugins.add('converse-muc', {
                 }
             },
 
-            onMessage (stanza) {
+            async onMessage (stanza) {
                 /* Handler for all MUC messages sent to this groupchat.
                  *
                  * Parameters:
@@ -976,9 +973,8 @@ converse.plugins.add('converse-muc', {
                         const subject = _.propertyOf(subject_el)('textContent') || '';
                         u.safeSave(this, {'subject': {'author': sender, 'text': subject}});
                     }
-                    this.createMessage(stanza, original_stanza)
-                        .then(msg => this.incrementUnreadMsgCounter(msg))
-                        .catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+                    const msg = await this.createMessage(stanza, original_stanza);
+                    this.incrementUnreadMsgCounter(msg);
                 }
                 if (sender !== this.get('nick')) {
                     // We only emit an event if it's not our own message
@@ -1149,37 +1145,35 @@ converse.plugins.add('converse-muc', {
                 }
             },
 
-            fetchMembers () {
-                this.chatroom.getJidsWithAffiliations(['member', 'owner', 'admin'])
-                .then(new_members => {
-                    const new_jids = new_members.map(m => m.jid).filter(m => !_.isUndefined(m)),
-                          new_nicks = new_members.map(m => !m.jid && m.nick || undefined).filter(m => !_.isUndefined(m)),
-                          removed_members = this.filter(m => {
-                              return f.includes(m.get('affiliation'), ['admin', 'member', 'owner']) &&
-                                  !f.includes(m.get('nick'), new_nicks) &&
-                                    !f.includes(m.get('jid'), new_jids);
-                          });
-
-                    _.each(removed_members, (occupant) => {
-                        if (occupant.get('jid') === _converse.bare_jid) { return; }
-                        if (occupant.get('show') === 'offline') {
-                            occupant.destroy();
-                        }
-                    });
-                    _.each(new_members, (attrs) => {
-                        let occupant;
-                        if (attrs.jid) {
-                            occupant = this.findOccupant({'jid': attrs.jid});
-                        } else {
-                            occupant = this.findOccupant({'nick': attrs.nick});
-                        }
-                        if (occupant) {
-                            occupant.save(attrs);
-                        } else {
-                            this.create(attrs);
-                        }
-                    });
-                }).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
+            async fetchMembers () {
+                const new_members = await this.chatroom.getJidsWithAffiliations(['member', 'owner', 'admin']);
+                const new_jids = new_members.map(m => m.jid).filter(m => !_.isUndefined(m)),
+                      new_nicks = new_members.map(m => !m.jid && m.nick || undefined).filter(m => !_.isUndefined(m)),
+                      removed_members = this.filter(m => {
+                          return f.includes(m.get('affiliation'), ['admin', 'member', 'owner']) &&
+                              !f.includes(m.get('nick'), new_nicks) &&
+                                !f.includes(m.get('jid'), new_jids);
+                      });
+
+                _.each(removed_members, (occupant) => {
+                    if (occupant.get('jid') === _converse.bare_jid) { return; }
+                    if (occupant.get('show') === 'offline') {
+                        occupant.destroy();
+                    }
+                });
+                _.each(new_members, (attrs) => {
+                    let occupant;
+                    if (attrs.jid) {
+                        occupant = this.findOccupant({'jid': attrs.jid});
+                    } else {
+                        occupant = this.findOccupant({'nick': attrs.nick});
+                    }
+                    if (occupant) {
+                        occupant.save(attrs);
+                    } else {
+                        this.create(attrs);
+                    }
+                });
             },
 
             findOccupant (data) {