diff --git a/CHANGES.md b/CHANGES.md index 099879dd1..4c6f18152 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,6 +4,8 @@ - Avoid `eval` (via `_.template` from lodash). - Bugfix. Avatars weren't being shown. +- Bugfix. Bookmarks list and open rooms list weren't recreated after logging in for a 2nd time (without reloading the browser). +- Don't show bookmark toggles when PEP bookmarking not supported by the XMPP server. - Add LibreJS support ## 3.3.3 (2018-02-14) diff --git a/src/converse-bookmarks.js b/src/converse-bookmarks.js index f68ebccfa..57c09348d 100644 --- a/src/converse-bookmarks.js +++ b/src/converse-bookmarks.js @@ -87,11 +87,10 @@ this.__super__.renderHeading.apply(this, arguments); const { _converse } = this.__super__; if (_converse.allow_bookmarks) { - _converse.api.disco.getIdentity('pubsub', 'pep', _converse.bare_jid).then((identity) => { - if (_.isNil(identity)) { - return; + _converse.checkBookmarksSupport().then((supported) => { + if (supported) { + this.renderBookmarkToggle(); } - this.renderBookmarkToggle(); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)); } }, @@ -530,41 +529,38 @@ } }); + _converse.checkBookmarksSupport = function () { + return new Promise((resolve, reject) => { + Promise.all([ + _converse.api.disco.getIdentity('pubsub', 'pep', _converse.bare_jid), + _converse.api.disco.supports(Strophe.NS.PUBSUB+'#publish-options', _converse.bare_jid) + ]).then((args) => { + resolve(args[0] && (args[1].supported || _converse.allow_public_bookmarks)); + }); + }); + } + const initBookmarks = function () { if (!_converse.allow_bookmarks) { return; } - Promise.all([ - _converse.api.disco.getIdentity('pubsub', 'pep', _converse.bare_jid), - _converse.api.disco.supports(Strophe.NS.PUBSUB+'#publish-options', _converse.bare_jid) - ]).then((args) => { - const identity = args[0], - options_support = args[1]; - - if (_.isNil(identity) || (!options_support.supported && !_converse.allow_public_bookmarks)) { + _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'); - return; } - _converse.bookmarks = new _converse.Bookmarks(); - _converse.bookmarks.fetchBookmarks().then(() => { - _converse.bookmarksview = new _converse.BookmarksView( - {'model': _converse.bookmarks} - ); - }).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR)) - .then(() => { - _converse.emit('bookmarksInitialized'); - }); - }).catch((e) => { - _converse.log(e, Strophe.LogLevel.ERROR); - _converse.emit('bookmarksInitialized'); }); - }; + } - Promise.all([ - _converse.api.waitUntil('chatBoxesFetched'), - _converse.api.waitUntil('roomsPanelRendered') - ]).then(initBookmarks) - .catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)); + u.onMultipleEvents([ + {'object': _converse, 'event': 'chatBoxesFetched'}, + {'object': _converse, 'event': 'roomsPanelRendered'} + ], initBookmarks); _converse.on('connected', () => { // Add a handler for bookmarks pushed from other connected clients diff --git a/src/converse-core.js b/src/converse-core.js index b2c7a1102..387d47b89 100644 --- a/src/converse-core.js +++ b/src/converse-core.js @@ -654,6 +654,9 @@ } else { _converse._tearDown(); } + // Recreate all the promises + _.each(_.keys(_converse.promises), addPromise); + _converse.emit('logout'); }; diff --git a/src/converse-minimize.js b/src/converse-minimize.js index 1c1b421e6..cae24581c 100644 --- a/src/converse-minimize.js +++ b/src/converse-minimize.js @@ -536,7 +536,6 @@ const new_html = tpl_chatbox_minimize( {info_minimize: __('Minimize this chat box')} ); - const el = view.el.querySelector('.toggle-chatbox-button'); if (el) { el.outerHTML = new_html; @@ -553,11 +552,6 @@ _converse.chatboxviews.trimChats(chatbox); } }); - - const logOut = function () { - _converse.minimized_chats.remove(); - }; - _converse.on('logout', logOut); } }); })); diff --git a/src/converse-roomslist.js b/src/converse-roomslist.js index 73bf1fdce..519e4822d 100644 --- a/src/converse-roomslist.js +++ b/src/converse-roomslist.js @@ -118,7 +118,11 @@ toHTML () { return tpl_rooms_list_item( _.extend(this.model.toJSON(), { - 'allow_bookmarks': _converse.allow_bookmarks, + // XXX: By the time this renders, the _converse.bookmarks + // collection should already exist if bookmarks are + // supported by the XMPP server. So we can use it + // as a check for support (other ways of checking are async). + 'allow_bookmarks': _converse.allow_bookmarks && _converse.bookmarks, 'info_leave_room': __('Leave this room'), 'info_remove_bookmark': __('Unbookmark this room'), 'info_add_bookmark': __('Bookmark this room'), @@ -237,18 +241,18 @@ ); }; - Promise.all([ - _converse.api.waitUntil('chatBoxesFetched'), - _converse.api.waitUntil('roomsPanelRendered') - ]).then(() => { - if (_converse.allow_bookmarks) { - _converse.api.waitUntil('bookmarksInitialized').then( - initRoomsListView - ); - } else { - initRoomsListView(); - } - }); + if (_converse.allow_bookmarks) { + u.onMultipleEvents([ + {'object': _converse, 'event': 'chatBoxesFetched'}, + {'object': _converse, 'event': 'roomsPanelRendered'}, + {'object': _converse, 'event': 'bookmarksInitialized'} + ], initRoomsListView); + } else { + u.onMultipleEvents([ + {'object': _converse, 'event': 'chatBoxesFetched'}, + {'object': _converse, 'event': 'roomsPanelRendered'} + ], initRoomsListView); + } _converse.api.listen.on('reconnected', initRoomsListView); } diff --git a/src/utils.js b/src/utils.js index 4b5278a2c..8f325b7de 100644 --- a/src/utils.js +++ b/src/utils.js @@ -654,6 +654,28 @@ }); }; + u.onMultipleEvents = function (events=[], callback) { + /* Call the callback once all the events have been triggered + * + * Parameters: + * (Array) events: An array of objects, with keys `object` and + * `event`, representing the event name and the object it's + * triggered upon. + * (Function) callback: The function to call once all events have + * been triggered. + */ + let triggered = []; + + function handler (result) { + triggered.push(result) + if (events.length === triggered.length) { + callback(triggered); + triggered = []; + } + } + _.each(events, (map) => map.object.on(map.event, handler)); + }; + u.safeSave = function (model, attributes) { if (u.isPersistableModel(model)) { model.save(attributes);